(x.email ?? '') + ' ' + (x.name ?? '') + ' ' + (x.company ?? '') + ' ' + (x.username ?? '') + ' ' + (x.workspace_id ?? '')} />
{#if showHeaderInfo}
Windmill
{#if $workspaceStore !== 'admins'}
{/if} {/if}
{#if !yamlMode}
{#if $workspaceStore !== 'admins'} {/if}
{/if}
{#if tab === 'ai' && !yamlMode} {:else if tab === 'users' && !yamlMode}
{#if !automateUsernameCreation && !isCloudHosted()}

Automatic username creation

Automatically create a username for new users based on their email, shared across workspaces. Learn more
{ automateUsernameModalOpen = false enableAutomateUsernameCreationSetting() }} on:canceled={() => (automateUsernameModalOpen = false)} title="Automatic username creation" confirmationText="Enable" > Once activated, it will not be possible to disable this feature. In case existing users have different usernames in different workspaces, you will have to manually confirm the username for each user.
{/if} {#if extJwtTokens.length > 0} {/if} {#if usersListShown}
{#snippet trigger()} {/snippet} {#snippet content()} listUsers(activeOnly)} /> {/snippet}

{filteredUsers.length} user{filteredUsers.length !== 1 ? 's' : ''} found

Email {#if automateUsernameCreation} Username {/if} Name Auth {#if activeOnly} Kind {/if} Role Actions {#if filteredUsers && users} {#each filteredUsers.slice(0, nbDisplayed) as { email, super_admin, devops, login_type, name, username, operator_only, is_workspace_admin, role_source, disabled, workspace_id }, i (email + '::' + (workspace_id ?? ''))} {@const isServiceAccount = login_type === 'service_account'} {@const groupRole = role_source === 'instance_group' && (super_admin || devops)} {@const groupRoleTooltip = 'Role is set by an instance group. Superadmin and Devops can be set here, but demoting to User requires removing the user from the group.'} {@const serviceAccountTooltip = 'Service accounts are always users in the instance. Their workspace role is managed in the workspace user settings.'}
{#if isServiceAccount} {email} {:else} {email} {/if} {#if disabled} Disabled {/if}
{#if automateUsernameCreation} {#if username} {username} {:else} {#key filteredUsers.map((u) => u.username).join()} { listUsers(activeOnly) }} /> {/key} {/if} {/if} {truncate(name ?? '', 30)} {login_type} {#if activeOnly} {#if is_workspace_admin} Admin {:else if operator_only} Operator only {:else} Developer {/if} {/if}
{#key `${super_admin}_${devops}_${role_source}`} { if (email == $userStore?.email) { sendUserToast('You cannot demote yourself', true) listUsers(activeOnly) return } let role = e.detail if (role === 'super_admin') { await UserService.globalUserUpdate({ email, requestBody: { is_super_admin: true, is_devops: false } }) } if (role === 'devops') { await UserService.globalUserUpdate({ email, requestBody: { is_super_admin: false, is_devops: true } }) } if (role === 'user') { await UserService.globalUserUpdate({ email, requestBody: { is_super_admin: false, is_devops: false } }) } sendUserToast('User updated') listUsers(activeOnly) }} > {#snippet children({ item })} {/snippet} {/key} {#if isServiceAccount} {is_workspace_admin ? 'Admin' : operator_only ? 'Operator' : 'Developer'} in {#if workspace_id} closeDrawer?.()} >{truncate(workspace_id, 20)} {:else} its workspace {/if} {:else if groupRole} closeDrawer?.()} > Set by instance group {/if}
{#if isServiceAccount} {#if workspace_id} closeDrawer?.(), href: `/workspace_settings?tab=users&workspace=${workspace_id}` } ]} /> {/if} {:else} { const btn = editWrappers[email]?.querySelector( '[aria-label="Popup button"]' ) 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: 'Reassign', icon: ArrowRightLeft, action: () => { offboardingEmail = email offboardingReassignOnly = true } }, { displayName: 'Remove', icon: UserMinus, type: 'delete', action: () => { offboardingEmail = email offboardingReassignOnly = false } } ]} /> {/if}
{/each} {#if filteredUsers.length > nbDisplayed} {@const remaining = Math.min(50, filteredUsers.length - nbDisplayed)} {/if} {/if}
{:else if usersSubTab === 'ext_jwt'} loadExtJwtPage(Math.floor(extJwtTokens.length / extJwtPerPage) + 1)} onActiveOnlyChange={(v) => { extJwtActiveOnly = v loadExtJwtPage(1) }} /> {:else if usersSubTab === 'guests' && !guestList} {#if guestLoading} {:else} {/if} {:else if usersSubTab === 'guests' && guestList} loadGuestPage(Math.floor((guestList?.guests.length ?? 0) / guestPerPage) + 1)} onInstanceSwitch={() => loadGuestPage(1)} /> {/if}
{:else} { const targetTab = categoryToTabMap[category] if (targetTab) { handleNavigate(targetTab) } }} /> {/if}
{#if offboardingEmail} { offboardingEmail = undefined }} onComplete={() => { offboardingEmail = undefined listUsers(activeOnly) }} /> {/if} { disableConfirmedCallback = undefined listUsers(activeOnly) }} on:confirmed={() => { if (disableConfirmedCallback) { disableConfirmedCallback() } disableConfirmedCallback = undefined }} >
Are you sure you want to disable {disableUserEmail}? 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.