summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathijs van Veluw <[email protected]>2024-10-18 20:37:32 +0200
committerGitHub <[email protected]>2024-10-18 20:37:32 +0200
commitae6ed0ece8bae45e8ff0e4a473004b54db348e25 (patch)
tree8388a3e2c1600559b277e4059aa284756cdb19f1
parentb7c254eb300fdf9e499e92e1384c74b4cc9e5297 (diff)
downloadvaultwarden-ae6ed0ece8bae45e8ff0e4a473004b54db348e25.tar.gz
vaultwarden-ae6ed0ece8bae45e8ff0e4a473004b54db348e25.zip
Fix collection management and match some json output (#5095)
- Fixed collection management to be usable from the Password Manager UI - Checked and brought in-to-sync with upstream several json responses - Fixed a small issue with the `fields` response when it was empty Signed-off-by: BlackDex <[email protected]>
-rw-r--r--src/api/core/ciphers.rs1
-rw-r--r--src/api/core/organizations.rs1
-rw-r--r--src/api/identity.rs13
-rw-r--r--src/db/models/cipher.rs2
-rw-r--r--src/db/models/collection.rs6
-rw-r--r--src/db/models/group.rs2
-rw-r--r--src/db/models/organization.rs6
-rw-r--r--src/db/models/user.rs12
8 files changed, 16 insertions, 27 deletions
diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs
index da718942..94bdc485 100644
--- a/src/api/core/ciphers.rs
+++ b/src/api/core/ciphers.rs
@@ -150,7 +150,6 @@ async fn sync(data: SyncData, headers: Headers, mut conn: DbConn) -> Json<Value>
"ciphers": ciphers_json,
"domains": domains_json,
"sends": sends_json,
- "unofficialServer": true,
"object": "sync"
}))
}
diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs
index ffbf0812..402e7617 100644
--- a/src/api/core/organizations.rs
+++ b/src/api/core/organizations.rs
@@ -363,6 +363,7 @@ async fn get_org_collections_details(org_id: &str, headers: ManagerHeadersLoose,
json_object["users"] = json!(users);
json_object["groups"] = json!(groups);
json_object["object"] = json!("collectionAccessDetails");
+ json_object["unmanaged"] = json!(false);
data.push(json_object)
}
diff --git a/src/api/identity.rs b/src/api/identity.rs
index 4244d68d..672f128c 100644
--- a/src/api/identity.rs
+++ b/src/api/identity.rs
@@ -120,16 +120,8 @@ async fn _refresh_login(data: ConnectData, conn: &mut DbConn) -> JsonResult {
"expires_in": expires_in,
"token_type": "Bearer",
"refresh_token": device.refresh_token,
- "Key": user.akey,
- "PrivateKey": user.private_key,
- "Kdf": user.client_kdf_type,
- "KdfIterations": user.client_kdf_iter,
- "KdfMemory": user.client_kdf_memory,
- "KdfParallelism": user.client_kdf_parallelism,
- "ResetMasterPassword": false, // TODO: according to official server seems something like: user.password_hash.is_empty(), but would need testing
"scope": scope,
- "unofficialServer": true,
});
Ok(Json(result))
@@ -342,7 +334,6 @@ async fn _password_login(
"MasterPasswordPolicy": master_password_policy,
"scope": scope,
- "unofficialServer": true,
"UserDecryptionOptions": {
"HasMasterPassword": !user.password_hash.is_empty(),
"Object": "userDecryptionOptions"
@@ -461,9 +452,8 @@ async fn _user_api_key_login(
"KdfIterations": user.client_kdf_iter,
"KdfMemory": user.client_kdf_memory,
"KdfParallelism": user.client_kdf_parallelism,
- "ResetMasterPassword": false, // TODO: Same as above
+ "ResetMasterPassword": false, // TODO: according to official server seems something like: user.password_hash.is_empty(), but would need testing
"scope": "api",
- "unofficialServer": true,
});
Ok(Json(result))
@@ -495,7 +485,6 @@ async fn _organization_api_key_login(data: ConnectData, conn: &mut DbConn, ip: &
"expires_in": 3600,
"token_type": "Bearer",
"scope": "api.organization",
- "unofficialServer": true,
})))
}
diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs
index 06aa69c5..fb2b5021 100644
--- a/src/db/models/cipher.rs
+++ b/src/db/models/cipher.rs
@@ -264,7 +264,7 @@ impl Cipher {
// NOTE: This was marked as *Backwards Compatibility Code*, but as of January 2021 this is still being used by upstream
// data_json should always contain the following keys with every atype
- data_json["fields"] = json!([fields_json]);
+ data_json["fields"] = json!(fields_json);
data_json["name"] = json!(self.name);
data_json["notes"] = json!(self.notes);
data_json["passwordHistory"] = Value::Array(password_history_json.clone());
diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs
index 7fb17c66..a26f22c7 100644
--- a/src/db/models/collection.rs
+++ b/src/db/models/collection.rs
@@ -81,8 +81,8 @@ impl Collection {
let (read_only, hide_passwords, can_manage) = if let Some(cipher_sync_data) = cipher_sync_data {
match cipher_sync_data.user_organizations.get(&self.org_uuid) {
// Only for Manager types Bitwarden returns true for the can_manage option
- // Owners and Admins always have false, but they can manage all collections anyway
- Some(uo) if uo.has_full_access() => (false, false, uo.atype == UserOrgType::Manager),
+ // Owners and Admins always have true
+ Some(uo) if uo.has_full_access() => (false, false, uo.atype >= UserOrgType::Manager),
Some(uo) => {
// Only let a manager manage collections when the have full read/write access
let is_manager = uo.atype == UserOrgType::Manager;
@@ -98,7 +98,7 @@ impl Collection {
}
} else {
match UserOrganization::find_confirmed_by_user_and_org(user_uuid, &self.org_uuid, conn).await {
- Some(ou) if ou.has_full_access() => (false, false, ou.atype == UserOrgType::Manager),
+ Some(ou) if ou.has_full_access() => (false, false, ou.atype >= UserOrgType::Manager),
Some(ou) => {
let is_manager = ou.atype == UserOrgType::Manager;
let read_only = !self.is_writable_by_user(user_uuid, conn).await;
diff --git a/src/db/models/group.rs b/src/db/models/group.rs
index 6e2db088..66ad338a 100644
--- a/src/db/models/group.rs
+++ b/src/db/models/group.rs
@@ -82,7 +82,7 @@ impl Group {
"id": entry.collections_uuid,
"readOnly": entry.read_only,
"hidePasswords": entry.hide_passwords,
- "manage": *user_org_type == UserOrgType::Manager && !entry.read_only && !entry.hide_passwords
+ "manage": *user_org_type >= UserOrgType::Admin || (*user_org_type == UserOrgType::Manager && !entry.read_only && !entry.hide_passwords)
})
})
.collect();
diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs
index e59c1b05..21c241bf 100644
--- a/src/db/models/organization.rs
+++ b/src/db/models/organization.rs
@@ -161,7 +161,6 @@ impl Organization {
"identifier": null, // not supported by us
"name": self.name,
"seats": null,
- "maxAutoscaleSeats": null,
"maxCollections": null,
"maxStorageGb": i16::MAX, // The value doesn't matter, we don't check server-side
"use2fa": true,
@@ -374,7 +373,6 @@ impl UserOrganization {
"identifier": null, // Not supported
"name": org.name,
"seats": null,
- "maxAutoscaleSeats": null,
"maxCollections": null,
"usersGetPremium": true,
"use2fa": true,
@@ -411,7 +409,7 @@ impl UserOrganization {
"familySponsorshipValidUntil": null,
"familySponsorshipToDelete": null,
"accessSecretsManager": false,
- "limitCollectionCreationDeletion": true,
+ "limitCollectionCreationDeletion": false, // This should be set to true only when we can handle roles like createNewCollections
"allowAdminAccessToAllCollectionItems": true,
"flexibleCollections": false,
@@ -477,7 +475,7 @@ impl UserOrganization {
.into_iter()
.filter_map(|c| {
let (read_only, hide_passwords, can_manage) = if self.has_full_access() {
- (false, false, self.atype == UserOrgType::Manager)
+ (false, false, self.atype >= UserOrgType::Manager)
} else if let Some(cu) = cu.get(&c.uuid) {
(
cu.read_only,
diff --git a/src/db/models/user.rs b/src/db/models/user.rs
index d91c91c1..94f42c84 100644
--- a/src/db/models/user.rs
+++ b/src/db/models/user.rs
@@ -1,3 +1,4 @@
+use crate::util::{format_date, get_uuid, retry};
use chrono::{NaiveDateTime, TimeDelta, Utc};
use serde_json::Value;
@@ -90,7 +91,7 @@ impl User {
let email = email.to_lowercase();
Self {
- uuid: crate::util::get_uuid(),
+ uuid: get_uuid(),
enabled: true,
created_at: now,
updated_at: now,
@@ -107,7 +108,7 @@ impl User {
salt: crypto::get_random_bytes::<64>().to_vec(),
password_iterations: CONFIG.password_iterations(),
- security_stamp: crate::util::get_uuid(),
+ security_stamp: get_uuid(),
stamp_exception: None,
password_hint: None,
@@ -188,7 +189,7 @@ impl User {
}
pub fn reset_security_stamp(&mut self) {
- self.security_stamp = crate::util::get_uuid();
+ self.security_stamp = get_uuid();
}
/// Set the stamp_exception to only allow a subsequent request matching a specific route using the current security-stamp.
@@ -259,6 +260,7 @@ impl User {
"forcePasswordReset": false,
"avatarColor": self.avatar_color,
"usesKeyConnector": false,
+ "creationDate": format_date(&self.created_at),
"object": "profile",
})
}
@@ -340,7 +342,7 @@ impl User {
let updated_at = Utc::now().naive_utc();
db_run! {conn: {
- crate::util::retry(|| {
+ retry(|| {
diesel::update(users::table)
.set(users::updated_at.eq(updated_at))
.execute(conn)
@@ -357,7 +359,7 @@ impl User {
async fn _update_revision(uuid: &str, date: &NaiveDateTime, conn: &mut DbConn) -> EmptyResult {
db_run! {conn: {
- crate::util::retry(|| {
+ retry(|| {
diesel::update(users::table.filter(users::uuid.eq(uuid)))
.set(users::updated_at.eq(date))
.execute(conn)