Coverage for webapp/snapcraft/views.py: 46%

84 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-15 22:43 +0000

1import flask 

2 

3from webapp.config import DEFAULT_ICON_URL 

4from webapp.snapcraft import logic 

5 

6 

7def snapcraft_blueprint(): 

8 snapcraft = flask.Blueprint("snapcraft", __name__) 

9 

10 @snapcraft.route("/") 

11 def homepage(): 

12 nps = flask.request.args.get("nps") 

13 

14 livestream = logic.get_livestreams() 

15 

16 return flask.render_template( 

17 "index.html", nps=nps, livestream=livestream 

18 ) 

19 

20 @snapcraft.route("/account.json") 

21 def get_account_json(): 

22 """ 

23 A JSON endpoint to request login status 

24 """ 

25 try: 

26 publisher = None 

27 

28 if "publisher" in flask.session: 

29 publisher = flask.session["publisher"] 

30 

31 response = {"publisher": publisher} 

32 response = flask.make_response(response) 

33 

34 # Unset the last_login_method cookie to avoid forcing 

35 response.set_cookie("last_login_method", "", expires=0) 

36 

37 response.headers["Cache-Control"] = "no-store" 

38 

39 return response 

40 except Exception: 

41 response = {"error": "Error fetching account information"} 

42 response = flask.make_response(response) 

43 response.headers["Cache-Control"] = "no-store" 

44 return response, 502 

45 

46 @snapcraft.route("/iot") 

47 def iot(): 

48 status_code = 200 

49 

50 icon_host = "https://dashboard.snapcraft.io/site_media/appmedia" 

51 

52 devices = [ 

53 { 

54 "package_name": "ubuntu-frame-osk", 

55 "icon_url": "/".join([icon_host, "2023/03/icon_2_Frame.png"]), 

56 "title": "Ubuntu Frame", 

57 "developer_name": "Canonical", 

58 "developer_link": "/publisher/canonical", 

59 "developer_validation": "verified", 

60 }, 

61 { 

62 "package_name": "mir-kiosk", 

63 "icon_url": "/".join( 

64 [icon_host, "2021/06/mir-sqr-stacked-orng.png"] 

65 ), 

66 "title": "mir-kiosk", 

67 "developer_name": "Canonical", 

68 "developer_link": "/publisher/canonical", 

69 "developer_validation": "verified", 

70 }, 

71 { 

72 "package_name": "edgexfoundry", 

73 "icon_url": "/".join([icon_host, "2018/12/icon_Hx6IyH0.png"]), 

74 "title": "Edgexfoundry", 

75 "developer_name": "Canonical", 

76 "developer_link": "/publisher/canonical", 

77 "developer_validation": "verified", 

78 }, 

79 { 

80 "package_name": "node-red", 

81 "icon_url": "/".join([icon_host, "2017/01/nr-hex_1.png"]), 

82 "title": "Node-Red", 

83 "developer_name": "Node-RED-Team (noderedteam)", 

84 "developer_link": "/publisher/noderedteam", 

85 "developer_validation": "verified", 

86 }, 

87 { 

88 "package_name": "bluez", 

89 "icon_url": "/".join( 

90 [icon_host, "2020/05/bluez-logo-2.jpg.png"] 

91 ), 

92 "title": "bluez", 

93 "developer_name": "Canonical", 

94 "developer_link": "/publisher/canonical", 

95 "developer_validation": "verified", 

96 }, 

97 { 

98 "package_name": "zwave-js-ui", 

99 "icon_url": "/".join( 

100 [icon_host, "2022/10/app_logo-svg_2.svg.png"] 

101 ), 

102 "title": "Zwave JS UI", 

103 "developer_name": "Giaever.online (giaever-online)", 

104 "developer_link": "/publisher/giaever-online", 

105 }, 

106 { 

107 "package_name": "ubports-installer", 

108 "icon_url": "/".join( 

109 [icon_host, "2017/09/256x256_h3aYso1.png"] 

110 ), 

111 "title": "ubports-installer", 

112 "developer_name": "UBports", 

113 "developer_link": "/publisher/ubports", 

114 }, 

115 { 

116 "package_name": "librepcb", 

117 "icon_url": "/".join([icon_host, "2022/10/librepcb.png"]), 

118 "title": "LibrePCB", 

119 "developer_name": "librepcb", 

120 "developer_link": "/publisher/librepcb", 

121 "developer_validation": "verified", 

122 }, 

123 { 

124 "package_name": "ammp-edge", 

125 "icon_url": "/".join( 

126 [icon_host, "2020/12/glyph-rounder-square-180px.png"] 

127 ), 

128 "title": "ammp-edge", 

129 "developer_name": "AMMP Technologies (ammp)", 

130 "developer_link": "/publisher/ammp", 

131 }, 

132 { 

133 "package_name": "pi-bluetooth", 

134 "icon_url": DEFAULT_ICON_URL, 

135 "title": "pi-bluetooth", 

136 "developer_name": "Dave Jones (waveform)", 

137 "developer_link": "/publisher/waveform", 

138 }, 

139 ] 

