Browse Source

feat(frontend): add auto-link existing accounts toggle to OIDC provider settings (#973)

Exposes the backend auto_link_existing_accounts field in the OIDC provider
form, edit view, and info display. Adds translations for all 7 supported
locales (en, de, fr, it, pt-BR, zh-CN, ja).
Sn0rrii 1 month ago
parent
commit
eba5a2924a

+ 2 - 0
frontend/src/api/client.ts

@@ -2465,6 +2465,7 @@ export interface OIDCProvider {
   scopes: string;
   scopes: string;
   is_enabled: boolean;
   is_enabled: boolean;
   auto_create_users: boolean;
   auto_create_users: boolean;
+  auto_link_existing_accounts: boolean;
   icon_url?: string | null;
   icon_url?: string | null;
 }
 }
 
 
@@ -2476,6 +2477,7 @@ export interface OIDCProviderCreate {
   scopes?: string;
   scopes?: string;
   is_enabled?: boolean;
   is_enabled?: boolean;
   auto_create_users?: boolean;
   auto_create_users?: boolean;
+  auto_link_existing_accounts?: boolean;
   icon_url?: string | null;
   icon_url?: string | null;
 }
 }
 
 

+ 15 - 0
frontend/src/components/OIDCProviderSettings.tsx

@@ -18,6 +18,7 @@ const EMPTY_FORM: OIDCProviderCreate = {
   scopes: 'openid email profile',
   scopes: 'openid email profile',
   is_enabled: true,
   is_enabled: true,
   auto_create_users: false,
   auto_create_users: false,
+  auto_link_existing_accounts: false,
   icon_url: undefined,
   icon_url: undefined,
 };
 };
 
 
@@ -107,6 +108,13 @@ function ProviderForm({
             <p className="text-bambu-gray text-xs">{t('settings.oidc.form.autoCreateDesc')}</p>
             <p className="text-bambu-gray text-xs">{t('settings.oidc.form.autoCreateDesc')}</p>
           </div>
           </div>
         </label>
         </label>
+        <label className="flex items-center gap-3 cursor-pointer">
+          <Toggle checked={form.auto_link_existing_accounts ?? false} onChange={(v) => set('auto_link_existing_accounts', v)} />
+          <div>
+            <p className="text-white text-sm">{t('settings.oidc.form.autoLink')}</p>
+            <p className="text-bambu-gray text-xs">{t('settings.oidc.form.autoLinkDesc')}</p>
+          </div>
+        </label>
       </div>
       </div>
 
 
       <div className="flex gap-3 pt-2">
       <div className="flex gap-3 pt-2">
@@ -295,6 +303,7 @@ export function OIDCProviderSettings() {
                     scopes: provider.scopes,
                     scopes: provider.scopes,
                     is_enabled: provider.is_enabled,
                     is_enabled: provider.is_enabled,
                     auto_create_users: provider.auto_create_users,
                     auto_create_users: provider.auto_create_users,
+                    auto_link_existing_accounts: provider.auto_link_existing_accounts,
                     icon_url: provider.icon_url ?? undefined,
                     icon_url: provider.icon_url ?? undefined,
                   }}
                   }}
                   onSave={(data) => updateMutation.mutate({ id: provider.id, data })}
                   onSave={(data) => updateMutation.mutate({ id: provider.id, data })}
@@ -322,6 +331,12 @@ export function OIDCProviderSettings() {
                     {provider.auto_create_users ? t('common.yes') : t('common.no')}
                     {provider.auto_create_users ? t('common.yes') : t('common.no')}
                   </dd>
                   </dd>
                 </div>
                 </div>
+                <div>
+                  <dt className="text-bambu-gray">{t('settings.oidc.form.autoLink')}</dt>
+                  <dd className={provider.auto_link_existing_accounts ? 'text-green-400' : 'text-bambu-gray'}>
+                    {provider.auto_link_existing_accounts ? t('common.yes') : t('common.no')}
+                  </dd>
+                </div>
               </dl>
               </dl>
             </CardContent>
             </CardContent>
           )}
           )}

+ 2 - 0
frontend/src/i18n/locales/de.ts

@@ -2146,6 +2146,8 @@ export default {
         enabled: 'Aktiviert',
         enabled: 'Aktiviert',
         autoCreate: 'Benutzer automatisch anlegen',
         autoCreate: 'Benutzer automatisch anlegen',
         autoCreateDesc: 'Erstellt beim ersten Login automatisch ein lokales Konto.',
         autoCreateDesc: 'Erstellt beim ersten Login automatisch ein lokales Konto.',
+        autoLink: 'Bestehende Konten automatisch verknüpfen',
+        autoLinkDesc: 'Verknüpft beim ersten Login vorhandene lokale Konten anhand der E-Mail-Adresse.',
         secretHint: 'leer lassen zum Beibehalten',
         secretHint: 'leer lassen zum Beibehalten',
         secretPlaceholder: 'neues Secret',
         secretPlaceholder: 'neues Secret',
       },
       },

