Skip to content

Commit ad91755

Browse files
author
Thomas
committed
publish API & test case.
remove sessionUserService mocking in bundle test case ( will use WithMockUser annotation in the future)
1 parent a9b10c7 commit ad91755

File tree

7 files changed

+173
-35
lines changed

7 files changed

+173
-35
lines changed

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import reactor.core.publisher.Mono;
1010

1111
import java.util.Collection;
12+
import java.util.Map;
1213
import java.util.Set;
1314

1415
public interface BundleService {
@@ -23,6 +24,8 @@ public interface BundleService {
2324
Mono<Void> deleteAllById(Collection<String> ids);
2425

2526
Mono<Boolean> exist(String id);
27+
Mono<Bundle> publish(String bundleId);
28+
Mono<Boolean> updatePublishedBundleDSL(String bundleId, Map<String, Object> bundleDSL);
2629

2730
@NonEmptyMono
2831
@SuppressWarnings("ReactiveStreamsNullableInLambdaInTransform")

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/bundle/service/BundleServiceImpl.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
import lombok.RequiredArgsConstructor;
44
import org.apache.commons.lang3.StringUtils;
5-
import org.lowcoder.domain.application.model.Application;
6-
import org.lowcoder.domain.application.model.ApplicationRequestType;
75
import org.lowcoder.domain.bundle.model.Bundle;
86
import org.lowcoder.domain.bundle.model.BundleRequestType;
97
import org.lowcoder.domain.bundle.repository.BundleRepository;
@@ -82,10 +80,24 @@ public Mono<Boolean> exist(String id) {
8280
});
8381
}
8482

83+
@Override
84+
public Mono<Bundle> publish(String bundleId) {
85+
return findById(bundleId)
86+
.flatMap(newBundle -> { // copy editingApplicationDSL to publishedApplicationDSL
87+
Map<String, Object> editingBundleDSL = newBundle.getEditingBundleDSL();
88+
return updatePublishedBundleDSL(bundleId, editingBundleDSL)
89+
.thenReturn(newBundle);
90+
});
91+
}
92+
93+
@Override
94+
public Mono<Boolean> updatePublishedBundleDSL(String bundleId, Map<String, Object> bundleDSL) {
95+
Bundle bundle = Bundle.builder().publishedBundleDSL(bundleDSL).build();
96+
return mongoUpsertHelper.updateById(bundle, bundleId);
97+
}
8598

