import { Injectable } from '@angular/core'; import { Observable, of } from 'rxjs'; import { delay } from 'rxjs/operators'; import { AdminInvitation, AdminRole, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model'; import { AdminUsersGateway } from './admin-users-gateway.interface'; const BUILT_IN_ROLES: AdminRole[] = [ { id: 'owner', name: 'Owner', permissions: ['*'], builtIn: true }, { id: 'admin', name: 'Admin', permissions: ['products.manage', 'categories.manage', 'orders.manage', 'media.manage'], builtIn: true }, { id: 'editor', name: 'Editor', permissions: ['products.manage', 'categories.manage', 'media.manage'], builtIn: true }, { id: 'viewer', name: 'Viewer', permissions: ['products.view', 'orders.view'], builtIn: true }, ]; @Injectable({ providedIn: 'root' }) export class AdminUsersLocalGateway implements AdminUsersGateway { private users: AdminUser[] | null = null; private roles: AdminRole[] = [...BUILT_IN_ROLES]; private invitations: AdminInvitation[] = []; private sessions: Record = {}; private audit: Record = {}; loadUsers(): Observable { return of(this.ensureUsers()).pipe(delay(50)); } loadRoles(): Observable { return of(this.roles).pipe(delay(50)); } loadInvitations(): Observable { return of(this.invitations).pipe(delay(50)); } loadSessions(userId: string): Observable { if (!this.sessions[userId]) { this.sessions[userId] = [ { id: `${userId}-s1`, userId, device: 'Chrome on Windows', ip: '10.0.0.1', lastActiveAt: new Date().toISOString(), current: true }, { id: `${userId}-s2`, userId, device: 'Telegram App on Android', ip: '10.0.0.2', lastActiveAt: new Date(Date.now() - 86400000).toISOString(), current: false }, ]; } return of(this.sessions[userId]).pipe(delay(50)); } loadAudit(userId: string): Observable { return of(this.audit[userId] ?? []).pipe(delay(50)); } setUserRole(userId: string, roleId: string): Observable { return this.mutateUser(userId, user => ({ ...user }), roleId, undefined); } setUserStatus(userId: string, status: AdminUserStatus): Observable { return this.mutateUser(userId, user => ({ ...user }), undefined, status); } inviteUser(email: string, roleId: string, scope: AdminUserScope): Observable { const invitation: AdminInvitation = { id: `invite-${Date.now()}`, email, roleId, scope, status: 'pending', invitedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), }; this.invitations = [invitation, ...this.invitations]; return of(invitation).pipe(delay(50)); } revokeInvitation(id: string): Observable { this.invitations = this.invitations.map(invite => invite.id === id ? { ...invite, status: 'revoked' } : invite); return of(void 0).pipe(delay(50)); } revokeSession(sessionId: string): Observable { for (const userId of Object.keys(this.sessions)) { this.sessions[userId] = this.sessions[userId].filter(session => session.id !== sessionId); } return of(void 0).pipe(delay(50)); } private mutateUser(userId: string, transform: (user: AdminUser) => AdminUser, roleId: string | undefined, status: AdminUserStatus | undefined): Observable { const users = this.ensureUsers(); const existing = users.find(user => user.id === userId); if (!existing) { return of(null); } const updated = transform({ ...existing, roleId: roleId ?? existing.roleId, status: status ?? existing.status }); this.users = users.map(user => user.id === userId ? updated : user); this.audit[userId] = [ ...(this.audit[userId] ?? []), roleId ? { eventKey: 'roleChanged', roleId, actor: 'admin', timestamp: new Date().toISOString() } : { eventKey: 'statusChanged', status, actor: 'admin', timestamp: new Date().toISOString() }, ]; return of(updated).pipe(delay(50)); } private ensureUsers(): AdminUser[] { if (!this.users) { this.users = [ { id: 'user-1', name: 'Karen Sargsyan', telegramUsername: '@karen', email: 'karen@dexar.market', scope: 'marketplace', roleId: 'owner', status: 'active', lastLoginAt: new Date().toISOString(), createdAt: new Date(Date.now() - 90 * 86400000).toISOString() }, { id: 'user-2', name: 'Anna Petrova', telegramUsername: '@anna', email: 'anna@dexar.market', scope: 'marketplace', roleId: 'admin', status: 'active', lastLoginAt: new Date(Date.now() - 2 * 86400000).toISOString(), createdAt: new Date(Date.now() - 60 * 86400000).toISOString() }, { id: 'user-3', name: 'Ivan Ivanov', telegramUsername: '@ivan', email: 'ivan@dexar.market', scope: 'office', roleId: 'editor', status: 'active', lastLoginAt: new Date(Date.now() - 5 * 86400000).toISOString(), createdAt: new Date(Date.now() - 30 * 86400000).toISOString() }, { id: 'user-4', name: 'Mariam Grigoryan', telegramUsername: '@mariam', email: 'mariam@dexar.market', scope: 'office', roleId: 'viewer', status: 'suspended', lastLoginAt: null, createdAt: new Date(Date.now() - 10 * 86400000).toISOString() }, ]; } return this.users; } }