From 1727af1182bba73c63c1cc25c45284f4256e86aa Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Mon, 29 Jul 2024 19:15:55 +0700 Subject: [PATCH 01/15] update doc --- .../market/controller/ProductController.java | 22 +++++++++++++------ .../controller/ProductDetailsController.java | 17 +++++++++----- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 4cfe168b2..b03c8246b 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -8,6 +8,10 @@ import static com.axonivy.market.constants.RequestParamConstants.RESET_SYNC; import static com.axonivy.market.constants.RequestParamConstants.TYPE; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; import org.apache.commons.lang3.time.StopWatch; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -37,6 +41,7 @@ @RestController @RequestMapping(PRODUCT) +@Tag(name = "Product Controller", description = "API collection to get and search products") public class ProductController { private final ProductService productService; @@ -45,18 +50,20 @@ public class ProductController { private final PagedResourcesAssembler pagedResourcesAssembler; public ProductController(ProductService productService, GitHubService gitHubService, ProductModelAssembler assembler, - PagedResourcesAssembler pagedResourcesAssembler) { + PagedResourcesAssembler pagedResourcesAssembler) { this.productService = productService; this.gitHubService = gitHubService; this.assembler = assembler; this.pagedResourcesAssembler = pagedResourcesAssembler; } - @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'") @GetMapping() - public ResponseEntity> findProducts(@RequestParam(name = TYPE) String type, - @RequestParam(required = false, name = KEYWORD) String keyword, - @RequestParam(name = LANGUAGE) String language, Pageable pageable) { + @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'") + public ResponseEntity> findProducts(@RequestParam(name = TYPE) @Parameter(name = "Type", description = "Type of product.", in = ParameterIn.QUERY, + schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) String type, + @RequestParam(required = false, name = KEYWORD) @Parameter(name = "Keyword", description = "Keyword that exist in product's name or short description.", in = ParameterIn.QUERY) String keyword, + @RequestParam(name = LANGUAGE) @Parameter(name = "Language", description = "Language of product short description.", in = ParameterIn.QUERY, + schema = @Schema(allowableValues = {"en", "de"})) String language, @Parameter(name = "Pagination", description = "Pagination configuration for result set") Pageable pageable) { Page results = productService.findProducts(type, keyword, language, pageable); if (results.isEmpty()) { return generateEmptyPagedModel(); @@ -67,8 +74,9 @@ public ResponseEntity> findProducts(@RequestParam(name } @PutMapping(SYNC) + @Operation(hidden = true) public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION) String authorizationHeader, - @RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) { + @RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) { String token = null; if (authorizationHeader.startsWith(CommonConstants.BEARER)) { token = authorizationHeader.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix @@ -96,7 +104,7 @@ public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION @SuppressWarnings("unchecked") private ResponseEntity> generateEmptyPagedModel() { var emptyPagedModel = (PagedModel) pagedResourcesAssembler.toEmptyModel(Page.empty(), - ProductModel.class); + ProductModel.class); return new ResponseEntity<>(emptyPagedModel, HttpStatus.OK); } } diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index b09611dcb..e1735a48c 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -12,6 +12,8 @@ import java.util.List; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; @@ -32,6 +34,7 @@ @RestController @RequestMapping(PRODUCT_DETAILS) +@Tag(name = "Product Detail Controllers", description = "API collection to get product's detail.") public class ProductDetailsController { private final VersionService versionService; private final ProductService productService; @@ -45,22 +48,24 @@ public ProductDetailsController(VersionService versionService, ProductService pr } @GetMapping(BY_ID_AND_TAG) - public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) String id, - @PathVariable(TAG) String tag) { + @Operation(summary = "Find product detail by product id and release tag.", description = "get product detail by it product id and release tag.") + public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) @Parameter(name = "Product id (from meta.json)", example = "portal") String id, + @PathVariable(TAG) @Parameter(name = "Release tag (from git hub repo tags)", example = "10.0.19") String tag) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, tag), HttpStatus.OK); } - @Operation(summary = "increase installation count by 1", description = "update installation count when click download product files by users") @CrossOrigin(originPatterns = "*") @PutMapping(INSTALLATION_COUNT_BY_ID) - public ResponseEntity syncInstallationCount(@PathVariable(ID) String key) { - int result = productService.updateInstallationCountForProduct(key); + @Operation(summary = "Update installation count of product", description = "By default, increase installation count when click download product files by users") + public ResponseEntity syncInstallationCount(@PathVariable(ID) @Parameter(name = "Product id (from meta.json)", example = "portal") String productId) { + int result = productService.updateInstallationCountForProduct(productId); return new ResponseEntity<>(result, HttpStatus.OK); } @GetMapping(BY_ID) - public ResponseEntity findProductDetails(@PathVariable(ID) String id) { + @Operation(summary = "increase installation count by 1", description = "update installation count when click download product files by users") + public ResponseEntity findProductDetails(@PathVariable(ID) @Parameter(name = "Product id (from meta.json)", example = "portal") String id) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, null), HttpStatus.OK); } From ecfcb0d1f877aecd9542f2b27ce25c96997be809 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 02:49:46 +0700 Subject: [PATCH 02/15] update doc --- .../market/controller/FeedbackController.java | 32 ++++++++++++++----- .../controller/ProductDetailsController.java | 15 +++++---- .../axonivy/market/model/FeedbackModel.java | 17 ++++++++++ 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index 74ebf6d0a..cb11ca41e 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -11,12 +11,20 @@ import java.net.URI; import java.util.List; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PagedResourcesAssembler; import org.springframework.hateoas.PagedModel; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -42,6 +50,7 @@ @RestController @RequestMapping(FEEDBACK) +@Tag(name = "User Feedback Controllers", description = "API collection to handle user's feedback.") public class FeedbackController { private final FeedbackService feedbackService; @@ -58,9 +67,9 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService this.pagedResourcesAssembler = pagedResourcesAssembler; } - @Operation(summary = "Find all feedbacks by product id") @GetMapping(PRODUCT_BY_ID) - public ResponseEntity> findFeedbacks(@PathVariable(ID) String productId, + @Operation(summary = "Find feedbacks by product id with lazy loading.", description = "Get all user feedback by product id (from meta.json) with lazy loading.") + public ResponseEntity> findFeedbacks(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH)String productId, Pageable pageable) { Page results = feedbackService.findFeedbacks(productId, pageable); if (results.isEmpty()) { @@ -72,20 +81,27 @@ public ResponseEntity> findFeedbacks(@PathVariable(ID) } @GetMapping(BY_ID) - public ResponseEntity findFeedback(@PathVariable(ID) String id) { + @Operation(summary = "Find all feedbacks by product id", description = "Get all feedbacks by product id(from meta.json) which is used in mobile viewport.") + public ResponseEntity findFeedback(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH)String id) { Feedback feedback = feedbackService.findFeedback(id); return ResponseEntity.ok(feedbackModelAssembler.toModel(feedback)); } - @Operation(summary = "Find all feedbacks by user id and product id") @GetMapping() - public ResponseEntity findFeedbackByUserIdAndProductId(@RequestParam(USER_ID) String userId, - @RequestParam("productId") String productId) { + @Operation(summary = "Find all feedbacks by user id and product id", description="Get current user feedback on target product.") + public ResponseEntity findFeedbackByUserIdAndProductId(@RequestParam(USER_ID) @Parameter(name = "User Id",description = "Id of current user from DB", example = "1234",in = ParameterIn.QUERY)String userId, + @RequestParam("productId") @Parameter(name = "Product Id",description = "Product id (from meta.json)", example = "portal",in = ParameterIn.QUERY)String productId) { Feedback feedback = feedbackService.findFeedbackByUserIdAndProductId(userId, productId); return ResponseEntity.ok(feedbackModelAssembler.toModel(feedback)); } @PostMapping + @Operation(summary = "Create user feedback", description = "Save user feedback of product with their token from Github account.") + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModel.class))) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successfully created user feedback"), + @ApiResponse(responseCode = "400", description = "Invalid input") + }) public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModel feedback, @RequestHeader(value = AUTHORIZATION) String authorizationHeader) { String token = null; @@ -108,9 +124,9 @@ public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModel fee return ResponseEntity.created(location).build(); } - @Operation(summary = "Find rating information of product by id") + @Operation(summary = "Find rating information of product by id",description = "Get overall rating of product from user.") @GetMapping(PRODUCT_RATING_BY_ID) - public ResponseEntity> getProductRating(@PathVariable(ID) String productId) { + public ResponseEntity> getProductRating(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)",example = "portal", in = ParameterIn.PATH)String productId) { return ResponseEntity.ok(feedbackService.getProductRatingById(productId)); } diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index e1735a48c..14519b3a7 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -13,6 +13,7 @@ import java.util.List; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -49,8 +50,8 @@ public ProductDetailsController(VersionService versionService, ProductService pr @GetMapping(BY_ID_AND_TAG) @Operation(summary = "Find product detail by product id and release tag.", description = "get product detail by it product id and release tag.") - public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) @Parameter(name = "Product id (from meta.json)", example = "portal") String id, - @PathVariable(TAG) @Parameter(name = "Release tag (from git hub repo tags)", example = "10.0.19") String tag) { + public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) @Parameter( description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH) String id, + @PathVariable(TAG) @Parameter( description = "Release tag (from git hub repo tags)", example = "10.0.19",in = ParameterIn.PATH) String tag) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, tag), HttpStatus.OK); } @@ -58,22 +59,22 @@ public ResponseEntity findProductDetailsByVersion(@PathVaria @CrossOrigin(originPatterns = "*") @PutMapping(INSTALLATION_COUNT_BY_ID) @Operation(summary = "Update installation count of product", description = "By default, increase installation count when click download product files by users") - public ResponseEntity syncInstallationCount(@PathVariable(ID) @Parameter(name = "Product id (from meta.json)", example = "portal") String productId) { + public ResponseEntity syncInstallationCount(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH) String productId) { int result = productService.updateInstallationCountForProduct(productId); return new ResponseEntity<>(result, HttpStatus.OK); } @GetMapping(BY_ID) @Operation(summary = "increase installation count by 1", description = "update installation count when click download product files by users") - public ResponseEntity findProductDetails(@PathVariable(ID) @Parameter(name = "Product id (from meta.json)", example = "portal") String id) { + public ResponseEntity findProductDetails(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH) String id) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, null), HttpStatus.OK); } @GetMapping(VERSIONS_BY_ID) - public ResponseEntity> findProductVersionsById(@PathVariable(ID) String id, - @RequestParam(SHOW_DEV_VERSION) boolean isShowDevVersion, - @RequestParam(name = DESIGNER_VERSION, required = false) String designerVersion) { + public ResponseEntity> findProductVersionsById(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH)String id, + @RequestParam(SHOW_DEV_VERSION) @Parameter(name ="Show dev version",description = "Option to get Dev Version (Snapshot/ sprint release)", in = ParameterIn.QUERY)boolean isShowDevVersion, + @RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(name = "Designer version", in = ParameterIn.QUERY, example = "10.0.19") String designerVersion) { List models = versionService.getArtifactsAndVersionToDisplay(id, isShowDevVersion, designerVersion); return new ResponseEntity<>(models, HttpStatus.OK); diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java index 663fab1dc..44b5506e0 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java @@ -1,6 +1,7 @@ package com.axonivy.market.model; import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; @@ -21,23 +22,39 @@ @Relation(collectionRelation = "feedbacks", itemRelation = "feedback") @JsonInclude(JsonInclude.Include.NON_NULL) public class FeedbackModel extends RepresentationModel { + @Schema(description = "", example = "") private String id; + + @Schema(description = "", example = "") private String userId; + + @Schema(description = "Github username", example = "ntqdinh-axonivy") private String username; + + @Schema(description = "Url of github avatar", example = "") private String userAvatarUrl; + + @Schema(description = "", example = "") private String userProvider; + @Schema(description = "Product id (from meta.json)", example = "portal", nullable = false) @NotBlank(message = "Product id cannot be blank") private String productId; + @Schema(description = "User's feedback content", example = "Pretty cool connector.", nullable = false) @NotBlank(message = "Content cannot be blank") @Size(max = 5, message = "Content length must be up to 250 characters") private String content; + @Schema(description = "User's rating point of target product", example = "5", nullable = false, minimum = "1", maximum = "5") @Min(value = 1, message = "Rating should not be less than 1") @Max(value = 5, message = "Rating should not be greater than 5") private Integer rating; + + @Schema(description = "Feedback/rating creating timestamp", example = "", nullable = false) private Date createdAt; + + @Schema(description = "Latest feedback/rating updating timestamp", example = "", nullable = false) private Date updatedAt; @Override From 02187829a16730be61d482cfcb353422476bdf5a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 03:40:04 +0700 Subject: [PATCH 03/15] Update ProductController.java --- .../java/com/axonivy/market/controller/ProductController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index b03c8246b..e263a4d52 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -61,7 +61,7 @@ public ProductController(ProductService productService, GitHubService gitHubServ @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'") public ResponseEntity> findProducts(@RequestParam(name = TYPE) @Parameter(name = "Type", description = "Type of product.", in = ParameterIn.QUERY, schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) String type, - @RequestParam(required = false, name = KEYWORD) @Parameter(name = "Keyword", description = "Keyword that exist in product's name or short description.", in = ParameterIn.QUERY) String keyword, + @RequestParam(required = false, name = KEYWORD) @Parameter(name = "Keyword", description = "Keyword that exist in product's name or short description.", example = "connector",in = ParameterIn.QUERY) String keyword, @RequestParam(name = LANGUAGE) @Parameter(name = "Language", description = "Language of product short description.", in = ParameterIn.QUERY, schema = @Schema(allowableValues = {"en", "de"})) String language, @Parameter(name = "Pagination", description = "Pagination configuration for result set") Pageable pageable) { Page results = productService.findProducts(type, keyword, language, pageable); From bc2429f82e659c7a6d62866d6d506418e8ee09d7 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 11:18:16 +0700 Subject: [PATCH 04/15] update document --- .../ProductDetailModelAssembler.java | 2 +- .../market/controller/FeedbackController.java | 57 ++++++++++++------- .../market/controller/OAuth2Controller.java | 14 ++++- .../market/controller/ProductController.java | 28 ++++++--- .../controller/ProductDetailsController.java | 28 ++++++--- .../axonivy/market/model/FeedbackModel.java | 12 ++-- .../market/model/Oauth2AuthorizationCode.java | 2 + .../axonivy/market/model/ProductRating.java | 4 ++ 8 files changed, 102 insertions(+), 45 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java b/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java index e72ab8034..1c6c9c2fd 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java +++ b/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java @@ -26,7 +26,7 @@ public ProductDetailModelAssembler(ProductModelAssembler productModelAssembler) @Override public ProductDetailModel toModel(Product product) { - return createModel(product, null); + return createModel(product, StringUtils.EMPTY); } public ProductDetailModel toModel(Product product, String tag) { diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index cb11ca41e..ac702cb56 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -18,6 +18,8 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -59,8 +61,7 @@ public class FeedbackController { private final PagedResourcesAssembler pagedResourcesAssembler; - public FeedbackController(FeedbackService feedbackService, JwtService jwtService, - FeedbackModelAssembler feedbackModelAssembler, PagedResourcesAssembler pagedResourcesAssembler) { + public FeedbackController(FeedbackService feedbackService, JwtService jwtService, FeedbackModelAssembler feedbackModelAssembler, PagedResourcesAssembler pagedResourcesAssembler) { this.feedbackService = feedbackService; this.jwtService = jwtService; this.feedbackModelAssembler = feedbackModelAssembler; @@ -69,8 +70,12 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService @GetMapping(PRODUCT_BY_ID) @Operation(summary = "Find feedbacks by product id with lazy loading.", description = "Get all user feedback by product id (from meta.json) with lazy loading.") - public ResponseEntity> findFeedbacks(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH)String productId, - Pageable pageable) { + @PageableAsQueryParam + public ResponseEntity> findFeedbacks(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) + String productId, + @ParameterObject + Pageable pageable) { Page results = feedbackService.findFeedbacks(productId, pageable); if (results.isEmpty()) { return generateEmptyPagedModel(); @@ -82,31 +87,40 @@ public ResponseEntity> findFeedbacks(@PathVariable(ID) @GetMapping(BY_ID) @Operation(summary = "Find all feedbacks by product id", description = "Get all feedbacks by product id(from meta.json) which is used in mobile viewport.") - public ResponseEntity findFeedback(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH)String id) { + public ResponseEntity findFeedback(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) + String id) { Feedback feedback = feedbackService.findFeedback(id); return ResponseEntity.ok(feedbackModelAssembler.toModel(feedback)); } @GetMapping() - @Operation(summary = "Find all feedbacks by user id and product id", description="Get current user feedback on target product.") - public ResponseEntity findFeedbackByUserIdAndProductId(@RequestParam(USER_ID) @Parameter(name = "User Id",description = "Id of current user from DB", example = "1234",in = ParameterIn.QUERY)String userId, - @RequestParam("productId") @Parameter(name = "Product Id",description = "Product id (from meta.json)", example = "portal",in = ParameterIn.QUERY)String productId) { + @Operation(summary = "Find all feedbacks by user id and product id", description = "Get current user feedback on target product.") + public ResponseEntity findFeedbackByUserIdAndProductId(@RequestParam(USER_ID) + @Parameter(description = "Id of current user from DB", example = "1234", in = ParameterIn.QUERY) + String userId, + @RequestParam("productId") + @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.QUERY) + String productId) { Feedback feedback = feedbackService.findFeedbackByUserIdAndProductId(userId, productId); return ResponseEntity.ok(feedbackModelAssembler.toModel(feedback)); } @PostMapping @Operation(summary = "Create user feedback", description = "Save user feedback of product with their token from Github account.") - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModel.class))) + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModel.class))) @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Successfully created user feedback"), - @ApiResponse(responseCode = "400", description = "Invalid input") - }) - public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModel feedback, - @RequestHeader(value = AUTHORIZATION) String authorizationHeader) { + @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), + @ApiResponse(responseCode = "401", description = "Unauthorized request")}) + public ResponseEntity createFeedback(@RequestBody + @Valid + FeedbackModel feedback, + @RequestHeader(value = AUTHORIZATION) + @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) + String bearerToken) { String token = null; - if (authorizationHeader != null && authorizationHeader.startsWith(CommonConstants.BEARER)) { - token = authorizationHeader.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix + if (bearerToken != null && bearerToken.startsWith(CommonConstants.BEARER)) { + token = bearerToken.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix } // Validate the token @@ -118,22 +132,23 @@ public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModel fee feedback.setUserId(claims.getSubject()); Feedback newFeedback = feedbackService.upsertFeedback(feedback); - URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(BY_ID).buildAndExpand(newFeedback.getId()) - .toUri(); + URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(BY_ID).buildAndExpand(newFeedback.getId()).toUri(); return ResponseEntity.created(location).build(); } - @Operation(summary = "Find rating information of product by id",description = "Get overall rating of product from user.") + @Operation(summary = "Find rating information of product by its id.", description = "Get overall rating of product by its id.") @GetMapping(PRODUCT_RATING_BY_ID) - public ResponseEntity> getProductRating(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)",example = "portal", in = ParameterIn.PATH)String productId) { + public ResponseEntity> getProductRating(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) + String productId) { return ResponseEntity.ok(feedbackService.getProductRatingById(productId)); } @SuppressWarnings("unchecked") private ResponseEntity> generateEmptyPagedModel() { var emptyPagedModel = (PagedModel) pagedResourcesAssembler.toEmptyModel(Page.empty(), - FeedbackModel.class); + FeedbackModel.class); return new ResponseEntity<>(emptyPagedModel, HttpStatus.OK); } } diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java index 968c81e2b..14efcc799 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java @@ -7,7 +7,13 @@ import java.util.Collections; import java.util.Map; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -39,11 +45,15 @@ public OAuth2Controller(GitHubService gitHubService, JwtService jwtService, GitH } @PostMapping(GIT_HUB_LOGIN) + @Operation(description = "Get rating authentication token") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successfully login to GitHub provider", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Map.class))), + @ApiResponse(responseCode = "400", description = "Bad Request")}) + @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Oauth2AuthorizationCode.class))) public ResponseEntity> gitHubLogin(@RequestBody Oauth2AuthorizationCode oauth2AuthorizationCode) { String accessToken = EMPTY; try { - GitHubAccessTokenResponse tokenResponse = gitHubService.getAccessToken(oauth2AuthorizationCode.getCode(), - gitHubProperty); + GitHubAccessTokenResponse tokenResponse = gitHubService.getAccessToken(oauth2AuthorizationCode.getCode(), gitHubProperty); accessToken = tokenResponse.getAccessToken(); } catch (Exception e) { return new ResponseEntity<>(Map.of(e.getClass().getName(), e.getMessage()), HttpStatus.BAD_REQUEST); diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index e263a4d52..f0d5cef51 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -13,6 +13,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import org.apache.commons.lang3.time.StopWatch; +import org.springdoc.core.annotations.ParameterObject; +import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -58,12 +60,22 @@ public ProductController(ProductService productService, GitHubService gitHubServ } @GetMapping() + @PageableAsQueryParam @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'") - public ResponseEntity> findProducts(@RequestParam(name = TYPE) @Parameter(name = "Type", description = "Type of product.", in = ParameterIn.QUERY, - schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) String type, - @RequestParam(required = false, name = KEYWORD) @Parameter(name = "Keyword", description = "Keyword that exist in product's name or short description.", example = "connector",in = ParameterIn.QUERY) String keyword, - @RequestParam(name = LANGUAGE) @Parameter(name = "Language", description = "Language of product short description.", in = ParameterIn.QUERY, - schema = @Schema(allowableValues = {"en", "de"})) String language, @Parameter(name = "Pagination", description = "Pagination configuration for result set") Pageable pageable) { + public ResponseEntity> findProducts(@RequestParam(name = TYPE) + @Parameter(description = "Type of product.", in = ParameterIn.QUERY, + schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) + String type, + @RequestParam(required = false, name = KEYWORD) + @Parameter(description = "Keyword that exist in product's name or short description.", example = "connector", in = ParameterIn.QUERY) + String keyword, + @RequestParam(name = LANGUAGE) + @Parameter(description = "Language of product short description.", in = ParameterIn.QUERY, + schema = @Schema(allowableValues = {"en", "de"})) + String language, + @ParameterObject + Pageable pageable) { + Page results = productService.findProducts(type, keyword, language, pageable); if (results.isEmpty()) { return generateEmptyPagedModel(); @@ -75,8 +87,10 @@ public ResponseEntity> findProducts(@RequestParam(name @PutMapping(SYNC) @Operation(hidden = true) - public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION) String authorizationHeader, - @RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) { + public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION) + String authorizationHeader, + @RequestParam(value = RESET_SYNC, required = false) + Boolean resetSync) { String token = null; if (authorizationHeader.startsWith(CommonConstants.BEARER)) { token = authorizationHeader.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index 14519b3a7..088f9b979 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -50,8 +50,12 @@ public ProductDetailsController(VersionService versionService, ProductService pr @GetMapping(BY_ID_AND_TAG) @Operation(summary = "Find product detail by product id and release tag.", description = "get product detail by it product id and release tag.") - public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) @Parameter( description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH) String id, - @PathVariable(TAG) @Parameter( description = "Release tag (from git hub repo tags)", example = "10.0.19",in = ParameterIn.PATH) String tag) { + public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) + String id, + @PathVariable(TAG) + @Parameter(description = "Release tag (from git hub repo tags)", example = "v10.0.20", in = ParameterIn.PATH) + String tag) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, tag), HttpStatus.OK); } @@ -59,22 +63,30 @@ public ResponseEntity findProductDetailsByVersion(@PathVaria @CrossOrigin(originPatterns = "*") @PutMapping(INSTALLATION_COUNT_BY_ID) @Operation(summary = "Update installation count of product", description = "By default, increase installation count when click download product files by users") - public ResponseEntity syncInstallationCount(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH) String productId) { + public ResponseEntity syncInstallationCount(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) + String productId) { int result = productService.updateInstallationCountForProduct(productId); return new ResponseEntity<>(result, HttpStatus.OK); } @GetMapping(BY_ID) @Operation(summary = "increase installation count by 1", description = "update installation count when click download product files by users") - public ResponseEntity findProductDetails(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH) String id) { + public ResponseEntity findProductDetails(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) + String id) { var productDetail = productService.fetchProductDetail(id); - return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, null), HttpStatus.OK); + return new ResponseEntity<>(detailModelAssembler.toModel(productDetail), HttpStatus.OK); } @GetMapping(VERSIONS_BY_ID) - public ResponseEntity> findProductVersionsById(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal",in = ParameterIn.PATH)String id, - @RequestParam(SHOW_DEV_VERSION) @Parameter(name ="Show dev version",description = "Option to get Dev Version (Snapshot/ sprint release)", in = ParameterIn.QUERY)boolean isShowDevVersion, - @RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(name = "Designer version", in = ParameterIn.QUERY, example = "10.0.19") String designerVersion) { + public ResponseEntity> findProductVersionsById(@PathVariable(ID) + @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) + String id, + @RequestParam(SHOW_DEV_VERSION) @Parameter(description = "Option to get Dev Version (Snapshot/ sprint release)", in = ParameterIn.QUERY) + boolean isShowDevVersion, + @RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(in = ParameterIn.QUERY, example = "v10.0.20") + String designerVersion) { List models = versionService.getArtifactsAndVersionToDisplay(id, isShowDevVersion, designerVersion); return new ResponseEntity<>(models, HttpStatus.OK); diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java index 44b5506e0..c82237dc2 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java @@ -22,19 +22,19 @@ @Relation(collectionRelation = "feedbacks", itemRelation = "feedback") @JsonInclude(JsonInclude.Include.NON_NULL) public class FeedbackModel extends RepresentationModel { - @Schema(description = "", example = "") + @Schema(description = "Id of feedback", example = "667940ecc881b1d0db072f9e") private String id; - @Schema(description = "", example = "") + @Schema(description = "User Id", example = "666ff14c847c664ac54d2643") private String userId; @Schema(description = "Github username", example = "ntqdinh-axonivy") private String username; - @Schema(description = "Url of github avatar", example = "") + @Schema(description = "Url of github avatar", example = "https://avatars.githubusercontent.com/u/1?v=4") private String userAvatarUrl; - @Schema(description = "", example = "") + @Schema(description = "3rd party login provider", example = "GitHub") private String userProvider; @Schema(description = "Product id (from meta.json)", example = "portal", nullable = false) @@ -51,10 +51,10 @@ public class FeedbackModel extends RepresentationModel { @Max(value = 5, message = "Rating should not be greater than 5") private Integer rating; - @Schema(description = "Feedback/rating creating timestamp", example = "", nullable = false) + @Schema(description = "Feedback/rating creating timestamp", example = "2024-06-24T00:00:00.000Z", nullable = false) private Date createdAt; - @Schema(description = "Latest feedback/rating updating timestamp", example = "", nullable = false) + @Schema(description = "Latest feedback/rating updating timestamp", example = "2024-06-24T00:00:00.000Z", nullable = false) private Date updatedAt; @Override diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/Oauth2AuthorizationCode.java b/marketplace-service/src/main/java/com/axonivy/market/model/Oauth2AuthorizationCode.java index b73f8dc66..febebdb42 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/Oauth2AuthorizationCode.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/Oauth2AuthorizationCode.java @@ -1,5 +1,6 @@ package com.axonivy.market.model; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -8,5 +9,6 @@ @Setter @NoArgsConstructor public class Oauth2AuthorizationCode { + @Schema(description = "Exchange code") private String code; } diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/ProductRating.java b/marketplace-service/src/main/java/com/axonivy/market/model/ProductRating.java index b151e05f4..e53967946 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/ProductRating.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/ProductRating.java @@ -1,5 +1,6 @@ package com.axonivy.market.model; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,7 +11,10 @@ @AllArgsConstructor @NoArgsConstructor public class ProductRating { + @Schema(description = "Specific rating point of product", example = "3") private Integer starRating; + @Schema(description = "Count of rating on this specific point", example = "20") private Integer commentNumber; + @Schema(description = "Weight ration of this point/ total point", example = "20") private Integer percent; } From fbc3234986866c0318c91fc6720603fa3a817db3 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 12:00:07 +0700 Subject: [PATCH 05/15] update documention --- .../axonivy/market/controller/FeedbackController.java | 2 +- .../axonivy/market/controller/ProductController.java | 11 +++++++---- .../market/controller/ProductDetailsController.java | 2 +- .../java/com/axonivy/market/model/FeedbackModel.java | 10 +++++----- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index ac702cb56..5f4482879 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -69,7 +69,7 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService } @GetMapping(PRODUCT_BY_ID) - @Operation(summary = "Find feedbacks by product id with lazy loading.", description = "Get all user feedback by product id (from meta.json) with lazy loading.") + @Operation(summary = "Find feedbacks by product id with lazy loading", description = "Get all user feedback by product id (from meta.json) with lazy loading") @PageableAsQueryParam public ResponseEntity> findFeedbacks(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index f0d5cef51..fa52db681 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -60,17 +60,20 @@ public ProductController(ProductService productService, GitHubService gitHubServ } @GetMapping() - @PageableAsQueryParam - @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'") + @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'", parameters = { + @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), + @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), + @Parameter(name = "sort", description = "Sorting criteria in the format: property(popularity|alphabetically|recent),(asc|desc)", in = ParameterIn.QUERY, example = "popularity,asc", required = true) + }) public ResponseEntity> findProducts(@RequestParam(name = TYPE) @Parameter(description = "Type of product.", in = ParameterIn.QUERY, schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) String type, @RequestParam(required = false, name = KEYWORD) - @Parameter(description = "Keyword that exist in product's name or short description.", example = "connector", in = ParameterIn.QUERY) + @Parameter(description = "Keyword that exist in product's name or short description", example = "connector", in = ParameterIn.QUERY) String keyword, @RequestParam(name = LANGUAGE) - @Parameter(description = "Language of product short description.", in = ParameterIn.QUERY, + @Parameter(description = "Language of product short description", in = ParameterIn.QUERY, schema = @Schema(allowableValues = {"en", "de"})) String language, @ParameterObject diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index 088f9b979..4910a83b8 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -49,7 +49,7 @@ public ProductDetailsController(VersionService versionService, ProductService pr } @GetMapping(BY_ID_AND_TAG) - @Operation(summary = "Find product detail by product id and release tag.", description = "get product detail by it product id and release tag.") + @Operation(summary = "Find product detail by product id and release tag.", description = "get product detail by it product id and release tag") public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) String id, diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java index c82237dc2..ca3e8da8f 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java @@ -37,24 +37,24 @@ public class FeedbackModel extends RepresentationModel { @Schema(description = "3rd party login provider", example = "GitHub") private String userProvider; - @Schema(description = "Product id (from meta.json)", example = "portal", nullable = false) + @Schema(description = "Product id (from meta.json)", example = "portal") @NotBlank(message = "Product id cannot be blank") private String productId; - @Schema(description = "User's feedback content", example = "Pretty cool connector.", nullable = false) + @Schema(description = "User's feedback content", example = "Pretty cool connector.") @NotBlank(message = "Content cannot be blank") @Size(max = 5, message = "Content length must be up to 250 characters") private String content; - @Schema(description = "User's rating point of target product", example = "5", nullable = false, minimum = "1", maximum = "5") + @Schema(description = "User's rating point of target product", example = "5", minimum = "1", maximum = "5") @Min(value = 1, message = "Rating should not be less than 1") @Max(value = 5, message = "Rating should not be greater than 5") private Integer rating; - @Schema(description = "Feedback/rating creating timestamp", example = "2024-06-24T00:00:00.000Z", nullable = false) + @Schema(description = "Feedback/rating creating timestamp", example = "2024-06-24T00:00:00.000Z") private Date createdAt; - @Schema(description = "Latest feedback/rating updating timestamp", example = "2024-06-24T00:00:00.000Z", nullable = false) + @Schema(description = "Latest feedback/rating updating timestamp", example = "2024-06-24T00:00:00.000Z") private Date updatedAt; @Override From e3a6f6f63a6b0f57b7e26d6eb611ef8171a66fe2 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 12:57:53 +0700 Subject: [PATCH 06/15] provide example for schema --- .../axonivy/market/entity/MavenArtifactModel.java | 3 +++ .../axonivy/market/entity/ProductModuleContent.java | 10 ++++++++++ .../market/model/MavenArtifactVersionModel.java | 2 ++ .../com/axonivy/market/model/ProductDetailModel.java | 12 ++++++++++++ .../java/com/axonivy/market/model/ProductModel.java | 7 +++++++ 5 files changed, 34 insertions(+) diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java b/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java index 81a27e864..e1bb99383 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/MavenArtifactModel.java @@ -1,5 +1,6 @@ package com.axonivy.market.entity; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -17,7 +18,9 @@ public class MavenArtifactModel implements Serializable { @Serial private static final long serialVersionUID = 1L; + @Schema(description = "Display name and type of artifact", example = "Adobe Acrobat Sign Connector (.iar)") private String name; + @Schema(description = "Artifact download url", example = "https://maven.axonivy.com/com/axonivy/connector/adobe/acrobat/sign/adobe-acrobat-sign-connector/10.0.25/adobe-acrobat-sign-connector-10.0.25.iar") private String downloadUrl; @Transient private Boolean isProductArtifact; diff --git a/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java b/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java index bc48a39ad..43397d99a 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java +++ b/marketplace-service/src/main/java/com/axonivy/market/entity/ProductModuleContent.java @@ -1,5 +1,6 @@ package com.axonivy.market.entity; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -16,13 +17,22 @@ public class ProductModuleContent implements Serializable { @Serial private static final long serialVersionUID = 1L; + @Schema(description = "Target release tag", example = "v10.0.25") private String tag; + @Schema(description = "Product detail description content ", example = "{ \"de\": \"E-Sign-Konnektor\", \"en\": \"E-sign connector\" }") private Map description; + @Schema(description = "Setup tab content", example = "Adobe Sign account creation: An Adobe Sign account needs to be created to setup and use the connector.") private String setup; + @Schema(description = "Demo tab content", example = "The demo project can be used to test the authentication and signing and the demo implementation can be used as inspiration for development") private String demo; + @Schema(description = "Is dependency artifact", example = "true") private Boolean isDependency; + @Schema(example = "Adobe Acrobat Sign Connector") private String name; + @Schema(description = "Product artifact's group id", example = "com.axonivy.connector.adobe.acrobat.sign") private String groupId; + @Schema(description = "Product artifact's artifact id", example = "adobe-acrobat-sign-connector-product") private String artifactId; + @Schema(description = "Artifact file type", example = "iar") private String type; } diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/MavenArtifactVersionModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/MavenArtifactVersionModel.java index 4acdc23ad..32ef52dcd 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/MavenArtifactVersionModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/MavenArtifactVersionModel.java @@ -1,6 +1,7 @@ package com.axonivy.market.model; import com.axonivy.market.entity.MavenArtifactModel; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -13,6 +14,7 @@ @AllArgsConstructor @NoArgsConstructor public class MavenArtifactVersionModel { + @Schema(description = "Target version", example = "10.0.19") private String version; private List artifactsByVersion; } \ No newline at end of file diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/ProductDetailModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/ProductDetailModel.java index 99a13922f..bfe864dbd 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/ProductDetailModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/ProductDetailModel.java @@ -1,6 +1,7 @@ package com.axonivy.market.model; import com.axonivy.market.entity.ProductModuleContent; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -11,17 +12,28 @@ @Setter @NoArgsConstructor public class ProductDetailModel extends ProductModel { + @Schema(description = "Product vendor", example = "Axon Ivy AG") private String vendor; + @Schema(description = "Platform review", example = "4.5") private String platformReview; + @Schema(description = "Latest release version from maven", example = "v10.0.25") private String newestReleaseVersion; + @Schema(description = "Product cost", example = "Free") private String cost; + @Schema(description = "Source repository url", example = "https://github.com/axonivy-market/adobe-acrobat-sign-connector") private String sourceUrl; + @Schema(description = "Status badge url", example = "https://github.com/axonivy-market/adobe-acrobat-sign-connector/actions/workflows/ci.yml/badge.svg") private String statusBadgeUrl; + @Schema(description = "Default language", example = "English") private String language; + @Schema(description = "Product industry", example = "Cross-Industry") private String industry; + @Schema(description = "Compatibility", example = "10.0+") private String compatibility; + @Schema(description = "Can contact us", example = "false") private Boolean contactUs; private ProductModuleContent productModuleContent; + @Schema(description = "Installation/download count", example = "0") private int installationCount; @Override diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java index 1eeb4f3bc..74fbe9471 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/ProductModel.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -19,11 +20,17 @@ @Relation(collectionRelation = "products", itemRelation = "product") @JsonInclude(Include.NON_NULL) public class ProductModel extends RepresentationModel { + @Schema(description = "Product id", example = "jira-connector") private String id; + @Schema(description = "Product name by locale", example = "{ \"de\": \"Atlassian Jira\", \"en\": \"Atlassian Jira\" }") private Map names; + @Schema(description = "Product's short descriptions by locale", example = "{ \"de\": \"Nutze den Jira Connector von Atlassian, um Jira-Tickets direkt von der Axon Ivy Plattform aus zu verfolgen.\", \"en\": \"Atlassian's Jira connector lets you track issues directly from the Axon Ivy platform\" }") private Map shortDescriptions; + @Schema(description = "Product's logo url", example = "https://raw.githubusercontent.com/axonivy-market/market/feature/MARP-463-Multilingualism-for-Website/market/connector/jira/logo.png") private String logoUrl; + @Schema(description = "Type of product", example = "connector") private String type; + @Schema(description = "Tags of product", example = "[\"helper\"]") private List tags; @Override From a7bac17446608befdfa5c8e93c02d12bf122f40d Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 13:31:34 +0700 Subject: [PATCH 07/15] update array --- .../com/axonivy/market/controller/FeedbackController.java | 7 +++++-- .../com/axonivy/market/controller/ProductController.java | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index 5f4482879..a5e835c6e 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -13,6 +13,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -69,8 +70,10 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService } @GetMapping(PRODUCT_BY_ID) - @Operation(summary = "Find feedbacks by product id with lazy loading", description = "Get all user feedback by product id (from meta.json) with lazy loading") - @PageableAsQueryParam + @Operation(summary = "Find feedbacks by product id with lazy loading", description = "Get all user feedback by product id (from meta.json) with lazy loading", parameters = { + @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), + @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), + @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) public ResponseEntity> findFeedbacks(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) String productId, diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index fa52db681..2a4843cb0 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -63,8 +63,7 @@ public ProductController(ProductService productService, GitHubService gitHubServ @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'", parameters = { @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), - @Parameter(name = "sort", description = "Sorting criteria in the format: property(popularity|alphabetically|recent),(asc|desc)", in = ParameterIn.QUERY, example = "popularity,asc", required = true) - }) + @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) public ResponseEntity> findProducts(@RequestParam(name = TYPE) @Parameter(description = "Type of product.", in = ParameterIn.QUERY, schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) From 0a4b55ee51c49ee2c0dde47f3aaab78ed73da057 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 13:33:25 +0700 Subject: [PATCH 08/15] update format --- .../java/com/axonivy/market/controller/FeedbackController.java | 3 ++- .../java/com/axonivy/market/controller/ProductController.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index a5e835c6e..b04e04d67 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -73,7 +73,8 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService @Operation(summary = "Find feedbacks by product id with lazy loading", description = "Get all user feedback by product id (from meta.json) with lazy loading", parameters = { @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), - @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) + @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", + in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) public ResponseEntity> findFeedbacks(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) String productId, diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 2a4843cb0..86d1191fb 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -63,7 +63,8 @@ public ProductController(ProductService productService, GitHubService gitHubServ @Operation(summary = "Find all products", description = "Be default system will finds product by type as 'all'", parameters = { @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), - @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) + @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", + in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) public ResponseEntity> findProducts(@RequestParam(name = TYPE) @Parameter(description = "Type of product.", in = ParameterIn.QUERY, schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) From 0744fe1da7ce95f428f95366e846f39ab7d74dae Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 30 Jul 2024 13:44:15 +0700 Subject: [PATCH 09/15] update test --- .../axonivy/market/assembler/ProductDetailModelAssembler.java | 2 +- .../com/axonivy/market/controller/ProductDetailsController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java b/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java index 1c6c9c2fd..e72ab8034 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java +++ b/marketplace-service/src/main/java/com/axonivy/market/assembler/ProductDetailModelAssembler.java @@ -26,7 +26,7 @@ public ProductDetailModelAssembler(ProductModelAssembler productModelAssembler) @Override public ProductDetailModel toModel(Product product) { - return createModel(product, StringUtils.EMPTY); + return createModel(product, null); } public ProductDetailModel toModel(Product product, String tag) { diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index 4910a83b8..d7fde184a 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -76,7 +76,7 @@ public ResponseEntity findProductDetails(@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) String id) { var productDetail = productService.fetchProductDetail(id); - return new ResponseEntity<>(detailModelAssembler.toModel(productDetail), HttpStatus.OK); + return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, null), HttpStatus.OK); } @GetMapping(VERSIONS_BY_ID) From b6f10fcd273d6b360b5e9c62d44fee2bf796b4b6 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 1 Aug 2024 10:40:39 +0700 Subject: [PATCH 10/15] handle sonnar --- .../com/axonivy/market/controller/FeedbackController.java | 2 -- .../com/axonivy/market/controller/OAuth2Controller.java | 2 +- .../com/axonivy/market/controller/ProductController.java | 8 -------- .../java/com/axonivy/market/factory/ProductFactory.java | 2 +- .../axonivy/market/service/impl/ProductServiceImpl.java | 2 +- 5 files changed, 3 insertions(+), 13 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index b04e04d67..3cc8ebec1 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -13,14 +13,12 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import org.springdoc.core.annotations.ParameterObject; -import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java index 14efcc799..169ac6e06 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java @@ -51,7 +51,7 @@ public OAuth2Controller(GitHubService gitHubService, JwtService jwtService, GitH @ApiResponse(responseCode = "400", description = "Bad Request")}) @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Oauth2AuthorizationCode.class))) public ResponseEntity> gitHubLogin(@RequestBody Oauth2AuthorizationCode oauth2AuthorizationCode) { - String accessToken = EMPTY; + String accessToken; try { GitHubAccessTokenResponse tokenResponse = gitHubService.getAccessToken(oauth2AuthorizationCode.getCode(), gitHubProperty); accessToken = tokenResponse.getAccessToken(); diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index e20f0aa8f..9c9374006 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -26,7 +26,6 @@ import jakarta.validation.Valid; import org.apache.commons.lang3.time.StopWatch; import org.springdoc.core.annotations.ParameterObject; -import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -44,13 +43,6 @@ import org.springframework.web.bind.annotation.RestController; import static com.axonivy.market.constants.RequestMappingConstants.CUSTOM_SORT; -import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; -import static com.axonivy.market.constants.RequestMappingConstants.SYNC; -import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; -import static com.axonivy.market.constants.RequestParamConstants.KEYWORD; -import static com.axonivy.market.constants.RequestParamConstants.LANGUAGE; -import static com.axonivy.market.constants.RequestParamConstants.RESET_SYNC; -import static com.axonivy.market.constants.RequestParamConstants.TYPE; @RestController @RequestMapping(PRODUCT) diff --git a/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java b/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java index d687c1577..224de4e86 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java +++ b/marketplace-service/src/main/java/com/axonivy/market/factory/ProductFactory.java @@ -46,7 +46,7 @@ public static Product mappingByGHContent(Product product, GHContent content) { } public static Product mappingByMetaJSONFile(Product product, GHContent ghContent) { - Meta meta = null; + Meta meta; try { meta = jsonDecode(ghContent); } catch (Exception e) { diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java index c58fd8b8b..d001550b9 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/ProductServiceImpl.java @@ -214,7 +214,7 @@ private void updateLatestChangeToProductsFromGithubRepo() { } private void modifyProductLogo(String parentPath, GitHubFile file, Product product, GHContent fileContent) { - Product result = null; + Product result; switch (file.getStatus()) { case MODIFIED, ADDED: var searchCriteria = new ProductSearchCriteria(); From 65dfd73c744a5bc3871a5df656a582093a51234f Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Thu, 1 Aug 2024 10:41:13 +0700 Subject: [PATCH 11/15] Add FeedbackModelRequest and refactor code --- .../market/controller/FeedbackController.java | 103 ++++++++---------- .../market/controller/ProductController.java | 8 -- .../axonivy/market/model/FeedbackModel.java | 9 -- .../market/model/FeedbackModelRequest.java | 27 +++++ .../market/service/FeedbackService.java | 4 +- .../service/impl/FeedbackServiceImpl.java | 10 +- .../controller/FeedbackControllerTest.java | 12 +- .../service/FeedbackServiceImplTest.java | 21 +++- 8 files changed, 98 insertions(+), 96 deletions(-) create mode 100644 marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModelRequest.java diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index b04e04d67..3b6f84498 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -1,26 +1,24 @@ package com.axonivy.market.controller; -import static com.axonivy.market.constants.RequestMappingConstants.BY_ID; -import static com.axonivy.market.constants.RequestMappingConstants.FEEDBACK; -import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT_BY_ID; -import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT_RATING_BY_ID; -import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; -import static com.axonivy.market.constants.RequestParamConstants.ID; -import static com.axonivy.market.constants.RequestParamConstants.USER_ID; - -import java.net.URI; -import java.util.List; - +import com.axonivy.market.assembler.FeedbackModelAssembler; +import com.axonivy.market.constants.CommonConstants; +import com.axonivy.market.entity.Feedback; +import com.axonivy.market.model.FeedbackModel; +import com.axonivy.market.model.FeedbackModelRequest; +import com.axonivy.market.model.ProductRating; +import com.axonivy.market.service.FeedbackService; +import com.axonivy.market.service.JwtService; +import io.jsonwebtoken.Claims; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import org.springdoc.core.annotations.ParameterObject; -import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -39,17 +37,16 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import com.axonivy.market.assembler.FeedbackModelAssembler; -import com.axonivy.market.constants.CommonConstants; -import com.axonivy.market.entity.Feedback; -import com.axonivy.market.model.FeedbackModel; -import com.axonivy.market.model.ProductRating; -import com.axonivy.market.service.FeedbackService; -import com.axonivy.market.service.JwtService; +import java.net.URI; +import java.util.List; -import io.jsonwebtoken.Claims; -import io.swagger.v3.oas.annotations.Operation; -import jakarta.validation.Valid; +import static com.axonivy.market.constants.RequestMappingConstants.BY_ID; +import static com.axonivy.market.constants.RequestMappingConstants.FEEDBACK; +import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT_BY_ID; +import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT_RATING_BY_ID; +import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; +import static com.axonivy.market.constants.RequestParamConstants.ID; +import static com.axonivy.market.constants.RequestParamConstants.USER_ID; @RestController @RequestMapping(FEEDBACK) @@ -62,7 +59,8 @@ public class FeedbackController { private final PagedResourcesAssembler pagedResourcesAssembler; - public FeedbackController(FeedbackService feedbackService, JwtService jwtService, FeedbackModelAssembler feedbackModelAssembler, PagedResourcesAssembler pagedResourcesAssembler) { + public FeedbackController(FeedbackService feedbackService, JwtService jwtService, + FeedbackModelAssembler feedbackModelAssembler, PagedResourcesAssembler pagedResourcesAssembler) { this.feedbackService = feedbackService; this.jwtService = jwtService; this.feedbackModelAssembler = feedbackModelAssembler; @@ -71,15 +69,12 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService @GetMapping(PRODUCT_BY_ID) @Operation(summary = "Find feedbacks by product id with lazy loading", description = "Get all user feedback by product id (from meta.json) with lazy loading", parameters = { - @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), - @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), - @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", - in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) - public ResponseEntity> findFeedbacks(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) - String productId, - @ParameterObject - Pageable pageable) { + @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), + @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), + @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true) }) + public ResponseEntity> findFeedbacks( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) String productId, + @ParameterObject Pageable pageable) { Page results = feedbackService.findFeedbacks(productId, pageable); if (results.isEmpty()) { return generateEmptyPagedModel(); @@ -91,37 +86,28 @@ public ResponseEntity> findFeedbacks(@PathVariable(ID) @GetMapping(BY_ID) @Operation(summary = "Find all feedbacks by product id", description = "Get all feedbacks by product id(from meta.json) which is used in mobile viewport.") - public ResponseEntity findFeedback(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) - String id) { + public ResponseEntity findFeedback( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) String id) { Feedback feedback = feedbackService.findFeedback(id); return ResponseEntity.ok(feedbackModelAssembler.toModel(feedback)); } @GetMapping() @Operation(summary = "Find all feedbacks by user id and product id", description = "Get current user feedback on target product.") - public ResponseEntity findFeedbackByUserIdAndProductId(@RequestParam(USER_ID) - @Parameter(description = "Id of current user from DB", example = "1234", in = ParameterIn.QUERY) - String userId, - @RequestParam("productId") - @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.QUERY) - String productId) { + public ResponseEntity findFeedbackByUserIdAndProductId( + @RequestParam(USER_ID) @Parameter(description = "Id of current user from DB", example = "1234", in = ParameterIn.QUERY) String userId, + @RequestParam("productId") @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.QUERY) String productId) { Feedback feedback = feedbackService.findFeedbackByUserIdAndProductId(userId, productId); return ResponseEntity.ok(feedbackModelAssembler.toModel(feedback)); } @PostMapping @Operation(summary = "Create user feedback", description = "Save user feedback of product with their token from Github account.") - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModel.class))) - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), - @ApiResponse(responseCode = "401", description = "Unauthorized request")}) - public ResponseEntity createFeedback(@RequestBody - @Valid - FeedbackModel feedback, - @RequestHeader(value = AUTHORIZATION) - @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) - String bearerToken) { + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModelRequest.class))) + @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), + @ApiResponse(responseCode = "401", description = "Unauthorized request") }) + public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModelRequest feedbackRequest, + @RequestHeader(value = AUTHORIZATION) @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) String bearerToken) { String token = null; if (bearerToken != null && bearerToken.startsWith(CommonConstants.BEARER)) { token = bearerToken.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix @@ -133,26 +119,25 @@ public ResponseEntity createFeedback(@RequestBody } Claims claims = jwtService.getClaimsFromToken(token); - feedback.setUserId(claims.getSubject()); - Feedback newFeedback = feedbackService.upsertFeedback(feedback); + Feedback newFeedback = feedbackService.upsertFeedback(feedbackRequest, claims.getSubject()); - URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(BY_ID).buildAndExpand(newFeedback.getId()).toUri(); + URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(BY_ID).buildAndExpand(newFeedback.getId()) + .toUri(); return ResponseEntity.created(location).build(); } @Operation(summary = "Find rating information of product by its id.", description = "Get overall rating of product by its id.") @GetMapping(PRODUCT_RATING_BY_ID) - public ResponseEntity> getProductRating(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) - String productId) { + public ResponseEntity> getProductRating( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) String productId) { return ResponseEntity.ok(feedbackService.getProductRatingById(productId)); } @SuppressWarnings("unchecked") private ResponseEntity> generateEmptyPagedModel() { var emptyPagedModel = (PagedModel) pagedResourcesAssembler.toEmptyModel(Page.empty(), - FeedbackModel.class); + FeedbackModel.class); return new ResponseEntity<>(emptyPagedModel, HttpStatus.OK); } } diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index e20f0aa8f..9c9374006 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -26,7 +26,6 @@ import jakarta.validation.Valid; import org.apache.commons.lang3.time.StopWatch; import org.springdoc.core.annotations.ParameterObject; -import org.springdoc.core.converters.models.PageableAsQueryParam; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -44,13 +43,6 @@ import org.springframework.web.bind.annotation.RestController; import static com.axonivy.market.constants.RequestMappingConstants.CUSTOM_SORT; -import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; -import static com.axonivy.market.constants.RequestMappingConstants.SYNC; -import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; -import static com.axonivy.market.constants.RequestParamConstants.KEYWORD; -import static com.axonivy.market.constants.RequestParamConstants.LANGUAGE; -import static com.axonivy.market.constants.RequestParamConstants.RESET_SYNC; -import static com.axonivy.market.constants.RequestParamConstants.TYPE; @RestController @RequestMapping(PRODUCT) diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java index ca3e8da8f..eea330356 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java +++ b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModel.java @@ -2,10 +2,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -38,17 +34,12 @@ public class FeedbackModel extends RepresentationModel { private String userProvider; @Schema(description = "Product id (from meta.json)", example = "portal") - @NotBlank(message = "Product id cannot be blank") private String productId; @Schema(description = "User's feedback content", example = "Pretty cool connector.") - @NotBlank(message = "Content cannot be blank") - @Size(max = 5, message = "Content length must be up to 250 characters") private String content; @Schema(description = "User's rating point of target product", example = "5", minimum = "1", maximum = "5") - @Min(value = 1, message = "Rating should not be less than 1") - @Max(value = 5, message = "Rating should not be greater than 5") private Integer rating; @Schema(description = "Feedback/rating creating timestamp", example = "2024-06-24T00:00:00.000Z") diff --git a/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModelRequest.java b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModelRequest.java new file mode 100644 index 000000000..a6807dcd2 --- /dev/null +++ b/marketplace-service/src/main/java/com/axonivy/market/model/FeedbackModelRequest.java @@ -0,0 +1,27 @@ +package com.axonivy.market.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class FeedbackModelRequest { + @Schema(description = "Product id (from meta.json)", example = "portal") + @NotBlank(message = "Product id cannot be blank") + private String productId; + + @Schema(description = "User's feedback content", example = "Pretty cool connector.") + @NotBlank(message = "Content cannot be blank") + @Size(max = 250, message = "Content length must not exceed 250 characters") + private String content; + + @Schema(description = "User's rating point of target product", example = "5", minimum = "1", maximum = "5") + @Min(value = 1, message = "Rating should not be less than 1") + @Max(value = 5, message = "Rating should not be greater than 5") + private Integer rating; +} diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/FeedbackService.java b/marketplace-service/src/main/java/com/axonivy/market/service/FeedbackService.java index b7d1785b5..435ada5a0 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/FeedbackService.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/FeedbackService.java @@ -2,7 +2,7 @@ import com.axonivy.market.entity.Feedback; import com.axonivy.market.exceptions.model.NotFoundException; -import com.axonivy.market.model.FeedbackModel; +import com.axonivy.market.model.FeedbackModelRequest; import com.axonivy.market.model.ProductRating; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -16,7 +16,7 @@ public interface FeedbackService { Feedback findFeedbackByUserIdAndProductId(String userId, String productId) throws NotFoundException; - Feedback upsertFeedback(FeedbackModel feedback) throws NotFoundException; + Feedback upsertFeedback(FeedbackModelRequest feedback, String userId) throws NotFoundException; List getProductRatingById(String productId); } diff --git a/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java b/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java index 77e007e1b..b4148918c 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java +++ b/marketplace-service/src/main/java/com/axonivy/market/service/impl/FeedbackServiceImpl.java @@ -3,7 +3,7 @@ import com.axonivy.market.entity.Feedback; import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; -import com.axonivy.market.model.FeedbackModel; +import com.axonivy.market.model.FeedbackModelRequest; import com.axonivy.market.model.ProductRating; import com.axonivy.market.repository.FeedbackRepository; import com.axonivy.market.repository.ProductRepository; @@ -58,14 +58,14 @@ public Feedback findFeedbackByUserIdAndProductId(String userId, String productId } @Override - public Feedback upsertFeedback(FeedbackModel feedback) throws NotFoundException { - validateUserExists(feedback.getUserId()); + public Feedback upsertFeedback(FeedbackModelRequest feedback, String userId) throws NotFoundException { + validateUserExists(userId); - Feedback existingUserFeedback = feedbackRepository.findByUserIdAndProductId(feedback.getUserId(), + Feedback existingUserFeedback = feedbackRepository.findByUserIdAndProductId(userId, feedback.getProductId()); if (existingUserFeedback == null) { Feedback newFeedback = new Feedback(); - newFeedback.setUserId(feedback.getUserId()); + newFeedback.setUserId(userId); newFeedback.setProductId(feedback.getProductId()); newFeedback.setRating(feedback.getRating()); newFeedback.setContent(feedback.getContent()); diff --git a/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java b/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java index 1af06b839..78819a592 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/controller/FeedbackControllerTest.java @@ -3,7 +3,7 @@ import com.axonivy.market.assembler.FeedbackModelAssembler; import com.axonivy.market.entity.Feedback; import com.axonivy.market.entity.User; -import com.axonivy.market.model.FeedbackModel; +import com.axonivy.market.model.FeedbackModelRequest; import com.axonivy.market.service.FeedbackService; import com.axonivy.market.service.JwtService; import com.axonivy.market.service.UserService; @@ -122,14 +122,14 @@ void testFindFeedbackByUserIdAndProductId() { @Test void testCreateFeedback() { - FeedbackModel mockFeedbackModel = createFeedbackModelMock(); + FeedbackModelRequest mockFeedbackModel = createFeedbackModelRequestMock(); Feedback mockFeedback = createFeedbackMock(); Claims mockClaims = createMockClaims(); MockHttpServletRequest request = new MockHttpServletRequest(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); when(jwtService.validateToken(TOKEN_SAMPLE)).thenReturn(true); when(jwtService.getClaimsFromToken(TOKEN_SAMPLE)).thenReturn(mockClaims); - when(service.upsertFeedback(any())).thenReturn(mockFeedback); + when(service.upsertFeedback(any(), any())).thenReturn(mockFeedback); var result = feedbackController.createFeedback(mockFeedbackModel, "Bearer " + TOKEN_SAMPLE); assertEquals(HttpStatus.CREATED, result.getStatusCode()); @@ -146,10 +146,8 @@ private Feedback createFeedbackMock() { return mockFeedback; } - private FeedbackModel createFeedbackModelMock() { - FeedbackModel mockFeedback = new FeedbackModel(); - mockFeedback.setId(FEEDBACK_ID_SAMPLE); - mockFeedback.setUserId(USER_ID_SAMPLE); + private FeedbackModelRequest createFeedbackModelRequestMock() { + FeedbackModelRequest mockFeedback = new FeedbackModelRequest(); mockFeedback.setProductId(PRODUCT_ID_SAMPLE); mockFeedback.setContent("Great product!"); mockFeedback.setRating(5); diff --git a/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java b/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java index 75f97b562..9bf3084d7 100644 --- a/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java +++ b/marketplace-service/src/test/java/com/axonivy/market/service/FeedbackServiceImplTest.java @@ -6,6 +6,7 @@ import com.axonivy.market.enums.ErrorCode; import com.axonivy.market.exceptions.model.NotFoundException; import com.axonivy.market.model.FeedbackModel; +import com.axonivy.market.model.FeedbackModelRequest; import com.axonivy.market.model.ProductRating; import com.axonivy.market.repository.FeedbackRepository; import com.axonivy.market.repository.ProductRepository; @@ -52,21 +53,31 @@ class FeedbackServiceImplTest { private Feedback feedback; private FeedbackModel feedbackModel; + private FeedbackModelRequest feedbackModelRequest; + private String userId; + @BeforeEach void setUp() { + userId = "user1"; + feedback = new Feedback(); feedback.setId("1"); - feedback.setUserId("user1"); + feedback.setUserId(userId); feedback.setProductId("product1"); feedback.setRating(5); feedback.setContent("Great product!"); feedbackModel = new FeedbackModel(); - feedbackModel.setUserId("user1"); + feedbackModel.setUserId(userId); feedbackModel.setProductId("product1"); feedbackModel.setRating(5); feedbackModel.setContent("Great product!"); + + feedbackModelRequest = new FeedbackModelRequest(); + feedbackModelRequest.setProductId("product1"); + feedbackModelRequest.setRating(5); + feedbackModelRequest.setContent("Great product!"); } @Test @@ -159,14 +170,13 @@ void testFindFeedbackByUserIdAndProductId_NotFound() { @Test void testUpsertFeedback_Insert() throws NotFoundException { - String userId = "user1"; String productId = "product1"; when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(null); when(feedbackRepository.save(any(Feedback.class))).thenReturn(feedback); - Feedback result = feedbackService.upsertFeedback(feedbackModel); + Feedback result = feedbackService.upsertFeedback(feedbackModelRequest, userId); assertNotNull(result); assertEquals(feedbackModel.getUserId(), result.getUserId()); assertEquals(feedbackModel.getProductId(), result.getProductId()); @@ -179,14 +189,13 @@ void testUpsertFeedback_Insert() throws NotFoundException { @Test void testUpsertFeedback_Update() throws NotFoundException { - String userId = "user1"; String productId = "product1"; when(userRepository.findById(userId)).thenReturn(Optional.of(new User())); when(feedbackRepository.findByUserIdAndProductId(userId, productId)).thenReturn(feedback); when(feedbackRepository.save(any(Feedback.class))).thenReturn(feedback); - Feedback result = feedbackService.upsertFeedback(feedbackModel); + Feedback result = feedbackService.upsertFeedback(feedbackModelRequest, userId); assertNotNull(result); assertEquals(feedbackModel.getUserId(), result.getUserId()); assertEquals(feedbackModel.getProductId(), result.getProductId()); From e73f29a8531ad8a8dbbc0d0adb9e839177688936 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 1 Aug 2024 11:05:58 +0700 Subject: [PATCH 12/15] handle feedback --- .../axonivy/market/constants/RequestParamConstants.java | 2 +- .../com/axonivy/market/controller/FeedbackController.java | 7 ++++--- .../com/axonivy/market/controller/ProductController.java | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java b/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java index a7517d7d6..5bb093dcb 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java +++ b/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java @@ -11,7 +11,7 @@ public class RequestParamConstants { public static final String KEYWORD = "keyword"; public static final String LANGUAGE = "language"; public static final String USER_ID = "userId"; - public static final String AUTHORIZATION = "Authorization"; + public static final String X_AUTHORIZATION = "X-Authorization"; public static final String RESET_SYNC = "resetSync"; public static final String SHOW_DEV_VERSION = "isShowDevVersion"; public static final String DESIGNER_VERSION = "designerVersion"; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index 3b6f84498..21e1dc91d 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -44,7 +44,7 @@ import static com.axonivy.market.constants.RequestMappingConstants.FEEDBACK; import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT_BY_ID; import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT_RATING_BY_ID; -import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; +import static com.axonivy.market.constants.RequestParamConstants.X_AUTHORIZATION; import static com.axonivy.market.constants.RequestParamConstants.ID; import static com.axonivy.market.constants.RequestParamConstants.USER_ID; @@ -104,10 +104,11 @@ public ResponseEntity findFeedbackByUserIdAndProductId( @PostMapping @Operation(summary = "Create user feedback", description = "Save user feedback of product with their token from Github account.") @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModelRequest.class))) - @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), @ApiResponse(responseCode = "401", description = "Unauthorized request") }) public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModelRequest feedbackRequest, - @RequestHeader(value = AUTHORIZATION) @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) String bearerToken) { + @RequestHeader(value = X_AUTHORIZATION) @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) String bearerToken) { String token = null; if (bearerToken != null && bearerToken.startsWith(CommonConstants.BEARER)) { token = bearerToken.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 9c9374006..808e7d9a2 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -117,6 +117,7 @@ public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION } @PostMapping(CUSTOM_SORT) + @Operation(hidden = true) public ResponseEntity createCustomSortProducts( @RequestHeader(value = AUTHORIZATION) String authorizationHeader, @RequestBody @Valid ProductCustomSortRequest productCustomSortRequest) { From 45df6c56b66af8a60f5a5891c20048adfaf38c4a Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 1 Aug 2024 11:20:17 +0700 Subject: [PATCH 13/15] update prop name & format --- .../market/controller/FeedbackController.java | 14 ++++---- .../market/controller/OAuth2Controller.java | 4 +-- .../market/controller/ProductController.java | 26 +++++---------- .../controller/ProductDetailsController.java | 33 +++++++------------ .../product-feedback.service.spec.ts | 2 +- .../product-feedback.service.ts | 2 +- 6 files changed, 32 insertions(+), 49 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java index 21e1dc91d..3ad5c599d 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/FeedbackController.java @@ -59,8 +59,7 @@ public class FeedbackController { private final PagedResourcesAssembler pagedResourcesAssembler; - public FeedbackController(FeedbackService feedbackService, JwtService jwtService, - FeedbackModelAssembler feedbackModelAssembler, PagedResourcesAssembler pagedResourcesAssembler) { + public FeedbackController(FeedbackService feedbackService, JwtService jwtService, FeedbackModelAssembler feedbackModelAssembler, PagedResourcesAssembler pagedResourcesAssembler) { this.feedbackService = feedbackService; this.jwtService = jwtService; this.feedbackModelAssembler = feedbackModelAssembler; @@ -71,7 +70,7 @@ public FeedbackController(FeedbackService feedbackService, JwtService jwtService @Operation(summary = "Find feedbacks by product id with lazy loading", description = "Get all user feedback by product id (from meta.json) with lazy loading", parameters = { @Parameter(name = "page", description = "Page number to retrieve", in = ParameterIn.QUERY, example = "0", required = true), @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), - @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true) }) + @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) public ResponseEntity> findFeedbacks( @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "portal", in = ParameterIn.PATH) String productId, @ParameterObject Pageable pageable) { @@ -105,10 +104,11 @@ public ResponseEntity findFeedbackByUserIdAndProductId( @Operation(summary = "Create user feedback", description = "Save user feedback of product with their token from Github account.") @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "Example request body for feedback", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = FeedbackModelRequest.class))) @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), - @ApiResponse(responseCode = "401", description = "Unauthorized request") }) - public ResponseEntity createFeedback(@RequestBody @Valid FeedbackModelRequest feedbackRequest, - @RequestHeader(value = X_AUTHORIZATION) @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) String bearerToken) { + @ApiResponse(responseCode = "201", description = "Successfully created user feedback"), + @ApiResponse(responseCode = "401", description = "Unauthorized request")}) + public ResponseEntity createFeedback( + @RequestBody @Valid FeedbackModelRequest feedbackRequest, + @RequestHeader(value = X_AUTHORIZATION) @Parameter(description = "JWT Bearer token", example = "Bearer 123456", in = ParameterIn.HEADER) String bearerToken) { String token = null; if (bearerToken != null && bearerToken.startsWith(CommonConstants.BEARER)) { token = bearerToken.substring(CommonConstants.BEARER.length()).trim(); // Remove "Bearer " prefix diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java index 169ac6e06..0547e5a74 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/OAuth2Controller.java @@ -47,8 +47,8 @@ public OAuth2Controller(GitHubService gitHubService, JwtService jwtService, GitH @PostMapping(GIT_HUB_LOGIN) @Operation(description = "Get rating authentication token") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Successfully login to GitHub provider", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Map.class))), - @ApiResponse(responseCode = "400", description = "Bad Request")}) + @ApiResponse(responseCode = "200", description = "Successfully login to GitHub provider", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Map.class))), + @ApiResponse(responseCode = "400", description = "Bad Request")}) @io.swagger.v3.oas.annotations.parameters.RequestBody(content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Oauth2AuthorizationCode.class))) public ResponseEntity> gitHubLogin(@RequestBody Oauth2AuthorizationCode oauth2AuthorizationCode) { String accessToken; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 808e7d9a2..0b4dade05 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -2,7 +2,7 @@ import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; import static com.axonivy.market.constants.RequestMappingConstants.SYNC; -import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; +import static com.axonivy.market.constants.RequestParamConstants.X_AUTHORIZATION; import static com.axonivy.market.constants.RequestParamConstants.KEYWORD; import static com.axonivy.market.constants.RequestParamConstants.LANGUAGE; import static com.axonivy.market.constants.RequestParamConstants.RESET_SYNC; @@ -68,20 +68,11 @@ public ProductController(ProductService productService, GitHubService gitHubServ @Parameter(name = "size", description = "Number of items per page", in = ParameterIn.QUERY, example = "20", required = true), @Parameter(name = "sort", description = "Sorting criteria in the format: Sorting criteria(popularity|alphabetically|recent), Sorting order(asc|desc)", in = ParameterIn.QUERY, example = "[\"popularity\",\"asc\"]", required = true)}) - public ResponseEntity> findProducts(@RequestParam(name = TYPE) - @Parameter(description = "Type of product.", in = ParameterIn.QUERY, - schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) - String type, - @RequestParam(required = false, name = KEYWORD) - @Parameter(description = "Keyword that exist in product's name or short description", example = "connector", in = ParameterIn.QUERY) - String keyword, - @RequestParam(name = LANGUAGE) - @Parameter(description = "Language of product short description", in = ParameterIn.QUERY, - schema = @Schema(allowableValues = {"en", "de"})) - String language, - @ParameterObject - Pageable pageable) { - + public ResponseEntity> findProducts( + @RequestParam(name = TYPE) @Parameter(description = "Type of product.", in = ParameterIn.QUERY, schema = @Schema(type = "string", allowableValues = {"all", "connectors", "utilities", "solutions", "demos"})) String type, + @RequestParam(required = false, name = KEYWORD) @Parameter(description = "Keyword that exist in product's name or short description", example = "connector", in = ParameterIn.QUERY) String keyword, + @RequestParam(name = LANGUAGE) @Parameter(description = "Language of product short description", in = ParameterIn.QUERY, schema = @Schema(allowableValues = {"en", "de"})) String language, + @ParameterObject Pageable pageable) { Page results = productService.findProducts(type, keyword, language, pageable); if (results.isEmpty()) { return generateEmptyPagedModel(); @@ -93,7 +84,8 @@ public ResponseEntity> findProducts(@RequestParam(name @PutMapping(SYNC) @Operation(hidden = true) - public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION) String authorizationHeader, + public ResponseEntity syncProducts( + @RequestHeader(value = X_AUTHORIZATION) String authorizationHeader, @RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) { String token = getBearerToken(authorizationHeader); gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); @@ -119,7 +111,7 @@ public ResponseEntity syncProducts(@RequestHeader(value = AUTHORIZATION @PostMapping(CUSTOM_SORT) @Operation(hidden = true) public ResponseEntity createCustomSortProducts( - @RequestHeader(value = AUTHORIZATION) String authorizationHeader, + @RequestHeader(value = X_AUTHORIZATION) String authorizationHeader, @RequestBody @Valid ProductCustomSortRequest productCustomSortRequest) { String token = getBearerToken(authorizationHeader); gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java index 4910a83b8..6242e5589 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductDetailsController.java @@ -41,8 +41,7 @@ public class ProductDetailsController { private final ProductService productService; private final ProductDetailModelAssembler detailModelAssembler; - public ProductDetailsController(VersionService versionService, ProductService productService, - ProductDetailModelAssembler detailModelAssembler) { + public ProductDetailsController(VersionService versionService, ProductService productService, ProductDetailModelAssembler detailModelAssembler) { this.versionService = versionService; this.productService = productService; this.detailModelAssembler = detailModelAssembler; @@ -50,12 +49,9 @@ public ProductDetailsController(VersionService versionService, ProductService pr @GetMapping(BY_ID_AND_TAG) @Operation(summary = "Find product detail by product id and release tag.", description = "get product detail by it product id and release tag") - public ResponseEntity findProductDetailsByVersion(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) - String id, - @PathVariable(TAG) - @Parameter(description = "Release tag (from git hub repo tags)", example = "v10.0.20", in = ParameterIn.PATH) - String tag) { + public ResponseEntity findProductDetailsByVersion( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) String id, + @PathVariable(TAG) @Parameter(description = "Release tag (from git hub repo tags)", example = "v10.0.20", in = ParameterIn.PATH) String tag) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail, tag), HttpStatus.OK); } @@ -63,30 +59,25 @@ public ResponseEntity findProductDetailsByVersion(@PathVaria @CrossOrigin(originPatterns = "*") @PutMapping(INSTALLATION_COUNT_BY_ID) @Operation(summary = "Update installation count of product", description = "By default, increase installation count when click download product files by users") - public ResponseEntity syncInstallationCount(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) - String productId) { + public ResponseEntity syncInstallationCount( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) String productId) { int result = productService.updateInstallationCountForProduct(productId); return new ResponseEntity<>(result, HttpStatus.OK); } @GetMapping(BY_ID) @Operation(summary = "increase installation count by 1", description = "update installation count when click download product files by users") - public ResponseEntity findProductDetails(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) - String id) { + public ResponseEntity findProductDetails( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) String id) { var productDetail = productService.fetchProductDetail(id); return new ResponseEntity<>(detailModelAssembler.toModel(productDetail), HttpStatus.OK); } @GetMapping(VERSIONS_BY_ID) - public ResponseEntity> findProductVersionsById(@PathVariable(ID) - @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) - String id, - @RequestParam(SHOW_DEV_VERSION) @Parameter(description = "Option to get Dev Version (Snapshot/ sprint release)", in = ParameterIn.QUERY) - boolean isShowDevVersion, - @RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(in = ParameterIn.QUERY, example = "v10.0.20") - String designerVersion) { + public ResponseEntity> findProductVersionsById( + @PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "adobe-acrobat-connector", in = ParameterIn.PATH) String id, + @RequestParam(SHOW_DEV_VERSION) @Parameter(description = "Option to get Dev Version (Snapshot/ sprint release)", in = ParameterIn.QUERY) boolean isShowDevVersion, + @RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(in = ParameterIn.QUERY, example = "v10.0.20") String designerVersion) { List models = versionService.getArtifactsAndVersionToDisplay(id, isShowDevVersion, designerVersion); return new ResponseEntity<>(models, HttpStatus.OK); diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.spec.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.spec.ts index 45ac6ef43..258f434cf 100644 --- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.spec.ts +++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.spec.ts @@ -55,7 +55,7 @@ describe('ProductFeedbackService', () => { const req = httpMock.expectOne('api/feedback'); expect(req.request.method).toBe('POST'); - expect(req.request.headers.get('Authorization')).toBe('Bearer mockToken'); + expect(req.request.headers.get('X-Authorization')).toBe('Bearer mockToken'); req.flush(feedback); expect(productStarRatingService.fetchData).toHaveBeenCalled(); }); diff --git a/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.ts b/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.ts index f21ea75c3..3236febe2 100644 --- a/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.ts +++ b/marketplace-ui/src/app/modules/product/product-detail/product-detail-feedback/product-feedbacks-panel/product-feedback.service.ts @@ -47,7 +47,7 @@ export class ProductFeedbackService { submitFeedback(feedback: Feedback): Observable { const headers = new HttpHeaders().set( - 'Authorization', + 'X-Authorization', `Bearer ${this.authService.getToken()}` ); return this.http From 798e28ea8d49c23e3481bbb254de254c701e313d Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 1 Aug 2024 11:32:01 +0700 Subject: [PATCH 14/15] reverse change --- .../com/axonivy/market/constants/RequestParamConstants.java | 1 + .../com/axonivy/market/controller/ProductController.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java b/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java index 5bb093dcb..b0b446b5f 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java +++ b/marketplace-service/src/main/java/com/axonivy/market/constants/RequestParamConstants.java @@ -11,6 +11,7 @@ public class RequestParamConstants { public static final String KEYWORD = "keyword"; public static final String LANGUAGE = "language"; public static final String USER_ID = "userId"; + public static final String AUTHORIZATION = "Authorization"; public static final String X_AUTHORIZATION = "X-Authorization"; public static final String RESET_SYNC = "resetSync"; public static final String SHOW_DEV_VERSION = "isShowDevVersion"; diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 0b4dade05..99a8954f6 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -3,6 +3,7 @@ import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; import static com.axonivy.market.constants.RequestMappingConstants.SYNC; import static com.axonivy.market.constants.RequestParamConstants.X_AUTHORIZATION; +import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; import static com.axonivy.market.constants.RequestParamConstants.KEYWORD; import static com.axonivy.market.constants.RequestParamConstants.LANGUAGE; import static com.axonivy.market.constants.RequestParamConstants.RESET_SYNC; @@ -85,7 +86,7 @@ public ResponseEntity> findProducts( @PutMapping(SYNC) @Operation(hidden = true) public ResponseEntity syncProducts( - @RequestHeader(value = X_AUTHORIZATION) String authorizationHeader, + @RequestHeader(value = AUTHORIZATION) String authorizationHeader, @RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) { String token = getBearerToken(authorizationHeader); gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); @@ -111,7 +112,7 @@ public ResponseEntity syncProducts( @PostMapping(CUSTOM_SORT) @Operation(hidden = true) public ResponseEntity createCustomSortProducts( - @RequestHeader(value = X_AUTHORIZATION) String authorizationHeader, + @RequestHeader(value = AUTHORIZATION) String authorizationHeader, @RequestBody @Valid ProductCustomSortRequest productCustomSortRequest) { String token = getBearerToken(authorizationHeader); gitHubService.validateUserOrganization(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME); From 67ce8d601e2da2fe1b5d2a0608b4fee973c77435 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Thu, 1 Aug 2024 11:34:10 +0700 Subject: [PATCH 15/15] Update ProductController.java --- .../java/com/axonivy/market/controller/ProductController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java index 99a8954f6..f315ad6f4 100644 --- a/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java +++ b/marketplace-service/src/main/java/com/axonivy/market/controller/ProductController.java @@ -2,7 +2,6 @@ import static com.axonivy.market.constants.RequestMappingConstants.PRODUCT; import static com.axonivy.market.constants.RequestMappingConstants.SYNC; -import static com.axonivy.market.constants.RequestParamConstants.X_AUTHORIZATION; import static com.axonivy.market.constants.RequestParamConstants.AUTHORIZATION; import static com.axonivy.market.constants.RequestParamConstants.KEYWORD; import static com.axonivy.market.constants.RequestParamConstants.LANGUAGE;