140 

141 robotics = [ 

142 { 

143 "package_name": "arduino", 

144 "icon_url": "/".join([icon_host, "2020/02/icon_s4HbwJl.png"]), 

145 "title": "Arduino IDE", 

146 "developer_name": "Snapcrafters", 

147 "developer_link": "/publisher/snapcrafters", 

148 "developer_validation": "starred", 

149 }, 

150 { 

151 "package_name": "rosbot-xl", 

152 "icon_url": "/".join([icon_host, "2024/06/rosbot-xl.png"]), 

153 "title": "ROSbot XL", 

154 "developer_name": "Husarion", 

155 "developer_link": "/publisher/husarion", 

156 "developer_validation": "verified", 

157 }, 

158 { 

159 "package_name": "rosbot-xl-teleop", 

160 "icon_url": "/".join( 

161 [icon_host, "2023/10/popr512x512px_rosbot_xl_teleop.png"] 

162 ), 

163 "title": "ROSbot XL: teleop", 

164 "developer_name": "Husarion", 

165 "developer_link": "/publisher/husarion", 

166 "developer_validation": "verified", 

167 }, 

168 { 

169 "package_name": "webots", 

170 "icon_url": "/".join([icon_host, "2019/08/webots.png"]), 

171 "title": "Webots", 

172 "developer_name": "Cyberbotics", 

173 "developer_link": "/publisher/cyberbotics", 

174 }, 

175 { 

176 "package_name": "gazebo", 

177 "icon_url": "/".join([icon_host, "2022/05/icon.svg.png"]), 

178 "title": "gazebo", 

179 "developer_name": ( 

180 "Ubuntu Robotics Community (ubuntu-robotics-community)" 

181 ), 

182 "developer_link": "/publisher/ubuntu-robotics-community", 

183 "developer_validation": "verified", 

184 }, 

185 { 

186 "package_name": "ros2-cli", 

187 "icon_url": "/".join( 

188 [icon_host, "2023/02/ros2-cli_icon_1.png"] 

189 ), 

190 "title": "ros2-cli", 

191 "developer_name": ( 

192 "Ubuntu Robotics Community (ubuntu-robotics-community)" 

193 ), 

194 "developer_link": "/publisher/ubuntu-robotics-community", 

195 "developer_validation": "verified", 

196 }, 

197 { 

198 "package_name": "vulcanexus-router", 

199 "icon_url": "/".join([icon_host, "2023/05/V-DDSRouter.png"]), 

200 "title": "Vulcanexus Router", 

201 "developer_name": "eProsima", 

202 "developer_link": "/publisher/eprosima", 

203 }, 

204 { 

205 "package_name": "bow-webots", 

206 "icon_url": DEFAULT_ICON_URL, 

207 "title": "BOW Webots", 

208 "developer_name": "Daniel Camilleri (bow-robotics)", 

209 "developer_link": "/publisher/bow-robotics", 

210 }, 

211 { 

212 "package_name": "foxglove-studio", 

213 "icon_url": "/".join([icon_host, "2022/07/fs-icon.svg.png"]), 

214 "title": "foxglove-studio", 

215 "developer_name": "Roman Shtylman (roman-foxglove)", 

216 "developer_link": "/publisher/roman-foxglove", 

217 }, 

218 { 

219 "package_name": "husarion-ouster", 

220 "icon_url": "/".join( 

221 [icon_host, "2023/10/husarion-ouster.png"] 

222 ), 

223 "title": "husarion-ouster", 

224 "developer_name": "Husarion", 

225 "developer_link": "/publisher/husarion", 

226 "developer_validation": "verified", 

227 }, 

228 ] 

229 

