Роли ADMIN и USER, User panel и Admin panel
continuous-integration/drone/pr Build is passing

- Роль ADMIN = users.is_admin; встроенный администратор (mailserver.admins, по
  умолчанию admin@) всегда ADMIN и получает роль в базе при старте.
- PUT /api/admin/mailboxes/{id}/role {ADMIN|USER}: только ADMIN; не свою, не
  встроенного, общий ящик не может быть ADMIN.
- Admin panel (/admin, только ADMIN): USERS (логины и роли, MAKE ADMIN / MAKE USER),
  MAILBOXES, LISTS. User panel (/settings): профиль, пароль, хранилище, вид, мои ящики.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-07 20:18:18 +01:00
co-authored by Claude Opus 5.5
parent 402d2c403b
commit cf87b60b38
13 changed files with 215 additions and 18 deletions
@@ -144,6 +144,13 @@ import { ToastService } from '../../ui/toast.service';
<mat-icon class="!text-xl">{{ link.icon }}</mat-icon>{{ link.label }}
</a>
}
@if (state.profile()?.admin) {
<a routerLink="/admin" routerLinkActive="nav-active-text"
class="flex items-center gap-3 px-3 py-1.5 rounded-lg text-slate-400 hover:text-cyan-300 font-rajdhani font-semibold"
(click)="menuOpen.set(false)">
<mat-icon class="!text-xl">admin_panel_settings</mat-icon>Admin panel
</a>
}
</div>
@if (state.profile(); as p) {
@@ -180,7 +187,7 @@ export class ShellComponent {
readonly links = [
{ path: '/contacts', label: 'Contacts', icon: 'contacts' },
{ path: '/blocked', label: 'Blocked senders', icon: 'block' },
{ path: '/settings', label: 'Settings', icon: 'settings' }
{ path: '/settings', label: 'User panel', icon: 'person' }
];
readonly folderActions: RowAction[] = [