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    }
 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}