Skip to content

Commit

Permalink
fix: delete all user by domain when a domain is rmeoved
Browse files Browse the repository at this point in the history
  • Loading branch information
leleueri committed Jan 21, 2022
1 parent 969ec2b commit f83a8b0
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.gravitee.am.model.common.Page;
import io.gravitee.am.repository.common.CrudRepository;
import io.gravitee.am.repository.management.api.search.FilterCriteria;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
Expand Down Expand Up @@ -60,4 +61,6 @@ public interface UserRepository extends CommonUserRepository {
Single<Long> countByApplication(String domain, String application);

Single<Map<Object, Object>> statistics(AnalyticsQuery query);

Completable deleteByReference(ReferenceType referenceType, String referenceId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -538,4 +538,20 @@ private Single<User> completeUser(User userToComplete) {
);
}

@Override
public Completable deleteByReference(ReferenceType referenceType, String referenceId) {
LOGGER.debug("deleteByReference({}, {})", referenceType, referenceId);
TransactionalOperator trx = TransactionalOperator.create(tm);
Mono<Integer> delete = dbClient.execute("DELETE FROM users WHERE reference_type = :refType AND reference_id = :refId").bind("refType", referenceType.name()).bind("refId", referenceId).fetch().rowsUpdated();
return monoToCompletable(deleteChildEntitiesByDomain(referenceType.name(), referenceId).then(delete).as(trx::transactional));
}


private Mono<Integer> deleteChildEntitiesByDomain(String refType, String refId) {
Mono<Integer> deleteRoles = dbClient.execute("DELETE FROM user_roles WHERE user_id IN (SELECT id FROM users u WHERE u.reference_type = :refType AND u.reference_id = :refId)").bind("refType", refType).bind("refId", refId).fetch().rowsUpdated();
Mono<Integer> deleteAddresses = dbClient.execute("DELETE FROM user_addresses WHERE user_id IN (SELECT id FROM users u WHERE u.reference_type = :refType AND u.reference_id = :refId)").bind("refType", refType).bind("refId", refId).fetch().rowsUpdated();
Mono<Integer> deleteAttributes = dbClient.execute("DELETE FROM user_attributes WHERE user_id IN (SELECT id FROM users u WHERE u.reference_type = :refType AND u.reference_id = :refId)").bind("refType", refType).bind("refId", refId).fetch().rowsUpdated();
Mono<Integer> deleteEntitlements = dbClient.execute("DELETE FROM user_entitlements WHERE user_id IN (SELECT id FROM users u WHERE u.reference_type = :refType AND u.reference_id = :refId)").bind("refType", refType).bind("refId", refId).fetch().rowsUpdated();
return deleteRoles.then(deleteAddresses).then(deleteAttributes).then(deleteEntitlements);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2015 The Gravitee team (http://gravitee.io)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] [%X{domain}] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<!-- Strictly speaking, the level attribute is not necessary since -->
<!-- the level of the root level is set to DEBUG by default. -->
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>

</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
import io.gravitee.am.model.analytics.AnalyticsQuery;
import io.gravitee.am.repository.management.api.UserRepository;
import io.gravitee.am.repository.mongodb.management.internal.model.UserMongo;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.*;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -160,4 +158,9 @@ private Single<Map<Object, Object>> registrationsStatusRepartition(AnalyticsQuer
protected UserMongo convert(User user) {
return convert(user, new UserMongo());
}

@Override
public Completable deleteByReference(ReferenceType referenceType, String referenceId) {
return Completable.fromPublisher(usersCollection.deleteMany(and(eq(FIELD_REFERENCE_TYPE, referenceType.name()), eq(FIELD_REFERENCE_ID, referenceId))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.gravitee.am.repository.management.api.search.FilterCriteria;
import io.reactivex.observers.TestObserver;
import io.reactivex.subscribers.TestSubscriber;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

Expand Down Expand Up @@ -324,10 +325,7 @@ public void testUpdate() throws TechnicalException {
@Test
public void testDelete() throws TechnicalException {
// create user
User user = new User();
user.setReferenceType(ReferenceType.DOMAIN);
user.setReferenceId("domainId");
user.setUsername("testsUsername");
User user = buildUser();
User userCreated = userRepository.create(user).blockingGet();

// fetch user
Expand All @@ -345,6 +343,46 @@ public void testDelete() throws TechnicalException {
userRepository.findById(userCreated.getId()).test().assertEmpty();
}

@Test
public void testDeleteByDomain() throws TechnicalException {
final String DOMAIN_1 = "domain1";
final String DOMAIN_2 = "domain2";

// create user
User user = buildUser();
user.setReferenceId(DOMAIN_1);
user.setReferenceType(ReferenceType.DOMAIN);
userRepository.create(user).blockingGet();

user = buildUser();
user.setReferenceId(DOMAIN_1);
user.setReferenceType(ReferenceType.DOMAIN);
userRepository.create(user).blockingGet();

user = buildUser();
user.setReferenceId(DOMAIN_2);
user.setReferenceType(ReferenceType.DOMAIN);
userRepository.create(user).blockingGet();

final long usersDomain1 = userRepository.findAll(ReferenceType.DOMAIN, DOMAIN_1).count().blockingGet();
Assert.assertEquals("Domain1 should have 2 users", 2, usersDomain1);
long usersDomain2 = userRepository.findAll(ReferenceType.DOMAIN, DOMAIN_2).count().blockingGet();
Assert.assertEquals("Domain2 should have 1 users", 1, usersDomain2);

// delete user
TestObserver testObserver1 = userRepository.deleteByReference(ReferenceType.DOMAIN, DOMAIN_1).test();
testObserver1.awaitTerminalEvent();

// fetch user
final TestSubscriber<User> find = userRepository.findAll(ReferenceType.DOMAIN, DOMAIN_1).test();
find.awaitTerminalEvent();
find.assertNoValues();

usersDomain2 = userRepository.findAll(ReferenceType.DOMAIN, DOMAIN_2).count().blockingGet();
Assert.assertEquals("Domain2 should have 1 users", 1, usersDomain2);

}

@Test
public void testSearch_byUsername_strict() {
testSearch_strict("testUsername");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ public interface UserService extends CommonUserService {

Single<Map<Object, Object>> statistics(AnalyticsQuery query);

Completable deleteByDomain(String domainId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,7 @@ public Completable delete(String domainId, User principal) {
})
)
// delete users
.andThen(userService.findByDomain(domainId)
.flatMapCompletable(user ->
userService.delete(user.getId()))
.andThen(userService.deleteByDomain(domainId)
)
// delete groups
.andThen(groupService.findByDomain(domainId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@

import io.gravitee.am.common.event.Action;
import io.gravitee.am.common.event.Type;
import io.gravitee.am.model.Group;
import io.gravitee.am.model.ReferenceType;
import io.gravitee.am.model.User;
import io.gravitee.am.model.analytics.AnalyticsQuery;
import io.gravitee.am.model.common.Page;
import io.gravitee.am.model.common.event.Event;
import io.gravitee.am.model.common.event.Payload;
import io.gravitee.am.repository.management.api.UserRepository;
import io.gravitee.am.service.GroupService;
import io.gravitee.am.service.RoleService;
import io.gravitee.am.service.UserService;
import io.gravitee.am.service.exception.AbstractManagementException;
import io.gravitee.am.service.exception.TechnicalManagementException;
import io.gravitee.am.service.model.NewUser;
import io.gravitee.am.service.model.UpdateUser;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
Expand All @@ -40,7 +38,6 @@
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author David BRASSELY (david.brassely at graviteesource.com)
Expand Down Expand Up @@ -176,4 +173,9 @@ public Single<Map<Object, Object>> statistics(AnalyticsQuery query) {
String.format("An error occurs while count users analytics : %s", query), ex));
});
}
}

public Completable deleteByDomain(String domain) {
LOGGER.debug("Delete all users from domain {}", domain);
return userRepository.deleteByReference(ReferenceType.DOMAIN, domain);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -573,9 +573,7 @@ public void shouldDelete() {
when(role.getId()).thenReturn(ROLE_ID);
when(roleService.findByDomain(DOMAIN_ID)).thenReturn(Single.just(Collections.singleton(role)));
when(roleService.delete(eq(ReferenceType.DOMAIN), eq(DOMAIN_ID), anyString())).thenReturn(Completable.complete());
when(user.getId()).thenReturn(USER_ID);
when(userService.findByDomain(DOMAIN_ID)).thenReturn(Flowable.just(user));
when(userService.delete(anyString())).thenReturn(Completable.complete());
when(userService.deleteByDomain(any())).thenReturn(Completable.complete());
when(scope.getId()).thenReturn(SCOPE_ID);
when(scopeService.findByDomain(DOMAIN_ID, 0, Integer.MAX_VALUE)).thenReturn(Single.just(new Page<>(Collections.singleton(scope),0,1)));
when(scopeService.delete(SCOPE_ID, true)).thenReturn(Completable.complete());
Expand Down Expand Up @@ -619,7 +617,7 @@ public void shouldDelete() {
verify(identityProviderService, times(1)).delete(DOMAIN_ID, IDP_ID);
verify(extensionGrantService, times(1)).delete(DOMAIN_ID, EXTENSION_GRANT_ID);
verify(roleService, times(1)).delete(eq(ReferenceType.DOMAIN), eq(DOMAIN_ID), eq(ROLE_ID));
verify(userService, times(1)).delete(USER_ID);
verify(userService, times(1)).deleteByDomain(DOMAIN_ID);
verify(scopeService, times(1)).delete(SCOPE_ID, true);
verify(groupService, times(1)).delete(eq(ReferenceType.DOMAIN), eq(DOMAIN_ID), eq(GROUP_ID));
verify(formService, times(1)).delete(eq(DOMAIN_ID), eq(FORM_ID));
Expand All @@ -640,7 +638,7 @@ public void shouldDeleteWithoutRelatedData() {
when(identityProviderService.findByDomain(DOMAIN_ID)).thenReturn(Flowable.empty());
when(extensionGrantService.findByDomain(DOMAIN_ID)).thenReturn(Flowable.empty());
when(roleService.findByDomain(DOMAIN_ID)).thenReturn(Single.just(Collections.emptySet()));
when(userService.findByDomain(DOMAIN_ID)).thenReturn(Flowable.empty());
when(userService.deleteByDomain(DOMAIN_ID)).thenReturn(Completable.complete());
when(scopeService.findByDomain(DOMAIN_ID, 0, Integer.MAX_VALUE)).thenReturn(Single.just(new Page<>(Collections.emptySet(),0,1)));
when(groupService.findByDomain(DOMAIN_ID)).thenReturn(Flowable.empty());
when(formService.findByDomain(DOMAIN_ID)).thenReturn(Flowable.empty());
Expand All @@ -665,7 +663,7 @@ public void shouldDeleteWithoutRelatedData() {
verify(identityProviderService, never()).delete(anyString(), anyString());
verify(extensionGrantService, never()).delete(anyString(), anyString());
verify(roleService, never()).delete(eq(ReferenceType.DOMAIN), eq(DOMAIN_ID), anyString());
verify(userService, never()).delete(anyString());
verify(userService).deleteByDomain(anyString());
verify(scopeService, never()).delete(anyString(), anyBoolean());
verify(formService, never()).delete(anyString(), anyString());
verify(emailTemplateService, never()).delete(anyString());
Expand Down

0 comments on commit f83a8b0

Please sign in to comment.