Skip to content

Commit 86fa678

Browse files
dragonpooludomikula
authored andcommitted
Added slug to organization and application
1 parent 4a06cc4 commit 86fa678

File tree

17 files changed

+154
-31
lines changed

17 files changed

+154
-31
lines changed

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/model/Application.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33

44
import com.fasterxml.jackson.annotation.JsonIgnore;
55
import com.fasterxml.jackson.annotation.JsonProperty;
6-
import com.github.f4b6a3.uuid.UuidCreator;
76
import lombok.Getter;
87
import lombok.NoArgsConstructor;
98
import lombok.Setter;
109
import lombok.experimental.SuperBuilder;
1110
import lombok.extern.jackson.Jacksonized;
12-
import org.apache.commons.collections4.MapUtils;
1311
import org.apache.commons.lang3.BooleanUtils;
1412
import org.lowcoder.domain.application.ApplicationUtil;
1513
import org.lowcoder.domain.application.service.ApplicationRecordService;
@@ -20,11 +18,13 @@
2018
import org.lowcoder.sdk.util.JsonUtils;
2119
import org.springframework.data.annotation.Transient;
2220
import org.springframework.data.mongodb.core.mapping.Document;
23-
import org.springframework.util.StringUtils;
2421
import reactor.core.publisher.Mono;
2522

2623
import java.time.Instant;
27-
import java.util.*;
24+
import java.util.Collections;
25+
import java.util.HashMap;
26+
import java.util.Map;
27+
import java.util.Set;
2828
import java.util.function.Supplier;
2929

