diff --git a/migrations/mysql/2020-11-30-224000_add_user_enabled/down.sql b/migrations/mysql/2020-11-30-224000_add_user_enabled/down.sql new file mode 100644 index 0000000..e69de29 diff --git a/migrations/mysql/2020-11-30-224000_add_user_enabled/up.sql b/migrations/mysql/2020-11-30-224000_add_user_enabled/up.sql new file mode 100644 index 0000000..508cf10 --- /dev/null +++ b/migrations/mysql/2020-11-30-224000_add_user_enabled/up.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT 1; diff --git a/migrations/postgresql/2020-11-30-224000_add_user_enabled/down.sql b/migrations/postgresql/2020-11-30-224000_add_user_enabled/down.sql new file mode 100644 index 0000000..e69de29 diff --git a/migrations/postgresql/2020-11-30-224000_add_user_enabled/up.sql b/migrations/postgresql/2020-11-30-224000_add_user_enabled/up.sql new file mode 100644 index 0000000..1f13c20 --- /dev/null +++ b/migrations/postgresql/2020-11-30-224000_add_user_enabled/up.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT true; diff --git a/migrations/sqlite/2020-11-30-224000_add_user_enabled/down.sql b/migrations/sqlite/2020-11-30-224000_add_user_enabled/down.sql new file mode 100644 index 0000000..e69de29 diff --git a/migrations/sqlite/2020-11-30-224000_add_user_enabled/up.sql b/migrations/sqlite/2020-11-30-224000_add_user_enabled/up.sql new file mode 100644 index 0000000..508cf10 --- /dev/null +++ b/migrations/sqlite/2020-11-30-224000_add_user_enabled/up.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT 1; diff --git a/src/api/admin.rs b/src/api/admin.rs index 415311e..ee19ec2 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -36,6 +36,8 @@ pub fn routes() -> Vec { logout, delete_user, deauth_user, + disable_user, + enable_user, remove_2fa, update_revision_users, post_config, @@ -297,6 +299,7 @@ fn users_overview(_token: AdminToken, conn: DbConn) -> ApiResult> { usr["cipher_count"] = json!(Cipher::count_owned_by_user(&u.uuid, &conn)); usr["attachment_count"] = json!(Attachment::count_by_user(&u.uuid, &conn)); usr["attachment_size"] = json!(get_display_size(Attachment::size_by_user(&u.uuid, &conn) as i32)); + usr["user_enabled"] = json!(u.enabled); usr }).collect(); @@ -319,6 +322,24 @@ fn deauth_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult { user.save(&conn) } +#[post("/users//disable")] +fn disable_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult { + let mut user = User::find_by_uuid(&uuid, &conn).map_res("User doesn't exist")?; + Device::delete_all_by_user(&user.uuid, &conn)?; + user.reset_security_stamp(); + user.enabled = false; + + user.save(&conn) +} + +#[post("/users//enable")] +fn enable_user(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult { + let mut user = User::find_by_uuid(&uuid, &conn).map_res("User doesn't exist")?; + user.enabled = true; + + user.save(&conn) +} + #[post("/users//remove-2fa")] fn remove_2fa(uuid: String, _token: AdminToken, conn: DbConn) -> EmptyResult { let mut user = User::find_by_uuid(&uuid, &conn).map_res("User doesn't exist")?; diff --git a/src/api/identity.rs b/src/api/identity.rs index 46a7040..dcfe607 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -102,6 +102,14 @@ fn _password_login(data: ConnectData, conn: DbConn, ip: &ClientIp) -> JsonResult ) } + // Check if the user is disabled + if !user.enabled { + err!( + "This user has been disabled", + format!("IP: {}. Username: {}.", ip.ip, username) + ) + } + let now = Local::now(); if user.verified_at.is_none() && CONFIG.mail_enabled() && CONFIG.signups_verify() { diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 32c3cec..6334807 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -11,6 +11,7 @@ db_object! { #[primary_key(uuid)] pub struct User { pub uuid: String, + pub enabled: bool, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, pub verified_at: Option, @@ -70,6 +71,7 @@ impl User { Self { uuid: crate::util::get_uuid(), + enabled: true, created_at: now, updated_at: now, verified_at: None, diff --git a/src/db/schemas/mysql/schema.rs b/src/db/schemas/mysql/schema.rs index a353fa5..cc91a73 100644 --- a/src/db/schemas/mysql/schema.rs +++ b/src/db/schemas/mysql/schema.rs @@ -116,6 +116,7 @@ table! { table! { users (uuid) { uuid -> Text, + enabled -> Bool, created_at -> Datetime, updated_at -> Datetime, verified_at -> Nullable, diff --git a/src/db/schemas/postgresql/schema.rs b/src/db/schemas/postgresql/schema.rs index fcacb3e..69571e8 100644 --- a/src/db/schemas/postgresql/schema.rs +++ b/src/db/schemas/postgresql/schema.rs @@ -116,6 +116,7 @@ table! { table! { users (uuid) { uuid -> Text, + enabled -> Bool, created_at -> Timestamp, updated_at -> Timestamp, verified_at -> Nullable, diff --git a/src/db/schemas/sqlite/schema.rs b/src/db/schemas/sqlite/schema.rs index fcacb3e..69571e8 100644 --- a/src/db/schemas/sqlite/schema.rs +++ b/src/db/schemas/sqlite/schema.rs @@ -116,6 +116,7 @@ table! { table! { users (uuid) { uuid -> Text, + enabled -> Bool, created_at -> Timestamp, updated_at -> Timestamp, verified_at -> Nullable, diff --git a/src/static/templates/admin/users.hbs b/src/static/templates/admin/users.hbs index c99d928..fe6ee81 100644 --- a/src/static/templates/admin/users.hbs +++ b/src/static/templates/admin/users.hbs @@ -22,6 +22,9 @@ {{Name}} {{Email}} + {{#unless user_enabled}} + Disabled + {{/unless}} {{#if TwoFactorEnabled}} 2FA {{/if}} @@ -54,6 +57,11 @@ {{/if}} Deauthorize sessions Delete User + {{#if user_enabled}} + Disable User + {{else}} + Enable User + {{/if}} {{/each}} @@ -113,6 +121,24 @@ "Error deauthorizing sessions"); return false; } + function disableUser(id, mail) { + var confirmed = confirm("Are you sure you want to disable user '" + mail + "'? This will also deauthorize their sessions.") + if (confirmed) { + _post("{{urlpath}}/admin/users/" + id + "/disable", + "User disabled successfully", + "Error disabling user"); + } + return false; + } + function enableUser(id, mail) { + var confirmed = confirm("Are you sure you want to enable user '" + mail + "'?") + if (confirmed) { + _post("{{urlpath}}/admin/users/" + id + "/enable", + "User enabled successfully", + "Error enabling user"); + } + return false; + } function updateRevisions() { _post("{{urlpath}}/admin/users/update_revision", "Success, clients will sync next time they connect",