Update the API to use new naming matching database.

This commit is contained in:
Leo Vasanko
2026-01-27 02:22:29 +00:00
parent db104d762b
commit 2413a32bda
12 changed files with 40 additions and 40 deletions
+12 -12
View File
@@ -130,7 +130,7 @@ function parseHash() {
async function loadOrgs() {
const data = await apiJson('/auth/api/admin/orgs')
orgs.value = data.map(o => {
const roles = o.roles.map(r => ({ ...r, org_uuid: o.uuid, users: [] }))
const roles = o.roles.map(r => ({ ...r, org: o.uuid, users: [] }))
const roleMap = Object.fromEntries(roles.map(r => [r.display_name, r]))
for (const u of o.users || []) {
if (roleMap[u.role]) roleMap[u.role].users.push(u)
@@ -242,9 +242,9 @@ async function moveUserToRole(org, user, targetRoleDisplayName) {
}
}
function onUserDragStart(e, user, org_uuid) {
function onUserDragStart(e, user, org) {
e.dataTransfer.effectAllowed = 'move'
e.dataTransfer.setData('text/plain', JSON.stringify({ user_uuid: user.uuid, org_uuid }))
e.dataTransfer.setData('text/plain', JSON.stringify({ user_uuid: user.uuid, org }))
}
function onRoleDragOver(e) {
@@ -256,7 +256,7 @@ function onRoleDrop(e, org, role) {
e.preventDefault()
try {
const data = JSON.parse(e.dataTransfer.getData('text/plain'))
if (data.org_uuid !== org.uuid) return // only within same org
if (data.org !== org.uuid) return // only within same org
const user = org.roles.flatMap(r => r.users).find(u => u.uuid === data.user_uuid)
if (user) moveUserToRole(org, user, role.display_name)
} catch (_) { /* ignore */ }
@@ -269,7 +269,7 @@ function updateRole(role) { openDialog('role-update', { role, name: role.display
function deleteRole(role) {
// UI only allows deleting empty roles, so no confirmation needed
apiJson(`/auth/api/admin/orgs/${role.org_uuid}/roles/${role.uuid}`, { method: 'DELETE' })
apiJson(`/auth/api/admin/orgs/${role.org}/roles/${role.uuid}`, { method: 'DELETE' })
.then(() => {
authStore.showMessage(`Role "${role.display_name}" deleted.`, 'success', 2500)
loadOrgs()
@@ -289,7 +289,7 @@ async function toggleRolePermission(role, pid, checked) {
try {
const method = checked ? 'POST' : 'DELETE'
await apiJson(`/auth/api/admin/orgs/${role.org_uuid}/roles/${role.uuid}/permissions/${pid}`, {
await apiJson(`/auth/api/admin/orgs/${role.org}/roles/${role.uuid}/permissions/${pid}`, {
method
})
await loadOrgs()
@@ -360,7 +360,7 @@ const selectedUser = computed(() => {
for (const o of orgs.value) {
for (const r of o.roles) {
const u = r.users.find(x => x.uuid === currentUserId.value)
if (u) return { ...u, org_uuid: o.uuid, role_display_name: r.display_name }
if (u) return { ...u, org: o.uuid, role_display_name: r.display_name }
}
}
return null
@@ -381,7 +381,7 @@ const breadcrumbEntries = computed(() => {
// Determine organization for user view if selectedOrg not explicitly chosen.
let orgForUser = null
if (selectedUser.value) {
orgForUser = orgs.value.find(o => o.uuid === selectedUser.value.org_uuid) || null
orgForUser = orgs.value.find(o => o.uuid === selectedUser.value.org) || null
}
const orgToShow = selectedOrg.value || orgForUser
if (orgToShow) {
@@ -396,7 +396,7 @@ const breadcrumbEntries = computed(() => {
watch(selectedUser, async (u) => {
if (!u) { userDetail.value = null; return }
try {
userDetail.value = await apiJson(`/auth/api/admin/orgs/${u.org_uuid}/users/${u.uuid}`)
userDetail.value = await apiJson(`/auth/api/admin/orgs/${u.org}/users/${u.uuid}`)
} catch (e) {
userDetail.value = { error: e.message }
}
@@ -532,7 +532,7 @@ async function refreshUserDetail() {
await loadOrgs()
if (selectedUser.value) {
try {
userDetail.value = await apiJson(`/auth/api/admin/orgs/${selectedUser.value.org_uuid}/users/${selectedUser.value.uuid}`)
userDetail.value = await apiJson(`/auth/api/admin/orgs/${selectedUser.value.org}/users/${selectedUser.value.uuid}`)
} catch (e) { authStore.showMessage(e.message || 'Failed to reload user', 'error') }
}
}
@@ -594,7 +594,7 @@ async function submitDialog() {
// Close dialog immediately, then perform async operation
closeDialog()
apiJson(`/auth/api/admin/orgs/${role.org_uuid}/roles/${role.uuid}`, { method: 'PATCH', body: { display_name: name } })
apiJson(`/auth/api/admin/orgs/${role.org}/roles/${role.uuid}`, { method: 'PATCH', body: { display_name: name } })
.then(() => {
authStore.showMessage(`Role renamed to "${name}".`, 'success', 2500)
loadOrgs()
@@ -622,7 +622,7 @@ async function submitDialog() {
// Close dialog immediately, then perform async operation
closeDialog()
apiJson(`/auth/api/admin/orgs/${user.org_uuid}/users/${user.uuid}/display-name`, { method: 'PATCH', body: { display_name: name } })
apiJson(`/auth/api/admin/orgs/${user.org}/users/${user.uuid}/display-name`, { method: 'PATCH', body: { display_name: name } })
.then(() => {
authStore.showMessage(`User renamed to "${name}".`, 'success', 2500)
onUserNameSaved()
+5 -5
View File
@@ -45,7 +45,7 @@ function handleEditName() {
async function handleDelete(credential) {
try {
const data = await apiJson(`/auth/api/admin/orgs/${props.selectedUser.org_uuid}/users/${props.selectedUser.uuid}/credentials/${credential.credential_uuid}`, { method: 'DELETE' })
const data = await apiJson(`/auth/api/admin/orgs/${props.selectedUser.org}/users/${props.selectedUser.uuid}/credentials/${credential.credential}`, { method: 'DELETE' })
if (data.status === 'ok') {
emit('onUserNameSaved') // Reuse to refresh user detail
} else {
@@ -61,7 +61,7 @@ async function handleTerminateSession(session) {
if (!sessionId) return
terminatingSessions.value = { ...terminatingSessions.value, [sessionId]: true }
try {
const data = await apiJson(`/auth/api/admin/orgs/${props.selectedUser.org_uuid}/users/${props.selectedUser.uuid}/sessions/${sessionId}`, { method: 'DELETE' })
const data = await apiJson(`/auth/api/admin/orgs/${props.selectedUser.org}/users/${props.selectedUser.uuid}/sessions/${sessionId}`, { method: 'DELETE' })
if (data.status === 'ok') {
if (data.current_session_terminated) {
sessionStorage.clear()
@@ -183,7 +183,7 @@ defineExpose({ focusFirstElement })
:loading="loading"
:org-display-name="userDetail.org.display_name"
:role-name="userDetail.role"
:update-endpoint="`/auth/api/admin/orgs/${selectedUser.org_uuid}/users/${selectedUser.uuid}/display-name`"
:update-endpoint="`/auth/api/admin/orgs/${selectedUser.org}/users/${selectedUser.uuid}/display-name`"
@saved="$emit('onUserNameSaved')"
@edit-name="handleEditName"
/>
@@ -212,7 +212,7 @@ defineExpose({ focusFirstElement })
:aaguid-info="userDetail.aaguid_info"
:allow-delete="true"
:hovered-credential-uuid="hoveredCredentialUuid"
:hovered-session-credential-uuid="hoveredSession?.credential_uuid"
:hovered-session-credential-uuid="hoveredSession?.credential"
:navigation-disabled="hasActiveModal"
@delete="handleDelete"
@credential-hover="hoveredCredentialUuid = $event"
@@ -238,7 +238,7 @@ defineExpose({ focusFirstElement })
</div>
<RegistrationLinkModal
v-if="showRegModal"
:endpoint="`/auth/api/admin/orgs/${selectedUser.org_uuid}/users/${selectedUser.uuid}/create-link`"
:endpoint="`/auth/api/admin/orgs/${selectedUser.org}/users/${selectedUser.uuid}/create-link`"
:user-name="userDetail?.display_name || selectedUser.display_name"
@close="$emit('closeRegModal')"
@copied="onLinkCopied"
+6 -6
View File
@@ -5,16 +5,16 @@
<template v-else>
<div
v-for="credential in credentials"
:key="credential.credential_uuid"
:key="credential.credential"
:class="['credential-item', {
'current-session': credential.is_current_session && !hoveredCredentialUuid && !hoveredSessionCredentialUuid,
'is-hovered': hoveredCredentialUuid === credential.credential_uuid,
'is-linked-session': hoveredSessionCredentialUuid === credential.credential_uuid
'is-hovered': hoveredCredentialUuid === credential.credential,
'is-linked-session': hoveredSessionCredentialUuid === credential.credential
}]"
tabindex="-1"
@mousedown.prevent
@click.capture="handleCardClick"
@focusin="handleCredentialFocus(credential.credential_uuid)"
@focusin="handleCredentialFocus(credential.credential)"
@focusout="handleCredentialBlur($event)"
@keydown="handleItemKeydown($event, credential)"
>
@@ -33,8 +33,8 @@
<h4 class="item-title">{{ getCredentialAuthName(credential) }}</h4>
<div class="item-actions">
<span v-if="credential.is_current_session && !hoveredCredentialUuid && !hoveredSessionCredentialUuid" class="badge badge-current">Current</span>
<span v-else-if="hoveredCredentialUuid === credential.credential_uuid" class="badge badge-current">Selected</span>
<span v-else-if="hoveredSessionCredentialUuid === credential.credential_uuid" class="badge badge-current">Linked</span>
<span v-else-if="hoveredCredentialUuid === credential.credential" class="badge badge-current">Selected</span>
<span v-else-if="hoveredSessionCredentialUuid === credential.credential" class="badge badge-current">Linked</span>
<button
v-if="allowDelete"
@click="$emit('delete', credential)"
+2 -2
View File
@@ -47,7 +47,7 @@
:aaguid-info="authStore.userInfo?.aaguid_info || {}"
:loading="authStore.isLoading"
:hovered-credential-uuid="hoveredCredentialUuid"
:hovered-session-credential-uuid="hoveredSession?.credential_uuid"
:hovered-session-credential-uuid="hoveredSession?.credential"
:navigation-disabled="hasActiveModal"
allow-delete
@delete="handleDelete"
@@ -292,7 +292,7 @@ const handleLogoutButtonKeydown = (event) => {
}
const handleDelete = async (credential) => {
const credentialId = credential?.credential_uuid
const credentialId = credential?.credential
if (!credentialId) return
try {
await authStore.deleteCredential(credentialId)
+1 -1
View File
@@ -279,7 +279,7 @@ onUnmounted(() => {
defineExpose({
showMessage,
isAuthenticated,
userInfo
session
})
</script>
+2 -2
View File
@@ -20,7 +20,7 @@
:class="['session-item', {
'is-current': session.is_current && !hoveredIp && !hoveredCredentialUuid,
'is-hovered': hoveredSession?.id === session.id,
'is-linked-credential': hoveredCredentialUuid === session.credential_uuid
'is-linked-credential': hoveredCredentialUuid === session.credential
}]"
tabindex="-1"
@mousedown.prevent
@@ -34,7 +34,7 @@
<div class="item-actions">
<span v-if="session.is_current && !hoveredIp && !hoveredCredentialUuid" class="badge badge-current">Current</span>
<span v-else-if="hoveredSession?.id === session.id" class="badge badge-current">Selected</span>
<span v-else-if="hoveredCredentialUuid === session.credential_uuid" class="badge badge-current">Linked</span>
<span v-else-if="hoveredCredentialUuid === session.credential" class="badge badge-current">Linked</span>
<span v-else-if="!hoveredCredentialUuid && isSameHost(session.ip)" class="badge">Same IP</span>
<button
@click="$emit('terminate', session)"
+3 -3
View File
@@ -99,7 +99,7 @@ async def admin_list_orgs(request: Request, auth=AUTH_COOKIE):
def role_to_dict(r):
return {
"uuid": str(r.uuid),
"org_uuid": str(r.org_uuid),
"org": str(r.org),
"display_name": r.display_name,
"permissions": r.permissions,
}
@@ -600,7 +600,7 @@ async def admin_get_user_detail(
aaguids.add(aaguid_str)
creds.append(
{
"credential_uuid": str(c.uuid),
"credential": str(c.uuid),
"aaguid": aaguid_str,
"created_at": (
c.created_at.astimezone(timezone.utc)
@@ -656,7 +656,7 @@ async def admin_get_user_detail(
sessions_payload.append(
{
"id": entry.key,
"credential_uuid": str(entry.credential_uuid),
"credential": str(entry.credential),
"host": entry.host,
"ip": entry.ip,
"user_agent": useragent.compact_user_agent(entry.user_agent),
+1 -1
View File
@@ -268,5 +268,5 @@ async def api_set_session(
session.set_session_cookie(response, auth.credentials)
return {
"message": "Session cookie set successfully",
"user_uuid": str(user.user_uuid),
"user": str(user.user),
}
+1 -1
View File
@@ -179,7 +179,7 @@ async def websocket_remote_auth_request(ws: WebSocket):
):
response = {
"status": "authenticated",
"user_uuid": str(result_data["user_uuid"]),
"user": str(result_data["user_uuid"]),
}
if result_data.get("session_token"):
response["session_token"] = result_data["session_token"]
+3 -3
View File
@@ -93,8 +93,8 @@ async def websocket_register_add(
assert isinstance(auth, str) and len(auth) == 16
await ws.send_json(
{
"user_uuid": str(user.uuid),
"credential_uuid": str(credential.uuid),
"user": str(user.uuid),
"credential": str(credential.uuid),
"session_token": auth,
"message": "New credential added successfully",
}
@@ -164,7 +164,7 @@ async def websocket_authenticate(ws: WebSocket, auth=AUTH_COOKIE):
await ws.send_json(
{
"user_uuid": str(stored_cred.user),
"user": str(stored_cred.user),
"session_token": token,
}
)
+3 -3
View File
@@ -57,13 +57,13 @@ async def format_user_info(
user_aaguids.add(aaguid_str)
credentials.append(
{
"credential_uuid": str(c.uuid),
"credential": str(c.uuid),
"aaguid": aaguid_str,
"created_at": _format_datetime(c.created_at),
"last_used": _format_datetime(c.last_used),
"last_verified": _format_datetime(c.last_verified),
"sign_count": c.sign_count,
"is_current_session": session_record.credential_uuid == c.uuid,
"is_current_session": session_record.credential == c.uuid,
}
)
@@ -80,7 +80,7 @@ async def format_user_info(
sessions_payload.append(
{
"id": entry.key,
"credential_uuid": str(entry.credential_uuid),
"credential": str(entry.credential),
"host": entry.host,
"ip": entry.ip,
"user_agent": useragent.compact_user_agent(entry.user_agent),
+1 -1
View File
@@ -317,7 +317,7 @@ class TestSetSessionEndpoint:
)
assert response.status_code == 200
data = response.json()
assert "user_uuid" in data
assert "user" in data
# Check that Set-Cookie header is present
assert "set-cookie" in response.headers