1use crate::{
2 auth::RequestExt as _, github::Release, AppState, LayoutData, Request, RequestExt as _,
3};
4use comrak::ComrakOptions;
5use serde::{Deserialize, Serialize};
6use std::sync::Arc;
7use tide::{http::mime, log, Server};
8
9pub fn add_routes(app: &mut Server<Arc<AppState>>) {
10 app.at("/").get(get_home);
11 app.at("/signups").post(post_signup);
12 app.at("/releases/:tag_name/:name").get(get_release_asset);
13}
14
15async fn get_home(mut request: Request) -> tide::Result {
16 #[derive(Serialize)]
17 struct HomeData {
18 #[serde(flatten)]
19 layout: Arc<LayoutData>,
20 releases: Option<Vec<Release>>,
21 }
22
23 let mut data = HomeData {
24 layout: request.layout_data().await?,
25 releases: None,
26 };
27
28 if let Some(user) = request.current_user().await? {
29 if user.is_insider {
30 data.releases = Some(
31 request
32 .state()
33 .repo_client
34 .releases()
35 .await?
36 .into_iter()
37 .filter_map(|mut release| {
38 if release.draft {
39 None
40 } else {
41 let mut options = ComrakOptions::default();
42 options.render.unsafe_ = true; // Allow raw HTML in the markup. We control these release notes anyway.
43 release.body = comrak::markdown_to_html(&release.body, &options);
44 Some(release)
45 }
46 })
47 .collect(),
48 );
49 }
50 }
51
52 Ok(tide::Response::builder(200)
53 .body(request.state().render_template("home.hbs", &data)?)
54 .content_type(mime::HTML)
55 .build())
56}
57
58async fn post_signup(mut request: Request) -> tide::Result {
59 #[derive(Debug, Deserialize)]
60 struct Form {
61 github_login: String,
62 email_address: String,
63 about: String,
64 }
65
66 let mut form: Form = request.body_form().await?;
67 form.github_login = form
68 .github_login
69 .strip_prefix("@")
70 .map(str::to_string)
71 .unwrap_or(form.github_login);
72
73 log::info!("Signup submitted: {:?}", form);
74
75 // Save signup in the database
76 request
77 .db()
78 .create_signup(&form.github_login, &form.email_address, &form.about)
79 .await?;
80
81 let layout_data = request.layout_data().await?;
82 Ok(tide::Response::builder(200)
83 .body(
84 request
85 .state()
86 .render_template("signup.hbs", &layout_data)?,
87 )
88 .content_type(mime::HTML)
89 .build())
90}
91
92async fn get_release_asset(request: Request) -> tide::Result {
93 let body = request
94 .state()
95 .repo_client
96 .release_asset(request.param("tag_name")?, request.param("name")?)
97 .await?;
98
99 Ok(tide::Response::builder(200)
100 .header("Cache-Control", "no-transform")
101 .content_type(mime::BYTE_STREAM)
102 .body(body)
103 .build())
104}