From a3df3e882e2da8662317cc50a08f6d14e444734c Mon Sep 17 00:00:00 2001 From: alemi Date: Sun, 24 Mar 2024 23:55:48 +0100 Subject: [PATCH] feat: super barebones auth route --- Cargo.toml | 2 ++ src/activitypub/mod.rs | 47 +++++++++++++++++++++++++++++++++++++++++- src/router.rs | 2 ++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ae65a7c..fa3cfd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,5 @@ uuid = { version = "1.8.0", features = ["v4"] } jrd = "0.1" # nodeinfo = "0.0.2" # the version on crates.io doesn't re-export necessary types to build the struct!!! nodeinfo = { git = "https://codeberg.org/thefederationinfo/nodeinfo-rs", rev = "e865094804" } +rand = "0.8.5" +sha256 = "1.5.0" diff --git a/src/activitypub/mod.rs b/src/activitypub/mod.rs index f9efe53..878b888 100644 --- a/src/activitypub/mod.rs +++ b/src/activitypub/mod.rs @@ -9,8 +9,10 @@ pub mod jsonld; pub use jsonld::JsonLD; use axum::{extract::State, http::StatusCode, Json}; +use rand::Rng; +use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter}; -use crate::{activitystream::{object::{actor::{ActorMut, ActorType}, ObjectMut}, BaseMut}, server::Context, url}; +use crate::{activitystream::{object::{actor::{ActorMut, ActorType}, ObjectMut}, BaseMut}, model, server::Context, url}; use self::jsonld::LD; @@ -55,3 +57,46 @@ pub async fn view(State(ctx): State) -> Result, )) } + +#[derive(Debug, Clone, serde::Deserialize)] +pub struct LoginForm { + email: String, + password: String, +} + +pub async fn auth(State(ctx): State, Json(login): Json) -> Result, StatusCode> { + // TODO salt the pwd + match model::credential::Entity::find() + .filter(Condition::all() + .add(model::credential::Column::Email.eq(login.email)) + .add(model::credential::Column::Password.eq(sha256::digest(login.password))) + ) + .one(ctx.db()) + .await + { + Ok(Some(x)) => { + // TODO should probably use crypto-safe rng + let token : String = rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(128) + .map(char::from) + .collect(); + model::session::Entity::insert( + model::session::ActiveModel { + id: sea_orm::ActiveValue::NotSet, + actor: sea_orm::ActiveValue::Set(x.id), + session: sea_orm::ActiveValue::Set(token.clone()), + expires: sea_orm::ActiveValue::Set(chrono::Utc::now() + std::time::Duration::from_secs(3600 * 6)), + } + ) + .exec(ctx.db()) + .await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + Ok(Json(serde_json::Value::String(token))) + }, + Ok(None) => Err(StatusCode::UNAUTHORIZED), + Err(e) => { + tracing::error!("error querying db for user credentials: {e}"); + Err(StatusCode::INTERNAL_SERVER_ERROR) + } + } +} diff --git a/src/router.rs b/src/router.rs index 7835e68..e853ef1 100644 --- a/src/router.rs +++ b/src/router.rs @@ -12,6 +12,8 @@ pub async fn serve(db: DatabaseConnection, domain: String) { // .route("/inbox", post(ap::inbox::post)) // .route("/outbox", get(ap::outbox::get)) // .route("/outbox", get(ap::outbox::post)) + // AUTH routes + .route("/auth", post(ap::auth)) // .well-known and discovery .route("/.well-known/webfinger", get(ap::well_known::webfinger)) .route("/.well-known/host-meta", get(ap::well_known::host_meta))