Files
ContentGen_BE/src/modules/admin/admin.controller.ts
Harun CAN 013b2856bc
Some checks failed
Backend Deploy 🚀 / build-and-deploy (push) Has been cancelled
main
2026-03-30 15:18:20 +03:00

384 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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';
import { AdminService } from './admin.service';
@ApiTags('Admin')
@ApiBearerAuth()
@Controller('admin')
@Roles('admin')
export class AdminController {
constructor(
private readonly prisma: PrismaService,
private readonly adminService: AdminService,
@Inject(CACHE_MANAGER) private cacheManager: cacheManager.Cache,
) {}
// ================== System Stats ==================
@Get('stats')
@ApiOperation({ summary: 'Sistem istatistiklerini getir' })
async getSystemStats(): Promise<ApiResponse<any>> {
const stats = await this.adminService.getSystemStats();
return createSuccessResponse(stats);
}
// ================== Plan Management ==================
@Get('plans')
@ApiOperation({ summary: 'Tüm planları getir (admin detay)' })
async getAllPlans(): Promise<ApiResponse<any>> {
const plans = await this.adminService.getAllPlans();
return createSuccessResponse(plans);
}
@Put('plans/:id')
@ApiOperation({ summary: 'Plan güncelle' })
async updatePlan(
@Param('id') id: string,
@Body() data: any,
): Promise<ApiResponse<any>> {
const plan = await this.adminService.updatePlan(id, data);
return createSuccessResponse(plan, 'Plan güncellendi');
}
// ================== Credit Management ==================
@Post('users/:userId/credits')
@ApiOperation({ summary: 'Kullanıcıya kredi ver' })
async grantCredits(
@Param('userId') userId: string,
@Body() data: { amount: number; description: string },
): Promise<ApiResponse<any>> {
const tx = await this.adminService.grantCredits(userId, data.amount, data.description);
return createSuccessResponse(tx, 'Kredi yüklendi');
}
// ================== User Detail ==================
@Get('users/:id/detail')
@ApiOperation({ summary: 'Kullanıcı detay — abonelik, projeler, krediler' })
async getUserDetail(
@Param('id') id: string,
): Promise<ApiResponse<any>> {
const user = await this.adminService.getUserDetail(id);
return createSuccessResponse(user);
}
// ================== 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 },
});
await this.cacheManager.del('roles_list');
return createSuccessResponse(null, 'Permission removed from role');
}
// ================== Project Management (Admin) ==================
@Get('projects')
@ApiOperation({ summary: 'Tüm projeleri getir (admin)' })
async getAllProjects(
@Query() query: { page?: number; limit?: number; status?: string; userId?: string },
): Promise<ApiResponse<any>> {
const result = await this.adminService.getAllProjects({
page: query.page ? Number(query.page) : 1,
limit: query.limit ? Number(query.limit) : 20,
status: query.status,
userId: query.userId,
});
return createSuccessResponse(result);
}
@Delete('projects/:id')
@ApiOperation({ summary: 'Projeyi sil (soft delete)' })
async adminDeleteProject(@Param('id') id: string): Promise<ApiResponse<any>> {
const result = await this.adminService.adminDeleteProject(id);
return createSuccessResponse(result, 'Proje silindi');
}
// ================== Render Job Management (Admin) ==================
@Get('render-jobs')
@ApiOperation({ summary: 'Tüm render jobları getir (admin)' })
async getAllRenderJobs(
@Query() query: { page?: number; limit?: number; status?: string },
): Promise<ApiResponse<any>> {
const result = await this.adminService.getAllRenderJobs({
page: query.page ? Number(query.page) : 1,
limit: query.limit ? Number(query.limit) : 20,
status: query.status,
});
return createSuccessResponse(result);
}
// ================== Ban / Activate User ==================
@Put('users/:id/ban')
@ApiOperation({ summary: 'Kullanıcıyı banla' })
async banUser(@Param('id') id: string): Promise<ApiResponse<any>> {
const user = await this.adminService.setUserActive(id, false);
return createSuccessResponse(
plainToInstance(UserResponseDto, user),
'Kullanıcı banlandı',
);
}
@Put('users/:id/activate')
@ApiOperation({ summary: 'Kullanıcıyı aktif et' })
async activateUser(@Param('id') id: string): Promise<ApiResponse<any>> {
const user = await this.adminService.setUserActive(id, true);
return createSuccessResponse(
plainToInstance(UserResponseDto, user),
'Kullanıcı aktif edildi',
);
}
}