Files
skript-be-v2/src/modules/admin/admin.controller.ts
Fahri Can Seçer 02ecfada63
Some checks failed
CI / build (push) Successful in 1m16s
Deploy Backend / build-and-deploy (push) Failing after 13m4s
main
2026-02-07 00:20:27 +03:00

271 lines
7.5 KiB
TypeScript

import {
Controller,
Get,
Post,
Put,
Delete,
Param,
Body,
Query,
UseInterceptors,
Inject,
} from '@nestjs/common';
import {
CacheInterceptor,
CacheKey,
CacheTTL,
CACHE_MANAGER,
} from '@nestjs/cache-manager';
import * as cacheManager from 'cache-manager';
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
import { Roles } from '../../common/decorators';
import { PrismaService } from '../../database/prisma.service';
import { PaginationDto } from '../../common/dto/pagination.dto';
import {
ApiResponse,
createSuccessResponse,
createPaginatedResponse,
PaginatedData,
} from '../../common/types/api-response.type';
import { plainToInstance } from 'class-transformer';
import { UserResponseDto } from '../users/dto/user.dto';
import {
PermissionResponseDto,
RolePermissionResponseDto,
RoleResponseDto,
UserRoleResponseDto,
} from './dto/admin.dto';
@ApiTags('Admin')
@ApiBearerAuth()
@Controller('admin')
@Roles('admin')
export class AdminController {
constructor(
private readonly prisma: PrismaService,
@Inject(CACHE_MANAGER) private cacheManager: cacheManager.Cache,
) {}
// ================== Users Management ==================
@Get('users')
@ApiOperation({ summary: 'Get all users (admin)' })
async getAllUsers(
@Query() pagination: PaginationDto,
): Promise<ApiResponse<PaginatedData<UserResponseDto>>> {
const { skip, take, orderBy } = pagination;
const [users, total] = await Promise.all([
this.prisma.user.findMany({
skip,
take,
orderBy,
include: {
roles: {
include: {
role: true,
},
},
},
}),
this.prisma.user.count(),
]);
const dtos = plainToInstance(
UserResponseDto,
users,
) as unknown as UserResponseDto[];
return createPaginatedResponse(
dtos,
total,
pagination.page || 1,
pagination.limit || 10,
);
}
@Put('users/:id/toggle-active')
@ApiOperation({ summary: 'Toggle user active status' })
async toggleUserActive(
@Param('id') id: string,
): Promise<ApiResponse<UserResponseDto>> {
const user = await this.prisma.user.findUnique({ where: { id } });
const updated = await this.prisma.user.update({
where: { id },
data: { isActive: !user?.isActive },
});
return createSuccessResponse(
plainToInstance(UserResponseDto, updated),
'User status updated',
);
}
@Post('users/:userId/roles/:roleId')
@ApiOperation({ summary: 'Assign role to user' })
async assignRole(
@Param('userId') userId: string,
@Param('roleId') roleId: string,
): Promise<ApiResponse<UserRoleResponseDto>> {
const userRole = await this.prisma.userRole.create({
data: { userId, roleId },
});
return createSuccessResponse(
plainToInstance(UserRoleResponseDto, userRole),
'Role assigned to user',
);
}
@Delete('users/:userId/roles/:roleId')
@ApiOperation({ summary: 'Remove role from user' })
async removeRole(
@Param('userId') userId: string,
@Param('roleId') roleId: string,
): Promise<ApiResponse<null>> {
await this.prisma.userRole.deleteMany({
where: { userId, roleId },
});
return createSuccessResponse(null, 'Role removed from user');
}
// ================== Roles Management ==================
@Get('roles')
@UseInterceptors(CacheInterceptor)
@CacheKey('roles_list')
@CacheTTL(60 * 1000)
@ApiOperation({ summary: 'Get all roles' })
async getAllRoles(): Promise<ApiResponse<RoleResponseDto[]>> {
const roles = await this.prisma.role.findMany({
include: {
permissions: {
include: {
permission: true,
},
},
_count: {
select: { users: true },
},
},
});
// Transform Prisma structure to DTO structure
const transformedRoles = roles.map((role) => ({
...role,
permissions: role.permissions.map((rp) => rp.permission),
}));
return createSuccessResponse(
plainToInstance(
RoleResponseDto,
transformedRoles,
) as unknown as RoleResponseDto[],
);
}
@Post('roles')
@ApiOperation({ summary: 'Create a new role' })
async createRole(
@Body() data: { name: string; description?: string },
): Promise<ApiResponse<RoleResponseDto>> {
const role = await this.prisma.role.create({ data });
await this.cacheManager.del('roles_list');
return createSuccessResponse(
plainToInstance(RoleResponseDto, role),
'Role created',
201,
);
}
@Put('roles/:id')
@ApiOperation({ summary: 'Update a role' })
async updateRole(
@Param('id') id: string,
@Body() data: { name?: string; description?: string },
): Promise<ApiResponse<RoleResponseDto>> {
const role = await this.prisma.role.update({ where: { id }, data });
await this.cacheManager.del('roles_list');
return createSuccessResponse(
plainToInstance(RoleResponseDto, role),
'Role updated',
);
}
@Delete('roles/:id')
@ApiOperation({ summary: 'Delete a role' })
async deleteRole(@Param('id') id: string): Promise<ApiResponse<null>> {
await this.prisma.role.delete({ where: { id } });
await this.cacheManager.del('roles_list');
return createSuccessResponse(null, 'Role deleted');
}
// ================== Permissions Management ==================
@Get('permissions')
@UseInterceptors(CacheInterceptor)
@CacheKey('permissions_list')
@CacheTTL(60 * 1000)
@ApiOperation({ summary: 'Get all permissions' })
async getAllPermissions(): Promise<ApiResponse<PermissionResponseDto[]>> {
const permissions = await this.prisma.permission.findMany();
return createSuccessResponse(
plainToInstance(
PermissionResponseDto,
permissions,
) as unknown as PermissionResponseDto[],
);
}
@Post('permissions')
@ApiOperation({ summary: 'Create a new permission' })
async createPermission(
@Body()
data: {
name: string;
description?: string;
resource: string;
action: string;
},
): Promise<ApiResponse<PermissionResponseDto>> {
const permission = await this.prisma.permission.create({ data });
await this.cacheManager.del('permissions_list');
return createSuccessResponse(
plainToInstance(PermissionResponseDto, permission),
'Permission created',
201,
);
}
@Post('roles/:roleId/permissions/:permissionId')
@ApiOperation({ summary: 'Assign permission to role' })
async assignPermission(
@Param('roleId') roleId: string,
@Param('permissionId') permissionId: string,
): Promise<ApiResponse<RolePermissionResponseDto>> {
const rolePermission = await this.prisma.rolePermission.create({
data: { roleId, permissionId },
});
// Invalidate roles_list because permissions are nested in roles
await this.cacheManager.del('roles_list');
return createSuccessResponse(
plainToInstance(RolePermissionResponseDto, rolePermission),
'Permission assigned to role',
);
}
@Delete('roles/:roleId/permissions/:permissionId')
@ApiOperation({ summary: 'Remove permission from role' })
async removePermission(
@Param('roleId') roleId: string,
@Param('permissionId') permissionId: string,
): Promise<ApiResponse<null>> {
await this.prisma.rolePermission.deleteMany({
where: { roleId, permissionId },
});
// Invalidate roles_list because permissions are nested in roles
await this.cacheManager.del('roles_list');
return createSuccessResponse(null, 'Permission removed from role');
}
}