diff --git a/crates/ezidam/src/icons.rs b/crates/ezidam/src/icons.rs index 7834370..f331ef4 100644 --- a/crates/ezidam/src/icons.rs +++ b/crates/ezidam/src/icons.rs @@ -45,7 +45,10 @@ impl Icon { "users", Users, r#""#, "mail", Mail, r#""#, "password", Password, r#""#, - "2fa-large", TwoFaLarge, r#""# + "2fa-large", TwoFaLarge, r#""#, + "check", Check, r#""#, + "x", X, r#""#, + "progress", Progress, r#""# } } @@ -72,6 +75,9 @@ pub fn icons_to_templates(tera: &mut Tera) { Icon::Mail, Icon::Password, Icon::TwoFaLarge, + Icon::Check, + Icon::X, + Icon::Progress, ]; // For each icon, it will output: ("icons/name", "...") diff --git a/crates/ezidam/src/id.rs b/crates/ezidam/src/id.rs index 7fdab7c..15d3be3 100644 --- a/crates/ezidam/src/id.rs +++ b/crates/ezidam/src/id.rs @@ -6,7 +6,7 @@ use rocket::serde::{Deserialize, Serialize}; use std::fmt; use std::str::FromStr; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] #[serde(crate = "rocket::serde")] pub struct RocketUserID(pub UserID); @@ -18,7 +18,15 @@ impl<'r> FromParam<'r> for RocketUserID { } } -#[derive(Serialize, Deserialize)] +impl UriDisplay for RocketUserID { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + UriDisplay::fmt(&self.0 .0, f) + } +} + +impl_from_uri_param_identity!([Path] RocketUserID); + +#[derive(Serialize, Deserialize, Debug)] #[serde(crate = "rocket::serde")] pub struct RocketAppID(pub AppID); diff --git a/crates/ezidam/src/page.rs b/crates/ezidam/src/page.rs index 1fec61b..700d4e0 100644 --- a/crates/ezidam/src/page.rs +++ b/crates/ezidam/src/page.rs @@ -29,6 +29,7 @@ pub enum Page { ResetPassword(ResetPassword), UserSecurityTotp(UserSecurityTotp), AuthorizeTotp(AuthorizeTotp), + AdminUsersView(AdminUsersView), } impl Page { @@ -54,6 +55,7 @@ impl Page { Page::ResetPassword(_) => "pages/reset-password", Page::UserSecurityTotp(_) => "pages/settings/totp", Page::AuthorizeTotp(_) => "pages/oauth/totp", + Page::AdminUsersView(_) => "pages/admin/users/view", } } @@ -79,6 +81,7 @@ impl Page { Page::ResetPassword(_) => "Reset password", Page::UserSecurityTotp(_) => "Enable One-time password", Page::AuthorizeTotp(_) => "Verifying your account", + Page::AdminUsersView(_) => "User info", } } @@ -106,6 +109,7 @@ impl Page { Page::ResetPassword(_) => None, Page::UserSecurityTotp(_) => Some(UserMenu::Settings.into()), Page::AuthorizeTotp(_) => None, + Page::AdminUsersView(_) => Some(AdminMenu::Users.into()), } } @@ -131,6 +135,7 @@ impl Page { Page::ResetPassword(reset) => Box::new(reset), Page::UserSecurityTotp(totp) => Box::new(totp), Page::AuthorizeTotp(totp) => Box::new(totp), + Page::AdminUsersView(view) => Box::new(view), } } } diff --git a/crates/ezidam/src/routes/admin.rs b/crates/ezidam/src/routes/admin.rs index ffadb91..5fc13f8 100644 --- a/crates/ezidam/src/routes/admin.rs +++ b/crates/ezidam/src/routes/admin.rs @@ -24,6 +24,8 @@ pub fn routes() -> Vec { admin_apps_new_secret, admin_apps_archive, admin_users_list, + admin_users_view, + admin_users_archive, ] } @@ -86,4 +88,13 @@ pub mod content { pub user: JwtClaims, pub users: Vec, } + + #[derive(Serialize)] + #[serde(crate = "rocket::serde")] + #[derive(Clone)] + pub struct AdminUsersView { + pub user: JwtClaims, + pub jwt_duration: i64, + pub local: User, + } } diff --git a/crates/ezidam/src/routes/admin/users.rs b/crates/ezidam/src/routes/admin/users.rs index ee33b55..c1c79c9 100644 --- a/crates/ezidam/src/routes/admin/users.rs +++ b/crates/ezidam/src/routes/admin/users.rs @@ -1,5 +1,9 @@ use crate::routes::prelude::*; -use rocket::get; +use crate::tokens::JWT_DURATION_MINUTES; +use authorization_codes::AuthorizationCode; +use rocket::{get, post}; +use settings::Settings; +use users::totp_login_request::TotpLoginRequest; use users::User; #[get("/admin/users")] @@ -19,3 +23,116 @@ pub async fn admin_users_list( .map(|flash| Page::with_flash(page.clone(), flash)) .unwrap_or_else(|| page.into())) } + +#[get("/admin/users/")] +pub async fn admin_users_view( + admin_not_current: JwtAdminNotCurrent, + mut db: Connection, + id: RocketUserID, + flash: Option>, +) -> Result