230 smart_home = [ 

231 { 

232 "package_name": "openhab", 

233 "icon_url": "/".join([icon_host, "2017/11/favicon.png"]), 

234 "title": "openhab", 

235 "developer_name": "openHAB Foundation e.V. (openhab)", 

236 "developer_link": "/publisher/openhab", 

237 }, 

238 { 

239 "package_name": "homebridge", 

240 "icon_url": "/".join([icon_host, "2018/10/Logo2x.png"]), 

241 "title": "homebridge", 

242 "developer_name": "Ondrej Kubik (ondra)", 

243 }, 

244 { 

245 "package_name": "home-assistant-snap", 

246 "icon_url": "/".join( 

247 [icon_host, "2020/07/favicon-192x192.png"] 

248 ), 

249 "title": "Home Assistant", 

250 "developer_name": "Giaever.online (giaever-online)", 

251 "developer_link": "/publisher/giaever-online", 

252 }, 

253 { 

254 "package_name": "security-bear", 

255 "icon_url": "/".join( 

256 [icon_host, "2020/11/security-bear_Logo.png"] 

257 ), 

258 "title": "security-bear", 

259 "developer_name": "CyBear Jinni (cybearjinni)", 

260 "developer_link": "/publisher/cybearjinni", 

261 }, 

262 { 

263 "package_name": "chip-tool", 

264 "icon_url": "/".join([icon_host, "2023/01/1F3E0_color.png"]), 

265 "title": "chip-tool", 

266 "developer_name": "Canonical IoT Labs (canonical-iot-labs)", 

267 "developer_link": "/publisher/canonical-iot-labs", 

268 }, 

269 { 

270 "package_name": "openthread-border-router", 

271 "icon_url": "/".join( 

272 [icon_host, "2023/09/ThreadLogo-stort-1.png"] 

273 ), 

274 "title": "openthread-border-router", 

275 "developer_name": "Canonical IoT Labs (canonical-iot-labs)", 

276 "developer_link": "/publisher/canonical-iot-labs", 

277 }, 

278 { 

279 "package_name": "matter-bridge-tapo-lighting", 

280 "icon_url": "/".join( 

281 [icon_host, "2023/01/1F3E0_color_8tMXOjP.png"] 

282 ), 

283 "title": "matter-bridge-tapo-lighting", 

284 "developer_name": "Canonical IoT Labs (canonical-iot-labs)", 

285 "developer_link": "/publisher/canonical-iot-labs", 

286 }, 

287 { 

288 "package_name": "matter-pi-gpio-commander", 

289 "icon_url": "/".join([icon_host, "2023/03/E1C7_color.png"]), 

290 "title": "matter-pi-gpio-commander", 

291 "developer_name": "Canonical IoT Labs (canonical-iot-labs)", 

292 "developer_link": "/publisher/canonical-iot-labs", 

293 }, 

294 ] 

295 

296 networking = [ 

297 { 

298 "package_name": "mosquitto", 

299 "icon_url": "/".join( 

300 [icon_host, "2018/08/mosquitto-logo-only.svg.png"] 

301 ), 

302 "title": "mosquitto", 

303 "developer_name": "Mosquitto Team (mosquitto)", 

304 "developer_link": "/publisher/mosquitto", 

305 "developer_validation": "verified", 

306 }, 

307 { 

308 "package_name": "domotzpro-agent-publicstore", 

309 "icon_url": "/".join( 

310 [icon_host, "2019/03/new_domotz_icon.png"] 

311 ), 

312 "title": "Domotz Pro Agent", 

313 "developer_name": "Domotz (domotzpublicstore)", 

314 "developer_link": "/publisher/domotzpublicstore", 

315 "developer_validation": "verified", 

316 }, 

317 { 

318 "package_name": "adguard-home", 

319 "icon_url": "/".join([icon_host, "2020/04/256.png"]), 

320 "title": "AdGuard Home", 

321 "developer_name": "AdGuard (ameshkov)", 

322 "developer_link": "/publisher/ameshkov", 

323 "developer_validation": "verified", 

324 }, 

325 { 

326 "package_name": "flexran", 

327 "icon_url": "/".join([icon_host, "2018/04/m5g-flexran.png"]), 

328 "title": "flexran", 

329 "developer_name": "Mosaic 5G (mosaic-5g)", 

330 "developer_link": "/publisher/mosaic-5g", 

331 }, 

332 { 

333 "package_name": "modem-manager", 

334 "icon_url": "/".join([icon_host, "2020/05/mm-logo.png"]), 

335 "title": "modem-manager", 

336 "developer_name": "Canonical", 

337 "developer_link": "/publisher/canonical", 

338 "developer_validation": "verified", 

339 }, 

340 { 

341 "package_name": "snap-store-proxy", 

342 "icon_url": "/".join( 

343 [icon_host, "2018/09/Snapcraft_Proxy_Aubergine-256.png"] 

344 ), 

345 "title": "snap-store-proxy", 

346 "developer_name": "Canonical", 

347 "developer_link": "/publisher/canonical", 

348 "developer_validation": "verified", 

349 }, 

350 ] 

351 

