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 = "کاربران تعیین شده برای این فضای کاری نیستند!",
|
USERS_DONT_BELONG_TO_THIS_WORKSPACE = "کاربران تعیین شده برای این فضای کاری نیستند!",
|
||||||
WORKSPACE_SAME_NAME_EXISTS = "فضای کاری با این اسم از قبل وجود دارد!",
|
WORKSPACE_SAME_NAME_EXISTS = "فضای کاری با این اسم از قبل وجود دارد!",
|
||||||
WORKSPACE_ID_PARAM_NOT_EMPTY = "پارامتر شناسه فضای کار نباید خالی باشد!",
|
WORKSPACE_ID_PARAM_NOT_EMPTY = "پارامتر شناسه فضای کار نباید خالی باشد!",
|
||||||
WORKSPACE_ID_UUID = "شناسه فضای کار باید uuid باشد"
|
WORKSPACE_ID_UUID = "شناسه فضای کار باید uuid باشد",
|
||||||
|
FORBIDDEN = "شما اجازه دسترسی به این فضای کار را ندارید و یا عضو آن نیستید!"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum ProjectMessage {
|
export const enum ProjectMessage {
|
||||||
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
|
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
|
||||||
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!",
|
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!",
|
||||||
PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید.",
|
PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید.",
|
||||||
NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!"
|
NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum TaskPhaseMessage {
|
export const enum TaskPhaseMessage {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { PermissionEnum } from "../../users/enums/permission.enum";
|
|||||||
import { UserDec } from "../../../common/decorators/user.decorator";
|
import { UserDec } from "../../../common/decorators/user.decorator";
|
||||||
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
||||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||||
|
import { ITokenPayload } from "../../auth/interfaces/IToken-payload";
|
||||||
|
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
@AdminRoute()
|
@AdminRoute()
|
||||||
@@ -19,24 +20,6 @@ import { ParamDto } from "../../../common/DTO/param.dto";
|
|||||||
export class ProjectController {
|
export class ProjectController {
|
||||||
constructor(private readonly projectService: ProjectService) {}
|
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()
|
@Post()
|
||||||
@PermissionsDec(PermissionEnum.PROJECT)
|
@PermissionsDec(PermissionEnum.PROJECT)
|
||||||
@ApiOperation({ summary: "Create a new project" })
|
@ApiOperation({ summary: "Create a new project" })
|
||||||
@@ -69,26 +52,23 @@ export class ProjectController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get("user/workspace/:id")
|
@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: 200, description: "Got user projects successfully!" })
|
||||||
@ApiResponse({status: 400, description: "Bad Request!"})
|
@ApiResponse({ status: 400, description: "Bad Request!" })
|
||||||
findUserProjects(
|
findUserProjectsByWorkspace(
|
||||||
@UserDec("id") userId: string,
|
@UserDec() user: ITokenPayload,
|
||||||
@Param() paramDto : ParamDto,
|
@Param() paramDto: ParamDto,
|
||||||
@Query() pagination: PaginationDto,
|
@Query() pagination: PaginationDto,
|
||||||
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
): 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")
|
@Get("project/:id")
|
||||||
@ApiOperation({summary: "Get project detail"})
|
@ApiOperation({ summary: "Get project detail" })
|
||||||
@ApiResponse({status: 200, description: "Got Project Detail Successfully!"})
|
@ApiResponse({ status: 200, description: "Got Project Detail Successfully!" })
|
||||||
@ApiResponse({status: 400, description: "Bad request!"})
|
@ApiResponse({ status: 400, description: "Bad request!" })
|
||||||
@ApiResponse({status: 404, description: "The project was not found!"})
|
@ApiResponse({ status: 404, description: "The project was not found!" })
|
||||||
getProjectDetail(@Param() paramDto: ParamDto,
|
getProjectDetail(@Param() paramDto: ParamDto, @UserDec() user: ITokenPayload): Promise<TMProject | null> {
|
||||||
@UserDec('id') userId: string
|
return this.projectService.getProjectDetail(paramDto.id, user.id, user.permissions);
|
||||||
): Promise<TMProject | null> {
|
|
||||||
return this.projectService.getProjectDetail(paramDto.id, userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
|||||||
import { User } from "../../users/entities/user.entity";
|
import { User } from "../../users/entities/user.entity";
|
||||||
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
|
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
|
||||||
import { WorkspaceService } from "./workspace.service";
|
import { WorkspaceService } from "./workspace.service";
|
||||||
|
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProjectService {
|
export class ProjectService {
|
||||||
@@ -19,29 +20,6 @@ export class ProjectService {
|
|||||||
private readonly userRepository: Repository<User>,
|
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> {
|
async findOneOrFail(id: string): Promise<TMProject> {
|
||||||
const project = await this.projectRepository.findOne({ where: { id } });
|
const project = await this.projectRepository.findOne({ where: { id } });
|
||||||
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||||
@@ -124,21 +102,36 @@ export class ProjectService {
|
|||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findUserProjects(
|
async findUserProjectsByWorkspace(
|
||||||
userId: string,
|
userId: string,
|
||||||
|
permissions: PermissionEnum[],
|
||||||
wsId: string,
|
wsId: string,
|
||||||
pagination: PaginationDto,
|
pagination: PaginationDto,
|
||||||
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||||
|
const workspace = await this.workspaceService.findOneOrFail(wsId);
|
||||||
|
|
||||||
const page = pagination.page ?? 1;
|
const page = pagination.page ?? 1;
|
||||||
const limit = pagination.limit ?? 10;
|
const limit = pagination.limit ?? 10;
|
||||||
const skip = (page - 1) * limit;
|
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 };
|
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({
|
const project = await this.projectRepository.findOne({
|
||||||
where: { id: projectId },
|
where: { id: projectId },
|
||||||
relations: {
|
relations: {
|
||||||
@@ -147,8 +140,9 @@ export class ProjectService {
|
|||||||
});
|
});
|
||||||
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||||
|
|
||||||
const isUserMember = project.users.some(user => user.id === userId);
|
const isUserMember = project.users.some((user) => user.id === userId);
|
||||||
if(!isUserMember) throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
|
if (!isUserMember && !permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS))
|
||||||
|
throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
|
||||||
|
|
||||||
const projectDetail = await this.projectRepository.getProjectDetail(projectId);
|
const projectDetail = await this.projectRepository.getProjectDetail(projectId);
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class WorkspaceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findByUser(userId: string, permissions: PermissionEnum[]): Promise<TMWorkspace[]> {
|
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.find();
|
||||||
}
|
}
|
||||||
return await this.workspaceRepository.findByUser(userId);
|
return await this.workspaceRepository.findByUser(userId);
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ export enum PermissionEnum {
|
|||||||
DPAGE = "dpage",
|
DPAGE = "dpage",
|
||||||
DMAIL = 'dmail',
|
DMAIL = 'dmail',
|
||||||
RESELLER="reseller",
|
RESELLER="reseller",
|
||||||
WORKSPACE="workspace",
|
WORKSPACE="workspace", // create, update, remove
|
||||||
VIEW_ALL_WORKSPACES="view_all_workspaces",
|
VIEW_ALL_WORKSPACES="view_all_workspaces",
|
||||||
PROJECT="project",
|
PROJECT="project", // create, update, remove
|
||||||
VIEW_ALL_PROJECTS="view_all_projects",
|
VIEW_ALL_PROJECTS="view_all_projects",
|
||||||
TASK="task",
|
TASK="task",
|
||||||
TASK_PHASE="task_phase",
|
TASK_PHASE="task_phase",
|
||||||
|
|||||||
Reference in New Issue
Block a user