Compare commits

...

32 Commits

Author SHA1 Message Date
hugocasa
df15255035 fix: block disabled users from token refresh, clear error on OAuth login
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 18:17:27 +01:00
hugocasa
54a4006c92 fix: add missing sqlx cache for non-enterprise git sync query
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 14:09:15 +01:00
hugocasa
b45e953e23 fix: restore sqlx cache files deleted by incorrect prepare run
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 13:56:56 +01:00
hugocasa
92b8b8bde4 chore: update sqlx cache for non-enterprise code paths
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 13:54:49 +01:00
hugocasa
9f956e5550 fix: delete tokens on user removal, improve confirmation modal texts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 13:43:25 +01:00
hugocasa
02e2c5dfa2 fix: use .catch() for enable user error handling in dropdown action
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 13:01:36 +01:00
hugocasa
dd7362efac Merge origin/main into scim-handle-active-false 2026-03-25 12:33:13 +01:00
hugocasa
cb412bc82f chore: remove accidentally committed gen files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:30:47 +01:00
hugocasa
d215d233fd chore: update ee-repo-ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:30:07 +01:00
hugocasa
b826163811 fix: rename 'Show active users only' to 'Recently active only' to avoid confusion with disabled state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:24:56 +01:00
hugocasa
a4581bec94 refactor: move disable/enable to dropdown menu, add disabled badge on email
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:10:14 +01:00
hugocasa
63e7c37b69 fix: properly revert toggle on disable cancel using reset key
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 12:01:04 +01:00
hugocasa
7414caae00 fix: revert toggle state when disable confirmation is cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:58:38 +01:00
hugocasa
ddc814cf2d fix: improve disable user confirmation text
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:54:42 +01:00
hugocasa
51751f290d feat: add confirmation modal when disabling instance user
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:53:00 +01:00
hugocasa
ed4761ac23 [ee] feat: show disabled toggle in superadmin user list, add disabled field to API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:22:12 +01:00
hugocasa
d65a0b2647 [ee] refactor: use password.disabled for SCIM deactivation, block login for disabled users
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:45:48 +01:00
hugocasa
a441069f10 chore: update ee-repo-ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 19:33:01 +01:00
hugocasa
af7e8f25ff chore: update ee-repo-ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:39:42 +01:00
hugocasa
a94a832fa3 fix: rename migration to avoid timestamp conflict, update sqlx cache
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:28:58 +01:00
hugocasa
f81b13ec94 chore: add down migration for scim_deactivated_user
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:22:54 +01:00
hugocasa
3c687a1878 chore: update ee-repo-ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:21:26 +01:00
hugocasa
9da8bb52e2 Merge origin/main into scim-handle-active-false 2026-03-24 17:55:22 +01:00
hugocasa
c1a6a66969 chore: update ee-repo-ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:54:02 +01:00
hugocasa
8baba58f01 [ee] fix: apply SCIM filters to deactivated users, add name column
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:13:11 +01:00
hugocasa
a2cd537f8b [ee] refactor: use scim_deactivated_user table instead of password.disabled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:39:41 +01:00
hugocasa
1c036a4bb9 [ee] feat: enforce password.disabled in auth checks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:17:48 +01:00
hugocasa
3fc0a6b444 [ee] feat: add password.disabled column for SCIM user deactivation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:09:56 +01:00
hugocasa
b7870b8878 nit sqlx 2026-03-23 19:06:03 +01:00
hugocasa
b46bb0a439 chore: update ee-repo-ref
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:53:37 +01:00
hugocasa
9c32402285 chore: update ee-repo-ref for SCIM active:false deprovision fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:43:06 +01:00
hugocasa
bc7027470b [ee] feat: handle active:false in SCIM user PATCH/PUT for deprovisioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:36:46 +01:00
18 changed files with 264 additions and 68 deletions

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, login_type::text, verified, super_admin, devops, name, company, username, NULL::bool as operator_only, first_time_user, role_source FROM password ORDER BY super_admin DESC, devops DESC, email LIMIT $1 OFFSET $2",
"query": "SELECT email, login_type::text, verified, super_admin, devops, name, company, username, NULL::bool as operator_only, first_time_user, role_source, disabled FROM password ORDER BY super_admin DESC, devops DESC, email LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
@@ -57,6 +57,11 @@
"ordinal": 10,
"name": "role_source",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
@@ -76,8 +81,9 @@
true,
null,
false,
false,
false
]
},
"hash": "05027983ffdb11824190543754d0be922e1463d2046753cf80377369a90013ab"
"hash": "115a9cb44d0a41952c08dc36e0331410d32a8d672cfa4929e9e3763c51daa1bc"
}

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "DELETE FROM token WHERE email = $1",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Text"
]
},
"nullable": []
},
"hash": "192ddae8c3c82a8f099a4944483024d9826a328bf0416c22daf06fff5ced08f6"
}

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "SELECT COUNT(*) FROM usr WHERE workspace_id = $1 AND disabled = false",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "count",
"type_info": "Int8"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
null
]
},
"hash": "21f4840f60e8310d7b7efcba7483e69e4ef8821c6cbf3b4f296b3853d95692af"
}

