feat: add ability to revoke passkeys of users as admin (#1386)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jose-d <7630424+jose-d@users.noreply.github.com>
Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com>
Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
jose_d
2026-04-12 18:29:42 +02:00
committed by GitHub
parent 544f4e63d8
commit 33cceeafa8
17 changed files with 265 additions and 40 deletions

View File

@@ -32,6 +32,12 @@
hidden: !isAdmin,
value: (item) => item.username ?? m.unknown()
},
{
label: m.actor(),
key: 'actorUsername',
hidden: !isAdmin,
value: (item) => item.actorUsername ?? m.unknown()
},
{
label: m.event(),
column: 'event',

View File

@@ -9,12 +9,14 @@
icon,
onRename,
onDelete,
showRenameAction = true,
label,
description
}: {
icon: typeof IconType;
onRename: () => void;
onRename?: () => void;
onDelete: () => void;
showRenameAction?: boolean;
description?: string;
label?: string;
} = $props();
@@ -36,22 +38,24 @@
{/if}
</Item.Content>
<Item.Actions>
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger>
<Button
onclick={onRename}
size="icon"
variant="ghost"
class="size-8"
aria-label={m.rename()}
>
<LucidePencil class="size-4" />
</Button>
</Tooltip.Trigger>
<Tooltip.Content>{m.rename()}</Tooltip.Content>
</Tooltip.Root>
</Tooltip.Provider>
{#if showRenameAction && onRename}
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger>
<Button
onclick={onRename}
size="icon"
variant="ghost"
class="size-8"
aria-label={m.rename()}
>
<LucidePencil class="size-4" />
</Button>
</Tooltip.Trigger>
<Tooltip.Content>{m.rename()}</Tooltip.Content>
</Tooltip.Root>
</Tooltip.Provider>
{/if}
<Tooltip.Provider>
<Tooltip.Root>

View File

@@ -1,5 +1,6 @@
import userStore from '$lib/stores/user-store';
import type { ListRequestOptions, Paginated } from '$lib/types/list-request.type';
import type { Passkey } from '$lib/types/passkey.type';
import type { SignupToken } from '$lib/types/signup-token.type';
import type { UserGroup } from '$lib/types/user-group.type';
import type { AccountUpdate, User, UserCreate, UserSignUp } from '$lib/types/user.type';
@@ -33,6 +34,11 @@ export default class UserService extends APIService {
return res.data as UserGroup[];
};
listUserPasskeys = async (userId: string) => {
const res = await this.api.get(`/users/${userId}/webauthn-credentials`);
return res.data as Passkey[];
};
update = async (id: string, user: UserCreate) => {
const res = await this.api.put(`/users/${id}`, user);
return res.data as User;
@@ -47,6 +53,10 @@ export default class UserService extends APIService {
await this.api.delete(`/users/${id}`);
};
removeUserPasskey = async (userId: string, passkeyId: string) => {
await this.api.delete(`/users/${userId}/webauthn-credentials/${passkeyId}`);
};
updateProfilePicture = async (userId: string, image: File) => {
const formData = new FormData();
formData.append('file', image!);

View File

@@ -7,6 +7,7 @@ export type AuditLog = {
device: string;
userId: string;
username?: string;
actorUsername?: string;
createdAt: string;
data: any;
};