+ 2 - 0
frontend/src/i18n/locales/en.ts

@@ -2167,6 +2167,8 @@ export default {
         enabled: 'Enabled',
         enabled: 'Enabled',
         autoCreate: 'Auto-create users',
         autoCreate: 'Auto-create users',
         autoCreateDesc: 'Automatically create a local account on first login.',
         autoCreateDesc: 'Automatically create a local account on first login.',
+        autoLink: 'Auto-link existing accounts',
+        autoLinkDesc: 'Link existing local accounts by matching email on first login.',
         secretHint: 'leave blank to keep current',
         secretHint: 'leave blank to keep current',
         secretPlaceholder: 'new secret',
         secretPlaceholder: 'new secret',
       },
       },

+ 2 - 0
frontend/src/i18n/locales/fr.ts

@@ -2107,6 +2107,8 @@ export default {
         enabled: 'Activé',
         enabled: 'Activé',
         autoCreate: 'Créer les utilisateurs automatiquement',
         autoCreate: 'Créer les utilisateurs automatiquement',
         autoCreateDesc: 'Crée automatiquement un compte local lors de la première connexion.',
         autoCreateDesc: 'Crée automatiquement un compte local lors de la première connexion.',
+        autoLink: 'Lier automatiquement les comptes existants',
+        autoLinkDesc: 'Lie les comptes locaux existants par e-mail lors de la première connexion.',
         secretHint: 'laisser vide pour conserver',
         secretHint: 'laisser vide pour conserver',
         secretPlaceholder: 'nouveau secret',
         secretPlaceholder: 'nouveau secret',
       },
       },

+ 2 - 0
frontend/src/i18n/locales/it.ts

@@ -2106,6 +2106,8 @@ export default {
         enabled: 'Abilitato',
         enabled: 'Abilitato',
         autoCreate: 'Crea utenti automaticamente',
         autoCreate: 'Crea utenti automaticamente',
         autoCreateDesc: 'Crea automaticamente un account locale al primo accesso.',
         autoCreateDesc: 'Crea automaticamente un account locale al primo accesso.',
+        autoLink: 'Collega automaticamente gli account esistenti',
+        autoLinkDesc: 'Collega gli account locali esistenti tramite email al primo accesso.',
         secretHint: 'lascia vuoto per mantenere',
         secretHint: 'lascia vuoto per mantenere',
         secretPlaceholder: 'nuovo segreto',
         secretPlaceholder: 'nuovo segreto',
       },
       },

+ 2 - 0
frontend/src/i18n/locales/ja.ts

@@ -2145,6 +2145,8 @@ export default {
         enabled: '有効',
         enabled: '有効',
         autoCreate: 'ユーザーを自動作成',
         autoCreate: 'ユーザーを自動作成',
         autoCreateDesc: '初回ログイン時にローカルアカウントを自動的に作成します。',
         autoCreateDesc: '初回ログイン時にローカルアカウントを自動的に作成します。',
+        autoLink: '既存アカウントを自動リンク',
+        autoLinkDesc: '初回ログイン時にメールアドレスで既存のローカルアカウントにリンクします。',
         secretHint: '空白のままで現在のものを維持',
         secretHint: '空白のままで現在のものを維持',
         secretPlaceholder: '新しいシークレット',
         secretPlaceholder: '新しいシークレット',
       },
       },

+ 2 - 0
frontend/src/i18n/locales/pt-BR.ts

@@ -2106,6 +2106,8 @@ export default {
         enabled: 'Ativado',
         enabled: 'Ativado',
         autoCreate: 'Criar usuários automaticamente',
         autoCreate: 'Criar usuários automaticamente',
         autoCreateDesc: 'Cria automaticamente uma conta local no primeiro login.',
         autoCreateDesc: 'Cria automaticamente uma conta local no primeiro login.',
+        autoLink: 'Vincular contas existentes automaticamente',
+        autoLinkDesc: 'Vincula contas locais existentes por e-mail no primeiro login.',
         secretHint: 'deixe em branco para manter',
         secretHint: 'deixe em branco para manter',
         secretPlaceholder: 'novo segredo',
         secretPlaceholder: 'novo segredo',
       },
       },

+ 2 - 0
frontend/src/i18n/locales/zh-CN.ts

@@ -2106,6 +2106,8 @@ export default {
         enabled: '已启用',
         enabled: '已启用',
         autoCreate: '自动创建用户',
         autoCreate: '自动创建用户',
         autoCreateDesc: '首次登录时自动创建本地账户。',
         autoCreateDesc: '首次登录时自动创建本地账户。',
+        autoLink: '自动关联已有账户',
+        autoLinkDesc: '首次登录时通过邮箱匹配现有本地账户并自动关联。',
         secretHint: '留空以保留当前',
         secretHint: '留空以保留当前',
         secretPlaceholder: '新密钥',
         secretPlaceholder: '新密钥',
       },
       },