solution for bug 2427: permissions are now supported on User and related objects, including persistence and test case

This commit is contained in:
Axel Uhl committed 2014-12-01 15:25:47 +01:00
1 parent 70647f1afc
commit 619a801f3e
15 files changed
+182 -27

No files matched your search

@@ -3,6 +3,7 @@ package com.sap.sse.security.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.net.UnknownHostException;
import java.util.Properties;
@@ -13,11 +14,13 @@ import org.junit.Test;
import com.mongodb.DB;
import com.mongodb.MongoException;
import com.sap.sse.common.Util;
import com.sap.sse.mongodb.MongoDBConfiguration;
import com.sap.sse.mongodb.MongoDBService;
import com.sap.sse.security.UsernamePasswordRealm;
import com.sap.sse.security.impl.Activator;
import com.sap.sse.security.impl.SecurityServiceImpl;
import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.userstore.mongodb.UserStoreImpl;
import com.sap.sse.security.userstore.mongodb.impl.CollectionNames;
@@ -29,6 +32,7 @@ public class LoginTest {
final MongoDBConfiguration dbConfiguration = MongoDBConfiguration.getDefaultTestConfiguration();
final MongoDBService service = dbConfiguration.getService();
DB db = service.getDB();
db.getCollection(CollectionNames.USERS.name()).drop();
db.getCollection(CollectionNames.SETTINGS.name()).drop();
db.getCollection(CollectionNames.PREFERENCES.name()).drop();
db.getCollection(CollectionNames.PREFERENCES.name()).drop();
@@ -58,4 +62,21 @@ public class LoginTest {
UserStoreImpl store2 = new UserStoreImpl();
assertNull(store2.getPreference("me", "key"));
}
@Test
public void rolesTest() throws UserManagementException {
store.createUser("me", "me@sap.com");
store.addRoleForUser("me", "testrole");
UserStoreImpl store2 = new UserStoreImpl();
assertTrue(Util.contains(store2.getUserByName("me").getRoles(), "testrole"));
}
@Test
public void permissionsTest() throws UserManagementException {
store.createUser("me", "me@sap.com");
store.addPermissionForUser("me", "a:b:c");
UserStoreImpl store2 = new UserStoreImpl();
assertTrue(store2.getUserByName("me").hasPermission("a:b:c"));
}
}
@@ -41,6 +41,8 @@ public interface UserManagementService extends RemoteService {
SuccessInfo setRolesForUser(String username, Iterable<String> roles);
SuccessInfo setPermissionsForUser(String username, Iterable<String> permissions);
Map<String, String> getSettings();
Map<String, String> getSettingTypes();
@@ -31,6 +31,8 @@ public interface UserManagementServiceAsync {
void setRolesForUser(String username, Iterable<String> roles, AsyncCallback<SuccessInfo> callback);
void setPermissionsForUser(String username, Iterable<String> permissions, AsyncCallback<SuccessInfo> callback);
void deleteUser(String username, AsyncCallback<SuccessInfo> callback);
void getSettings(AsyncCallback<Map<String, String>> callback);
@@ -39,12 +41,6 @@ public interface UserManagementServiceAsync {
void getSettingTypes(AsyncCallback<Map<String, String>> callback);
//------------------------------------------------ OAuth Interface ----------------------------------------------------------------------
void getAuthorizationUrl(CredentialDTO credential, AsyncCallback<String> callback);
void verifySocialUser(CredentialDTO credential, AsyncCallback<UserDTO> callback);
void addSetting(String key, String clazz, String setting, AsyncCallback<Void> callback);
void setPreference(String username, String key, String value, AsyncCallback<Void> callback);
@@ -53,4 +49,10 @@ public interface UserManagementServiceAsync {
void getPreference(String username, String key, AsyncCallback<String> callback);
//------------------------------------------------ OAuth Interface ----------------------------------------------------------------------
void getAuthorizationUrl(CredentialDTO credential, AsyncCallback<String> callback);
void verifySocialUser(CredentialDTO credential, AsyncCallback<UserDTO> callback);
}
@@ -216,7 +216,6 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
if (u == null) {
return new SuccessInfo(false, "User does not exist.", /* redirectURL */null, null);
}
try {
Set<String> rolesToRemove = new HashSet<>();
Util.addAll(u.getRoles(), rolesToRemove);
Util.removeAll(roles, rolesToRemove);
@@ -229,10 +228,35 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
for (String roleToAdd : rolesToAdd) {
getSecurityService().addRoleForUser(username, roleToAdd);
}
return new SuccessInfo(true, "Added role: " + roles + ".", /* redirectURL */ null, createUserDTOFromUser(u));
} catch (UserManagementException e) {
return new SuccessInfo(false, e.getMessage(), /* redirectURL */ null, null);
return new SuccessInfo(true, "Set roles " + roles + " for user " + username, /* redirectURL */null,
createUserDTOFromUser(u));
} else {
return new SuccessInfo(false, "You don't have the required permissions to add a role.", /* redirectURL */ null, null);
}
}
@Override
public SuccessInfo setPermissionsForUser(String username, Iterable<String> permissions) {
Subject currentSubject = SecurityUtils.getSubject();
if (currentSubject.hasRole(DefaultRoles.ADMIN.getRolename())) {
User u = getSecurityService().getUserByName(username);
if (u == null) {
return new SuccessInfo(false, "User does not exist.", /* redirectURL */null, null);
}
Set<String> permissionsToRemove = new HashSet<>();
Util.addAll(u.getPermissions(), permissionsToRemove);
Util.removeAll(permissions, permissionsToRemove);
for (String permissionToRemove : permissionsToRemove) {
getSecurityService().removePermissionFromUser(username, permissionToRemove);
}
Set<String> permissionsToAdd = new HashSet<>();
Util.addAll(permissions, permissionsToAdd);
Util.removeAll(u.getPermissions(), permissionsToAdd);
for (String permissionToAdd : permissionsToAdd) {
getSecurityService().addPermissionForUser(username, permissionToAdd);
}
return new SuccessInfo(true, "Set roles " + permissions + " for user " + username, /* redirectURL */null,
createUserDTOFromUser(u));
} else {
return new SuccessInfo(false, "You don't have the required permissions to add a role.", /* redirectURL */ null, null);
}
@@ -1,11 +1,11 @@
package com.sap.sse.security.ui.shared;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sse.common.Util;
public class UserDTO implements IsSerializable {
private String name;
@@ -35,8 +35,8 @@ public class UserDTO implements IsSerializable {
return roles.contains(role);
}
public void addRoles(Collection<String> roles) {
this.roles.addAll(roles);
public void addRoles(Iterable<String> roles) {
Util.addAll(roles, this.roles);
}
public List<AccountDTO> getAccounts() {
@@ -198,7 +198,7 @@ public class UserStoreImpl implements UserStore {
}
@Override
public Set<String> getRolesFromUser(String username) throws UserManagementException {
public Iterable<String> getRolesFromUser(String username) throws UserManagementException {
if (users.get(username) == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
}
@@ -228,6 +228,37 @@ public class UserStoreImpl implements UserStore {
}
}
@Override
public Iterable<String> getPermissionsFromUser(String username) throws UserManagementException {
if (users.get(username) == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
}
return users.get(username).getPermissions();
}
@Override
public void addPermissionForUser(String name, String permission) throws UserManagementException {
final User user = users.get(name);
if (user == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
}
user.addPermission(permission);
if (mongoObjectFactory != null) {
mongoObjectFactory.storeUser(user);
}
}
@Override
public void removePermissionFromUser(String name, String permission) throws UserManagementException {
if (users.get(name) == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
}
users.get(name).removePermission(permission);
if (mongoObjectFactory != null) {
mongoObjectFactory.storeUser(users.get(name));
}
}
@Override
public void deleteUser(String name) throws UserManagementException {
if (users.get(name) == null) {
@@ -70,18 +70,28 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
String passwordResetSecret = (String) userDBObject.get(FieldNames.User.PASSWORD_RESET_SECRET.name());
String validationSecret = (String) userDBObject.get(FieldNames.User.VALIDATION_SECRET.name());
Set<String> roles = new HashSet<String>();
Set<String> permissions = new HashSet<String>();
BasicDBList rolesO = (BasicDBList) userDBObject.get(FieldNames.User.ROLES.name());
if (rolesO != null) {
for (Object o : rolesO) {
roles.add((String) o);
}
}
BasicDBList permissionsO = (BasicDBList) userDBObject.get(FieldNames.User.PERMISSIONS.name());
if (permissionsO != null) {
for (Object o : permissionsO) {
permissions.add((String) o);
}
}
DBObject accountsMap = (DBObject) userDBObject.get(FieldNames.User.ACCOUNTS.name());
Map<AccountType, Account> accounts = createAccountMapFromdDBObject(accountsMap);
User result = new User(name, email, emailValidated==null?false:emailValidated, passwordResetSecret, validationSecret, accounts.values());
for (String role : roles) {
result.addRole(role);
}
for (String permission : permissions) {
result.addPermission(permission);
}
return result;
}
@@ -6,7 +6,7 @@ public class FieldNames {
NAME,
EMAIL,
ACCOUNTS,
ROLES,
ROLES, PERMISSIONS,
EMAIL_VALIDATED,
PASSWORD_RESET_SECRET,
VALIDATION_SECRET;
@@ -43,6 +43,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
dbUser.put(FieldNames.User.VALIDATION_SECRET.name(), user.getValidationSecret());
dbUser.put(FieldNames.User.ACCOUNTS.name(), createAccountMapObject(user.getAllAccounts()));
dbUser.put(FieldNames.User.ROLES.name(), user.getRoles());
dbUser.put(FieldNames.User.PERMISSIONS.name(), user.getPermissions());
usersCollection.update(query, dbUser, /* upsrt */true, /* multi */false, WriteConcern.SAFE);
}
@@ -1,7 +1,6 @@
package com.sap.sse.security;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.servlet.ServletContext;
@@ -53,11 +52,17 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
void deleteUser(String username) throws UserManagementException;
Set<String> getRolesFromUser(String username) throws UserManagementException;
Iterable<String> getRolesFromUser(String username) throws UserManagementException;
void addRoleForUser(String username, String role) throws UserManagementException;
void addRoleForUser(String username, String role);
void removeRoleFromUser(String username, String role) throws UserManagementException;
void removeRoleFromUser(String username, String role);
Iterable<String> getPermissionsFromUser(String username) throws UserManagementException;
void removePermissionFromUser(String username, String permissionToRemove);
void addPermissionForUser(String username, String permissionToAdd);
/**
* Registers a settings key together with its type. Calling this method is necessary for {@link #setSetting(String, Object)}
@@ -43,6 +43,7 @@ public class User implements Named, WithID {
private boolean emailValidated;
private final Set<String> roles;
private final Set<String> permissions;
private final Map<AccountType, Account> accounts;
public User(String name, String email, Account... accounts) {
@@ -58,6 +59,7 @@ public class User implements Named, WithID {
super();
this.name = name;
this.roles = new HashSet<>();
this.permissions = new HashSet<>();
this.email = email;
this.passwordResetSecret = passwordResetSecret;
this.validationSecret = validationSecret;
@@ -84,7 +86,7 @@ public class User implements Named, WithID {
this.name = name;
}
public Set<String> getRoles() {
public Iterable<String> getRoles() {
return roles;
}
@@ -100,6 +102,22 @@ public class User implements Named, WithID {
roles.remove(role);
}
public Iterable<String> getPermissions() {
return permissions;
}
public void addPermission(String permission) {
permissions.add(permission);
}
public boolean hasPermission(String permission) {
return permissions.contains(permission);
}
public void removePermission(String permission) {
permissions.remove(permission);
}
public Account getAccount(AccountType type) {
return accounts.get(type);
}
@@ -1,7 +1,6 @@
package com.sap.sse.security;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.sap.sse.common.Named;
@@ -19,12 +18,18 @@ public interface UserStore extends Named {
void updateUser(User user);
Set<String> getRolesFromUser(String username) throws UserManagementException;
Iterable<String> getRolesFromUser(String username) throws UserManagementException;
void addRoleForUser(String name, String role) throws UserManagementException;
void removeRoleFromUser(String name, String role) throws UserManagementException;
Iterable<String> getPermissionsFromUser(String username) throws UserManagementException;
void removePermissionFromUser(String name, String permission) throws UserManagementException;
void addPermissionForUser(String name, String permission) throws UserManagementException;
void deleteUser(String name) throws UserManagementException;
/**
@@ -12,6 +12,7 @@ import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import com.sap.sse.common.Util;
import com.sap.sse.security.shared.Account.AccountType;
import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.shared.UsernamePasswordAccount;
@@ -39,15 +40,18 @@ public class UsernamePasswordRealm extends AbstractUserStoreBasedRealm {
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
final SimpleAuthorizationInfo ai = new SimpleAuthorizationInfo();
final List<String> roles = new ArrayList<>();
for (Object r : principals.asList()){
final List<String> permissions = new ArrayList<>();
for (Object r : principals) {
String username = r.toString();
try {
roles.addAll(getUserStore().getRolesFromUser(username));
Util.addAll(getUserStore().getRolesFromUser(username), roles);
Util.addAll(getUserStore().getPermissionsFromUser(username), permissions);
} catch (UserManagementException e) {
throw new AuthenticationException(e.getMessage());
}
}
ai.addRoles(roles);
ai.addStringPermissions(permissions);
return ai;
}
@@ -28,5 +28,10 @@ public interface ReplicableSecurityService extends SecurityService {
Void internalRemoveRoleFromUser(String username, String role) throws UserManagementException;
Void internalAddPermissionForUser(String username, String permissionToAdd) throws UserManagementException;
Void internalRemovePermissionForUser(String username, String permissionToRemove) throws UserManagementException;
Void internalDeleteUser(String username) throws UserManagementException;
}
@@ -458,12 +458,12 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica
}
@Override
public Set<String> getRolesFromUser(String name) throws UserManagementException {
public Iterable<String> getRolesFromUser(String name) throws UserManagementException {
return store.getRolesFromUser(name);
}
@Override
public void addRoleForUser(String username, String role) throws UserManagementException {
public void addRoleForUser(String username, String role) {
apply(s->s.internalAddRoleForUser(username, role));
}
@@ -474,7 +474,7 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica
}
@Override
public void removeRoleFromUser(String username, String role) throws UserManagementException {
public void removeRoleFromUser(String username, String role) {
apply(s->s.internalRemoveRoleFromUser(username, role));
}
@@ -484,6 +484,33 @@ public class SecurityServiceImpl extends RemoteServiceServlet implements Replica
return null;
}
@Override
public Iterable<String> getPermissionsFromUser(String username) throws UserManagementException {
return store.getPermissionsFromUser(username);
}
@Override
public void removePermissionFromUser(String username, String permissionToRemove) {
apply(s->s.internalRemovePermissionForUser(username, permissionToRemove));
}
@Override
public Void internalRemovePermissionForUser(String username, String permissionToRemove) throws UserManagementException {
store.removePermissionFromUser(username, permissionToRemove);
return null;
}
@Override
public void addPermissionForUser(String username, String permissionToAdd) {
apply(s->s.internalAddPermissionForUser(username, permissionToAdd));
}
@Override
public Void internalAddPermissionForUser(String username, String permissionToAdd) throws UserManagementException {
store.addPermissionForUser(username, permissionToAdd);
return null;
}
@Override
public void deleteUser(String username) throws UserManagementException {
apply(s->s.internalDeleteUser(username));