home.rs

  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        #[serde(default)]
 65        wants_releases: bool,
 66        #[serde(default)]
 67        wants_updates: bool,
 68        #[serde(default)]
 69        wants_community: bool,
 70    }
 71
 72    let mut form: Form = request.body_form().await?;
 73    form.github_login = form
 74        .github_login
 75        .strip_prefix("@")
 76        .map(str::to_string)
 77        .unwrap_or(form.github_login);
 78
 79    log::info!("Signup submitted: {:?}", form);
 80
 81    // Save signup in the database
 82    request
 83        .db()
 84        .create_signup(
 85            &form.github_login,
 86            &form.email_address,
 87            &form.about,
 88            form.wants_releases,
 89            form.wants_updates,
 90            form.wants_community,
 91        )
 92        .await?;
 93
 94    let layout_data = request.layout_data().await?;
 95    Ok(tide::Response::builder(200)
 96        .body(
 97            request
 98                .state()
 99                .render_template("signup.hbs", &layout_data)?,
100        )
101        .content_type(mime::HTML)
102        .build())
103}
104
105async fn get_release_asset(request: Request) -> tide::Result {
106    let body = request
107        .state()
108        .repo_client
109        .release_asset(request.param("tag_name")?, request.param("name")?)
110        .await?;
111
112    Ok(tide::Response::builder(200)
113        .header("Cache-Control", "no-transform")
114        .content_type(mime::BYTE_STREAM)
115        .body(body)
116        .build())
117}