View File

@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, disabled FROM password WHERE email = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "email",
"type_info": "Varchar"
},
{
"ordinal": 1,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false
]
},
"hash": "23b9c862d050b00aaa332527b62ef901cd3c417b9f3af03f35009213143bd443"
}

View File

@@ -15,7 +15,7 @@
]
},
"nullable": [
null
true
]
},
"hash": "5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55"

View File

@@ -0,0 +1,15 @@
{
"db_name": "PostgreSQL",
"query": "UPDATE password SET disabled = $1 WHERE email = $2",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Bool",
"Text"
]
},
"nullable": []
},
"hash": "8bd266705fc8272f3d8941922ad7d18161eb6f5ec1ba9f1b55feffe8b6518c67"
}

View File

@@ -1,17 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO deployment_metadata (workspace_id, path, script_hash, deployment_msg) VALUES ($1, $2, $3, $4) ON CONFLICT (workspace_id, script_hash) WHERE script_hash IS NOT NULL DO UPDATE SET deployment_msg = EXCLUDED.deployment_msg",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Varchar",
"Varchar",
"Int8",
"Text"
]
},
"nullable": []
},
"hash": "9f07510019ebe6f0c5fa17bf31c2d14755474cba82b3b388a47585a8bb325b1a"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "WITH active_users AS (SELECT distinct username as email FROM (SELECT username, timestamp, operation FROM audit_partitioned UNION ALL SELECT username, timestamp, operation FROM audit) AS a WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')),\n authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username, first_time_user, role_source\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n ORDER BY super_admin DESC, devops DESC\n LIMIT $1 OFFSET $2",
"query": "WITH active_users AS (SELECT distinct username as email FROM (SELECT username, timestamp, operation FROM audit_partitioned UNION ALL SELECT username, timestamp, operation FROM audit) AS a WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')),\n authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username, first_time_user, role_source, disabled\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n ORDER BY super_admin DESC, devops DESC\n LIMIT $1 OFFSET $2",
"describe": {
"columns": [
{
@@ -57,6 +57,11 @@
"ordinal": 10,
"name": "role_source",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
@@ -76,8 +81,9 @@
true,
true,
false,
false,
false
]
},
"hash": "60118de85463098220b1c74f667b6fedb0f3f0040844c3774145e8f1f4c023ce"
"hash": "a5fd115e7be5129d623543bbfa7b5b31f0efc6d8ef73f691009c73f833dcee10"
}

View File

