From 081791f8701a9f8f549094e6a8a04f22b7abc20c Mon Sep 17 00:00:00 2001 From: Thomasr Date: Fri, 20 Dec 2024 15:04:24 -0500 Subject: [PATCH 1/2] slug validation --- .../repository/ApplicationRepository.java | 4 +++- .../service/ApplicationServiceImpl.java | 15 ++++++++------- .../service/OrganizationServiceImpl.java | 4 ++++ .../java/org/lowcoder/domain/util/SlugUtils.java | 7 +++++++ .../java/org/lowcoder/sdk/exception/BizError.java | 3 ++- 5 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/util/SlugUtils.java diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java index 4a984b8da..e8ee2ed00 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java @@ -67,6 +67,8 @@ public interface ApplicationRepository extends ReactiveMongoRepository findByPublicToAllIsTrueAndAgencyProfileIsTrue(); - Mono existsBySlug(String slug); + + @Query("{ 'organizationId': ?0, 'slug': ?1 }") + Mono existsByOrganizationIdAndSlug(String organizationId, String slug); } diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java index 3b3be763a..9de7ff950 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java @@ -18,6 +18,7 @@ import org.lowcoder.domain.permission.model.ResourceType; import org.lowcoder.domain.permission.service.ResourcePermissionService; import org.lowcoder.domain.user.repository.UserRepository; +import org.lowcoder.domain.util.SlugUtils; import org.lowcoder.infra.annotation.NonEmptyMono; import org.lowcoder.infra.mongo.MongoUpsertHelper; import org.lowcoder.sdk.constants.FieldName; @@ -349,15 +350,15 @@ public Mono> getLiveDSLByApplicationId(String applicationId) @Override public Mono updateSlug(String applicationId, String newSlug) { - return repository.existsBySlug(newSlug).flatMap(exists -> { + return repository.findById(applicationId).flatMap(application -> repository.existsByOrganizationIdAndSlug(application.getOrganizationId(), newSlug).flatMap(exists -> { + if (!SlugUtils.validate(newSlug)) { + return Mono.error(new BizException(BizError.INVALID_SLUG, "Slug format is invalid")); + } if (exists) { return Mono.error(new BizException(BizError.DUPLICATE_ENTRY, "Slug already exists")); } - return repository.findById(applicationId) - .flatMap(application -> { - application.setSlug(newSlug); - return repository.save(application); - }); - }); + application.setSlug(newSlug); + return repository.save(application); + })); } } diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java index f1bc1470d..0b1362248 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java @@ -16,6 +16,7 @@ import org.lowcoder.domain.organization.repository.OrganizationRepository; import org.lowcoder.domain.user.model.User; import org.lowcoder.domain.user.repository.UserRepository; +import org.lowcoder.domain.util.SlugUtils; import org.lowcoder.infra.annotation.PossibleEmptyMono; import org.lowcoder.infra.mongo.MongoUpsertHelper; import org.lowcoder.sdk.config.CommonConfig; @@ -292,6 +293,9 @@ private String buildCommonSettingsUpdateTimeKey(String key) { @Override public Mono updateSlug(String organizationId, String newSlug) { return repository.existsBySlug(newSlug).flatMap(exists -> { + if (!SlugUtils.validate(newSlug)) { + return Mono.error(new BizException(BizError.INVALID_SLUG, "Slug format is invalid")); + } if (exists) { return Mono.error(new BizException(BizError.DUPLICATE_ENTRY, "Slug already exists")); } diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/util/SlugUtils.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/util/SlugUtils.java new file mode 100644 index 000000000..be7e138f3 --- /dev/null +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/util/SlugUtils.java @@ -0,0 +1,7 @@ +package org.lowcoder.domain.util; + +public class SlugUtils { + public static Boolean validate(String slug) { + return slug.matches("^[a-zA-Z0-9_-]*$"); + } +} diff --git a/server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/exception/BizError.java b/server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/exception/BizError.java index aac1d9565..b43c5e51d 100644 --- a/server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/exception/BizError.java +++ b/server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/exception/BizError.java @@ -154,7 +154,8 @@ public enum BizError { ILLEGAL_BUNDLE_PERMISSION_ID(500, 6404), //slug 6501 - 6501 - DUPLICATE_ENTRY(403, 6501); + DUPLICATE_ENTRY(403, 6501), + INVALID_SLUG(403, 6502); static { checkDuplicates(values(), BizError::getBizErrorCode); From 9fd3f286ffa628f078afd1520e40949f8b58359a Mon Sep 17 00:00:00 2001 From: Thomasr Date: Fri, 20 Dec 2024 15:55:22 -0500 Subject: [PATCH 2/2] search by slugs --- .../repository/ApplicationRepository.java | 5 +++++ .../service/ApplicationServiceImpl.java | 14 +++++++----- .../repository/OrganizationRepository.java | 3 +++ .../service/OrganizationServiceImpl.java | 8 +++---- .../org/lowcoder/api/util/GidService.java | 22 ++++++++++++------- .../api/common/TestRedisConfiguration.java | 2 +- 6 files changed, 36 insertions(+), 18 deletions(-) diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java index e8ee2ed00..c320dc0c9 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java @@ -29,6 +29,9 @@ public interface ApplicationRepository extends ReactiveMongoRepository findByGid(@Nonnull String gid); + @Aggregation(pipeline = {"{ $match: { slug: ?0 } }", "{ $project: { 'editingApplicationDSL.settings': 1, _id: 1, gid: 1, organizationId: 1, name: 1, applicationType: 1, applicationStatus: 1, publicToAll: 1, publicToMarketplace: 1, agencyProfile: 1, editingUserId: 1, lastEditedAt: 1, createdAt: 1, updatedAt: 1, createdBy: 1, modifiedBy: 1, _class: 1}}"}) + Flux findBySlug(@Nonnull String slug); + Mono countByOrganizationIdAndApplicationStatus(String organizationId, ApplicationStatus applicationStatus); @Query("{$or : [{'publishedApplicationDSL.queries.datasourceId':?0},{'editingApplicationDSL.queries.datasourceId':?0}]}") @@ -36,9 +39,11 @@ public interface ApplicationRepository extends ReactiveMongoRepository findByIdIn(Collection ids); Flux findByGidIn(Collection ids); + Flux findBySlugIn(Collection slugs); Flux findByCreatedByAndIdIn(String userId, Collection ids); Flux findByCreatedByAndGidIn(String userId, Collection gids); + Flux findByCreatedByAndSlugIn(String userId, Collection slugs); /** * Filter public applications from list of supplied IDs diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java index 9de7ff950..e8fc4b791 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java @@ -61,9 +61,13 @@ public Mono findByIdWithoutDsl(String id) { return Mono.error(new BizException(BizError.INVALID_PARAMETER, "INVALID_PARAMETER", FieldName.ID)); } - if(FieldName.isGID(id)) - return Mono.from(repository.findByGid(id)).switchIfEmpty(Mono.error(new BizException(BizError.NO_RESOURCE_FOUND, "CANT_FIND_APPLICATION", id))); - return repository.findById(id) + return Mono.from(repository.findBySlug(id)) + .switchIfEmpty( + Mono.defer(() -> { + if (FieldName.isGID(id)) + return Mono.from(repository.findByGid(id)); + return repository.findById(id); + })) .switchIfEmpty(Mono.error(new BizException(BizError.NO_RESOURCE_FOUND, "CANT_FIND_APPLICATION", id))); } @@ -124,7 +128,7 @@ public Mono countByOrganizationId(String orgId, ApplicationStatus applicat public Flux findByIdIn(List applicationIds) { if(!applicationIds.isEmpty() && FieldName.isGID(applicationIds.get(0))) return repository.findByGidIn(applicationIds); - return repository.findByIdIn(applicationIds); + return repository.findBySlugIn(applicationIds).switchIfEmpty(repository.findByIdIn(applicationIds)); } @Override @@ -280,7 +284,7 @@ public Mono> getPrivateApplicationIds(Collection application .map(Application::getGid) .collect(Collectors.toSet()); - return repository.findByCreatedByAndIdIn(userId, applicationIds) + return repository.findByCreatedByAndSlugIn(userId, applicationIds).switchIfEmpty(repository.findByCreatedByAndIdIn(userId, applicationIds)) .map(HasIdAndAuditing::getId) .collect(Collectors.toSet()); } diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/repository/OrganizationRepository.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/repository/OrganizationRepository.java index 13f7d2399..7fceace3e 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/repository/OrganizationRepository.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/repository/OrganizationRepository.java @@ -16,11 +16,14 @@ public interface OrganizationRepository extends ReactiveMongoRepository findByIdInAndState(Collection id, OrganizationState state); Flux findByGidInAndState(Collection gid, OrganizationState state); + Flux findBySlugInAndState(Collection slug, OrganizationState state); Flux findByGid(String gid); + Flux findBySlug(String slug); Flux findByState(OrganizationState state); Mono findByIdAndState(String id, OrganizationState state); Mono findByGidAndState(String gid, OrganizationState state); + Mono findBySlugAndState(String slug, OrganizationState state); Mono findBySourceAndThirdPartyCompanyIdAndState(String source, String tpCompanyId, OrganizationState state); diff --git a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java index 0b1362248..5cc9fe87b 100644 --- a/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java +++ b/server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java @@ -170,7 +170,7 @@ public Mono getById(String id) { if(FieldName.isGID(id)) return repository.findByGidAndState(id, ACTIVE) .switchIfEmpty(deferredError(UNABLE_TO_FIND_VALID_ORG, "INVALID_ORG_ID")); - return repository.findByIdAndState(id, ACTIVE) + return repository.findBySlugAndState(id, ACTIVE).switchIfEmpty(repository.findByIdAndState(id, ACTIVE)) .switchIfEmpty(deferredError(UNABLE_TO_FIND_VALID_ORG, "INVALID_ORG_ID")); } @@ -180,7 +180,7 @@ public Mono getOrgCommonSettings(String orgId) { return repository.findByGidAndState(orgId, ACTIVE) .switchIfEmpty(deferredError(UNABLE_TO_FIND_VALID_ORG, "INVALID_ORG_ID")) .map(Organization::getCommonSettings); - return repository.findByIdAndState(orgId, ACTIVE) + return repository.findBySlugAndState(orgId, ACTIVE).switchIfEmpty(repository.findByIdAndState(orgId, ACTIVE)) .switchIfEmpty(deferredError(UNABLE_TO_FIND_VALID_ORG, "INVALID_ORG_ID")) .map(Organization::getCommonSettings); } @@ -189,7 +189,7 @@ public Mono getOrgCommonSettings(String orgId) { public Flux getByIds(Collection ids) { if(!ids.isEmpty() && FieldName.isGID(ids.stream().findFirst().get())) return repository.findByGidInAndState(ids, ACTIVE); - return repository.findByIdInAndState(ids, ACTIVE); + return repository.findBySlugInAndState(ids, ACTIVE).switchIfEmpty(repository.findByIdInAndState(ids, ACTIVE)); } @Override @@ -222,7 +222,7 @@ public Mono uploadLogo(String organizationId, Part filePart) { public Mono deleteLogo(String organizationId) { Mono organizationMono; if(FieldName.isGID(organizationId)) organizationMono = repository.findByGidAndState(organizationId, ACTIVE); - else organizationMono = repository.findByIdAndState(organizationId, ACTIVE); + else organizationMono = repository.findBySlugAndState(organizationId, ACTIVE).switchIfEmpty(repository.findByIdAndState(organizationId, ACTIVE)); return organizationMono .flatMap(organization -> { // delete from asset repo. diff --git a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/util/GidService.java b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/util/GidService.java index 2b9e0ecfc..921bcb164 100644 --- a/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/util/GidService.java +++ b/server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/util/GidService.java @@ -40,10 +40,13 @@ public class GidService { private BundleRepository bundleRepository; public Mono convertApplicationIdToObjectId(String id) { - if(FieldName.isGID(id)) { - return applicationRepository.findByGid(id).next().mapNotNull(HasIdAndAuditing::getId); - } - return Mono.just(id); + return applicationRepository.findBySlug(id).next().mapNotNull(HasIdAndAuditing::getId).switchIfEmpty( + Mono.defer(() -> { + if (FieldName.isGID(id)) { + return applicationRepository.findByGid(id).next().mapNotNull(HasIdAndAuditing::getId); + } + return Mono.just(id); + })); } public Mono convertDatasourceIdToObjectId(String id) { @@ -54,10 +57,13 @@ public Mono convertDatasourceIdToObjectId(String id) { } public Mono convertOrganizationIdToObjectId(String id) { - if(FieldName.isGID(id)) { - return organizationRepository.findByGid(id).next().mapNotNull(HasIdAndAuditing::getId); - } - return Mono.just(id); + return organizationRepository.findBySlug(id).next().mapNotNull(HasIdAndAuditing::getId).switchIfEmpty( + Mono.defer(() -> { + if(FieldName.isGID(id)) { + return organizationRepository.findByGid(id).next().mapNotNull(HasIdAndAuditing::getId); + } + return Mono.just(id); + })); } public Mono convertGroupIdToObjectId(String id) { diff --git a/server/api-service/lowcoder-server/src/test/java/org/lowcoder/api/common/TestRedisConfiguration.java b/server/api-service/lowcoder-server/src/test/java/org/lowcoder/api/common/TestRedisConfiguration.java index 1119462f2..f42ae0cd4 100644 --- a/server/api-service/lowcoder-server/src/test/java/org/lowcoder/api/common/TestRedisConfiguration.java +++ b/server/api-service/lowcoder-server/src/test/java/org/lowcoder/api/common/TestRedisConfiguration.java @@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger; @SuppressWarnings("UnstableApiUsage") -@TestConfiguration +//@TestConfiguration public class TestRedisConfiguration { private static final AtomicInteger STATE = new AtomicInteger(0);