diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/routes/mod.rs | 3 | ||||
| -rw-r--r-- | server/src/routes/ui/admin/user.rs | 92 | 
2 files changed, 88 insertions, 7 deletions
| diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs index cb7d90f..48fdf96 100644 --- a/server/src/routes/mod.rs +++ b/server/src/routes/mod.rs @@ -25,7 +25,7 @@ use ui::{          log::r_admin_log,          r_admin_dashboard, r_admin_delete_cache, r_admin_import, r_admin_invite,          r_admin_remove_invite, -        user::{r_admin_remove_user, r_admin_user, r_admin_users}, +        user::{r_admin_remove_user, r_admin_user, r_admin_user_permission, r_admin_users},      },      assets::r_item_assets,      browser::r_all_items_filter, @@ -104,6 +104,7 @@ pub fn build_rocket(database: Database, federation: Federation) -> Rocket<Build>                  r_admin_user,                  r_admin_users,                  r_admin_remove_invite, +                r_admin_user_permission,                  r_admin_import,                  r_admin_delete_cache,                  r_admin_log, diff --git a/server/src/routes/ui/admin/user.rs b/server/src/routes/ui/admin/user.rs index 9868343..e61ec45 100644 --- a/server/src/routes/ui/admin/user.rs +++ b/server/src/routes/ui/admin/user.rs @@ -7,8 +7,9 @@ use crate::{      },      uri,  }; -use anyhow::anyhow; -use rocket::{form::Form, get, post, FromForm, State}; +use anyhow::{anyhow, Context}; +use jellycommon::user::{PermissionSet, UserPermission}; +use rocket::{form::Form, get, post, FromForm, FromFormField, State};  #[get("/admin/users")]  pub fn r_admin_users( @@ -48,18 +49,17 @@ pub fn r_admin_user<'a>(      database: &State<Database>,      name: &'a str,  ) -> MyResult<DynLayoutPage<'a>> { -    manage_single_user(database, None, name) +    manage_single_user(database, None, name.to_string())  }  fn manage_single_user<'a>(      database: &Database,      flash: Option<MyResult<String>>, -    name: &'a str, +    name: String,  ) -> MyResult<DynLayoutPage<'a>> { -    // TODO this doesnt scale, pagination!      let user = database          .user -        .get(&name.to_string())? +        .get(&name)?          .ok_or(anyhow!("user does not exist"))?;      let flash = flash.map(|f| f.map_err(|e| format!("{e:?}"))); @@ -73,15 +73,95 @@ fn manage_single_user<'a>(                  input[type="text", name="name", value=&user.name, hidden];                  input[type="submit", value="Remove(!)"];              } + +            h3 { "Permissions" } +            @PermissionDisplay { perms: &user.permissions } + +            form[method="POST", action=uri!(r_admin_user_permission())] { +                input[type="text", name="name", value=&user.name, hidden]; +                fieldset.perms { +                    legend { "Permission" } +                    @for p in UserPermission::ALL_ENUMERABLE { +                        label { +                            input[type="radio", name="permission", value=serde_json::to_string(p).unwrap()]; +                            @format!("{p}") +                        } br; +                    } +                } +                fieldset.perms { +                    legend { "Permission" } +                    label { input[type="radio", name="action", value="unset"]; "Unset" } +                    label { input[type="radio", name="action", value="grant"]; "Grant" } +                    label { input[type="radio", name="action", value="revoke"]; "Revoke" } +                } +                input[type="submit", value="Update"]; +            } +          },          ..Default::default()      })  } +markup::define! { +    PermissionDisplay<'a>(perms: &'a PermissionSet) { +        ul { @for (perm,grant) in &perms.0 { +            @if *grant { +                li[class="perm-grant"] { @format!("Allow {}", perm) } +            } else { +                li[class="perm-revoke"] { @format!("Deny {}", perm) } +            } +        }} +    } +} +  #[derive(FromForm)]  pub struct DeleteUser {      name: String,  } +#[derive(FromForm)] +pub struct UserPermissionForm { +    name: String, +    permission: String, +    action: GrantState, +} + +#[derive(FromFormField)] +pub enum GrantState { +    Grant, +    Revoke, +    Unset, +} + +#[post("/admin/update_user_permission", data = "<form>")] +pub fn r_admin_user_permission( +    session: AdminSession, +    database: &State<Database>, +    form: Form<UserPermissionForm>, +) -> MyResult<DynLayoutPage<'static>> { +    drop(session); +    let perm = serde_json::from_str::<UserPermission>(&form.permission) +        .context("parsing provided permission")?; + +    database +        .user +        .update_and_fetch(&form.name, |user| { +            user.map(|mut user| { +                match form.action { +                    GrantState::Grant => drop(user.permissions.0.insert(perm.clone(), true)), +                    GrantState::Revoke => drop(user.permissions.0.insert(perm.clone(), false)), +                    GrantState::Unset => drop(user.permissions.0.remove(&perm)), +                } +                user +            }) +        })? +        .ok_or(anyhow!("user did not exist"))?; + +    manage_single_user( +        database, +        Some(Ok("Permissions update".into())), +        form.name.clone(), +    ) +}  #[post("/admin/remove_user", data = "<form>")]  pub fn r_admin_remove_user( | 
