feat: add list instance emails endpoint and use Select in AddUser
Add a new GET /users/list_instance_emails endpoint that returns all instance user emails (from the password table). This endpoint is only available on non-cloud instances. In the frontend AddUser component, when the instance emails are available (non-cloud), replace the email text input with a Select component that allows both selecting from existing instance users and typing custom emails. Closes #7902 Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
This commit is contained in:
20
backend/.sqlx/query-21e9a9fc33dcdb66a2c8e95b1359ca1b3e04b4ecf155757abf5798834ebfd0ce.json
generated
Normal file
20
backend/.sqlx/query-21e9a9fc33dcdb66a2c8e95b1359ca1b3e04b4ecf155757abf5798834ebfd0ce.json
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT email FROM password ORDER BY email",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "email",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "21e9a9fc33dcdb66a2c8e95b1359ca1b3e04b4ecf155757abf5798834ebfd0ce"
|
||||
}
|
||||
@@ -86,6 +86,10 @@ pub fn global_service() -> Router {
|
||||
.route("/decline_invite", post(decline_invite))
|
||||
.route("/accept_invite", post(accept_invite))
|
||||
.route("/list_as_super_admin", get(list_users_as_super_admin))
|
||||
.route(
|
||||
"/list_instance_emails",
|
||||
get(list_instance_emails),
|
||||
)
|
||||
.route("/set_login_type/:user", post(set_login_type))
|
||||
.route("/update/:user", post(update_user))
|
||||
.route("/delete/:user", delete(delete_user))
|
||||
@@ -420,6 +424,21 @@ async fn list_users_as_super_admin(
|
||||
Ok(Json(rows))
|
||||
}
|
||||
|
||||
async fn list_instance_emails(
|
||||
_authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
) -> JsonResult<Vec<String>> {
|
||||
if *CLOUD_HOSTED {
|
||||
return Err(Error::BadRequest(
|
||||
"This endpoint is not available on cloud hosted instances".to_string(),
|
||||
));
|
||||
}
|
||||
let rows = sqlx::query_scalar!("SELECT email FROM password ORDER BY email")
|
||||
.fetch_all(&db)
|
||||
.await?;
|
||||
Ok(Json(rows))
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Progress {
|
||||
progress: u64,
|
||||
|
||||
@@ -2306,6 +2306,22 @@ paths:
|
||||
items:
|
||||
$ref: "#/components/schemas/GlobalUserInfo"
|
||||
|
||||
/users/list_instance_emails:
|
||||
get:
|
||||
summary: list all instance user emails (only on non-cloud instances)
|
||||
operationId: listInstanceEmails
|
||||
tags:
|
||||
- user
|
||||
responses:
|
||||
"200":
|
||||
description: list of instance user emails
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
/w/{workspace}/workspaces/list_pending_invites:
|
||||
get:
|
||||
summary: list pending invites for a workspace
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte'
|
||||
import { UserPlus } from 'lucide-svelte'
|
||||
import Select from './select/Select.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -31,6 +32,19 @@
|
||||
}
|
||||
getAutomateUsernameCreationSetting()
|
||||
|
||||
let instanceEmails: { label: string; value: string }[] | undefined = $state(undefined)
|
||||
|
||||
async function loadInstanceEmails() {
|
||||
if (isCloudHosted()) return
|
||||
try {
|
||||
const emails = await UserService.listInstanceEmails()
|
||||
instanceEmails = emails.map((e) => ({ label: e, value: e }))
|
||||
} catch {
|
||||
instanceEmails = undefined
|
||||
}
|
||||
}
|
||||
loadInstanceEmails()
|
||||
|
||||
async function addUser() {
|
||||
await WorkspaceService.addUser({
|
||||
workspace: $workspaceStore!,
|
||||
@@ -84,7 +98,25 @@
|
||||
<span class="text-sm mb-2 leading-6 font-semibold">Add a new user</span>
|
||||
|
||||
<span class="text-xs mb-1 leading-6">Email</span>
|
||||
<input type="email mb-1" onkeyup={handleKeyUp} placeholder="email" bind:value={email} />
|
||||
{#if instanceEmails}
|
||||
<Select
|
||||
items={instanceEmails}
|
||||
bind:value={email}
|
||||
placeholder="Select or type an email"
|
||||
createText="Use custom email:"
|
||||
onCreateItem={(v) => {
|
||||
email = v
|
||||
}}
|
||||
disablePortal={true}
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
type="email"
|
||||
onkeyup={handleKeyUp}
|
||||
placeholder="email"
|
||||
bind:value={email}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if !automateUsernameCreation}
|
||||
<span class="text-xs mb-1 pt-2 leading-6">Username</span>
|
||||
|
||||
Reference in New Issue
Block a user