Coverage for webapp / endpoints / publisher / listing.py: 83%
110 statements
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-29 22:06 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-29 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)
29 details_metrics_enabled = snap_details["public_metrics_enabled"]
30 details_blacklist = snap_details.get("public_metrics_blacklist", [])
32 # Filter icon & screenshot urls from the media set.
33 icon_urls, screenshot_urls, banner_urls = logic.categorise_media(
34 snap_details["media"]
35 )
37 primary_website = ""
38 if (
39 "website" in snap_details["links"]
40 and len(snap_details["links"]["website"]) > 0
41 ):
42 primary_website = snap_details["links"]["website"][0]
44 websites = []
45 if "website" in snap_details["links"]:
46 if len(snap_details["links"]["website"]) > 1:
47 snap_details["links"]["website"].pop(0)
48 for website in snap_details["links"]["website"]:
49 websites.append({"url": website})
51 def format_links(key):
52 result = []
53 if key in snap_details["links"]:
54 for url in snap_details["links"][key]:
55 result.append({"url": url})
56 return result
58 licenses = []
59 for license in helpers.get_licenses():
60 licenses.append({"key": license["licenseId"], "name": license["name"]})
62 license = snap_details["license"]
63 license_type = "custom"
65 if " AND " not in license.upper() and " WITH " not in license.upper():
66 license_type = "simple"
68 try:
69 categories_results = device_gateway.get_categories()
70 except StoreApiError:
71 categories_results = []
73 categories = sorted(
74 get_categories(categories_results),
75 key=lambda category: category["slug"],
76 )
78 snap_categories = logic.replace_reserved_categories_key(
79 snap_details["categories"]
80 )
82 snap_categories = logic.filter_categories(snap_categories)
84 snap_categories["categories"] = [
85 category["name"] for category in snap_categories["categories"]
86 ]
88 filename = "publisher/content/listing_tour.yaml"
89 tour_steps = helpers.get_yaml(filename, typ="rt")
91 primary_category = ""
92 if len(snap_categories["categories"]) > 0:
93 primary_category = snap_categories["categories"][0]
95 secondary_category = ""
96 if len(snap_categories["categories"]) > 1:
97 secondary_category = snap_categories["categories"][1]
99 video_urls = None
101 if len(snap_details["video_urls"]) > 0:
102 video_urls = snap_details["video_urls"][0]
104 context = {
105 "title": snap_details["title"],
106 "video_urls": video_urls,
107 "summary": snap_details["summary"],
108 "description": snap_details["description"],
109 "categories": categories,
110 "primary_category": primary_category,
111 "secondary_category": secondary_category,
112 "websites": websites,
113 "contacts": format_links("contact"),
114 "donations": format_links("donations"),
115 "source_code": format_links("source"),
116 "issues": format_links("issues"),
117 "primary_website": primary_website,
118 "snap_id": snap_details["snap_id"],
119 "public_metrics_enabled": details_metrics_enabled,
120 "public_metrics_blacklist": details_blacklist,
121 "license": license,
122 "license_type": license_type,
123 "licenses": licenses,
124 "icon_url": icon_urls[0] if icon_urls else None,
125 "screenshot_urls": screenshot_urls,
126 "banner_urls": banner_urls,
127 "update_metadata_on_release": snap_details[
128 "update_metadata_on_release"
129 ],
130 "tour_steps": tour_steps,
131 }
133 res = {}
134 res["data"] = context
135 res["message"] = ""
136 res["success"] = True
138 return flask.jsonify(res)
141@login_required
142def post_listing_data(snap_name):
143 changes = None
144 changed_fields = flask.request.form.get("changes")
146 if changed_fields:
147 changes = loads(changed_fields)
149 if changes:
150 snap_id = flask.request.form.get("snap_id")
151 error_list = []
153 if "images" in changes:
154 # Add existing screenshots
155 current_screenshots = dashboard.snap_screenshots(
156 flask.session, snap_id
157 )
159 icon_input = (
160 flask.request.files.get("icon")
161 if flask.request.files.get("icon")
162 else None
163 )
164 screenshots_input = [
165 s if s else None
166 for s in flask.request.files.getlist("screenshots")
167 ]
168 banner_image_input = (
169 flask.request.files.get("banner-image")
170 if flask.request.files.get("banner-image")
171 else None
172 )
174 images_json, images_files = logic.build_changed_images(
175 changes["images"],
176 current_screenshots,
177 icon_input,
178 screenshots_input,
179 banner_image_input,
180 )
182 try:
183 dashboard.snap_screenshots(
184 flask.session, snap_id, images_json, images_files
185 )
186 except StoreApiResponseErrorList as api_response_error_list:
187 if api_response_error_list.status_code != 404:
188 error_list = error_list + api_response_error_list.errors
190 body_json = logic.filter_changes_data(changes)
192 if body_json:
193 if "description" in body_json:
194 body_json["description"] = logic.remove_invalid_characters(
195 body_json["description"]
196 )
198 try:
199 dashboard.snap_metadata(flask.session, snap_id, body_json)
200 except StoreApiResponseErrorList as api_response_error_list:
201 if api_response_error_list.status_code != 404:
202 error_list = error_list + api_response_error_list.errors
204 if error_list:
205 try:
206 snap_details = dashboard.get_snap_info(
207 flask.session, snap_name
208 )
209 except StoreApiResponseErrorList as api_response_error_list:
210 if api_response_error_list.status_code == 404:
211 return flask.abort(
212 404, "No snap named {}".format(snap_name)
213 )
214 else:
215 error_list = error_list + api_response_error_list.errors
217 licenses = []
218 for license in helpers.get_licenses():
219 licenses.append(
220 {"key": license["licenseId"], "name": license["name"]}
221 )
223 license = snap_details["license"]
225 snap_categories = logic.replace_reserved_categories_key(
226 snap_details["categories"]
227 )
229 snap_categories = logic.filter_categories(snap_categories)
231 res = {"success": True, "errors": error_list}
233 return flask.make_response(res, 200)
235 return flask.make_response({"success": True}, 200)