From cf77354cdec1d4bbe12eb9a6aae976a3e7a5e58d Mon Sep 17 00:00:00 2001 From: Lewis Date: Wed, 18 Mar 2026 18:36:16 +0200 Subject: [PATCH] refactor(frontend): rewrite SecurityContent --- .../dashboard/SecurityContent.svelte | 1001 +++-------------- 1 file changed, 178 insertions(+), 823 deletions(-) diff --git a/frontend/src/components/dashboard/SecurityContent.svelte b/frontend/src/components/dashboard/SecurityContent.svelte index 8c95447..7d64527 100644 --- a/frontend/src/components/dashboard/SecurityContent.svelte +++ b/frontend/src/components/dashboard/SecurityContent.svelte @@ -1,6 +1,5 @@
- {#if loading} -
{$_('common.loading')}
- {:else} -
-

{$_('security.passkeys')}

+ passkeyCount = count} + /> - {#if !passkeysLoading} - {#if passkeys.length > 0} -
    - {#each passkeys as passkey} -
  • - {#if editingPasskeyId === passkey.id} -
    - - - -
    - {:else} -
    - {passkey.friendlyName || $_('security.unnamedPasskey')} - - {$_('security.added')} {formatDate(passkey.createdAt)} - {#if passkey.lastUsed} - - {$_('security.lastUsed')} {formatDate(passkey.lastUsed)} - {/if} - -
    -
    - - {#if hasPassword || passkeys.length > 1} - - {/if} -
    - {/if} + totpEnabled = enabled} + /> + + hasPassword = has} + onReauthRequired={handleReauthRequired} + /> + + {#if ssoProviders.length > 0} +
    +

    {$_('oauth.sso.linkedAccounts')}

    + + {#if linkedAccountsLoading} +
    {$_('common.loading')}
    + {:else} + {#if linkedAccounts.length > 0} +
      + {#each linkedAccounts as account} +
    • +
      + {account.provider_name} + {account.provider_username} + {$_('oauth.sso.linkedAt')} {formatDate(account.created_at)} +
      +
    • {/each}
    {:else} -
    {$_('security.noPasskeys')}
    +

    {$_('oauth.sso.noLinkedAccounts')}

    {/if} -
    - - -
    - - {/if} -
    - -
    -

    {$_('security.totp')}

    - - {#if totpSetup.step === 'idle'} - {#if totpEnabled} -
    {$_('security.totpEnabled')}
    - - {#if !showDisableForm && !showRegenForm} -
    - - -
    - {/if} - - {#if showRegenForm} -
    -

    {$_('security.regenerateBackupCodes')}

    -

    {$_('security.regenerateConfirm')}

    -
    - - -
    -
    - - -
    -
    - - -
    -
    - {/if} - - {#if showDisableForm} -
    -

    {$_('security.disableTotp')}

    -

    {$_('security.disableTotpWarning')}

    -
    - - -
    -
    - - -
    -
    - - -
    -
    - {/if} - {:else} -
    {$_('security.totpDisabled')}
    - - {/if} - {:else if totpSetup.step === 'qr'} - {@const qrData = totpSetup as TotpQr} -
    -

    {$_('security.totpSetupInstructions')}

    -
    - TOTP QR Code -
    -
    - {$_('security.cantScan')} - {qrData.totpUri.split('secret=')[1]?.split('&')[0] || ''} -
    - -
    - {:else if totpSetup.step === 'verify'} - {@const verifyData = totpSetup} -
    -

    {$_('security.totpCodePlaceholder')}

    -
    - -
    - - -
    -
    -
    - {:else if totpSetup.step === 'backup'} -
    -

    {$_('security.backupCodes')}

    -

    {$_('security.backupCodesDescription')}

    -
    - {#each totpSetup.backupCodes as code} - {code} {/each}
    -
    - - -
    -
    - {/if} -
    - -
    -

    {$_('security.password')}

    - {#if !passwordLoading} - {#if hasPassword} -
    {$_('security.passwordStatus')}
    - - {#if !showChangePasswordForm && !showRemovePasswordForm} -
    - - {#if passkeys.length > 0} - - {/if} -
    - {/if} - - {#if showChangePasswordForm} -
    -

    {$_('security.changePassword')}

    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - {/if} - - {#if showRemovePasswordForm} -
    -

    {$_('security.removePasswordWarning')}

    -
    - - -
    -
    - {/if} - {:else} -
    {$_('security.noPassword')}
    - - {#if !showSetPasswordForm} - - {:else} -
    -

    {$_('security.setPassword')}

    -
    - - -
    -
    - - -
    -
    - - -
    -
    - {/if} - {/if} - {/if} -
    - - {#if ssoProviders.length > 0} -
    -

    {$_('oauth.sso.linkedAccounts')}

    - - {#if linkedAccountsLoading} -
    {$_('common.loading')}
    - {:else} - {#if linkedAccounts.length > 0} -
      - {#each linkedAccounts as account} -
    • -
      - {account.provider_name} - {account.provider_username} - {$_('oauth.sso.linkedAt')} {formatDate(account.created_at)} -
      - -
    • - {/each} -
    - {:else} -

    {$_('oauth.sso.noLinkedAccounts')}

    - {/if} - -
    -

    {$_('oauth.sso.linkNewAccount')}

    -
    - {#each ssoProviders as provider} - {@const isLinked = linkedAccounts.some(a => a.provider === provider.provider)} - - {/each} -
    -
    - {/if} -
    - {/if} - - {#if hasMfa} -
    -

    {$_('security.appCompatibility')}

    -

    {$_('security.legacyLoginDescription')}

    - - {#if !legacyLoginLoading} -
    -
    - {$_('security.legacyLogin')} - - {#if allowLegacyLogin} - {$_('security.legacyLoginOn')} - {:else} - {$_('security.legacyLoginOff')} - {/if} - -
    - -
    - - {#if totpEnabled && allowLegacyLogin} -
    - {$_('security.legacyLoginWarning')} -
    - {/if} - -
    - {$_('security.legacyAppsTitle')} -

    {$_('security.legacyAppsDescription')}

    -
    - {/if} -
    - {/if} - -
    -

    {$_('security.trustedDevices')}

    -

    {$_('security.trustedDevicesDescription')}

    - - {#if trustedDevicesLoading} -
    {$_('common.loading')}
    - {:else if trustedDevices.length === 0} -

    {$_('trustedDevices.noDevices')}

    -

    {$_('trustedDevices.noDevicesHint')}

    - {:else} -
    - {#each trustedDevices as device} -
    -
    - {#if editingDeviceId === device.id} - -
    - - -
    - {:else} - {device.friendlyName || parseUserAgent(device.userAgent)} - - {/if} -
    - -
    - {#if device.userAgent} - {parseUserAgent(device.userAgent)} - {/if} - {#if device.trustedAt} - {$_('trustedDevices.trustedSince')} {formatDate(device.trustedAt)} - {/if} - {$_('trustedDevices.lastSeen')} {formatDate(device.lastSeenAt)} - {#if device.trustedUntil} - {@const daysRemaining = getDaysRemaining(device.trustedUntil)} - - {#if daysRemaining <= 0} - {$_('trustedDevices.expired')} - {:else if daysRemaining === 1} - {$_('trustedDevices.tomorrow')} - {:else} - {$_('trustedDevices.inDays', { values: { days: daysRemaining } })} - {/if} - - {/if} -
    - - -
    - {/each}
    {/if}
    {/if} + + {#if hasMfa} +
    +

    {$_('security.appCompatibility')}

    +

    {$_('security.legacyLoginDescription')}

    + + {#if !legacyLoginLoading} +
    +
    + {$_('security.legacyLogin')} + + {#if allowLegacyLogin} + {$_('security.legacyLoginOn')} + {:else} + {$_('security.legacyLoginOff')} + {/if} + +
    + +
    + + {#if totpEnabled && allowLegacyLogin} +
    + {$_('security.legacyLoginWarning')} +
    + {/if} + +
    + {$_('security.legacyAppsTitle')} +

    {$_('security.legacyAppsDescription')}

    +
    + {/if} +
    + {/if} + +
    +

    {$_('security.trustedDevices')}

    +

    {$_('security.trustedDevicesDescription')}

    + + {#if trustedDevicesLoading} +
    {$_('common.loading')}
    + {:else if trustedDevices.length === 0} +

    {$_('trustedDevices.noDevices')}

    +

    {$_('trustedDevices.noDevicesHint')}

    + {:else} +
    + {#each trustedDevices as device} +
    +
    + {#if editingDeviceId === device.id} + +
    + + +
    + {:else} + {device.friendlyName || parseUserAgent(device.userAgent)} + + {/if} +
    + +
    + {#if device.userAgent} + {parseUserAgent(device.userAgent)} + {/if} + {#if device.trustedAt} + {$_('trustedDevices.trustedSince')} {formatDate(device.trustedAt)} + {/if} + {$_('trustedDevices.lastSeen')} {formatDate(device.lastSeenAt)} + {#if device.trustedUntil} + {@const daysRemaining = getDaysRemaining(device.trustedUntil)} + + {#if daysRemaining <= 0} + {$_('trustedDevices.expired')} + {:else if daysRemaining === 1} + {$_('trustedDevices.tomorrow')} + {:else} + {$_('trustedDevices.inDays', { values: { days: daysRemaining } })} + {/if} + + {/if} +
    + + +
    + {/each} +
    + {/if} +