From f6e1bc1f47691ae7142111db853c21ab0c48fc2e Mon Sep 17 00:00:00 2001 From: Zoe Date: Thu, 8 Oct 2026 13:41:02 -0500 Subject: [PATCH] feat: basic admin interface --- app/components/Dialog/Confirm.vue | 34 + app/components/Dialog/CreateUser.vue | 155 + app/components/Dialog/index.vue | 4 + app/components/Sidenav/NavSettings.vue | 23 +- app/composables/useAuth.ts | 4 +- app/composables/useDialog.ts | 1 + app/middleware/auth.global.ts | 2 +- app/pages/auth/login.vue | 9 +- app/pages/auth/register.vue | 9 +- app/pages/settings.vue | 3 + app/pages/settings/instance/index.vue | 104 + app/pages/settings/instance/users.vue | 348 ++ .../migration.sql | 5 + .../snapshot.json | 3094 +++++++++++++++++ drizzle/schema.ts | 13 + lib/auth.ts | 33 +- server/api/account/index.delete.ts | 36 +- server/api/admin/instance.get.ts | 9 + server/api/admin/instance.put.ts | 43 + server/api/admin/users/[id]/index.delete.ts | 40 + .../api/admin/users/[id]/two-factor.delete.ts | 34 + server/api/admin/users/index.get.ts | 39 + server/api/instance.get.ts | 6 + server/api/setup/index.get.ts | 4 - server/utils/account.ts | 39 + server/utils/admin.ts | 26 + server/utils/instance.ts | 27 + 27 files changed, 4095 insertions(+), 49 deletions(-) create mode 100644 app/components/Dialog/Confirm.vue create mode 100644 app/components/Dialog/CreateUser.vue create mode 100644 app/pages/settings/instance/index.vue create mode 100644 app/pages/settings/instance/users.vue create mode 100644 drizzle/migrations/20261008182241_instance-settings/migration.sql create mode 100644 drizzle/migrations/20261008182241_instance-settings/snapshot.json create mode 100644 server/api/admin/instance.get.ts create mode 100644 server/api/admin/instance.put.ts create mode 100644 server/api/admin/users/[id]/index.delete.ts create mode 100644 server/api/admin/users/[id]/two-factor.delete.ts create mode 100644 server/api/admin/users/index.get.ts create mode 100644 server/api/instance.get.ts delete mode 100644 server/api/setup/index.get.ts create mode 100644 server/utils/account.ts create mode 100644 server/utils/admin.ts create mode 100644 server/utils/instance.ts diff --git a/app/components/Dialog/Confirm.vue b/app/components/Dialog/Confirm.vue new file mode 100644 index 0000000..f4aeae8 --- /dev/null +++ b/app/components/Dialog/Confirm.vue @@ -0,0 +1,34 @@ + + + diff --git a/app/components/Dialog/CreateUser.vue b/app/components/Dialog/CreateUser.vue new file mode 100644 index 0000000..61014cc --- /dev/null +++ b/app/components/Dialog/CreateUser.vue @@ -0,0 +1,155 @@ + + + diff --git a/app/components/Dialog/index.vue b/app/components/Dialog/index.vue index 47f859a..f7bbdf9 100644 --- a/app/components/Dialog/index.vue +++ b/app/components/Dialog/index.vue @@ -4,6 +4,8 @@ import QuickSwitcher from './QuickSwitcher.vue'; import ChangePassword from './ChangePassword.vue'; import TwoFactor from './TwoFactor.vue'; import DeleteAccount from './DeleteAccount.vue'; +import Confirm from './Confirm.vue'; +import CreateUser from './CreateUser.vue'; import { DialogType } from '~/composables/useDialog'; @@ -69,6 +71,8 @@ onUnmounted(() => { + + diff --git a/app/components/Sidenav/NavSettings.vue b/app/components/Sidenav/NavSettings.vue index f1a55d8..e50232c 100644 --- a/app/components/Sidenav/NavSettings.vue +++ b/app/components/Sidenav/NavSettings.vue @@ -3,10 +3,21 @@ import { providerIcons } from '~/utils/model-mapping'; const route = useRoute(); const { providers } = await useModels(); +const { isAdmin } = useAuth(); -const groups = [ +const ADMIN_GROUP = { + label: 'Instance', + adminOnly: true, + items: [ + { to: '/settings/instance/users', name: 'Users', icon: 'i-mynaui-users' }, + { to: '/settings/instance', name: 'Instance', icon: 'i-tabler-server' }, + ], +}; + +const BASE_GROUPS = [ { label: 'Account', + adminOnly: false, items: [ { to: '/settings/profile', name: 'Profile', icon: 'i-mynaui-user' }, { to: '/settings/security', name: 'Security', icon: 'i-mynaui-shield' }, @@ -14,6 +25,7 @@ const groups = [ }, { label: 'App', + adminOnly: false, items: [ { to: '/settings/general', name: 'General', icon: 'i-mynaui-cog-four' }, { to: '/settings/appearance', name: 'Appearance', icon: 'i-tabler-palette' }, @@ -23,6 +35,8 @@ const groups = [ }, ]; +const groups = computed(() => isAdmin.value ? [...BASE_GROUPS, ADMIN_GROUP] : BASE_GROUPS); + const inProviders = computed(() => route.path.startsWith('/settings/providers')); // enabled providers first, same order the provider list uses @@ -35,8 +49,13 @@ const sortedProviders = computed(() => [