3030
import static com.google.common.base.Suppliers.memoize;
@@ -39,6 +39,9 @@
3939
public class Application extends HasIdAndAuditing {
4040
@Getter
4141
private String gid;
42+
@Setter
43+
@Getter
44+
private String slug;
4245
private String organizationId;
4346
private String name;
4447
private Integer applicationType;

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/repository/ApplicationRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,6 @@ public interface ApplicationRepository extends ReactiveMongoRepository<Applicati
6767
* Find all agency applications
6868
*/
6969
Flux<Application> findByPublicToAllIsTrueAndAgencyProfileIsTrue();
70+
Mono<Boolean> existsBySlug(String slug);
71+
7072
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,6 @@ public interface ApplicationService {
7373

7474
Mono<Boolean> updateLastEditedAt(String applicationId, Instant time, String visitorId);
7575
Mono<Map<String, Object>> getLiveDSLByApplicationId(String applicationId);
76+
77+
Mono<Application> updateSlug(String applicationId, String newSlug);
7678
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/application/service/ApplicationServiceImpl.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,16 @@
1414
import org.lowcoder.domain.application.model.ApplicationRequestType;
1515
import org.lowcoder.domain.application.model.ApplicationStatus;
1616
import org.lowcoder.domain.application.repository.ApplicationRepository;
17-
import org.lowcoder.domain.organization.repository.OrganizationRepository;
18-
import org.lowcoder.domain.organization.service.OrgMemberService;
1917
import org.lowcoder.domain.permission.model.ResourceRole;
2018
import org.lowcoder.domain.permission.model.ResourceType;
2119
import org.lowcoder.domain.permission.service.ResourcePermissionService;
22-
import org.lowcoder.domain.query.model.LibraryQuery;
23-
import org.lowcoder.domain.query.model.LibraryQueryRecord;
24-
import org.lowcoder.domain.query.service.LibraryQueryRecordService;
2520
import org.lowcoder.domain.user.repository.UserRepository;
26-
import org.lowcoder.domain.user.service.UserService;
2721
import org.lowcoder.infra.annotation.NonEmptyMono;
2822
import org.lowcoder.infra.mongo.MongoUpsertHelper;
2923
import org.lowcoder.sdk.constants.FieldName;
3024
import org.lowcoder.sdk.exception.BizError;
3125
import org.lowcoder.sdk.exception.BizException;
3226
import org.lowcoder.sdk.models.HasIdAndAuditing;
33-
import org.springframework.beans.factory.annotation.Autowired;
3427
import org.springframework.stereotype.Service;
3528

3629
import com.google.common.collect.Lists;
@@ -353,4 +346,18 @@ public Mono<Map<String, Object>> getLiveDSLByApplicationId(String applicationId)
353346
.switchIfEmpty(findById(applicationId)
354347
.map(Application::getEditingApplicationDSL));
355348
}
349+
350+
@Override
351+
public Mono<Application> updateSlug(String applicationId, String newSlug) {
352+
return repository.existsBySlug(newSlug).flatMap(exists -> {
353+
if (exists) {
354+
return Mono.error(new BizException(BizError.DUPLICATE_ENTRY, "Slug already exists"));
355+
}
356+
return repository.findById(applicationId)
357+
.flatMap(application -> {
358+
application.setSlug(newSlug);
359+
return repository.save(application);
360+
});
361+
});
362+
}
356363
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/model/Organization.java

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
package org.lowcoder.domain.organization.model;
22

3-
import static java.util.Optional.ofNullable;
4-
import static org.apache.commons.lang3.ObjectUtils.firstNonNull;
5-
import static org.lowcoder.infra.util.AssetUtils.toAssetPath;
6-
7-
import java.util.*;
8-
9-
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
10-
import com.fasterxml.jackson.annotation.JsonView;
11-
import com.github.f4b6a3.uuid.UuidCreator;
3+
import com.fasterxml.jackson.annotation.JsonIgnore;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.Setter;
128
import lombok.experimental.SuperBuilder;
139
import lombok.extern.jackson.Jacksonized;
1410
import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -17,16 +13,14 @@
1713
import org.lowcoder.domain.mongodb.BeforeMongodbWrite;
1814
import org.lowcoder.domain.mongodb.MongodbInterceptorContext;
1915
import org.lowcoder.sdk.auth.AbstractAuthConfig;
20-
import org.lowcoder.sdk.config.JsonViews;
2116
import org.lowcoder.sdk.models.HasIdAndAuditing;
2217
import org.springframework.data.mongodb.core.mapping.Document;
2318

24-
import com.fasterxml.jackson.annotation.JsonIgnore;
25-
import com.fasterxml.jackson.annotation.JsonProperty;
19+
import java.util.*;
2620

27-
import lombok.Getter;
28-
import lombok.NoArgsConstructor;
29-
import lombok.Setter;
21+
import static java.util.Optional.ofNullable;
22+
import static org.apache.commons.lang3.ObjectUtils.firstNonNull;
23+
import static org.lowcoder.infra.util.AssetUtils.toAssetPath;
3024

3125

3226
@Getter
@@ -41,6 +35,8 @@ public class Organization extends HasIdAndAuditing implements BeforeMongodbWrite
4135
@Getter
4236
private String gid;
4337

38+
private String slug;
39+
4440
private String name;
4541

4642
private Boolean isAutoGeneratedOrganization;

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/repository/OrganizationRepository.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ public interface OrganizationRepository extends ReactiveMongoRepository<Organiza
2727
Mono<Organization> findByOrganizationDomain_DomainAndState(String domain, OrganizationState state);
2828

2929
Flux<Organization> findByOrganizationDomainIsNotNull();
30+
Mono<Boolean> existsBySlug(String slug);
3031
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ public interface OrganizationService {
4848
Mono<Organization> getByDomain();
4949

5050
Mono<Boolean> updateCommonSettings(String orgId, String key, Object value);
51+
52+
Mono<Organization> updateSlug(String organizationId, String newSlug);
5153
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/organization/service/OrganizationServiceImpl.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import org.lowcoder.domain.organization.repository.OrganizationRepository;
1717
import org.lowcoder.domain.user.model.User;
1818
import org.lowcoder.domain.user.repository.UserRepository;
19-
import org.lowcoder.domain.user.service.UserService;
2019
import org.lowcoder.infra.annotation.PossibleEmptyMono;
2120
import org.lowcoder.infra.mongo.MongoUpsertHelper;
2221
import org.lowcoder.sdk.config.CommonConfig;
@@ -35,10 +34,8 @@
3534
import reactor.core.publisher.Mono;
3635

3736
import java.util.Collection;
38-
import java.util.List;
3937
import java.util.Locale;
4038

41-
import static org.lowcoder.domain.authentication.AuthenticationService.DEFAULT_AUTH_CONFIG;
4239
import static org.lowcoder.domain.organization.model.OrganizationState.ACTIVE;
4340
import static org.lowcoder.domain.organization.model.OrganizationState.DELETED;
4441
import static org.lowcoder.domain.util.QueryDslUtils.fieldName;
@@ -291,4 +288,18 @@ public Mono<Boolean> updateCommonSettings(String orgId, String key, Object value
291288
private String buildCommonSettingsUpdateTimeKey(String key) {
292289
return key + "_updateTime";
293290
}
291+
292+
@Override
293+
public Mono<Organization> updateSlug(String organizationId, String newSlug) {
294+
return repository.existsBySlug(newSlug).flatMap(exists -> {
295+
if (exists) {
296+
return Mono.error(new BizException(BizError.DUPLICATE_ENTRY, "Slug already exists"));
297+
}
298+
return repository.findById(organizationId)
299+
.flatMap(organization -> {
300+
organization.setSlug(newSlug);
301+
return repository.save(organization);
302+
});
303+
});
304+
}
294305
}

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/exception/BizError.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ public enum BizError {
152152
BUNDLE_NOT_EXIST(500, 6402),
153153
BUNDLE_NAME_CONFLICT(500, 6403),
154154
ILLEGAL_BUNDLE_PERMISSION_ID(500, 6404),
155-
;
155+
156+
//slug 6501 - 6501
157+
DUPLICATE_ENTRY(403, 6501);
156158

157159
static {
158160
checkDuplicates(values(), BizError::getBizErrorCode);

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationApiService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,6 @@ Mono<Boolean> grantPermission(String applicationId,
6262

6363
// Falk: why we have request.publicToMarketplace() - but here only agencyProfile? Not from request?
6464
Mono<Boolean> setApplicationAsAgencyProfile(String applicationId, boolean agencyProfile);
65+
66+
Mono<Application> updateSlug(String applicationId, String slug);
6567
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationApiServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,11 @@ public Mono<Boolean> setApplicationAsAgencyProfile(String applicationId, boolean
600600
(applicationId, agencyProfile));
601601
}
602602

603+
@Override
604+
public Mono<Application> updateSlug(String applicationId, String slug) {
605+
return applicationService.updateSlug(applicationId, slug);
606+
}
607+
603608
private Map<String, Object> sanitizeDsl(Map<String, Object> applicationDsl) {
604609
if (applicationDsl.get("queries") instanceof List<?> queries) {
605610
List<Map<String, Object>> list = queries.stream().map(this::doSanitizeQuery).toList();

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationController.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.lowcoder.api.application;
22

3-
import io.sentry.protocol.App;
43
import lombok.RequiredArgsConstructor;
54
import org.lowcoder.api.application.view.*;
65
import org.lowcoder.api.framework.view.PageResponseView;
@@ -165,6 +164,12 @@ public Mono<ResponseView<Boolean>> updateEditState(@PathVariable String applicat
165164
.map(ResponseView::success));
166165
}
167166

167+
@Override
168+
public Mono<ResponseView<Application>> updateSlug(@PathVariable String applicationId, @RequestBody String slug) {
169+
return applicationApiService.updateSlug(applicationId, slug)
170+
.map(ResponseView::success);
171+
}
172+
168173
@Override
169174
public Mono<ResponseView<UserHomepageView>> getUserHomePage(@RequestParam(required = false, defaultValue = "0") int applicationType) {
170175
ApplicationType type = ApplicationType.fromValue(applicationType);

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/application/ApplicationEndpoints.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ public Mono<ResponseView<ApplicationView>> publish(@PathVariable String applicat
146146
public Mono<ResponseView<Boolean>> updateEditState(@PathVariable String applicationId,
147147
@RequestBody UpdateEditStateRequest updateEditStateRequest);
148148

149+
@PutMapping("/{applicationId}/slug")
150+
public Mono<ResponseView<Application>> updateSlug(@PathVariable String applicationId, @RequestBody String slug);
151+
149152
@Operation(
150153
tags = TAG_APPLICATION_MANAGEMENT,
151154
operationId = "getUserHomepageApplication",

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/OrganizationController.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,10 @@ public Mono<ResponseView<Long>> getOrgApiUsageCount(String orgId, Boolean lastMo
166166
.map(ResponseView::success));
167167
}
168168

169+
@Override
170+
public Mono<ResponseView<Organization>> updateSlug(@PathVariable String orgId, @RequestBody String slug) {
171+
return organizationService.updateSlug(orgId, slug)
172+
.map(ResponseView::success);
173+
}
174+
169175
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/OrganizationEndpoints.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ public Mono<ResponseView<Boolean>> removeUserFromOrg(@PathVariable String orgId,
181181
@GetMapping("/{orgId}/api-usage")
182182
public Mono<ResponseView<Long>> getOrgApiUsageCount(@PathVariable String orgId, @RequestParam(required = false) Boolean lastMonthOnly);
183183

184+
@PutMapping("/{orgId}/slug")
185+
Mono<ResponseView<Organization>> updateSlug(@PathVariable String orgId, @RequestBody String slug);
186+
184187
public record UpdateOrgCommonSettingsRequest(String key, Object value) {
185188

186189
}

server/api-service/lowcoder-server/src/test/java/org/lowcoder/api/application/ApplicationApiServiceTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.lowcoder.domain.application.model.ApplicationStatus;
2121
import org.lowcoder.domain.application.model.ApplicationType;
2222
import org.lowcoder.domain.application.service.ApplicationService;
23+
import org.lowcoder.domain.organization.model.Organization;
2324
import org.lowcoder.domain.permission.model.ResourceHolder;
2425
import org.lowcoder.domain.permission.model.ResourceRole;
2526
import org.lowcoder.sdk.constants.FieldName;
@@ -332,4 +333,24 @@ public void testAppCreateAndRetrievalByGID() {
332333
})
333334
.verifyComplete();
334335
}
336+
337+
@Test
338+
@WithMockUser
339+
public void testUpdateSlug() {
340+
// Create a dummy application
341+
Mono<String> applicationMono = createApplication("SlugTestApp", null)
342+
.map(applicationView -> applicationView.getApplicationInfoView().getApplicationId());
343+
344+
// Assume updateSlug is performed by passing applicationId and the new slug
345+
Mono<Application> updatedApplicationMono = applicationMono
346+
.flatMap(applicationId -> applicationApiService.updateSlug(applicationId, "new-slug-value"));
347+
348+
// Verify the application updates with the new slug
349+
StepVerifier.create(updatedApplicationMono)
350+
.assertNext(application -> {
351+
Assertions.assertNotNull(application.getSlug(), "Slug should not be null");
352+
Assertions.assertEquals("new-slug-value", application.getSlug(), "Slug should be updated to 'new-slug-value'");
353+
})
354+
.verifyComplete();
355+
}
335356
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package org.lowcoder.api.service;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.api.TestInstance;
7+
import org.lowcoder.api.common.mockuser.WithMockUser;
8+
import org.lowcoder.domain.organization.model.Organization;
9+
import org.lowcoder.domain.organization.service.OrganizationService;
10+
import org.lowcoder.sdk.models.HasIdAndAuditing;
11+
import org.springframework.boot.test.context.SpringBootTest;
12+
import org.springframework.test.context.ActiveProfiles;
13+
import reactor.core.publisher.Mono;
14+
import reactor.test.StepVerifier;
15+
16+
@SpringBootTest
17+
//@RunWith(SpringRunner.class)
18+
@ActiveProfiles("OrganizationApiServiceTest")
19+
@Slf4j(topic = "OrganizationApiServiceTest")
20+
21+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
22+
public class OrganizationServiceTest {
23+
24+
private OrganizationService organizationService;
25+
26+
private Mono<Organization> createOrganization(String name) {
27+
Organization organization = Organization.builder()
28+
.name(name)
29+
.build();
30+
return organizationService.create(organization, "", false);
31+
}
32+
33+
@Test
34+
@WithMockUser
35+
public void testUpdateSlug() {
36+
// Create a dummy organization
37+
Mono<String> organizationMono = createOrganization("SlugTestOrganization")
38+
.map(HasIdAndAuditing::getId);
39+
40+
// Assume updateSlug is performed by passing organizationId and the new slug
41+
Mono<Organization> updatedOrganizationMono = organizationMono
42+
.flatMap(organizationId -> organizationService.updateSlug(organizationId, "new-slug-value"));
43+
44+
// Verify the organization updates with the new slug
45+
StepVerifier.create(updatedOrganizationMono)
46+
.assertNext(organization -> {
47+
Assertions.assertNotNull(organization.getSlug(), "Slug should not be null");
48+
Assertions.assertEquals("new-slug-value", organization.getSlug(), "Slug should be updated to 'new-slug-value'");
49+
})
50+
.verifyComplete();
51+
}
52+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy