Coverage for webapp/app.py: 68%
84 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-27 22:07 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-27 22:07 +0000
1import talisker.requests
2from flask import render_template, make_response, request, session
3from dateutil import parser
5from canonicalwebteam.candid import CandidClient
6from canonicalwebteam.flask_base.app import FlaskBase
8from webapp.store_api import publisher_gateway
9from webapp.extensions import csrf
10from webapp.config import APP_NAME
11from webapp.handlers import set_handlers
12from webapp.login.views import login
13from webapp.topics.views import topics
14from webapp.publisher.views import publisher
15from webapp.store.views import store
16from webapp.integrations.views import integrations
17from webapp.search.views import search
18from webapp.search.logic import cache
19from webapp.helpers import markdown_to_html
20from webapp.decorators import login_required
21from webapp.packages.store_packages import store_packages
22from opentelemetry.instrumentation.requests import RequestsInstrumentor
23from opentelemetry.instrumentation.flask import FlaskInstrumentor
24from opentelemetry.trace import Span
27app = FlaskBase(
28 __name__,
29 "charmhub.io",
30 template_404="404.html",
31 template_500="500.html",
32 favicon_url="https://assets.ubuntu.com/v1/5d4edefd-jaas-favicon.png",
33 static_folder="../static",
34 template_folder="../templates",
35)
38app.name = APP_NAME
39app.config["LOGIN_REQUIRED"] = login_required
41set_handlers(app)
43request_session = talisker.requests.get_session()
44candid = CandidClient(request_session)
45cache.init_app(app)
46csrf.init_app(app)
48app.register_blueprint(store_packages)
49app.register_blueprint(publisher)
50app.register_blueprint(store)
51app.register_blueprint(login)
52app.register_blueprint(topics)
53app.register_blueprint(integrations)
54app.register_blueprint(search)
57app.jinja_env.filters["markdown"] = markdown_to_html
59# OpenTelemetry
60UNTRACED_ROUTES = ["/_status", "/static", ".json"]
63def request_hook(span: Span, environ):
64 if span and span.is_recording():
65 span.update_name(f"{environ['REQUEST_METHOD']} {environ['PATH_INFO']}")
68# Add tracing auto instrumentation
69FlaskInstrumentor().instrument_app(
70 app, excluded_urls=",".join(UNTRACED_ROUTES), request_hook=request_hook
71)
72RequestsInstrumentor().instrument()
75@app.route("/account.json")
76def get_account_json():
77 """
78 A JSON endpoint to request login status
79 """
80 account = None
82 if "account" in session:
83 account = session["account"]
85 response = {"account": account}
86 response = make_response(response)
87 response.headers["Cache-Control"] = "no-store"
89 return response
92@app.route("/contact-us")
93def contact_us():
94 return render_template("contact-us.html")
97@app.route("/thank-you")
98def thank_you():
99 return render_template("thank-you.html")
102@app.route("/icon-validator")
103def icon_validator():
104 return render_template("icon-validator.html")
107@app.route("/sitemap.xml")
108def site_map():
109 xml_sitemap = render_template(
110 "sitemap/sitemap.xml",
111 base_url=f"{request.scheme}://{request.host}",
112 )
113 response = make_response(xml_sitemap)
114 response.headers["Content-Type"] = "application/xml"
116 return response
119@app.route("/sitemap-links.xml")
120def site_map_links():
121 links = [
122 "/contact-us",
123 ]
125 xml_sitemap = render_template(
126 "sitemap/sitemap-links.xml",
127 base_url=f"{request.scheme}://{request.host}",
128 links=links,
129 )
130 response = make_response(xml_sitemap)
131 response.headers["Content-Type"] = "application/xml"
133 return response
136@app.route("/sitemap-operators.xml")
137def site_map_operators():
138 charms = publisher_gateway.find(
139 fields=["default-release.channel.released-at"]
140 ).get("results", [])
142 for charm in charms:
143 charm["date"] = (
144 parser.parse(charm["default-release"]["channel"]["released-at"])
145 .replace(tzinfo=None)
146 .strftime("%Y-%m-%d")
147 )
149 xml_sitemap = render_template(
150 "sitemap/sitemap-operators.xml",
151 base_url=f"{request.scheme}://{request.host}",
152 charms=charms,
153 )
154 response = make_response(xml_sitemap)
155 response.headers["Content-Type"] = "application/xml"
157 return response