summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/mod.rs9
-rw-r--r--src/api/oauth.rs60
-rw-r--r--src/api/ops.rs13
-rw-r--r--src/main.rs2
-rw-r--r--src/resources/templates.rs19
-rw-r--r--src/services/db/client.rs19
6 files changed, 81 insertions, 41 deletions
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<str>,
+ redirect_uri: Option<Url>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+struct AuthorizeCredentials {
+ username: Box<str>,
+ password: Box<str>,
+}
+
+#[post("/authorize")]
+async fn authorize(
+ query: web::Query<AuthorizationParameters>,
+ credentials: web::Form<AuthorizeCredentials>,
+) -> HttpResponse {
+ // TODO check that the URI is valid
+ todo!()
+}
+
+#[get("/authorize")]
+async fn authorize_page(
+ db: web::Data<MySqlPool>,
+ tera: web::Data<Tera>,
+ translations: web::Data<languages::Translations>,
+ query: web::Query<AuthorizationParameters>,
+) -> 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<str>, Box<str>>,
+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<Tera>,
- translations: web::Data<languages::Translations>,
-) -> 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<String, Value>| -> tera::Result<Value> {
- 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<String, Value>| Ok(Value::String("foo".to_string())))
-}
-
fn extend_tera(
tera: &Tera,
language: Language,
@@ -35,9 +27,7 @@ fn extend_tera(
) -> Result<Tera, RawUnexpected> {
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<Tera> {
pub fn login_page(
tera: &Tera,
+ params: &AuthorizationParameters,
language: Language,
mut translations: languages::Translations,
) -> Result<String, RawUnexpected> {
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<bool, RawUnexpected> {
+ 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,