feat: add OAuth APIs with scoped permissions (#1542)

Co-authored-by: Alessandro (Ale) Segala <43508+ItalyPaleAle@users.noreply.github.com>
This commit is contained in:
Elias Schneider
2026-07-06 12:25:02 -07:00
committed by GitHub
co-authored by Alessandro Segala
parent 0b2706a488
commit 09d196f7c5
68 changed files with 3945 additions and 157 deletions
@@ -32,6 +32,7 @@
children,
onInput,
labelFor,
readonly = false,
inputClass,
...restProps
}: HTMLAttributes<HTMLDivElement> &
@@ -43,6 +44,7 @@
disabled?: boolean;
inputClass?: string;
type?: 'text' | 'password' | 'email' | 'number' | 'checkbox' | 'date' | 'url';
readonly?: boolean;
onInput?: (e: FormInputEvent) => void;
} = $props();
@@ -64,7 +66,7 @@
<FormattedMessage m={description} />
{#if docsLink}
<a
class="relative text-black after:absolute after:bottom-0 after:left-0 after:h-px after:w-full after:translate-y-[-1px] after:bg-white dark:text-white"
class="relative text-black after:absolute after:bottom-0 after:left-0 after:h-px after:w-full after:-translate-y-px after:bg-white dark:text-white"
href={docsLink}
target="_blank"
>
@@ -91,6 +93,7 @@
bind:value={input.value}
{disabled}
oninput={(e) => onInput?.(e)}
{readonly}
/>
{/if}
{/if}
+16 -3
View File
@@ -1,13 +1,19 @@
<script lang="ts">
import * as Item from '$lib/components/ui/item/index.js';
import { m } from '$lib/paraglide/messages';
import { LucideMail, LucideUser, LucideUsers } from '@lucide/svelte';
import type { InteractionScopeInfo } from '$lib/types/oidc.type';
import { LucideKeyRound, LucideMail, LucideUser, LucideUsers } from '@lucide/svelte';
import ScopeItem from './scope-item.svelte';
let { scopes }: { scopes: string[] } = $props();
let { scopes, scopeInfo = [] }: { scopes: string[]; scopeInfo?: InteractionScopeInfo[] } =
$props();
const standardScopes = ['openid', 'profile', 'email', 'groups', 'offline_access'];
const infoByKey = $derived(new Map(scopeInfo.map((info) => [info.key, info])));
const customScopes = $derived(scopes.filter((scope) => !standardScopes.includes(scope)));
</script>
<Item.Group data-testid="scopes">
<Item.Group data-testid="scopes" class="gap-1">
{#if scopes.includes('email')}
<ScopeItem icon={LucideMail} name={m.email()} description={m.view_your_email_address()} />
{/if}
@@ -25,4 +31,11 @@
description={m.view_the_groups_you_are_a_member_of()}
/>
{/if}
{#each customScopes as scope}
<ScopeItem
icon={LucideKeyRound}
name={infoByKey.get(scope)?.name ?? scope}
description={infoByKey.get(scope)?.description || m.access_an_api_on_your_behalf()}
/>
{/each}
</Item.Group>
@@ -13,7 +13,7 @@
<p
bind:this={ref}
data-slot="card-description"
class={cn('text-muted-foreground text-sm', className)}
class={cn('text-muted-foreground text-sm mt-3', className)}
{...restProps}
>
{@render children?.()}