diff --git a/src/modules/admin/admin.module.ts b/src/modules/admin/admin.module.ts index 5f8f3d5..aabe91c 100644 --- a/src/modules/admin/admin.module.ts +++ b/src/modules/admin/admin.module.ts @@ -12,11 +12,16 @@ import { RoleService } from './providers/role.service'; import { RoleController } from './controllers/role.controller'; import { PermissionService } from './providers/permission.service'; import { PermissionController } from './controllers/permission.controller'; +import { UtilsModule } from '../utils/utils.module'; @Module({ providers: [AdminService, AdminRepository, RoleService, PermissionService], controllers: [AdminController, RoleController, PermissionController], - imports: [MikroOrmModule.forFeature([Admin, Role, Permission, RolePermission]), JwtModule], + imports: [ + MikroOrmModule.forFeature([Admin, Role, Permission, RolePermission]), + JwtModule, + UtilsModule, + ], exports: [AdminService, AdminRepository, RoleService, PermissionService], }) export class AdminModule {} diff --git a/src/modules/admin/providers/admin.service.ts b/src/modules/admin/providers/admin.service.ts index 1242f46..7edda3f 100644 --- a/src/modules/admin/providers/admin.service.ts +++ b/src/modules/admin/providers/admin.service.ts @@ -5,13 +5,17 @@ import { Admin } from '../entities/admin.entity'; import { Role } from '../entities/role.entity'; import { Restaurant } from '../../restaurants/entities/restaurant.entity'; import { EntityManager } from '@mikro-orm/postgresql'; +import { CacheService } from '../../utils/cache.service'; @Injectable() export class AdminService { + private readonly ADMIN_PERMISSIONS_KEY = 'admin-perms'; + constructor( @InjectRepository(Admin) private readonly adminRepository: EntityRepository, private readonly em: EntityManager, + private readonly cacheService: CacheService, ) {} async findByPhone(phone: string): Promise { @@ -45,4 +49,60 @@ export class AdminService { await this.em.persistAndFlush(admin); return admin; } + + /** + * Get admin permissions from cache or database + * @param adminId - The admin ID + * @param restId - The restaurant ID + * @returns Array of permission names (string[]) + */ + async getAdminPermissions(adminId: string, restId: string): Promise { + const cacheKey = `${this.ADMIN_PERMISSIONS_KEY}:${adminId}:${restId}`; + + // Try to get from cache first + const cachedPermissions = await this.cacheService.get(cacheKey); + if (cachedPermissions) { + try { + const parsed = JSON.parse(cachedPermissions); + // Ensure it's an array of strings + if (Array.isArray(parsed) && parsed.every((p): p is string => typeof p === 'string')) { + return parsed; + } + // If invalid format, continue to fetch from DB + } catch { + // If parsing fails, continue to fetch from DB + } + } + + // If not in cache, fetch from database + const admin = await this.adminRepository.findOne( + { id: adminId, restaurant: { id: restId } }, + { populate: ['role', 'role.permissions'] }, + ); + + if (!admin || !admin.role) { + return []; + } + + // Extract permission names as array of strings + const permissions = await admin.role.permissions.loadItems(); + const permissionNames: string[] = permissions + .map(p => p.name) + .filter((name): name is string => typeof name === 'string'); + + // Store in cache as JSON stringified array of strings (1 hour TTL) + await this.cacheService.set(cacheKey, JSON.stringify(permissionNames), 3600); + + return permissionNames; + } + + /** + * Invalidate admin permissions cache + * @param adminId - The admin ID + * @param restId - The restaurant ID + */ + async invalidateAdminPermissionsCache(adminId: string, restId: string): Promise { + const cacheKey = `${this.ADMIN_PERMISSIONS_KEY}:${adminId}:${restId}`; + await this.cacheService.del(cacheKey); + } }