Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MARP-1709 Create Marketplace release 1.7.0 #263

Merged
merged 17 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8d7a4a5
MARP-1573 fix issues of SonarQube (#249)
phhung-axonivy Dec 4, 2024
e4a7b57
MARP-1545 change german translation Überprüfung -> Bewertung (#250)
phhung-axonivy Dec 5, 2024
8145ab3
Bugfix/marp 1497 download tooltip is different from figma (#252)
tvtphuc-axonivy Dec 10, 2024
a50762f
MARP-1577 marketplace cannot install market item on the web browser o…
ntqdinh-axonivy Dec 13, 2024
d89c12a
MARP-997 recent sorting should be based on first publish date (#255)
phhung-axonivy Dec 13, 2024
4439b5d
MARP-1642 Application Freezing due to missing product detail content …
ntqdinh-axonivy Dec 13, 2024
6ec5f3f
MARP-1294 Create a central monitoring reporting for security issues o…
ndkhanh-axonivy Dec 17, 2024
e1a0d85
MARP-1548 Suspicious installation counts (#257)
quanpham-axonivy Dec 17, 2024
efd4a3f
MARP-1294 Enhance performance for central monitoring reporting (#259)
ndkhanh-axonivy Dec 19, 2024
4b06539
Modify docker's log directory
quanpham-axonivy Dec 19, 2024
f1b7648
MARP-1629 Change README split, image regex (#256)
nntthuy-axonivy Dec 19, 2024
c77e787
Fix wrong support email
Dec 19, 2024
28eb978
MARP-1548 Fix log missing arguments (#261)
quanpham-axonivy Dec 19, 2024
e781fda
MARP-1548 Suspicious numbers in installation count - Fix unstable test
quanpham-axonivy Dec 19, 2024
4458876
MARP-1118 reloading of webpage caused a flickering (#254)
ntqdinh-axonivy Dec 23, 2024
d052ec8
Handle feedback
Dec 23, 2024
64e7871
Merge branch 'master' into develop
phhung-axonivy Dec 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion marketplace-build/.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ MARKET_GITHUB_OAUTH_APP_CLIENT_ID=
MARKET_GITHUB_OAUTH_APP_CLIENT_SECRET=
MARKET_JWT_SECRET_KEY=
MARKET_CORS_ALLOWED_ORIGIN=*
MARKET_MONGO_LOG_LEVEL=DEBUG
MARKET_MONGO_LOG_LEVEL=DEBUG
MARKET_LOG_PATH=logs
3 changes: 2 additions & 1 deletion marketplace-build/dev/.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ MARKET_GITHUB_OAUTH_APP_CLIENT_ID=
MARKET_GITHUB_OAUTH_APP_CLIENT_SECRET=
MARKET_JWT_SECRET_KEY=
MARKET_CORS_ALLOWED_ORIGIN=*
MARKET_MONGO_LOG_LEVEL=DEBUG
MARKET_MONGO_LOG_LEVEL=DEBUG
MARKET_LOG_PATH=logs
2 changes: 2 additions & 0 deletions marketplace-build/dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ services:
volumes:
- /home/axonivy/marketplace/data/market-installations.json:/app/data/market-installation.json
- marketcache:/app/data/market-cache
- ../logs:/app/logs
environment:
- MONGODB_HOST=${SERVICE_MONGODB_HOST}
- MONGODB_DATABASE=${SERVICE_MONGODB_DATABASE}
Expand All @@ -36,6 +37,7 @@ services:
- MARKET_JWT_SECRET_KEY=${MARKET_JWT_SECRET_KEY}
- MARKET_CORS_ALLOWED_ORIGIN=${MARKET_CORS_ALLOWED_ORIGIN}
- MARKET_MONGO_LOG_LEVEL=${MARKET_MONGO_LOG_LEVEL}
- MARKET_LOG_PATH=${MARKET_LOG_PATH}
build:
context: ../../marketplace-service
dockerfile: Dockerfile
Expand Down
2 changes: 2 additions & 0 deletions marketplace-build/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ services:
volumes:
- /home/axonivy/marketplace/data/market-installations.json:/app/data/market-installation.json
- marketcache:/app/data/market-cache
- ../logs:/app/logs
environment:
- MONGODB_HOST=${SERVICE_MONGODB_HOST}
- MONGODB_DATABASE=${SERVICE_MONGODB_DATABASE}
Expand All @@ -36,6 +37,7 @@ services:
- MARKET_JWT_SECRET_KEY=${MARKET_JWT_SECRET_KEY}
- MARKET_CORS_ALLOWED_ORIGIN=${MARKET_CORS_ALLOWED_ORIGIN}
- MARKET_MONGO_LOG_LEVEL=${MARKET_MONGO_LOG_LEVEL}
- MARKET_LOG_PATH=${MARKET_LOG_PATH}
build:
context: ../marketplace-service
dockerfile: Dockerfile
Expand Down
3 changes: 2 additions & 1 deletion marketplace-build/release/.env
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ MARKET_GITHUB_OAUTH_APP_CLIENT_ID=
MARKET_GITHUB_OAUTH_APP_CLIENT_SECRET=
MARKET_JWT_SECRET_KEY=
MARKET_CORS_ALLOWED_ORIGIN=*
MARKET_MONGO_LOG_LEVEL=DEBUG
MARKET_MONGO_LOG_LEVEL=DEBUG
MARKET_LOG_PATH=logs
2 changes: 2 additions & 0 deletions marketplace-build/release/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ services:
volumes:
- /home/axonivy/marketplace/data/market-installations.json:/app/data/market-installation.json
- marketcache:/app/data/market-cache
- ../logs:/app/logs
environment:
- MONGODB_HOST=${SERVICE_MONGODB_HOST}
- MONGODB_DATABASE=${SERVICE_MONGODB_DATABASE}
Expand All @@ -34,6 +35,7 @@ services:
- MARKET_JWT_SECRET_KEY=${MARKET_JWT_SECRET_KEY}
- MARKET_CORS_ALLOWED_ORIGIN=${MARKET_CORS_ALLOWED_ORIGIN}
- MARKET_MONGO_LOG_LEVEL=${MARKET_MONGO_LOG_LEVEL}
- MARKET_LOG_PATH=${MARKET_LOG_PATH}
networks:
- marketplace-network

Expand Down
6 changes: 5 additions & 1 deletion marketplace-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.axonivy.market.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class CommonConstants {
public static final String REQUESTED_BY = "X-Requested-By";
public static final String USER_AGENT = "user-agent";
public static final String SLASH = "/";
public static final String DOT_SEPARATOR = ".";
public static final String PLUS = "+";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ public static class Json {
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String CODE = "code";
public static final String USER_ID = "id";
public static final String USER_NAME = "name";
public static final String USER_AVATAR_URL = "avatar_url";
public static final String USER_LOGIN_NAME = "login";
public static final String SEVERITY = "severity";
public static final String SECURITY_SEVERITY_LEVEL = "security_severity_level";
public static final String SEVERITY_ADVISORY = "security_advisory";
public static final String RULE = "rule";
}

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static class Url {
private static final String BASE_URL = "https://api.github.com";
public static final String USER = BASE_URL + "/user";
public static final String REPO_DEPENDABOT_ALERTS_OPEN = BASE_URL + "/repos/%s/%s/dependabot/alerts?state=open";
public static final String REPO_SECRET_SCANNING_ALERTS_OPEN =
BASE_URL + "/repos/%s/%s/secret-scanning/alerts?state=open";
public static final String REPO_CODE_SCANNING_ALERTS_OPEN =
BASE_URL + "/repos/%s/%s/code-scanning/alerts?state=open";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.axonivy.market.constants;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LoggingConstants {

public static final String ENTRY_FORMAT = " <%s>%s</%s>%n";
public static final String ENTRY_START = " <LogEntry>\n";
public static final String ENTRY_END = " </LogEntry>\n";
public static final String DATE_FORMAT = "yyyy-MM-dd";
public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String LOG_START = "<Logs>\n";
public static final String LOG_END = "</Logs>";
public static final String METHOD = "method";
public static final String ARGUMENTS = "arguments";
public static final String TIMESTAMP = "timestamp";
public static final String NO_ARGUMENTS = "No arguments";
public static final String MARKET_WEBSITE = "marketplace-website";

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class RequestMappingConstants {
public static final String FEEDBACK = API + "/feedback";
public static final String IMAGE = API + "/image";
public static final String SYNC = "sync";
public static final String SYNC_PRODUCT_VERSION = SYNC + "/product-version";
public static final String SYNC_FIRST_PUBLISHED_DATE_ALL_PRODUCTS = SYNC + "/first-published-date";
public static final String SYNC_ONE_PRODUCT_BY_ID = "sync/{id}";
public static final String SWAGGER_URL = "/swagger-ui/index.html";
public static final String GIT_HUB_LOGIN = "/github/login";
Expand All @@ -32,4 +32,5 @@ public class RequestMappingConstants {
public static final String LATEST_ARTIFACT_DOWNLOAD_URL_BY_ID = "/{id}/artifact";
public static final String EXTERNAL_DOCUMENT = API + "/externaldocument";
public static final String PRODUCT_MARKETPLACE_DATA = API + "/product-marketplace-data";
public static final String SECURITY_MONITOR = API + "/security-monitor";
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,34 +112,6 @@ public ResponseEntity<Message> syncProducts(@RequestHeader(value = AUTHORIZATION
return new ResponseEntity<>(message, HttpStatus.OK);
}

/**
* @deprecated
*/
@Deprecated(forRemoval = true , since = "1.6.0")
@PutMapping(SYNC_PRODUCT_VERSION)
@Operation(hidden = true)
public ResponseEntity<Message> syncProductVersions(@RequestHeader(value = AUTHORIZATION) String authorizationHeader
,@RequestParam(value = RESET_SYNC, required = false) Boolean resetSync) {
String token = AuthorizationUtils.getBearerToken(authorizationHeader);
gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME,
GitHubConstants.AXONIVY_MARKET_TEAM_NAME);
if (Boolean.TRUE.equals(resetSync)) {
productService.clearAllProductVersion();
}
int nonSyncResult = metadataService.syncAllProductsMetadata();
var message = new Message();
HttpStatus statusCode = HttpStatus.OK;
if(nonSyncResult == 1) {
message.setHelpCode(ErrorCode.SUCCESSFUL.getCode());
message.setHelpText(ErrorCode.SUCCESSFUL.getHelpText());
} else {
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
message.setHelpCode(ErrorCode.MAVEN_VERSION_SYNC_FAILED.getCode());
message.setMessageDetails(ErrorCode.MAVEN_VERSION_SYNC_FAILED.getHelpText());
}
return new ResponseEntity<>(message, statusCode);
}

@PutMapping(SYNC_ONE_PRODUCT_BY_ID)
@Operation(hidden = true)
public ResponseEntity<Message> syncOneProduct(
Expand Down Expand Up @@ -173,6 +145,25 @@ public ResponseEntity<Message> syncOneProduct(
return new ResponseEntity<>(message, HttpStatus.OK);
}

@PutMapping(SYNC_FIRST_PUBLISHED_DATE_ALL_PRODUCTS)
@Operation(hidden = true)
public ResponseEntity<Message> syncFirstPublishedDateOfAllProducts(
@RequestHeader(value = AUTHORIZATION) String authorizationHeader) {
String token = AuthorizationUtils.getBearerToken(authorizationHeader);
gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME,
GitHubConstants.AXONIVY_MARKET_TEAM_NAME);

var message = new Message();
var isSuccess = productService.syncFirstPublishedDateOfAllProducts();
if (isSuccess) {
message.setHelpCode(ErrorCode.SUCCESSFUL.getCode());
message.setMessageDetails("Sync successfully!");
} else {
message.setMessageDetails("Sync unsuccessfully!");
}
return new ResponseEntity<>(message, HttpStatus.OK);
}

@SuppressWarnings("unchecked")
private ResponseEntity<PagedModel<ProductModel>> generateEmptyPagedModel() {
var emptyPagedModel = (PagedModel<ProductModel>) pagedResourcesAssembler.toEmptyModel(Page.empty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
import com.axonivy.market.constants.GitHubConstants;
import com.axonivy.market.enums.ErrorCode;
import com.axonivy.market.github.service.GitHubService;
import com.axonivy.market.logging.Loggable;
import com.axonivy.market.model.Message;
import com.axonivy.market.model.ProductCustomSortRequest;
import com.axonivy.market.service.ProductMarketplaceDataService;
import com.axonivy.market.util.AuthorizationUtils;
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.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
Expand All @@ -36,7 +35,7 @@
public class ProductMarketplaceDataController {
private final GitHubService gitHubService;
private final ProductMarketplaceDataService productMarketplaceDataService;

@PostMapping(CUSTOM_SORT)
@Operation(hidden = true)
public ResponseEntity<Message> createCustomSortProducts(
Expand All @@ -51,15 +50,14 @@ public ResponseEntity<Message> createCustomSortProducts(
return new ResponseEntity<>(message, HttpStatus.OK);
}

@Loggable
@Operation(hidden = true)
@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<Integer> syncInstallationCount(
@PathVariable(ID) @Parameter(description = "Product id (from meta.json)", example = "approval-decision-utils",
in = ParameterIn.PATH) String productId,
@RequestParam(name = DESIGNER_VERSION, required = false) @Parameter(in = ParameterIn.QUERY,
example = "v10.0.20") String designerVersion) {
@PathVariable(ID) String productId,
@RequestParam(name = DESIGNER_VERSION, required = false) String designerVersion) {
int result = productMarketplaceDataService.updateInstallationCountForProduct(productId, designerVersion);
return new ResponseEntity<>(result, HttpStatus.OK);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.axonivy.market.controller;

import com.axonivy.market.constants.GitHubConstants;
import com.axonivy.market.github.service.GitHubService;
import com.axonivy.market.github.model.ProductSecurityInfo;
import com.axonivy.market.util.AuthorizationUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import static com.axonivy.market.constants.RequestMappingConstants.SECURITY_MONITOR;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

@RestController
@RequestMapping(SECURITY_MONITOR)
@Tag(name = "Security Monitor Controllers", description = "API collection to get Github Marketplace security's detail.")
@AllArgsConstructor
public class SecurityMonitorController {
private final GitHubService gitHubService;

@GetMapping
@Operation(hidden = true)
public ResponseEntity<Object> getGitHubMarketplaceSecurity(
@RequestHeader(value = AUTHORIZATION) String authorizationHeader) {
String token = AuthorizationUtils.getBearerToken(authorizationHeader);
gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME,
GitHubConstants.AXONIVY_MARKET_TEAM_NAME);
List<ProductSecurityInfo> securityInfoList = gitHubService.getSecurityDetailsForAllProducts(token,
GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME);
return ResponseEntity.ok(securityInfoList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,12 @@ public class Product implements Serializable {
@Transient
private int installationCount;
private Date newestPublishedDate;
private Date firstPublishedDate;
private String newestReleaseVersion;
@Transient
private ProductModuleContent productModuleContent;
private List<Artifact> artifacts;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.6.0")
private Boolean synchronizedInstallationCount;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.6.0")
private Integer customOrder;
private List<String> releasedVersions;
@Transient
private String metaProductJsonUrl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ public class ProductJsonContent {
@JsonIgnore
private String id;
private String version;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.5.0")
private String relatedTag;
private String productId;
private String name;
private String content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import static com.axonivy.market.constants.EntityConstants.PRODUCT_MODULE_CONTENT;

Expand All @@ -31,18 +30,6 @@ public class ProductModuleContent implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "product Id (from meta.json)", example = "portal")
private String productId;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.5.0")
@Schema(description = "Target release tag", example = "v10.0.25")
private String tag;
/**
* @deprecated
*/
@Deprecated(forRemoval = true, since = "1.5.0")
@Schema(description = "Versions in maven", example = "10.0.25-SNAPSHOT")
private Set<String> mavenVersions;
@Schema(description = "Maven version", example = "10.0.25")
private String version;
@Schema(description = "Product detail description content ",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.axonivy.market.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum AccessLevel {
NO_PERMISSION, ENABLED, DISABLED
}
Loading
Loading