feat: map allowed groups to OIDC clients (#202)

This commit is contained in:
Elias Schneider
2025-02-03 18:41:15 +01:00
committed by GitHub
parent 430421e98b
commit 13b02a072f
30 changed files with 518 additions and 218 deletions

View File

@@ -0,0 +1,75 @@
<script lang="ts">
import { cn } from '$lib/utils/style';
import { LucideChevronDown } from 'lucide-svelte';
import { onMount, type Snippet } from 'svelte';
import { slide } from 'svelte/transition';
import { Button } from './ui/button';
import * as Card from './ui/card';
let {
id,
title,
description,
defaultExpanded = false,
children
}: {
id: string;
title: string;
description?: string;
defaultExpanded?: boolean;
children: Snippet;
} = $props();
let expanded = $state(defaultExpanded);
function loadExpandedState() {
const state = JSON.parse(localStorage.getItem('collapsible-cards-expanded') || '{}');
expanded = state[id] || false;
}
function saveExpandedState() {
const state = JSON.parse(localStorage.getItem('collapsible-cards-expanded') || '{}');
state[id] = expanded;
localStorage.setItem('collapsible-cards-expanded', JSON.stringify(state));
}
function toggleExpanded() {
expanded = !expanded;
saveExpandedState();
}
onMount(() => {
if (defaultExpanded) {
saveExpandedState();
}
loadExpandedState();
});
</script>
<Card.Root>
<Card.Header class="cursor-pointer" onclick={toggleExpanded}>
<div class="flex items-center justify-between">
<div>
<Card.Title>{title}</Card.Title>
{#if description}
<Card.Description>{description}</Card.Description>
{/if}
</div>
<Button class="ml-10 h-8 p-3" variant="ghost" aria-label="Expand card">
<LucideChevronDown
class={cn(
'h-5 w-5 transition-transform duration-200',
expanded && 'rotate-180 transform'
)}
/>
</Button>
</div>
</Card.Header>
{#if expanded}
<div transition:slide={{ duration: 200 }}>
<Card.Content>
{@render children()}
</Card.Content>
</div>
{/if}
</Card.Root>

View File

@@ -8,6 +8,6 @@
export { className as class };
</script>
<p class={cn('text-sm text-muted-foreground', className)} {...$$restProps}>
<p class={cn('text-sm text-muted-foreground mt-1', className)} {...$$restProps}>
<slot />
</p>

View File

@@ -1,4 +1,9 @@
import type { AuthorizeResponse, OidcClient, OidcClientCreate } from '$lib/types/oidc.type';
import type {
AuthorizeResponse,
OidcClient,
OidcClientCreate,
OidcClientWithAllowedUserGroups
} from '$lib/types/oidc.type';
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
import APIService from './api-service';
@@ -23,24 +28,13 @@ class OidcService extends APIService {
return res.data as AuthorizeResponse;
}
async authorizeNewClient(
clientId: string,
scope: string,
callbackURL: string,
nonce?: string,
codeChallenge?: string,
codeChallengeMethod?: string
) {
const res = await this.api.post('/oidc/authorize/new-client', {
async isAuthorizationRequired(clientId: string, scope: string) {
const res = await this.api.post('/oidc/authorization-required', {
scope,
nonce,
callbackURL,
clientId,
codeChallenge,
codeChallengeMethod
clientId
});
return res.data as AuthorizeResponse;
return res.data.authorizationRequired as boolean;
}
async listClients(options?: SearchPaginationSortRequest) {
@@ -59,7 +53,7 @@ class OidcService extends APIService {
}
async getClient(id: string) {
return (await this.api.get(`/oidc/clients/${id}`)).data as OidcClient;
return (await this.api.get(`/oidc/clients/${id}`)).data as OidcClientWithAllowedUserGroups;
}
async updateClient(id: string, client: OidcClientCreate) {
@@ -88,6 +82,11 @@ class OidcService extends APIService {
async createClientSecret(id: string) {
return (await this.api.post(`/oidc/clients/${id}/secret`)).data.secret as string;
}
async updateAllowedUserGroups(id: string, userGroupIds: string[]) {
const res = await this.api.put(`/oidc/clients/${id}/allowed-user-groups`, { userGroupIds });
return res.data as OidcClientWithAllowedUserGroups;
}
}
export default OidcService;

View File

@@ -1,3 +1,5 @@
import type { UserGroup } from './user-group.type';
export type OidcClient = {
id: string;
name: string;
@@ -8,6 +10,10 @@ export type OidcClient = {
pkceEnabled: boolean;
};
export type OidcClientWithAllowedUserGroups = OidcClient & {
allowedUserGroups: UserGroup[];
};
export type OidcClientCreate = Omit<OidcClient, 'id' | 'logoURL' | 'hasLogo'>;
export type OidcClientCreateWithLogo = OidcClientCreate & {