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

84 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-14 22:07 +0000

1import flask 

2 

3from webapp.snapcraft import logic 

4 

5 

6def snapcraft_blueprint(): 

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

8 

9 @snapcraft.route("/") 

10 def homepage(): 

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

12 

13 livestream = logic.get_livestreams() 

14 

15 return flask.render_template( 

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

17 ) 

18 

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

20 def get_account_json(): 

21 """ 

22 A JSON endpoint to request login status 

23 """ 

24 try: 

25 publisher = None 

26 

27 if "publisher" in flask.session: 

28 publisher = flask.session["publisher"] 

29 

30 response = {"publisher": publisher} 

31 response = flask.make_response(response) 

32 

33 # Unset the last_login_method cookie to avoid forcing 

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

35 

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

37 

38 return response 

39 except Exception: 

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

41 response = flask.make_response(response) 

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

43 return response, 502 

44 

45 @snapcraft.route("/iot") 

46 def iot(): 

47 status_code = 200 

48 

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

50 assets_host = "https://assets.ubuntu.com/v1" 

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": "/".join( 

135 [assets_host, "be6eb412-snapcraft-missing-icon.svg"] 

136 ), 

137 "title": "pi-bluetooth", 

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

139 "developer_link": "/publisher/waveform", 

140 }, 

141 ] 

142 

143 robotics = [ 

144 { 

145 "package_name": "arduino", 

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

147 "title": "Arduino IDE", 

148 "developer_name": "Snapcrafters", 

149 "developer_link": "/publisher/snapcrafters", 

150 "developer_validation": "starred", 

151 }, 

152 { 

153 "package_name": "rosbot-xl", 

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

155 "title": "ROSbot XL", 

156 "developer_name": "Husarion", 

157 "developer_link": "/publisher/husarion", 

158 "developer_validation": "verified", 

159 }, 

160 { 

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

162 "icon_url": "/".join( 

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

164 ), 

165 "title": "ROSbot XL: teleop", 

166 "developer_name": "Husarion", 

167 "developer_link": "/publisher/husarion", 

168 "developer_validation": "verified", 

169 }, 

170 { 

171 "package_name": "webots", 

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

173 "title": "Webots", 

174 "developer_name": "Cyberbotics", 

175 "developer_link": "/publisher/cyberbotics", 

176 }, 

177 { 

178 "package_name": "gazebo", 

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

180 "title": "gazebo", 

181 "developer_name": ( 

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

183 ), 

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

185 "developer_validation": "verified", 

186 }, 

187 { 

188 "package_name": "ros2-cli", 

189 "icon_url": "/".join( 

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

191 ), 

192 "title": "ros2-cli", 

193 "developer_name": ( 

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

195 ), 

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

197 "developer_validation": "verified", 

198 }, 

199 { 

200 "package_name": "vulcanexus-router", 

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

202 "title": "Vulcanexus Router", 

203 "developer_name": "eProsima", 

204 "developer_link": "/publisher/eprosima", 

205 }, 

206 { 

207 "package_name": "bow-webots", 

208 "icon_url": "/".join( 

209 [assets_host, "be6eb412-snapcraft-missing-icon.svg"] 

210 ), 

211 "title": "BOW Webots", 

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

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

214 }, 

215 { 

216 "package_name": "foxglove-studio", 

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

218 "title": "foxglove-studio", 

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

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

221 }, 

222 { 

223 "package_name": "husarion-ouster", 

224 "icon_url": "/".join( 

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

226 ), 

227 "title": "husarion-ouster", 

228 "developer_name": "Husarion", 

229 "developer_link": "/publisher/husarion", 

230 "developer_validation": "verified", 

231 }, 

232 ] 

233 

234 smart_home = [ 

235 { 

236 "package_name": "openhab", 

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

238 "title": "openhab", 

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

240 "developer_link": "/publisher/openhab", 

241 }, 

242 { 

243 "package_name": "homebridge", 

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

245 "title": "homebridge", 

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

247 }, 

248 { 

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

250 "icon_url": "/".join( 

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

252 ), 

253 "title": "Home Assistant", 

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

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

256 }, 

257 { 

258 "package_name": "security-bear", 

259 "icon_url": "/".join( 

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

261 ), 

262 "title": "security-bear", 

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

264 "developer_link": "/publisher/cybearjinni", 

265 }, 

266 { 

267 "package_name": "chip-tool", 

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

269 "title": "chip-tool", 

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

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

272 }, 

273 { 

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

275 "icon_url": "/".join( 

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

277 ), 

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

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

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

281 }, 

282 { 

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

284 "icon_url": "/".join( 

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

286 ), 

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

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

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

290 }, 

291 { 

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

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

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

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

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

297 }, 

298 ] 

