Skip to content

Commit 570d184

Browse files
committed
Add feature to set app as agency profile
1 parent 697c308 commit 570d184

File tree

9 files changed

+148
-4
lines changed

9 files changed

+148
-4
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public class Application extends HasIdAndAuditing {
4141
private final Boolean publicToAll;
4242
private final Boolean publicToMarketplace;
4343

44+
private final Boolean agencyProfile;
45+
4446
private Map<String, Object> editingApplicationDSL;
4547

4648
@Transient
@@ -78,6 +80,7 @@ public Application(@JsonProperty("orgId") String organizationId,
7880
@JsonProperty("publishedApplicationDSL") Map<String, Object> publishedApplicationDSL,
7981
@JsonProperty("publicToAll") Boolean publicToAll,
8082
@JsonProperty("publicToMarketplace") Boolean publicToMarketplace,
83+
@JsonProperty("agencyProfile") Boolean agencyProfile,
8184
@JsonProperty("editingApplicationDSL") Map<String, Object> editingApplicationDSL) {
8285
this.organizationId = organizationId;
8386
this.name = name;
@@ -86,6 +89,7 @@ public Application(@JsonProperty("orgId") String organizationId,
8689
this.publishedApplicationDSL = publishedApplicationDSL;
8790
this.publicToAll = publicToAll;
8891
this.publicToMarketplace = publicToMarketplace;
92+
this.agencyProfile = agencyProfile;
8993
this.editingApplicationDSL = editingApplicationDSL;
9094
}
9195

@@ -113,6 +117,10 @@ public boolean isPublicToMarketplace() {
113117
return BooleanUtils.toBooleanDefaultIfNull(publicToMarketplace, false);
114118
}
115119

120+
public boolean agencyProfile() {
121+
return BooleanUtils.toBooleanDefaultIfNull(agencyProfile, false);
122+
}
123+
116124
public ApplicationQuery getQueryByViewModeAndQueryId(boolean isViewMode, String queryId) {
117125
return (isViewMode ? getLiveQueries() : getEditingQueries())
118126
.stream()

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ public interface ApplicationRepository extends ReactiveMongoRepository<Applicati
3434

3535
Flux<Application> findByIdIn(List<String> ids);
3636

37-
@Query(fields = "{_id : 1}")
38-
Flux<Application> findByPublicToAllIsTrueAndPublicToMarketplaceIsAndIdIn(Boolean publicToMarketplace, Collection<String> ids);
37+
@Query(value = "{$and:[{'publicToAll':true},{'$or':[{'publicToMarketplace':?0},{'agencyProfile':?1}]}, {'_id': { $in: ?2}}]}", fields = "{_id : 1}")
38+
Flux<Application> findByPublicToAllIsTrueAndPublicToMarketplaceIsOrAgencyProfileIsAndIdIn
39+
(Boolean publicToMarketplace, Boolean agencyProfile, Collection<String> ids);
3940

4041
Flux<Application> findByPublicToAllIsTrueAndPublicToMarketplaceIsTrue();
4142

43+
Flux<Application> findByPublicToAllIsTrueAndAgencyProfileIsTrue();
44+
4245
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ public Flux<Application> findAllMarketplaceApps() {
107107
return repository.findByPublicToAllIsTrueAndPublicToMarketplaceIsTrue();
108108
}
109109

110+
public Flux<Application> findAllAgencyProfileApps() {
111+
return repository.findByPublicToAllIsTrueAndAgencyProfileIsTrue();
112+
}
113+
110114
public Mono<Long> countByOrganizationId(String orgId, ApplicationStatus applicationStatus) {
111115
return repository.countByOrganizationIdAndApplicationStatus(orgId, applicationStatus);
112116
}
@@ -158,10 +162,17 @@ public Mono<Boolean> setApplicationPublicToMarketplace(String applicationId, boo
158162
return mongoUpsertHelper.updateById(application, applicationId);
159163
}
160164

165+
public Mono<Boolean> setApplicationAsAgencyProfile(String applicationId, boolean agencyProfile) {
166+
Application application = Application.builder()
167+
.agencyProfile(agencyProfile)
168+
.build();
169+
return mongoUpsertHelper.updateById(application, applicationId);
170+
}
171+
161172
@NonEmptyMono
162173
@SuppressWarnings("ReactiveStreamsNullableInLambdaInTransform")
163174
public Mono<Set<String>> getPublicApplicationIds(Collection<String> applicationIds, Boolean isAnonymous) {
164-
return repository.findByPublicToAllIsTrueAndPublicToMarketplaceIsAndIdIn(!isAnonymous, applicationIds)
175+
return repository.findByPublicToAllIsTrueAndPublicToMarketplaceIsOrAgencyProfileIsAndIdIn(!isAnonymous, !isAnonymous, applicationIds)
165176
.map(HasIdAndAuditing::getId)
166177
.collect(Collectors.toSet());
167178

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/permission/model/ResourceAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public enum ResourceAction {
2525

2626
SET_APPLICATIONS_PUBLIC(ResourceRole.EDITOR, ResourceType.APPLICATION),
2727
SET_APPLICATIONS_PUBLIC_TO_MARKETPLACE(ResourceRole.EDITOR, ResourceType.APPLICATION),
28+
SET_APPLICATIONS_AS_AGENCY_PROFILE(ResourceRole.EDITOR, ResourceType.APPLICATION),
2829

2930
// datasource action
3031
MANAGE_DATASOURCES(ResourceRole.OWNER, ResourceType.DATASOURCE),

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public Mono<ApplicationView> create(CreateApplicationRequest createApplicationRe
141141
createApplicationRequest.applicationType(),
142142
NORMAL,
143143
createApplicationRequest.publishedApplicationDSL(),
144-
false, false, createApplicationRequest.editingApplicationDSL());
144+
false, false, false, createApplicationRequest.editingApplicationDSL());
145145

146146
if (StringUtils.isBlank(application.getOrganizationId())) {
147147
return deferredError(INVALID_PARAMETER, "ORG_ID_EMPTY");
@@ -506,6 +506,12 @@ public Mono<Boolean> setApplicationPublicToMarketplace(String applicationId, boo
506506
.then(applicationService.setApplicationPublicToMarketplace(applicationId, publicToMarketplace));
507507
}
508508

509+
public Mono<Boolean> setApplicationAsAgencyProfile(String applicationId, boolean agencyProfile) {
510+
return checkCurrentUserApplicationPermission(applicationId, ResourceAction.SET_APPLICATIONS_AS_AGENCY_PROFILE)
511+
.then(checkApplicationStatus(applicationId, NORMAL))
512+
.then(applicationService.setApplicationAsAgencyProfile(applicationId, agencyProfile));
513+
}
514+
509515
private Map<String, Object> sanitizeDsl(Map<String, Object> applicationDsl) {
510516
if (applicationDsl.get("queries") instanceof List<?> queries) {
511517
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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ public Mono<ResponseView<ApplicationView>> getPublishedMarketPlaceApplication(@P
105105
.map(ResponseView::success);
106106
}
107107

108+
@Override
109+
public Mono<ResponseView<ApplicationView>> getAgencyProfileApplication(@PathVariable String applicationId) {
110+
return applicationApiService.getPublishedApplication(applicationId)
111+
.delayUntil(applicationView -> applicationApiService.updateUserApplicationLastViewTime(applicationId))
112+
.delayUntil(applicationView -> businessEventPublisher.publishApplicationCommonEvent(applicationView, VIEW))
113+
.map(ResponseView::success);
114+
}
115+
108116
@Override
109117
public Mono<ResponseView<ApplicationView>> update(@PathVariable String applicationId,
110118
@RequestBody Application newApplication) {
@@ -144,6 +152,14 @@ public Mono<ResponseView<List<MarketplaceApplicationInfoView>>> getMarketplaceAp
144152
.map(ResponseView::success);
145153
}
146154

155+
@Override
156+
public Mono<ResponseView<List<MarketplaceApplicationInfoView>>> getAgencyProfileApplications(@RequestParam(required = false) Integer applicationType) {
157+
ApplicationType applicationTypeEnum = applicationType == null ? null : ApplicationType.fromValue(applicationType);
158+
return userHomeApiService.getAllMarketplaceApplications(applicationTypeEnum)
159+
.collectList()
160+
.map(ResponseView::success);
161+
}
162+
147163
@Override
148164
public Mono<ResponseView<Boolean>> updatePermission(@PathVariable String applicationId,
149165
@PathVariable String permissionId,
@@ -201,4 +217,13 @@ public Mono<ResponseView<Boolean>> setApplicationPublicToMarketplace(@PathVariab
201217
return applicationApiService.setApplicationPublicToMarketplace(applicationId, request.publicToMarketplace())
202218
.map(ResponseView::success);
203219
}
220+
221+
@Override
222+
public Mono<ResponseView<Boolean>> setApplicationAsAgencyProfile(@PathVariable String applicationId,
223+
@RequestBody ApplicationAsAgencyProfileRequest request) {
224+
return applicationApiService.setApplicationAsAgencyProfile(applicationId, request.agencyProfile())
225+
.map(ResponseView::success);
226+
}
227+
228+
204229
}

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ public interface ApplicationEndpoints
120120
@GetMapping("/{applicationId}/view_marketplace")
121121
public Mono<ResponseView<ApplicationView>> getPublishedMarketPlaceApplication(@PathVariable String applicationId);
122122

123+
@Operation(
124+
tags = TAG_APPLICATION_MANAGEMENT,
125+
operationId = "getAgencyProfileApplicationDataInViewMode",
126+
summary = "Get Agency profile Application data in view mode",
127+
description = "Retrieve the DSL data of a Lowcoder Application in view-mode by its ID marked as agency profile."
128+
)
129+
@GetMapping("/{applicationId}/view_agency")
130+
public Mono<ResponseView<ApplicationView>> getAgencyProfileApplication(@PathVariable String applicationId);
131+
123132
@Operation(
124133
tags = TAG_APPLICATION_MANAGEMENT,
125134
operationId = "updateApplication",
@@ -168,6 +177,15 @@ public Mono<ResponseView<List<ApplicationInfoView>>> getApplications(@RequestPar
168177
@GetMapping("/marketplace-apps")
169178
public Mono<ResponseView<List<MarketplaceApplicationInfoView>>> getMarketplaceApplications(@RequestParam(required = false) Integer applicationType);
170179

180+
@Operation(
181+
tags = TAG_APPLICATION_MANAGEMENT,
182+
operationId = "listAgencyProfileApplications",
183+
summary = "List agency profile Applications",
184+
description = "Retrieve a list of Lowcoder Applications that are set as agency profiles"
185+
)
186+
@GetMapping("/agency-profiles")
187+
public Mono<ResponseView<List<MarketplaceApplicationInfoView>>> getAgencyProfileApplications(@RequestParam(required = false) Integer applicationType);
188+
171189
@Operation(
172190
tags = TAG_APPLICATION_PERMISSIONS,
173191
operationId = "updateApplicationPermissions",
@@ -231,6 +249,16 @@ public Mono<ResponseView<Boolean>> setApplicationPublicToAll(@PathVariable Strin
231249
public Mono<ResponseView<Boolean>> setApplicationPublicToMarketplace(@PathVariable String applicationId,
232250
@RequestBody ApplicationPublicToMarketplaceRequest request);
233251

252+
@Operation(
253+
tags = TAG_APPLICATION_MANAGEMENT,
254+
operationId = "setApplicationAsAgencyProfile",
255+
summary = "Set Application as agency profile",
256+
description = "Set a Lowcoder Application identified by its ID as as agency profile but to only logged in users."
257+
)
258+
@PutMapping("/{applicationId}/agency-profile")
259+
public Mono<ResponseView<Boolean>> setApplicationAsAgencyProfile(@PathVariable String applicationId,
260+
@RequestBody ApplicationAsAgencyProfileRequest request);
261+
234262

235263
public record BatchAddPermissionRequest(String role, Set<String> userIds, Set<String> groupIds) {
236264
}
@@ -249,6 +277,13 @@ public Boolean publicToMarketplace() {
249277
}
250278
}
251279

280+
public record ApplicationAsAgencyProfileRequest(Boolean agencyProfile) {
281+
@Override
282+
public Boolean agencyProfile() {
283+
return BooleanUtils.isTrue(agencyProfile);
284+
}
285+
}
286+
252287
public record UpdatePermissionRequest(String role) {
253288
}
254289

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/home/UserHomeApiService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,6 @@ Flux<ApplicationInfoView> getAllAuthorisedApplications4CurrentOrgMember(@Nullabl
2525
@Nullable ApplicationStatus applicationStatus, boolean withContainerSize);
2626

2727
public Flux<MarketplaceApplicationInfoView> getAllMarketplaceApplications(@Nullable ApplicationType applicationType);
28+
29+
public Flux<MarketplaceApplicationInfoView> getAllAgencyProfileApplications(@Nullable ApplicationType applicationType);
2830
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/home/UserHomeApiServiceImpl.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,59 @@ public Flux<MarketplaceApplicationInfoView> getAllMarketplaceApplications(@Nulla
310310
});
311311
}
312312

313+
@Override
314+
public Flux<MarketplaceApplicationInfoView> getAllAgencyProfileApplications(@Nullable ApplicationType applicationType) {
315+
316+
return sessionUserService.getVisitorOrgMemberCache()
317+
.flatMapMany(orgMember -> {
318+
// application flux
319+
Flux<Application> applicationFlux = Flux.defer(() -> applicationService.findAllAgencyProfileApps())
320+
.filter(application -> isNull(applicationType) || application.getApplicationType() == applicationType.getValue())
321+
.cache();
322+
323+
// user map
324+
Mono<Map<String, User>> userMapMono = applicationFlux
325+
.flatMap(application -> emptyIfNull(application.getCreatedBy()))
326+
.collectList()
327+
.flatMap(creatorIds -> userService.getByIds(creatorIds))
328+
.cache();
329+
330+
// org map
331+
Mono<Map<String, Organization>> orgMapMono = applicationFlux
332+
.flatMap(application -> emptyIfNull(application.getOrganizationId()))
333+
.collectList()
334+
.flatMap(orgIds -> organizationService.getByIds(orgIds)
335+
.collectList()
336+
.map(it -> it.stream().collect(Collectors.toMap(Organization::getId, Function.identity())))
337+
)
338+
.cache();
339+
340+
341+
return applicationFlux
342+
.flatMap(application -> Mono.zip(Mono.just(application), userMapMono, orgMapMono))
343+
.map(tuple -> {
344+
// build view
345+
Application application = tuple.getT1();
346+
Map<String, User> userMap = tuple.getT2();
347+
Map<String, Organization> orgMap = tuple.getT3();
348+
return MarketplaceApplicationInfoView.builder()
349+
.applicationId(application.getId())
350+
.name(application.getName())
351+
.applicationType(application.getApplicationType())
352+
.applicationStatus(application.getApplicationStatus())
353+
.orgId(application.getOrganizationId())
354+
.orgName(orgMap.get(application.getOrganizationId()).getName())
355+
.creatorEmail(Optional.ofNullable(userMap.get(application.getCreatedBy()))
356+
.map(User::getName)
357+
.orElse(""))
358+
.createAt(application.getCreatedAt().toEpochMilli())
359+
.createBy(application.getCreatedBy())
360+
.build();
361+
});
362+
363+
});
364+
}
365+
313366
private ApplicationInfoView buildView(Application application, ResourceRole maxRole, Map<String, User> userMap, @Nullable Instant lastViewTime,
314367
boolean withContainerSize) {
315368
ApplicationInfoViewBuilder applicationInfoViewBuilder = ApplicationInfoView.builder()

0 commit comments

Comments
 (0)