more consistent user/group/tenant handling and serialization

Change-Id: Ib7621e2cbddb913db0e32e2607d122e38505d87b
This commit is contained in:
Axel Uhl
2017-12-12 18:25:41 +01:00
parent 0ef04ce1a4
commit 55e6297f55
21 changed files with 201 additions and 57 deletions
@@ -1,7 +1,6 @@
package com.sap.sailing.domain.common.security;
import com.sap.sse.security.shared.WildcardPermission;
public enum Permission implements com.sap.sse.security.shared.Permission {
// AdminConsole permissions
@@ -63,6 +62,11 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
return result;
}
@Override
public WildcardPermission getPermission(com.sap.sse.security.shared.Permission.Mode... modes) {
return new WildcardPermission(getStringPermission(modes));
}
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
@Override
public String getStringPermissionForObjects(com.sap.sse.security.shared.Permission.Mode mode, String... objectIdentifiers) {
@@ -82,6 +86,11 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
return result.toString();
}
@Override
public WildcardPermission getPermissionForObjects(com.sap.sse.security.shared.Permission.Mode mode, String... objectIdentifiers) {
return new WildcardPermission(getStringPermissionForObjects(mode, objectIdentifiers));
}
/**
* The mode of interaction with a resource; used as the second element of a wildcard permission
*
@@ -352,11 +352,12 @@ public class EventListComposite extends Composite implements EventsRefresher, Le
public Iterable<Action> getAllowedActions(EventDTO event) {
ArrayList<Action> allowedActions = new ArrayList<>();
for (Action action : Arrays.asList(DefaultActions.EDIT, DefaultActions.REMOVE)) {
if (user.hasPermission(
PermissionBuilderImpl.getInstance().getPermission("com.sap.sailing.domain.base.Event", action, event.id.toString()),
event.getAcl(), event.getOwnership())) {
allowedActions.add(action);
}
if (user.hasPermission(
PermissionBuilderImpl.getInstance().getPermission(
"com.sap.sailing.domain.base.Event", action, event.id.toString()),
event.getOwnership(), event.getAcl())) {
allowedActions.add(action);
}
}
return allowedActions;
}
@@ -60,7 +60,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
@Override
public void onUserStatusChange(UserDTO user, boolean preAuthenticated) {
RaceTimePanel.this.hasCanReplayDuringLiveRacesPermission = user != null && user.hasPermission(
Permission.CAN_REPLAY_DURING_LIVE_RACES.getStringPermission());
Permission.CAN_REPLAY_DURING_LIVE_RACES.getPermission(), /* TODO race ownership */ null, /* TODO race acl */ null);
}
};
@@ -489,7 +489,7 @@ public class MediaPlayerManagerComponent extends AbstractComponent<MediaPlayerSe
final VideoSynchPlayer videoPlayer;
final UserDTO currentUser = userService.getCurrentUser();
boolean showSynchControls = currentUser != null
&& currentUser.hasPermission(Permission.MANAGE_MEDIA.getStringPermission());
&& currentUser.hasPermission(Permission.MANAGE_MEDIA.getPermission(), /* TODO race ownership */ null, /* TODO race ACL */ null);
if (videoTrack.isYoutube()) {
videoPlayer = new VideoYoutubePlayer(videoTrack, getRaceStartTime(), showSynchControls, raceTimer);
} else {
@@ -673,7 +673,7 @@ public class MediaPlayerManagerComponent extends AbstractComponent<MediaPlayerSe
public boolean allowsEditing() {
UserDTO currentUser = userService.getCurrentUser();
return currentUser != null
&& currentUser.hasPermission(Permission.MANAGE_MEDIA.getStringPermission());
&& currentUser.hasPermission(Permission.MANAGE_MEDIA.getPermission(), /* TODO race ownership */ null, /* TODO race ACL */ null);
}
@Override
@@ -307,7 +307,7 @@ public class SideBySideComponentViewer implements UserStatusEventHandler {
final Splitter markPassingsSplitter = splitLayoutPanel.getAssociatedSplitter(markPassingsPanel);
final Splitter markPositionSplitter = splitLayoutPanel.getAssociatedSplitter(markPositionPanel);
boolean forceLayout = false;
if (user != null && user.hasPermission(Permission.MANAGE_MARK_PASSINGS.getStringPermission())) {
if (user != null && user.hasPermission(Permission.MANAGE_MARK_PASSINGS.getPermission(), /* TODO race ownership */ null, /* TODO race acl */ null)) {
if (markPassingsSplitter != null) { // if the panel is not present, the splitter may not be found
markPassingsSplitter.getToggleButton().setVisible(true);
}
@@ -318,7 +318,7 @@ public class SideBySideComponentViewer implements UserStatusEventHandler {
markPassingsSplitter.getToggleButton().setVisible(false);
}
}
if (user != null && user.hasPermission(Permission.MANAGE_MARK_POSITIONS.getStringPermission())) {
if (user != null && user.hasPermission(Permission.MANAGE_MARK_POSITIONS.getPermission(), /* TODO race ownership */ null, /* TODO race acl */ null)) {
if (markPositionSplitter != null) { // if the panel is not present, the splitter may not be found
markPositionSplitter.getToggleButton().setVisible(true);
}
@@ -191,7 +191,7 @@ public class EventsResource extends AbstractSailingServerResource {
@FormParam("numberofraces") String numberOfRacesParam) throws ParseException, NotFoundException,
NumberFormatException, IOException, org.json.simple.parser.ParseException, InvalidDateException {
if (enforceSecurityChecks) {
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermission(Mode.CREATE));
SecurityUtils.getSubject().checkPermission(Permission.EVENT.getStringPermissionForObjects(Mode.CREATE, eventId));
}
final Response response;
UUID id;
@@ -441,7 +441,7 @@ public class AdminConsolePanel extends HeaderPanel implements HandleTabSelectabl
*/
private boolean userHasPermissionsToSeeWidget(UserDTO user, Widget widget) {
for (Permission requiredStringPermission : permissionsAnyOfWhichIsRequiredToSeeWidget.get(widget)) {
WildcardPermission requiredPermission = new WildcardPermission(requiredStringPermission.getStringPermission());
WildcardPermission requiredPermission = requiredStringPermission.getPermission();
// TODO use PermissionChecker instead of enumerating all permissions
for (WildcardPermission userPermission : user.getAllPermissions()) {
if (requiredPermission.implies(userPermission) || userPermission.implies(requiredPermission)) {
@@ -28,6 +28,11 @@ public enum DefaultPermissions implements Permission {
return result;
}
@Override
public WildcardPermission getPermission(Mode... modes) {
return new WildcardPermission(getStringPermission(modes));
}
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
public String getStringPermissionForObjects(Mode mode, String... objectIdentifiers) {
final StringBuilder result = new StringBuilder(getStringPermission(mode));
@@ -46,5 +51,11 @@ public enum DefaultPermissions implements Permission {
return result.toString();
}
@Override
public WildcardPermission getPermissionForObjects(Mode mode, String... objectIdentifiers) {
return new WildcardPermission(getStringPermissionForObjects(mode, objectIdentifiers));
}
private final String stringPermission;
}
@@ -2,30 +2,42 @@ package com.sap.sse.security.shared;
public interface Permission {
String name();
int ordinal();
/**
* If one or more modes are specified, a string permission is rendered that has the
* {@link Mode#getStringPermission() permission strings} of those modes listed in the second wildcard permission
* component. Otherwise, only the primary permission with one segment is returned.
*/
String getStringPermission(Mode... modes);
/**
* Produces a string permission for this permission, the <code>mode</code> specified as the second wildcard permission
* segment, and the <code>objectIdentifier</code> as the third wildcard permission segment.
* Same as {@link #getStringPermission(Mode...)}, only that the result is a {@link WildcardPermission} instead of a
* {@link String}
*/
WildcardPermission getPermission(Mode... modes);
/**
* Produces a string permission for this permission, the <code>mode</code> specified as the second wildcard
* permission segment, and the <code>objectIdentifier</code> as the third wildcard permission segment.
*/
String getStringPermissionForObjects(Mode mode, String... objectIdentifiers);
/**
* Same as {@link #getStringPermissionForObjects(Mode, String...)}, only that the result is a
* {@link WildcardPermission} instead of a {@link String}
*/
WildcardPermission getPermissionForObjects(Mode mode, String... objectIdentifiers);
public static interface Mode {
String name();
int ordinal();
String getStringPermission();
}
public enum DefaultModes implements Mode {
CREATE, READ, UPDATE, DELETE;
@@ -27,9 +27,14 @@ public class PermissionChecker {
}
/**
* @param permission Permission of the form "data_object_type:action:instance_id".
* The instance id can be omitted when a general permission for the data
* object type is asked after (e.g. "event:create").
* @param permission
* Permission of the form "data_object_type:action:instance_id". The instance id can be omitted when a
* general permission for the data object type is asked after (e.g. "event:create").
* @param ownership
* may be {@code null}, causing user- or tenant-parameterized roles and no user ownership override to be
* applied
* @param acl
* may be {@code null} in which case no ACL-specific checks are performed
*/
public static boolean isPermitted(WildcardPermission permission, SecurityUser user, Iterable<UserGroup> groupsOfWhichUserIsMember,
Iterable<Role> roles, Ownership ownership,
@@ -15,8 +15,33 @@ import com.sap.sse.common.WithID;
public interface SecurityUser extends NamedWithID {
Tenant getDefaultTenant();
/**
* Checks whether this user has the {@code permission} requested. For this, the {@link #getRoles() roles}
* and {@link #getPermissions() permissions} are checked; however, since this method does not accept
* {@link Ownership} or {@link AccessControlList} parameters, no further inferences are made.
*/
boolean hasPermission(WildcardPermission permission);
/**
* Checks whether this user has the {@code permission} requested. For this, the {@link #getRoles() roles} and
* {@link #getPermissions() permissions} are checked, furthermore if this user is the
* {@link Ownership#getUserOwner() user owner} as per the {@code ownership} information, the permission will be
* granted because users have all rights to the objects they own. Furthermore, tenant and user parameterized roles
* will be applied based on the {@code ownership} information. No {@link AccessControlList} rules are applied here.
*/
boolean hasPermission(WildcardPermission permission, Ownership ownership);
/**
* Checks whether this user has the {@code permission} requested. For this, the {@link #getRoles() roles} and
* {@link #getPermissions() permissions} are checked, furthermore if this user is the
* {@link Ownership#getUserOwner() user owner} as per the {@code ownership} information, the permission will be
* granted because users have all rights to the objects they own. Furthermore, tenant and user parameterized roles
* will be applied based on the {@code ownership} information. If the user belongs to one or more groups
* ({@code groupsThisUserIsPartOf}) and a non-{@code null} {@code acl} is provided, the access control list
* permissions are applied accordingly.
*/
boolean hasPermission(WildcardPermission permission, Ownership ownership, Iterable<UserGroup> groupsThisUserIsPartOf, AccessControlList acl);
/**
* Returns the "raw" permissions explicitly set for this user. This does not include permissions
* inferred by any {@link PermissionsForRoleProvider} for the {@link #getRoles() roles} that this
@@ -5,9 +5,13 @@ import java.util.HashSet;
import java.util.Set;
import com.sap.sse.common.Util;
import com.sap.sse.security.shared.AccessControlList;
import com.sap.sse.security.shared.Ownership;
import com.sap.sse.security.shared.PermissionChecker;
import com.sap.sse.security.shared.Role;
import com.sap.sse.security.shared.SecurityUser;
import com.sap.sse.security.shared.Tenant;
import com.sap.sse.security.shared.UserGroup;
import com.sap.sse.security.shared.WildcardPermission;
public class SecurityUserImpl implements SecurityUser {
@@ -76,9 +80,20 @@ public class SecurityUserImpl implements SecurityUser {
@Override
public boolean hasPermission(WildcardPermission permission) {
return permissions.contains(permission);
return hasPermission(permission, /* ownership */ null);
}
@Override
public boolean hasPermission(WildcardPermission permission, Ownership ownership) {
return hasPermission(permission, ownership, /* user groups */ null, /* ACL */ null);
}
@Override
public boolean hasPermission(WildcardPermission permission, Ownership ownership,
Iterable<UserGroup> groupsThisUserIsPartOf, AccessControlList acl) {
return PermissionChecker.isPermitted(permission, this, groupsThisUserIsPartOf, getRoles(), ownership, acl);
}
public void addRole(Role role) {
roles.add(role);
}
@@ -14,7 +14,7 @@ public class AuthenticationContextImpl implements AuthenticationContext {
private final UserDTO currentUser;
private final static UserDTO ANONYMOUS = new UserDTO("Anonymous", "", "", "", null, false, new ArrayList<AccountDTO>(),
new ArrayList<Role>(), /* default tenant */ null, new ArrayList<WildcardPermission>());
new ArrayList<Role>(), /* default tenant */ null, new ArrayList<WildcardPermission>(), /* groups */ null);
/**
* Creating an {@link AuthenticationContextImpl} containing an anonymous {@link UserDTO} object.
@@ -5,6 +5,7 @@ import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellList;
import com.google.gwt.user.client.ui.ImageResourceRenderer;
import com.sap.sse.common.Util;
import com.sap.sse.security.ui.client.IconResources;
import com.sap.sse.security.ui.shared.UserDTO;
@@ -28,7 +29,7 @@ public class UserList extends CellList<UserDTO> {
sb.appendHtmlConstant("</td>");
sb.appendHtmlConstant("<td>");
sb.appendHtmlConstant("<div>");
sb.appendEscaped(value.getName());
sb.appendEscaped(value.getName()+" ("+Util.join(", ", value.getUserGroups())+")");
sb.appendHtmlConstant("</div>");
sb.appendHtmlConstant("</td>");
sb.appendHtmlConstant("</tr>");
@@ -55,6 +55,7 @@ import com.sap.sse.security.shared.UsernamePasswordAccount;
import com.sap.sse.security.shared.WildcardPermission;
import com.sap.sse.security.shared.impl.SecurityUserImpl;
import com.sap.sse.security.shared.impl.TenantImpl;
import com.sap.sse.security.shared.impl.UserGroupImpl;
import com.sap.sse.security.ui.client.UserManagementService;
import com.sap.sse.security.ui.oauth.client.CredentialDTO;
import com.sap.sse.security.ui.oauth.client.SocialUserDTO;
@@ -100,13 +101,14 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
}.start();
}
private SecurityUser createUserDTOFromUser(SecurityUser user, Map<Tenant, Tenant> fromOriginalToStrippedDownTenant, Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser) {
private SecurityUser createUserDTOFromUser(SecurityUser user, Map<Tenant, Tenant> fromOriginalToStrippedDownTenant, Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser,
Map<UserGroup, UserGroup> fromOriginalToStrippedDownUserGroup) {
SecurityUser result = fromOriginalToStrippedDownUser.get(user);
if (result == null) {
final SecurityUserImpl preResult = new SecurityUserImpl(user.getName(), /* default tenant to be set later: */ null);
result = preResult;
fromOriginalToStrippedDownUser.put(user, result);
preResult.setDefaultTenant(createTenantDTOFromTenant(user.getDefaultTenant(), fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser));
preResult.setDefaultTenant(createTenantDTOFromTenant(user.getDefaultTenant(), fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser, fromOriginalToStrippedDownUserGroup));
}
return result;
}
@@ -125,10 +127,12 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
* as will for tenants.
*/
private Tenant createTenantDTOFromTenant(Tenant tenant) {
return createTenantDTOFromTenant(tenant, new HashMap<>(), new HashMap<>());
return createTenantDTOFromTenant(tenant, new HashMap<>(), new HashMap<>(), new HashMap<>());
}
private Tenant createTenantDTOFromTenant(Tenant tenant, Map<Tenant, Tenant> fromOriginalToStrippedDownTenant, Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser) {
private Tenant createTenantDTOFromTenant(Tenant tenant, Map<Tenant, Tenant> fromOriginalToStrippedDownTenant,
Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser,
Map<UserGroup, UserGroup> fromOriginalToStrippedDownUserGroup) {
final Tenant result;
if (tenant == null) {
result = null;
@@ -138,7 +142,8 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
result = new TenantImpl(tenant.getId(), tenant.getName());
fromOriginalToStrippedDownTenant.put(tenant, result);
for (final SecurityUser user : tenant.getUsers()) {
result.add(createUserDTOFromUser(user, fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser));
result.add(createUserDTOFromUser(user, fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser,
fromOriginalToStrippedDownUserGroup));
}
}
return result;
@@ -261,10 +266,11 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
if (SecurityUtils.getSubject().isPermitted("tenant:delete:" + tenantIdAsString)) {
try {
UUID tenantId = UUID.fromString(tenantIdAsString);
getSecurityService().deleteTenant(getSecurityService().getTenant(tenantId));
final Tenant tenant = getSecurityService().getTenant(tenantId);
getSecurityService().deleteTenant(tenant);
getSecurityService().deleteACL(tenantIdAsString);
getSecurityService().deleteOwnership(tenantIdAsString);
return new SuccessInfo(true, "Deleted tenant: " + tenantIdAsString + ".", /* redirectURL */ null, null);
return new SuccessInfo(true, "Deleted tenant: " + tenant.getName() + ".", /* redirectURL */ null, null);
} catch (UserGroupManagementException e) {
return new SuccessInfo(false, "Could not delete tenant.", /* redirectURL */ null, null);
}
@@ -518,10 +524,11 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
}
private UserDTO createUserDTOFromUser(User user) {
return createUserDTOFromUser(user, new HashMap<>(), new HashMap<>());
return createUserDTOFromUser(user, new HashMap<>(), new HashMap<>(), new HashMap<>());
}
private UserDTO createUserDTOFromUser(User user, Map<Tenant, Tenant> fromOriginalToStrippedDownTenant, Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser) {
private UserDTO createUserDTOFromUser(User user, Map<Tenant, Tenant> fromOriginalToStrippedDownTenant, Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser,
Map<UserGroup, UserGroup> fromOriginalToStrippedDownUserGroup) {
UserDTO userDTO;
Map<AccountType, Account> accounts = user.getAllAccounts();
List<AccountDTO> accountDTOs = new ArrayList<>();
@@ -544,12 +551,50 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U
userDTO = new UserDTO(user.getName(), user.getEmail(), user.getFullName(), user.getCompany(),
user.getLocale() != null ? user.getLocale().toLanguageTag() : null, user.isEmailValidated(),
accountDTOs, user.getRoles(), /* default tenant filled in later */ null,
user.getPermissions());
user.getPermissions(),
createUserGroupDTOsFromUserGroups(getSecurityService().getUserGroupsOfUser(user),
fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser,
fromOriginalToStrippedDownUserGroup));
fromOriginalToStrippedDownUser.put(user, userDTO);
userDTO.setDefaultTenant(createTenantDTOFromTenant(user.getDefaultTenant(), fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser));
userDTO.setDefaultTenant(createTenantDTOFromTenant(user.getDefaultTenant(), fromOriginalToStrippedDownTenant,
fromOriginalToStrippedDownUser, fromOriginalToStrippedDownUserGroup));
return userDTO;
}
private Iterable<UserGroup> createUserGroupDTOsFromUserGroups(Iterable<UserGroup> userGroups,
Map<Tenant, Tenant> fromOriginalToStrippedDownTenant,
Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser,
Map<UserGroup, UserGroup> fromOriginalToStrippedDownUserGroup) {
final List<UserGroup> result;
if (userGroups == null) {
result = null;
} else {
result = new ArrayList<>();
for (final UserGroup userGroup : userGroups) {
result.add(createUserDTOFromUserGroup(userGroup, fromOriginalToStrippedDownTenant,
fromOriginalToStrippedDownUser, fromOriginalToStrippedDownUserGroup));
}
}
return result;
}
private UserGroup createUserDTOFromUserGroup(UserGroup userGroup,
Map<Tenant, Tenant> fromOriginalToStrippedDownTenant,
Map<SecurityUser, SecurityUser> fromOriginalToStrippedDownUser,
Map<UserGroup, UserGroup> fromOriginalToStrippedDownUserGroup) {
final UserGroup result;
if (fromOriginalToStrippedDownUserGroup.containsKey(userGroup)) {
result = fromOriginalToStrippedDownUserGroup.get(userGroup);
} else {
result = new UserGroupImpl(userGroup.getId(), userGroup.getName());
fromOriginalToStrippedDownUserGroup.put(userGroup, result);
for (final SecurityUser user : userGroup.getUsers()) {
result.add(createUserDTOFromUser(user, fromOriginalToStrippedDownTenant, fromOriginalToStrippedDownUser, fromOriginalToStrippedDownUserGroup));
}
}
return result;
}
@Override
public Map<String, String> getSettings() {
Map<String, String> settings = new TreeMap<String, String>();
@@ -10,7 +10,6 @@ import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sse.common.Util;
import com.sap.sse.security.shared.AccessControlList;
import com.sap.sse.security.shared.Ownership;
import com.sap.sse.security.shared.PermissionChecker;
import com.sap.sse.security.shared.Role;
import com.sap.sse.security.shared.Tenant;
import com.sap.sse.security.shared.UserGroup;
@@ -26,6 +25,7 @@ public class UserDTO extends SecurityUserImpl implements IsSerializable {
private String locale;
private List<AccountDTO> accounts;
private boolean emailValidated;
private List<UserGroup> groups;
// for GWT serialization only
@Deprecated
@@ -33,8 +33,12 @@ public class UserDTO extends SecurityUserImpl implements IsSerializable {
super();
}
/**
* @param groups may be {@code null} which is equivalent to passing an empty groups collection
*/
public UserDTO(String name, String email, String fullName, String company, String locale, boolean emailValidated,
List<AccountDTO> accounts, Iterable<Role> roles, Tenant defaultTenant, Iterable<WildcardPermission> permissions) {
List<AccountDTO> accounts, Iterable<Role> roles, Tenant defaultTenant, Iterable<WildcardPermission> permissions,
Iterable<UserGroup> groups) {
super(name, roles, defaultTenant, permissions);
this.email = email;
this.fullName = fullName;
@@ -42,6 +46,8 @@ public class UserDTO extends SecurityUserImpl implements IsSerializable {
this.locale = locale;
this.emailValidated = emailValidated;
this.accounts = accounts;
this.groups = new ArrayList<>();
Util.addAll(groups, this.groups);
}
public String getFullName() {
@@ -105,20 +111,16 @@ public class UserDTO extends SecurityUserImpl implements IsSerializable {
return result;
}
public List<UserGroup> getUserGroups() {
return groups;
}
public boolean hasPermission(String permission) {
return hasPermission(new WildcardPermission(permission));
}
public boolean hasPermission(String permission, AccessControlList acl, Ownership ownership) {
return hasPermission(new WildcardPermission(permission), acl, ownership);
}
public boolean hasPermission(WildcardPermission permission, AccessControlList acl, Ownership ownership) {
ArrayList<UserGroup> groupsTheUserBelongsTo = new ArrayList<>();
if (acl != null) {
groupsTheUserBelongsTo = new ArrayList<>(acl.getActionsByUserGroup().keySet());
}
return PermissionChecker.isPermitted(permission, this, groupsTheUserBelongsTo, getRoles(), ownership, acl);
public boolean hasPermission(WildcardPermission permission, Ownership ownership, AccessControlList acl) {
return hasPermission(permission, ownership, getUserGroups(), acl);
}
public List<AccountDTO> getAccounts() {
@@ -72,7 +72,9 @@ public class UserStoreImpl implements UserStore {
/**
* Protects access to the two maps {@link #userGroupsContainingUser} and {@link #usersInUserGroups} which implement
* an efficient lookup for the m:n association between {@link UserGroup#getUsers()} and {@link SecurityUser}.
* an efficient lookup for the m:n association between {@link UserGroup#getUsers()} and {@link SecurityUser}. The
* collections also contain the relationships for the specialized {@link Tenant} objects which are not part of
* {@link #userGroups} but of {@link #tenants}.
*/
private final NamedReentrantReadWriteLock userGroupsUserCacheLock = new NamedReentrantReadWriteLock("User Groups Cache", /* fair */ false);
private final ConcurrentHashMap<SecurityUser, Set<UserGroup>> userGroupsContainingUser;
@@ -170,7 +170,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
BasicDBList usersO = (BasicDBList) groupDBObject.get(FieldNames.UserGroup.USERNAMES.name());
if (usersO != null) {
for (Object o : usersO) {
users.add(usersByName.get((String) o));
final UserImpl user = usersByName.get((String) o);
if (user != null) {
users.add(user);
}
}
}
UserGroup result = new UserGroupImpl(id, name, users);
@@ -104,6 +104,8 @@ public interface SecurityService extends ReplicableWithObjectInputStream<Replica
UserGroup getUserGroup(UUID id);
UserGroup getUserGroupByName(String name);
Iterable<UserGroup> getUserGroupsOfUser(SecurityUser user);
Iterable<Tenant> getTenants();
@@ -490,6 +490,11 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
return userStore.getUserGroupByName(name);
}
@Override
public Iterable<UserGroup> getUserGroupsOfUser(SecurityUser user) {
return userStore.getUserGroupsOfUser(user);
}
@Override
public Iterable<Tenant> getTenants() {
return userStore.getTenants();
@@ -552,7 +557,8 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
@Override
public void deleteTenant(Tenant tenant) throws TenantManagementException, UserGroupManagementException {
for (Ownership ownership : accessControlStore.getOwnerships()) {
if (ownership.getTenantOwner().equals(tenant)) {
if (!Util.equalsWithNull(ownership.getIdOfOwnedObjectAsString(), tenant.getId().toString()) &&
Util.equalsWithNull(ownership.getTenantOwner(), tenant)) {
throw new TenantManagementException("The tenant "+tenant.getName()+
" is still used as tenant owner and therefore cannot be removed");
}
@@ -620,7 +626,12 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat
@Override
public Void internalDeleteUserGroup(UUID groupId) throws UserGroupManagementException {
userStore.deleteUserGroup(getUserGroup(groupId));
final UserGroup userGroup = getUserGroup(groupId);
if (userGroup == null) {
logger.warning("Strange: the user group with ID "+groupId+" which is about to be deleted couldn't be found");
} else {
userStore.deleteUserGroup(userGroup);
}
return null;
}