299 

300 networking = [ 

301 { 

302 "package_name": "mosquitto", 

303 "icon_url": "/".join( 

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

305 ), 

306 "title": "mosquitto", 

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

308 "developer_link": "/publisher/mosquitto", 

309 "developer_validation": "verified", 

310 }, 

311 { 

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

313 "icon_url": "/".join( 

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

315 ), 

316 "title": "Domotz Pro Agent", 

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

318 "developer_link": "/publisher/domotzpublicstore", 

319 "developer_validation": "verified", 

320 }, 

321 { 

322 "package_name": "adguard-home", 

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

324 "title": "AdGuard Home", 

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

326 "developer_link": "/publisher/ameshkov", 

327 "developer_validation": "verified", 

328 }, 

329 { 

330 "package_name": "flexran", 

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

332 "title": "flexran", 

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

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

335 }, 

336 { 

337 "package_name": "modem-manager", 

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

339 "title": "modem-manager", 

340 "developer_name": "Canonical", 

341 "developer_link": "/publisher/canonical", 

342 "developer_validation": "verified", 

343 }, 

344 { 

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

346 "icon_url": "/".join( 

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

348 ), 

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

350 "developer_name": "Canonical", 

351 "developer_link": "/publisher/canonical", 

352 "developer_validation": "verified", 

353 }, 

354 ] 

355 

356 board_images = [ 

357 { 

358 "package_name": "pc", 

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

360 "title": "PC", 

361 "developer_name": "Canonical", 

362 "developer_link": "/publisher/canonical", 

363 "developer_validation": "verified", 

364 }, 

365 { 

366 "package_name": "rpi-imager", 

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

368 "title": "rpi-imager", 

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

370 "developer_link": "/publisher/waveform", 

371 }, 

372 { 

373 "package_name": "pi-desktop", 

374 "icon_url": "/".join( 

375 [assets_host, "be6eb412-snapcraft-missing-icon.svg"] 

376 ), 

377 "title": "pi-desktop", 

378 "developer_name": "Canonical", 

379 "developer_link": "/publisher/canonical", 

380 "develper_validation": "verified", 

381 }, 

382 { 

383 "package_name": "pi", 

384 "icon_url": "/".join( 

385 [assets_host, "be6eb412-snapcraft-missing-icon.svg"] 

386 ), 

387 "title": "pi", 

388 "developer_name": "Canonical", 

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

390 "developer_validation": "verified", 

391 }, 

392 { 

393 "package_name": "pi2", 

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

395 "title": "pi2", 

396 "developer_name": "Canonical", 

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

398 "developer_validation": "verified", 

399 }, 

400 { 

401 "package_name": "pi3", 

402 "icon_url": "/".join( 

403 [assets_host, "be6eb412-snapcraft-missing-icon.svg"] 

404 ), 

405 "title": "pi3", 

406 "developer_name": "Canonical", 

407 "developer_link": "/publisher/canonical", 

408 "developer_validation": "verified", 

409 }, 

410 ] 

411 

412 context = { 

413 "devices": devices, 

414 "robotics": robotics, 

415 "smart_home": smart_home, 

416 "networking": networking, 

417 "board_images": board_images, 

418 } 

419 

420 return ( 

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

422 status_code, 

423 ) 

424 

425 @snapcraft.route("/about") 

426 def about(): 

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

428 

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

430 def about_publish(): 

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

432 

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

434 def about_listing(): 

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

436 

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

438 def about_release(): 

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

440 

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

442 def about_publicise(): 

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

444 

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

446 def about_contact(): 

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

448 

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

450 def about_thankyou(): 

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

452 

453 @snapcraft.route("/community") 

454 def community_redirect(): 

455 return flask.redirect("/") 

456 

457 @snapcraft.route("/create") 

458 def create_redirect(): 

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

460 

461 @snapcraft.route("/build") 

462 def build(): 

463 status_code = 200 

464 

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

466 

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

468 def sitemap(): 

469 xml_sitemap = flask.render_template( 

470 "sitemap/sitemap-index.xml", 

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

472 ) 

473 response = flask.make_response(xml_sitemap) 

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

475 

476 return response 

477 

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

479 def sitemap_links(): 

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

481 links = [ 

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

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

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

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

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

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

488 ] 

489 

490 xml_sitemap = flask.render_template( 

491 "sitemap/sitemap.xml", 

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

493 links=links, 

494 ) 

495 response = flask.make_response(xml_sitemap) 

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

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

498 

499 return response 

500 

501 return snapcraft