Skip to content

Commit b09f2e0

Browse files
authored
Merge pull request lowcoder-org#154 from lvhuichao/develop
1. remove user in enterprise mode
2 parents e6785ce + a8d8029 commit b09f2e0

File tree

13 files changed

+79
-68
lines changed

13 files changed

+79
-68
lines changed

server/openblocks-domain/src/main/java/com/openblocks/domain/user/model/Connection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class Connection {
2929
private static final long serialVersionUID = -9218373922209100577L;
3030

3131
@NotEmpty
32-
private final String source;
32+
private String source;
3333

3434
@NotEmpty
3535
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)

server/openblocks-domain/src/main/java/com/openblocks/domain/user/model/User.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.util.Set;
99
import java.util.function.Supplier;
1010

11+
import org.apache.commons.collections4.SetUtils;
1112
import org.apache.commons.lang3.StringUtils;
1213
import org.springframework.data.annotation.Transient;
1314
import org.springframework.data.mongodb.core.mapping.Document;
@@ -98,4 +99,12 @@ public void set(String orgId, TransformedUserInfo transformedUserInfo) {
9899
public record TransformedUserInfo(long updateTime, Map<String, Object> extra) {
99100

100101
}
102+
103+
public void markAsDeleted() {
104+
this.setState(UserState.DELETED);
105+
this.setIsEnabled(false);
106+
SetUtils.emptyIfNull(this.getConnections())
107+
.forEach(connection -> connection.setSource(
108+
connection.getSource() + "(User deleted at " + System.currentTimeMillis() / 1000 + ")"));
109+
}
101110
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.openblocks.domain.user.model;
22

33
public enum UserState {
4-
NEW, INVITED, ACTIVATED
4+
NEW, INVITED, ACTIVATED,
5+
DELETED// User can only be deleted in enterprise mode.
56
}

server/openblocks-domain/src/main/java/com/openblocks/domain/user/service/UserService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,7 @@ public interface UserService {
4848
Mono<Boolean> setPassword(String userId, String password);
4949

5050
Mono<CurrentUser> buildCurrentUser(User user, boolean withoutDynamicGroups);
51+
52+
Mono<Boolean> markUserDeletedAndInvalidConnectionsAtEnterpriseMode(String userId);
5153
}
5254

server/openblocks-domain/src/main/java/com/openblocks/domain/user/service/UserServiceImpl.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import static com.openblocks.sdk.util.ExceptionUtils.ofException;
99

1010
import java.util.Collection;
11-
import java.util.Collections;
1211
import java.util.List;
1312
import java.util.Locale;
1413
import java.util.Map;
@@ -28,7 +27,6 @@
2827
import org.springframework.web.server.ServerWebExchange;
2928

3029
import com.google.common.collect.ImmutableSet;
31-
import com.google.common.collect.Maps;
3230
import com.openblocks.domain.asset.model.Asset;
3331
import com.openblocks.domain.asset.service.AssetService;
3432
import com.openblocks.domain.encryption.EncryptionService;
@@ -45,10 +43,12 @@
4543
import com.openblocks.domain.user.model.UserState;
4644
import com.openblocks.domain.user.repository.UserRepository;
4745
import com.openblocks.infra.mongo.MongoUpsertHelper;
46+
import com.openblocks.sdk.config.CommonConfig;
4847
import com.openblocks.sdk.config.dynamic.Conf;
4948
import com.openblocks.sdk.config.dynamic.ConfigCenter;
5049
import com.openblocks.sdk.constants.AuthSourceConstants;
5150
import com.openblocks.sdk.constants.FieldName;
51+
import com.openblocks.sdk.constants.WorkspaceMode;
5252
import com.openblocks.sdk.exception.BizError;
5353
import com.openblocks.sdk.exception.BizException;
5454
import com.openblocks.sdk.util.LocaleUtils;
@@ -77,6 +77,8 @@ public class UserServiceImpl implements UserService {
7777
private OrgMemberService orgMemberService;
7878
@Autowired
7979
private GroupService groupService;
80+
@Autowired
81+
private CommonConfig commonConfig;
8082

8183
private Conf<Integer> avatarMaxSizeInKb;
8284

@@ -281,6 +283,21 @@ public Mono<CurrentUser> buildCurrentUser(User user, boolean withoutDynamicGroup
281283
});
282284
}
283285

