Refactored roles and rolePermissionModels

This commit is contained in:
Jonas Dann
2017-11-24 12:39:54 +01:00
parent b463fcc76d
commit 8528cce300
30 changed files with 202 additions and 157 deletions
@@ -15,7 +15,7 @@ public class SailingPermissionsForRoleProvider implements PermissionsForRoleProv
public Iterable<String> getPermissions(String role, RolePermissionModel rolePermissionModel) { public Iterable<String> getPermissions(String role, RolePermissionModel rolePermissionModel) {
final Iterable<String> result; final Iterable<String> result;
if (rolePermissionModel == null) { if (rolePermissionModel == null) {
if (AdminRole.getInstance().getDisplayName().equals(role)) { if (AdminRole.getInstance().getName().equals(role)) {
ArrayList<String> permissions = new ArrayList<>(); ArrayList<String> permissions = new ArrayList<>();
permissions.add("*"); permissions.add("*");
result = permissions; result = permissions;
@@ -10,7 +10,6 @@ import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel; import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.security.Permission; import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication;
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants;
@@ -49,7 +48,7 @@ public class DataMiningEntryPoint extends AbstractSailingEntryPoint {
SAPHeaderWithAuthentication header = new SAPHeaderWithAuthentication(getStringMessages().sapSailingAnalytics(), getStringMessages().dataMining()); SAPHeaderWithAuthentication header = new SAPHeaderWithAuthentication(getStringMessages().sapSailingAnalytics(), getStringMessages().dataMining());
GenericAuthentication genericSailingAuthentication = new FixedSailingAuthentication(getUserService(), header.getAuthenticationMenuView()); GenericAuthentication genericSailingAuthentication = new FixedSailingAuthentication(getUserService(), header.getAuthenticationMenuView());
AuthorizedContentDecorator authorizedContentDecorator = new GenericAuthorizedContentDecorator(genericSailingAuthentication); AuthorizedContentDecorator authorizedContentDecorator = new GenericAuthorizedContentDecorator(genericSailingAuthentication);
authorizedContentDecorator.setPermissionToCheck(Permission.DATA_MINING, SailingPermissionsForRoleProvider.INSTANCE); authorizedContentDecorator.setPermissionToCheck(Permission.DATA_MINING);
authorizedContentDecorator.setContentWidgetFactory(new WidgetFactory() { authorizedContentDecorator.setContentWidgetFactory(new WidgetFactory() {
@Override @Override
public Widget get() { public Widget get() {
@@ -11,7 +11,6 @@ import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.security.Permission; import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication;
import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication;
import com.sap.sailing.gwt.settings.client.leaderboardedit.LeaderboardEditContextDefinition; import com.sap.sailing.gwt.settings.client.leaderboardedit.LeaderboardEditContextDefinition;
@@ -42,7 +41,7 @@ public class LeaderboardEditPage extends AbstractSailingEntryPoint {
SAPHeaderWithAuthentication header = initHeader(); SAPHeaderWithAuthentication header = initHeader();
GenericAuthentication genericSailingAuthentication = new FixedSailingAuthentication(getUserService(), header.getAuthenticationMenuView()); GenericAuthentication genericSailingAuthentication = new FixedSailingAuthentication(getUserService(), header.getAuthenticationMenuView());
AuthorizedContentDecorator authorizedContentDecorator = new GenericAuthorizedContentDecorator(genericSailingAuthentication); AuthorizedContentDecorator authorizedContentDecorator = new GenericAuthorizedContentDecorator(genericSailingAuthentication);
authorizedContentDecorator.setPermissionToCheck(Permission.MANAGE_LEADERBOARD_RESULTS, SailingPermissionsForRoleProvider.INSTANCE); authorizedContentDecorator.setPermissionToCheck(Permission.MANAGE_LEADERBOARD_RESULTS);
authorizedContentDecorator.setContentWidgetFactory(new WidgetFactory() { authorizedContentDecorator.setContentWidgetFactory(new WidgetFactory() {
@Override @Override
public Widget get() { public Widget get() {
@@ -446,8 +446,7 @@ public class AdminConsolePanel extends DockLayoutPanel implements HandleTabSelec
private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) { private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) {
for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) { for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) {
WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission()); WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission());
for (String userStringPermission : user.getAllPermissions(permissionsForRoleProvider)) { for (WildcardPermission userPermission : user.getAllPermissions(permissionsForRoleProvider)) {
WildcardPermission userPermission = new WildcardPermission(userStringPermission);
if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) { if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) {
return true; return true;
} }
@@ -6,13 +6,14 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class AdminRole implements Role { public class AdminRole implements Role {
private static final long serialVersionUID = 3291793984984443193L;
private static AdminRole INSTANCE; private static AdminRole INSTANCE;
private static final String NAME = "admin"; private static final String NAME = "admin";
private static final String UUID_STRING = "dc77e3d1-d405-435e-8699-ce7245f6fd7a"; private static final String UUID_STRING = "dc77e3d1-d405-435e-8699-ce7245f6fd7a";
private final UUID id; private final UUID id;
private final Set<WildcardPermission> permissions; private final Set<WildcardPermission> permissions;
AdminRole() { AdminRole() {
id = UUID.fromString(UUID_STRING); id = UUID.fromString(UUID_STRING);
permissions = new HashSet<>(); permissions = new HashSet<>();
@@ -20,7 +21,7 @@ public class AdminRole implements Role {
} }
@Override @Override
public String getDisplayName() { public String getName() {
return NAME; return NAME;
} }
@@ -2,6 +2,7 @@ package com.sap.sse.security.shared;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
/** /**
* The {@link PermissionChecker} is an implementation of the permission * The {@link PermissionChecker} is an implementation of the permission
@@ -31,7 +32,7 @@ public class PermissionChecker {
* The instance id can be omitted when a general permission for the data * The instance id can be omitted when a general permission for the data
* object type is asked after (e.g. "event:create"). * object type is asked after (e.g. "event:create").
*/ */
public static boolean isPermitted(WildcardPermission permission, String user, Iterable<UserGroup> tenants, Iterable<WildcardPermission> directPermissions, Iterable<String> roles, public static boolean isPermitted(WildcardPermission permission, String user, Iterable<UserGroup> tenants, Iterable<WildcardPermission> directPermissions, Iterable<UUID> roles,
RolePermissionModel rolePermissionModel, Owner ownership, AccessControlList acl) { RolePermissionModel rolePermissionModel, Owner ownership, AccessControlList acl) {
List<Set<String>> parts = permission.getParts(); List<Set<String>> parts = permission.getParts();
// permission has at least data object type and action as parts // permission has at least data object type and action as parts
@@ -43,7 +44,7 @@ public class PermissionChecker {
PermissionState result = PermissionState.NONE; PermissionState result = PermissionState.NONE;
// 1. check ownership // 1. check ownership
if (ownership != null && user.equals(ownership.getOwner())) { // TODO check for tenant ownership if (ownership != null && user.equals(ownership.getOwner())) {
result = PermissionState.GRANTED; result = PermissionState.GRANTED;
} }
// 2. check ACL // 2. check ACL
@@ -61,7 +62,7 @@ public class PermissionChecker {
} }
// 4. check role permissions // 4. check role permissions
if (result == PermissionState.NONE) { if (result == PermissionState.NONE) {
for (String role : roles) { for (UUID role : roles) {
if (rolePermissionModel.implies(role, permission, ownership)) { if (rolePermissionModel.implies(role, permission, ownership)) {
result = PermissionState.GRANTED; result = PermissionState.GRANTED;
break; break;
@@ -2,9 +2,8 @@ package com.sap.sse.security.shared;
import java.util.Set; import java.util.Set;
import com.sap.sse.common.WithID; import com.sap.sse.common.NamedWithID;
public interface Role extends WithID { public interface Role extends NamedWithID {
String getDisplayName();
Set<WildcardPermission> getPermissions(); Set<WildcardPermission> getPermissions();
} }
@@ -6,32 +6,34 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class RoleImpl implements Role { public class RoleImpl implements Role {
private static final long serialVersionUID = -402472324567793082L;
private final UUID id; private final UUID id;
private final String displayName; private final String name;
private final Set<WildcardPermission> permissions; private final Set<WildcardPermission> permissions;
public RoleImpl(UUID id, String displayName) { public RoleImpl(UUID id, String displayName) {
this(id, displayName, new HashSet<WildcardPermission>()); this(id, displayName, new HashSet<WildcardPermission>());
} }
public RoleImpl(UUID id, String displayName, Set<WildcardPermission> permissions) { public RoleImpl(UUID id, String name, Set<WildcardPermission> permissions) {
this.id = id; this.id = id;
this.displayName = displayName; this.name = name;
this.permissions = permissions; this.permissions = permissions;
} }
@Override
public Serializable getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override @Override
public Set<WildcardPermission> getPermissions() { public Set<WildcardPermission> getPermissions() {
return permissions; return permissions;
} }
@Override
public String getDisplayName() {
return displayName;
}
@Override
public Serializable getId() {
return id;
}
} }
@@ -1,11 +1,16 @@
package com.sap.sse.security.shared; package com.sap.sse.security.shared;
import java.util.UUID;
public interface RolePermissionModel { public interface RolePermissionModel {
Iterable<String> getPermissions(String role); String getName(UUID id);
Iterable<WildcardPermission> getPermissions(UUID id);
boolean implies(String role, WildcardPermission permission); boolean implies(UUID id, WildcardPermission permission);
boolean implies(UUID id, WildcardPermission permission, Owner ownership);
/** /**
* @param role Role of the for "role_title:tenant". The tenant is an optional * @param id Id of role
* @param name Role name of the form "role_title:tenant". The tenant is an optional
* parameter. It restricts permissions with a * as the instance id * parameter. It restricts permissions with a * as the instance id
* to data objects where the tenant parameter equals the tenant owner * to data objects where the tenant parameter equals the tenant owner
* of the data object. E.g.: * of the data object. E.g.:
@@ -16,5 +21,5 @@ public interface RolePermissionModel {
* "tw2016-dyas" would have "tw2016" as the tenant owner) * "tw2016-dyas" would have "tw2016" as the tenant owner)
* @param ownership Ownership of the data object * @param ownership Ownership of the data object
*/ */
boolean implies(String role, WildcardPermission permission, Owner ownership); boolean implies(UUID id, String name, WildcardPermission permission, Owner ownership);
} }
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.UUID;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import org.junit.Before; import org.junit.Before;
@@ -69,9 +70,10 @@ public class LoginTest {
@Test @Test
public void rolesTest() throws UserManagementException { public void rolesTest() throws UserManagementException {
store.createUser("me", "me@sap.com", "admin"); store.createUser("me", "me@sap.com", "admin");
store.addRoleForUser("me", "testrole"); UUID testId = UUID.randomUUID();
store.addRoleForUser("me", testId);
UserStoreImpl store2 = new UserStoreImpl(); UserStoreImpl store2 = new UserStoreImpl();
assertTrue(Util.contains(store2.getUserByName("me").getRoles(), "testrole")); assertTrue(Util.contains(store2.getUserByName("me").getRoles(), testId));
} }
@Test @Test
@@ -1,7 +1,8 @@
package com.sap.sse.security.ui.authentication.app; package com.sap.sse.security.ui.authentication.app;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashMap;
import java.util.UUID;
import com.sap.sse.security.ui.shared.AccountDTO; import com.sap.sse.security.ui.shared.AccountDTO;
import com.sap.sse.security.ui.shared.RolePermissionModelDTO; import com.sap.sse.security.ui.shared.RolePermissionModelDTO;
@@ -14,7 +15,7 @@ public class AuthenticationContextImpl implements AuthenticationContext {
private final UserDTO currentUser; private final UserDTO currentUser;
private final static UserDTO ANONYMOUS = new UserDTO("Anonymous", "", "", "", null, false, new ArrayList<AccountDTO>(), private final static UserDTO ANONYMOUS = new UserDTO("Anonymous", "", "", "", null, false, new ArrayList<AccountDTO>(),
new ArrayList<String>(), new RolePermissionModelDTO(new HashSet<>()), new ArrayList<String>()); new ArrayList<UUID>(), new RolePermissionModelDTO(new HashMap<>()), new ArrayList<String>());
/** /**
* Creating an {@link AuthenticationContextImpl} containing an anonymous {@link UserDTO} object. * Creating an {@link AuthenticationContextImpl} containing an anonymous {@link UserDTO} object.
@@ -9,7 +9,6 @@ import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.security.shared.Permission; import com.sap.sse.security.shared.Permission;
import com.sap.sse.security.shared.PermissionsForRoleProvider;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext; import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext; import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
import com.sap.sse.security.ui.client.i18n.StringMessages; import com.sap.sse.security.ui.client.i18n.StringMessages;
@@ -20,13 +19,11 @@ import com.sap.sse.security.ui.client.i18n.StringMessages;
* *
*/ */
public class AuthorizedContentDecorator extends Composite implements RequiresResize, NeedsAuthenticationContext { public class AuthorizedContentDecorator extends Composite implements RequiresResize, NeedsAuthenticationContext {
private final SimplePanel contentHolder = new SimplePanel(); private final SimplePanel contentHolder = new SimplePanel();
private Widget content; private Widget content;
private WidgetFactory contentWidgetFactory; private WidgetFactory contentWidgetFactory;
private final NotLoggedInView notLoggedInView; private final NotLoggedInView notLoggedInView;
private String permissionToCheck; private String permissionToCheck;
private PermissionsForRoleProvider permissionsForRoleProvider;
public AuthorizedContentDecorator(NotLoggedInPresenter presenter, NotLoggedInView notLoggedInView) { public AuthorizedContentDecorator(NotLoggedInPresenter presenter, NotLoggedInView notLoggedInView) {
this.notLoggedInView = notLoggedInView; this.notLoggedInView = notLoggedInView;
@@ -116,13 +113,6 @@ public class AuthorizedContentDecorator extends Composite implements RequiresRes
|| userManagementContext.getCurrentUser().hasPermission(permissionToCheck); || userManagementContext.getCurrentUser().hasPermission(permissionToCheck);
} }
/**
* @param permissionsForRoleProvider the PermissionsForRoleProvider used when checking the required permission of a user.
*/
public void setPermissionsForRoleProvider(PermissionsForRoleProvider permissionsForRoleProvider) {
this.permissionsForRoleProvider = permissionsForRoleProvider;
}
/** /**
* Setting a permission causes that the user not only needs to be logged in but also needs to have the given permission. * Setting a permission causes that the user not only needs to be logged in but also needs to have the given permission.
* *
@@ -140,16 +130,4 @@ public class AuthorizedContentDecorator extends Composite implements RequiresRes
public void setPermissionToCheck(Permission permissionToCheck) { public void setPermissionToCheck(Permission permissionToCheck) {
setPermissionToCheck(permissionToCheck.getStringPermission()); setPermissionToCheck(permissionToCheck.getStringPermission());
} }
/**
* Setting a permission causes that the user not only needs to be logged in but also needs to have the given permission.
*
* @param permissionToCheck the permission to check
* @param permissionsForRoleProvider the PermissionsForRoleProvider used when checking the required permission of a user.
*/
public void setPermissionToCheck(Permission permissionToCheck, PermissionsForRoleProvider permissionsForRoleProvider) {
setPermissionToCheck(permissionToCheck);
setPermissionsForRoleProvider(permissionsForRoleProvider);
}
} }
@@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteService;
import com.sap.sse.common.mail.MailException; import com.sap.sse.common.mail.MailException;
@@ -71,7 +72,7 @@ public interface UserManagementService extends RemoteService {
SuccessInfo logout(); SuccessInfo logout();
SuccessInfo setRolesForUser(String username, Iterable<String> roles); SuccessInfo setRolesForUser(String username, Iterable<UUID> roles);
SuccessInfo setPermissionsForUser(String username, Iterable<String> permissions); SuccessInfo setPermissionsForUser(String username, Iterable<String> permissions);
@@ -32,6 +32,7 @@ import com.sap.sse.security.shared.Permission;
import com.sap.sse.security.shared.PermissionsForRoleProvider; import com.sap.sse.security.shared.PermissionsForRoleProvider;
import com.sap.sse.security.shared.Role; import com.sap.sse.security.shared.Role;
import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.ui.client.IconResources; import com.sap.sse.security.ui.client.IconResources;
import com.sap.sse.security.ui.client.UserChangeEventHandler; import com.sap.sse.security.ui.client.UserChangeEventHandler;
import com.sap.sse.security.ui.client.UserManagementServiceAsync; import com.sap.sse.security.ui.client.UserManagementServiceAsync;
@@ -75,7 +76,7 @@ public class UserDetailsView extends FlowPanel {
for (Permission permission : additionalPermissions) { for (Permission permission : additionalPermissions) {
defaultPermissionNames.add(permission.getStringPermission()); defaultPermissionNames.add(permission.getStringPermission());
} }
rolesEditor = new StringListEditorComposite(user==null?Collections.<String>emptySet():user.getRoles(), stringMessages, com.sap.sse.gwt.client.IconResources.INSTANCE.removeIcon(), defaultRoleNames, rolesEditor = new StringListEditorComposite(user==null?Collections.<String>emptySet():user.getStringRoles(), stringMessages, com.sap.sse.gwt.client.IconResources.INSTANCE.removeIcon(), defaultRoleNames,
stringMessages.enterRoleName()); stringMessages.enterRoleName());
rolesEditor.addValueChangeHandler(new ValueChangeHandler<Iterable<String>>() { rolesEditor.addValueChangeHandler(new ValueChangeHandler<Iterable<String>>() {
@Override @Override
@@ -254,11 +255,11 @@ public class UserDetailsView extends FlowPanel {
} }
accountPanels.add(accountPanelDecorator); accountPanels.add(accountPanelDecorator);
} }
rolesEditor.setValue(user.getRoles(), /* fireEvents */ false); rolesEditor.setValue(user.getStringRoles(), /* fireEvents */ false);
permissionsEditor.setValue(user.getStringPermissions(), /* fireEvents */ false); permissionsEditor.setValue(user.getStringPermissions(), /* fireEvents */ false);
allPermissionsList.clear(); allPermissionsList.clear();
for (String permission : user.getAllPermissions(permissionForRoleProvider)) { for (WildcardPermission permission : user.getAllPermissions(permissionForRoleProvider)) {
allPermissionsList.addItem(permission); allPermissionsList.addItem(permission.toString());
} }
} }
} }
@@ -332,7 +332,7 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
public void updateSimpleUserPassword(final String username, String oldPassword, String passwordResetSecret, String newPassword) throws UserManagementException { public void updateSimpleUserPassword(final String username, String oldPassword, String passwordResetSecret, String newPassword) throws UserManagementException {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
// the signed-in subject has role ADMIN // the signed-in subject has role ADMIN
if (subject.hasRole(AdminRole.getInstance().getDisplayName()) if (subject.hasRole(AdminRole.getInstance().getName())
// someone knew a username and the correct password for that user // someone knew a username and the correct password for that user
|| (oldPassword != null && getSecurityService().checkPassword(username, oldPassword)) || (oldPassword != null && getSecurityService().checkPassword(username, oldPassword))
// someone provided the correct password reset secret for the correct username // someone provided the correct password reset secret for the correct username
@@ -355,7 +355,7 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
private void ensureThatUserInQuestionIsLoggedInOrCurrentUserIsAdmin(String username) throws UserManagementException { private void ensureThatUserInQuestionIsLoggedInOrCurrentUserIsAdmin(String username) throws UserManagementException {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
// the signed-in subject has role ADMIN or is changing own user // the signed-in subject has role ADMIN or is changing own user
if (!subject.hasRole(AdminRole.getInstance().getDisplayName()) && (subject.getPrincipal() == null if (!subject.hasRole(AdminRole.getInstance().getName()) && (subject.getPrincipal() == null
|| !username.equals(subject.getPrincipal().toString()))) { || !username.equals(subject.getPrincipal().toString()))) {
throw new UserManagementException(UserManagementException.INVALID_CREDENTIALS); throw new UserManagementException(UserManagementException.INVALID_CREDENTIALS);
} }
@@ -410,23 +410,23 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
} }
@Override @Override
public SuccessInfo setRolesForUser(String username, Iterable<String> roles) { public SuccessInfo setRolesForUser(String username, Iterable<UUID> roles) {
Subject currentSubject = SecurityUtils.getSubject(); Subject currentSubject = SecurityUtils.getSubject();
if (currentSubject.hasRole(AdminRole.getInstance().getDisplayName())) { if (currentSubject.hasRole(AdminRole.getInstance().getName())) {
User u = getSecurityService().getUserByName(username); User u = getSecurityService().getUserByName(username);
if (u == null) { if (u == null) {
return new SuccessInfo(false, "User does not exist.", /* redirectURL */null, null); return new SuccessInfo(false, "User does not exist.", /* redirectURL */null, null);
} }
Set<String> rolesToRemove = new HashSet<>(); Set<UUID> rolesToRemove = new HashSet<>();
Util.addAll(u.getRoles(), rolesToRemove); Util.addAll(u.getRoles(), rolesToRemove);
Util.removeAll(roles, rolesToRemove); Util.removeAll(roles, rolesToRemove);
for (String roleToRemove : rolesToRemove) { for (UUID roleToRemove : rolesToRemove) {
getSecurityService().removeRoleFromUser(username, roleToRemove); getSecurityService().removeRoleFromUser(username, roleToRemove);
} }
Set<String> rolesToAdd = new HashSet<>(); Set<UUID> rolesToAdd = new HashSet<>();
Util.addAll(roles, rolesToAdd); Util.addAll(roles, rolesToAdd);
Util.removeAll(u.getRoles(), rolesToAdd); Util.removeAll(u.getRoles(), rolesToAdd);
for (String roleToAdd : rolesToAdd) { for (UUID roleToAdd : rolesToAdd) {
getSecurityService().addRoleForUser(username, roleToAdd); getSecurityService().addRoleForUser(username, roleToAdd);
} }
return new SuccessInfo(true, "Set roles " + roles + " for user " + username, /* redirectURL */null, return new SuccessInfo(true, "Set roles " + roles + " for user " + username, /* redirectURL */null,
@@ -439,7 +439,7 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
@Override @Override
public SuccessInfo setPermissionsForUser(String username, Iterable<String> permissions) { public SuccessInfo setPermissionsForUser(String username, Iterable<String> permissions) {
Subject currentSubject = SecurityUtils.getSubject(); Subject currentSubject = SecurityUtils.getSubject();
if (currentSubject.hasRole(AdminRole.getInstance().getDisplayName()) || currentSubject.isPermitted(Permission.MANAGE_USERS.getStringPermissionForObjects(DefaultModes.UPDATE, username))) { if (currentSubject.hasRole(AdminRole.getInstance().getName()) || currentSubject.isPermitted(Permission.MANAGE_USERS.getStringPermissionForObjects(DefaultModes.UPDATE, username))) {
User u = getSecurityService().getUserByName(username); User u = getSecurityService().getUserByName(username);
if (u == null) { if (u == null) {
return new SuccessInfo(false, "User does not exist.", /* redirectURL */null, null); return new SuccessInfo(false, "User does not exist.", /* redirectURL */null, null);
@@ -493,7 +493,7 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
} }
userDTO = new UserDTO(user.getName(), user.getEmail(), user.getFullName(), user.getCompany(), userDTO = new UserDTO(user.getName(), user.getEmail(), user.getFullName(), user.getCompany(),
user.getLocale() != null ? user.getLocale().toLanguageTag() : null, user.isEmailValidated(), user.getLocale() != null ? user.getLocale().toLanguageTag() : null, user.isEmailValidated(),
accountDTOs, user.getRoles(), new RolePermissionModelDTO(new HashSet<>()), user.getPermissions()); accountDTOs, user.getRoles(), new RolePermissionModelDTO(new HashMap<>()), user.getPermissions());
return userDTO; return userDTO;
} }
@@ -1,38 +1,51 @@
package com.sap.sse.security.ui.shared; package com.sap.sse.security.ui.shared;
import java.util.Set; import java.util.Map;
import java.util.UUID;
import com.google.gwt.user.client.rpc.IsSerializable; import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sse.security.shared.Owner; import com.sap.sse.security.shared.Owner;
import com.sap.sse.security.shared.Role;
import com.sap.sse.security.shared.RolePermissionModel; import com.sap.sse.security.shared.RolePermissionModel;
import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.WildcardPermission;
public class RolePermissionModelDTO implements RolePermissionModel, IsSerializable { public class RolePermissionModelDTO implements RolePermissionModel, IsSerializable {
private Set<String> rules; private Map<UUID, Role> roles;
RolePermissionModelDTO() {} // for serialization only RolePermissionModelDTO() {} // for serialization only
public RolePermissionModelDTO(Set<String> rules) { public RolePermissionModelDTO(Map<UUID, Role> roles) {
this.rules = rules; this.roles = roles;
} }
@Override @Override
public Iterable<String> getPermissions(String role) { public String getName(UUID id) {
return rules; return roles.get(id).getName();
} }
@Override @Override
public boolean implies(String role, WildcardPermission permission) { // TODO as default implementation in interface public Iterable<WildcardPermission> getPermissions(UUID id) {
return implies(role, permission, null); return roles.get(id).getPermissions();
}
// TODO as default implementation in interface
@Override
public boolean implies(UUID id, WildcardPermission permission) {
return implies(id, permission, null);
} }
@Override @Override
public boolean implies(String role, WildcardPermission permission, Owner ownership) { // TODO as default implementation in interface public boolean implies(UUID id, WildcardPermission permission, Owner ownership) {
String[] parts = role.split(":"); return implies(id, roles.get(id).getName(), permission, ownership);
}
// TODO as default implementation in interface
@Override
public boolean implies(UUID id, String name, WildcardPermission permission, Owner ownership) {
String[] parts = name.split(":");
// if there is no parameter or the first parameter (tenant) equals the tenant owner // if there is no parameter or the first parameter (tenant) equals the tenant owner
if (parts.length < 2 || (ownership != null && ownership.getTenantOwner().equals(parts[1]))) { if (parts.length < 2 || (ownership != null && ownership.getTenantOwner().equals(parts[1]))) {
for (String rolePermissionString : getPermissions(role)) { for (WildcardPermission rolePermission : getPermissions(id)) {
WildcardPermission rolePermission = new WildcardPermission(rolePermissionString, true);
if (rolePermission.implies(permission)) { if (rolePermission.implies(permission)) {
return true; return true;
} }
@@ -5,6 +5,7 @@ import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import com.google.gwt.user.client.rpc.IsSerializable; import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sse.common.Util; import com.sap.sse.common.Util;
@@ -20,15 +21,15 @@ public class UserDTO implements IsSerializable {
private String company; private String company;
private String locale; private String locale;
private List<AccountDTO> accounts; private List<AccountDTO> accounts;
private Set<String> roles; private Set<UUID> roles;
private RolePermissionModelDTO rolePermissionModelDTO; private RolePermissionModelDTO rolePermissionModel;
private Set<WildcardPermission> permissions; private Set<WildcardPermission> permissions;
private boolean emailValidated; private boolean emailValidated;
UserDTO() {} // for serialization only UserDTO() {} // for serialization only
public UserDTO(String name, String email, String fullName, String company, String locale, boolean emailValidated, public UserDTO(String name, String email, String fullName, String company, String locale, boolean emailValidated,
List<AccountDTO> accounts, Iterable<String> roles, RolePermissionModelDTO rolePermissionModelDTO, List<AccountDTO> accounts, Iterable<UUID> roles, RolePermissionModelDTO rolePermissionModelDTO,
Iterable<String> stringPermissions) { Iterable<String> stringPermissions) {
this.name = name; this.name = name;
this.email = email; this.email = email;
@@ -39,7 +40,7 @@ public class UserDTO implements IsSerializable {
this.accounts = accounts; this.accounts = accounts;
this.roles = new HashSet<>(); this.roles = new HashSet<>();
Util.addAll(roles, this.roles); Util.addAll(roles, this.roles);
this.rolePermissionModelDTO = rolePermissionModelDTO; this.rolePermissionModel = rolePermissionModelDTO;
this.permissions = new HashSet<>(); this.permissions = new HashSet<>();
for (String permission : stringPermissions) { for (String permission : stringPermissions) {
this.permissions.add(new WildcardPermission(permission, true)); this.permissions.add(new WildcardPermission(permission, true));
@@ -62,10 +63,18 @@ public class UserDTO implements IsSerializable {
return locale; return locale;
} }
public Iterable<String> getRoles() { public Iterable<UUID> getRoles() {
return roles; return roles;
} }
public Iterable<String> getStringRoles() {
ArrayList<String> result = new ArrayList<>();
for (UUID id : roles) {
result.add(rolePermissionModel.getName(id));
}
return result;
}
public boolean hasRole(String role) { public boolean hasRole(String role) {
return roles.contains(role); return roles.contains(role);
} }
@@ -102,12 +111,12 @@ public class UserDTO implements IsSerializable {
* @return a set of permissions with no duplicates, all in the format parsable by * @return a set of permissions with no duplicates, all in the format parsable by
* {@link WildcardPermission#WildcardPermission(String)} * {@link WildcardPermission#WildcardPermission(String)}
*/ */
public Iterable<String> getAllPermissions(PermissionsForRoleProvider permissionsForRoleProvider) { public Iterable<WildcardPermission> getAllPermissions(PermissionsForRoleProvider permissionsForRoleProvider) {
Set<String> result = new LinkedHashSet<>(); Set<WildcardPermission> result = new LinkedHashSet<>();
Util.addAll(getStringPermissions(), result); Util.addAll(permissions, result);
if (permissionsForRoleProvider != null) { if (rolePermissionModel != null) {
for (String role : getRoles()) { for (UUID role : getRoles()) {
Util.addAll(permissionsForRoleProvider.getPermissions(role, null), result); Util.addAll(rolePermissionModel.getPermissions(role), result);
} }
} }
return result; return result;
@@ -130,7 +139,7 @@ public class UserDTO implements IsSerializable {
if (acl != null) { if (acl != null) {
userGroups = new ArrayList<>(acl.getUserGroupPermissionMap().keySet()); userGroups = new ArrayList<>(acl.getUserGroupPermissionMap().keySet());
} }
return PermissionChecker.isPermitted(permission, name, userGroups, permissions, roles, rolePermissionModelDTO, owner, acl); return PermissionChecker.isPermitted(permission, name, userGroups, permissions, roles, rolePermissionModel, owner, acl);
} }
public List<AccountDTO> getAccounts() { public List<AccountDTO> getAccounts() {
@@ -183,7 +183,7 @@ public class AccessControlStoreImpl implements AccessControlStore {
@Override @Override
public AccessControlStore setRolePermissions(UUID id, Set<WildcardPermission> permissions) { public AccessControlStore setRolePermissions(UUID id, Set<WildcardPermission> permissions) {
Role role = roleList.get(id); Role role = roleList.get(id);
role = new RoleImpl(id, role.getDisplayName(), permissions); role = new RoleImpl(id, role.getName(), permissions);
mongoObjectFactory.storeRole(role); mongoObjectFactory.storeRole(role);
return this; return this;
} }
@@ -193,7 +193,7 @@ public class AccessControlStoreImpl implements AccessControlStore {
Role role = roleList.get(id); Role role = roleList.get(id);
Set<WildcardPermission> permissions = role.getPermissions(); Set<WildcardPermission> permissions = role.getPermissions();
permissions.add(permission); permissions.add(permission);
role = new RoleImpl(id, role.getDisplayName(), permissions); role = new RoleImpl(id, role.getName(), permissions);
mongoObjectFactory.storeRole(role); mongoObjectFactory.storeRole(role);
return this; return this;
} }
@@ -203,7 +203,7 @@ public class AccessControlStoreImpl implements AccessControlStore {
Role role = roleList.get(id); Role role = roleList.get(id);
Set<WildcardPermission> permissions = role.getPermissions(); Set<WildcardPermission> permissions = role.getPermissions();
permissions.remove(permission); permissions.remove(permission);
role = new RoleImpl(id, role.getDisplayName(), permissions); role = new RoleImpl(id, role.getName(), permissions);
mongoObjectFactory.storeRole(role); mongoObjectFactory.storeRole(role);
return this; return this;
} }
@@ -249,7 +249,7 @@ public class UserStoreImpl implements UserStore {
public String getAccessToken(String username) { public String getAccessToken(String username) {
// only the user or an administrator may request a user's access token // only the user or an administrator may request a user's access token
final Object principal = SecurityUtils.getSubject().getPrincipal(); final Object principal = SecurityUtils.getSubject().getPrincipal();
if (SecurityUtils.getSubject().hasRole(AdminRole.getInstance().getDisplayName()) || if (SecurityUtils.getSubject().hasRole(AdminRole.getInstance().getName()) ||
(principal != null && principal.toString().equals(username))) { (principal != null && principal.toString().equals(username))) {
return getPreference(username, ACCESS_TOKEN_KEY); return getPreference(username, ACCESS_TOKEN_KEY);
} else { } else {
@@ -260,7 +260,7 @@ public class UserStoreImpl implements UserStore {
@Override @Override
public void removeAccessToken(String username) { public void removeAccessToken(String username) {
// only the user or an administrator may request a user's access token // only the user or an administrator may request a user's access token
if (SecurityUtils.getSubject().hasRole(AdminRole.getInstance().getDisplayName()) || if (SecurityUtils.getSubject().hasRole(AdminRole.getInstance().getName()) ||
SecurityUtils.getSubject().getPrincipal().toString().equals(username)) { SecurityUtils.getSubject().getPrincipal().toString().equals(username)) {
User user = users.get(username); User user = users.get(username);
if (user != null) { if (user != null) {
@@ -508,7 +508,7 @@ public class UserStoreImpl implements UserStore {
} }
@Override @Override
public Iterable<String> getRolesFromUser(String username) throws UserManagementException { public Iterable<UUID> getRolesFromUser(String username) throws UserManagementException {
if (users.get(username) == null) { if (users.get(username) == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST); throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
} }
@@ -516,7 +516,7 @@ public class UserStoreImpl implements UserStore {
} }
@Override @Override
public void addRoleForUser(String name, String role) throws UserManagementException { public void addRoleForUser(String name, UUID role) throws UserManagementException {
final User user = users.get(name); final User user = users.get(name);
if (user == null) { if (user == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST); throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
@@ -528,7 +528,7 @@ public class UserStoreImpl implements UserStore {
} }
@Override @Override
public void removeRoleFromUser(String name, String role) throws UserManagementException { public void removeRoleFromUser(String name, UUID role) throws UserManagementException {
if (users.get(name) == null) { if (users.get(name) == null) {
throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST); throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST);
} }
@@ -129,7 +129,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
private Role loadRole(DBObject roleDBObject) { private Role loadRole(DBObject roleDBObject) {
final String id = (String) roleDBObject.get(FieldNames.Role.ID.name()); final String id = (String) roleDBObject.get(FieldNames.Role.ID.name());
final String displayName = (String) roleDBObject.get(FieldNames.Role.DISPLAY_NAME.name()); final String displayName = (String) roleDBObject.get(FieldNames.Role.NAME.name());
final Set<WildcardPermission> permissions = new HashSet<>(); final Set<WildcardPermission> permissions = new HashSet<>();
for (Object o : (BasicDBList) roleDBObject.get(FieldNames.Role.PERMISSIONS.name())) { for (Object o : (BasicDBList) roleDBObject.get(FieldNames.Role.PERMISSIONS.name())) {
permissions.add(new WildcardPermission(o.toString(), true)); permissions.add(new WildcardPermission(o.toString(), true));
@@ -217,12 +217,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
Boolean emailValidated = (Boolean) userDBObject.get(FieldNames.User.EMAIL_VALIDATED.name()); Boolean emailValidated = (Boolean) userDBObject.get(FieldNames.User.EMAIL_VALIDATED.name());
String passwordResetSecret = (String) userDBObject.get(FieldNames.User.PASSWORD_RESET_SECRET.name()); String passwordResetSecret = (String) userDBObject.get(FieldNames.User.PASSWORD_RESET_SECRET.name());
String validationSecret = (String) userDBObject.get(FieldNames.User.VALIDATION_SECRET.name()); String validationSecret = (String) userDBObject.get(FieldNames.User.VALIDATION_SECRET.name());
Set<String> roles = new HashSet<String>(); Set<UUID> roles = new HashSet<>();
Set<String> permissions = new HashSet<String>(); Set<String> permissions = new HashSet<>();
BasicDBList rolesO = (BasicDBList) userDBObject.get(FieldNames.User.ROLES.name()); BasicDBList rolesO = (BasicDBList) userDBObject.get(FieldNames.User.ROLES.name());
if (rolesO != null) { if (rolesO != null) {
for (Object o : rolesO) { for (Object o : rolesO) {
roles.add((String) o); roles.add(UUID.fromString((String) o));
} }
} }
BasicDBList permissionsO = (BasicDBList) userDBObject.get(FieldNames.User.PERMISSIONS.name()); BasicDBList permissionsO = (BasicDBList) userDBObject.get(FieldNames.User.PERMISSIONS.name());
@@ -234,7 +234,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
DBObject accountsMap = (DBObject) userDBObject.get(FieldNames.User.ACCOUNTS.name()); DBObject accountsMap = (DBObject) userDBObject.get(FieldNames.User.ACCOUNTS.name());
Map<AccountType, Account> accounts = createAccountMapFromdDBObject(accountsMap); Map<AccountType, Account> accounts = createAccountMapFromdDBObject(accountsMap);
User result = new User(name, email, fullName, company, locale, emailValidated==null?false:emailValidated, passwordResetSecret, validationSecret, accounts.values()); User result = new User(name, email, fullName, company, locale, emailValidated==null?false:emailValidated, passwordResetSecret, validationSecret, accounts.values());
for (String role : roles) { for (UUID role : roles) {
result.addRole(role); result.addRole(role);
} }
for (String permission : permissions) { for (String permission : permissions) {
@@ -17,7 +17,7 @@ public class FieldNames {
public static enum Role { public static enum Role {
ID, ID,
DISPLAY_NAME, NAME,
PERMISSIONS PERMISSIONS
} }
@@ -91,7 +91,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBObject dbRole = new BasicDBObject(); DBObject dbRole = new BasicDBObject();
DBObject query = new BasicDBObject(FieldNames.Role.ID.name(), role.getId().toString()); DBObject query = new BasicDBObject(FieldNames.Role.ID.name(), role.getId().toString());
dbRole.put(FieldNames.Role.ID.name(), role.getId().toString()); dbRole.put(FieldNames.Role.ID.name(), role.getId().toString());
dbRole.put(FieldNames.Role.DISPLAY_NAME.name(), role.getDisplayName()); dbRole.put(FieldNames.Role.NAME.name(), role.getName());
HashSet<String> stringPermissions = new HashSet<>(); HashSet<String> stringPermissions = new HashSet<>();
for (WildcardPermission permission : role.getPermissions()) { for (WildcardPermission permission : role.getPermissions()) {
stringPermissions.add(permission.toString()); stringPermissions.add(permission.toString());
@@ -161,7 +161,11 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
dbUser.put(FieldNames.User.PASSWORD_RESET_SECRET.name(), user.getPasswordResetSecret()); dbUser.put(FieldNames.User.PASSWORD_RESET_SECRET.name(), user.getPasswordResetSecret());
dbUser.put(FieldNames.User.VALIDATION_SECRET.name(), user.getValidationSecret()); dbUser.put(FieldNames.User.VALIDATION_SECRET.name(), user.getValidationSecret());
dbUser.put(FieldNames.User.ACCOUNTS.name(), createAccountMapObject(user.getAllAccounts())); dbUser.put(FieldNames.User.ACCOUNTS.name(), createAccountMapObject(user.getAllAccounts()));
dbUser.put(FieldNames.User.ROLES.name(), user.getRoles()); HashSet<String> roles = new HashSet<>();
for (UUID id : user.getRoles()) {
roles.add(id.toString());
}
dbUser.put(FieldNames.User.ROLES.name(), roles);
dbUser.put(FieldNames.User.PERMISSIONS.name(), user.getPermissions()); dbUser.put(FieldNames.User.PERMISSIONS.name(), user.getPermissions());
usersCollection.update(query, dbUser, /* upsrt */true, /* multi */false, WriteConcern.SAFE); usersCollection.update(query, dbUser, /* upsrt */true, /* multi */false, WriteConcern.SAFE);
} }
@@ -3,6 +3,7 @@ package com.sap.sse.security;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@@ -21,7 +22,7 @@ import org.osgi.util.tracker.ServiceTracker;
import com.sap.sse.security.impl.Activator; import com.sap.sse.security.impl.Activator;
import com.sap.sse.security.shared.Owner; import com.sap.sse.security.shared.Owner;
import com.sap.sse.security.shared.PermissionChecker; import com.sap.sse.security.shared.PermissionChecker;
import com.sap.sse.security.shared.PermissionsForRoleProvider; import com.sap.sse.security.shared.Role;
import com.sap.sse.security.shared.RolePermissionModel; import com.sap.sse.security.shared.RolePermissionModel;
import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.WildcardPermission;
@@ -30,7 +31,6 @@ public abstract class AbstractCompositeAuthrizingRealm extends AuthorizingRealm
private static final Logger logger = Logger.getLogger(AbstractCompositeAuthrizingRealm.class.getName()); private static final Logger logger = Logger.getLogger(AbstractCompositeAuthrizingRealm.class.getName());
private final Future<UserStore> userStore; private final Future<UserStore> userStore;
private final Future<AccessControlStore> aclStore; private final Future<AccessControlStore> aclStore;
private PermissionsForRoleProvider permissionsForRoleProvider;
/** /**
* In a non-OSGi test environment, having Shiro instantiate this class with a default constructor makes it difficult * In a non-OSGi test environment, having Shiro instantiate this class with a default constructor makes it difficult
@@ -61,10 +61,6 @@ public abstract class AbstractCompositeAuthrizingRealm extends AuthorizingRealm
aclStore = null; aclStore = null;
} }
} }
public void setPermissionsForRoleProvider(PermissionsForRoleProvider permissionsForRoleProvider) {
this.permissionsForRoleProvider = permissionsForRoleProvider;
}
private Future<UserStore> createUserStoreFuture(BundleContext bundleContext) { private Future<UserStore> createUserStoreFuture(BundleContext bundleContext) {
final ServiceTracker<UserStore, UserStore> tracker = new ServiceTracker<>(bundleContext, UserStore.class, /* customizer */ null); final ServiceTracker<UserStore, UserStore> tracker = new ServiceTracker<>(bundleContext, UserStore.class, /* customizer */ null);
@@ -213,8 +209,8 @@ public abstract class AbstractCompositeAuthrizingRealm extends AuthorizingRealm
public boolean hasRole(PrincipalCollection principal, String roleIdentifier) { public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
String user = (String) principal.getPrimaryPrincipal(); String user = (String) principal.getPrimaryPrincipal();
try { try {
for (String role : getUserStore().getRolesFromUser(user)) { for (UUID role : getUserStore().getRolesFromUser(user)) {
if (role.equals(roleIdentifier)) { if (role.equals(UUID.fromString(roleIdentifier))) {
return true; return true;
} }
} }
@@ -266,23 +262,58 @@ public abstract class AbstractCompositeAuthrizingRealm extends AuthorizingRealm
return null; // As all the public methods of AuthorizingRealm are overridden to not use this, this should never be called. return null; // As all the public methods of AuthorizingRealm are overridden to not use this, this should never be called.
} }
@Override private Role getRole(UUID id) {
public Iterable<String> getPermissions(String role) { try {
return permissionsForRoleProvider.getPermissions(role, null); return aclStore.get().getRole(id);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
return null;
}
} }
@Override @Override
public boolean implies(String role, WildcardPermission permission) { // TODO as default implementation in interface public String getName(UUID id) {
return implies(role, permission, null); Role role = getRole(id);
if (role != null) {
return role.getName();
} else {
return "";
}
} }
@Override @Override
public boolean implies(String role, WildcardPermission permission, Owner ownership) { // TODO as default implementation in interface public Iterable<WildcardPermission> getPermissions(UUID id) {
String[] parts = role.split(":"); Role role = getRole(id);
if (role != null) {
return role.getPermissions();
} else {
return new ArrayList<>();
}
}
// TODO as default implementation in interface
@Override
public boolean implies(UUID id, WildcardPermission permission) {
return implies(id, permission, null);
}
@Override
public boolean implies(UUID id, WildcardPermission permission, Owner ownership) {
Role role = getRole(id);
if (role != null) {
return implies(id, role.getName(), permission, ownership);
} else {
return false;
}
}
// TODO as default implementation in interface
@Override
public boolean implies(UUID id, String name, WildcardPermission permission, Owner ownership) {
String[] parts = name.split(":");
// if there is no parameter or the first parameter (tenant) equals the tenant owner // if there is no parameter or the first parameter (tenant) equals the tenant owner
if (parts.length < 2 || (ownership != null && ownership.getTenantOwner().equals(parts[1]))) { if (parts.length < 2 || (ownership != null && ownership.getTenantOwner().equals(parts[1]))) {
for (String rolePermissionString : getPermissions(role)) { for (WildcardPermission rolePermission : getPermissions(id)) {
WildcardPermission rolePermission = new WildcardPermission(rolePermissionString, true);
if (rolePermission.implies(permission)) { if (rolePermission.implies(permission)) {
return true; return true;
} }
@@ -30,5 +30,4 @@ public class BearerTokenRealm extends AbstractCompositeAuthrizingRealm {
SaltedAuthenticationInfo sai = new SimpleSaltedAuthenticationInfo(user.getName(), accessToken.getCredentials(), /* salt */ null); SaltedAuthenticationInfo sai = new SimpleSaltedAuthenticationInfo(user.getName(), accessToken.getCredentials(), /* salt */ null);
return sai; return sai;
} }
} }
@@ -134,11 +134,11 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
void deleteUser(String username) throws UserManagementException; void deleteUser(String username) throws UserManagementException;
Iterable<String> getRolesFromUser(String username) throws UserManagementException; Iterable<UUID> getRolesFromUser(String username) throws UserManagementException;
void addRoleForUser(String username, String role); void addRoleForUser(String username, UUID role);
void removeRoleFromUser(String username, String role); void removeRoleFromUser(String username, UUID role);
Iterable<String> getPermissionsFromUser(String username) throws UserManagementException; Iterable<String> getPermissionsFromUser(String username) throws UserManagementException;
@@ -10,6 +10,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import org.apache.shiro.crypto.hash.Sha256Hash; import org.apache.shiro.crypto.hash.Sha256Hash;
@@ -64,7 +65,7 @@ public class User implements NamedWithID {
private boolean emailValidated; private boolean emailValidated;
private final Set<String> roles; private final Set<UUID> roles;
private final Set<String> permissions; private final Set<String> permissions;
private final Map<AccountType, Account> accounts; private final Map<AccountType, Account> accounts;
@@ -136,19 +137,19 @@ public class User implements NamedWithID {
return locale == null ? Locale.ENGLISH : locale; return locale == null ? Locale.ENGLISH : locale;
} }
public Iterable<String> getRoles() { public Iterable<UUID> getRoles() {
return roles; return roles;
} }
public void addRole(String role) { public void addRole(UUID role) {
roles.add(role); roles.add(role);
} }
public boolean hasRole(String role) { public boolean hasRole(UUID role) {
return roles.contains(role); return roles.contains(role);
} }
public void removeRole(String role) { public void removeRole(UUID role) {
roles.remove(role); roles.remove(role);
} }
@@ -55,11 +55,11 @@ public interface UserStore extends Named {
void updateUser(User user); void updateUser(User user);
Iterable<String> getRolesFromUser(String username) throws UserManagementException; Iterable<UUID> getRolesFromUser(String username) throws UserManagementException;
void addRoleForUser(String name, String role) throws UserManagementException; void addRoleForUser(String name, UUID role) throws UserManagementException;
void removeRoleFromUser(String name, String role) throws UserManagementException; void removeRoleFromUser(String name, UUID role) throws UserManagementException;
Iterable<String> getPermissionsFromUser(String username) throws UserManagementException; Iterable<String> getPermissionsFromUser(String username) throws UserManagementException;
@@ -63,9 +63,9 @@ public interface ReplicableSecurityService extends SecurityService {
Void internalAddSetting(String key, Class<?> clazz); Void internalAddSetting(String key, Class<?> clazz);
Void internalAddRoleForUser(String username, String role) throws UserManagementException; Void internalAddRoleForUser(String username, UUID role) throws UserManagementException;
Void internalRemoveRoleFromUser(String username, String role) throws UserManagementException; Void internalRemoveRoleFromUser(String username, UUID role) throws UserManagementException;
Void internalAddPermissionForUser(String username, String permissionToAdd) throws UserManagementException; Void internalAddPermissionForUser(String username, String permissionToAdd) throws UserManagementException;
@@ -207,7 +207,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
logger.info("No users found, creating default user \"admin\" with password \"admin\""); logger.info("No users found, creating default user \"admin\" with password \"admin\"");
createSimpleUser("admin", "nobody@sapsailing.com", "admin", createSimpleUser("admin", "nobody@sapsailing.com", "admin",
/* fullName */ null, /* company */ null, /* validationBaseURL */ null); /* fullName */ null, /* company */ null, /* validationBaseURL */ null);
addRoleForUser("admin", AdminRole.getInstance().getDisplayName()); addRoleForUser("admin", (UUID) AdminRole.getInstance().getId());
} catch (UserManagementException | MailException e) { } catch (UserManagementException | MailException e) {
logger.log(Level.SEVERE, "Exception while creating default admin user", e); logger.log(Level.SEVERE, "Exception while creating default admin user", e);
} }
@@ -223,7 +223,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
Set<String> adminPermissions = new HashSet<>(); Set<String> adminPermissions = new HashSet<>();
adminPermissions.add("*"); adminPermissions.add("*");
AdminRole role = AdminRole.getInstance(); AdminRole role = AdminRole.getInstance();
aclStore.createRole((UUID) role.getId(), role.getDisplayName(), role.getPermissions()); aclStore.createRole((UUID) role.getId(), role.getName(), role.getPermissions());
} }
} }
@@ -748,28 +748,28 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
} }
@Override @Override
public Iterable<String> getRolesFromUser(String name) throws UserManagementException { public Iterable<UUID> getRolesFromUser(String name) throws UserManagementException {
return userStore.getRolesFromUser(name); return userStore.getRolesFromUser(name);
} }
@Override @Override
public void addRoleForUser(String username, String role) { public void addRoleForUser(String username, UUID role) {
apply(s->s.internalAddRoleForUser(username, role)); apply(s->s.internalAddRoleForUser(username, role));
} }
@Override @Override
public Void internalAddRoleForUser(String username, String role) throws UserManagementException { public Void internalAddRoleForUser(String username, UUID role) throws UserManagementException {
userStore.addRoleForUser(username, role); userStore.addRoleForUser(username, role);
return null; return null;
} }
@Override @Override
public void removeRoleFromUser(String username, String role) { public void removeRoleFromUser(String username, UUID role) {
apply(s->s.internalRemoveRoleFromUser(username, role)); apply(s->s.internalRemoveRoleFromUser(username, role));
} }
@Override @Override
public Void internalRemoveRoleFromUser(String username, String role) throws UserManagementException { public Void internalRemoveRoleFromUser(String username, UUID role) throws UserManagementException {
userStore.removeRoleFromUser(username, role); userStore.removeRoleFromUser(username, role);
return null; return null;
} }
@@ -1127,7 +1127,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
private void ensureThatUserInQuestionIsLoggedInOrCurrentUserIsAdmin(String username) { private void ensureThatUserInQuestionIsLoggedInOrCurrentUserIsAdmin(String username) {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
if (!subject.hasRole(AdminRole.getInstance().getDisplayName()) && (subject.getPrincipal() == null if (!subject.hasRole(AdminRole.getInstance().getName()) && (subject.getPrincipal() == null
|| !username.equals(subject.getPrincipal().toString()))) { || !username.equals(subject.getPrincipal().toString()))) {
final String currentUserName = subject.getPrincipal() == null ? "<anonymous>" final String currentUserName = subject.getPrincipal() == null ? "<anonymous>"
: subject.getPrincipal().toString(); : subject.getPrincipal().toString();
@@ -1228,7 +1228,7 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
@Override @Override
public void removeAccessToken(String username) { public void removeAccessToken(String username) {
Subject subject = SecurityUtils.getSubject(); Subject subject = SecurityUtils.getSubject();
if (subject.hasRole(AdminRole.getInstance().getDisplayName()) || username.equals(subject.getPrincipal().toString())) { if (subject.hasRole(AdminRole.getInstance().getName()) || username.equals(subject.getPrincipal().toString())) {
apply(s -> s.internalRemoveAccessToken(username)); apply(s -> s.internalRemoveAccessToken(username));
} else { } else {
throw new org.apache.shiro.authz.AuthorizationException("User " + subject.getPrincipal().toString() throw new org.apache.shiro.authz.AuthorizationException("User " + subject.getPrincipal().toString()
@@ -68,7 +68,7 @@ public class SecurityResource extends AbstractSecurityResource {
@Produces("text/plain;charset=UTF-8") @Produces("text/plain;charset=UTF-8")
public Response changePassword(@FormParam("username") String username, @FormParam("password") String password) { public Response changePassword(@FormParam("username") String username, @FormParam("password") String password) {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
if (!subject.hasRole(AdminRole.getInstance().getDisplayName()) && (subject.getPrincipal() == null if (!subject.hasRole(AdminRole.getInstance().getName()) && (subject.getPrincipal() == null
|| !username.equals(subject.getPrincipal().toString()))) { || !username.equals(subject.getPrincipal().toString()))) {
return Response.status(Status.UNAUTHORIZED).build(); return Response.status(Status.UNAUTHORIZED).build();
} else { } else {
@@ -144,7 +144,7 @@ public class SecurityResource extends AbstractSecurityResource {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
// ADMIN can query all; otherwise, only the owning user can query // ADMIN can query all; otherwise, only the owning user can query
// TODO: ideally, we would introduce a USER:READ:<username> permission which later can be granted to tenant admins for all users of that tenant // TODO: ideally, we would introduce a USER:READ:<username> permission which later can be granted to tenant admins for all users of that tenant
if (subject.getPrincipal() == null || (username != null && !subject.hasRole(AdminRole.getInstance().getDisplayName()))) { if (subject.getPrincipal() == null || (username != null && !subject.hasRole(AdminRole.getInstance().getName()))) {
return Response.status(Status.UNAUTHORIZED).build(); return Response.status(Status.UNAUTHORIZED).build();
} else { } else {
final User user = getService().getUserByName(username == null ? subject.getPrincipal().toString() : username); final User user = getService().getUserByName(username == null ? subject.getPrincipal().toString() : username);
@@ -167,7 +167,7 @@ public class SecurityResource extends AbstractSecurityResource {
public Response deleteUser(@QueryParam("username") String username) { public Response deleteUser(@QueryParam("username") String username) {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
// the signed-in subject has role ADMIN // the signed-in subject has role ADMIN
if (!subject.hasRole(AdminRole.getInstance().getDisplayName()) && (subject.getPrincipal() == null if (!subject.hasRole(AdminRole.getInstance().getName()) && (subject.getPrincipal() == null
|| !username.equals(subject.getPrincipal().toString()))) { || !username.equals(subject.getPrincipal().toString()))) {
return Response.status(Status.UNAUTHORIZED).build(); return Response.status(Status.UNAUTHORIZED).build();
} else { } else {
@@ -188,7 +188,7 @@ public class SecurityResource extends AbstractSecurityResource {
@QueryParam("company") String company) { @QueryParam("company") String company) {
final Subject subject = SecurityUtils.getSubject(); final Subject subject = SecurityUtils.getSubject();
// the signed-in subject has role ADMIN // the signed-in subject has role ADMIN
if (!subject.hasRole(AdminRole.getInstance().getDisplayName()) && (subject.getPrincipal() == null if (!subject.hasRole(AdminRole.getInstance().getName()) && (subject.getPrincipal() == null
|| !username.equals(subject.getPrincipal().toString()))) { || !username.equals(subject.getPrincipal().toString()))) {
return Response.status(Status.UNAUTHORIZED).build(); return Response.status(Status.UNAUTHORIZED).build();
} else { } else {