mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 16:02:28 +00:00
[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>
This commit is contained in:
+8
-2
@@ -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"
|
||||
}
|
||||
+8
-2
@@ -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"
|
||||
}
|
||||
+8
-2
@@ -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"
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -588,6 +588,8 @@ paths:
|
||||
type: boolean
|
||||
name:
|
||||
type: string
|
||||
disabled:
|
||||
type: boolean
|
||||
responses:
|
||||
"200":
|
||||
description: user updated
|
||||
@@ -23168,6 +23170,8 @@ components:
|
||||
role_source:
|
||||
type: string
|
||||
enum: ["manual", "instance_group"]
|
||||
disabled:
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- email
|
||||
@@ -23176,6 +23180,7 @@ components:
|
||||
- verified
|
||||
- first_time_user
|
||||
- role_source
|
||||
- disabled
|
||||
|
||||
Flow:
|
||||
allOf:
|
||||
|
||||
@@ -332,6 +332,7 @@
|
||||
{/if}
|
||||
<Cell head>Name</Cell>
|
||||
<Cell head>Auth</Cell>
|
||||
<Cell head>Enabled</Cell>
|
||||
{#if activeOnly}
|
||||
<Cell head>Kind</Cell>
|
||||
{/if}
|
||||
@@ -343,7 +344,7 @@
|
||||
</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)}
|
||||
{#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'}>
|
||||
<Cell first class="max-w-[200px]"
|
||||
><a href="mailto:{email}" title={email} class="truncate block"
|
||||
@@ -377,6 +378,26 @@
|
||||
><span title={login_type} class="truncate block">{login_type}</span
|
||||
></Cell
|
||||
>
|
||||
<Cell>
|
||||
<Toggle
|
||||
size="xs"
|
||||
checked={!disabled}
|
||||
on:change={async () => {
|
||||
try {
|
||||
await UserService.globalUserUpdate({
|
||||
email,
|
||||
requestBody: {
|
||||
disabled: !disabled
|
||||
}
|
||||
})
|
||||
sendUserToast(disabled ? 'User enabled' : 'User disabled')
|
||||
listUsers(activeOnly)
|
||||
} catch (e) {
|
||||
sendUserToast('Failed to update user', true)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Cell>
|
||||
{#if activeOnly}
|
||||
<Cell>
|
||||
{#if operator_only}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user