mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-22 21:55:39 +00:00
made tests, particularly replication tests, green again
Change-Id: I493aec5ac3ea3f1bd6b1a1fd95b8ddd349ce4198
This commit is contained in:
@@ -25,7 +25,11 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.server,
|
||||
com.sap.sailing.server.testsupport,
|
||||
com.sap.sailing.domain.persistence,
|
||||
com.sap.sse.filestorage
|
||||
com.sap.sse.filestorage,
|
||||
com.sap.sse.security,
|
||||
com.sap.sse.security.userstore.mongodb,
|
||||
com.sap.sse.security.common,
|
||||
org.mongodb.mongo-java-driver
|
||||
Export-Package: com.sap.sailing.domain.test,
|
||||
com.sap.sailing.domain.test.mock
|
||||
Import-Package: org.osgi.util.tracker
|
||||
|
||||
+22
@@ -47,9 +47,15 @@ import com.sap.sse.common.Color;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.security.AccessControlStore;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.UserStore;
|
||||
import com.sap.sse.security.impl.SecurityServiceImpl;
|
||||
import com.sap.sse.security.shared.User;
|
||||
import com.sap.sse.security.shared.UserGroup;
|
||||
import com.sap.sse.security.shared.UserGroupManagementException;
|
||||
import com.sap.sse.security.shared.UserManagementException;
|
||||
import com.sap.sse.security.userstore.mongodb.AccessControlStoreImpl;
|
||||
import com.sap.sse.security.userstore.mongodb.UserStoreImpl;
|
||||
|
||||
public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
@@ -105,8 +111,24 @@ public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
public void testSerializingUserStore() throws UserGroupManagementException, UserManagementException, ClassNotFoundException, IOException {
|
||||
DomainFactory receiverDomainFactory = new DomainFactoryImpl((srlid)->null);
|
||||
UserStore userStore = new UserStoreImpl("defaultTenant");
|
||||
userStore.clear();
|
||||
AccessControlStore aclStore = new AccessControlStoreImpl(userStore);
|
||||
SecurityService securityService = new SecurityServiceImpl(userStore, aclStore);
|
||||
assertNotNull(securityService);
|
||||
{
|
||||
User admin = userStore.getUserByName("admin");
|
||||
UserGroup adminTenant = admin.getDefaultTenant();
|
||||
assertTrue(adminTenant.contains(admin));
|
||||
assertTrue(Util.contains(admin.getUserGroups(), adminTenant));
|
||||
}
|
||||
UserStore deserializedUserStore = cloneBySerialization(userStore, receiverDomainFactory);
|
||||
assertNotNull(deserializedUserStore);
|
||||
{
|
||||
User admin = deserializedUserStore.getUserByName("admin");
|
||||
UserGroup adminTenant = admin.getDefaultTenant();
|
||||
assertTrue(adminTenant.contains(admin));
|
||||
assertTrue(Util.contains(admin.getUserGroups(), adminTenant));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+10
@@ -37,10 +37,20 @@ public class AbstractMailServiceReplicationTest extends AbstractServerWithSingle
|
||||
@Override
|
||||
public Void internalSendMail(String toAddress, String subject, SerializableMultipartSupplier multipartSupplier)
|
||||
throws MailException {
|
||||
countOneIfCanSendMail(canSendMail);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void countOneIfCanSendMail(final boolean canSendMail) {
|
||||
if (canSendMail) {
|
||||
Integer old = numberOfMailsSent.get(this);
|
||||
numberOfMailsSent.put(this, old == null ? 1 : old + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void internalSendMail(String toAddress, String subject, String body) throws MailException {
|
||||
countOneIfCanSendMail(canSendMail);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
+31
-1
@@ -1,8 +1,12 @@
|
||||
package com.sap.sse.security.shared.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
@@ -16,8 +20,22 @@ import com.sap.sse.security.shared.WildcardPermission;
|
||||
|
||||
public class SecurityUserImpl implements SecurityUser {
|
||||
private static final long serialVersionUID = -3639860207453072248L;
|
||||
|
||||
private String name;
|
||||
private Set<Role> roles;
|
||||
|
||||
/**
|
||||
* Roles can refer back to this user object, e.g., for the user qualification, or during the tenant
|
||||
* qualification if this user belongs to the tenant for which the role is qualified. Therefore, this
|
||||
* set has to be transient, and the {@link #roleListForSerialization} field takes over the serialization
|
||||
* which is resolved by {@link #readResolve}.
|
||||
*
|
||||
* @see #writeObject
|
||||
* @see #readResolve
|
||||
*/
|
||||
private transient Set<Role> roles;
|
||||
|
||||
private List<Role> roleListForSerialization;
|
||||
|
||||
private Set<WildcardPermission> permissions;
|
||||
|
||||
/**
|
||||
@@ -47,7 +65,19 @@ public class SecurityUserImpl implements SecurityUser {
|
||||
this.permissions.add(permission);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
roleListForSerialization = new ArrayList<>(roles);
|
||||
oos.defaultWriteObject();
|
||||
roleListForSerialization = null;
|
||||
}
|
||||
|
||||
protected Object readResolve() {
|
||||
roles = new HashSet<>(roleListForSerialization);
|
||||
roleListForSerialization = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
||||
+30
-1
@@ -1,12 +1,17 @@
|
||||
package com.sap.sse.security.shared.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.security.shared.SecurityUser;
|
||||
import com.sap.sse.security.shared.User;
|
||||
import com.sap.sse.security.shared.UserGroup;
|
||||
|
||||
public class UserGroupImpl implements UserGroup {
|
||||
@@ -15,7 +20,18 @@ public class UserGroupImpl implements UserGroup {
|
||||
private UUID id;
|
||||
private String name;
|
||||
|
||||
private Set<SecurityUser> users;
|
||||
/**
|
||||
* A {@link HashSet} such as the one used for {@link #users} must not reference back to this object, or
|
||||
* serialization / deserialization will be corrupt. In particular, during de-serialization the {@link User}
|
||||
* objects will not have been fully constructed yet when they are to be added to the {@link HashSet}, causing
|
||||
* {@link NullPointerException}s in their {@link User#hashCode} method execution. Therefore, we use a list for
|
||||
* transporting the users through serialization, but outside of this use case the field is left {@code null}.
|
||||
*
|
||||
* @see #writeObject
|
||||
* @see #readObject
|
||||
*/
|
||||
private List<SecurityUser> usersAsListForSerialization;
|
||||
private transient Set<SecurityUser> users;
|
||||
|
||||
@Deprecated
|
||||
protected UserGroupImpl() {} // for GWT serialization only
|
||||
@@ -31,6 +47,19 @@ public class UserGroupImpl implements UserGroup {
|
||||
Util.addAll(users, this.users);
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
usersAsListForSerialization = new ArrayList<>(users);
|
||||
oos.defaultWriteObject();
|
||||
usersAsListForSerialization = null;
|
||||
}
|
||||
|
||||
protected Object readResolve() {
|
||||
users = new HashSet<>();
|
||||
users.addAll(usersAsListForSerialization);
|
||||
usersAsListForSerialization = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return id;
|
||||
|
||||
+1
-2
@@ -37,12 +37,11 @@ public abstract class AbstractSecurityReplicationTest extends AbstractServerWith
|
||||
final UserStoreImpl userStore = new UserStoreImpl("TestDefaultTenant");
|
||||
final AccessControlStore accessControlStore = new AccessControlStoreImpl(userStore);
|
||||
SecurityServiceImpl result = new SecurityServiceImpl(userStore, accessControlStore);
|
||||
result.clearReplicaState();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SecurityServiceImpl createNewReplica() throws UserGroupManagementException, UserManagementException {
|
||||
protected SecurityServiceImpl createNewReplica() throws UserGroupManagementException, UserManagementException, MalformedURLException, IOException, InterruptedException {
|
||||
final UserStoreImpl userStore = new UserStoreImpl("TestDefaultTenant");
|
||||
final AccessControlStore accessControlStore = new AccessControlStoreImpl(userStore);
|
||||
return new SecurityServiceImpl(userStore, accessControlStore);
|
||||
|
||||
+2
-12
@@ -57,18 +57,18 @@ public class SecurityReplicationLeadingToEmailReplicationTest extends AbstractSe
|
||||
final UserStoreImpl userStore = new UserStoreImpl("TestDefaultTenant");
|
||||
final AccessControlStore accessControlStore = new AccessControlStoreImpl(userStore);
|
||||
SecurityServiceImpl result = new SecurityServiceImpl(trackerMock, userStore, accessControlStore);
|
||||
result.clearReplicaState();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SecurityServiceImpl createNewReplica() throws UserGroupManagementException, UserManagementException {
|
||||
protected SecurityServiceImpl createNewReplica() throws UserGroupManagementException, UserManagementException, MalformedURLException, IOException, InterruptedException {
|
||||
@SuppressWarnings("unchecked")
|
||||
ServiceTracker<MailService, MailService> trackerMock = mock(ServiceTracker.class);
|
||||
doReturn(replicaMailService).when(trackerMock).getService();
|
||||
final UserStoreImpl userStore = new UserStoreImpl("TestDefaultTenant");
|
||||
final AccessControlStore accessControlStore = new AccessControlStoreImpl(userStore);
|
||||
SecurityServiceImpl result = new SecurityServiceImpl(trackerMock, userStore, accessControlStore);
|
||||
result.clearReplicaState();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -101,21 +101,16 @@ public class SecurityReplicationLeadingToEmailReplicationTest extends AbstractSe
|
||||
//same message queue, but don't know about each other (unlike actual OSGi setup, where there is only
|
||||
//one replication service per instance that nows all Replicables)
|
||||
SecurityService masterSecurityService = securitySetUp.getMaster();
|
||||
|
||||
final String username = "Ernie";
|
||||
final String email = "ernie@sesame-street.com";
|
||||
final String password = "BertMyFriend";
|
||||
final String validationBaseURL = null; //so that validation email is not sent
|
||||
|
||||
masterSecurityService.createSimpleUser(username, email, password,
|
||||
/* fullName */ null, /* company */ null, validationBaseURL);
|
||||
|
||||
masterSecurityService.sendMail(username, "subject", "body");
|
||||
|
||||
securitySetUp.getReplicaReplicator().waitUntilQueueIsEmpty();
|
||||
mailSetUp.getReplicaReplicator().waitUntilQueueIsEmpty();
|
||||
Thread.sleep(3000);
|
||||
|
||||
assertThat("mail was not sent on replica",
|
||||
AbstractMailServiceReplicationTest.numberOfMailsSent.get(replicaMailService), equalTo(null));
|
||||
assertThat("mail was sent on master",
|
||||
@@ -132,21 +127,16 @@ public class SecurityReplicationLeadingToEmailReplicationTest extends AbstractSe
|
||||
public void triggerEmailSendByAddingUserOnReplica()
|
||||
throws UserManagementException, MailException, IllegalAccessException, InterruptedException, UserGroupManagementException {
|
||||
SecurityService replicaSecurityService = securitySetUp.getReplica();
|
||||
|
||||
final String username = "Ernie";
|
||||
final String email = "ernie@sesame-street.com";
|
||||
final String password = "BertMyFriend";
|
||||
final String validationBaseURL = null; //so that validation email is not sent
|
||||
|
||||
replicaSecurityService.createSimpleUser(username, email, password,
|
||||
/* fullName */ null, /* company */ null, validationBaseURL);
|
||||
|
||||
replicaSecurityService.sendMail(username, "subject", "body");
|
||||
|
||||
securitySetUp.getReplicaReplicator().waitUntilQueueIsEmpty();
|
||||
mailSetUp.getReplicaReplicator().waitUntilQueueIsEmpty();
|
||||
Thread.sleep(3000);
|
||||
|
||||
assertThat("mail was not sent on replica",
|
||||
AbstractMailServiceReplicationTest.numberOfMailsSent.get(replicaMailService), equalTo(null));
|
||||
assertThat("mail was sent on master",
|
||||
|
||||
+5
-3
@@ -16,6 +16,7 @@ import com.sap.sse.security.impl.SecurityServiceImpl;
|
||||
import com.sap.sse.security.shared.UserGroupManagementException;
|
||||
import com.sap.sse.security.shared.UserManagementException;
|
||||
import com.sap.sse.security.userstore.mongodb.AccessControlStoreImpl;
|
||||
import com.sap.sse.security.userstore.mongodb.PersistenceFactory;
|
||||
import com.sap.sse.security.userstore.mongodb.UserStoreImpl;
|
||||
|
||||
public class SecurityServiceInitialLoadTest extends AbstractServerWithSingleServiceReplicationTest<SecurityService, SecurityServiceImpl> {
|
||||
@@ -31,10 +32,11 @@ public class SecurityServiceInitialLoadTest extends AbstractServerWithSingleServ
|
||||
@Override
|
||||
protected SecurityServiceImpl createNewMaster()
|
||||
throws MalformedURLException, IOException, InterruptedException, UserManagementException, MailException, UserGroupManagementException {
|
||||
final UserStore userStore = new UserStoreImpl(null, null, "TestDefaultTenant"); // no persistence
|
||||
final AccessControlStore accessControlStore = new AccessControlStoreImpl(null, null, userStore); // no persistence
|
||||
final UserStore userStore = new UserStoreImpl(PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(),
|
||||
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), "TestDefaultTenant");
|
||||
final AccessControlStore accessControlStore = new AccessControlStoreImpl(PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(),
|
||||
PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(), userStore);
|
||||
final SecurityServiceImpl newMaster = new SecurityServiceImpl(userStore, accessControlStore);
|
||||
newMaster.clearReplicaState();
|
||||
newMaster.createSimpleUser(username, email, password, fullName, company, /* validationBaseURL */ null);
|
||||
accessToken = newMaster.createAccessToken(username);
|
||||
return newMaster;
|
||||
|
||||
+10
-6
@@ -2,7 +2,6 @@ package com.sap.sse.security.userstore.mongodb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -266,10 +265,15 @@ public class UserStoreImpl implements UserStore {
|
||||
UserStoreImpl.class.getSimpleName() + " lock for listeners collection", false);
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
protected Object readResolve() {
|
||||
for (final User user : getUsers()) {
|
||||
if (user instanceof UserImpl) {
|
||||
((UserImpl) user).setUserGroupProvider(this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
userGroups.clear();
|
||||
@@ -497,12 +501,12 @@ public class UserStoreImpl implements UserStore {
|
||||
|
||||
@Override
|
||||
public UserGroup getUserGroupByName(String name) {
|
||||
return userGroupsByName.get(name);
|
||||
return name == null ? null : userGroupsByName.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserGroup getUserGroup(UUID id) {
|
||||
return userGroups.get(id);
|
||||
return id == null ? null : userGroups.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,5 +36,6 @@ Require-Bundle: javax.servlet;bundle-version="3.1.0",
|
||||
com.sap.sse.shared.android
|
||||
Web-ContextPath: /security
|
||||
Export-Package: com.sap.sse.security,
|
||||
com.sap.sse.security.impl;x-friends:="com.sap.sailing.domain.test",
|
||||
com.sap.sse.security.jaxrs
|
||||
Automatic-Module-Name: com.sap.sse.security
|
||||
|
||||
@@ -61,7 +61,7 @@ public class UserImpl extends SecurityUserImpl implements User {
|
||||
|
||||
private final Map<AccountType, Account> accounts;
|
||||
|
||||
private transient final UserGroupProvider userGroupProvider;
|
||||
private transient UserGroupProvider userGroupProvider;
|
||||
|
||||
public UserImpl(String name, String email, UserGroup defaultTenant, UserGroupProvider userGroupProvider, Account... accounts) {
|
||||
this(name, email, defaultTenant, Arrays.asList(accounts), userGroupProvider);
|
||||
@@ -88,6 +88,14 @@ public class UserImpl extends SecurityUserImpl implements User {
|
||||
this.accounts.put(a.getAccountType(), a);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main use case for this method is to restore the link to a {@link UserStore} after de-serialization, e.g.,
|
||||
* on a replica.
|
||||
*/
|
||||
public void setUserGroupProvider(UserGroupProvider userGroupProvider) {
|
||||
this.userGroupProvider = userGroupProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* For the time being, the user {@link #getName() name} is used as ID
|
||||
|
||||
@@ -661,6 +661,9 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
|
||||
String hashedPasswordBase64 = hashPassword(password, salt);
|
||||
UsernamePasswordAccount upa = new UsernamePasswordAccount(username, hashedPasswordBase64, salt);
|
||||
final UserImpl result = userStore.createUser(username, email, tenant, upa); // TODO: get the principal as owner
|
||||
// now the user creation needs to be replicated so that when replicating role addition and group assignment
|
||||
// the replica will be able to resolve the user correctly
|
||||
apply(s->s.internalStoreUser(result));
|
||||
addRoleForUser(result, new RoleImpl(UserRole.getInstance(), /* tenant qualifier */ null, /* user qualifier */ result));
|
||||
addUserToUserGroup(tenant, result);
|
||||
// the new user becomes the owning user of its own specific tenant which initially only contains the new user
|
||||
|
||||
Reference in New Issue
Block a user