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 { RoleController } from './controllers/role.controller';
|
||||||
import { PermissionService } from './providers/permission.service';
|
import { PermissionService } from './providers/permission.service';
|
||||||
import { PermissionController } from './controllers/permission.controller';
|
import { PermissionController } from './controllers/permission.controller';
|
||||||
|
import { UtilsModule } from '../utils/utils.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [AdminService, AdminRepository, RoleService, PermissionService],
|
providers: [AdminService, AdminRepository, RoleService, PermissionService],
|
||||||
controllers: [AdminController, RoleController, PermissionController],
|
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],
|
exports: [AdminService, AdminRepository, RoleService, PermissionService],
|
||||||
})
|
})
|
||||||
export class AdminModule {}
|
export class AdminModule {}
|
||||||
|
|||||||
@@ -5,13 +5,17 @@ import { Admin } from '../entities/admin.entity';
|
|||||||
import { Role } from '../entities/role.entity';
|
import { Role } from '../entities/role.entity';
|
||||||
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
|
import { CacheService } from '../../utils/cache.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AdminService {
|
export class AdminService {
|
||||||
|
private readonly ADMIN_PERMISSIONS_KEY = 'admin-perms';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Admin)
|
@InjectRepository(Admin)
|
||||||
private readonly adminRepository: EntityRepository<Admin>,
|
private readonly adminRepository: EntityRepository<Admin>,
|
||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
|
private readonly cacheService: CacheService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findByPhone(phone: string): Promise<Admin | null> {
|
async findByPhone(phone: string): Promise<Admin | null> {
|
||||||
@@ -45,4 +49,60 @@ export class AdminService {
|
|||||||
await this.em.persistAndFlush(admin);
|
await this.em.persistAndFlush(admin);
|
||||||
return 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