diff --git a/frontend/src/api/admin.js b/frontend/src/api/admin.js
index 028ce79..cf25da0 100644
--- a/frontend/src/api/admin.js
+++ b/frontend/src/api/admin.js
@@ -1,8 +1,8 @@
/**
* Admin API — user management, quota, AI config, audit log, daily exports.
*
- * Consumers: AdminUsersTab.vue, AdminQuotasTab.vue, AdminAiConfigTab.vue,
- * AuditLogTab.vue, AdminDailyExportsTab.vue
+ * Consumers: AdminUsersView.vue, AdminQuotasView.vue, AdminAiView.vue,
+ * AdminAuditView.vue
*/
import { request, fetchWithRetry } from './utils.js'
diff --git a/frontend/src/components/admin/AdminAiConfigTab.vue b/frontend/src/components/admin/AdminAiConfigTab.vue
deleted file mode 100644
index e0eed21..0000000
--- a/frontend/src/components/admin/AdminAiConfigTab.vue
+++ /dev/null
@@ -1,391 +0,0 @@
-
-
-
-
-
-
System AI Providers (Global)
-
- These settings apply to all classification jobs. Per-user overrides below take precedence when set.
-
-
-
-
-
-
-
- Loading AI providers…
-
-
-
-
-
- {{ systemError }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- OK
- Failed
-
-
-
-
-
-
-
-
-
-
-
-
- Loading AI config…
-
-
-
-
-
-
No users yet
-
Create the first user account to get started.
-
-
-
-
-
-
-
{{ loadError }}
-
-
-
-
diff --git a/frontend/src/components/admin/AdminQuotasTab.vue b/frontend/src/components/admin/AdminQuotasTab.vue
deleted file mode 100644
index 7babeb4..0000000
--- a/frontend/src/components/admin/AdminQuotasTab.vue
+++ /dev/null
@@ -1,182 +0,0 @@
-
-
-
-
-
-
- Loading quotas…
-
-
-
-
-
-
No users yet
-
Create the first user account to get started.
-
-
-
-
-
-
-
- | Email |
- Used |
- Limit |
- Usage % |
- Actions |
-
-
-
-
- | {{ row.email }} |
- {{ formatMB(row.used_bytes) }} |
-
-
-
-
-
-
- New limit is below current usage ({{ formatMB(row.used_bytes) }}). Existing documents will not be deleted, but uploads will be blocked.
-
-
- {{ formatMB(row.limit_bytes) }}
- |
-
-
- {{ usagePercent(row.used_bytes, row.limit_bytes) }}%
- |
-
-
-
-
-
- ·
-
-
-
- |
-
-
-
-
-
-
-
{{ loadError }}
-
-
-
-
diff --git a/frontend/src/components/admin/AdminUsersTab.vue b/frontend/src/components/admin/AdminUsersTab.vue
deleted file mode 100644
index 289ae61..0000000
--- a/frontend/src/components/admin/AdminUsersTab.vue
+++ /dev/null
@@ -1,480 +0,0 @@
-
-
-
-
-
Create user
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ createError }}
-
-
-
-
-
-
-
-
-
-
{{ users.length }} user{{ users.length !== 1 ? 's' : '' }}
-
-
-
-
-
-
-
-
-
No users yet
-
Create the first user account to get started.
-
-
-
-
-
-
-
- | Email |
- Handle |
- Role |
- Status |
- Created |
- Actions |
-
-
-
-
- | {{ user.email }} |
- {{ user.handle ? '@' + user.handle : '—' }} |
-
-
- {{ user.role === 'admin' ? 'Admin' : 'User' }}
-
- |
-
-
- {{ user.is_active ? 'Active' : 'Deactivated' }}
-
- |
- {{ formatDate(user.created_at) }} |
-
-
-
-
- Deactivate {{ user.email }}? They will lose access immediately. Their data is preserved.
-
-
-
- ·
-
-
-
-
-
-
-
- Permanently delete {{ user.email }}?
- This will erase all their documents, cloud connections, and quota data. This cannot be undone.
-
-
-
-
-
- {{ deleteError }}
-
-
- ·
-
-
-
-
-
-
-
-
-
-
-
-
- ·
-
- ·
-
-
-
-
-
- ·
-
-
-
- |
-
-
-
-
-
-
-
{{ actionError }}
-
-
-
-
diff --git a/frontend/src/components/admin/AuditLogTab.vue b/frontend/src/components/admin/AuditLogTab.vue
deleted file mode 100644
index 6e110c8..0000000
--- a/frontend/src/components/admin/AuditLogTab.vue
+++ /dev/null
@@ -1,346 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ activeFilterCount }} filter{{ activeFilterCount !== 1 ? 's' : '' }} active
-
-
-
{{ exportError }}
-
-
-
-
-
-
- Loading audit log…
-
-
-
-
-
{{ fetchError }}
-
-
-
- No audit log entries match the selected filters.
-
-
-
-
-
-
-
- | Timestamp |
- User |
- Email |
- Action Type |
- IP Address |
-
-
-
-
- | {{ formatTimestamp(entry.created_at) }} |
- {{ entry.user_handle || entry.user_id || '—' }} |
-
- {{ entry.user_email }}
- hash:{{ entry.metadata_.attempted_email_hash }} (attempted)
- —
- |
-
-
- {{ entry.event_type }}
-
- |
- {{ entry.ip_address || '—' }} |
-
-
-
-
-
-
-
-
- Page {{ page }}
-
-
-
-
-
-
Daily exports
-
-
Loading exports…
-
-
- No daily exports available.
-
-
-
-
-
-
-
-
-
{{ exportsError }}
-
-
-
-
-
diff --git a/frontend/src/components/admin/__tests__/AdminAiConfigTab.test.js b/frontend/src/components/admin/__tests__/AdminAiConfigTab.test.js
index 8c0d0af..2e0f365 100644
--- a/frontend/src/components/admin/__tests__/AdminAiConfigTab.test.js
+++ b/frontend/src/components/admin/__tests__/AdminAiConfigTab.test.js
@@ -7,7 +7,7 @@ vi.mock('../../../api/client.js', () => ({
adminUpdateAiConfig: vi.fn(),
}))
-import AdminAiConfigTab from '../AdminAiConfigTab.vue'
+import AdminAiConfigTab from '../../../views/admin/AdminAiView.vue'
import * as api from '../../../api/client.js'
function makeUser(overrides = {}) {
diff --git a/frontend/src/components/admin/__tests__/AdminQuotasTab.test.js b/frontend/src/components/admin/__tests__/AdminQuotasTab.test.js
index ed57863..fc82868 100644
--- a/frontend/src/components/admin/__tests__/AdminQuotasTab.test.js
+++ b/frontend/src/components/admin/__tests__/AdminQuotasTab.test.js
@@ -8,7 +8,7 @@ vi.mock('../../../api/client.js', () => ({
adminUpdateQuota: vi.fn(),
}))
-import AdminQuotasTab from '../AdminQuotasTab.vue'
+import AdminQuotasTab from '../../../views/admin/AdminQuotasView.vue'
import * as api from '../../../api/client.js'
const MB = 1048576
diff --git a/frontend/src/components/admin/__tests__/AdminUsersTab.test.js b/frontend/src/components/admin/__tests__/AdminUsersTab.test.js
index cfa67e9..f116353 100644
--- a/frontend/src/components/admin/__tests__/AdminUsersTab.test.js
+++ b/frontend/src/components/admin/__tests__/AdminUsersTab.test.js
@@ -11,7 +11,7 @@ vi.mock('../../../api/client.js', () => ({
adminCreateUser: vi.fn(),
}))
-import AdminUsersTab from '../AdminUsersTab.vue'
+import AdminUsersTab from '../../../views/admin/AdminUsersView.vue'
import * as api from '../../../api/client.js'
function makeUser(overrides = {}) {
diff --git a/frontend/src/router/__tests__/router.guard.test.js b/frontend/src/router/__tests__/router.guard.test.js
index 99336fc..036a88c 100644
--- a/frontend/src/router/__tests__/router.guard.test.js
+++ b/frontend/src/router/__tests__/router.guard.test.js
@@ -11,7 +11,12 @@ vi.mock('../../views/auth/LoginView.vue', () => ({ default: { template: '
vi.mock('../../views/auth/RegisterView.vue', () => ({ default: { template: '' } }))
vi.mock('../../views/auth/PasswordResetView.vue', () => ({ default: { template: '' } }))
vi.mock('../../views/auth/NewPasswordView.vue', () => ({ default: { template: '' } }))
-vi.mock('../../views/AdminView.vue', () => ({ default: { template: '' } }))
+vi.mock('../../layouts/AdminLayout.vue', () => ({ default: { template: '
' } }))
+vi.mock('../../views/admin/AdminOverviewView.vue', () => ({ default: { template: '' } }))
+vi.mock('../../views/admin/AdminUsersView.vue', () => ({ default: { template: '' } }))
+vi.mock('../../views/admin/AdminQuotasView.vue', () => ({ default: { template: '' } }))
+vi.mock('../../views/admin/AdminAiView.vue', () => ({ default: { template: '' } }))
+vi.mock('../../views/admin/AdminAuditView.vue', () => ({ default: { template: '' } }))
vi.mock('../../views/SharedView.vue', () => ({ default: { template: '' } }))
// Heavy view components imported statically — stub them too
@@ -78,4 +83,18 @@ describe('router — admin guard (SEC-07)', () => {
await router.push('/admin')
expect(router.currentRoute.value.path).toBe('/admin')
})
+
+ it('redirects an admin user away from / to /admin (D-09)', async () => {
+ // Arrange: admin trying to navigate to a regular user route
+ useAuthStore.mockReturnValue({
+ accessToken: 'fake-token',
+ user: { id: '1', role: 'admin' },
+ refresh: vi.fn().mockResolvedValue(undefined),
+ })
+
+ // Act: admin attempts to visit the regular user home
+ await router.push('/')
+ // The D-09 guard branch returns { path: '/admin' }
+ expect(router.currentRoute.value.path).toBe('/admin')
+ })
})
diff --git a/frontend/src/views/AdminView.vue b/frontend/src/views/AdminView.vue
deleted file mode 100644
index 22dae05..0000000
--- a/frontend/src/views/AdminView.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
Admin panel
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/views/SettingsView.vue b/frontend/src/views/SettingsView.vue
index ec1bd19..616f5b3 100644
--- a/frontend/src/views/SettingsView.vue
+++ b/frontend/src/views/SettingsView.vue
@@ -27,7 +27,7 @@
-
+