@@ -0,0 +1,28 @@
{
"db_name": "PostgreSQL",
"query": "SELECT super_admin, disabled FROM password WHERE email = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "super_admin",
"type_info": "Bool"
},
{
"ordinal": 1,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false,
false
]
},
"hash": "d09706517cbc4763bcd4010a3de2c868e9ad2361ff56bb64a1ff12dab8c124b1"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "INSERT INTO password (email, login_type, verified, username, name) VALUES ($1, 'saml', true, $2, $3) ON CONFLICT DO NOTHING",
"query": "INSERT INTO password (email, login_type, verified, username, name) VALUES ($1, 'saml', true, $2, $3) ON CONFLICT (email) DO UPDATE SET disabled = false",
"describe": {
"columns": [],
"parameters": {
@@ -12,5 +12,5 @@
},
"nullable": []
},
"hash": "638d3c2ba1198dce5b5b0e47df59a92ff8011e19fbefcc3960d6f0fe167e55b6"
"hash": "daa1a6bf3d4a1001da88301932a7ac9019767074158e0c027988e5b0d51a3656"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "SELECT email, login_type::TEXT, super_admin, devops, verified, name, company, username, NULL::bool as operator_only, first_time_user, role_source FROM password WHERE email = $1",
"query": "SELECT email, login_type::TEXT, super_admin, devops, verified, name, company, username, NULL::bool as operator_only, first_time_user, role_source, disabled FROM password WHERE email = $1",
"describe": {
"columns": [
{
@@ -57,6 +57,11 @@
"ordinal": 10,
"name": "role_source",
"type_info": "Varchar"
},
{
"ordinal": 11,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
@@ -75,8 +80,9 @@
true,
null,
false,
false,
false
]
},
"hash": "65c59e224e460351c2f88261f8b1b1e7ce2bb160270b59c0f359b7952453b2b9"
"hash": "f0c9c54740cc1c0c2a6fa4e79d4d504b7b5cb7a39538ab9abeb44f781c711493"
}

View File

@@ -0,0 +1,22 @@
{
"db_name": "PostgreSQL",
"query": "SELECT disabled FROM password WHERE email = $1",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "disabled",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
},
"hash": "fc6c6310ae8ac5eb351d7e2af1678447d0aa3d143e94e49924ff7ac8b7abf924"
}

View File

@@ -1 +1 @@
b5c8af4df9ba2c39fdd494d7a40f9a92fbff8abc
7e3a0afd393646a7179278febe593fa598252fed

View File

@@ -0,0 +1 @@
ALTER TABLE password DROP COLUMN IF EXISTS disabled;

View File

@@ -0,0 +1 @@
ALTER TABLE password ADD COLUMN disabled BOOLEAN NOT NULL DEFAULT false;

View File