352 board_images = [ 

353 { 

354 "package_name": "pc", 

355 "icon_url": "/".join([icon_host, "2016/07/icon_30.png"]), 

356 "title": "PC", 

357 "developer_name": "Canonical", 

358 "developer_link": "/publisher/canonical", 

359 "developer_validation": "verified", 

360 }, 

361 { 

362 "package_name": "rpi-imager", 

363 "icon_url": "/".join([icon_host, "2020/03/rpi-imager.png"]), 

364 "title": "rpi-imager", 

365 "developer_name": "Dave Jones (waveform)", 

366 "developer_link": "/publisher/waveform", 

367 }, 

368 { 

369 "package_name": "pi-desktop", 

370 "icon_url": DEFAULT_ICON_URL, 

371 "title": "pi-desktop", 

372 "developer_name": "Canonical", 

373 "developer_link": "/publisher/canonical", 

374 "develper_validation": "verified", 

375 }, 

376 { 

377 "package_name": "pi", 

378 "icon_url": DEFAULT_ICON_URL, 

379 "title": "pi", 

380 "developer_name": "Canonical", 

381 "developer_link": "/publisher/canonical", 

382 "developer_validation": "verified", 

383 }, 

384 { 

385 "package_name": "pi2", 

386 "icon_url": "/".join([icon_host, "2015/04/berry.jpg.png"]), 

387 "title": "pi2", 

388 "developer_name": "Canonical", 

389 "developer_link": "/publisher/canonical", 

390 "developer_validation": "verified", 

391 }, 

392 { 

393 "package_name": "pi3", 

394 "icon_url": DEFAULT_ICON_URL, 

395 "title": "pi3", 

396 "developer_name": "Canonical", 

397 "developer_link": "/publisher/canonical", 

398 "developer_validation": "verified", 

399 }, 

400 ] 

401 

402 context = { 

403 "devices": devices, 

404 "robotics": robotics, 

405 "smart_home": smart_home, 

406 "networking": networking, 

407 "board_images": board_images, 

408 } 

409 

410 return ( 

411 flask.render_template("store/categories/iot.html", **context), 

412 status_code, 

413 ) 

414 

415 @snapcraft.route("/about") 

416 def about(): 

417 return flask.render_template("about/index.html") 

418 

419 @snapcraft.route("/about/publish") 

420 def about_publish(): 

421 return flask.render_template("about/publish.html") 

422 

423 @snapcraft.route("/about/listing") 

424 def about_listing(): 

425 return flask.render_template("about/listing.html") 

426 

427 @snapcraft.route("/about/release") 

428 def about_release(): 

429 return flask.render_template("about/release.html") 

430 

431 @snapcraft.route("/about/publicise") 

432 def about_publicise(): 

433 return flask.render_template("about/publicise.html") 

434 

435 @snapcraft.route("/about/contact-us") 

436 def about_contact(): 

437 return flask.render_template("contact-us.html") 

438 

439 @snapcraft.route("/about/thank-you") 

440 def about_thankyou(): 

441 return flask.render_template("thank-you.html") 

442 

443 @snapcraft.route("/community") 

444 def community_redirect(): 

445 return flask.redirect("/") 

446 

447 @snapcraft.route("/create") 

448 def create_redirect(): 

449 return flask.redirect("https://docs.snapcraft.io/build-snaps") 

450 

451 @snapcraft.route("/build") 

452 def build(): 

453 status_code = 200 

454 

455 return flask.render_template("snapcraft/build.html"), status_code 

456 

457 @snapcraft.route("/sitemap.xml") 

458 def sitemap(): 

459 xml_sitemap = flask.render_template( 

460 "sitemap/sitemap-index.xml", 

461 base_url="https://snapcraft.io", 

462 ) 

463 response = flask.make_response(xml_sitemap) 

464 response.headers["Content-Type"] = "application/xml" 

465 

466 return response 

467 

468 @snapcraft.route("/sitemap-links.xml") 

469 def sitemap_links(): 

470 base_url = "https://snapcraft.io" 

471 links = [ 

472 {"url": f"{base_url}/about"}, 

473 {"url": f"{base_url}/about/publish"}, 

474 {"url": f"{base_url}/about/listing"}, 

475 {"url": f"{base_url}/about/release"}, 

476 {"url": f"{base_url}/about/publicise"}, 

477 {"url": f"{base_url}/iot"}, 

478 ] 

479 

480 xml_sitemap = flask.render_template( 

481 "sitemap/sitemap.xml", 

482 base_url="https://snapcraft.io", 

483 links=links, 

484 ) 

485 response = flask.make_response(xml_sitemap) 

486 response.headers["Content-Type"] = "application/xml" 

487 response.headers["Cache-Control"] = "public, max-age=43200" 

488 

489 return response 

490 

491 return snapcraft