use std::future::Future; use crate::{ config::Config, schema::{self, UIDCDatabase}, server::{self, SessionHelper, UIDCRequest}, }; mod generic_oidc; mod github; pub trait ExternalAuthenticator { fn build(db: &UIDCDatabase, config: &Config) -> Option where Self: Sized; fn register_routes(&'static self, server: &mut tide::Server); fn generate_login_url(&self, realm: &str, redirect: &str) -> String; fn generate_registration_url(&self, realm: &str, redirect: &str) -> String; fn extract_login_state(&self, req: UIDCRequest) -> impl Future; fn handle_registration(&self, _req: UIDCRequest) -> tide::Response { todo!() } fn handle_matching_login( &self, req: UIDCRequest, user: schema::UserID, redirect: &str, ) -> tide::Response { let sh = SessionHelper::new(&req); let mut lease = req.state().pool.acquire().expect("couldn't get lease"); let Ok((resp, cookie)) = sh.get_or_build_session(&mut lease, &req) else { return tide::Response::builder(500) .body("error while building session") .build(); }; let realm_id = sh.get_realm(&mut lease).unwrap().id(); // remove any existing authentication for this realm just in case resp.auth .with(schema::SessionAuth::Realm, realm_id) .first() .delete(&mut lease) .expect("couldn't remove existing authentication"); resp.auth .insert( &mut lease, schema::SessionAuth { realm: realm_id, user: Some(user), pending_user: None, pending_challenges: vec![].into_serialized(), }, ) .expect("couldn't insert new authentication"); let mut resp: tide::Response = tide::Redirect::see_other(redirect).into(); if let Some(cookie) = cookie { resp.insert_cookie(cookie); } return resp; } fn handle_no_mapping(&self, req: UIDCRequest, redirect: String) -> tide::Response { let sh = SessionHelper::new(&req); return sh.render_login_from_auth( tide::Response::new(200), redirect, None, Some("External user not associated with any local user.".to_string()), ); } } pub use generic_oidc::{OIDCAuthenticator, OIDCConfig}; pub use github::{GithubAuthenticator, GithubConfig}; use microrm::{ prelude::{Insertable, Queryable}, schema::Serializable, };