aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjanost <[email protected]>2020-11-30 23:12:56 +0100
committerjanost <[email protected]>2020-11-30 23:12:56 +0100
commit043aa27aa36f3918ad273eb67068cc0dc925dfb4 (patch)
treeb527f59825e7ad311edb49882f6cf643e3327d3d
parent9824d94a1cc039d1e0ac62301abf0b6fbb148709 (diff)
downloadvaultwarden-043aa27aa36f3918ad273eb67068cc0dc925dfb4.tar.gz
vaultwarden-043aa27aa36f3918ad273eb67068cc0dc925dfb4.zip
Implement admin ability to enable/disable users
-rw-r--r--migrations/mysql/2020-11-30-224000_add_user_enabled/down.sql0
-rw-r--r--migrations/mysql/2020-11-30-224000_add_user_enabled/up.sql1
-rw-r--r--migrations/postgresql/2020-11-30-224000_add_user_enabled/down.sql0
-rw-r--r--migrations/postgresql/2020-11-30-224000_add_user_enabled/up.sql1
-rw-r--r--migrations/sqlite/2020-11-30-224000_add_user_enabled/down.sql0
-rw-r--r--migrations/sqlite/2020-11-30-224000_add_user_enabled/up.sql1
-rw-r--r--src/api/admin.rs21
-rw-r--r--src/api/identity.rs8
-rw-r--r--src/db/models/user.rs2
-rw-r--r--src/db/schemas/mysql/schema.rs1
-rw-r--r--src/db/schemas/postgresql/schema.rs1
-rw-r--r--src/db/schemas/sqlite/schema.rs1
-rw-r--r--src/static/templates/admin/users.hbs26
13 files changed, 63 insertions, 0 deletions
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 00000000..e69de29b
--- /dev/null
+++ b/migrations/mysql/2020-11-30-224000_add_user_enabled/down.sql
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 00000000..508cf101
--- /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 00000000..e69de29b
--- /dev/null
+++ b/migrations/postgresql/2020-11-30-224000_add_user_enabled/down.sql
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 00000000..1f13c203
--- /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 00000000..e69de29b
--- /dev/null
+++ b/migrations/sqlite/2020-11-30-224000_add_user_enabled/down.sql
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 00000000..508cf101
--- /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 415311e7..ee19ec20 100644
--- a/src/api/admin.rs
+++ b/src/api/admin.rs
@@ -36,6 +36,8 @@ pub fn routes() -> Vec<Route> {
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<Html<String>> {
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/<uuid>/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/<uuid>/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/<uuid>/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 46a70405..dcfe607a 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 32c3cecc..63348074 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<NaiveDateTime>,
@@ -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 a353fa5b..cc91a730 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<Datetime>,
diff --git a/src/db/schemas/postgresql/schema.rs b/src/db/schemas/postgresql/schema.rs
index fcacb3ec..69571e8e 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<Timestamp>,
diff --git a/src/db/schemas/sqlite/schema.rs b/src/db/schemas/sqlite/schema.rs
index fcacb3ec..69571e8e 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<Timestamp>,
diff --git a/src/static/templates/admin/users.hbs b/src/static/templates/admin/users.hbs
index c99d9283..fe6ee817 100644
--- a/src/static/templates/admin/users.hbs
+++ b/src/static/templates/admin/users.hbs
@@ -22,6 +22,9 @@
<strong>{{Name}}</strong>
<span class="d-block">{{Email}}</span>
<span class="d-block">
+ {{#unless user_enabled}}
+ <span class="badge badge-danger mr-2" title="User is disabled">Disabled</span>
+ {{/unless}}
{{#if TwoFactorEnabled}}
<span class="badge badge-success mr-2" title="2FA is enabled">2FA</span>
{{/if}}
@@ -54,6 +57,11 @@
{{/if}}
<a class="d-block" href="#" onclick='deauthUser({{jsesc Id}})'>Deauthorize sessions</a>
<a class="d-block" href="#" onclick='deleteUser({{jsesc Id}}, {{jsesc Email}})'>Delete User</a>
+ {{#if user_enabled}}
+ <a class="d-block" href="#" onclick='disableUser({{jsesc Id}}, {{jsesc Email}})'>Disable User</a>
+ {{else}}
+ <a class="d-block" href="#" onclick='enableUser({{jsesc Id}}, {{jsesc Email}})'>Enable User</a>
+ {{/if}}
</td>
</tr>
{{/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",