8699
@Override
87100
@NonEmptyMono
88-
@SuppressWarnings("ReactiveStreamsNullableInLambdaInTransform")
89101
public Mono<Set<String>> getFilteredPublicBundleIds(BundleRequestType requestType, Collection<String> bundleIds, String userId, Boolean isPrivateMarketplace) {
90102
boolean isAnonymous = StringUtils.isBlank(userId);
91103
switch(requestType)
@@ -149,7 +161,7 @@ public Mono<Set<String>> getPrivateBundleIds(Collection<String> bundleIds, Strin
149161
@SuppressWarnings("ReactiveStreamsNullableInLambdaInTransform")
150162
public Mono<Set<String>> getPublicMarketplaceBundleIds(Collection<String> bundleIds, boolean isAnonymous, boolean isPrivateMarketplace) {
151163

152-
if ((isAnonymous && !isPrivateMarketplace) || !isAnonymous)
164+
if (!isAnonymous || !isPrivateMarketplace)
153165
{
154166
return repository.findByPublicToAllIsTrueAndPublicToMarketplaceIsTrueAndIdIn(bundleIds)
155167
.map(HasIdAndAuditing::getId)

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/bundle/BundleApiService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public interface BundleApiService {
2323

2424
Mono<Void> checkBundleCurrentUser(Bundle bundle, String currentOrgId);
2525
Mono<BundleInfoView> getPublishedBundle(String bundleId, BundleRequestType requestType);
26+
Mono<BundleInfoView> getEditingBundle(String bundleId);
2627

2728
Mono<Bundle> delete(@Nonnull String bundleId);
2829

@@ -32,6 +33,7 @@ public interface BundleApiService {
3233
Flux<BundleInfoView> getRecycledBundles();
3334

3435
Mono<BundleInfoView> update(Bundle bundle);
36+
Mono<BundleInfoView> publish(String bundleId);
3537

3638
Mono<Void> moveApp(String applicationId, String fromBundled, String toBundleId);
3739

@@ -41,6 +43,8 @@ public interface BundleApiService {
4143

4244
@Nonnull
4345
Mono<ResourcePermission> checkBundlePermissionWithReadableErrorMsg(String bundleId, ResourceAction action, BundleRequestType requestType);
46+
@Nonnull
47+
Mono<ResourcePermission> checkPermissionWithReadableErrorMsg(String bundleId, ResourceAction action);
4448

4549
Mono<Void> grantPermission(String bundleId, Set<String> userIds, Set<String> groupIds, ResourceRole role);
4650

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/bundle/BundleApiServiceImpl.java

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import lombok.RequiredArgsConstructor;
66
import org.apache.commons.collections4.CollectionUtils;
77
import org.apache.commons.lang3.StringUtils;
8-
import org.lowcoder.api.bundle.BundleEndpoints.CreateBundleRequest;
98
import org.lowcoder.api.application.view.ApplicationInfoView;
109
import org.lowcoder.api.application.view.ApplicationPermissionView;
10+
import org.lowcoder.api.bundle.BundleEndpoints.CreateBundleRequest;
1111
import org.lowcoder.api.bundle.view.BundleInfoView;
1212
import org.lowcoder.api.bundle.view.BundlePermissionView;
1313
import org.lowcoder.api.home.FolderApiService;
@@ -17,30 +17,28 @@
1717
import org.lowcoder.api.permission.view.PermissionItemView;
1818
import org.lowcoder.api.usermanagement.OrgDevChecker;
1919
import org.lowcoder.domain.application.model.Application;
20-
import org.lowcoder.domain.application.model.ApplicationStatus;
2120
import org.lowcoder.domain.application.model.ApplicationType;
2221
import org.lowcoder.domain.application.repository.ApplicationRepository;
2322
import org.lowcoder.domain.application.service.ApplicationServiceImpl;
24-
import org.lowcoder.domain.bundle.model.*;
23+
import org.lowcoder.domain.bundle.model.Bundle;
24+
import org.lowcoder.domain.bundle.model.BundleApplication;
25+
import org.lowcoder.domain.bundle.model.BundleRequestType;
26+
import org.lowcoder.domain.bundle.model.BundleStatus;
2527
import org.lowcoder.domain.bundle.repository.BundleRepository;
2628
import org.lowcoder.domain.bundle.service.BundleElementRelationService;
27-
import org.lowcoder.domain.bundle.service.BundleNode;
2829
import org.lowcoder.domain.bundle.service.BundleService;
29-
import org.lowcoder.domain.bundle.service.*;
3030
import org.lowcoder.domain.group.service.GroupService;
3131
import org.lowcoder.domain.organization.model.OrgMember;
3232
import org.lowcoder.domain.organization.model.Organization;
33+
import org.lowcoder.domain.organization.service.OrgMemberService;
3334
import org.lowcoder.domain.organization.service.OrganizationService;
3435
import org.lowcoder.domain.permission.model.*;
3536
import org.lowcoder.domain.permission.service.ResourcePermissionService;
36-
import org.lowcoder.domain.user.model.User;
3737
import org.lowcoder.domain.user.service.UserService;
38-
import org.lowcoder.infra.birelation.BiRelation;
3938
import org.lowcoder.infra.birelation.BiRelationBizType;
4039
import org.lowcoder.infra.birelation.BiRelationServiceImpl;
4140
import org.lowcoder.sdk.exception.BizError;
4241
import org.lowcoder.sdk.exception.BizException;
43-
import org.springframework.beans.factory.annotation.Autowired;
4442
import org.springframework.context.annotation.Lazy;
4543
import org.springframework.stereotype.Service;
4644
import reactor.core.publisher.Flux;
@@ -49,14 +47,11 @@
4947

5048
import java.util.*;
5149
import java.util.function.Function;
52-
import java.util.function.ToLongFunction;
53-
import java.util.stream.Collectors;
5450

55-
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
5651
import static org.lowcoder.domain.bundle.model.BundleStatus.NORMAL;
5752
import static org.lowcoder.domain.permission.model.ResourceAction.*;
58-
import static org.lowcoder.infra.util.MonoUtils.emptyIfNull;
5953
import static org.lowcoder.sdk.exception.BizError.*;
54+
import static org.lowcoder.sdk.util.ExceptionUtils.deferredError;
6055
import static org.lowcoder.sdk.util.ExceptionUtils.ofError;
6156

6257
@RequiredArgsConstructor
@@ -65,6 +60,7 @@ public class BundleApiServiceImpl implements BundleApiService {
6560
private final BiRelationServiceImpl biRelationService;
6661
private final BundleService bundleService;
6762
private final SessionUserService sessionUserService;
63+
private final OrgMemberService orgMemberService;
6864
private final OrgDevChecker orgDevChecker;
6965
@Lazy
7066
private final UserHomeApiService userHomeApiService;
@@ -96,8 +92,10 @@ public Mono<BundleInfoView> create(CreateBundleRequest createBundleRequest) {
9692
if (StringUtils.isBlank(bundle.getName())) {
9793
return Mono.error(new BizException(BizError.INVALID_PARAMETER, "BUNDLE_NAME_EMPTY"));
9894
}
99-
return orgDevChecker.checkCurrentOrgDev()
100-
.then(sessionUserService.getVisitorOrgMemberCache())
95+
return sessionUserService.getVisitorId()
96+
.flatMap(userId -> orgMemberService.getOrgMember(bundle.getOrganizationId(), userId))
97+
.switchIfEmpty(deferredError(NOT_AUTHORIZED, "NOT_AUTHORIZED"))
98+
.delayUntil(orgMember -> orgDevChecker.checkCurrentOrgDev())
10199
.delayUntil(orgMember -> checkBundleNameUnique(bundle.getName(), orgMember.getUserId()))
102100
.delayUntil(orgMember -> {
103101
String folderId = createBundleRequest.folderId();
@@ -251,6 +249,29 @@ public Mono<BundleInfoView> update(Bundle bundle) {
251249
.flatMap(f -> buildBundleInfoView(f, true, true, null));
252250
}
253251

252+
@Override
253+
public Mono<BundleInfoView> publish(String bundleId) {
254+
return checkBundleStatus(bundleId, BundleStatus.NORMAL)
255+
.then(sessionUserService.getVisitorId())
256+
.flatMap(userId -> resourcePermissionService.checkAndReturnMaxPermission(userId,
257+
bundleId, PUBLISH_BUNDLES))
258+
.flatMap(permission -> bundleService.publish(bundleId)
259+
.map(bundleUpdated -> BundleInfoView.builder()
260+
.bundleId(bundleUpdated.getId())
261+
.name(bundleUpdated.getName())
262+
.editingBundleDSL(bundleUpdated.getEditingBundleDSL())
263+
.publishedBundleDSL(bundleUpdated.getPublishedBundleDSL())
264+
.title(bundleUpdated.getTitle())
265+
.image(bundleUpdated.getImage())
266+
.createAt(bundleUpdated.getCreatedAt().toEpochMilli())
267+
.category(bundleUpdated.getCategory())
268+
.agencyProfile(bundleUpdated.getAgencyProfile())
269+
.publicToAll(bundleUpdated.getPublicToAll())
270+
.publicToMarketplace(bundleUpdated.getPublicToMarketplace())
271+
.createBy(bundleUpdated.getCreatedBy())
272+
.build()));
273+
}
274+
254275
/**
255276
* @param applicationId app id to move
256277
* @param fromBundleId bundle id to remove app from
@@ -381,6 +402,32 @@ public Mono<BundleInfoView> getPublishedBundle(String bundleId, BundleRequestTyp
381402
});
382403
}
383404

405+
@Override
406+
public Mono<BundleInfoView> getEditingBundle(String bundleId) {
407+
return checkPermissionWithReadableErrorMsg(bundleId, READ_BUNDLES)
408+
.zipWhen(permission -> bundleService.findById(bundleId)
409+
.delayUntil(bundle -> checkBundleStatus(bundle, BundleStatus.NORMAL)))
410+
.map(tuple -> {
411+
Bundle bundle = tuple.getT2();
412+
return BundleInfoView.builder()
413+
.bundleId(bundle.getId())
414+
.name(bundle.getName())
415+
.title(bundle.getTitle())
416+
.category(bundle.getCategory())
417+
.description(bundle.getDescription())
418+
.image(bundle.getImage())
419+
.editingBundleDSL(bundle.getEditingBundleDSL())
420+
// .publishedBundleDSL(bundle.getPublishedBundleDSL())
421+
.publicToMarketplace(bundle.getPublicToMarketplace())
422+
.publicToAll(bundle.getPublicToAll())
423+
.agencyProfile(bundle.getAgencyProfile())
424+
.createAt(bundle.getCreatedAt().toEpochMilli())
425+
.createTime(bundle.getCreatedAt())
426+
.createBy(bundle.getCreatedBy())
427+
.build();
428+
});
429+
}
430+
384431
private Mono<Void> checkBundleViewRequest(Bundle bundle, BundleRequestType expected) {
385432

386433
// TODO: check bundle.isPublicToAll() from v2.4.0
@@ -402,6 +449,28 @@ private Mono<Void> checkBundleViewRequest(Bundle bundle, BundleRequestType expec
402449
return Mono.error(new BizException(BizError.UNSUPPORTED_OPERATION, "BAD_REQUEST"));
403450
}
404451

452+
@Override
453+
@Nonnull
454+
public Mono<ResourcePermission> checkPermissionWithReadableErrorMsg(String bundleId, ResourceAction action) {
455+
return sessionUserService.getVisitorId()
456+
.flatMap(visitorId -> resourcePermissionService.checkUserPermissionStatusOnResource(visitorId, bundleId, action))
457+
.flatMap(permissionStatus -> {
458+
if (!permissionStatus.hasPermission()) {
459+
if (permissionStatus.failByAnonymousUser()) {
460+
return ofError(USER_NOT_SIGNED_IN, "USER_NOT_SIGNED_IN");
461+
}
462+
463+
if (permissionStatus.failByNotInOrg()) {
464+
return ofError(NO_PERMISSION_TO_REQUEST_APP, "INSUFFICIENT_PERMISSION");
465+
}
466+
467+
String messageKey = action == EDIT_APPLICATIONS ? "NO_PERMISSION_TO_EDIT" : "NO_PERMISSION_TO_VIEW";
468+
return ofError(NO_PERMISSION_TO_REQUEST_APP, messageKey);
469+
}
470+
return Mono.just(permissionStatus.getPermission());
471+
});
472+
}
473+
405474
@Override
406475
@Nonnull
407476
public Mono<ResourcePermission> checkBundlePermissionWithReadableErrorMsg(String bundleId, ResourceAction action, BundleRequestType requestType) {

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/bundle/BundleController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ public Mono<ResponseView<BundleInfoView>> update(@RequestBody Bundle bundle) {
6464
.map(tuple2 -> ResponseView.success(tuple2.getT2()));
6565
}
6666

67+
@Override
68+
public Mono<ResponseView<BundleInfoView>> publish(@PathVariable String bundleId) {
69+
return bundleApiService.publish(bundleId).map(ResponseView::success);
70+
}
71+
6772
@Override
6873
public Mono<ResponseView<Boolean>> recycle(@PathVariable String bundleId) {
6974
return bundleApiService.recycle(bundleId)

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/bundle/BundleEndpoints.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,15 @@ public Mono<ResponseView<Boolean>> setBundlePublicToMarketplace(@PathVariable St
253253
@PutMapping("/{bundleId}/agency-profile")
254254
public Mono<ResponseView<Boolean>> setBundleAsAgencyProfile(@PathVariable String bundleId,
255255
@RequestBody BundleEndpoints.BundleAsAgencyProfileRequest request);
256+
257+
@Operation(
258+
tags = TAG_BUNDLE_MANAGEMENT,
259+
operationId = "publicBundle",
260+
summary = "Publish Bundle for users",
261+
description = "Set a Lowcoder Bundle identified by its ID as available to all selected Users or User-Groups. This is similar to the classic deployment. The Lowcoder Bundle gets published in production mode."
262+
)
263+
@PostMapping("/{bundleId}/publish")
264+
public Mono<ResponseView<BundleInfoView>> publish(@PathVariable String bundleId);
256265

257266
public record BundlePublicToAllRequest(Boolean publicToAll) {
258267
@Override

0 commit comments

Comments
 (0)