+ * {@code + * { + * "logo" : "logo of the group", -> [String] + * "name" : "name of the group", -> [String] + * "group_description": "description of the group", -> [String] + * "members" : [ -> [List of Strings or empty] + * // id of the group member -> [String] + * ], + * "projects" : [ -> [List of Strings or empty] + * // id of the projects -> [String] + * ] + * } + * } + *+ * @return the result of the request as {@link String} + */ + @PostMapping( + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/groups", method = POST) + public String createGroup( + @PathVariable(IDENTIFIER_KEY) String id, + @RequestHeader(TOKEN_KEY) String token, + @ModelAttribute GroupDTO payload + ) { + String isValidRequest = isValidRequest(id, token, payload, false); + if (isValidRequest != null) + return failedResponse(isValidRequest); + try { + groupsHelper.createGroup(me, generateIdentifier(), payload); + } catch (IOException e) { + return failedResponse(WRONG_PROCEDURE_MESSAGE); + } + return successResponse(); + } + + /** + * Method to create edit an existing group + * + * @param id The identifier of the user + * @param token The token of the user + * @param payload: payload of the request + *
+ * {@code + * { + * "logo" : "logo of the group", -> [String] + * "name" : "name of the group", -> [String] + * "group_description": "description of the group", -> [String] + * "members" : [ -> [List of Strings or empty] + * // id of the group member -> [String] + * ], + * "projects" : [ -> [List of Strings or empty] + * // id of the projects -> [String] + * ] + * } + * } + *+ * @return the result of the request as {@link String} + */ + @PostMapping( + path = "/{" + GROUP_IDENTIFIER_KEY + "}", + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/groups/{group_id}", method = POST) + public String editGroup( + @PathVariable(IDENTIFIER_KEY) String id, + @PathVariable(GROUP_IDENTIFIER_KEY) String groupId, + @RequestHeader(TOKEN_KEY) String token, + @ModelAttribute GroupDTO payload + ) { + String isValidRequest = isValidRequest(id, token, payload, true); + if (isValidRequest != null) + return failedResponse(isValidRequest); + if (groupsHelper.getGroup(id, groupId) == null) + return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + try { + groupsHelper.editGroup(me, groupId, payload); + } catch (IOException e) { + return failedResponse(WRONG_PROCEDURE_MESSAGE); + } + return successResponse(); + } + + /** + * Method to check the validity of a request between {@link #createGroup(String, String, GroupDTO)} and + * {@link #editGroup(String, String, String, GroupDTO)} + * + * @param id The identifier of the user + * @param token The token of the user + * @param payload: payload of the request + *
+ * {@code + * { + * "logo" : "logo of the group", -> [String] + * "name" : "name of the group", -> [String] + * "group_description": "description of the group", -> [String] + * "members" : [ -> [List of Strings or empty] + * // id of the group member -> [String] + * ], + * "projects" : [ -> [List of Strings or empty] + * // id of the projects -> [String] + * ] + * } + * } + *+ * @return the result of the validation as {@link String} + */ + private String isValidRequest(String id, String token, GroupDTO payload, boolean editingMode) { + if (!isMe(id, token)) + return WRONG_PROCEDURE_MESSAGE; + String groupName = payload.name(); + MultipartFile logo = payload.logo(); + if (!editingMode && (logo == null || logo.isEmpty())) + return WRONG_GROUP_LOGO_MESSAGE; + if (!INSTANCE.isGroupNameValid(groupName)) + return WRONG_GROUP_NAME_ERROR_MESSAGE; + if (!editingMode && groupsHelper.groupExists(id, groupName)) + return WRONG_GROUP_ALREADY_EXISTS_ERROR_MESSAGE; + String groupDescription = payload.group_description(); + if (!INSTANCE.isGroupDescriptionValid(groupDescription)) + return WRONG_GROUP_DESCRIPTION_ERROR_MESSAGE; + if (!me.getProjectsIds().containsAll(payload.projects())) + return WRONG_PROCEDURE_MESSAGE; + return null; + } + + /** + * Method to get a single group + * + * @param id The identifier of the user + * @param token The token of the user + * @param groupId The identifier of the group to fetch + * + * @return the result of the request as {@link String} + */ + @GetMapping( + path = "/{" + GROUP_IDENTIFIER_KEY + "}", + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/groups/{group_id}", method = GET) + public
+ * {@code + * { + * "id" : "identifier of the member", -> [String] + * "role": "new role of the member" -> [InvitationStatus] + * } + * } + *+ * + * @return the result of the request as {@link String} + */ + @PatchMapping( + path = "/{" + GROUP_IDENTIFIER_KEY + "}" + CHANGE_MEMBER_ROLE_ENDPOINT, + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/groups/{group_id}/changeMemberRole", method = PATCH) + public String changeMemberRole( + @PathVariable(IDENTIFIER_KEY) String id, + @RequestHeader(TOKEN_KEY) String token, + @PathVariable(GROUP_IDENTIFIER_KEY) String groupId, + @RequestBody Map
+ * {@code + * { + * "name" : "name of the project", -> [String] + * "project_description": "description of the project", -> [String] + * "project_version": "current project project_version", -> [String] + * "groups" : [ -> [List of Strings or empty] + * // id of the group -> [String] + * ], + * "project_repository": "the GitHub or Gitlab project's project_repository" -> [String] + * } + * } + *+ * + * @return the result of the request as {@link String} + */ + @PostMapping( + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/projects", method = POST) + public String addProject( + @PathVariable(IDENTIFIER_KEY) String id, + @RequestHeader(TOKEN_KEY) String token, + @ModelAttribute ProjectDTO payload + ) { + return workWithProject(id, token, payload, null); + } + + /** + * Method to edit an existing project + * + * @param id The identifier of the user + * @param token The token of the user + * @param payload: payload of the request + *
+ * {@code + * { + * "name" : "name of the project", -> [String] + * "project_description": "description of the project", -> [String] + * "project_version": "current project project_version", -> [String] + * "groups" : [ -> [List of Strings or empty] + * // id of the group -> [String] + * ], + * "project_repository": "the GitHub or Gitlab project's project_repository" -> [String] + * } + * } + *+ * + * @return the result of the request as {@link String} + */ + @PostMapping( + path = "/{" + PROJECT_IDENTIFIER_KEY + "}", + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/projects/{project_id}", method = PATCH) + public String editProject( + @PathVariable(IDENTIFIER_KEY) String id, + @RequestHeader(TOKEN_KEY) String token, + @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, + @ModelAttribute ProjectDTO payload + ) { + return workWithProject(id, token, payload, projectId); + } + + /** + * Method to add or edit a project + * + * @param id The identifier of the user + * @param token The token of the user + * @param payload: payload of the request + *
+ * {@code + * { + * "name" : "name of the project", -> [String] + * "project_description": "description of the project", -> [String] + * "project_version": "current project project_version", -> [String] + * "groups" : [ -> [List of Strings or empty] + * // id of the group -> [String] + * ], + * "project_repository": "the GitHub or Gitlab project's project_repository" -> [String] + * } + * } + *+ * @param projectId The identifier of the project if exists + * + * @return the result of the request as {@link String} + */ + private String workWithProject(String id, String token, ProjectDTO payload, String projectId) { + if (!isMe(id, token)) + return failedResponse(WRONG_PROCEDURE_MESSAGE); + String name = payload.name(); + if (!INSTANCE.isValidProjectName(name)) + return failedResponse(WRONG_PROJECT_NAME_ERROR_MESSAGE); + boolean isAdding = projectId == null; + if (!isAdding) { + Project currentEditingProject = projectsHelper.getProjectById(projectId); + if (currentEditingProject == null || !currentEditingProject.getAuthor().getId().equals(id)) + return failedResponse(NOT_AUTHORIZED_OR_WRONG_DETAILS_MESSAGE); + } + String description = payload.project_description(); + if (!INSTANCE.isValidProjectDescription(description)) + return failedResponse(WRONG_PROJECT_DESCRIPTION_ERROR_MESSAGE); + String version = payload.project_version(); + if (!INSTANCE.isValidVersion(version)) + return failedResponse(WRONG_PROJECT_VERSION_ERROR_MESSAGE); + String repository = payload.project_repository(); + if (!INSTANCE.isValidRepository(repository)) + return failedResponse(WRONG_PROJECT_REPOSITORY_ERROR_MESSAGE); + if (isAdding) + projectId = generateIdentifier(); + try { + projectsHelper.workWithProject(id, projectId, payload, isAdding); + } catch (Exception e) { + return failedResponse(WRONG_PROJECT_NAME_EXISTS_ERROR_MESSAGE); + } + return successResponse(); + } + + /** + * Method to get a single project + * + * @param id The identifier of the user + * @param token The token of the user + * @param projectId The identifier of the project to fetch + * + * @return the result of the request as {@link String} + */ + @GetMapping( + path = "/{" + PROJECT_IDENTIFIER_KEY + "}", + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/projects/{project_id}", method = GET) + public
+ * {@code + * { + * "target_version": "the target project_version of the update", -> [String] + * "update_change_notes": [ -> [List of Strings or empty] + * // the change note of the update -> [String] + * ] + * } + * } + *+ * + * @return the result of the request as {@link String} + */ + @PostMapping( + path = "/{" + PROJECT_IDENTIFIER_KEY + "}" + UPDATES_PATH + SCHEDULE_UPDATE_ENDPOINT, + headers = { + TOKEN_KEY + } + ) + @RequestPath(path = "/api/v1/users/{id}/projects/{project_id}/updates/schedule", method = POST) + public String scheduleUpdate( + @PathVariable(IDENTIFIER_KEY) String id, + @RequestHeader(TOKEN_KEY) String token, + @PathVariable(PROJECT_IDENTIFIER_KEY) String projectId, + @RequestBody Map
Method to set the CORS filter No any-params required
The com.tecknobit.pandoro.configuration.CORSAdvice
+ class is useful to set the CORS policy
N7ghtm4r3 - Tecknobit