Skip to content

Commit b09f2e0

Browse files
authored
Merge pull request #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)