From cdcdba2b9a02dd698c77ab9b37d50fccc21acb18 Mon Sep 17 00:00:00 2001
From: Philippe Loctaux
Date: Wed, 5 Apr 2023 18:09:32 +0200
Subject: [PATCH] ezidam: split home routes
---
crates/ezidam/src/menu/items/admin.rs | 2 +-
crates/ezidam/src/menu/items/user.rs | 2 +-
crates/ezidam/src/routes/root.rs | 149 ++----------------------
crates/ezidam/src/routes/root/avatar.rs | 34 ++++++
crates/ezidam/src/routes/root/home.rs | 23 ++++
crates/ezidam/src/routes/root/logo.rs | 36 ++++++
crates/ezidam/src/routes/root/logout.rs | 49 ++++++++
crates/ezidam/src/routes/setup.rs | 6 +-
8 files changed, 160 insertions(+), 141 deletions(-)
create mode 100644 crates/ezidam/src/routes/root/avatar.rs
create mode 100644 crates/ezidam/src/routes/root/home.rs
create mode 100644 crates/ezidam/src/routes/root/logo.rs
create mode 100644 crates/ezidam/src/routes/root/logout.rs
diff --git a/crates/ezidam/src/menu/items/admin.rs b/crates/ezidam/src/menu/items/admin.rs
index 702f9a0..a04cba8 100644
--- a/crates/ezidam/src/menu/items/admin.rs
+++ b/crates/ezidam/src/menu/items/admin.rs
@@ -24,7 +24,7 @@ impl AdminMenu {
MainItem {
id: AdminMenu::Exit.id(),
label: "Exit admin panel",
- link: uri!(routes::root::homepage).to_string(),
+ link: uri!(routes::root::home::homepage).to_string(),
icon: Icon::Logout.svg,
sub: None,
},
diff --git a/crates/ezidam/src/menu/items/user.rs b/crates/ezidam/src/menu/items/user.rs
index f7e3bb5..804e9e9 100644
--- a/crates/ezidam/src/menu/items/user.rs
+++ b/crates/ezidam/src/menu/items/user.rs
@@ -17,7 +17,7 @@ impl UserMenu {
vec![MainItem {
id: UserMenu::Home.id(),
label: "Home",
- link: uri!(routes::root::homepage).to_string(),
+ link: uri!(routes::root::home::homepage).to_string(),
icon: Icon::Home.svg,
sub: None,
}]
diff --git a/crates/ezidam/src/routes/root.rs b/crates/ezidam/src/routes/root.rs
index 18199a0..0f55f42 100644
--- a/crates/ezidam/src/routes/root.rs
+++ b/crates/ezidam/src/routes/root.rs
@@ -1,86 +1,26 @@
use super::prelude::*;
-use crate::tokens::{JWT_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME};
-use rocket::http::{Cookie, CookieJar};
-use rocket::{get, post};
-use settings::Settings;
-use users::User;
+use avatar::*;
+use home::*;
+use logo::*;
+use logout::*;
+
+pub mod avatar;
+pub mod home;
+pub mod logo;
+pub mod logout;
pub fn routes() -> Vec {
routes![
- logo,
- avatar,
+ get_logo,
+ user_avatar,
homepage,
homepage_user,
homepage_redirect,
redirect_to_setup,
- logout,
+ request_logout,
]
}
-#[get("/logo")]
-async fn logo(mut db: Connection) -> Result {
- // Get settings
- let settings = Settings::get(&mut *db).await?;
-
- // HTTP response
- Ok(FileFromBytes::from(settings.business_logo()))
-}
-
-#[cfg(test)]
-mod test {
- use crate::tests::*;
-
- #[test]
- fn logo() {
- // Setup http server
- let client = setup_rocket_testing();
-
- // Make request
- let response = client.get(uri!(super::logo)).dispatch();
- assert_eq!(response.status(), Status::Ok);
-
- // Assert size of logo
- let logo_length = response.into_bytes().expect("bytes containing logo").len();
- use settings::DEFAULT_BUSINESS_LOGO;
- assert_eq!(
- logo_length,
- DEFAULT_BUSINESS_LOGO.len(),
- "Invalid logo size in bytes, value was `{logo_length}`",
- );
- }
-}
-
-#[get("/avatar/?")]
-async fn avatar(
- mut db: Connection,
- _user: JwtUser,
- user_id: RocketUserID,
- size: Option,
-) -> Result {
- // Verify existence of user
- User::get_by_login(&mut *db, user_id.0.as_ref())
- .await?
- .ok_or_else(|| Error::not_found(user_id.0.to_string()))?;
-
- // Generate avatar
- let avatar = task::spawn_blocking(move || {
- let mut avatar = identicon_rs::Identicon::new(user_id.0);
-
- // Set optional size
- if let Some(size) = size {
- avatar.set_scale(size)?;
- }
-
- avatar.export_png_data()
- })
- .await?;
-
- // HTTP response
- avatar
- .map(FileFromBytes::from)
- .map_err(Error::internal_server_error)
-}
-
pub mod content {
use jwt::JwtClaims;
use rocket::serde::Serialize;
@@ -92,68 +32,3 @@ pub mod content {
pub user: JwtClaims,
}
}
-
-#[get("/")]
-async fn redirect_to_setup(_setup: NeedSetup) -> Redirect {
- Redirect::to(uri!(super::setup::setup))
-}
-
-#[get("/", rank = 2)]
-async fn homepage(admin: JwtAdmin) -> Page {
- Page::Homepage(content::Homepage { user: admin.0 })
-}
-
-#[get("/", rank = 3)]
-async fn homepage_user(user: JwtUser) -> Page {
- Page::Homepage(content::Homepage { user: user.0 })
-}
-
-#[get("/", rank = 4)]
-async fn homepage_redirect() -> Redirect {
- Redirect::to(uri!(super::oauth::authorize::authorize_ezidam))
-}
-
-#[post("/logout")]
-async fn logout(
- mut db: Connection,
- refresh_token: RefreshToken,
- cookie_jar: &CookieJar<'_>,
-) -> Result {
- let mut transaction = db.begin().await?;
-
- let refresh_token = refresh_tokens::RefreshToken::get_one(&mut transaction, &refresh_token.0)
- .await?
- .ok_or_else(|| Error::not_found("Unknown refresh token"))?;
-
- // Delete cookies
- cookie_jar.remove(Cookie::named(JWT_COOKIE_NAME));
- cookie_jar.remove(Cookie::named(REFRESH_TOKEN_COOKIE_NAME));
-
- // If refresh token has already been used
- if refresh_token.has_been_used() {
- // Revoke all refresh tokens for user
- refresh_tokens::RefreshToken::revoke_all_for_user(&mut transaction, refresh_token.user())
- .await?;
-
- transaction.commit().await?;
-
- return Err(Error::forbidden("This refresh token has already been used"));
- }
-
- // If token has been revoked
- if refresh_token.is_revoked() {
- return Err(Error::forbidden("This refresh token has been revoked"));
- }
-
- // If token has expired
- if refresh_token.has_expired() {
- return Err(Error::forbidden("This refresh token has expired"));
- }
-
- // Revoke token
- refresh_token.revoke(&mut transaction).await?;
-
- transaction.commit().await?;
-
- Ok(Redirect::to(uri!(homepage)))
-}
diff --git a/crates/ezidam/src/routes/root/avatar.rs b/crates/ezidam/src/routes/root/avatar.rs
new file mode 100644
index 0000000..a4f0efa
--- /dev/null
+++ b/crates/ezidam/src/routes/root/avatar.rs
@@ -0,0 +1,34 @@
+use crate::routes::prelude::*;
+use rocket::get;
+use users::User;
+
+#[get("/avatar/?")]
+pub async fn user_avatar(
+ mut db: Connection,
+ _user: JwtUser,
+ user_id: RocketUserID,
+ size: Option,
+) -> Result {
+ // Verify existence of user
+ User::get_by_login(&mut *db, user_id.0.as_ref())
+ .await?
+ .ok_or_else(|| Error::not_found(user_id.0.to_string()))?;
+
+ // Generate avatar
+ let avatar = task::spawn_blocking(move || {
+ let mut avatar = identicon_rs::Identicon::new(user_id.0);
+
+ // Set optional size
+ if let Some(size) = size {
+ avatar.set_scale(size)?;
+ }
+
+ avatar.export_png_data()
+ })
+ .await?;
+
+ // HTTP response
+ avatar
+ .map(FileFromBytes::from)
+ .map_err(Error::internal_server_error)
+}
diff --git a/crates/ezidam/src/routes/root/home.rs b/crates/ezidam/src/routes/root/home.rs
new file mode 100644
index 0000000..6f29f5e
--- /dev/null
+++ b/crates/ezidam/src/routes/root/home.rs
@@ -0,0 +1,23 @@
+use super::content;
+use crate::routes::prelude::*;
+use rocket::get;
+
+#[get("/")]
+pub async fn homepage(admin: JwtAdmin) -> Page {
+ Page::Homepage(content::Homepage { user: admin.0 })
+}
+
+#[get("/", rank = 2)]
+pub async fn homepage_user(user: JwtUser) -> Page {
+ Page::Homepage(content::Homepage { user: user.0 })
+}
+
+#[get("/", rank = 3)]
+pub async fn redirect_to_setup(_setup: NeedSetup) -> Redirect {
+ Redirect::to(uri!(crate::routes::setup::setup))
+}
+
+#[get("/", rank = 4)]
+pub async fn homepage_redirect() -> Redirect {
+ Redirect::to(uri!(crate::routes::oauth::authorize::authorize_ezidam))
+}
diff --git a/crates/ezidam/src/routes/root/logo.rs b/crates/ezidam/src/routes/root/logo.rs
new file mode 100644
index 0000000..d7f8b30
--- /dev/null
+++ b/crates/ezidam/src/routes/root/logo.rs
@@ -0,0 +1,36 @@
+use crate::routes::prelude::*;
+use rocket::get;
+use settings::Settings;
+
+#[get("/logo")]
+pub async fn get_logo(mut db: Connection) -> Result {
+ // Get settings
+ let settings = Settings::get(&mut *db).await?;
+
+ // HTTP response
+ Ok(FileFromBytes::from(settings.business_logo()))
+}
+
+#[cfg(test)]
+mod test {
+ use crate::tests::*;
+
+ #[test]
+ fn logo() {
+ // Setup http server
+ let client = setup_rocket_testing();
+
+ // Make request
+ let response = client.get(uri!(super::logo)).dispatch();
+ assert_eq!(response.status(), Status::Ok);
+
+ // Assert size of logo
+ let logo_length = response.into_bytes().expect("bytes containing logo").len();
+ use settings::DEFAULT_BUSINESS_LOGO;
+ assert_eq!(
+ logo_length,
+ DEFAULT_BUSINESS_LOGO.len(),
+ "Invalid logo size in bytes, value was `{logo_length}`",
+ );
+ }
+}
diff --git a/crates/ezidam/src/routes/root/logout.rs b/crates/ezidam/src/routes/root/logout.rs
new file mode 100644
index 0000000..3c004dc
--- /dev/null
+++ b/crates/ezidam/src/routes/root/logout.rs
@@ -0,0 +1,49 @@
+use crate::routes::prelude::*;
+use crate::tokens::{JWT_COOKIE_NAME, REFRESH_TOKEN_COOKIE_NAME};
+use rocket::http::{Cookie, CookieJar};
+use rocket::post;
+
+#[post("/logout")]
+pub async fn request_logout(
+ mut db: Connection,
+ refresh_token: RefreshToken,
+ cookie_jar: &CookieJar<'_>,
+) -> Result {
+ let mut transaction = db.begin().await?;
+
+ let refresh_token = refresh_tokens::RefreshToken::get_one(&mut transaction, &refresh_token.0)
+ .await?
+ .ok_or_else(|| Error::not_found("Unknown refresh token"))?;
+
+ // Delete cookies
+ cookie_jar.remove(Cookie::named(JWT_COOKIE_NAME));
+ cookie_jar.remove(Cookie::named(REFRESH_TOKEN_COOKIE_NAME));
+
+ // If refresh token has already been used
+ if refresh_token.has_been_used() {
+ // Revoke all refresh tokens for user
+ refresh_tokens::RefreshToken::revoke_all_for_user(&mut transaction, refresh_token.user())
+ .await?;
+
+ transaction.commit().await?;
+
+ return Err(Error::forbidden("This refresh token has already been used"));
+ }
+
+ // If token has been revoked
+ if refresh_token.is_revoked() {
+ return Err(Error::forbidden("This refresh token has been revoked"));
+ }
+
+ // If token has expired
+ if refresh_token.has_expired() {
+ return Err(Error::forbidden("This refresh token has expired"));
+ }
+
+ // Revoke token
+ refresh_token.revoke(&mut transaction).await?;
+
+ transaction.commit().await?;
+
+ Ok(Redirect::to(uri!(super::homepage)))
+}
diff --git a/crates/ezidam/src/routes/setup.rs b/crates/ezidam/src/routes/setup.rs
index 90094fa..8f473a5 100644
--- a/crates/ezidam/src/routes/setup.rs
+++ b/crates/ezidam/src/routes/setup.rs
@@ -13,7 +13,7 @@ pub fn routes() -> Vec {
#[get("/setup")]
async fn setup_completed(_setup: CompletedSetup) -> Redirect {
- Redirect::to(uri!(super::root::homepage))
+ Redirect::to(uri!(super::root::home::homepage))
}
#[get("/setup", rank = 2)]
@@ -100,7 +100,9 @@ async fn create_first_account(
transaction.commit().await?;
// Redirect to home
- Ok(Either::Left(Redirect::to(uri!(super::root::homepage))))
+ Ok(Either::Left(Redirect::to(uri!(
+ super::root::home::homepage
+ ))))
}
#[cfg(test)]