diff --git a/src/modules/admin/controllers/admin.controller.ts b/src/modules/admin/controllers/admin.controller.ts index 91a9414..15fce62 100644 --- a/src/modules/admin/controllers/admin.controller.ts +++ b/src/modules/admin/controllers/admin.controller.ts @@ -4,21 +4,23 @@ import { CreateAdminDto } from '../dto/create-admin.dto'; import { UpdateAdminDto } from '../dto/update-admin.dto'; import { ApiTags, ApiOperation, ApiBody, ApiBearerAuth, ApiParam, ApiHeader } from '@nestjs/swagger'; import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard'; +import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard'; import { RestId } from 'src/common/decorators'; import { AdminId } from 'src/common/decorators/admin-id.decorator'; import { Admin } from '../entities/admin.entity'; import { Permission } from 'src/common/enums/permission.enum'; import { Permissions } from 'src/common/decorators/permissions.decorator'; - +import { CreateMyRestaurantAdminDto } from '../dto/create-my-restaurant-admin.dto'; + @ApiBearerAuth() @ApiTags('admin') -@UseGuards(AdminAuthGuard) -@Permissions(Permission.MANAGE_ADMINS) @Controller('admin/admins') export class AdminController { - constructor(private readonly adminService: AdminService) {} + constructor(private readonly adminService: AdminService) { } @Get() + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ADMINS) @ApiOperation({ summary: 'admin' }) async getAll(@RestId() restId: string) { const admin = await this.adminService.findAllByRestaurantId(restId); @@ -26,6 +28,8 @@ export class AdminController { } @Get('profile') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ADMINS) @ApiOperation({ summary: 'admin' }) async getMe(@AdminId() adminId: string, @RestId() restId: string) { const admin = await this.adminService.findById(adminId, restId); @@ -33,6 +37,8 @@ export class AdminController { } @Post() + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ADMINS) @HttpCode(HttpStatus.CREATED) @ApiOperation({ summary: 'Create a new admin' }) @ApiBody({ type: CreateAdminDto }) @@ -42,22 +48,55 @@ export class AdminController { } @Patch(':adminId') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ADMINS) @ApiOperation({ summary: 'Update an admin' }) @ApiParam({ name: 'adminId', description: 'Admin ID' }) @ApiBody({ type: UpdateAdminDto }) update(@Param('adminId') adminId: string, @Body() dto: UpdateAdminDto, @RestId() restId: string): Promise { return this.adminService.update(adminId, restId, dto); } + @Get(':adminId') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ADMINS) @ApiOperation({ summary: 'Get an admin by ID' }) @ApiParam({ name: 'id', description: 'Admin ID' }) getById(@Param('adminId') adminId: string, @RestId() restId: string): Promise { return this.adminService.findById(adminId, restId); } + @Delete(':adminId') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ADMINS) @ApiOperation({ summary: 'Delete an admin by ID' }) @ApiParam({ name: 'id', description: 'Admin ID' }) deleteById(@Param('adminId') adminId: string, @RestId() restId: string): Promise { return this.adminService.remove(adminId, restId); } + + /** Super Admin Endpoints */ + @UseGuards(SuperAdminAuthGuard) + @Post('super-admin/restaurants/:restaurantId/admins') + @ApiOperation({ summary: 'Create admin for a specific restaurant (Super Admin only)' }) + @ApiParam({ name: 'restaurantId', description: 'Restaurant ID' }) + @ApiBody({ type: CreateMyRestaurantAdminDto }) + createAdminForRestaurant( + @Param('restaurantId') restaurantId: string, + @Body() dto: CreateMyRestaurantAdminDto, + ): Promise { + return this.adminService.createAdminForRestaurantBySuperAdmin(restaurantId, dto); + } + + @UseGuards(SuperAdminAuthGuard) + @Delete('super-admin/restaurants/:restaurantId/admins/:adminId') + @ApiOperation({ summary: 'Revoke admin role from a restaurant (Super Admin only)' }) + @ApiParam({ name: 'restaurantId', description: 'Restaurant ID' }) + @ApiParam({ name: 'adminId', description: 'Admin ID' }) + revokeAdminFromRestaurant( + @Param('restaurantId') restaurantId: string, + @Param('adminId') adminId: string, + ): Promise { + return this.adminService.remove(adminId, restaurantId); + } } diff --git a/src/modules/admin/providers/admin.service.ts b/src/modules/admin/providers/admin.service.ts index 7d9fbd3..ed9bb1b 100644 --- a/src/modules/admin/providers/admin.service.ts +++ b/src/modules/admin/providers/admin.service.ts @@ -20,7 +20,7 @@ export class AdminService { private readonly adminRoleRepository: EntityRepository, private readonly em: EntityManager, private readonly cacheService: CacheService, - ) {} + ) { } async findByPhone(phone: string): Promise { const normalizedPhone = normalizePhone(phone); @@ -79,32 +79,45 @@ export class AdminService { return admin; } - // async createRestaurantBySuperAdmin(data: { - // phone: string; - // firstName?: string; - // lastName?: string; - // roleId: string; - // restId: string; - // }) { - // const { phone, firstName, lastName, roleId, restId } = data; + async createAdminForRestaurantBySuperAdmin(restId: string, dto: CreateMyRestaurantAdminDto) { + const { phone, firstName, lastName, roleId } = dto; + const normalizedPhone = normalizePhone(phone); + let admin: Admin | null = null; + admin = await this.adminRepository.findOne({ + phone: normalizedPhone, + }); + if (!admin) { + admin = this.adminRepository.create({ + phone: normalizedPhone, + firstName, + lastName, + }); + await this.em.persistAndFlush(admin); + } + const role = await this.em.findOne(Role, { id: roleId, isSystem: false }); + if (!role) throw new NotFoundException('Role not found'); - // // check existing - // const existing = await this.adminRepository.findOne({ phone, roles: { restaurant: { id: restId } } }); - // if (existing) { - // return existing; - // } + const restaurant = await this.em.findOne(Restaurant, { id: restId }); + if (!restaurant) throw new NotFoundException('Restaurant not found'); - // // load Role and Restaurant using the EntityManager - // const role = await this.em.findOne(Role, { id: roleId }); - // if (!role) throw new Error('Role not found'); + let adminRole = await this.adminRoleRepository.findOne({ + admin: admin, + restaurant: restaurant, + }); - // const restaurant = await this.em.findOne(Restaurant, { id: restId }); - // if (!restaurant) throw new Error('Restaurant not found'); + if (!adminRole) { + adminRole = this.adminRoleRepository.create({ + admin: admin, + role, + restaurant, + }); + } else { + adminRole.role = role; + } - // const admin = this.adminRepository.create({ phone, firstName, lastName, roles: [{ role, restaurant }] }); - // await this.em.persistAndFlush(admin); - // return admin; - // } + await this.em.persistAndFlush(adminRole); + return admin; + } async update(adminId: string, restId: string, dto: UpdateAdminDto): Promise { const admin = await this.adminRepository.findOne( diff --git a/src/modules/restaurants/controllers/restaurants.controller.ts b/src/modules/restaurants/controllers/restaurants.controller.ts index 27d684a..4876b40 100644 --- a/src/modules/restaurants/controllers/restaurants.controller.ts +++ b/src/modules/restaurants/controllers/restaurants.controller.ts @@ -89,5 +89,14 @@ export class RestaurantsController { return this.restaurantsService.findOneBySubscriptionId(subscriptionId); } + @UseGuards(SuperAdminAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Update a restaurant by ID' }) + @ApiParam({ name: 'id', required: true, description: 'Restaurant ID' }) + @ApiBody({ type: UpdateRestaurantDto }) + @Patch('super-admin/restaurants/:id') + updateRestaurant(@Param('id') id: string, @Body() updateRestaurantDto: UpdateRestaurantDto) { + return this.restaurantsService.update(id, updateRestaurantDto); + } } diff --git a/src/modules/roles/controllers/roles.controller.ts b/src/modules/roles/controllers/roles.controller.ts index 2269181..f727fc0 100644 --- a/src/modules/roles/controllers/roles.controller.ts +++ b/src/modules/roles/controllers/roles.controller.ts @@ -5,30 +5,35 @@ import { PermissionsService } from '../providers/permissions.service'; import { CreateRoleDto } from '../dto/create-role.dto'; import { UpdateRoleDto } from '../dto/update-role.dto'; import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard'; +import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard'; import { Permissions } from 'src/common/decorators/permissions.decorator'; import { RestId } from 'src/common/decorators'; import { AdminId } from 'src/common/decorators/admin-id.decorator'; import { Permission } from 'src/common/enums/permission.enum'; -@UseGuards(AdminAuthGuard) -@Permissions(Permission.MANAGE_ROLES) -@ApiBearerAuth() + @ApiTags('roles') -@Controller('admin/roles') +@Controller() export class RolesController { constructor( private readonly roleService: RolesService, private readonly permissionService: PermissionsService, ) { } - @Get() + @Get('admin/roles') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ROLES) + @ApiBearerAuth() @ApiOperation({ summary: 'Get all through restaurant roles with pagination and filters' }) findAll(@RestId() restId: string) { return this.roleService.findAllGeneralAndRestaurantRoles(restId); } - @Get('permissions') + @Get('admin/roles/permissions') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ROLES) + @ApiBearerAuth() @ApiOperation({ summary: 'Get all permissions that the admin has' }) async findAllPermissions(@AdminId() adminId: string, @RestId() restId: string) { const adminPermissionNames = await this.permissionService.getAdminFullPermissions(adminId, restId); @@ -36,29 +41,53 @@ export class RolesController { return adminPermissionNames; } - @Post() + + + @Post('admin/roles') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ROLES) + @ApiBearerAuth() @ApiOperation({ summary: 'Create a new role' }) @ApiBody({ type: CreateRoleDto }) create(@Body() dto: CreateRoleDto, @RestId() restId: string) { return this.roleService.createRestaurantRole(dto, restId); } - @Get(':id') + @Get('admin/roles/:id') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ROLES) + @ApiBearerAuth() @ApiOperation({ summary: 'Get a specific role by ID' }) findOne(@Param('id') id: string, @RestId() restId: string) { return this.roleService.findOne(restId, id); } - @Patch(':id') + @Patch('admin/roles/:id') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ROLES) + @ApiBearerAuth() @ApiOperation({ summary: 'Update a role' }) @ApiBody({ type: UpdateRoleDto }) update(@Param('id') id: string, @Body() dto: UpdateRoleDto, @RestId() restId: string) { return this.roleService.update(restId, id, dto); } - @Delete(':id') + @Delete('admin/roles/:id') + @UseGuards(AdminAuthGuard) + @Permissions(Permission.MANAGE_ROLES) + @ApiBearerAuth() @ApiOperation({ summary: 'Delete a role' }) remove(@Param('id') id: string, @RestId() restId: string) { return this.roleService.remove(restId, id); } + + /** Super Admin Endpoints */ + @UseGuards(SuperAdminAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Get all system roles for super-admin' }) + @Get('super-admin/system-roles') + @ApiOperation({ summary: 'Get all system roles for super-admin' }) + findAllSystemRoles() { + return this.roleService.findAllSystemRoles(); + } } diff --git a/src/modules/roles/providers/roles.service.ts b/src/modules/roles/providers/roles.service.ts index f818308..3182035 100644 --- a/src/modules/roles/providers/roles.service.ts +++ b/src/modules/roles/providers/roles.service.ts @@ -104,6 +104,18 @@ export class RolesService { return role; } + async findAllSystemRoles() { + const roles = await this.roleRepository.find( + { isSystem: true }, + { + orderBy: { createdAt: 'desc' }, + populate: ['permissions', 'restaurant'], + }, + ); + + return roles; + } + async remove(restId: string, id: string) { const role = await this.roleRepository.findOne( { id, restaurant: { id: restId } },