Browse Source

Merge cc6866fa71 into 07569a06da

pull/6491/merge
KyattsuNoTsume 2 days ago
committed by GitHub
parent
commit
713e91ee7e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 76
      src/api/admin.rs
  2. 11
      src/db/models/user.rs

76
src/api/admin.rs

@ -296,8 +296,8 @@ struct InviteData {
email: String, email: String,
} }
async fn get_user_or_404(user_id: &UserId, conn: &DbConn) -> ApiResult<User> { async fn get_user_or_404(user_id: &UserId, conn: &DbConn) -> ApiResult<(User, Option<SsoUser>)> {
if let Some(user) = User::find_by_uuid(user_id, conn).await { if let Some(user) = SsoUser::find_by_uuid(user_id, conn).await {
Ok(user) Ok(user)
} else { } else {
err_code!("User doesn't exist", Status::NotFound.code); err_code!("User doesn't exist", Status::NotFound.code);
@ -347,36 +347,16 @@ fn logout(cookies: &CookieJar<'_>) -> Redirect {
Redirect::to(admin_path()) Redirect::to(admin_path())
} }
#[get("/users")] async fn get_users_property(users: Vec<(User, Option<SsoUser>)>, conn: &DbConn) -> Vec<Value> {
async fn get_users_json(_token: AdminToken, conn: DbConn) -> Json<Value> {
let users = User::get_all(&conn).await;
let mut users_json = Vec::with_capacity(users.len());
for (u, _) in users {
let mut usr = u.to_json(&conn).await;
usr["userEnabled"] = json!(u.enabled);
usr["createdAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT));
usr["lastActive"] = match u.last_active(&conn).await {
Some(dt) => json!(format_naive_datetime_local(&dt, DT_FMT)),
None => json!(None::<String>),
};
users_json.push(usr);
}
Json(Value::Array(users_json))
}
#[get("/users/overview")]
async fn users_overview(_token: AdminToken, conn: DbConn) -> ApiResult<Html<String>> {
let users = User::get_all(&conn).await;
let mut users_json = Vec::with_capacity(users.len()); let mut users_json = Vec::with_capacity(users.len());
for (u, sso_u) in users { for (u, sso_u) in users {
let mut usr = u.to_json(&conn).await; let mut usr = u.to_json(conn).await;
usr["cipher_count"] = json!(Cipher::count_owned_by_user(&u.uuid, &conn).await); usr["cipher_count"] = json!(Cipher::count_owned_by_user(&u.uuid, conn).await);
usr["attachment_count"] = json!(Attachment::count_by_user(&u.uuid, &conn).await); usr["attachment_count"] = json!(Attachment::count_by_user(&u.uuid, conn).await);
usr["attachment_size"] = json!(get_display_size(Attachment::size_by_user(&u.uuid, &conn).await)); usr["attachment_size"] = json!(get_display_size(Attachment::size_by_user(&u.uuid, conn).await));
usr["user_enabled"] = json!(u.enabled); usr["user_enabled"] = json!(u.enabled);
usr["created_at"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT)); usr["created_at"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT));
usr["last_active"] = match u.last_active(&conn).await { usr["last_active"] = match u.last_active(conn).await {
Some(dt) => json!(format_naive_datetime_local(&dt, DT_FMT)), Some(dt) => json!(format_naive_datetime_local(&dt, DT_FMT)),
None => json!("Never"), None => json!("Never"),
}; };
@ -385,18 +365,29 @@ async fn users_overview(_token: AdminToken, conn: DbConn) -> ApiResult<Html<Stri
users_json.push(usr); users_json.push(usr);
} }
users_json
}
#[get("/users")]
async fn get_users_json(_token: AdminToken, conn: DbConn) -> Json<Value> {
let users = User::get_all(&conn).await;
let users_json = get_users_property(users, &conn).await;
Json(Value::Array(users_json))
}
#[get("/users/overview")]
async fn users_overview(_token: AdminToken, conn: DbConn) -> ApiResult<Html<String>> {
let users = User::get_all(&conn).await;
let users_json = get_users_property(users, &conn).await;
let text = AdminTemplateData::new("admin/users", json!(users_json)).render()?; let text = AdminTemplateData::new("admin/users", json!(users_json)).render()?;
Ok(Html(text)) Ok(Html(text))
} }
#[get("/users/by-mail/<mail>")] #[get("/users/by-mail/<mail>")]
async fn get_user_by_mail_json(mail: &str, _token: AdminToken, conn: DbConn) -> JsonResult { async fn get_user_by_mail_json(mail: &str, _token: AdminToken, conn: DbConn) -> JsonResult {
if let Some(u) = User::find_by_mail(mail, &conn).await { if let Some((u, sso)) = SsoUser::find_by_mail(mail, &conn).await {
let mut usr = u.to_json(&conn).await; let user_json = get_users_property(vec![(u, sso)], &conn).await[0].clone();
usr["userEnabled"] = json!(u.enabled); Ok(Json(user_json))
usr["createdAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT));
Ok(Json(usr))
} else { } else {
err_code!("User doesn't exist", Status::NotFound.code); err_code!("User doesn't exist", Status::NotFound.code);
} }
@ -404,16 +395,15 @@ async fn get_user_by_mail_json(mail: &str, _token: AdminToken, conn: DbConn) ->
#[get("/users/<user_id>")] #[get("/users/<user_id>")]
async fn get_user_json(user_id: UserId, _token: AdminToken, conn: DbConn) -> JsonResult { async fn get_user_json(user_id: UserId, _token: AdminToken, conn: DbConn) -> JsonResult {
let u = get_user_or_404(&user_id, &conn).await?; let u_sso = get_user_or_404(&user_id, &conn).await?;
let mut usr = u.to_json(&conn).await; let user_json = get_users_property(vec![u_sso], &conn).await[0].clone();
usr["userEnabled"] = json!(u.enabled);
usr["createdAt"] = json!(format_naive_datetime_local(&u.created_at, DT_FMT)); Ok(Json(user_json))
Ok(Json(usr))
} }
#[post("/users/<user_id>/delete", format = "application/json")] #[post("/users/<user_id>/delete", format = "application/json")]
async fn delete_user(user_id: UserId, token: AdminToken, conn: DbConn) -> EmptyResult { async fn delete_user(user_id: UserId, token: AdminToken, conn: DbConn) -> EmptyResult {
let user = get_user_or_404(&user_id, &conn).await?; let (user, _) = get_user_or_404(&user_id, &conn).await?;
// Get the membership records before deleting the actual user // Get the membership records before deleting the actual user
let memberships = Membership::find_any_state_by_user(&user_id, &conn).await; let memberships = Membership::find_any_state_by_user(&user_id, &conn).await;
@ -458,7 +448,7 @@ async fn delete_sso_user(user_id: UserId, token: AdminToken, conn: DbConn) -> Em
#[post("/users/<user_id>/deauth", format = "application/json")] #[post("/users/<user_id>/deauth", format = "application/json")]
async fn deauth_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Notify<'_>) -> EmptyResult { async fn deauth_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &conn).await?; let (mut user, _) = get_user_or_404(&user_id, &conn).await?;
nt.send_logout(&user, None, &conn).await; nt.send_logout(&user, None, &conn).await;
@ -479,7 +469,7 @@ async fn deauth_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Noti
#[post("/users/<user_id>/disable", format = "application/json")] #[post("/users/<user_id>/disable", format = "application/json")]
async fn disable_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Notify<'_>) -> EmptyResult { async fn disable_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Notify<'_>) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &conn).await?; let (mut user, _) = get_user_or_404(&user_id, &conn).await?;
Device::delete_all_by_user(&user.uuid, &conn).await?; Device::delete_all_by_user(&user.uuid, &conn).await?;
user.reset_security_stamp(); user.reset_security_stamp();
user.enabled = false; user.enabled = false;
@ -493,7 +483,7 @@ async fn disable_user(user_id: UserId, _token: AdminToken, conn: DbConn, nt: Not
#[post("/users/<user_id>/enable", format = "application/json")] #[post("/users/<user_id>/enable", format = "application/json")]
async fn enable_user(user_id: UserId, _token: AdminToken, conn: DbConn) -> EmptyResult { async fn enable_user(user_id: UserId, _token: AdminToken, conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &conn).await?; let (mut user, _) = get_user_or_404(&user_id, &conn).await?;
user.enabled = true; user.enabled = true;
user.save(&conn).await user.save(&conn).await
@ -501,7 +491,7 @@ async fn enable_user(user_id: UserId, _token: AdminToken, conn: DbConn) -> Empty
#[post("/users/<user_id>/remove-2fa", format = "application/json")] #[post("/users/<user_id>/remove-2fa", format = "application/json")]
async fn remove_2fa(user_id: UserId, token: AdminToken, conn: DbConn) -> EmptyResult { async fn remove_2fa(user_id: UserId, token: AdminToken, conn: DbConn) -> EmptyResult {
let mut user = get_user_or_404(&user_id, &conn).await?; let (mut user, _) = get_user_or_404(&user_id, &conn).await?;
TwoFactor::delete_all_by_user(&user.uuid, &conn).await?; TwoFactor::delete_all_by_user(&user.uuid, &conn).await?;
two_factor::enforce_2fa_policy(&user, &ACTING_ADMIN_USER.into(), 14, &token.ip.ip, &conn).await?; two_factor::enforce_2fa_policy(&user, &ACTING_ADMIN_USER.into(), 14, &token.ip.ip, &conn).await?;
user.totp_recover = None; user.totp_recover = None;

11
src/db/models/user.rs

@ -527,6 +527,17 @@ impl SsoUser {
}} }}
} }
pub async fn find_by_uuid(uuid: &UserId, conn: &DbConn) -> Option<(User, Option<Self>)> {
db_run! { conn: {
users::table
.left_join(sso_users::table)
.select(<(User, Option<Self>)>::as_select())
.filter(users::uuid.eq(uuid))
.first::<(User, Option<Self>)>(conn)
.ok()
}}
}
pub async fn delete(user_uuid: &UserId, conn: &DbConn) -> EmptyResult { pub async fn delete(user_uuid: &UserId, conn: &DbConn) -> EmptyResult {
db_run! { conn: { db_run! { conn: {
diesel::delete(sso_users::table.filter(sso_users::user_uuid.eq(user_uuid))) diesel::delete(sso_users::table.filter(sso_users::user_uuid.eq(user_uuid)))

Loading…
Cancel
Save