Skip to content

Add sharing details to events APPLICATION_SHARING_CHANGE #1545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.lowcoder.infra.event;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
Expand Down Expand Up @@ -57,7 +58,16 @@ public void populateDetails(ContextView contextView) {
try {
f.setAccessible(Boolean.TRUE);
value = f.get(this);
details.put(f.getName(), value);
JsonInclude jsonInclude = f.getAnnotation(JsonInclude.class);
if (jsonInclude != null && jsonInclude.value() == JsonInclude.Include.NON_NULL) {
// Include only if value is not null
if (value != null) {
details.put(f.getName(), value);
}
} else {
// Include regardless of value
details.put(f.getName(), value);
}
} catch (Exception e) {
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.lowcoder.infra.event;


import com.fasterxml.jackson.annotation.JsonInclude;
import jakarta.annotation.Nullable;
import lombok.Getter;
import lombok.experimental.SuperBuilder;
Expand All @@ -18,20 +19,33 @@ public class ApplicationCommonEvent extends AbstractEvent {
private final String applicationDescription;
private final EventType type;
@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String folderId;
@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String folderName;
@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String oldFolderId;
@Nullable
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String oldFolderName;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String permissionId;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String role;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final Set<String> userIds;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final Set<String> groupIds;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String shareType;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String tag;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final String commitMessage;
@JsonInclude(JsonInclude.Include.NON_NULL)
private final Object sharingDetails;

@Override
public EventType getEventType() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.lowcoder.infra.event;


import jakarta.annotation.Nullable;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

@Getter
@SuperBuilder
public class BundleCommonEvent extends AbstractEvent {

private final String bundleId;
private final String bundleGid;
private final String bundleName;
private final String bundleCategory;
private final String bundleDescription;
private final EventType type;
@Nullable
private final String folderId;
@Nullable
private final String folderName;
@Nullable
private final String oldFolderId;
@Nullable
private final String oldFolderName;

@Override
public EventType getEventType() {
return type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ public Mono<ResponseView<Boolean>> setApplicationPublicToAll(@PathVariable Strin
@RequestBody ApplicationPublicToAllRequest request) {
return gidService.convertApplicationIdToObjectId(applicationId).flatMap(appId ->
applicationApiService.setApplicationPublicToAll(appId, request.publicToAll())
.delayUntil(__ -> businessEventPublisher.publishApplicationSharingEvent(applicationId, "PublicToAll"))
.delayUntil(__ -> applicationApiService.getApplicationPermissions(appId)
.flatMap(applicationPermissionView -> businessEventPublisher.publishApplicationSharingEvent(applicationId, "PublicToAll", applicationPermissionView)))
.map(ResponseView::success));
}

Expand All @@ -279,7 +280,8 @@ public Mono<ResponseView<Boolean>> setApplicationPublicToMarketplace(@PathVariab
@RequestBody ApplicationPublicToMarketplaceRequest request) {
return gidService.convertApplicationIdToObjectId(applicationId).flatMap(appId ->
applicationApiService.setApplicationPublicToMarketplace(appId, request)
.delayUntil(__ -> businessEventPublisher.publishApplicationSharingEvent(applicationId, "PublicToMarketplace"))
.delayUntil(__ -> applicationApiService.getApplicationPermissions(appId)
.flatMap(applicationPermissionView -> businessEventPublisher.publishApplicationSharingEvent(applicationId, "PublicToMarketplace", applicationPermissionView)))
.map(ResponseView::success));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.lowcoder.api.bundle;

import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.lowcoder.api.bundle.view.BundleInfoView;
import org.lowcoder.api.bundle.view.BundlePermissionView;
import org.lowcoder.api.bundle.view.MarketplaceBundleInfoView;
Expand All @@ -20,12 +19,12 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

import static org.lowcoder.api.util.Pagination.fluxToPageResponseView;
import static org.lowcoder.plugin.api.event.LowcoderEvent.EventType.*;
import static org.lowcoder.sdk.exception.BizError.INVALID_PARAMETER;
import static org.lowcoder.sdk.util.ExceptionUtils.ofError;

Expand All @@ -43,16 +42,31 @@ public class BundleController implements BundleEndpoints
@Override
public Mono<ResponseView<BundleInfoView>> create(@RequestBody CreateBundleRequest bundle) {
return bundleApiService.create(bundle)
//TODO [thomasr]: add new method to BusinessEventPublisher(jar file)
// .delayUntil(f -> businessEventPublisher.publishBundleCommonEvent(f.getBundleId(), f.getName(), EventType.BUNDLE_CREATE))
.delayUntil(f -> businessEventPublisher.publishBundleCommonEvent(f, BUNDLE_CREATE))
.map(ResponseView::success);
}

@Override
public Mono<ResponseView<Void>> delete(@PathVariable("id") String bundleId) {
return gidService.convertBundleIdToObjectId(bundleId).flatMap(objectId ->
bundleApiService.delete(objectId)
// .delayUntil(f -> businessEventPublisher.publishBundleCommonEvent(f.getId(), f.getName(), EventType.BUNDLE_DELETE))
.delayUntil(f -> businessEventPublisher.publishBundleCommonEvent(
BundleInfoView.builder()
.bundleGid(f.getGid())
.editingBundleDSL(f.getEditingBundleDSL())
.image(f.getImage())
.title(f.getTitle())
.description(f.getDescription())
.name(f.getName())
.publicToMarketplace(f.isPublicToMarketplace())
.publicToAll(f.isPublicToAll())
.agencyProfile(f.agencyProfile())
.createTime(f.getCreatedAt())
.createBy(f.getCreatedBy())
.createAt(f.getCreatedAt().toEpochMilli())
.publishedBundleDSL(f.getPublishedBundleDSL())
.category(f.getCategory())
.build(), BUNDLE_DELETE))
.then(Mono.fromSupplier(() -> ResponseView.success(null))));
}

Expand All @@ -63,11 +77,10 @@ public Mono<ResponseView<Void>> delete(@PathVariable("id") String bundleId) {
public Mono<ResponseView<BundleInfoView>> update(@RequestBody Bundle bundle) {
return bundleService.findById(bundle.getId())
.zipWhen(__ -> bundleApiService.update(bundle))
// .delayUntil(tuple2 -> {
// Bundle old = tuple2.getT1();
// return businessEventPublisher.publishBundleCommonEvent(bundle.getId(), old.getName() + " => " + bundle.getName(),
// EventType.BUNDLE_UPDATE);
// })
.delayUntil(tuple2 -> {
Bundle old = tuple2.getT1();
return businessEventPublisher.publishBundleCommonEvent(tuple2.getT2(), BUNDLE_UPDATE);
})
.map(tuple2 -> ResponseView.success(tuple2.getT2()));
}

Expand All @@ -81,15 +94,15 @@ public Mono<ResponseView<BundleInfoView>> publish(@PathVariable String bundleId)
public Mono<ResponseView<Boolean>> recycle(@PathVariable String bundleId) {
return gidService.convertBundleIdToObjectId(bundleId).flatMap(objectId ->
bundleApiService.recycle(objectId)
// .delayUntil(__ -> businessEventPublisher.publishBundleCommonEvent(bundleId, null, BUNDLE_RECYCLED))
.delayUntil(__ -> businessEventPublisher.publishBundleCommonEvent(bundleId, null, null, BUNDLE_RECYCLED))
.map(ResponseView::success));
}

@Override
public Mono<ResponseView<Boolean>> restore(@PathVariable String bundleId) {
return gidService.convertBundleIdToObjectId(bundleId).flatMap(objectId ->
bundleApiService.restore(objectId)
// .delayUntil(__ -> businessEventPublisher.publishBundleCommonEvent(bundleId, null, BUNDLE_RESTORE))
.delayUntil(__ -> businessEventPublisher.publishBundleCommonEvent(bundleId, null, null, BUNDLE_RESTORE))
.map(ResponseView::success));
}

Expand Down Expand Up @@ -120,8 +133,7 @@ public Mono<ResponseView<Void>> moveApp(@PathVariable("id") String applicationId
gidService.convertBundleIdToObjectId(toBundleId).flatMap(objectIdTo ->
gidService.convertApplicationIdToObjectId(applicationId).flatMap(appId ->
bundleApiService.moveApp(appId, objectIdFrom, objectIdTo)
//TODO: Event Type not defined yet
// .then(businessEventPublisher.publishBundleCommonEvent(applicationLikeId, targetBundleId, BUNDLE_MOVE))
.then(businessEventPublisher.publishBundleCommonEvent(applicationId, fromBundleId, toBundleId, APPLICATION_MOVE))
.then(Mono.fromSupplier(() -> ResponseView.success(null))))));
}

Expand Down Expand Up @@ -188,23 +200,23 @@ public Mono<ResponseView<BundlePermissionView>> getBundlePermissions(@PathVariab
public Mono<ResponseView<BundleInfoView>> getPublishedBundle(@PathVariable String bundleId) {
return gidService.convertBundleIdToObjectId(bundleId).flatMap(objectId ->
bundleApiService.getPublishedBundle(objectId, BundleRequestType.PUBLIC_TO_ALL)
// .delayUntil(bundleView -> businessEventPublisher.publishBundleCommonEvent(bundleView, BUNDLE_VIEW))
.delayUntil(bundleView -> businessEventPublisher.publishBundleCommonEvent(bundleView, BUNDLE_VIEW))
.map(ResponseView::success));
}

@Override
public Mono<ResponseView<BundleInfoView>> getPublishedMarketPlaceBundle(@PathVariable String bundleId) {
return gidService.convertBundleIdToObjectId(bundleId).flatMap(objectId ->
bundleApiService.getPublishedBundle(objectId, BundleRequestType.PUBLIC_TO_MARKETPLACE)
// .delayUntil(bundleView -> businessEventPublisher.publishBundleCommonEvent(bundleView, BUNDLE_VIEW))
.delayUntil(bundleView -> businessEventPublisher.publishBundleCommonEvent(bundleView, BUNDLE_VIEW))
.map(ResponseView::success));
}

@Override
public Mono<ResponseView<BundleInfoView>> getAgencyProfileBundle(@PathVariable String bundleId) {
return gidService.convertBundleIdToObjectId(bundleId).flatMap(objectId ->
bundleApiService.getPublishedBundle(objectId, BundleRequestType.AGENCY_PROFILE)
// .delayUntil(bundleView -> businessEventPublisher.publishBundleCommonEvent(bundleView, BUNDLE_VIEW))
.delayUntil(bundleView -> businessEventPublisher.publishBundleCommonEvent(bundleView, BUNDLE_VIEW))
.map(ResponseView::success));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class BundleInfoView {
private final Long createAt;
private final String createBy;
private final String folderId;
private final String folderIdFrom;
private final Boolean publicToAll;
private final Boolean publicToMarketplace;
private final Boolean agencyProfile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.lowcoder.api.application.view.ApplicationInfoView;
import org.lowcoder.api.application.view.ApplicationPermissionView;
import org.lowcoder.api.application.view.ApplicationPublishRequest;
import org.lowcoder.api.application.view.ApplicationView;
import org.lowcoder.api.bundle.view.BundleInfoView;
import org.lowcoder.api.home.SessionUserService;
import org.lowcoder.api.usermanagement.view.AddMemberRequest;
import org.lowcoder.api.usermanagement.view.UpdateRoleRequest;
Expand Down Expand Up @@ -243,7 +245,7 @@ public Mono<Void> publishApplicationPermissionEvent(String applicationId, Set<St
}


public Mono<Void> publishApplicationSharingEvent(String applicationId, String shareType) {
public Mono<Void> publishApplicationSharingEvent(String applicationId, String shareType, ApplicationPermissionView applicationPermissionView) {
return sessionUserService.isAnonymousUser()
.flatMap(anonymous -> {
if (anonymous) {
Expand All @@ -270,6 +272,7 @@ public Mono<Void> publishApplicationSharingEvent(String applicationId, String sh
.applicationCategory(category)
.applicationDescription(description)
.type(EventType.APPLICATION_SHARING_CHANGE)
.sharingDetails(applicationPermissionView)
.shareType(shareType)
.isAnonymous(anonymous)
.sessionHash(Hashing.sha512().hashString(token, StandardCharsets.UTF_8).toString())
Expand Down Expand Up @@ -382,6 +385,76 @@ public Mono<Void> publishApplicationVersionChangeEvent(String applicationId, Str
}


public Mono<Void> publishBundleCommonEvent(BundleInfoView bundleInfoView, EventType eventType) {
return sessionUserService.isAnonymousUser()
.flatMap(anonymous -> {
if (anonymous) {
return Mono.empty();
}
return sessionUserService.getVisitorOrgMemberCache()
.zipWith(Mono.defer(() -> {
String folderId = bundleInfoView.getFolderId();
if (StringUtils.isBlank(folderId)) {
return Mono.just(Optional.<Folder> empty());
}
return folderService.findById(folderId)
.map(Optional::of)
.onErrorReturn(Optional.empty());
}))
.zipWith(Mono.defer(() -> {
String folderId = bundleInfoView.getFolderIdFrom();
if (StringUtils.isBlank(folderId)) {
return Mono.just(Optional.<Folder> empty());
}
return folderService.findById(folderId)
.map(Optional::of)
.onErrorReturn(Optional.empty());
}), TupleUtils::merge)
.zipWith(sessionUserService.getVisitorToken())
.flatMap(tuple -> {
OrgMember orgMember = tuple.getT1().getT1();
Optional<Folder> optional = tuple.getT1().getT2();
Optional<Folder> optionalFrom = tuple.getT1().getT3();
String token = tuple.getT2();
ApplicationCommonEvent event = ApplicationCommonEvent.builder()
.orgId(orgMember.getOrgId())
.userId(orgMember.getUserId())
.applicationId(bundleInfoView.getBundleId())
.applicationGid(bundleInfoView.getBundleGid())
.applicationName(bundleInfoView.getName())
.type(eventType)
.folderId(optional.map(Folder::getId).orElse(null))
.folderName(optional.map(Folder::getName).orElse(null))
.oldFolderId(optionalFrom.map(Folder::getId).orElse(null))
.oldFolderName(optionalFrom.map(Folder::getName).orElse(null))
.isAnonymous(anonymous)
.sessionHash(Hashing.sha512().hashString(token, StandardCharsets.UTF_8).toString())
.build();
return Mono.deferContextual(contextView -> {
event.populateDetails(contextView);
applicationEventPublisher.publishEvent(event);
return Mono.empty();
}).then();
})
.then()
.onErrorResume(throwable -> {
log.error("publishBundleCommonEvent error. {}, {}", bundleInfoView, eventType, throwable);
return Mono.empty();
});
});
}

public Mono<Void> publishBundleCommonEvent(String bundleId, @Nullable String folderIdFrom, @Nullable String folderIdTo, EventType eventType) {
return applicationService.findByIdWithoutDsl(bundleId)
.map(application -> BundleInfoView.builder()
.bundleId(bundleId)
.name(application.getName())
.folderId(folderIdTo)
.folderIdFrom(folderIdFrom)
.build())
.flatMap(bundleInfoView -> publishBundleCommonEvent(bundleInfoView, eventType));
}

public Mono<Void> publishUserLoginEvent(String source) {
return sessionUserService.getVisitorOrgMember().zipWith(sessionUserService.getVisitorToken())
.delayUntil(tuple -> {
Expand Down
Loading