286+
/**
287+
* In enterprise mode, user can be deleted and then related connections should be released here by appending a timestamp after the source field.
288+
*/
289+
@Override
290+
public Mono<Boolean> markUserDeletedAndInvalidConnectionsAtEnterpriseMode(String userId) {
291+
if (commonConfig.getWorkspace().getMode() == WorkspaceMode.SAAS) {
292+
return Mono.just(false);
293+
}
294+
return repository.findById(userId)
295+
.flatMap(user -> {
296+
user.markAsDeleted();
297+
return mongoUpsertHelper.updateById(user, userId);
298+
});
299+
}
300+
284301
protected Map<String, Object> getCurrentUserExtra(User user, String orgId) {
285302
return Optional.ofNullable(user.getOrgTransformedUserInfo())
286303
.map(orgTransformedUserInfo -> orgTransformedUserInfo.get(orgId))

server/openblocks-sdk/src/main/java/com/openblocks/sdk/constants/GlobalContext.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
public class GlobalContext {
44

55
public static final String VISITOR_ID = "visitorId";
6-
public static final String VISITOR = "visitor";
76
public static final String VISITOR_TOKEN = "visitorToken";
87

98
public static final String SYSTEM_USER_ID = "SYSTEM";

server/openblocks-sdk/src/main/java/com/openblocks/sdk/util/JsonUtils.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ public static <T> T fromJson(String obj, Class<T> tClass) {
6060
}
6161
}
6262

63+
public static <T> T fromJsonQuietly(String obj, Class<T> tClass) {
64+
try {
65+
return objectMapper.readValue(obj, tClass);
66+
} catch (JsonProcessingException e) {
67+
return null;
68+
}
69+
}
70+
6371
public static List<Object> fromJsonList(String obj) {
6472
return fromJsonList(obj, Object.class);
6573
}

server/openblocks-server/src/main/java/com/openblocks/api/framework/filter/GlobalContextFilter.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import static com.openblocks.sdk.constants.GlobalContext.REQUEST_ID_LOG;
99
import static com.openblocks.sdk.constants.GlobalContext.REQUEST_METHOD;
1010
import static com.openblocks.sdk.constants.GlobalContext.REQUEST_PATH;
11-
import static com.openblocks.sdk.constants.GlobalContext.VISITOR;
1211
import static com.openblocks.sdk.constants.GlobalContext.VISITOR_ID;
1312
import static com.openblocks.sdk.constants.GlobalContext.VISITOR_TOKEN;
1413
import static java.util.Optional.ofNullable;
@@ -33,7 +32,6 @@
3332
import com.openblocks.api.framework.service.GlobalContextService;
3433
import com.openblocks.api.home.SessionUserService;
3534
import com.openblocks.domain.organization.service.OrgMemberService;
36-
import com.openblocks.domain.user.service.UserService;
3735
import com.openblocks.infra.serverlog.ServerLog;
3836
import com.openblocks.infra.serverlog.ServerLogService;
3937
import com.openblocks.infra.util.NetworkUtils;
@@ -60,9 +58,6 @@ public class GlobalContextFilter implements WebFilter, Ordered {
6058
@Autowired
6159
private ServerLogService serverLogService;
6260

63-
@Autowired
64-
private UserService userService;
65-
6661
@Autowired
6762
private GlobalContextService globalContextService;
6863

@@ -105,9 +100,6 @@ private Map<String, Object> buildContextMap(ServerWebExchange serverWebExchange,
105100
.filter(x -> x.getKey().startsWith(MDC_HEADER_PREFIX))
106101
.collect(toMap(v -> v.getKey().substring((MDC_HEADER_PREFIX.length())), Map.Entry::getValue));
107102
contextMap.put(VISITOR_ID, visitorId);
108-
if (!isAnonymousUser(visitorId)) {
109-
contextMap.put(VISITOR, userService.findById(visitorId).cache());
110-
}
111103
contextMap.put(CLIENT_IP, NetworkUtils.getRemoteIp(serverWebExchange));
112104
contextMap.put(REQUEST_ID_LOG, getOrCreateRequestId(request));
113105
contextMap.put(REQUEST_PATH, request.getPath().pathWithinApplication().value());
Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,28 @@
11
package com.openblocks.api.home;
22

33
import static com.openblocks.sdk.constants.GlobalContext.CURRENT_ORG_MEMBER;
4-
import static com.openblocks.sdk.constants.GlobalContext.VISITOR;
54
import static com.openblocks.sdk.exception.BizError.UNABLE_TO_FIND_VALID_ORG;
65
import static com.openblocks.sdk.util.ExceptionUtils.deferredError;
7-
import static com.openblocks.sdk.util.JsonUtils.fromJson;
8-
import static com.openblocks.sdk.util.JsonUtils.toJson;
6+
import static com.openblocks.sdk.util.JsonUtils.fromJsonQuietly;
97

108
import java.time.Duration;
9+
import java.util.Objects;
1110

1211
import org.apache.commons.lang3.StringUtils;
1312
import org.springframework.beans.factory.annotation.Autowired;
1413
import org.springframework.data.redis.core.ReactiveRedisTemplate;
1514
import org.springframework.data.redis.core.ReactiveValueOperations;
16-
import org.springframework.security.core.Authentication;
1715
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
1816
import org.springframework.stereotype.Service;
1917

2018
import com.openblocks.domain.organization.model.OrgMember;
2119
import com.openblocks.domain.organization.service.OrgMemberService;
2220
import com.openblocks.domain.user.model.User;
21+
import com.openblocks.domain.user.model.UserState;
2322
import com.openblocks.domain.user.service.UserService;
24-
import com.openblocks.infra.annotation.NonEmptyMono;
2523

2624
import lombok.extern.slf4j.Slf4j;
2725
import reactor.core.publisher.Mono;
28-
import reactor.core.scheduler.Schedulers;
2926

3027
@Slf4j
3128
@Service
@@ -42,7 +39,7 @@ public class SessionUserServiceImpl implements SessionUserService {
4239
@SuppressWarnings("ReactiveStreamsNullableInLambdaInTransform")
4340
@Override
4441
public Mono<String> getVisitorId() {
45-
return getVisitorFromSecurityContext()
42+
return getVisitor()
4643
.map(User::getId);
4744
}
4845

@@ -51,13 +48,8 @@ public Mono<String> getVisitorId() {
5148
*/
5249
@Override
5350
public Mono<User> getVisitor() {
54-
return Mono.deferContextual(contextView -> getVisitorFromSecurityContext()
55-
.flatMap(it -> {
56-
if (it.isAnonymous()) {
57-
return Mono.just(it);
58-
}
59-
return contextView.get(VISITOR);
60-
}));
51+
return ReactiveSecurityContextHolder.getContext()
52+
.map(securityContext -> (User) securityContext.getAuthentication().getPrincipal());
6153
}
6254

6355
/**
@@ -83,25 +75,16 @@ public Mono<OrgMember> getVisitorOrgMember() {
8375
.switchIfEmpty(deferredError(UNABLE_TO_FIND_VALID_ORG, "UNABLE_TO_FIND_VALID_ORG"));
8476
}
8577

86-
@NonEmptyMono
87-
private Mono<User> getVisitorFromSecurityContext() {
88-
return ReactiveSecurityContextHolder.getContext()
89-
.flatMap(securityContext -> {
90-
Authentication authentication = securityContext.getAuthentication();
91-
return Mono.just((User) authentication.getPrincipal());
92-
});
93-
}
94-
9578
@Override
9679
public Mono<Boolean> isAnonymousUser() {
97-
return getVisitorFromSecurityContext()
80+
return getVisitor()
9881
.map(User::isAnonymous);
9982
}
10083

10184
@Override
102-
public Mono<Void> saveUserSession(String sessionId, User user) {
85+
public Mono<Void> saveUserSession(String token, User user) {
10386
ReactiveValueOperations<String, String> ops = getRedisOps();
104-
return ops.set(sessionId, toJson(user), Duration.ofDays(7))
87+
return ops.set(token, Objects.requireNonNull(user.getId()), Duration.ofDays(7))
10588
.then();
10689
}
10790

@@ -115,12 +98,12 @@ public Mono<Void> extendValidity(String token) {
11598
}
11699

117100
@Override
118-
public Mono<Void> removeUserSession(String sessionId) {
119-
if (StringUtils.isBlank(sessionId)) {
101+
public Mono<Void> removeUserSession(String token) {
102+
if (StringUtils.isBlank(token)) {
120103
return Mono.empty();
121104
}
122105
ReactiveValueOperations<String, String> ops = getRedisOps();
123-
return ops.delete(sessionId)
106+
return ops.delete(token)
124107
.then();
125108
}
126109

@@ -130,21 +113,19 @@ public Mono<User> resolveSessionUserFromCookie(String token) {
130113
return Mono.empty();
131114
}
132115
return getRedisOps().get(token)
133-
.flatMap(it -> {
134-
User user = fromJson(it, User.class);
116+
.flatMap(value -> {
117+
User user = fromJsonQuietly(value, User.class);
135118
if (user == null) {
136-
return Mono.empty();
119+
return userService.findById(value);
137120
}
138-
return Mono.just(user);
121+
// some compatible code
122+
return userService.findById(user.getId());
139123
})
140-
.subscribeOn(Schedulers.boundedElastic());
124+
.filter(user -> user.getState() != UserState.DELETED);
141125
}
142126

143-
144127
private ReactiveValueOperations<String, String> getRedisOps() {
145128
return reactiveTemplate.opsForValue();
146129
}
147-
148-
149130
}
150131

server/openblocks-server/src/main/java/com/openblocks/api/usermanagement/OrgApiServiceImpl.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,18 +212,19 @@ public Mono<Boolean> uploadLogo(String orgId, Mono<Part> fileMono) {
212212
.flatMap(file -> organizationService.uploadLogo(orgId, file));
213213
}
214214

215+
/**
216+
* Remove the specified user from the organization, and if in enterprise mode, mark the user deleted.
217+
*/
215218
@Override
216219
public Mono<Boolean> removeUserFromOrg(String orgId, String userId) {
217220
return checkVisitorAdminRole(orgId)
218-
.then(orgMemberService.removeMember(orgId, userId)
219-
.handle((result, sink) -> {
220-
if (result) {
221-
applicationContext.publishEvent(new OrgMemberLeftEvent(orgId, userId));
222-
sink.next(true);
223-
return;
224-
}
225-
sink.next(false);
226-
}));
221+
.then(orgMemberService.removeMember(orgId, userId))
222+
.doOnNext(result -> {
223+
if (result) {
224+
applicationContext.publishEvent(new OrgMemberLeftEvent(orgId, userId));
225+
}
226+
})
227+
.delayUntil(__ -> userService.markUserDeletedAndInvalidConnectionsAtEnterpriseMode(userId));
227228
}
228229

229230
@Override

server/openblocks-server/src/main/java/com/openblocks/runner/eventlistener/OrgAndGroupEventListener.java

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

33
import static com.openblocks.sdk.util.JsonUtils.toJson;
44

5-
import java.time.Duration;
5+
import java.util.List;
66
import java.util.concurrent.ExecutorService;
77
import java.util.concurrent.Executors;
88

@@ -22,7 +22,6 @@
2222
import com.openblocks.domain.permission.service.ResourcePermissionService;
2323

2424
import lombok.extern.slf4j.Slf4j;
25-
import reactor.core.publisher.Flux;
2625
import reactor.core.publisher.Mono;
2726
import reactor.core.scheduler.Scheduler;
2827
import reactor.core.scheduler.Schedulers;
@@ -74,23 +73,25 @@ public void onOrgDeleted(OrgDeletedEvent event) {
7473
public void onUserLeaveOrg(OrgMemberLeftEvent orgMemberLeftEvent) {
7574
String orgId = orgMemberLeftEvent.getOrgId();
7675
String userId = orgMemberLeftEvent.getUserId();
77-
Flux<Boolean> removeGroupMember = groupService.getByOrgId(orgId)
78-
.delayElements(Duration.ofMillis(100))
76+
Mono<List<Boolean>> removeGroupMember = groupService.getByOrgId(orgId)
7977
.flatMap(group -> groupMemberService.removeMember(group.getId(), userId))
78+
.collectList()
8079
.retry(3)
8180
.subscribeOn(orgEventScheduler);
8281

83-
Flux<Boolean> removeAppPermissions = applicationService.findByOrganizationIdWithoutDsl(orgId)
82+
Mono<List<Boolean>> removeAppPermissions = applicationService.findByOrganizationIdWithoutDsl(orgId)
8483
.flatMap(application -> resourcePermissionService.removeUserApplicationPermission(application.getId(), userId))
84+
.collectList()
8585
.retry(3)
8686
.subscribeOn(orgEventScheduler);
8787

88-
Flux<Boolean> removeDatasourcePermissions = datasourceService.getByOrgId(orgId)
88+
Mono<List<Boolean>> removeDatasourcePermissions = datasourceService.getByOrgId(orgId)
8989
.flatMap(datasource -> resourcePermissionService.removeUserDatasourcePermission(datasource.getId(), userId))
90+
.collectList()
9091
.retry(3)
9192
.subscribeOn(orgEventScheduler);
9293

93-
Flux.zip(removeGroupMember, removeAppPermissions, removeDatasourcePermissions)
94+
Mono.zip(removeGroupMember, removeAppPermissions, removeDatasourcePermissions)
9495
.subscribe();
9596
}
9697

server/openblocks-server/src/main/resources/application-openblocks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ common:
3535
security:
3636
cors-allowed-domains:
3737
- '*'
38-
version: 1.1.1
38+
version: 1.1.2
3939
block-hound-enable: false
4040

4141
material:

server/openblocks-server/src/main/resources/selfhost/ce/application.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ common:
2626
domain:
2727
default-value: openblocks.dev
2828
cloud: false
29-
version: 1.1.1
29+
version: 1.1.2
3030
block-hound-enable: false
3131

3232
material:

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