From fa2566d14fc745937ce104011475eca9e6c7a6f6 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Mon, 24 Aug 2026 19:38:23 +0200 Subject: [PATCH 1/6] Fix password change with newer web-vault (#7634) --- src/api/core/accounts.rs | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index 0cb4d3c0..626f22bb 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -595,29 +595,52 @@ async fn post_keys(data: Json, headers: Headers, conn: DbConn) -> Json #[serde(rename_all = "camelCase")] struct ChangePassData { master_password_hash: String, - new_master_password_hash: String, master_password_hint: Option, - key: String, + authentication_data: Option, + unlock_data: Option, + + // Outdated values, might still be used by older clients + new_master_password_hash: Option, + key: Option, } #[post("/accounts/password", data = "")] async fn post_password(data: Json, headers: Headers, conn: DbConn, nt: Notify<'_>) -> EmptyResult { let data: ChangePassData = data.into_inner(); - let mut user = headers.user; + let user = headers.user; if !user.check_valid_password(&data.master_password_hash) { err!("Invalid password") } - user.password_hint = clean_password_hint(data.master_password_hint.as_ref()); - enforce_password_hint_setting(user.password_hint.as_ref())?; - log_user_event(EventType::UserChangedPassword as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &conn) .await; + let (new_master_password_hash, new_key) = + if let (Some(unlock_data), Some(authentication_data)) = (data.unlock_data, data.authentication_data) { + if authentication_data.kdf != unlock_data.kdf { + err!("KDF settings must be equal for authentication and unlock") + } + + if user.email != authentication_data.salt || user.email != unlock_data.salt { + err!("Invalid master password salt") + } + + (authentication_data.master_password_authentication_hash, unlock_data.master_key_wrapped_user_key) + } else if let (Some(new_master_password_hash), Some(new_key)) = (data.new_master_password_hash, data.key) { + (new_master_password_hash, new_key) + } else { + err!("Invalid request!") + }; + + let mut user = user; + + user.password_hint = clean_password_hint(data.master_password_hint.as_ref()); + enforce_password_hint_setting(user.password_hint.as_ref())?; + user.set_password( - &data.new_master_password_hash, - Some(data.key), + &new_master_password_hash, + Some(new_key), true, Some(vec![ String::from("post_rotatekey"), From 10e044f563e6224eb0271419f7b7f4140791dc7f Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Sat, 29 Aug 2026 08:01:45 -0700 Subject: [PATCH 2/6] chore: remove duplicate "the" in ciphers.rs comment (#7254) `src/api/core/ciphers.rs:170` comment said "similar to the the userDecryptionOptions" -> "similar to the userDecryptionOptions". Comment-only. Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> --- src/api/core/ciphers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 2b51fd0c..3e94ca7c 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -167,7 +167,7 @@ async fn sync(data: SyncData, headers: Headers, client_version: Option Date: Sat, 29 Aug 2026 11:01:51 -0400 Subject: [PATCH 3/6] Ignore reset-password auto-enroll when mail is disabled (#7585) Account recovery requires SMTP. When mail is off, treat the organization reset-password auto-enroll policy as inactive so invite/accept flows are not forced to supply a reset-password key. Fixes #7459 --- src/db/models/org_policy.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/db/models/org_policy.rs b/src/db/models/org_policy.rs index d501f8b9..2b45cd86 100644 --- a/src/db/models/org_policy.rs +++ b/src/db/models/org_policy.rs @@ -318,6 +318,13 @@ impl OrgPolicy { } pub async fn org_is_reset_password_auto_enroll(org_uuid: &OrganizationId, conn: &DbConn) -> bool { + // Account recovery depends on outbound mail. When SMTP is disabled, treat the + // auto-enroll policy as inactive so invites/registration are not forced to + // supply a reset-password key (see check_reset_password_applicable). + if !CONFIG.mail_enabled() { + return false; + } + match OrgPolicy::find_by_org_and_type(org_uuid, OrgPolicyType::ResetPassword, conn).await { Some(policy) => match serde_json::from_str::(&policy.data) { Ok(opts) => { From 923f5d0b5eb7e223855031e35ba9606372ff5fa3 Mon Sep 17 00:00:00 2001 From: Timshel Date: Sat, 29 Aug 2026 15:02:01 +0000 Subject: [PATCH 4/6] Fix migration for MariaDB 12.2.2 (#7265) Co-authored-by: Timshel --- .../up.sql | 42 +++++++++++++------ playwright/docker-compose.yml | 2 +- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/migrations/mysql/2024-03-13-170000_sso_users_cascade/up.sql b/migrations/mysql/2024-03-13-170000_sso_users_cascade/up.sql index 9e5e46df..8d1eb178 100644 --- a/migrations/mysql/2024-03-13-170000_sso_users_cascade/up.sql +++ b/migrations/mysql/2024-03-13-170000_sso_users_cascade/up.sql @@ -1,15 +1,31 @@ --- Dynamically create DROP FOREIGN KEY --- Some versions of MySQL or MariaDB might fail if the key doesn't exists --- This checks if the key exists, and if so, will drop it. -SET @drop_sso_fk = IF((SELECT true FROM information_schema.TABLE_CONSTRAINTS WHERE - CONSTRAINT_SCHEMA = DATABASE() AND - TABLE_NAME = 'sso_users' AND - CONSTRAINT_NAME = 'sso_users_ibfk_1' AND - CONSTRAINT_TYPE = 'FOREIGN KEY') = true, - 'ALTER TABLE sso_users DROP FOREIGN KEY sso_users_ibfk_1', - 'SELECT 1'); -PREPARE stmt FROM @drop_sso_fk; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; +SELECT if ( + EXISTS( + SELECT CONSTRAINT_NAME FROM information_schema.table_constraints + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'sso_users' + AND CONSTRAINT_TYPE = 'FOREIGN KEY' + AND CONSTRAINT_NAME = 'sso_users_ibfk_1' + ) + ,'ALTER TABLE sso_users DROP FOREIGN KEY `sso_users_ibfk_1`' + ,'SELECT "info: FK sso_users_ibfk_1 does not exist."' +) INTO @drop_stmt; +PREPARE drop_stmt FROM @drop_stmt; +EXECUTE drop_stmt; + +SELECT if ( + EXISTS( + SELECT CONSTRAINT_NAME FROM information_schema.table_constraints + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'sso_users' + AND CONSTRAINT_TYPE = 'FOREIGN KEY' + AND CONSTRAINT_NAME = '1' + ) + ,'ALTER TABLE sso_users DROP FOREIGN KEY `1`' + ,'SELECT "info: FK sso_users 1 does not exist."' +) INTO @drop_stmt; +PREPARE drop_stmt FROM @drop_stmt; +EXECUTE drop_stmt; + +DEALLOCATE PREPARE drop_stmt; ALTER TABLE sso_users ADD FOREIGN KEY(user_uuid) REFERENCES users(uuid) ON UPDATE CASCADE ON DELETE CASCADE; diff --git a/playwright/docker-compose.yml b/playwright/docker-compose.yml index 5dd04ff4..5bfc47a5 100644 --- a/playwright/docker-compose.yml +++ b/playwright/docker-compose.yml @@ -61,7 +61,7 @@ services: Mariadb: profiles: ["playwright"] container_name: playwright_mariadb - image: mariadb:11.2.4 + image: mariadb:12.2.2 env_file: test.env healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] From 2073c03092d328e4b5fd19882ecfbe491dc8b5c7 Mon Sep 17 00:00:00 2001 From: Timshel Date: Sat, 29 Aug 2026 15:02:22 +0000 Subject: [PATCH 5/6] Add SSO_SIGNUPS_ALLOWED (#7272) * Add SSO_SIGNUPS_ALLOWED * Fix regression with domain_allowed in SSO onboarding --------- Co-authored-by: Timshel --- .env.template | 3 +++ src/api/identity.rs | 28 +++++++++++++++++++++++++++- src/config.rs | 13 +++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/.env.template b/.env.template index 9fc29989..5f6f374c 100644 --- a/.env.template +++ b/.env.template @@ -518,6 +518,9 @@ ## Prevent users from logging in directly without going through SSO # SSO_ONLY=false +## Allow SSO flow to create account. You probably want to disable it when using a public provider. +# SSO_SIGNUPS_ALLOWED=true + ## On SSO Signup if a user with a matching email already exists make the association # SSO_SIGNUPS_MATCH_EMAIL=true diff --git a/src/api/identity.rs b/src/api/identity.rs index 23411dc7..2b1ddfb1 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -234,6 +234,24 @@ async fn sso_login( } ) } + Some((user, None)) + if user.private_key.is_none() + && !CONFIG.sso_signups_allowed() + && !CONFIG.is_email_domain_allowed(&user.email) + && !CONFIG.mail_enabled() + && Invitation::find_by_mail(&user.email, conn).await.is_none() => + { + error!( + "Login failure ({}), no invitation with email ({}) was found", + user_infos.identifier, user.email + ); + err_silent!( + "Missing invitation", + ErrorEvent { + event: EventType::UserFailedLogIn + } + ) + } Some((user, None)) if user.private_key.is_some() && !CONFIG.sso_signups_match_email() => { error!( "Login failure ({}), existing non SSO user ({}) with same email ({}) and association is disabled", @@ -281,7 +299,15 @@ async fn sso_login( // Will trigger 2FA flow if needed let (user, mut device, twofactor_token, sso_user) = match user_with_sso { None => { - if !CONFIG.is_email_domain_allowed(&user_infos.email) { + if !CONFIG.is_sso_signup_allowed(&user_infos.email) { + if CONFIG.signups_domains_whitelist().is_empty() { + err!( + "Signups are disabled. You will need an invitation", + ErrorEvent { + event: EventType::UserFailedLogIn + } + ); + } err!( "Email domain not allowed", ErrorEvent { diff --git a/src/config.rs b/src/config.rs index 72b58252..2502dd02 100644 --- a/src/config.rs +++ b/src/config.rs @@ -817,6 +817,8 @@ make_config! { sso_enabled: bool, true, def, false; /// Only SSO login |> Disable Email+Master Password login sso_only: bool, true, def, false; + /// Allow SSO flow to create account |> You probably want to disable it when using a public provider + sso_signups_allowed: bool, true, def, true; /// Allow email association |> Associate existing non-SSO user based on email sso_signups_match_email: bool, true, def, true; /// Allow unknown email verification status |> Allowing this with `SSO_SIGNUPS_MATCH_EMAIL=true` open potential account takeover. @@ -1544,6 +1546,17 @@ impl Config { } } + /// Tests whether SSO signup is allowed for an email address, taking into + /// account the sso_signups_allowed and signups_domains_whitelist settings. + pub fn is_sso_signup_allowed(&self, email: &str) -> bool { + if self.signups_domains_whitelist().is_empty() { + self.sso_signups_allowed() + } else { + // The whitelist setting overrides the signups_allowed setting. + self.is_email_domain_allowed(email) + } + } + // The registration link should be hidden if // - Signup is not allowed and email whitelist is empty unless mail is disabled and invitations are allowed // - The SSO is activated and password login is disabled. From fdc156b247846ca73f6aa3e9c676a6f2f57577cf Mon Sep 17 00:00:00 2001 From: Timshel Date: Sat, 29 Aug 2026 15:02:26 +0000 Subject: [PATCH 6/6] log_event take enum parameter not i32 (#7656) Co-authored-by: Timshel --- src/api/admin.rs | 6 ++--- src/api/core/ciphers.rs | 28 ++++++++------------- src/api/core/events.rs | 6 ++--- src/api/core/organizations.rs | 46 +++++++++++++++++----------------- src/api/core/two_factor/mod.rs | 14 +++-------- 5 files changed, 42 insertions(+), 58 deletions(-) diff --git a/src/api/admin.rs b/src/api/admin.rs index 48f36afd..eaa681dd 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -425,7 +425,7 @@ async fn delete_user(user_id: UserId, token: AdminToken, conn: DbConn) -> EmptyR for membership in memberships { log_event( - EventType::OrganizationUserDeleted as i32, + EventType::OrganizationUserDeleted, &membership.uuid, &membership.org_uuid, &ACTING_ADMIN_USER.into(), @@ -446,7 +446,7 @@ async fn delete_sso_user(user_id: UserId, token: AdminToken, conn: DbConn) -> Em for membership in memberships { log_event( - EventType::OrganizationUserUnlinkedSso as i32, + EventType::OrganizationUserUnlinkedSso, &membership.uuid, &membership.org_uuid, &ACTING_ADMIN_USER.into(), @@ -571,7 +571,7 @@ async fn update_membership_type(data: Json, token: AdminToke OrgPolicy::check_user_allowed(&member_to_edit, "modify", &conn).await?; log_event( - EventType::OrganizationUserUpdated as i32, + EventType::OrganizationUserUpdated, &member_to_edit.uuid, &data.org_uuid, &ACTING_ADMIN_USER.into(), diff --git a/src/api/core/ciphers.rs b/src/api/core/ciphers.rs index 3e94ca7c..13021ca3 100644 --- a/src/api/core/ciphers.rs +++ b/src/api/core/ciphers.rs @@ -553,16 +553,8 @@ pub async fn update_cipher_from_data( (_, _) => EventType::CipherUpdated, }; - log_event( - event_type as i32, - &cipher.uuid, - org_id, - &headers.user.uuid, - headers.device.atype, - &headers.ip.ip, - conn, - ) - .await; + log_event(event_type, &cipher.uuid, org_id, &headers.user.uuid, headers.device.atype, &headers.ip.ip, conn) + .await; } nt.send_cipher_update( ut, @@ -850,7 +842,7 @@ async fn post_collections_update( .await; log_event( - EventType::CipherUpdatedCollections as i32, + EventType::CipherUpdatedCollections, &cipher.uuid, org_uuid, &headers.user.uuid, @@ -930,7 +922,7 @@ async fn post_collections_admin( .await; log_event( - EventType::CipherUpdatedCollections as i32, + EventType::CipherUpdatedCollections, &cipher.uuid, org_uuid, &headers.user.uuid, @@ -1335,7 +1327,7 @@ async fn save_attachment( if let Some(org_id) = &cipher.organization_uuid { log_event( - EventType::CipherAttachmentCreated as i32, + EventType::CipherAttachmentCreated, &cipher.uuid, org_id, &headers.user.uuid, @@ -1696,7 +1688,7 @@ async fn purge_org_vault( nt.send_user_update(UpdateType::SyncVault, &user, headers.device.push_uuid.as_ref(), &conn).await; log_event( - EventType::OrganizationPurgedVault as i32, + EventType::OrganizationPurgedVault, &organization.org_id, &organization.org_id, &user.uuid, @@ -1824,9 +1816,9 @@ async fn delete_cipher_by_uuid( let event_type = if *delete_options == CipherDeleteOptions::SoftSingle || *delete_options == CipherDeleteOptions::SoftMulti { - EventType::CipherSoftDeleted as i32 + EventType::CipherSoftDeleted } else { - EventType::CipherDeleted as i32 + EventType::CipherDeleted }; log_event(event_type, &cipher.uuid, &org_id, &headers.user.uuid, headers.device.atype, &headers.ip.ip, conn) @@ -1895,7 +1887,7 @@ async fn restore_cipher_by_uuid( if let Some(org_id) = &cipher.organization_uuid { log_event( - EventType::CipherRestored as i32, + EventType::CipherRestored, &cipher.uuid.clone(), org_id, &headers.user.uuid, @@ -1972,7 +1964,7 @@ async fn delete_cipher_attachment_by_id( if let Some(ref org_id) = cipher.organization_uuid { log_event( - EventType::CipherAttachmentDeleted as i32, + EventType::CipherAttachmentDeleted, &cipher.uuid, org_id, &headers.user.uuid, diff --git a/src/api/core/events.rs b/src/api/core/events.rs index 5518fa3c..2c437a36 100644 --- a/src/api/core/events.rs +++ b/src/api/core/events.rs @@ -10,7 +10,7 @@ use crate::{ auth::{AdminHeaders, Headers}, db::{ DbConn, DbPool, - models::{Cipher, CipherId, Event, Membership, MembershipId, OrganizationId, UserId}, + models::{Cipher, CipherId, Event, EventType, Membership, MembershipId, OrganizationId, UserId}, }, util::parse_date, }; @@ -267,7 +267,7 @@ async fn log_user_event_impl( } pub async fn log_event( - event_type: i32, + event_type: EventType, source_uuid: &str, org_id: &OrganizationId, act_user_id: &UserId, @@ -278,7 +278,7 @@ pub async fn log_event( if !CONFIG.org_events_enabled() { return; } - log_event_impl(event_type, source_uuid, org_id, act_user_id, device_type, None, ip, conn).await; + log_event_impl(event_type as i32, source_uuid, org_id, act_user_id, device_type, None, ip, conn).await; } #[expect(clippy::too_many_arguments)] diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index 989ca47d..9082297f 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -269,7 +269,7 @@ async fn leave_organization(org_id: OrganizationId, headers: OrgMemberHeaders, c } log_event( - EventType::OrganizationUserLeft as i32, + EventType::OrganizationUserLeft, &membership.uuid, &org_id, &headers.user.uuid, @@ -327,7 +327,7 @@ async fn post_organization( org.save(&conn).await?; log_event( - EventType::OrganizationUpdated as i32, + EventType::OrganizationUpdated, org_id.as_ref(), &org_id, &headers.user.uuid, @@ -514,7 +514,7 @@ async fn post_organization_collections( collection.save(&conn).await?; log_event( - EventType::CollectionCreated as i32, + EventType::CollectionCreated, &collection.uuid, &org_id, &headers.user.uuid, @@ -597,7 +597,7 @@ async fn post_bulk_access_collections( collection.save(&conn).await?; log_event( - EventType::CollectionUpdated as i32, + EventType::CollectionUpdated, &collection.uuid, &org_id, &headers.user.uuid, @@ -674,7 +674,7 @@ async fn post_organization_collection_update( collection.save(&conn).await?; log_event( - EventType::CollectionUpdated as i32, + EventType::CollectionUpdated, &collection.uuid, &org_id, &headers.user.uuid, @@ -723,7 +723,7 @@ async fn delete_organization_collection_impl( err!("Collection not found", "Collection does not exist or does not belong to this organization") }; log_event( - EventType::CollectionDeleted as i32, + EventType::CollectionDeleted, &collection.uuid, org_id, &headers.user.uuid, @@ -1148,7 +1148,7 @@ async fn send_invite( } log_event( - EventType::OrganizationUserInvited as i32, + EventType::OrganizationUserInvited, &new_member.uuid, &org_id, &headers.user.uuid, @@ -1447,7 +1447,7 @@ async fn confirm_invite_impl( OrgPolicy::check_user_allowed(&member_to_confirm, "confirm", conn).await?; log_event( - EventType::OrganizationUserConfirmed as i32, + EventType::OrganizationUserConfirmed, &member_to_confirm.uuid, org_id, &headers.user.uuid, @@ -1637,7 +1637,7 @@ async fn edit_member( } log_event( - EventType::OrganizationUserUpdated as i32, + EventType::OrganizationUserUpdated, &member_to_edit.uuid, &org_id, &headers.user.uuid, @@ -1724,7 +1724,7 @@ async fn delete_member_impl( } log_event( - EventType::OrganizationUserRemoved as i32, + EventType::OrganizationUserRemoved, &member_to_delete.uuid, org_id, &headers.user.uuid, @@ -2144,7 +2144,7 @@ async fn put_policy( } log_event( - EventType::OrganizationUserRemoved as i32, + EventType::OrganizationUserRemoved, &member.uuid, &org_id, &headers.user.uuid, @@ -2170,7 +2170,7 @@ async fn put_policy( policy.save(&conn).await?; log_event( - EventType::PolicyUpdated as i32, + EventType::PolicyUpdated, policy.uuid.as_ref(), &org_id, &headers.user.uuid, @@ -2339,7 +2339,7 @@ async fn revoke_member_impl( member.save(conn).await?; log_event( - EventType::OrganizationUserRevoked as i32, + EventType::OrganizationUserRevoked, &member.uuid, org_id, &headers.user.uuid, @@ -2437,7 +2437,7 @@ async fn restore_member_impl( member.save(conn).await?; log_event( - EventType::OrganizationUserRestored as i32, + EventType::OrganizationUserRestored, &member.uuid, org_id, &headers.user.uuid, @@ -2605,7 +2605,7 @@ async fn post_groups( let group = group_request.to_group(&org_id); log_event( - EventType::GroupCreated as i32, + EventType::GroupCreated, &group.uuid, &org_id, &headers.user.uuid, @@ -2646,7 +2646,7 @@ async fn put_group( GroupUser::delete_all_by_group(&group_id, &org_id, &conn).await?; log_event( - EventType::GroupUpdated as i32, + EventType::GroupUpdated, &updated_group.uuid, &org_id, &headers.user.uuid, @@ -2679,7 +2679,7 @@ async fn add_update_group( user_entry.save(conn).await?; log_event( - EventType::OrganizationUserUpdatedGroups as i32, + EventType::OrganizationUserUpdatedGroups, &assigned_member, &org_id, &headers.user.uuid, @@ -2754,7 +2754,7 @@ async fn delete_group_impl( }; log_event( - EventType::GroupDeleted as i32, + EventType::GroupDeleted, &group.uuid, org_id, &headers.user.uuid, @@ -2865,7 +2865,7 @@ async fn put_group_members( user_entry.save(&conn).await?; log_event( - EventType::OrganizationUserUpdatedGroups as i32, + EventType::OrganizationUserUpdatedGroups, &assigned_member, &org_id, &headers.user.uuid, @@ -2903,7 +2903,7 @@ async fn post_delete_group_member( } log_event( - EventType::OrganizationUserUpdatedGroups as i32, + EventType::OrganizationUserUpdatedGroups, &member_id, &org_id, &headers.user.uuid, @@ -3039,7 +3039,7 @@ async fn recover_account( nt.send_logout(&user, None, &conn).await; log_event( - EventType::OrganizationUserAdminResetPassword as i32, + EventType::OrganizationUserAdminResetPassword, &member_id, &org_id, &headers.user.uuid, @@ -3166,9 +3166,9 @@ async fn put_reset_password_enrollment( membership.save(&conn).await?; let event_type = if membership.reset_password_key.is_some() { - EventType::OrganizationUserResetPasswordEnroll as i32 + EventType::OrganizationUserResetPasswordEnroll } else { - EventType::OrganizationUserResetPasswordWithdraw as i32 + EventType::OrganizationUserResetPasswordWithdraw }; log_event(event_type, &membership.uuid, &org_id, &headers.user.uuid, headers.device.atype, &headers.ip.ip, &conn) diff --git a/src/api/core/two_factor/mod.rs b/src/api/core/two_factor/mod.rs index 8869d23d..c95fb297 100644 --- a/src/api/core/two_factor/mod.rs +++ b/src/api/core/two_factor/mod.rs @@ -190,7 +190,7 @@ pub async fn enforce_2fa_policy( member.save(conn).await?; log_event( - EventType::OrganizationUserRevoked as i32, + EventType::OrganizationUserRevoked, &member.uuid, &member.org_uuid, act_user_id, @@ -224,16 +224,8 @@ pub async fn enforce_2fa_policy_for_org( member.revoke(); member.save(conn).await?; - log_event( - EventType::OrganizationUserRevoked as i32, - &member.uuid, - org_id, - act_user_id, - device_type, - ip, - conn, - ) - .await; + log_event(EventType::OrganizationUserRevoked, &member.uuid, org_id, act_user_id, device_type, ip, conn) + .await; } }