Skip to content

Commit

Permalink
Merge branch 'develop' into feature/marp-1548-suspicious-installation…
Browse files Browse the repository at this point in the history
…-count
  • Loading branch information
quanpham-axonivy authored Dec 16, 2024
2 parents cc64d49 + 4439b5d commit 7c5e713
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 25 deletions.
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 Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,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 @@ -64,6 +64,7 @@ public class Product implements Serializable {
@Transient
private int installationCount;
private Date newestPublishedDate;
private Date firstPublishedDate;
private String newestReleaseVersion;
@Transient
private ProductModuleContent productModuleContent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public enum SortOption {
POPULARITY("popularity", "marketplaceData.installationCount", Sort.Direction.DESC),
ALPHABETICALLY("alphabetically", "names", Sort.Direction.ASC),
RECENT("recent", "newestPublishedDate", Sort.Direction.DESC),
RECENT("recent", "firstPublishedDate", Sort.Direction.DESC),
STANDARD("standard", "marketplaceData.customOrder", Sort.Direction.DESC),
ID("id", "_id", Sort.Direction.ASC);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ public interface ProductService {

boolean syncOneProduct(String productId, String marketItemPath, Boolean overrideMarketItemPath);

void clearAllProductVersion();
boolean syncFirstPublishedDateOfAllProducts();
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.kohsuke.github.GHCommit;
import org.kohsuke.github.GHContent;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GHTag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Expand All @@ -57,15 +58,7 @@
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.*;

import static com.axonivy.market.constants.CommonConstants.SLASH;
import static com.axonivy.market.constants.MavenConstants.*;
Expand Down Expand Up @@ -370,8 +363,8 @@ private List<String> syncProductsFromGitHubRepo(Boolean resetSync) {
} else if (productRepo.findById(product.getId()).isPresent()) {
continue;
}

updateProductContentForNonStandardProduct(ghContentEntity.getValue(), product);
updateFirstPublishedDate(product);
updateProductFromReleasedVersions(product);
transferComputedDataFromDB(product);
productMarketplaceDataRepo.checkAndInitProductMarketplaceDataIfNotExist(product.getId());
Expand Down Expand Up @@ -412,6 +405,53 @@ private String mapVendorImage(String productId, GHContent ghContent, String imag
return EMPTY;
}

private void updateFirstPublishedDate(Product product) {
try {
if (StringUtils.isNotBlank(product.getRepositoryName())) {
List<GHTag> gitHubTags = gitHubService.getRepositoryTags(product.getRepositoryName());
Date firstTagPublishedDate = getFirstTagPublishedDate(gitHubTags);
product.setFirstPublishedDate(firstTagPublishedDate);
}
} catch (IOException e) {
log.error("Get GH Tags failed: ", e);
}
}

private Date getFirstTagPublishedDate(List<GHTag> gitHubTags) {
Date firstTagPublishedDate = null;
try {
if (!CollectionUtils.isEmpty(gitHubTags)) {
List<GHTag> sortedTags = sortByTagCommitDate(gitHubTags);
GHCommit commit = sortedTags.get(0).getCommit();
if (commit != null) {
firstTagPublishedDate = commit.getCommitDate();
}
}
} catch (IOException e) {
log.error("Get first tag published date failed: ", e);
}

return firstTagPublishedDate;
}

private List<GHTag> sortByTagCommitDate(List<GHTag> gitHubTags) {
List<GHTag> sortedTags = new ArrayList<>(gitHubTags);
sortedTags.sort(Comparator.comparing(this::sortByCommitDate, Comparator.nullsLast(Comparator.naturalOrder())));
return sortedTags;
}

private Date sortByCommitDate(GHTag gitHubTag) {
Date commitDate = null;
try {
if (gitHubTag.getCommit() != null) {
commitDate = gitHubTag.getCommit().getCommitDate();
}
} catch (IOException e) {
log.error("Get commit date of tag commit failed: ", e);
}
return commitDate;
}

private void updateProductFromReleasedVersions(Product product) {
if (ObjectUtils.isEmpty(product.getArtifacts())) {
return;
Expand Down Expand Up @@ -536,7 +576,6 @@ private String createProductArtifactId(Artifact mavenArtifact) {
: mavenArtifact.getArtifactId().concat(PRODUCT_ARTIFACT_POSTFIX);
}


// Cover 3 cases after removing non-numeric characters (8, 11.1 and 10.0.2)
@Override
public String getCompatibilityFromOldestVersion(String oldestVersion) {
Expand Down Expand Up @@ -628,6 +667,7 @@ public boolean syncOneProduct(String productId, String marketItemPath, Boolean o
log.info("Update data of product {} from meta.json and logo files", productId);
mappingMetaDataAndLogoFromGHContent(gitHubContents, product);
updateProductContentForNonStandardProduct(gitHubContents, product);
updateFirstPublishedDate(product);
updateProductFromReleasedVersions(product);
productMarketplaceDataRepo.checkAndInitProductMarketplaceDataIfNotExist(productId);
productRepo.save(product);
Expand All @@ -640,13 +680,6 @@ public boolean syncOneProduct(String productId, String marketItemPath, Boolean o
return false;
}

@Override
public void clearAllProductVersion() {
metadataRepo.deleteAll();
metadataSyncRepo.deleteAll();
mavenArtifactVersionRepo.deleteAll();
}

private Product renewProductById(String productId, String marketItemPath, Boolean overrideMarketItemPath) {
Product product = new Product();
productRepo.findById(productId).ifPresent(foundProduct -> {
Expand Down Expand Up @@ -692,4 +725,28 @@ private void updateProductContentForNonStandardProduct(List<GHContent> ghContent
productModuleContentRepo.save(initialContent);
}
}

@Override
public boolean syncFirstPublishedDateOfAllProducts() {
try {
List<Product> products = productRepo.findAll();
if (!CollectionUtils.isEmpty(products)) {
for (Product product : products) {
if (product.getFirstPublishedDate() == null) {
log.info("sync FirstPublishedDate of product {} is starting ...", product.getId());
updateFirstPublishedDate(product);
productRepo.save(product);
log.info("Sync FirstPublishedDate of product {} is finished!", product.getId());
} else {
log.info("FirstPublishedDate of product {} is existing!", product.getId());
}
}
}
log.info("sync FirstPublishedDate of all products is finished!");
return true;
} catch (Exception e) {
log.error(e.getStackTrace());
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class BaseSetup {
protected static final String SAMPLE_PRODUCT_ID = "amazon-comprehend";
protected static final String SAMPLE_PRODUCT_PATH = "/market/connector/amazon-comprehend";
protected static final String SAMPLE_PRODUCT_NAME = "prody Comprehend";
protected static final String SAMPLE_PRODUCT_REPOSITORY_NAME = "axonivy-market/amazon-comprehend";
protected static final Pageable PAGEABLE = PageRequest.of(0, 20,
Sort.by(SortOption.ALPHABETICALLY.getOption()).descending());
protected static final String MOCK_PRODUCT_ID = "bpmn-statistic";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,32 @@ private Product createProductMock() {
mockProduct.setTags(List.of("AI"));
return mockProduct;
}

@Test
void testSyncFirstPublishedDateOfAllProductsInvalidToken() {
doThrow(new UnauthorizedException(ErrorCode.GITHUB_USER_UNAUTHORIZED.getCode(),
ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText())).when(gitHubService)
.validateUserInOrganizationAndTeam(any(String.class), any(String.class), any(String.class));

UnauthorizedException exception = assertThrows(UnauthorizedException.class,
() -> productController.syncFirstPublishedDateOfAllProducts(INVALID_AUTHORIZATION_HEADER));

assertEquals(ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText(), exception.getMessage());
}

@Test
void testSyncFirstPublishedDateOfAllProductsFailed() {
when(service.syncFirstPublishedDateOfAllProducts()).thenReturn(false);
var response = productController.syncFirstPublishedDateOfAllProducts(AUTHORIZATION_HEADER);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode());
}

@Test
void testSyncFirstPublishedDateOfAllProductsSuccess() {
when(service.syncFirstPublishedDateOfAllProducts()).thenReturn(true);
var response = productController.syncFirstPublishedDateOfAllProducts(AUTHORIZATION_HEADER);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode());
}
}
Loading

0 comments on commit 7c5e713

Please sign in to comment.