Coverage for webapp/admin/views.py: 70%
82 statements
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-05 22:06 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-05 22:06 +0000
1# Packages
2import os
3import json
4import flask
5from flask import make_response
6from canonicalwebteam.exceptions import (
7 StoreApiResponseErrorList,
8)
9from canonicalwebteam.store_api.dashboard import Dashboard
10from canonicalwebteam.store_api.publishergw import PublisherGW
11from canonicalwebteam.store_api.devicegw import DeviceGW
12from flask.json import jsonify
14# Local
15from webapp.decorators import login_required, exchange_required
16from webapp.helpers import api_publisher_session, api_session
19dashboard = Dashboard(api_session)
20publisher_gateway = PublisherGW("snap", api_publisher_session)
21device_gateway = DeviceGW("snap", api_session)
23admin = flask.Blueprint(
24 "admin", __name__, template_folder="/templates", static_folder="/static"
25)
27SNAPSTORE_DASHBOARD_API_URL = os.getenv(
28 "SNAPSTORE_DASHBOARD_API_URL", "https://dashboard.snapcraft.io/"
29)
31context = {"api_url": SNAPSTORE_DASHBOARD_API_URL}
34def get_brand_id(session, store_id):
35 store = dashboard.get_store(session, store_id)
36 return store["brand-id"]
39@admin.route("/admin", defaults={"path": ""})
40@admin.route("/admin/<path:path>")
41@login_required
42@exchange_required
43def get_admin(path):
44 return flask.render_template("admin/admin.html", **context)
47@admin.route("/api/store/<store_id>/invite", methods=["POST"])
48@login_required
49@exchange_required
50def post_invite_members(store_id):
51 members = json.loads(flask.request.form.get("members"))
53 res = {}
55 try:
56 dashboard.invite_store_members(flask.session, store_id, members)
57 res["msg"] = "Changes saved"
58 except StoreApiResponseErrorList as api_response_error_list:
59 msgs = [
60 f"{error.get('message', 'An error occurred')}"
61 for error in api_response_error_list.errors
62 ]
64 msgs = list(dict.fromkeys(msgs))
66 for msg in msgs:
67 flask.flash(msg, "negative")
69 return jsonify(res)
72@admin.route("/api/store/<store_id>/invite/update", methods=["POST"])
73@login_required
74@exchange_required
75def update_invite_status(store_id):
76 invites = json.loads(flask.request.form.get("invites"))
78 res = {}
80 try:
81 dashboard.update_store_invites(flask.session, store_id, invites)
82 res["msg"] = "Changes saved"
83 except StoreApiResponseErrorList as api_response_error_list:
84 msgs = [
85 f"{error.get('message', 'An error occurred')}"
86 for error in api_response_error_list.errors
87 ]
89 msgs = list(dict.fromkeys(msgs))
91 for msg in msgs:
92 flask.flash(msg, "negative")
94 return jsonify(res)
97# -------------------- FEATURED SNAPS AUTOMATION ------------------
98@admin.route("/admin/featured", methods=["POST"])
99@login_required
100@exchange_required
101def post_featured_snaps():
102 """
103 In this view, we do three things:
104 1. Fetch all currently featured snaps
105 2. Delete the currently featured snaps
106 3. Update featured snaps to be newly featured
108 Args:
109 None
111 Returns:
112 dict: A dictionary containing the response message and success status.
113 """
115 # new_featured_snaps is the list of featured snaps to be updated
116 featured_snaps = flask.request.form.get("snaps")
118 if not featured_snaps:
119 response = {
120 "success": False,
121 "message": "Snaps cannot be empty",
122 }
123 return make_response(response, 500)
124 new_featured_snaps = featured_snaps.split(",")
126 # currently_featured_snap is the list of featured snaps to be deleted
127 currently_featured_snaps = []
129 next = True
130 while next:
131 featured_snaps = device_gateway.get_featured_snaps()
132 currently_featured_snaps.extend(
133 featured_snaps.get("_embedded", {}).get("clickindex:package", [])
134 )
135 next = featured_snaps.get("_links", {}).get("next", False)
137 currently_featured_snap_ids = [
138 snap["snap_id"] for snap in currently_featured_snaps
139 ]
141 delete_response = publisher_gateway.delete_featured_snaps(
142 flask.session, {"packages": currently_featured_snap_ids}
143 )
144 if delete_response.status_code != 201:
145 response = {
146 "success": False,
147 "message": "An error occurred while deleting featured snaps",
148 }
149 return make_response(response, 500)
150 snap_ids = [
151 dashboard.get_snap_id(flask.session, snap_name)
152 for snap_name in new_featured_snaps
153 ]
155 update_response = publisher_gateway.update_featured_snaps(
156 flask.session, snap_ids
157 )
158 if update_response.status_code != 201:
159 response = {
160 "success": False,
161 "message": "An error occured while updating featured snaps",
162 }
163 return make_response(response, 500)
164 return make_response({"success": True}, 200)