Merge pull request #21 from internship-humic/feat/slug-assign-remove-member

feat(project): menambahkan slug pada assign-member dan remove-member dari project
This commit is contained in:
Muhammad Zhafran Ilham
2026-06-27 22:19:58 +07:00
committed by GitHub
2 changed files with 31 additions and 11 deletions
@@ -534,10 +534,10 @@ class ProjectService {
const { id_project, id_user } = payload; const { id_project, id_user } = payload;
if (!id_project || !id_user) { if (!id_project || !id_user) {
return error(new BadRequestError("Project ID and User ID are required")); return error(new BadRequestError("Project ID/slug and User ID are required"));
} }
const project = await projectRepository.findById(id_project); const project = await projectRepository.findByIdOrSlug(id_project);
if (!project) { if (!project) {
return error(new NotFoundError("Project not found")); return error(new NotFoundError("Project not found"));
} }
@@ -556,7 +556,7 @@ class ProjectService {
const activeMemberships = await projectRepository.findActiveMembershipsByUserIds([id_user]); const activeMemberships = await projectRepository.findActiveMembershipsByUserIds([id_user]);
if (activeMemberships.length > 0) { if (activeMemberships.length > 0) {
const activeProj = activeMemberships[0].project; const activeProj = activeMemberships[0].project;
if (activeMemberships[0].id_project === parseInt(id_project)) { if (activeMemberships[0].id_project === project.id) {
return error(new ConflictError("User is already an active member of this project")); return error(new ConflictError("User is already an active member of this project"));
} else { } else {
return error( return error(
@@ -567,7 +567,7 @@ class ProjectService {
} }
} }
const existingMembership = await projectRepository.findMembership(id_project, id_user); const existingMembership = await projectRepository.findMembership(project.id, id_user);
let membership; let membership;
if (existingMembership) { if (existingMembership) {
@@ -603,10 +603,10 @@ class ProjectService {
const { id_project, id_user } = payload; const { id_project, id_user } = payload;
if (!id_project || !id_user) { if (!id_project || !id_user) {
return error(new BadRequestError("Project ID and User ID are required")); return error(new BadRequestError("Project ID/slug and User ID are required"));
} }
const project = await projectRepository.findById(id_project); const project = await projectRepository.findByIdOrSlug(id_project);
if (!project) { if (!project) {
return error(new NotFoundError("Project not found")); return error(new NotFoundError("Project not found"));
} }
@@ -616,7 +616,13 @@ class ProjectService {
return error(new NotFoundError("User not found or inactive")); return error(new NotFoundError("User not found or inactive"));
} }
const existingMembership = await projectRepository.findMembership(id_project, id_user); if (user.role !== "intern") {
return error(
new ForbiddenError("Access denied: only interns can be removed from projects")
);
}
const existingMembership = await projectRepository.findMembership(project.id, id_user);
if (!existingMembership || existingMembership.status !== 'active') { if (!existingMembership || existingMembership.status !== 'active') {
return error(new BadRequestError("User is not an active member of this project")); return error(new BadRequestError("User is not an active member of this project"));
+16 -2
View File
@@ -825,8 +825,15 @@ router.get('/interns', verifyJWT, isMentorOrAdmin, projectController.getInterns)
* - id_user * - id_user
* properties: * properties:
* id_project: * id_project:
* type: integer * oneOf:
* - type: integer
* example: 1 * example: 1
* description: Project ID
* - type: string
* example: internify-lms
* description: Project slug
* description: Project ID or project slug
* example: internify-platform-dev
* id_user: * id_user:
* type: integer * type: integer
* example: 2 * example: 2
@@ -872,8 +879,15 @@ router.post('/assign-member', verifyJWT, isMentorOrAdmin, projectController.assi
* - id_user * - id_user
* properties: * properties:
* id_project: * id_project:
* type: integer * oneOf:
* - type: integer
* example: 1 * example: 1
* description: Project ID
* - type: string
* example: internify-lms
* description: Project slug
* description: Project ID or slug
* example: internify-lms
* id_user: * id_user:
* type: integer * type: integer
* example: 2 * example: 2