vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 4f7cc5e1908ec5bc20e474d7fb6e099a9f2cbaa9
parent 4de0bf37224e4abf9ff3b3cb2a7757a2e06f2395
Author: Daniel GarcĂ­a <dani-garcia@users.noreply.github.com>
Date:   Wed, 30 May 2018 17:32:08 +0200

Merge pull request #32 from mprasil/collection_users

Support listing and deleting users from collection
Diffstat:
Msrc/api/core/mod.rs | 1+
Msrc/api/core/organizations.rs | 61+++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/db/models/collection.rs | 28++++++++++++++++++++--------
Msrc/db/models/organization.rs | 16++++++++++++++++
4 files changed, 80 insertions(+), 26 deletions(-)

diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs @@ -68,6 +68,7 @@ pub fn routes() -> Vec<Route> { get_collection_users, post_organization, post_organization_collections, + post_organization_collection_delete_user, post_organization_collection_update, post_organization_collection_delete, post_collections_update, diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs @@ -192,6 +192,33 @@ fn post_organization_collection_update(org_id: String, col_id: String, headers: Ok(Json(collection.to_json())) } +#[post("/organizations/<org_id>/collections/<col_id>/delete-user/<org_user_id>")] +fn post_organization_collection_delete_user(org_id: String, col_id: String, org_user_id: String, headers: AdminHeaders, conn: DbConn) -> EmptyResult { + let collection = match Collection::find_by_uuid(&col_id, &conn) { + None => err!("Collection not found"), + Some(collection) => if collection.org_uuid == org_id { + collection + } else { + err!("Collection and Organization id do not match") + } + }; + + match UserOrganization::find_by_uuid(&org_user_id, &conn) { + None => err!("User not found in organization"), + Some(user_org) => { + match CollectionUser::find_by_collection_and_user(&collection.uuid, &user_org.user_uuid, &conn) { + None => err!("User not assigned to collection"), + Some(col_user) => { + match col_user.delete(&conn) { + Ok(()) => Ok(()), + Err(_) => err!("Failed removing user from collection") + } + } + } + } + } +} + #[derive(Deserialize, Debug)] #[allow(non_snake_case)] struct DeleteCollectionData { @@ -232,26 +259,21 @@ fn get_org_collection_detail(org_id: String, coll_id: String, headers: AdminHead #[get("/organizations/<org_id>/collections/<coll_id>/users")] fn get_collection_users(org_id: String, coll_id: String, headers: AdminHeaders, conn: DbConn) -> JsonResult { // Get org and collection, check that collection is from org + let collection = match Collection::find_by_uuid_and_org(&coll_id, &org_id, &conn) { + None => err!("Collection not found in Organization"), + Some(collection) => collection + }; // Get the users from collection - - /* - The elements from the data array to return have the following structure - - { - OrganizationUserId: <id> - AccessAll: true - Name: <user_name> - Email: <user_email> - Type: 0 - Status: 2 - ReadOnly: false - Object: collectionUser - } - */ + let user_list: Vec<Value> = CollectionUser::find_by_collection(&collection.uuid, &conn) + .iter().map(|col_user| { + UserOrganization::find_by_user_and_org(&col_user.user_uuid, &org_id, &conn) + .unwrap() + .to_json_collection_user_details(&col_user.read_only, &conn) + }).collect(); Ok(Json(json!({ - "Data": [], + "Data": user_list, "Object": "list" }))) } @@ -473,8 +495,11 @@ fn edit_user(org_id: String, user_id: String, data: Json<EditUserData>, headers: user_to_edit.type_ = new_type; // Delete all the odd collections - for c in Collection::find_by_organization_and_user_uuid(&org_id, &user_to_edit.user_uuid, &conn) { - CollectionUser::delete(&user_to_edit.user_uuid, &c.uuid, &conn); + for c in CollectionUser::find_by_organization_and_user_uuid(&org_id, &user_to_edit.user_uuid, &conn) { + match c.delete(&conn) { + Ok(()) => (), + Err(_) => err!("Failed deleting old collection assignment") + } } // If no accessAll, add the collections received diff --git a/src/db/models/collection.rs b/src/db/models/collection.rs @@ -188,14 +188,26 @@ impl CollectionUser { )).execute(&**conn).and(Ok(())) } - pub fn delete(user_uuid: &str, collection_uuid: &str, conn: &DbConn) -> bool { - match diesel::delete(users_collections::table - .filter(users_collections::user_uuid.eq(user_uuid)) - .filter(users_collections::collection_uuid.eq(collection_uuid))) - .execute(&**conn) { - Ok(1) => true, // One row deleted - _ => false, - } + pub fn delete(self, conn: &DbConn) -> QueryResult<()> { + diesel::delete(users_collections::table + .filter(users_collections::user_uuid.eq(&self.user_uuid)) + .filter(users_collections::collection_uuid.eq(&self.collection_uuid))) + .execute(&**conn).and(Ok(())) + } + + pub fn find_by_collection(collection_uuid: &str, conn: &DbConn) -> Vec<Self> { + users_collections::table + .filter(users_collections::collection_uuid.eq(collection_uuid)) + .select(users_collections::all_columns) + .load::<Self>(&**conn).expect("Error loading users_collections") + } + + pub fn find_by_collection_and_user(collection_uuid: &str, user_uuid: &str, conn: &DbConn) -> Option<Self> { + users_collections::table + .filter(users_collections::collection_uuid.eq(collection_uuid)) + .filter(users_collections::user_uuid.eq(user_uuid)) + .select(users_collections::all_columns) + .first::<Self>(&**conn).ok() } pub fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> QueryResult<()> { diff --git a/src/db/models/organization.rs b/src/db/models/organization.rs @@ -189,6 +189,22 @@ impl UserOrganization { }) } + pub fn to_json_collection_user_details(&self, read_only: &bool, conn: &DbConn) -> JsonValue { + use super::User; + let user = User::find_by_uuid(&self.user_uuid, conn).unwrap(); + + json!({ + "OrganizationUserId": self.uuid, + "AccessAll": self.access_all, + "Name": user.name, + "Email": user.email, + "Type": self.type_, + "Status": self.status, + "ReadOnly": read_only, + "Object": "collectionUser", + }) + } + pub fn to_json_details(&self, conn: &DbConn) -> JsonValue { let coll_uuids = if self.access_all { vec![] // If we have complete access, no need to fill the array