refactor: changed project functions logic of permissions
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class TMaddingSomeNewPermissionsToTheEnum1783428145772 implements MigrationInterface {
|
||||
name = 'TMaddingSomeNewPermissionsToTheEnum1783428145772'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TYPE "public"."permission_name_enum" RENAME TO "permission_name_enum_old"`);
|
||||
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum" AS ENUM('services', 'customers', 'agents', 'developers', 'invoices', 'transactions', 'discounts', 'admins', 'tickets', 'criticisms', 'contacts_us', 'advertisements', 'announcements', 'blogs', 'learnings', 'logs', 'settings', 'bank_accounts', 'payments', 'manage_sso_clients', 'support_plan', 'dmenu', 'dkala', 'dpage', 'dmail', 'reseller', 'workspace', 'view_all_workspaces', 'project', 'view_all_projects', 'task', 'task_phase', 'remark')`);
|
||||
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum" USING "name"::"text"::"public"."permission_name_enum"`);
|
||||
await queryRunner.query(`DROP TYPE "public"."permission_name_enum_old"`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum_old" AS ENUM('services', 'customers', 'agents', 'developers', 'invoices', 'transactions', 'discounts', 'admins', 'tickets', 'criticisms', 'contacts_us', 'advertisements', 'announcements', 'blogs', 'learnings', 'logs', 'settings', 'bank_accounts', 'payments', 'manage_sso_clients', 'support_plan', 'dmenu', 'dkala', 'dpage', 'dmail', 'reseller', 'workspace', 'project', 'task_phase')`);
|
||||
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum_old" USING "name"::"text"::"public"."permission_name_enum_old"`);
|
||||
await queryRunner.query(`DROP TYPE "public"."permission_name_enum"`);
|
||||
await queryRunner.query(`ALTER TYPE "public"."permission_name_enum_old" RENAME TO "permission_name_enum"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -922,14 +922,15 @@ export const enum WorkSpaceMessage {
|
||||
USERS_DONT_BELONG_TO_THIS_WORKSPACE = "کاربران تعیین شده برای این فضای کاری نیستند!",
|
||||
WORKSPACE_SAME_NAME_EXISTS = "فضای کاری با این اسم از قبل وجود دارد!",
|
||||
WORKSPACE_ID_PARAM_NOT_EMPTY = "پارامتر شناسه فضای کار نباید خالی باشد!",
|
||||
WORKSPACE_ID_UUID = "شناسه فضای کار باید uuid باشد"
|
||||
WORKSPACE_ID_UUID = "شناسه فضای کار باید uuid باشد",
|
||||
FORBIDDEN = "شما اجازه دسترسی به این فضای کار را ندارید و یا عضو آن نیستید!"
|
||||
}
|
||||
|
||||
export const enum ProjectMessage {
|
||||
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
|
||||
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!",
|
||||
PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید.",
|
||||
NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!"
|
||||
NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!",
|
||||
}
|
||||
|
||||
export const enum TaskPhaseMessage {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
import { UserDec } from "../../../common/decorators/user.decorator";
|
||||
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
import { ITokenPayload } from "../../auth/interfaces/IToken-payload";
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@@ -19,24 +20,6 @@ import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
export class ProjectController {
|
||||
constructor(private readonly projectService: ProjectService) {}
|
||||
|
||||
@Get()
|
||||
@PermissionsDec(PermissionEnum.PROJECT)
|
||||
@ApiOperation({ summary: "Get all projects, optionally filtered by workspace" })
|
||||
@ApiResponse({ status: 200, description: "Paginated list of projects" })
|
||||
findAll(@Query() pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
return this.projectService.findAll(pagination);
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
@PermissionsDec(PermissionEnum.PROJECT)
|
||||
@ApiOperation({ summary: "Get a project by ID" })
|
||||
@ApiParam({ name: "id", description: "Project ID" })
|
||||
@ApiResponse({ status: 200, description: "Project found", type: TMProject })
|
||||
@ApiResponse({ status: 404, description: "Project not found" })
|
||||
findOne(@Param("id") id: string): Promise<TMProject> {
|
||||
return this.projectService.findOneOrFail(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@PermissionsDec(PermissionEnum.PROJECT)
|
||||
@ApiOperation({ summary: "Create a new project" })
|
||||
@@ -69,26 +52,23 @@ export class ProjectController {
|
||||
}
|
||||
|
||||
@Get("user/workspace/:id")
|
||||
@ApiOperation({ summary: "Get user projects!" })
|
||||
@ApiOperation({ summary: "Get user projects in a specific workspace!" })
|
||||
@ApiResponse({ status: 200, description: "Got user projects successfully!" })
|
||||
@ApiResponse({status: 400, description: "Bad Request!"})
|
||||
findUserProjects(
|
||||
@UserDec("id") userId: string,
|
||||
@Param() paramDto : ParamDto,
|
||||
@ApiResponse({ status: 400, description: "Bad Request!" })
|
||||
findUserProjectsByWorkspace(
|
||||
@UserDec() user: ITokenPayload,
|
||||
@Param() paramDto: ParamDto,
|
||||
@Query() pagination: PaginationDto,
|
||||
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
return this.projectService.findUserProjects(userId, paramDto.id, pagination);
|
||||
return this.projectService.findUserProjectsByWorkspace(user.id, user.permissions, paramDto.id, pagination);
|
||||
}
|
||||
|
||||
@Get("project/:id")
|
||||
@ApiOperation({summary: "Get project detail"})
|
||||
@ApiResponse({status: 200, description: "Got Project Detail Successfully!"})
|
||||
@ApiResponse({status: 400, description: "Bad request!"})
|
||||
@ApiResponse({status: 404, description: "The project was not found!"})
|
||||
getProjectDetail(@Param() paramDto: ParamDto,
|
||||
@UserDec('id') userId: string
|
||||
): Promise<TMProject | null> {
|
||||
return this.projectService.getProjectDetail(paramDto.id, userId);
|
||||
@ApiOperation({ summary: "Get project detail" })
|
||||
@ApiResponse({ status: 200, description: "Got Project Detail Successfully!" })
|
||||
@ApiResponse({ status: 400, description: "Bad request!" })
|
||||
@ApiResponse({ status: 404, description: "The project was not found!" })
|
||||
getProjectDetail(@Param() paramDto: ParamDto, @UserDec() user: ITokenPayload): Promise<TMProject | null> {
|
||||
return this.projectService.getProjectDetail(paramDto.id, user.id, user.permissions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
|
||||
import { WorkspaceService } from "./workspace.service";
|
||||
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
|
||||
@Injectable()
|
||||
export class ProjectService {
|
||||
@@ -19,29 +20,6 @@ export class ProjectService {
|
||||
private readonly userRepository: Repository<User>,
|
||||
) {}
|
||||
|
||||
async findAll(pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
const page = pagination.page ?? 1;
|
||||
const limit = pagination.limit ?? 10;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [projects, count] = await this.projectRepository.findAndCount({
|
||||
skip: skip,
|
||||
take: limit,
|
||||
relations: {
|
||||
users: true,
|
||||
},
|
||||
select: {
|
||||
users: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return { projects, count, paginate: true };
|
||||
}
|
||||
|
||||
async findOneOrFail(id: string): Promise<TMProject> {
|
||||
const project = await this.projectRepository.findOne({ where: { id } });
|
||||
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||
@@ -124,21 +102,36 @@ export class ProjectService {
|
||||
return project;
|
||||
}
|
||||
|
||||
async findUserProjects(
|
||||
async findUserProjectsByWorkspace(
|
||||
userId: string,
|
||||
permissions: PermissionEnum[],
|
||||
wsId: string,
|
||||
pagination: PaginationDto,
|
||||
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
const workspace = await this.workspaceService.findOneOrFail(wsId);
|
||||
|
||||
const page = pagination.page ?? 1;
|
||||
const limit = pagination.limit ?? 10;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [projects, count] = await this.projectRepository.findUserProjects(userId, wsId, skip, limit);
|
||||
const isPermissionIncluded = permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS);
|
||||
const isUserMemeberOfWorkspace = workspace.users.some((user) => user.id === userId);
|
||||
|
||||
var res: [TMProject[], number];
|
||||
if (isUserMemeberOfWorkspace) {
|
||||
res = await this.projectRepository.findUserProjects(userId, wsId, skip, limit);
|
||||
} else if (isPermissionIncluded) {
|
||||
res = await this.projectRepository.findAndCount({ where: { workspaceId: wsId } });
|
||||
} else {
|
||||
throw new ForbiddenException(WorkSpaceMessage.FORBIDDEN);
|
||||
}
|
||||
|
||||
const [projects, count] = res;
|
||||
|
||||
return { projects, count, paginate: true };
|
||||
}
|
||||
|
||||
async getProjectDetail(projectId: string, userId: string): Promise<TMProject | null> {
|
||||
async getProjectDetail(projectId: string, userId: string, permissions: PermissionEnum[]): Promise<TMProject | null> {
|
||||
const project = await this.projectRepository.findOne({
|
||||
where: { id: projectId },
|
||||
relations: {
|
||||
@@ -147,8 +140,9 @@ export class ProjectService {
|
||||
});
|
||||
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||
|
||||
const isUserMember = project.users.some(user => user.id === userId);
|
||||
if(!isUserMember) throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
|
||||
const isUserMember = project.users.some((user) => user.id === userId);
|
||||
if (!isUserMember && !permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS))
|
||||
throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
|
||||
|
||||
const projectDetail = await this.projectRepository.getProjectDetail(projectId);
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ export class WorkspaceService {
|
||||
}
|
||||
|
||||
async findByUser(userId: string, permissions: PermissionEnum[]): Promise<TMWorkspace[]> {
|
||||
if(permissions.includes(PermissionEnum.WORKSPACE)) {
|
||||
if(permissions.includes(PermissionEnum.VIEW_ALL_WORKSPACES)) {
|
||||
return await this.workspaceRepository.find();
|
||||
}
|
||||
return await this.workspaceRepository.findByUser(userId);
|
||||
|
||||
@@ -25,9 +25,9 @@ export enum PermissionEnum {
|
||||
DPAGE = "dpage",
|
||||
DMAIL = 'dmail',
|
||||
RESELLER="reseller",
|
||||
WORKSPACE="workspace",
|
||||
WORKSPACE="workspace", // create, update, remove
|
||||
VIEW_ALL_WORKSPACES="view_all_workspaces",
|
||||
PROJECT="project",
|
||||
PROJECT="project", // create, update, remove
|
||||
VIEW_ALL_PROJECTS="view_all_projects",
|
||||
TASK="task",
|
||||
TASK_PHASE="task_phase",
|
||||
|
||||
Reference in New Issue
Block a user