Coverage for webapp/endpoints/publisher/listing.py: 83%
110 statements
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-26 22:06 +0000
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-26 22:06 +0000
1# Standard library
2from json import loads
4# Packages
5import flask
6from canonicalwebteam.exceptions import (
7 StoreApiError,
8 StoreApiResponseErrorList,
9)
10from canonicalwebteam.store_api.dashboard import Dashboard
11from canonicalwebteam.store_api.devicegw import DeviceGW
13# Local
14from webapp import helpers
15from webapp.helpers import api_session
16from webapp.decorators import login_required
17from webapp.publisher.snaps import logic
18from webapp.store.logic import (
19 get_categories,
20)
22dashboard = Dashboard(api_session)
23device_gateway = DeviceGW("snap", api_session)
26@login_required
27def get_listing_data(snap_name):
28 snap_details = dashboard.get_snap_info(flask.session, snap_name)
30 details_metrics_enabled = snap_details["public_metrics_enabled"]
31 details_blacklist = snap_details.get("public_metrics_blacklist", [])
33 # Filter icon & screenshot urls from the media set.
34 icon_urls, screenshot_urls, banner_urls = logic.categorise_media(
35 snap_details["media"]
36 )
38 primary_website = ""
39 if (
40 "website" in snap_details["links"]
41 and len(snap_details["links"]["website"]) > 0
42 ):
43 primary_website = snap_details["links"]["website"][0]
45 websites = []
46 if "website" in snap_details["links"]:
47 if len(snap_details["links"]["website"]) > 1:
48 snap_details["links"]["website"].pop(0)
49 for website in snap_details["links"]["website"]:
50 websites.append({"url": website})
52 def format_links(key):
53 result = []
54 if key in snap_details["links"]:
55 for url in snap_details["links"][key]:
56 result.append({"url": url})
57 return result
59 licenses = []
60 for license in helpers.get_licenses():
61 licenses.append({"key": license["licenseId"], "name": license["name"]})
63 license = snap_details["license"]
64 license_type = "custom"
66 if " AND " not in license.upper() and " WITH " not in license.upper():
67 license_type = "simple"
69 try:
70 categories_results = device_gateway.get_categories()
71 except StoreApiError:
72 categories_results = []
74 categories = sorted(
75 get_categories(categories_results),
76 key=lambda category: category["slug"],
77 )
79 snap_categories = logic.replace_reserved_categories_key(
80 snap_details["categories"]
81 )
83 snap_categories = logic.filter_categories(snap_categories)
85 snap_categories["categories"] = [
86 category["name"] for category in snap_categories["categories"]
87 ]
89 filename = "publisher/content/listing_tour.yaml"
90 tour_steps = helpers.get_yaml(filename, typ="rt")
92 primary_category = ""
93 if len(snap_categories["categories"]) > 0:
94 primary_category = snap_categories["categories"][0]
96 secondary_category = ""
97 if len(snap_categories["categories"]) > 1:
98 secondary_category = snap_categories["categories"][1]
100 video_urls = None
102 if len(snap_details["video_urls"]) > 0:
103 video_urls = snap_details["video_urls"][0]
105 context = {
106 "title": snap_details["title"],
107 "video_urls": video_urls,
108 "summary": snap_details["summary"],
109 "description": snap_details["description"],
110 "categories": categories,
111 "primary_category": primary_category,
112 "secondary_category": secondary_category,
113 "websites": websites,
114 "contacts": format_links("contact"),
115 "donations": format_links("donations"),
116 "source_code": format_links("source"),
117 "issues": format_links("issues"),
118 "primary_website": primary_website,
119 "snap_id": snap_details["snap_id"],
120 "public_metrics_enabled": details_metrics_enabled,
121 "public_metrics_blacklist": details_blacklist,
122 "license": license,
123 "license_type": license_type,
124 "licenses": licenses,
125 "icon_url": icon_urls[0] if icon_urls else None,
126 "screenshot_urls": screenshot_urls,
127 "banner_urls": banner_urls,
128 "update_metadata_on_release": snap_details[
129 "update_metadata_on_release"
130 ],
131 "tour_steps": tour_steps,
132 }
134 res = {}
135 res["data"] = context
136 res["message"] = ""
137 res["success"] = True
139 return flask.jsonify(res)
142@login_required
143def post_listing_data(snap_name):
144 changes = None
145 changed_fields = flask.request.form.get("changes")
147 if changed_fields:
148 changes = loads(changed_fields)
150 if changes:
151 snap_id = flask.request.form.get("snap_id")
152 error_list = []
154 if "images" in changes:
155 # Add existing screenshots
156 current_screenshots = dashboard.snap_screenshots(
157 flask.session, snap_id
158 )
160 icon_input = (
161 flask.request.files.get("icon")
162 if flask.request.files.get("icon")
163 else None
164 )
165 screenshots_input = [
166 s if s else None
167 for s in flask.request.files.getlist("screenshots")
168 ]
169 banner_image_input = (
170 flask.request.files.get("banner-image")
171 if flask.request.files.get("banner-image")
172 else None
173 )
175 images_json, images_files = logic.build_changed_images(
176 changes["images"],
177 current_screenshots,
178 icon_input,
179 screenshots_input,
180 banner_image_input,
181 )
183 try:
184 dashboard.snap_screenshots(
185 flask.session, snap_id, images_json, images_files
186 )
187 except StoreApiResponseErrorList as api_response_error_list:
188 if api_response_error_list.status_code != 404:
189 error_list = error_list + api_response_error_list.errors
191 body_json = logic.filter_changes_data(changes)
193 if body_json:
194 if "description" in body_json:
195 body_json["description"] = logic.remove_invalid_characters(
196 body_json["description"]
197 )
199 try:
200 dashboard.snap_metadata(flask.session, snap_id, body_json)
201 except StoreApiResponseErrorList as api_response_error_list:
202 if api_response_error_list.status_code != 404:
203 error_list = error_list + api_response_error_list.errors
205 if error_list:
206 try:
207 snap_details = dashboard.get_snap_info(
208 flask.session, snap_name
209 )
210 except StoreApiResponseErrorList as api_response_error_list:
211 if api_response_error_list.status_code == 404:
212 return flask.abort(
213 404, "No snap named {}".format(snap_name)
214 )
215 else:
216 error_list = error_list + api_response_error_list.errors
218 licenses = []
219 for license in helpers.get_licenses():
220 licenses.append(
221 {"key": license["licenseId"], "name": license["name"]}
222 )
224 license = snap_details["license"]
226 snap_categories = logic.replace_reserved_categories_key(
227 snap_details["categories"]
228 )
230 snap_categories = logic.filter_categories(snap_categories)
232 res = {"success": True, "errors": error_list}
234 return flask.make_response(res, 200)
236 return flask.make_response({"success": True}, 200)