Frontend: domain dialog fixes and dead-code removal
- Empty-origins default shows as a '*' placeholder row that is not persisted unless edited (open+save no longer tightens any-scheme to https-only) - Foreign wildcards are flagged invalid instead of being classified as related origins; over-cap related list disables Save - Single-label rp-ids accepted (matching backend validate_rp_id) - Auth-host mark follows row edits; row menu state resets on dialog close - rp-id/origin keys lowercased for classification and submit - settings cache: stale in-flight responses no longer overwrite a forced refresh - Remove the dead oidc-edit dialog path and other unused code; fix stale comments (realm→domain, '*' semantics, per-domain discovery URLs)
This commit is contained in:
@@ -17,7 +17,7 @@ import { apiJson, SessionValidator, settings as paskiaSettings } from 'paskia'
|
||||
import { updateThemeFromSession } from '@/utils/theme'
|
||||
import { uuidv7 } from 'uuidv7'
|
||||
import { getDirection } from '@/utils/keynav'
|
||||
import { goBack, originDisplayEntries } from '@/utils/helpers'
|
||||
import { originDisplayEntries } from '@/utils/helpers'
|
||||
|
||||
const info = ref(null)
|
||||
const loading = ref(true)
|
||||
@@ -465,10 +465,6 @@ function resetOidcSecret(clientId) {
|
||||
if (editingOidcClient.value?.client_id === clientId) {
|
||||
editingOidcClient.value = { ...editingOidcClient.value, client_secret }
|
||||
}
|
||||
// Also update dialog if open (for backwards compatibility)
|
||||
if (dialog.value.type === 'oidc-edit' && dialog.value.data?.client_id === clientId) {
|
||||
dialog.value.data.client_secret = client_secret
|
||||
}
|
||||
}
|
||||
|
||||
function createPermissionForClient(clientId) {
|
||||
@@ -483,14 +479,15 @@ function createDomain() {
|
||||
auth_host: '',
|
||||
origins: [],
|
||||
originValidation: [],
|
||||
originPlaceholders: [],
|
||||
wellKnownCheck: null,
|
||||
})
|
||||
}
|
||||
|
||||
function openDomain(domain) {
|
||||
// One combined list for editing, in display order: in-domain sites and
|
||||
// related origins, classified by hostname. The default is always shown
|
||||
// explicitly as the '*' entry.
|
||||
// related origins, classified by hostname. An empty origins object shows
|
||||
// as a '*' placeholder row, omitted again on submit unless edited.
|
||||
const rows = originDisplayEntries(domain)
|
||||
openDialog('domain-edit', {
|
||||
isNew: false,
|
||||
@@ -499,6 +496,7 @@ function openDomain(domain) {
|
||||
auth_host: rows.find(r => r.auth)?.key || '',
|
||||
origins: rows.map(r => r.key),
|
||||
originValidation: rows.map(() => null),
|
||||
originPlaceholders: rows.map(r => !!r.placeholder),
|
||||
wellKnownCheck: null,
|
||||
})
|
||||
}
|
||||
@@ -910,49 +908,27 @@ async function submitDialog() {
|
||||
authStore.showMessage(e.message || 'Failed to create permission', 'error')
|
||||
})
|
||||
return // Don't call closeDialog() again
|
||||
} else if (t === 'oidc-edit') {
|
||||
const { client_id, client_secret, isNew } = dialog.value.data
|
||||
const name = dialog.value.data.name?.trim()
|
||||
const uris = dialog.value.data.redirect_uris?.trim()
|
||||
if (!name) throw new Error('Client name required')
|
||||
|
||||
const redirect_uris = uris ? uris.split('\n').map(u => u.trim()).filter(u => u) : []
|
||||
|
||||
// Close dialog immediately, then perform async operation
|
||||
closeDialog()
|
||||
|
||||
const req = client_secret
|
||||
? sha256Hex(client_secret).then(secret_hash => isNew
|
||||
? apiJson('/auth/api/admin/oidc-clients', { method: 'POST', body: { client_id, secret_hash, name, redirect_uris } })
|
||||
: apiJson(`/auth/api/admin/oidc-clients/${client_id}`, { method: 'PATCH', body: { name, redirect_uris, secret_hash } }))
|
||||
: apiJson(`/auth/api/admin/oidc-clients/${client_id}`, { method: 'PATCH', body: { name, redirect_uris } })
|
||||
req
|
||||
.then(() => {
|
||||
authStore.showMessage(`OIDC client "${name}" ${isNew ? 'created' : 'updated'}.`, 'success', 2500)
|
||||
loadAdminData()
|
||||
})
|
||||
.catch(e => {
|
||||
authStore.showMessage(e.message || `Failed to ${isNew ? 'create' : 'update'} OIDC client`, 'error')
|
||||
})
|
||||
return // Don't call closeDialog() again
|
||||
} else if (t === 'domain-edit') {
|
||||
const d = dialog.value.data
|
||||
const rp_id = d.rp_id?.trim().toLowerCase()
|
||||
if (!rp_id) throw new Error('Domain (rp-id) required')
|
||||
const rp_name = d.rp_name?.trim() || ''
|
||||
const auth_host = d.auth_host?.trim() || ''
|
||||
const auth_host = d.auth_host?.trim().toLowerCase() || ''
|
||||
// The combined origins list is split by hostname: entries on the
|
||||
// rp-id domain form the in-domain origins object (the auth host
|
||||
// entry is marked), entries elsewhere are related origins (ROR).
|
||||
// Wildcards ('*.app.example.com') classify by their base domain.
|
||||
// Keys are stored without the https:// scheme.
|
||||
const keyOf = o => o.replace(/^https:\/\//, '').replace(/\/+$/, '')
|
||||
// Keys are stored lowercased, without the https:// scheme.
|
||||
const keyOf = o => o.replace(/^https:\/\//i, '').replace(/\/+$/, '').toLowerCase()
|
||||
const origins = {}
|
||||
const related = {}
|
||||
for (const o of (d.origins || []).map(o => o.trim()).filter(o => o)) {
|
||||
const key = keyOf(o)
|
||||
for (const [i, o] of (d.origins || []).entries()) {
|
||||
const key = keyOf(o.trim())
|
||||
// An untouched placeholder row only displays the empty-origins
|
||||
// default (any scheme in-domain) — don't persist it as '*'
|
||||
if (!key || d.originPlaceholders?.[i]) continue
|
||||
if (key === '*') {
|
||||
origins['*'] = true // anything in-domain, any scheme/port
|
||||
origins['*'] = true // shorthand for '*.{rp-id}' (https-only outside localhost)
|
||||
continue
|
||||
}
|
||||
let hn = null
|
||||
@@ -1119,8 +1095,6 @@ async function submitDialog() {
|
||||
:permission-id-pattern="PERMISSION_ID_PATTERN"
|
||||
@submit-dialog="submitDialog"
|
||||
@close-dialog="closeDialog"
|
||||
@reset-oidc-secret="resetOidcSecret"
|
||||
@create-permission-for-client="createPermissionForClient"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user