Enhance AdminService with caching for admin permissions and add UtilsModule to AdminModule imports
This commit is contained in:
@@ -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 {}
|
||||
|
||||
@@ -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<Admin>,
|
||||
private readonly em: EntityManager,
|
||||
private readonly cacheService: CacheService,
|
||||
) {}
|
||||
|
||||
async findByPhone(phone: string): Promise<Admin | null> {
|
||||
@@ -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<string[]> {
|
||||
const cacheKey = `${this.ADMIN_PERMISSIONS_KEY}:${adminId}:${restId}`;
|
||||
|
||||
// Try to get from cache first
|
||||
const cachedPermissions = await this.cacheService.get<string>(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<void> {
|
||||
const cacheKey = `${this.ADMIN_PERMISSIONS_KEY}:${adminId}:${restId}`;
|
||||
await this.cacheService.del(cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user