Renamed OIDC permissions claim to more commonly used groups. Move jwtk to a more convenient location. Draft admin app OIDC client configuratioon.
This commit is contained in:
@@ -24,6 +24,7 @@ const showBackMessage = ref(false)
|
||||
const error = ref(null)
|
||||
const orgs = ref([])
|
||||
const permissions = ref([])
|
||||
const oidcClients = ref([])
|
||||
const currentOrgId = ref(null) // UUID of selected org for detail view
|
||||
const currentUserId = ref(null) // UUID for user detail view
|
||||
const userDetail = ref(null) // cached user detail object
|
||||
@@ -143,6 +144,24 @@ async function loadPermissions() {
|
||||
permissions.value = await apiJson('/auth/api/admin/permissions')
|
||||
}
|
||||
|
||||
async function loadOidcClients() {
|
||||
// Only master admins can view OIDC clients
|
||||
if (!isMasterAdmin.value) {
|
||||
oidcClients.value = []
|
||||
return
|
||||
}
|
||||
try {
|
||||
oidcClients.value = await apiJson('/auth/api/admin/oidc-clients')
|
||||
} catch (e) {
|
||||
// If 403, user is not master admin - silently skip
|
||||
if (e.message?.includes('403') || e.message?.includes('Forbidden')) {
|
||||
oidcClients.value = []
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUserInfo() {
|
||||
const data = await apiJson('/auth/api/validate', { method: 'POST' })
|
||||
info.value = data
|
||||
@@ -153,6 +172,7 @@ function clearSensitiveState() {
|
||||
info.value = null
|
||||
orgs.value = []
|
||||
permissions.value = []
|
||||
oidcClients.value = []
|
||||
userDetail.value = null
|
||||
authenticated.value = false
|
||||
}
|
||||
@@ -181,6 +201,8 @@ async function load() {
|
||||
await Promise.all([loadOrgs(), loadPermissions()])
|
||||
// If we get here, user has admin access - now fetch user info for display
|
||||
await loadUserInfo()
|
||||
// Load OIDC clients after authentication (master admin only)
|
||||
await loadOidcClients()
|
||||
|
||||
if (!isMasterAdmin.value && isOrgAdmin.value && orgs.value.length === 1) {
|
||||
if (!window.location.hash || window.location.hash === '#overview') {
|
||||
@@ -383,6 +405,34 @@ function deletePermission(p) {
|
||||
} })
|
||||
}
|
||||
|
||||
// OIDC Client actions
|
||||
function createOidcClient() {
|
||||
openDialog('oidc-create', { name: '', redirect_uris: '' })
|
||||
}
|
||||
|
||||
function editOidcClient(client) {
|
||||
openDialog('oidc-edit', {
|
||||
client,
|
||||
name: client.name,
|
||||
redirect_uris: client.redirect_uris.join('\n')
|
||||
})
|
||||
}
|
||||
|
||||
function deleteOidcClient(client) {
|
||||
openDialog('confirm', {
|
||||
message: `Delete OIDC client "${client.name}"? This will break any applications using this client.`,
|
||||
action: async () => {
|
||||
await performOidcClientDeletion(client.uuid, client.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function performOidcClientDeletion(clientUuid, clientName) {
|
||||
await apiJson(`/auth/api/admin/oidc-clients/${clientUuid}`, { method: 'DELETE' })
|
||||
authStore.showMessage(`OIDC client "${clientName}" deleted.`, 'success', 2500)
|
||||
await loadOidcClients()
|
||||
}
|
||||
|
||||
const selectedOrg = computed(() => orgs.value.find(o => o.uuid === currentOrgId.value) || null)
|
||||
|
||||
function openOrg(o) {
|
||||
@@ -721,6 +771,59 @@ async function submitDialog() {
|
||||
authStore.showMessage(e.message || 'Failed to create permission', 'error')
|
||||
})
|
||||
return // Don't call closeDialog() again
|
||||
} else if (t === 'oidc-create') {
|
||||
const name = dialog.value.data.name?.trim()
|
||||
const uris = dialog.value.data.redirect_uris?.trim()
|
||||
if (!name) throw new Error('Client name required')
|
||||
if (!uris) throw new Error('Redirect URIs required')
|
||||
|
||||
const redirect_uris = uris.split('\n').map(u => u.trim()).filter(u => u)
|
||||
if (redirect_uris.length === 0) throw new Error('At least one redirect URI required')
|
||||
|
||||
// Close dialog immediately, then perform async operation
|
||||
closeDialog()
|
||||
apiJson('/auth/api/admin/oidc-clients', { method: 'POST', body: { name, redirect_uris } })
|
||||
.then((result) => {
|
||||
// Show success dialog with client credentials
|
||||
openDialog('oidc-created', {
|
||||
client_id: result.client_id,
|
||||
client_secret: result.client_secret
|
||||
})
|
||||
loadOidcClients()
|
||||
})
|
||||
.catch(e => {
|
||||
authStore.showMessage(e.message || 'Failed to create OIDC client', 'error')
|
||||
})
|
||||
return // Don't call closeDialog() again
|
||||
} else if (t === 'oidc-edit') {
|
||||
const { client } = 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')
|
||||
if (!uris) throw new Error('Redirect URIs required')
|
||||
|
||||
const redirect_uris = uris.split('\n').map(u => u.trim()).filter(u => u)
|
||||
if (redirect_uris.length === 0) throw new Error('At least one redirect URI required')
|
||||
|
||||
// Close dialog immediately, then perform async operation
|
||||
closeDialog()
|
||||
|
||||
// Check if anything changed
|
||||
const oldUris = [...client.redirect_uris].sort().join('\n')
|
||||
const newUris = [...redirect_uris].sort().join('\n')
|
||||
if (name === client.name && oldUris === newUris) {
|
||||
return // No changes
|
||||
}
|
||||
|
||||
apiJson(`/auth/api/admin/oidc-clients/${client.uuid}`, { method: 'PATCH', body: { name, redirect_uris } })
|
||||
.then(() => {
|
||||
authStore.showMessage(`OIDC client "${name}" updated.`, 'success', 2500)
|
||||
loadOidcClients()
|
||||
})
|
||||
.catch(e => {
|
||||
authStore.showMessage(e.message || 'Failed to update OIDC client', 'error')
|
||||
})
|
||||
return // Don't call closeDialog() again
|
||||
} else if (t === 'confirm') {
|
||||
const action = dialog.value.data.action
|
||||
// Close dialog first, then perform action (errors shown via showMessage)
|
||||
@@ -773,6 +876,7 @@ async function submitDialog() {
|
||||
:info="info"
|
||||
:orgs="orgs"
|
||||
:permissions="permissions"
|
||||
:oidc-clients="oidcClients"
|
||||
:navigation-disabled="hasActiveModal"
|
||||
:permission-summary="permissionSummary"
|
||||
@create-org="createOrg"
|
||||
@@ -783,6 +887,9 @@ async function submitDialog() {
|
||||
@open-dialog="openDialog"
|
||||
@delete-permission="deletePermission"
|
||||
@rename-permission-display="renamePermissionDisplay"
|
||||
@create-oidc-client="createOidcClient"
|
||||
@edit-oidc-client="editOidcClient"
|
||||
@delete-oidc-client="deleteOidcClient"
|
||||
@navigate-out="handlePanelNavigateOut"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user