From 2f8dce44d3f2be74b5c6ec0a2e7f4ceced715328 Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 13 Jul 2022 10:33:30 +0200 Subject: initial import --- src/api/auth/invite.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/api/auth/invite.rs (limited to 'src/api/auth/invite.rs') diff --git a/src/api/auth/invite.rs b/src/api/auth/invite.rs new file mode 100644 index 0000000..dd81540 --- /dev/null +++ b/src/api/auth/invite.rs @@ -0,0 +1,47 @@ +use base64::URL_SAFE_NO_PAD; +use chrono::{Duration, Utc}; +use rocket::{http::uri::Reference, serde::json::Json, State}; +use serde::{Deserialize, Serialize}; + +use crate::{api::auth, auth::Authenticated, crypto::SecretBytes, db::DbConn, Config}; + +use super::WithVerifiedFxaLogin; + +pub(crate) async fn generate_invite_link( + db: &DbConn, + cfg: &Config, + ttl: Duration, +) -> anyhow::Result> { + let code = base64::encode_config(&SecretBytes::<32>::generate().0, URL_SAFE_NO_PAD); + db.add_invite_code(&code, Utc::now() + ttl).await?; + Ok(Reference::parse_owned(format!("{}/#/register/{}", cfg.location, code)) + .map_err(|e| anyhow!("url building failed at {e}"))?) +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +pub(crate) struct GenerateReq { + ttl_hours: u32, +} + +#[derive(Debug, Serialize)] +pub(crate) struct GenerateResp { + url: Reference<'static>, +} + +#[post("/generate", data = "")] +pub(crate) async fn generate( + db: &DbConn, + cfg: &State, + req: Authenticated, +) -> auth::Result { + if !req.context.verified { + return Err(auth::Error::UnverifiedSession); + } + let user = db.get_user_by_id(&req.context.uid).await?; + if user.email != cfg.invite_admin_address { + return Err(auth::Error::InvalidAuthToken); + } + let url = generate_invite_link(&db, &cfg, Duration::hours(req.body.ttl_hours as i64)).await?; + Ok(Json(GenerateResp { url })) +} -- cgit v1.2.3