|
72 | 72 | import org.springframework.data.domain.Pageable; |
73 | 73 | import org.springframework.data.rest.webmvc.BasePathAwareController; |
74 | 74 | import org.springframework.data.rest.webmvc.RepositoryLinksResource; |
| 75 | +import org.springframework.data.rest.webmvc.ResourceNotFoundException; |
75 | 76 | import org.springframework.hateoas.*; |
76 | 77 | import org.springframework.hateoas.server.RepresentationModelProcessor; |
77 | 78 | import org.springframework.http.HttpStatus; |
|
80 | 81 | import org.springframework.security.access.AccessDeniedException; |
81 | 82 | import org.springframework.security.access.prepost.PreAuthorize; |
82 | 83 | import org.springframework.web.bind.annotation.*; |
83 | | -import org.springframework.web.client.HttpClientErrorException; |
84 | 84 | import org.springframework.web.multipart.MultipartFile; |
85 | 85 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; |
86 | 86 |
|
@@ -386,36 +386,85 @@ public ResponseEntity<CollectionModel<EntityModel<Component>>> searchByExternalI |
386 | 386 | @PreAuthorize("hasAuthority('WRITE')") |
387 | 387 | @Operation( |
388 | 388 | summary = "Update an existing component.", |
389 | | - description = "Update an existing component by its id.", |
390 | | - tags = {"Components"} |
| 389 | + description = "Partially update an existing component. Only provided fields will be updated. " + |
| 390 | + "If the user lacks direct write access, a moderation request will be created. " + |
| 391 | + "Include a 'comment' field in the request body when submitting moderation requests.", |
| 392 | + tags = {"Components"}, |
| 393 | + responses = { |
| 394 | + @ApiResponse(responseCode = "200", description = "Component updated successfully"), |
| 395 | + @ApiResponse(responseCode = "202", description = "Moderation request created"), |
| 396 | + @ApiResponse(responseCode = "400", description = "Invalid input or missing required fields"), |
| 397 | + @ApiResponse(responseCode = "401", description = "Unauthorized"), |
| 398 | + @ApiResponse(responseCode = "403", description = "Write access forbidden"), |
| 399 | + @ApiResponse(responseCode = "404", description = "Component not found") |
| 400 | + } |
391 | 401 | ) |
392 | 402 | @RequestMapping(value = COMPONENTS_URL + "/{id}", method = RequestMethod.PATCH) |
393 | 403 | public ResponseEntity<EntityModel<Component>> patchComponent( |
394 | 404 | @Parameter(description = "The id of the component to be updated.") |
395 | 405 | @PathVariable("id") String id, |
396 | | - @Parameter(description = "The component with updated fields.") |
397 | | - @RequestBody ComponentDTO updateComponentDto, |
398 | | - @Parameter(description = "Comment message.") |
399 | | - @RequestParam(value = "comment", required = false) String comment |
| 406 | + @Parameter(description = "Updated component fields. Add 'comment' field in body for moderation request.") |
| 407 | + @RequestBody ComponentDTO updateComponentDto |
400 | 408 | ) throws TException { |
401 | | - User user = restControllerHelper.getSw360UserFromAuthentication(); |
402 | | - Component sw360Component = componentService.getComponentForUserById(id, user); |
403 | | - user.setCommentMadeDuringModerationRequest(comment); |
| 409 | + final User user = restControllerHelper.getSw360UserFromAuthentication(); |
| 410 | + restControllerHelper.throwIfSecurityUser(user); |
| 411 | + Component sw360Component = validateAndGetComponent(id, updateComponentDto, user); |
| 412 | + String comment = extractModerationComment(updateComponentDto); |
404 | 413 | if (!restControllerHelper.isWriteActionAllowed(sw360Component, user) |
405 | 414 | && (comment == null || comment.isBlank())) { |
406 | 415 | throw new BadRequestClientException(RESPONSE_BODY_FOR_MODERATION_REQUEST_WITH_COMMIT.toString()); |
407 | 416 | } |
408 | | - if (updateComponentDto.getAttachments() != null) { |
409 | | - updateComponentDto.getAttachments().forEach(attachment -> wrapSW360Exception( |
410 | | - () -> this.attachmentService.fillCheckedAttachmentData(attachment, user))); |
| 417 | + user.setCommentMadeDuringModerationRequest(comment); |
| 418 | + |
| 419 | + if (updateComponentDto.getAttachments() != null && !updateComponentDto.getAttachments().isEmpty()) { |
| 420 | + updateComponentDto.getAttachments().forEach(attachment -> |
| 421 | + wrapSW360Exception(() -> attachmentService.fillCheckedAttachmentData(attachment, user)) |
| 422 | + ); |
411 | 423 | } |
412 | | - sw360Component = this.restControllerHelper.updateComponent(sw360Component, updateComponentDto); |
| 424 | + |
| 425 | + sw360Component = restControllerHelper.updateComponent(sw360Component, updateComponentDto); |
413 | 426 | RequestStatus updateComponentStatus = componentService.updateComponent(sw360Component, user); |
414 | | - HalResource<Component> userHalResource = createHalComponent(sw360Component, user); |
| 427 | + |
415 | 428 | if (updateComponentStatus == RequestStatus.SENT_TO_MODERATOR) { |
416 | 429 | return new ResponseEntity(RESPONSE_BODY_FOR_MODERATION_REQUEST, HttpStatus.ACCEPTED); |
417 | 430 | } |
418 | | - return new ResponseEntity<>(userHalResource, HttpStatus.OK); |
| 431 | + |
| 432 | + HalResource<Component> halResource = createHalComponent(sw360Component, user); |
| 433 | + return ResponseEntity.ok(halResource); |
| 434 | + } |
| 435 | + |
| 436 | + private String extractModerationComment(ComponentDTO updateComponentDto) { |
| 437 | + try { |
| 438 | + String comment = updateComponentDto.getComment(); |
| 439 | + return (comment != null && !comment.isBlank()) ? comment.trim() : null; |
| 440 | + } catch (Exception e) { |
| 441 | + log.debug("Comment field not available in ComponentDTO: {}", e.getMessage()); |
| 442 | + return null; |
| 443 | + } |
| 444 | + } |
| 445 | + |
| 446 | + |
| 447 | + private Component validateAndGetComponent(String id, ComponentDTO updateComponentDto, User user) { |
| 448 | + if (isNullOrEmpty(id)) { |
| 449 | + throw new BadRequestClientException("Component ID cannot be null or empty"); |
| 450 | + } |
| 451 | + |
| 452 | + Component sw360Component; |
| 453 | + try { |
| 454 | + sw360Component = componentService.getComponentForUserById(id, user); |
| 455 | + } catch (Exception e) { |
| 456 | + throw new ResourceNotFoundException("Component not found with ID: " + id); |
| 457 | + } |
| 458 | + |
| 459 | + if (sw360Component == null) { |
| 460 | + throw new ResourceNotFoundException("Component not found with ID: " + id); |
| 461 | + } |
| 462 | + |
| 463 | + if (updateComponentDto == null) { |
| 464 | + throw new BadRequestClientException("Component data cannot be null"); |
| 465 | + } |
| 466 | + |
| 467 | + return sw360Component; |
419 | 468 | } |
420 | 469 |
|
421 | 470 | @PreAuthorize("hasAuthority('WRITE')") |
|
0 commit comments