MFijak
2 years ago
17 changed files with 1188 additions and 19 deletions
@ -0,0 +1,3 @@ |
|||
DROP TABLE `groups`; |
|||
DROP TABLE groups_users; |
|||
DROP TABLE collections_groups; |
@ -0,0 +1,23 @@ |
|||
CREATE TABLE `groups` ( |
|||
uuid CHAR(36) NOT NULL PRIMARY KEY, |
|||
organizations_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), |
|||
name VARCHAR(100) NOT NULL, |
|||
access_all BOOLEAN NOT NULL, |
|||
external_id VARCHAR(300) NULL, |
|||
creation_date DATETIME NOT NULL, |
|||
revision_date DATETIME NOT NULL |
|||
); |
|||
|
|||
CREATE TABLE groups_users ( |
|||
groups_uuid CHAR(36) NOT NULL REFERENCES `groups` (uuid), |
|||
users_organizations_uuid VARCHAR(36) NOT NULL REFERENCES users_organizations (uuid), |
|||
UNIQUE (groups_uuid, users_organizations_uuid) |
|||
); |
|||
|
|||
CREATE TABLE collections_groups ( |
|||
collections_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), |
|||
groups_uuid CHAR(36) NOT NULL REFERENCES `groups` (uuid), |
|||
read_only BOOLEAN NOT NULL, |
|||
hide_passwords BOOLEAN NOT NULL, |
|||
UNIQUE (collections_uuid, groups_uuid) |
|||
); |
@ -0,0 +1,3 @@ |
|||
DROP TABLE groups; |
|||
DROP TABLE groups_users; |
|||
DROP TABLE collections_groups; |
@ -0,0 +1,23 @@ |
|||
CREATE TABLE groups ( |
|||
uuid CHAR(36) NOT NULL PRIMARY KEY, |
|||
organizations_uuid VARCHAR(40) NOT NULL REFERENCES organizations (uuid), |
|||
name VARCHAR(100) NOT NULL, |
|||
access_all BOOLEAN NOT NULL, |
|||
external_id VARCHAR(300) NULL, |
|||
creation_date TIMESTAMP NOT NULL, |
|||
revision_date TIMESTAMP NOT NULL |
|||
); |
|||
|
|||
CREATE TABLE groups_users ( |
|||
groups_uuid CHAR(36) NOT NULL REFERENCES groups (uuid), |
|||
users_organizations_uuid VARCHAR(36) NOT NULL REFERENCES users_organizations (uuid), |
|||
PRIMARY KEY (groups_uuid, users_organizations_uuid) |
|||
); |
|||
|
|||
CREATE TABLE collections_groups ( |
|||
collections_uuid VARCHAR(40) NOT NULL REFERENCES collections (uuid), |
|||
groups_uuid CHAR(36) NOT NULL REFERENCES groups (uuid), |
|||
read_only BOOLEAN NOT NULL, |
|||
hide_passwords BOOLEAN NOT NULL, |
|||
PRIMARY KEY (collections_uuid, groups_uuid) |
|||
); |
@ -0,0 +1,3 @@ |
|||
DROP TABLE groups; |
|||
DROP TABLE groups_users; |
|||
DROP TABLE collections_groups; |
@ -0,0 +1,23 @@ |
|||
CREATE TABLE groups ( |
|||
uuid TEXT NOT NULL PRIMARY KEY, |
|||
organizations_uuid TEXT NOT NULL REFERENCES organizations (uuid), |
|||
name TEXT NOT NULL, |
|||
access_all BOOLEAN NOT NULL, |
|||
external_id TEXT NULL, |
|||
creation_date TIMESTAMP NOT NULL, |
|||
revision_date TIMESTAMP NOT NULL |
|||
); |
|||
|
|||
CREATE TABLE groups_users ( |
|||
groups_uuid TEXT NOT NULL REFERENCES groups (uuid), |
|||
users_organizations_uuid TEXT NOT NULL REFERENCES users_organizations (uuid), |
|||
UNIQUE (groups_uuid, users_organizations_uuid) |
|||
); |
|||
|
|||
CREATE TABLE collections_groups ( |
|||
collections_uuid TEXT NOT NULL REFERENCES collections (uuid), |
|||
groups_uuid TEXT NOT NULL REFERENCES groups (uuid), |
|||
read_only BOOLEAN NOT NULL, |
|||
hide_passwords BOOLEAN NOT NULL, |
|||
UNIQUE (collections_uuid, groups_uuid) |
|||
); |
@ -0,0 +1,501 @@ |
|||
use chrono::{NaiveDateTime, Utc}; |
|||
use serde_json::Value; |
|||
|
|||
db_object! { |
|||
#[derive(Identifiable, Queryable, Insertable, AsChangeset)] |
|||
#[table_name = "groups"] |
|||
#[primary_key(uuid)] |
|||
pub struct Group { |
|||
pub uuid: String, |
|||
pub organizations_uuid: String, |
|||
pub name: String, |
|||
pub access_all: bool, |
|||
external_id: Option<String>, |
|||
pub creation_date: NaiveDateTime, |
|||
pub revision_date: NaiveDateTime, |
|||
} |
|||
|
|||
#[derive(Identifiable, Queryable, Insertable)] |
|||
#[table_name = "collections_groups"] |
|||
#[primary_key(collections_uuid, groups_uuid)] |
|||
pub struct CollectionGroup { |
|||
pub collections_uuid: String, |
|||
pub groups_uuid: String, |
|||
pub read_only: bool, |
|||
pub hide_passwords: bool, |
|||
} |
|||
|
|||
#[derive(Identifiable, Queryable, Insertable)] |
|||
#[table_name = "groups_users"] |
|||
#[primary_key(groups_uuid, users_organizations_uuid)] |
|||
pub struct GroupUser { |
|||
pub groups_uuid: String, |
|||
pub users_organizations_uuid: String |
|||
} |
|||
} |
|||
|
|||
/// Local methods
|
|||
impl Group { |
|||
pub fn new(organizations_uuid: String, name: String, access_all: bool, external_id: Option<String>) -> Self { |
|||
let now = Utc::now().naive_utc(); |
|||
|
|||
let mut new_model = Self { |
|||
uuid: crate::util::get_uuid(), |
|||
organizations_uuid, |
|||
name, |
|||
access_all, |
|||
external_id: None, |
|||
creation_date: now, |
|||
revision_date: now, |
|||
}; |
|||
|
|||
new_model.set_external_id(external_id); |
|||
|
|||
new_model |
|||
} |
|||
|
|||
pub fn to_json(&self) -> Value { |
|||
use crate::util::format_date; |
|||
|
|||
json!({ |
|||
"Id": self.uuid, |
|||
"OrganizationId": self.organizations_uuid, |
|||
"Name": self.name, |
|||
"AccessAll": self.access_all, |
|||
"ExternalId": self.external_id, |
|||
"CreationDate": format_date(&self.creation_date), |
|||
"RevisionDate": format_date(&self.revision_date) |
|||
}) |
|||
} |
|||
|
|||
pub fn set_external_id(&mut self, external_id: Option<String>) { |
|||
//Check if external id is empty. We don't want to have
|
|||
//empty strings in the database
|
|||
match external_id { |
|||
Some(external_id) => { |
|||
if external_id.is_empty() { |
|||
self.external_id = None; |
|||
} else { |
|||
self.external_id = Some(external_id) |
|||
} |
|||
} |
|||
None => self.external_id = None, |
|||
} |
|||
} |
|||
|
|||
pub fn get_external_id(&self) -> Option<String> { |
|||
self.external_id.clone() |
|||
} |
|||
} |
|||
|
|||
impl CollectionGroup { |
|||
pub fn new(collections_uuid: String, groups_uuid: String, read_only: bool, hide_passwords: bool) -> Self { |
|||
Self { |
|||
collections_uuid, |
|||
groups_uuid, |
|||
read_only, |
|||
hide_passwords, |
|||
} |
|||
} |
|||
} |
|||
|
|||
impl GroupUser { |
|||
pub fn new(groups_uuid: String, users_organizations_uuid: String) -> Self { |
|||
Self { |
|||
groups_uuid, |
|||
users_organizations_uuid, |
|||
} |
|||
} |
|||
} |
|||
|
|||
use crate::db::DbConn; |
|||
|
|||
use crate::api::EmptyResult; |
|||
use crate::error::MapResult; |
|||
|
|||
use super::{User, UserOrganization}; |
|||
|
|||
/// Database methods
|
|||
impl Group { |
|||
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult { |
|||
self.revision_date = Utc::now().naive_utc(); |
|||
|
|||
db_run! { conn: |
|||
sqlite, mysql { |
|||
match diesel::replace_into(groups::table) |
|||
.values(GroupDb::to_db(self)) |
|||
.execute(conn) |
|||
{ |
|||
Ok(_) => Ok(()), |
|||
// Record already exists and causes a Foreign Key Violation because replace_into() wants to delete the record first.
|
|||
Err(diesel::result::Error::DatabaseError(diesel::result::DatabaseErrorKind::ForeignKeyViolation, _)) => { |
|||
diesel::update(groups::table) |
|||
.filter(groups::uuid.eq(&self.uuid)) |
|||
.set(GroupDb::to_db(self)) |
|||
.execute(conn) |
|||
.map_res("Error saving group") |
|||
} |
|||
Err(e) => Err(e.into()), |
|||
}.map_res("Error saving group") |
|||
} |
|||
postgresql { |
|||
let value = GroupDb::to_db(self); |
|||
diesel::insert_into(groups::table) |
|||
.values(&value) |
|||
.on_conflict(groups::uuid) |
|||
.do_update() |
|||
.set(&value) |
|||
.execute(conn) |
|||
.map_res("Error saving group") |
|||
} |
|||
} |
|||
} |
|||
|
|||
pub async fn find_by_organization(organizations_uuid: &str, conn: &DbConn) -> Vec<Self> { |
|||
db_run! { conn: { |
|||
groups::table |
|||
.filter(groups::organizations_uuid.eq(organizations_uuid)) |
|||
.load::<GroupDb>(conn) |
|||
.expect("Error loading groups") |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
pub async fn find_by_uuid(uuid: &str, conn: &DbConn) -> Option<Self> { |
|||
db_run! { conn: { |
|||
groups::table |
|||
.filter(groups::uuid.eq(uuid)) |
|||
.first::<GroupDb>(conn) |
|||
.ok() |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
//Returns all organizations the user has full access to
|
|||
pub async fn gather_user_organizations_full_access(user_uuid: &str, conn: &DbConn) -> Vec<String> { |
|||
db_run! { conn: { |
|||
groups_users::table |
|||
.inner_join(users_organizations::table.on( |
|||
users_organizations::uuid.eq(groups_users::users_organizations_uuid) |
|||
)) |
|||
.inner_join(groups::table.on( |
|||
groups::uuid.eq(groups_users::groups_uuid) |
|||
)) |
|||
.filter(users_organizations::user_uuid.eq(user_uuid)) |
|||
.filter(groups::access_all.eq(true)) |
|||
.select(groups::organizations_uuid) |
|||
.distinct() |
|||
.load::<String>(conn) |
|||
.expect("Error loading organization group full access information for user") |
|||
}} |
|||
} |
|||
|
|||
pub async fn is_in_full_access_group(user_uuid: &str, org_uuid: &str, conn: &DbConn) -> bool { |
|||
db_run! { conn: { |
|||
groups::table |
|||
.inner_join(groups_users::table.on( |
|||
groups_users::groups_uuid.eq(groups::uuid) |
|||
)) |
|||
.inner_join(users_organizations::table.on( |
|||
users_organizations::uuid.eq(groups_users::users_organizations_uuid) |
|||
)) |
|||
.filter(users_organizations::user_uuid.eq(user_uuid)) |
|||
.filter(groups::organizations_uuid.eq(org_uuid)) |
|||
.filter(groups::access_all.eq(true)) |
|||
.select(groups::access_all) |
|||
.first::<bool>(conn) |
|||
.unwrap_or_default() |
|||
}} |
|||
} |
|||
|
|||
pub async fn delete(&self, conn: &DbConn) -> EmptyResult { |
|||
CollectionGroup::delete_all_by_group(&self.uuid, conn).await?; |
|||
GroupUser::delete_all_by_group(&self.uuid, conn).await?; |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(groups::table.filter(groups::uuid.eq(&self.uuid))) |
|||
.execute(conn) |
|||
.map_res("Error deleting group") |
|||
}} |
|||
} |
|||
|
|||
pub async fn update_revision(uuid: &str, conn: &DbConn) { |
|||
if let Err(e) = Self::_update_revision(uuid, &Utc::now().naive_utc(), conn).await { |
|||
warn!("Failed to update revision for {}: {:#?}", uuid, e); |
|||
} |
|||
} |
|||
|
|||
async fn _update_revision(uuid: &str, date: &NaiveDateTime, conn: &DbConn) -> EmptyResult { |
|||
db_run! {conn: { |
|||
crate::util::retry(|| { |
|||
diesel::update(groups::table.filter(groups::uuid.eq(uuid))) |
|||
.set(groups::revision_date.eq(date)) |
|||
.execute(conn) |
|||
}, 10) |
|||
.map_res("Error updating group revision") |
|||
}} |
|||
} |
|||
} |
|||
|
|||
impl CollectionGroup { |
|||
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult { |
|||
let group_users = GroupUser::find_by_group(&self.groups_uuid, conn).await; |
|||
for group_user in group_users { |
|||
group_user.update_user_revision(conn).await; |
|||
} |
|||
|
|||
db_run! { conn: |
|||
sqlite, mysql { |
|||
match diesel::replace_into(collections_groups::table) |
|||
.values(( |
|||
collections_groups::collections_uuid.eq(&self.collections_uuid), |
|||
collections_groups::groups_uuid.eq(&self.groups_uuid), |
|||
collections_groups::read_only.eq(&self.read_only), |
|||
collections_groups::hide_passwords.eq(&self.hide_passwords), |
|||
)) |
|||
.execute(conn) |
|||
{ |
|||
Ok(_) => Ok(()), |
|||
// Record already exists and causes a Foreign Key Violation because replace_into() wants to delete the record first.
|
|||
Err(diesel::result::Error::DatabaseError(diesel::result::DatabaseErrorKind::ForeignKeyViolation, _)) => { |
|||
diesel::update(collections_groups::table) |
|||
.filter(collections_groups::collections_uuid.eq(&self.collections_uuid)) |
|||
.filter(collections_groups::groups_uuid.eq(&self.groups_uuid)) |
|||
.set(( |
|||
collections_groups::collections_uuid.eq(&self.collections_uuid), |
|||
collections_groups::groups_uuid.eq(&self.groups_uuid), |
|||
collections_groups::read_only.eq(&self.read_only), |
|||
collections_groups::hide_passwords.eq(&self.hide_passwords), |
|||
)) |
|||
.execute(conn) |
|||
.map_res("Error adding group to collection") |
|||
} |
|||
Err(e) => Err(e.into()), |
|||
}.map_res("Error adding group to collection") |
|||
} |
|||
postgresql { |
|||
diesel::insert_into(collections_groups::table) |
|||
.values(( |
|||
collections_groups::collections_uuid.eq(&self.collections_uuid), |
|||
collections_groups::groups_uuid.eq(&self.groups_uuid), |
|||
collections_groups::read_only.eq(self.read_only), |
|||
collections_groups::hide_passwords.eq(self.hide_passwords), |
|||
)) |
|||
.on_conflict((collections_groups::collections_uuid, collections_groups::groups_uuid)) |
|||
.do_update() |
|||
.set(( |
|||
collections_groups::read_only.eq(self.read_only), |
|||
collections_groups::hide_passwords.eq(self.hide_passwords), |
|||
)) |
|||
.execute(conn) |
|||
.map_res("Error adding group to collection") |
|||
} |
|||
} |
|||
} |
|||
|
|||
pub async fn find_by_group(group_uuid: &str, conn: &DbConn) -> Vec<Self> { |
|||
db_run! { conn: { |
|||
collections_groups::table |
|||
.filter(collections_groups::groups_uuid.eq(group_uuid)) |
|||
.load::<CollectionGroupDb>(conn) |
|||
.expect("Error loading collection groups") |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
pub async fn find_by_user(user_uuid: &str, conn: &DbConn) -> Vec<Self> { |
|||
db_run! { conn: { |
|||
collections_groups::table |
|||
.inner_join(groups_users::table.on( |
|||
groups_users::groups_uuid.eq(collections_groups::groups_uuid) |
|||
)) |
|||
.inner_join(users_organizations::table.on( |
|||
users_organizations::uuid.eq(groups_users::users_organizations_uuid) |
|||
)) |
|||
.filter(users_organizations::user_uuid.eq(user_uuid)) |
|||
.select(collections_groups::all_columns) |
|||
.load::<CollectionGroupDb>(conn) |
|||
.expect("Error loading user collection groups") |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
pub async fn find_by_collection(collection_uuid: &str, conn: &DbConn) -> Vec<Self> { |
|||
db_run! { conn: { |
|||
collections_groups::table |
|||
.filter(collections_groups::collections_uuid.eq(collection_uuid)) |
|||
.select(collections_groups::all_columns) |
|||
.load::<CollectionGroupDb>(conn) |
|||
.expect("Error loading collection groups") |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
pub async fn delete(&self, conn: &DbConn) -> EmptyResult { |
|||
let group_users = GroupUser::find_by_group(&self.groups_uuid, conn).await; |
|||
for group_user in group_users { |
|||
group_user.update_user_revision(conn).await; |
|||
} |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(collections_groups::table) |
|||
.filter(collections_groups::collections_uuid.eq(&self.collections_uuid)) |
|||
.filter(collections_groups::groups_uuid.eq(&self.groups_uuid)) |
|||
.execute(conn) |
|||
.map_res("Error deleting collection group") |
|||
}} |
|||
} |
|||
|
|||
pub async fn delete_all_by_group(group_uuid: &str, conn: &DbConn) -> EmptyResult { |
|||
let group_users = GroupUser::find_by_group(group_uuid, conn).await; |
|||
for group_user in group_users { |
|||
group_user.update_user_revision(conn).await; |
|||
} |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(collections_groups::table) |
|||
.filter(collections_groups::groups_uuid.eq(group_uuid)) |
|||
.execute(conn) |
|||
.map_res("Error deleting collection group") |
|||
}} |
|||
} |
|||
|
|||
pub async fn delete_all_by_collection(collection_uuid: &str, conn: &DbConn) -> EmptyResult { |
|||
let collection_assigned_to_groups = CollectionGroup::find_by_collection(collection_uuid, conn).await; |
|||
for collection_assigned_to_group in collection_assigned_to_groups { |
|||
let group_users = GroupUser::find_by_group(&collection_assigned_to_group.groups_uuid, conn).await; |
|||
for group_user in group_users { |
|||
group_user.update_user_revision(conn).await; |
|||
} |
|||
} |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(collections_groups::table) |
|||
.filter(collections_groups::collections_uuid.eq(collection_uuid)) |
|||
.execute(conn) |
|||
.map_res("Error deleting collection group") |
|||
}} |
|||
} |
|||
} |
|||
|
|||
impl GroupUser { |
|||
pub async fn save(&mut self, conn: &DbConn) -> EmptyResult { |
|||
self.update_user_revision(conn).await; |
|||
|
|||
db_run! { conn: |
|||
sqlite, mysql { |
|||
match diesel::replace_into(groups_users::table) |
|||
.values(( |
|||
groups_users::users_organizations_uuid.eq(&self.users_organizations_uuid), |
|||
groups_users::groups_uuid.eq(&self.groups_uuid), |
|||
)) |
|||
.execute(conn) |
|||
{ |
|||
Ok(_) => Ok(()), |
|||
// Record already exists and causes a Foreign Key Violation because replace_into() wants to delete the record first.
|
|||
Err(diesel::result::Error::DatabaseError(diesel::result::DatabaseErrorKind::ForeignKeyViolation, _)) => { |
|||
diesel::update(groups_users::table) |
|||
.filter(groups_users::users_organizations_uuid.eq(&self.users_organizations_uuid)) |
|||
.filter(groups_users::groups_uuid.eq(&self.groups_uuid)) |
|||
.set(( |
|||
groups_users::users_organizations_uuid.eq(&self.users_organizations_uuid), |
|||
groups_users::groups_uuid.eq(&self.groups_uuid), |
|||
)) |
|||
.execute(conn) |
|||
.map_res("Error adding user to group") |
|||
} |
|||
Err(e) => Err(e.into()), |
|||
}.map_res("Error adding user to group") |
|||
} |
|||
postgresql { |
|||
diesel::insert_into(groups_users::table) |
|||
.values(( |
|||
groups_users::users_organizations_uuid.eq(&self.users_organizations_uuid), |
|||
groups_users::groups_uuid.eq(&self.groups_uuid), |
|||
)) |
|||
.on_conflict((groups_users::users_organizations_uuid, groups_users::groups_uuid)) |
|||
.do_update() |
|||
.set(( |
|||
groups_users::users_organizations_uuid.eq(&self.users_organizations_uuid), |
|||
groups_users::groups_uuid.eq(&self.groups_uuid), |
|||
)) |
|||
.execute(conn) |
|||
.map_res("Error adding user to group") |
|||
} |
|||
} |
|||
} |
|||
|
|||
pub async fn find_by_group(group_uuid: &str, conn: &DbConn) -> Vec<Self> { |
|||
db_run! { conn: { |
|||
groups_users::table |
|||
.filter(groups_users::groups_uuid.eq(group_uuid)) |
|||
.load::<GroupUserDb>(conn) |
|||
.expect("Error loading group users") |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
pub async fn find_by_user(users_organizations_uuid: &str, conn: &DbConn) -> Vec<Self> { |
|||
db_run! { conn: { |
|||
groups_users::table |
|||
.filter(groups_users::users_organizations_uuid.eq(users_organizations_uuid)) |
|||
.load::<GroupUserDb>(conn) |
|||
.expect("Error loading groups for user") |
|||
.from_db() |
|||
}} |
|||
} |
|||
|
|||
pub async fn update_user_revision(&self, conn: &DbConn) { |
|||
match UserOrganization::find_by_uuid(&self.users_organizations_uuid, conn).await { |
|||
Some(user) => User::update_uuid_revision(&user.user_uuid, conn).await, |
|||
None => warn!("User could not be found!"), |
|||
} |
|||
} |
|||
|
|||
pub async fn delete_by_group_id_and_user_id( |
|||
group_uuid: &str, |
|||
users_organizations_uuid: &str, |
|||
conn: &DbConn, |
|||
) -> EmptyResult { |
|||
match UserOrganization::find_by_uuid(users_organizations_uuid, conn).await { |
|||
Some(user) => User::update_uuid_revision(&user.user_uuid, conn).await, |
|||
None => warn!("User could not be found!"), |
|||
}; |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(groups_users::table) |
|||
.filter(groups_users::groups_uuid.eq(group_uuid)) |
|||
.filter(groups_users::users_organizations_uuid.eq(users_organizations_uuid)) |
|||
.execute(conn) |
|||
.map_res("Error deleting group users") |
|||
}} |
|||
} |
|||
|
|||
pub async fn delete_all_by_group(group_uuid: &str, conn: &DbConn) -> EmptyResult { |
|||
let group_users = GroupUser::find_by_group(group_uuid, conn).await; |
|||
for group_user in group_users { |
|||
group_user.update_user_revision(conn).await; |
|||
} |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(groups_users::table) |
|||
.filter(groups_users::groups_uuid.eq(group_uuid)) |
|||
.execute(conn) |
|||
.map_res("Error deleting group users") |
|||
}} |
|||
} |
|||
|
|||
pub async fn delete_all_by_user(users_organizations_uuid: &str, conn: &DbConn) -> EmptyResult { |
|||
match UserOrganization::find_by_uuid(users_organizations_uuid, conn).await { |
|||
Some(user) => User::update_uuid_revision(&user.user_uuid, conn).await, |
|||
None => warn!("User could not be found!"), |
|||
} |
|||
|
|||
db_run! { conn: { |
|||
diesel::delete(groups_users::table) |
|||
.filter(groups_users::users_organizations_uuid.eq(users_organizations_uuid)) |
|||
.execute(conn) |
|||
.map_res("Error deleting user groups") |
|||
}} |
|||
} |
|||
} |
Loading…
Reference in new issue