mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-19 15:54:27 +02:00
fix(oidc): use preferred_username/name claim for auto-created username When auto-creating an OIDC user without a valid email claim, derive the username from preferred_username or name IdP claims instead of falling back to the opaque provider_sub[:30].
This commit is contained in:
@@ -3,7 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { Plus, Edit2, Trash2, Globe, Check, X, RefreshCw, ExternalLink } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { api } from '../api/client';
|
||||
import type { OIDCProvider, OIDCProviderCreate } from '../api/client';
|
||||
import type { Group, OIDCProvider, OIDCProviderCreate } from '../api/client';
|
||||
import { Card, CardContent, CardHeader } from './Card';
|
||||
import { Button } from './Button';
|
||||
import { Toggle } from './Toggle';
|
||||
@@ -22,18 +22,21 @@ const EMPTY_FORM: OIDCProviderCreate = {
|
||||
email_claim: 'email',
|
||||
require_email_verified: true,
|
||||
icon_url: undefined,
|
||||
default_group_id: null,
|
||||
};
|
||||
|
||||
// ─── Provider form (create / edit) ───────────────────────────────────────────
|
||||
function ProviderForm({
|
||||
initial,
|
||||
isEdit = false,
|
||||
groups = [],
|
||||
onSave,
|
||||
onCancel,
|
||||
isPending,
|
||||
}: {
|
||||
initial: OIDCProviderCreate;
|
||||
isEdit?: boolean;
|
||||
groups?: Group[];
|
||||
onSave: (data: OIDCProviderCreate) => void;
|
||||
onCancel: () => void;
|
||||
isPending: boolean;
|
||||
@@ -157,6 +160,21 @@ function ProviderForm({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className={labelCls}>{t('settings.oidc.form.defaultGroup')}</label>
|
||||
<select
|
||||
className={inputCls}
|
||||
value={form.default_group_id ?? ''}
|
||||
onChange={(e) => set('default_group_id', e.target.value ? Number(e.target.value) : null)}
|
||||
>
|
||||
<option value="">{t('settings.oidc.form.defaultGroupViewersFallback')}</option>
|
||||
{groups.map((g) => (
|
||||
<option key={g.id} value={g.id}>{g.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="text-bambu-gray text-xs mt-1">{t('settings.oidc.form.defaultGroupDesc')}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3 pt-2">
|
||||
<Button variant="secondary" onClick={onCancel} className="flex-1">
|
||||
{t('common.cancel')}
|
||||
@@ -189,6 +207,11 @@ export function OIDCProviderSettings() {
|
||||
queryFn: () => api.getOIDCProvidersAll(),
|
||||
});
|
||||
|
||||
const { data: groups = [] } = useQuery({
|
||||
queryKey: ['groups'],
|
||||
queryFn: () => api.getGroups(),
|
||||
});
|
||||
|
||||
const createMutation = useMutation({
|
||||
mutationFn: (data: OIDCProviderCreate) => api.createOIDCProvider(data),
|
||||
onSuccess: () => {
|
||||
@@ -256,6 +279,7 @@ export function OIDCProviderSettings() {
|
||||
<h4 className="text-white font-medium mb-4">{t('settings.oidc.newProvider')}</h4>
|
||||
<ProviderForm
|
||||
initial={EMPTY_FORM}
|
||||
groups={groups}
|
||||
onSave={(data) => createMutation.mutate(data)}
|
||||
onCancel={() => setShowCreate(false)}
|
||||
isPending={createMutation.isPending}
|
||||
@@ -335,6 +359,7 @@ export function OIDCProviderSettings() {
|
||||
<div className="border-t border-bambu-dark-tertiary pt-4">
|
||||
<ProviderForm
|
||||
isEdit={true}
|
||||
groups={groups}
|
||||
initial={{
|
||||
name: provider.name,
|
||||
issuer_url: provider.issuer_url,
|
||||
@@ -347,6 +372,7 @@ export function OIDCProviderSettings() {
|
||||
email_claim: provider.email_claim,
|
||||
require_email_verified: provider.require_email_verified,
|
||||
icon_url: provider.icon_url ?? undefined,
|
||||
default_group_id: provider.default_group_id ?? null,
|
||||
}}
|
||||
onSave={(data) => updateMutation.mutate({ id: provider.id, data })}
|
||||
onCancel={() => setEditingId(null)}
|
||||
@@ -389,6 +415,14 @@ export function OIDCProviderSettings() {
|
||||
{provider.require_email_verified ? t('common.yes') : t('common.no')}
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt className="text-bambu-gray">{t('settings.oidc.form.defaultGroup')}</dt>
|
||||
<dd className="text-white">
|
||||
{provider.default_group_id
|
||||
? (groups.find((g) => g.id === provider.default_group_id)?.name ?? t('settings.oidc.form.defaultGroupViewersFallback'))
|
||||
: t('settings.oidc.form.defaultGroupViewersFallback')}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</CardContent>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user