From 436511846130ae5d8a058e031d9c8ad0bcb002aa Mon Sep 17 00:00:00 2001 From: mrw1593 Date: Mon, 29 May 2023 15:56:27 -0400 Subject: Create stubbed endpoints for authorization --- src/api/mod.rs | 9 ++++--- src/api/oauth.rs | 60 ++++++++++++++++++++++++++++++++++++---------- src/api/ops.rs | 13 +--------- src/main.rs | 2 +- src/resources/templates.rs | 19 +++++---------- src/services/db/client.rs | 19 +++++++++++++++ 6 files changed, 81 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/api/mod.rs b/src/api/mod.rs index 3d74be8..0ab4037 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,10 +1,13 @@ +mod clients; mod liveops; +mod oauth; mod ops; mod users; -mod oauth; -mod clients; +pub use clients::service as clients; pub use liveops::service as liveops; +pub use oauth::service as oauth; pub use ops::service as ops; pub use users::service as users; -pub use clients::service as clients; + +pub use oauth::AuthorizationParameters; diff --git a/src/api/oauth.rs b/src/api/oauth.rs index 9e0e5c6..9916053 100644 --- a/src/api/oauth.rs +++ b/src/api/oauth.rs @@ -1,24 +1,60 @@ -use std::collections::HashMap; +use std::str::FromStr; -use actix_web::{web, HttpResponse}; -use serde::Deserialize; +use actix_web::{get, post, web, HttpResponse, Scope}; +use serde::{Deserialize, Serialize}; +use sqlx::MySqlPool; +use tera::Tera; +use unic_langid::subtags::Language; use url::Url; -use uuid::Uuid; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] +use crate::resources::{languages, templates}; +use crate::services::db; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] enum ResponseType { Code, Token, } -#[derive(Debug, Clone, Deserialize)] -struct AuthorizationParameters { +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AuthorizationParameters { response_type: ResponseType, - client_id: Uuid, - redirect_uri: Url, - state: Box, + redirect_uri: Option, +} + +#[derive(Debug, Clone, Deserialize)] +struct AuthorizeCredentials { + username: Box, + password: Box, +} + +#[post("/authorize")] +async fn authorize( + query: web::Query, + credentials: web::Form, +) -> HttpResponse { + // TODO check that the URI is valid + todo!() +} + +#[get("/authorize")] +async fn authorize_page( + db: web::Data, + tera: web::Data, + translations: web::Data, + query: web::Query, +) -> HttpResponse { + // TODO find a better way of doing languages + // TODO check that the URI is valid + let language = Language::from_str("en").unwrap(); + let page = + templates::login_page(&tera, &query, language, translations.get_ref().clone()).unwrap(); + HttpResponse::Ok().content_type("text/html").body(page) +} - #[serde(flatten)] - additional_parameters: HashMap, Box>, +pub fn service() -> Scope { + web::scope("/oauth") + .service(authorize_page) + .service(authorize) } diff --git a/src/api/ops.rs b/src/api/ops.rs index d947e64..555bb1b 100644 --- a/src/api/ops.rs +++ b/src/api/ops.rs @@ -65,17 +65,6 @@ async fn login( Ok(response) } -#[get("/login")] -async fn login_page( - tera: web::Data, - translations: web::Data, -) -> HttpResponse { - // TODO find a better way of doing this - let language = Language::from_str("en").unwrap(); - let page = templates::login_page(&tera, language, translations.get_ref().clone()).unwrap(); - HttpResponse::Ok().content_type("text/html").body(page) -} - pub fn service() -> Scope { - web::scope("").service(login).service(login_page) + web::scope("").service(login) } diff --git a/src/main.rs b/src/main.rs index aca5977..c288c7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,7 +49,6 @@ async fn main() -> Result<(), RawUnexpected> { .app_data(Data::new(tera.clone())) .app_data(Data::new(translations.clone())) // frontend services - // has to be first so they don't get overwritten by the "" scope .service(style::get_css) .service(scripts::get_js) .service(languages::languages()) @@ -57,6 +56,7 @@ async fn main() -> Result<(), RawUnexpected> { .service(api::liveops()) .service(api::users()) .service(api::clients()) + .service(api::oauth()) .service(api::ops()) }) .shutdown_timeout(1) diff --git a/src/resources/templates.rs b/src/resources/templates.rs index 43d6b67..7578256 100644 --- a/src/resources/templates.rs +++ b/src/resources/templates.rs @@ -5,13 +5,9 @@ use raise::yeet; use tera::{Function, Tera, Value}; use unic_langid::subtags::Language; -use super::languages; +use crate::api::AuthorizationParameters; -fn make_lang(language: Language) -> impl Function { - Box::new(move |_: &HashMap| -> tera::Result { - Ok(Value::String(language.to_string())) - }) -} +use super::languages; fn make_msg(language: Language, translations: languages::Translations) -> impl Function { Box::new( @@ -24,10 +20,6 @@ fn make_msg(language: Language, translations: languages::Translations) -> impl F ) } -fn make_base_url() -> impl Function { - Box::new(|_: &HashMap| Ok(Value::String("foo".to_string()))) -} - fn extend_tera( tera: &Tera, language: Language, @@ -35,9 +27,7 @@ fn extend_tera( ) -> Result { let mut new_tera = initialize()?; new_tera.extend(tera)?; - new_tera.register_function("lang", make_lang(language)); new_tera.register_function("msg", make_msg(language, translations)); - new_tera.register_function("baseUrl", make_base_url()); Ok(new_tera) } @@ -48,12 +38,15 @@ pub fn initialize() -> tera::Result { pub fn login_page( tera: &Tera, + params: &AuthorizationParameters, language: Language, mut translations: languages::Translations, ) -> Result { translations.refresh()?; let mut tera = extend_tera(tera, language, translations)?; tera.full_reload()?; - let context = tera::Context::new(); + let mut context = tera::Context::new(); + context.insert("lang", language.as_str()); + context.insert("params", &serde_urlencoded::to_string(params)?); tera.render("login.html", &context).unexpect() } diff --git a/src/services/db/client.rs b/src/services/db/client.rs index d1531be..4643f49 100644 --- a/src/services/db/client.rs +++ b/src/services/db/client.rs @@ -98,6 +98,25 @@ pub async fn get_client_redirect_uris<'c>( .collect() } +pub async fn client_has_redirect_uri<'c>( + executor: impl Executor<'c, Database = MySql>, + id: Uuid, + url: Url, +) -> Result { + query_scalar!( + r"SELECT EXISTS( + SELECT redirect_uri + FROM client_redirect_uris + WHERE client_id = ? AND redirect_uri = ? + ) as `e: bool`", + id, + url.to_string() + ) + .fetch_one(executor) + .await + .unexpect() +} + async fn delete_client_redirect_uris<'c>( executor: impl Executor<'c, Database = MySql>, id: Uuid, -- cgit v1.2.3