@@ -157,6 +157,7 @@ pub struct GlobalUserInfo {
operator_only: Option<bool>,
first_time_user: bool,
role_source: String,
disabled: bool,
}
#[derive(Serialize, Debug)]
@@ -213,6 +214,7 @@ pub struct EditUser {
pub is_super_admin: Option<bool>,
pub is_devops: Option<bool>,
pub name: Option<String>,
pub disabled: Option<bool>,
}
#[derive(Deserialize)]
@@ -396,7 +398,7 @@ async fn list_users_as_super_admin(
GlobalUserInfo,
"WITH active_users AS (SELECT distinct username as email FROM (SELECT username, timestamp, operation FROM audit_partitioned UNION ALL SELECT username, timestamp, operation FROM audit) AS a WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')),
authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)
SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username, first_time_user, role_source
SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username, first_time_user, role_source, disabled
FROM password
WHERE email IN (SELECT email FROM active_users)
ORDER BY super_admin DESC, devops DESC
@@ -409,7 +411,7 @@ async fn list_users_as_super_admin(
} else {
sqlx::query_as!(
GlobalUserInfo,
"SELECT email, login_type::text, verified, super_admin, devops, name, company, username, NULL::bool as operator_only, first_time_user, role_source FROM password ORDER BY super_admin DESC, devops DESC, email LIMIT \
"SELECT email, login_type::text, verified, super_admin, devops, name, company, username, NULL::bool as operator_only, first_time_user, role_source, disabled FROM password ORDER BY super_admin DESC, devops DESC, email LIMIT \
$1 OFFSET $2",
per_page as i32,
offset as i32
@@ -625,7 +627,7 @@ async fn global_whoami(
) -> JsonResult<GlobalUserInfo> {
let user = sqlx::query_as!(
GlobalUserInfo,
"SELECT email, login_type::TEXT, super_admin, devops, verified, name, company, username, NULL::bool as operator_only, first_time_user, role_source FROM password WHERE \
"SELECT email, login_type::TEXT, super_admin, devops, verified, name, company, username, NULL::bool as operator_only, first_time_user, role_source, disabled FROM password WHERE \
email = $1",
email
)
@@ -648,6 +650,7 @@ async fn global_whoami(
operator_only: None,
first_time_user: false,
role_source: "manual".to_string(),
disabled: false,
}))
} else {
Err(user.unwrap_err())
@@ -1407,6 +1410,22 @@ async fn update_user(
.await?;
}
if let Some(d) = eu.disabled {
sqlx::query_scalar!(
"UPDATE password SET disabled = $1 WHERE email = $2",
d,
&email_to_update
)
.execute(&mut *tx)
.await?;
if d {
// Delete all tokens for immediate session revocation
sqlx::query!("DELETE FROM token WHERE email = $1", &email_to_update)
.execute(&mut *tx)
.await?;
}
}
audit_log(
&mut *tx,
&authed,
@@ -1429,6 +1448,9 @@ async fn delete_user(
require_super_admin(&db, &authed.email).await?;
let mut tx = db.begin().await?;
sqlx::query!("DELETE FROM token WHERE email = $1", &email_to_delete)
.execute(&mut *tx)
.await?;
sqlx::query!("DELETE FROM password WHERE email = $1", &email_to_delete)
.execute(&mut *tx)
.await?;
@@ -1687,7 +1709,7 @@ async fn login(
};
let email_w_h: Option<(String, String, bool)> = sqlx::query_as(
"SELECT email, password_hash, super_admin FROM password WHERE email = $1 AND login_type = \
'password'",
'password' AND disabled = false",
)
.bind(&email)
.fetch_optional(&mut *tx)
@@ -1775,13 +1797,20 @@ async fn refresh_token(
}
}
let super_admin = sqlx::query_scalar!(
"SELECT super_admin FROM password WHERE email = $1",
let password_row = sqlx::query!(
"SELECT super_admin, disabled FROM password WHERE email = $1",
&authed.email
)
.fetch_optional(&mut *tx)
.await?
.unwrap_or(false);
.await?;
if password_row.as_ref().map(|r| r.disabled).unwrap_or(false) {
return Err(Error::NotAuthorized(
"Your account has been disabled".to_string(),
));
}
let super_admin = password_row.map(|r| r.super_admin).unwrap_or(false);
let new_token = create_session_token(&authed.email, super_admin, &mut tx, cookies).await?;

View File

@@ -588,6 +588,8 @@ paths:
type: boolean
name:
type: string
disabled:
type: boolean
responses:
"200":
description: user updated
@@ -23412,6 +23414,8 @@ components:
role_source:
type: string
enum: ["manual", "instance_group"]
disabled:
type: boolean
required:
- email
@@ -23420,6 +23424,7 @@ components:
- verified
- first_time_user
- role_source
- disabled
Flow:
allOf:

View File

@@ -17,7 +17,7 @@
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
import { userStore, workspaceStore } from '$lib/stores'
import { ExternalLink, Pencil, UserMinus, UserPlus } from 'lucide-svelte'
import { Ban, CheckCircle2, ExternalLink, Pencil, UserMinus, UserPlus } from 'lucide-svelte'
import DropdownV2 from './DropdownV2.svelte'
import Popover from './meltComponents/Popover.svelte'
import ConfirmationModal from './common/confirmationModal/ConfirmationModal.svelte'
@@ -67,6 +67,8 @@
let filteredUsers: GlobalUserInfo[] = $state([])
let deleteConfirmedCallback: (() => void) | undefined = $state(undefined)
let deleteUserEmail: string = $state('')
let disableConfirmedCallback: (() => void) | undefined = $state(undefined)
let disableUserEmail: string = $state('')
let editWrappers: Record<string, HTMLDivElement> = $state({})
let activeOnly = $state(false)
@@ -293,9 +295,9 @@
/><Toggle
bind:checked={activeOnly}
options={{
left: 'Show active users only',
left: 'Recently active only',
leftTooltip:
'An active user is a user who has performed at least one action in the last 30 days'
'Show only users who have logged in or performed an action in the last 30 days'
}}
/>
@@ -347,13 +349,25 @@
</Head>
<tbody>
{#if filteredUsers && users}
{#each filteredUsers.slice(0, nbDisplayed) as { email, super_admin, devops, login_type, name, username, operator_only, role_source }, i (email)}
<tr class={i % 2 === 0 ? 'bg-surface-tertiary' : 'bg-surface'}>
<Cell first class="max-w-[200px]"
><a href="mailto:{email}" title={email} class="truncate block"
>{email}</a
></Cell
>
{#each filteredUsers.slice(0, nbDisplayed) as { email, super_admin, devops, login_type, name, username, operator_only, role_source, disabled }, i (email)}
<tr
class="{i % 2 === 0 ? 'bg-surface-tertiary' : 'bg-surface'} {disabled
? 'opacity-60'
: ''}"
>
<Cell first class="max-w-[250px]">
<div class="flex items-center gap-1.5">
<a href="mailto:{email}" title={email} class="truncate block"
>{email}</a
>
{#if disabled}
<span
class="text-2xs px-1.5 py-0.5 rounded bg-red-100 text-red-600 dark:bg-red-900 dark:text-red-300 whitespace-nowrap"
>Disabled</span
>
{/if}
</div>
</Cell>
{#if automateUsernameCreation}
<Cell class="max-w-[150px]">
{#if username}
@@ -514,6 +528,39 @@
if (btn instanceof HTMLElement) btn.click()
}
},
{
displayName: disabled ? 'Enable' : 'Disable',
icon: disabled ? CheckCircle2 : Ban,
action: () => {
if (!disabled) {
disableUserEmail = email
disableConfirmedCallback = async () => {
try {
await UserService.globalUserUpdate({
email,
requestBody: { disabled: true }
})
sendUserToast('User disabled')
listUsers(activeOnly)
} catch (e) {
sendUserToast('Failed to disable user', true)
}
}
} else {
UserService.globalUserUpdate({
email,
requestBody: { disabled: false }
})
.then(() => {
sendUserToast('User enabled')
listUsers(activeOnly)
})
.catch(() => {
sendUserToast('Failed to enable user', true)
})
}
}
},
{
displayName: 'Remove',
icon: UserMinus,
@@ -578,6 +625,33 @@
}}
>
<div class="flex flex-col w-full space-y-4">
<span>Are you sure you want to remove <b>{deleteUserEmail}</b>?</span>
<span
>Are you sure you want to remove <b>{deleteUserEmail}</b>? They will be removed from all
workspaces and instance groups, and all their sessions and tokens will be revoked. This action
is irreversible. Their workspace content (scripts, flows, apps) will not be deleted.</span
>
</div>
</ConfirmationModal>
<ConfirmationModal
open={Boolean(disableConfirmedCallback)}
title="Disable user"
confirmationText="Disable"
on:canceled={() => {
disableConfirmedCallback = undefined
listUsers(activeOnly)
}}
on:confirmed={() => {
if (disableConfirmedCallback) {
disableConfirmedCallback()
}
disableConfirmedCallback = undefined
}}
>
<div class="flex flex-col w-full space-y-4">
<span
>Are you sure you want to disable <b>{disableUserEmail}</b>? All their active sessions and
tokens will be revoked immediately. They will be unable to log in until re-enabled. Their
workspace memberships and content will be preserved.</span
>
</div>
</ConfirmationModal>