[Major] Implemented groups in privilege. Refactored nearly everything

This commit is contained in:
Robert von Burg 2023-09-25 10:47:53 +02:00
parent 648553409c
commit 48d121882e
Signed by: eitch
GPG Key ID: 75DB9C85C74331F7
75 changed files with 3549 additions and 3282 deletions

View File

@ -19,7 +19,7 @@ import static java.lang.Boolean.parseBoolean;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS;
import static li.strolch.privilege.handler.PrivilegeHandler.PARAM_PERSIST_SESSIONS_PATH;
import static li.strolch.privilege.helper.XmlConstants.XML_PARAM_BASE_PATH;
import static li.strolch.privilege.helper.XmlConstants.PARAM_BASE_PATH;
import static li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants.*;
import java.io.File;
@ -126,7 +126,7 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
if (containerModel.getPersistenceHandlerClassName().equals(XmlPersistenceHandler.class.getName())) {
Map<String, String> xmlParams = containerModel.getPersistenceHandlerParameterMap();
File configPath = runtimeConfig.getConfigPath();
xmlParams.put(XML_PARAM_BASE_PATH, configPath.getPath());
xmlParams.put(PARAM_BASE_PATH, configPath.getPath());
}
return new PrivilegeInitializer(getScheduledExecutor(getName())).initializeFromXml(containerModel);

View File

@ -9,7 +9,7 @@ import li.strolch.model.StrolchRootElement;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@ -20,10 +20,10 @@ public class ModelPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, IPrivilege, Restrictable)
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Privilege, Restrictable)
*/
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@ -31,15 +31,15 @@ public class ModelPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, IPrivilege, Restrictable)
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Privilege, Restrictable)
*/
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
preValidate(privilege, restrictable);

View File

@ -1,7 +1,5 @@
package li.strolch.model.json;
import java.util.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@ -11,6 +9,8 @@ import li.strolch.privilege.model.RoleRep;
import li.strolch.privilege.model.UserRep;
import li.strolch.privilege.model.UserState;
import java.util.*;
public class PrivilegeElementFromJsonVisitor {
public UserRep userRepFromJson(String string) {
@ -82,6 +82,7 @@ public class PrivilegeElementFromJsonVisitor {
JsonElement lastNameE = jsonObject.get("lastname");
JsonElement userStateE = jsonObject.get("userState");
JsonElement localeE = jsonObject.get("locale");
JsonElement groupsE = jsonObject.get("groups");
JsonElement rolesE = jsonObject.get("roles");
JsonElement propertiesE = jsonObject.get("properties");
@ -90,16 +91,11 @@ public class PrivilegeElementFromJsonVisitor {
String firstname = firstNameE == null ? null : firstNameE.getAsString().trim();
String lastname = lastNameE == null ? null : lastNameE.getAsString().trim();
UserState userState = userStateE == null ? null : UserState.valueOf(userStateE.getAsString().trim());
Locale locale = localeE == null ? null : new Locale(localeE.getAsString().trim());
Locale locale = localeE == null ? null : Locale.forLanguageTag(localeE.getAsString().trim());
Set<String> roles = null;
if (rolesE != null) {
roles = new HashSet<>();
JsonArray rolesArr = rolesE.getAsJsonArray();
for (JsonElement role : rolesArr) {
roles.add(role.getAsString().trim());
}
}
Set<String> groups = jsonArrayToSet(groupsE);
Set<String> roles = jsonArrayToSet(rolesE);
Map<String, String> properties = null;
if (propertiesE != null) {
@ -111,6 +107,19 @@ public class PrivilegeElementFromJsonVisitor {
}
}
return new UserRep(userId, username, firstname, lastname, userState, roles, locale, properties, null);
return new UserRep(userId, username, firstname, lastname, userState, groups, roles, locale, properties, null);
}
private Set<String> jsonArrayToSet(JsonElement array) {
if (array == null)
return Set.of();
Set<String> result = new HashSet<>();
JsonArray rolesArr = array.getAsJsonArray();
for (JsonElement role : rolesArr) {
result.add(role.getAsString().trim());
}
return result;
}
}

View File

@ -14,6 +14,7 @@ public class PrivilegeConstants {
public static final String PRIMARY_LOCATION = "primaryLocation";
public static final String SECONDARY_LOCATIONS = "secondaryLocations";
public static final String ROLES = "roles";
public static final String GROUPS = "groups";
public static final String EMAIL = "email";
public static final String ROLE_STROLCH_ADMIN = "StrolchAdmin";

View File

@ -1,5 +1,13 @@
package li.strolch.privilege.handler;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.model.internal.UserHistory;
import li.strolch.privilege.policy.PrivilegePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
@ -10,14 +18,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.model.internal.UserHistory;
import li.strolch.privilege.policy.PrivilegePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
protected static final Logger logger = LoggerFactory.getLogger(BaseLdapPrivilegeHandler.class);
@ -135,12 +135,13 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
Set<String> ldapGroups = getLdapGroups(username, attrs);
logger.info("User " + username + " is member of the following LDAP groups: ");
ldapGroups.forEach(s -> logger.info("- " + s));
Set<String> strolchGroups = mapToStrolchGroups(username, ldapGroups);
Set<String> strolchRoles = mapToStrolchRoles(username, ldapGroups);
Map<String, String> properties = buildProperties(username, attrs, ldapGroups, strolchRoles);
return new User(username, username, null, firstName, lastName, UserState.REMOTE, strolchRoles, locale,
properties, false, new UserHistory());
return new User(username, username, null, firstName, lastName, UserState.REMOTE, strolchGroups, strolchRoles,
locale, properties, false, UserHistory.EMPTY);
}
protected abstract Map<String, String> buildProperties(String username, Attributes attrs, Set<String> ldapGroups,
@ -168,5 +169,7 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
protected abstract Set<String> getLdapGroups(String username, Attributes attrs) throws NamingException;
protected abstract Set<String> mapToStrolchGroups(String username, Set<String> ldapGroups);
protected abstract Set<String> mapToStrolchRoles(String username, Set<String> ldapGroups);
}

View File

@ -44,7 +44,7 @@ import static li.strolch.privilege.helper.XmlConstants.*;
* <p>
* Required parameters:
* <ul>
* <li>{@link XmlConstants#XML_PARAM_HASH_ALGORITHM}</li>
* <li>{@link XmlConstants#PARAM_HASH_ALGORITHM}</li>
* </ul>
*
* @author Robert von Burg <eitch@eitchnet.ch>
@ -121,7 +121,7 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
try {
MessageDigest digest = MessageDigest.getInstance(this.nonSaltAlgorithm);
return new PasswordCrypt(digest.digest(new String(password).getBytes()), null);
return PasswordCrypt.of(digest.digest(new String(password).getBytes()), null);
} catch (NoSuchAlgorithmException e) {
throw new PrivilegeException(MessageFormat.format("Algorithm {0} was not found!", nonSaltAlgorithm),
@ -151,9 +151,8 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
@Override
public boolean isPasswordCryptOutdated(PasswordCrypt passwordCrypt) {
return passwordCrypt.getSalt() == null || passwordCrypt.getHashAlgorithm() == null ||
passwordCrypt.getHashIterations() != this.iterations ||
passwordCrypt.getHashKeyLength() != this.keyLength;
return passwordCrypt.salt() == null || passwordCrypt.hashAlgorithm() == null ||
passwordCrypt.hashIterations() != this.iterations || passwordCrypt.hashKeyLength() != this.keyLength;
}
@Override
@ -163,13 +162,13 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
this.secureRandom = new SecureRandom();
// get hash algorithm parameters
this.algorithm = parameterMap.getOrDefault(XML_PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
this.nonSaltAlgorithm = parameterMap.getOrDefault(XML_PARAM_HASH_ALGORITHM_NON_SALT,
this.algorithm = parameterMap.getOrDefault(PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
this.nonSaltAlgorithm = parameterMap.getOrDefault(PARAM_HASH_ALGORITHM_NON_SALT,
DEFAULT_ALGORITHM_NON_SALT);
this.iterations = Integer.parseInt(
parameterMap.getOrDefault(XML_PARAM_HASH_ITERATIONS, valueOf(DEFAULT_ITERATIONS)));
parameterMap.getOrDefault(PARAM_HASH_ITERATIONS, valueOf(DEFAULT_ITERATIONS)));
this.keyLength = Integer.parseInt(
parameterMap.getOrDefault(XML_PARAM_HASH_KEY_LENGTH, valueOf(DEFAULT_KEY_LENGTH)));
parameterMap.getOrDefault(PARAM_HASH_KEY_LENGTH, valueOf(DEFAULT_KEY_LENGTH)));
// test non-salt hash algorithm
try {
@ -178,7 +177,7 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
MessageFormat.format("Using non-salt hashing algorithm {0}", this.nonSaltAlgorithm));
} catch (Exception e) {
String msg = "[{0}] Defined parameter {1} is invalid because of underlying exception: {2}";
msg = MessageFormat.format(msg, EncryptionHandler.class.getName(), XML_PARAM_HASH_ALGORITHM_NON_SALT,
msg = MessageFormat.format(msg, EncryptionHandler.class.getName(), PARAM_HASH_ALGORITHM_NON_SALT,
e.getLocalizedMessage());
throw new PrivilegeException(msg, e);
}
@ -189,7 +188,7 @@ public class DefaultEncryptionHandler implements EncryptionHandler {
DefaultEncryptionHandler.logger.info(MessageFormat.format("Using hashing algorithm {0}", this.algorithm));
} catch (Exception e) {
String msg = "[{0}] Defined parameter {1} is invalid because of underlying exception: {2}";
msg = MessageFormat.format(msg, EncryptionHandler.class.getName(), XML_PARAM_HASH_ALGORITHM,
msg = MessageFormat.format(msg, EncryptionHandler.class.getName(), PARAM_HASH_ALGORITHM,
e.getLocalizedMessage());
throw new PrivilegeException(msg, e);
}

View File

@ -1,10 +1,11 @@
package li.strolch.privilege.handler;
import static java.lang.String.join;
import static java.util.stream.Collectors.toSet;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import li.strolch.privilege.helper.LdapHelper;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
@ -13,12 +14,11 @@ import java.io.FileReader;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import li.strolch.privilege.helper.LdapHelper;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
import static java.lang.String.join;
import static java.util.stream.Collectors.toSet;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
public class JsonConfigLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
@ -147,17 +147,25 @@ public class JsonConfigLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
return relevantLdapGroups;
}
@Override
protected Set<String> mapToStrolchGroups(String username, Set<String> ldapGroups) {
return mapLdapGroupToStrolch(ldapGroups, GROUPS);
}
@Override
protected Set<String> mapToStrolchRoles(String username, Set<String> ldapGroups) {
return mapLdapGroupToStrolch(ldapGroups, ROLES);
}
Set<String> strolchRoles = new HashSet<>();
private Set<String> mapLdapGroupToStrolch(Set<String> ldapGroups, String type) {
Set<String> mappedValues = new HashSet<>();
for (String relevantLdapGroup : ldapGroups) {
JsonObject mappingJ = this.ldapGroupConfigs.get(relevantLdapGroup).getAsJsonObject();
mappingJ.get(ROLES).getAsJsonArray().forEach(e -> strolchRoles.add(e.getAsString()));
if (mappingJ.has(type))
mappingJ.get(type).getAsJsonArray().forEach(e -> mappedValues.add(e.getAsString()));
}
return strolchRoles;
return mappedValues;
}
@Override

View File

@ -15,17 +15,17 @@
*/
package li.strolch.privilege.handler;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Group;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.policy.PrivilegePolicy;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* <p>
@ -36,7 +36,7 @@ import javax.xml.stream.XMLStreamException;
* <p>
* The {@link PersistenceHandler} also serves the special {@link PrivilegePolicy} objects. These policies are special
* objects which implement an algorithm to define if an action is allowed on a {@link Restrictable} by a {@link Role}
* and {@link IPrivilege}
* and {@link Privilege}
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
@ -50,6 +50,13 @@ public interface PersistenceHandler {
*/
List<User> getAllUsers();
/**
* Returns all currently known {@link Group}s
*
* @return all currently known {@link Group}s
*/
List<Group> getAllGroups();
/**
* Returns all currently known {@link Role}s
*
@ -60,18 +67,25 @@ public interface PersistenceHandler {
/**
* Returns a {@link User} object from the underlying database
*
* @param username
* the name/id of the {@link User} object to return
* @param username the name/id of the {@link User} object to return
*
* @return the {@link User} object, or null if it was not found
*/
User getUser(String username);
/**
* Returns a {@link Group} object from the underlying database
*
* @param groupName the name/id of the {@link Group} object to return
*
* @return the {@link Group} object, or null if it was not found
*/
Group getGroup(String groupName);
/**
* Returns a {@link Role} object from the underlying database
*
* @param roleName
* the name/id of the {@link Role} object to return
* @param roleName the name/id of the {@link Role} object to return
*
* @return the {@link Role} object, or null if it was not found
*/
@ -80,18 +94,25 @@ public interface PersistenceHandler {
/**
* Removes a {@link User} with the given name and returns the removed object if it existed
*
* @param username
* the name of the {@link User} to remove
* @param username the name of the {@link User} to remove
*
* @return the {@link User} removed, or null if it did not exist
*/
User removeUser(String username);
/**
* Removes a {@link Group} with the given name and returns the removed object if it existed
*
* @param groupName the name of the {@link Group} to remove
*
* @return the {@link Group} removed, or null if it did not exist
*/
Group removeGroup(String groupName);
/**
* Removes a {@link Role} with the given name and returns the removed object if it existed
*
* @param roleName
* the name of the {@link Role} to remove
* @param roleName the name of the {@link Role} to remove
*
* @return the {@link Role} removed, or null if it did not exist
*/
@ -100,35 +121,45 @@ public interface PersistenceHandler {
/**
* Adds a {@link User} object to the underlying database
*
* @param user
* the {@link User} object to add
* @param user the {@link User} object to add
*/
void addUser(User user);
/**
* Replaces the existing {@link User} object in the underlying database
*
* @param user
* the {@link User} object to add
* @param user the {@link User} object to add
*/
void replaceUser(User user);
/**
* Adds a {@link Role} object to the underlying database
*
* @param role
* the {@link User} object to add
* @param role the {@link Role} object to add
*/
void addRole(Role role);
/**
* Replaces the {@link Role} object in the underlying database
*
* @param role
* the {@link User} object to add
* @param role the {@link User} object to add
*/
void replaceRole(Role role);
/**
* Adds a {@link Group} object to the underlying database
*
* @param group the {@link Group} object to add
*/
void addGroup(Group group);
/**
* Replaces the {@link Group} object in the underlying database
*
* @param group the {@link Group} object to add
*/
void replaceGroup(Group group);
/**
* Informs this {@link PersistenceHandler} to persist any changes which need to be saved
*
@ -147,8 +178,7 @@ public interface PersistenceHandler {
* Initialize the concrete {@link PersistenceHandler}. The passed parameter map contains any configuration the
* concrete {@link PersistenceHandler} might need
*
* @param parameterMap
* a map containing configuration properties
* @param parameterMap a map containing configuration properties
*/
void initialize(Map<String, String> parameterMap);

View File

@ -0,0 +1,204 @@
package li.strolch.privilege.handler;
import li.strolch.privilege.base.PrivilegeConflictResolution;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.base.PrivilegeModelException;
import li.strolch.privilege.model.*;
import li.strolch.privilege.model.internal.Group;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.ZonedDateTime;
import java.util.*;
import static java.text.MessageFormat.format;
import static java.util.stream.Collectors.toCollection;
import static li.strolch.privilege.handler.DefaultPrivilegeHandler.streamAllRolesForUser;
public class PrivilegeContextBuilder {
private static final Logger logger = LoggerFactory.getLogger(PrivilegeContextBuilder.class);
private final Map<String, Class<PrivilegePolicy>> policyMap;
private final DefaultPrivilegeHandler privilegeHandler;
private final PrivilegeConflictResolution conflictResolution;
private final PersistenceHandler persistenceHandler;
private Set<String> userGroups;
private Set<String> userRoles;
private Map<String, String> userProperties;
public PrivilegeContextBuilder(DefaultPrivilegeHandler privilegeHandler) {
this.privilegeHandler = privilegeHandler;
this.persistenceHandler = privilegeHandler.persistenceHandler;
this.policyMap = privilegeHandler.policyMap;
this.conflictResolution = privilegeHandler.privilegeConflictResolution;
}
public PrivilegeContext buildPrivilegeContext(Usage usage, User user, String source, ZonedDateTime loginTime,
boolean keepAlive) {
String authToken = this.privilegeHandler.getEncryptionHandler().nextToken();
String sessionId = UUID.randomUUID().toString();
return buildPrivilegeContext(usage, user, authToken, sessionId, source, loginTime, keepAlive);
}
public PrivilegeContext buildPrivilegeContext(Usage usage, User user, String authToken, String sessionId,
String source, ZonedDateTime loginTime, boolean keepAlive) {
DBC.PRE.assertNotEmpty("source must not be empty!", source);
keepAlive = keepAlive && this.privilegeHandler.allowSessionRefresh;
prepare(user);
Map<String, Privilege> privileges = new HashMap<>();
Map<String, PrivilegePolicy> policies = new HashMap<>();
// cache the privileges and policies for this user by role
addPrivilegesForRoles(this.userRoles, user.getUsername(), privileges, policies);
UserRep userRep = user.asUserRep();
userRep.setRoles(this.userRoles);
userRep.setGroups(this.userGroups);
userRep.setProperties(this.userProperties);
userRep.readOnly();
Certificate certificate = new Certificate(usage, sessionId, user.getUsername(), user.getFirstname(),
user.getLastname(), user.getUserState(), authToken, source, loginTime, keepAlive, user.getLocale(),
this.userGroups, this.userRoles, this.userProperties);
return new PrivilegeContext(userRep, certificate, privileges, policies);
}
private void prepare(User user) {
this.userGroups = user.getGroups().stream().sorted().collect(toCollection(TreeSet::new));
this.userRoles = streamAllRolesForUser(this.persistenceHandler, user).sorted()
.collect(toCollection(TreeSet::new));
this.userProperties = new HashMap<>(user.getProperties());
// copy properties from groups to user properties
for (String groupName : this.userGroups) {
Group group = this.persistenceHandler.getGroup(groupName);
if (group == null) {
logger.error("Group " + groupName + " does not exist!");
continue;
}
Map<String, String> groupProperties = group.getProperties();
for (String key : groupProperties.keySet()) {
String replaced = this.userProperties.put(key, groupProperties.get(key));
if (replaced != null)
logger.error("Duplicate property {} for user {} from group {}", key, user.getUsername(), groupName);
}
}
}
private void addPrivilegesForRoles(Set<String> roles, String userName, Map<String, Privilege> privileges,
Map<String, PrivilegePolicy> policies) {
for (String roleName : roles) {
Role role = this.persistenceHandler.getRole(roleName);
if (role == null) {
logger.error("Role " + roleName + " does not exist for user " + userName);
} else {
addPrivilegesForRole(userName, role, privileges, policies);
}
}
}
private void addPrivilegesForRole(String userName, Role role, Map<String, Privilege> privileges,
Map<String, PrivilegePolicy> policies) {
for (Privilege privilege : role.privilegeMap().values()) {
String privilegeName = privilege.name();
if (!privileges.containsKey(privilegeName)) {
privileges.put(privilegeName, privilege);
} else {
handleDuplicatePrivilege(userName, role, privileges, privilege, privilegeName);
}
// cache the policy for the privilege
addPolicyForPrivilege(policies, privilege, privilegeName);
}
}
private void addPolicyForPrivilege(Map<String, PrivilegePolicy> policies, Privilege privilege,
String privilegeName) {
String policyName = privilege.getPolicy();
if (policies.containsKey(policyName))
return;
PrivilegePolicy policy = getPolicy(policyName);
if (policy == null) {
logger.error(format("The Policy {0} does not exist for Privilege {1}", policyName, privilegeName));
} else {
policies.put(policyName, policy);
}
}
private void handleDuplicatePrivilege(String userName, Role role, Map<String, Privilege> privileges,
Privilege additionalPrivilege, String privilegeName) {
// for strict, we have to throw an exception
if (this.conflictResolution.isStrict())
throw new PrivilegeModelException(
format("User " + userName + " has conflicts for privilege {0} with role {1}", privilegeName,
role.name()));
// merge privileges
Privilege knownPrivilege = privileges.get(privilegeName);
boolean allAllowed = knownPrivilege.isAllAllowed() || additionalPrivilege.isAllAllowed();
Set<String> allowList;
Set<String> denyList;
if (allAllowed) {
allowList = Set.of();
denyList = Set.of();
} else {
allowList = new HashSet<>(knownPrivilege.getAllowList());
allowList.addAll(additionalPrivilege.getAllowList());
denyList = new HashSet<>(knownPrivilege.getDenyList());
denyList.addAll(additionalPrivilege.getDenyList());
}
String policy = knownPrivilege.getPolicy();
privileges.put(privilegeName, new Privilege(knownPrivilege.getName(), policy, allAllowed, denyList, allowList));
}
/**
* <p>
* This method instantiates a {@link PrivilegePolicy} object from the given policyName. The {@link PrivilegePolicy}
* is not stored in a database. The privilege name is a class name and is then used to instantiate a new
* {@link PrivilegePolicy} object
* </p>
*
* @param policyName the class name of the {@link PrivilegePolicy} object to return
*
* @return the {@link PrivilegePolicy} object
*
* @throws PrivilegeException if the {@link PrivilegePolicy} object for the given policy name could not be
* instantiated
*/
private PrivilegePolicy getPolicy(String policyName) {
// get the policies class
Class<PrivilegePolicy> policyClazz = this.policyMap.get(policyName);
if (policyClazz == null) {
return null;
}
// instantiate the policy
PrivilegePolicy policy;
try {
policy = policyClazz.getConstructor().newInstance();
} catch (Exception e) {
String msg = "The class for the policy with the name {0} does not exist!{1}";
msg = format(msg, policyName, policyName);
throw new PrivilegeModelException(msg, e);
}
return policy;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -502,7 +502,7 @@ public interface PrivilegeHandler {
* @param roleName
* the roleName of the {@link Role} to which the privilege should be added
* @param privilegeRep
* the representation of the {@link IPrivilege} which should be added or replaced on the {@link Role}
* the representation of the {@link Privilege} which should be added or replaced on the {@link Role}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action

View File

@ -1,127 +0,0 @@
package li.strolch.privilege.handler;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import li.strolch.privilege.helper.LdapHelper;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
protected static final Logger logger = LoggerFactory.getLogger(SimpleLdapPrivilegeHandler.class);
private Locale defaultLocale;
private String adminUsers;
private Map<String, Set<String>> rolesForLdapGroups;
private String organisation;
private String location;
private String realm;
@Override
public void initialize(ScheduledExecutorService executorService, Map<String, String> parameterMap,
EncryptionHandler encryptionHandler, PasswordStrengthHandler passwordStrengthHandler,
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
super.initialize(executorService, parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
userChallengeHandler, ssoHandler, policyMap);
this.organisation = parameterMap.getOrDefault(ORGANISATION, "");
this.location = parameterMap.getOrDefault(LOCATION, "");
this.realm = parameterMap.getOrDefault(REALM, "");
this.defaultLocale = parameterMap.containsKey("defaultLocale") ?
Locale.forLanguageTag(parameterMap.get("defaultLocale")) : Locale.getDefault();
this.adminUsers = parameterMap.get("adminUsers");
this.rolesForLdapGroups = getLdapGroupToRolesMappingFromConfig(parameterMap);
}
@Override
protected String getFirstName(String username, Attributes attrs) throws NamingException {
String value = getLdapString(attrs, "givenName");
return isEmpty(value) ? username : value;
}
@Override
protected String getLastName(String username, Attributes attrs) throws NamingException {
String value = getLdapString(attrs, "sn");
return isEmpty(value) ? username : value;
}
@Override
protected Map<String, String> buildProperties(String username, Attributes attrs, Set<String> ldapGroups,
Set<String> strolchRoles) {
Map<String, String> properties = new HashMap<>();
properties.put(ORGANISATION, this.organisation);
properties.put(LOCATION, this.location);
properties.put(REALM, this.realm);
return properties;
}
@Override
protected Locale getLocale(Attributes attrs) {
return this.defaultLocale;
}
@Override
protected Set<String> getLdapGroups(String username, Attributes attrs) throws NamingException {
Set<String> ldapGroups = LdapHelper.getLdapGroups(attrs);
logger.info("User " + username + " has LDAP Groups: ");
ldapGroups.forEach(s -> logger.info("- " + s));
return ldapGroups;
}
@Override
protected Set<String> mapToStrolchRoles(String username, Set<String> ldapGroups) {
Set<String> strolchRoles = new HashSet<>();
for (String ldapRole : ldapGroups) {
Set<String> foundStrolchRoles = this.rolesForLdapGroups.get(ldapRole);
if (foundStrolchRoles != null)
strolchRoles.addAll(foundStrolchRoles);
}
// see if this is an admin user
if (this.adminUsers.contains(username))
strolchRoles = this.rolesForLdapGroups.get("admin");
return strolchRoles;
}
private Map<String, Set<String>> getLdapGroupToRolesMappingFromConfig(Map<String, String> params) {
String rolesForLdapGroups = params.get("rolesForLdapGroups");
DBC.PRE.assertNotEmpty("No roles mapping for ldap directory groups defined (param: rolesForLdapGroups)",
rolesForLdapGroups);
// rolesForLdapGroups = admin=StrolchAdmin,UserPrivileges;user=UserPrivileges
String[] ldapGroupRoles = rolesForLdapGroups.split(";");
Map<String, Set<String>> result = new HashMap<>();
for (String ldapGroupRole : ldapGroupRoles) {
ldapGroupRole = ldapGroupRole.trim();
String[] splitGroupRoles = ldapGroupRole.split("=");
String ldapGroupName = splitGroupRoles[0];
String[] strolchRoles = splitGroupRoles[1].split(",");
Set<String> roleNames = new HashSet<>();
for (String strolchRole : strolchRoles) {
roleNames.add(strolchRole.trim());
}
result.put(ldapGroupName, roleNames);
}
return result;
}
}

View File

@ -17,12 +17,10 @@ package li.strolch.privilege.handler;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.helper.XmlConstants;
import li.strolch.privilege.model.internal.Group;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.xml.PrivilegeRolesSaxReader;
import li.strolch.privilege.xml.PrivilegeRolesSaxWriter;
import li.strolch.privilege.xml.PrivilegeUsersSaxReader;
import li.strolch.privilege.xml.PrivilegeUsersSaxWriter;
import li.strolch.privilege.xml.*;
import li.strolch.utils.helper.XmlHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -54,20 +52,24 @@ public class XmlPersistenceHandler implements PersistenceHandler {
protected static final Logger logger = LoggerFactory.getLogger(XmlPersistenceHandler.class);
private final Map<String, User> userMap;
private final Map<String, Group> groupMap;
private final Map<String, Role> roleMap;
private boolean userMapDirty;
private boolean groupMapDirty;
private boolean roleMapDirty;
private Map<String, String> parameterMap;
private File usersPath;
private File groupsPath;
private File rolesPath;
private boolean caseInsensitiveUsername;
public XmlPersistenceHandler() {
this.roleMap = new ConcurrentHashMap<>();
this.groupMap = new ConcurrentHashMap<>();
this.userMap = new ConcurrentHashMap<>();
}
@ -83,6 +85,13 @@ public class XmlPersistenceHandler implements PersistenceHandler {
}
}
@Override
public List<Group> getAllGroups() {
synchronized (this.groupMap) {
return new LinkedList<>(this.groupMap.values());
}
}
@Override
public List<Role> getAllRoles() {
synchronized (this.roleMap) {
@ -95,6 +104,11 @@ public class XmlPersistenceHandler implements PersistenceHandler {
return this.userMap.get(this.caseInsensitiveUsername ? username.toLowerCase() : username);
}
@Override
public Group getGroup(String groupName) {
return this.groupMap.get(groupName);
}
@Override
public Role getRole(String roleName) {
return this.roleMap.get(roleName);
@ -107,6 +121,13 @@ public class XmlPersistenceHandler implements PersistenceHandler {
return user;
}
@Override
public Group removeGroup(String groupName) {
Group group = this.groupMap.remove(groupName);
this.groupMapDirty = group != null;
return group;
}
@Override
public Role removeRole(String roleName) {
Role role = this.roleMap.remove(roleName);
@ -133,6 +154,23 @@ public class XmlPersistenceHandler implements PersistenceHandler {
this.userMapDirty = true;
}
@Override
public void addGroup(Group group) {
if (this.groupMap.containsKey(group.name()))
throw new IllegalStateException(format("The group {0} already exists!", group.name()));
this.groupMap.put(group.name(), group);
this.groupMapDirty = true;
}
@Override
public void replaceGroup(Group group) {
if (!this.groupMap.containsKey(group.name()))
throw new IllegalStateException(
format("The group {0} can not be replaced as it does not exist!", group.name()));
this.groupMap.put(group.name(), group);
this.groupMapDirty = true;
}
@Override
public void addRole(Role role) {
if (this.roleMap.containsKey(role.getName()))
@ -153,9 +191,10 @@ public class XmlPersistenceHandler implements PersistenceHandler {
/**
* Initializes this {@link XmlPersistenceHandler} by reading the following parameters:
* <ul>
* <li>{@link XmlConstants#XML_PARAM_BASE_PATH}</li>
* <li>{@link XmlConstants#XML_PARAM_USERS_FILE}</li>
* <li>{@link XmlConstants#XML_PARAM_ROLES_FILE}</li>
* <li>{@link XmlConstants#PARAM_BASE_PATH}</li>
* <li>{@link XmlConstants#PARAM_USERS_FILE}</li>
* <li>{@link XmlConstants#PARAM_GROUPS_FILE}</li>
* <li>{@link XmlConstants#PARAM_ROLES_FILE}</li>
* </ul>
*/
@Override
@ -163,22 +202,21 @@ public class XmlPersistenceHandler implements PersistenceHandler {
this.parameterMap = Map.copyOf(paramsMap);
// get and validate base bath
String basePath = this.parameterMap.get(XML_PARAM_BASE_PATH);
String basePath = this.parameterMap.get(PARAM_BASE_PATH);
File basePathF = new File(basePath);
if (!basePathF.exists() && !basePathF.isDirectory()) {
String msg = "[{0}] Defined parameter {1} does not point to a valid path at {2}";
msg = format(msg, PersistenceHandler.class.getName(), XML_PARAM_BASE_PATH, basePathF.getAbsolutePath());
msg = format(msg, PersistenceHandler.class.getName(), PARAM_BASE_PATH, basePathF.getAbsolutePath());
throw new PrivilegeException(msg);
}
// get users file path
File usersPath = getFile(basePath, XML_PARAM_USERS_FILE, XML_PARAM_USERS_FILE_DEF);
// get roles file path
File rolesPath = getFile(basePath, XML_PARAM_ROLES_FILE, XML_PARAM_ROLES_FILE_DEF);
File usersPath = getFile(basePath, PARAM_USERS_FILE, PARAM_USERS_FILE_DEF, true);
File groupsPath = getFile(basePath, PARAM_GROUPS_FILE, PARAM_GROUPS_FILE_DEF, false);
File rolesPath = getFile(basePath, PARAM_ROLES_FILE, PARAM_ROLES_FILE_DEF, true);
// save path to model
this.usersPath = usersPath;
this.groupsPath = groupsPath;
this.rolesPath = rolesPath;
this.caseInsensitiveUsername = !this.parameterMap.containsKey(PARAM_CASE_INSENSITIVE_USERNAME) ||
@ -188,7 +226,7 @@ public class XmlPersistenceHandler implements PersistenceHandler {
logger.info("Privilege Data loaded.");
}
private File getFile(String basePath, String param, String defaultValue) {
private File getFile(String basePath, String param, String defaultValue, boolean required) {
String fileName = this.parameterMap.get(param);
if (isEmpty(fileName)) {
fileName = defaultValue;
@ -199,7 +237,7 @@ public class XmlPersistenceHandler implements PersistenceHandler {
String path = basePath + "/" + fileName;
File file = new File(path);
if (!file.exists()) {
if (required && !file.exists()) {
String msg = "[{0}] Defined parameter {1} is invalid as file does not exist at path {2}";
msg = format(msg, PersistenceHandler.class.getName(), param, file.getAbsolutePath());
throw new PrivilegeException(msg);
@ -221,6 +259,10 @@ public class XmlPersistenceHandler implements PersistenceHandler {
PrivilegeUsersSaxReader usersXmlHandler = new PrivilegeUsersSaxReader(this.caseInsensitiveUsername);
XmlHelper.parseDocument(this.usersPath, usersXmlHandler);
PrivilegeGroupsSaxReader groupsXmlHandler = new PrivilegeGroupsSaxReader();
if (this.groupsPath.exists())
XmlHelper.parseDocument(this.groupsPath, groupsXmlHandler);
PrivilegeRolesSaxReader rolesXmlHandler = new PrivilegeRolesSaxReader();
XmlHelper.parseDocument(this.rolesPath, rolesXmlHandler);
@ -230,6 +272,12 @@ public class XmlPersistenceHandler implements PersistenceHandler {
this.roleMap.putAll(rolesXmlHandler.getRoles());
}
// GROUPS
synchronized (this.groupMap) {
this.groupMap.clear();
this.groupMap.putAll(groupsXmlHandler.getGroups());
}
// USERS
synchronized (this.userMap) {
this.userMap.clear();
@ -237,21 +285,40 @@ public class XmlPersistenceHandler implements PersistenceHandler {
}
this.userMapDirty = false;
this.groupMapDirty = false;
this.roleMapDirty = false;
logger.info(format("Read {0} Users", this.userMap.size()));
logger.info(format("Read {0} Groups", this.groupMap.size()));
logger.info(format("Read {0} Roles", this.roleMap.size()));
// validate referenced roles exist
// validate referenced elements exist
for (User user : this.userMap.values()) {
for (String roleName : user.getRoles()) {
// validate that role exists
if (getRole(roleName) == null) {
logger.error(
format("Role {0} does not exist referenced by user {1}", roleName, user.getUsername()));
}
}
for (String groupName : user.getGroups()) {
// validate that group exists
if (getGroup(groupName) == null) {
logger.error(
format("Group {0} does not exist referenced by user {1}", groupName, user.getUsername()));
}
}
}
// validate referenced roles exist on groups
for (Group group : this.groupMap.values()) {
for (String roleName : group.roles()) {
// validate that role exists
if (getRole(roleName) == null) {
logger.error(format("Role {0} does not exist referenced by group {1}", roleName, group.name()));
}
}
}
return true;
@ -267,20 +334,21 @@ public class XmlPersistenceHandler implements PersistenceHandler {
// write users file
if (this.userMapDirty) {
// delegate writing
PrivilegeUsersSaxWriter modelWriter = new PrivilegeUsersSaxWriter(getAllUsers(), this.usersPath);
modelWriter.write();
new PrivilegeUsersSaxWriter(getAllUsers(), this.usersPath).write();
this.userMapDirty = false;
saved = true;
}
// write groups file
if (this.groupMapDirty) {
new PrivilegeGroupsSaxWriter(getAllGroups(), this.groupsPath).write();
this.groupMapDirty = false;
saved = true;
}
// write roles file
if (this.roleMapDirty) {
// delegate writing
PrivilegeRolesSaxWriter modelWriter = new PrivilegeRolesSaxWriter(getAllRoles(), this.rolesPath);
modelWriter.write();
new PrivilegeRolesSaxWriter(getAllRoles(), this.rolesPath).write();
this.roleMapDirty = false;
saved = true;
}

View File

@ -26,7 +26,6 @@ import java.util.HashMap;
import java.util.Map;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.privilege.model.internal.PasswordCrypt.buildPasswordString;
/**
* <p>
@ -111,9 +110,9 @@ public class PasswordCreator {
}
Map<String, String> parameterMap = new HashMap<>();
parameterMap.put(XmlConstants.XML_PARAM_HASH_ALGORITHM, hashAlgorithm);
parameterMap.put(XmlConstants.XML_PARAM_HASH_ITERATIONS, String.valueOf(iterations));
parameterMap.put(XmlConstants.XML_PARAM_HASH_KEY_LENGTH, String.valueOf(keyLength));
parameterMap.put(XmlConstants.PARAM_HASH_ALGORITHM, hashAlgorithm);
parameterMap.put(XmlConstants.PARAM_HASH_ITERATIONS, String.valueOf(iterations));
parameterMap.put(XmlConstants.PARAM_HASH_KEY_LENGTH, String.valueOf(keyLength));
DefaultEncryptionHandler encryptionHandler = new DefaultEncryptionHandler();
encryptionHandler.initialize(parameterMap);
@ -136,15 +135,15 @@ public class PasswordCreator {
byte[] salt = saltS.getBytes();
PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, salt);
String passwordHashS = StringHelper.toHexString(passwordCrypt.getPassword());
String passwordHashS = StringHelper.toHexString(passwordCrypt.password());
System.out.println("Hash is: " + passwordHashS);
System.out.println("Salt is: " + saltS);
System.out.println();
System.out.println(
XmlConstants.XML_ATTR_PASSWORD + "=\"" + passwordHashS + "\" " + XmlConstants.XML_ATTR_SALT +
"=\"" + saltS + "\"");
System.out.println(XmlConstants.XML_ATTR_PASSWORD + "=\"" + passwordCrypt.buildPasswordString() + "\"");
XmlConstants.ATTR_PASSWORD + "=\"" + passwordHashS + "\" " + XmlConstants.ATTR_SALT + "=\"" +
saltS + "\"");
System.out.println(XmlConstants.ATTR_PASSWORD + "=\"" + passwordCrypt.buildPasswordString() + "\"");
System.out.println();
}
}

View File

@ -23,308 +23,69 @@ package li.strolch.privilege.helper;
@SuppressWarnings("nls")
public class XmlConstants {
/**
* XML_ROOT_PRIVILEGE_CONTAINER = "PrivilegeContainer" :
*/
public static final String XML_ROOT_PRIVILEGE = "Privilege";
/**
* XML_CONTAINER = "Container" :
*/
public static final String XML_CONTAINER = "Container";
/**
* XML_POLICIES = "Policies" :
*/
public static final String XML_POLICIES = "Policies";
/**
* XML_PRIVILEGES = "Privileges" :
*/
public static final String XML_PRIVILEGES = "Privileges";
/**
* XML_ROOT_PRIVILEGE_USERS_AND_ROLES = "UsersAndRoles" :
*/
public static final String XML_ROOT_PRIVILEGE_USERS_AND_ROLES = "UsersAndRoles";
/**
* XML_ROOT_CERTIFICATES = "Certificates" :
*/
public static final String XML_ROOT_CERTIFICATES = "Certificates";
/**
* XML_HANDLER_USER_CHALLENGE = "UserChallengeHandler" :
*/
public static final String XML_HANDLER_USER_CHALLENGE = "UserChallengeHandler";
/**
* XML_HANDLER_PERSISTENCE = "PersistenceHandler" :
*/
public static final String XML_HANDLER_PERSISTENCE = "PersistenceHandler";
/**
* XML_HANDLER_ENCRYPTION = "EncryptionHandler" :
*/
public static final String XML_HANDLER_ENCRYPTION = "EncryptionHandler";
/**
* XML_HANDLER_ENCRYPTION = "PasswordStrengthHandler" :
*/
public static final String XML_HANDLER_PASSWORD_STRENGTH = "PasswordStrengthHandler";
/**
* XML_HANDLER_ENCRYPTION = "SsoHandler" :
*/
public static final String XML_HANDLER_SSO = "SsoHandler";
/**
* XML_HANDLER_PRIVILEGE = "PrivilegeHandler" :
*/
public static final String XML_HANDLER_PRIVILEGE = "PrivilegeHandler";
/**
* XML_ROLES = "Roles" :
*/
public static final String XML_ROLES = "Roles";
/**
* XML_ROLE = "Role" :
*/
public static final String XML_ROLE = "Role";
/**
* XML_USERS = "Users" :
*/
public static final String XML_USERS = "Users";
/**
* XML_CERTIFICATE = "Certificate" :
*/
public static final String XML_CERTIFICATE = "Certificate";
/**
* XML_SESSION_DATA = "SessionData" :
*/
public static final String XML_SESSION_DATA = "SessionData";
/**
* XML_USER = "User"
*/
public static final String XML_USER = "User";
/**
* XML_USER = "User"
*/
public static final String XML_HISTORY = "History";
/**
* XML_USER = "User"
*/
public static final String XML_FIRST_LOGIN = "FirstLogin";
/**
* XML_USER = "User"
*/
public static final String XML_LAST_LOGIN = "LastLogin";
/**
* XML_USER = "User"
*/
public static final String XML_LAST_PASSWORD_CHANGE = "LastPasswordChange";
/**
* XML_USER = "User"
*/
public static final String XML_PASSWORD_CHANGE_REQUESTED = "PasswordChangeRequested";
/**
* XML_PRIVILEGE = "Privilege" :
*/
public static final String XML_PRIVILEGE = "Privilege";
/**
* XML_POLICY = "Policy" :
*/
public static final String XML_POLICY = "Policy";
/**
* XML_PARAMETERS = "Parameters" :
*/
public static final String XML_PARAMETERS = "Parameters";
/**
* XML_PARAMETER = "Parameter" :
*/
public static final String XML_PARAMETER = "Parameter";
/**
* XML_PROPERTIES = "Properties" :
*/
public static final String XML_PROPERTIES = "Properties";
/**
* XML_PROPERTY = "Property" :
*/
public static final String XML_PROPERTY = "Property";
/**
* XML_ALL_ALLOWED = "AllAllowed" :
*/
public static final String XML_ALL_ALLOWED = "AllAllowed";
/**
* XML_DENY = "Deny" :
*/
public static final String XML_DENY = "Deny";
/**
* XML_ALLOW = "Allow" :
*/
public static final String XML_ALLOW = "Allow";
/**
* XML_FIRSTNAME = "Firstname" :
*/
public static final String XML_FIRSTNAME = "Firstname";
/**
* XML_LASTNAME = "Lastname" :
*/
public static final String XML_LASTNAME = "Lastname";
/**
* XML_STATE = "State" :
*/
public static final String XML_STATE = "State";
/**
* XML_LOCALE = "Locale" :
*/
public static final String XML_LOCALE = "Locale";
/**
* XML_ATTR_CLASS = "class" :
*/
public static final String XML_ATTR_CLASS = "class";
/**
* XML_ATTR_LOGIN_TIME = "loginTime" :
*/
public static final String XML_ATTR_LOGIN_TIME = "loginTime";
/**
* XML_ATTR_KEEP_ALIVE = "keepAlive" :
*/
public static final String XML_ATTR_KEEP_ALIVE = "keepAlive";
/**
* XML_ATTR_LAST_ACCESS = "lastAccess" :
*/
public static final String XML_ATTR_LAST_ACCESS = "lastAccess";
/**
* XML_ATTR_NAME = "name" :
*/
public static final String XML_ATTR_NAME = "name";
/**
* XML_ATTR_VALUE = "value" :
*/
public static final String XML_ATTR_VALUE = "value";
/**
* XML_ATTR_POLICY = "policy" :
*/
public static final String XML_ATTR_POLICY = "policy";
/**
* XML_ATTR_USER_ID = "userId" :
*/
public static final String XML_ATTR_USER_ID = "userId";
/**
* XML_ATTR_SESSION_ID = "sessionId" :
*/
public static final String XML_ATTR_SESSION_ID = "sessionId";
/**
* XML_ATTR_SESSION_ID = "usage" :
*/
public static final String XML_ATTR_USAGE = "usage";
/**
* XML_ATTR_USERNAME = "username" :
*/
public static final String XML_ATTR_USERNAME = "username";
/**
* XML_ATTR_AUTH_TOKEN = "authToken" :
*/
public static final String XML_ATTR_AUTH_TOKEN = "authToken";
/**
* XML_ATTR_SOURCE = "source" :
*/
public static final String XML_ATTR_SOURCE = "source";
/**
* XML_ATTR_LOCALE = "locale" :
*/
public static final String XML_ATTR_LOCALE = "locale";
/**
* XML_ATTR_PASSWORD = "password" :
*/
public static final String XML_ATTR_PASSWORD = "password";
/**
* XML_ATTR_SALT = "salt" :
*/
public static final String XML_ATTR_SALT = "salt";
/**
* XML_PARAM_HASH_ALGORITHM = "hashAlgorithm" :
*/
public static final String XML_PARAM_HASH_ALGORITHM = "hashAlgorithm";
/**
* XML_PARAM_HASH_ALGORITHM_NON_SALT = "hashAlgorithmNonSalt" :
*/
public static final String XML_PARAM_HASH_ALGORITHM_NON_SALT = "hashAlgorithmNonSalt";
/**
* XML_PARAM_HASH_ALGORITHM = "hashAlgorithm" :
*/
public static final String XML_PARAM_HASH_ITERATIONS = "hashIterations";
/**
* XML_PARAM_HASH_ALGORITHM = "hashAlgorithm" :
*/
public static final String XML_PARAM_HASH_KEY_LENGTH = "hashKeyLength";
/**
* XML_PARAM_USERS_FILE = "usersXmlFile" :
*/
public static final String XML_PARAM_USERS_FILE = "usersXmlFile";
/**
* XML_PARAM_USERS_FILE_DEF = "PrivilegeUsers.xml" :
*/
public static final String XML_PARAM_USERS_FILE_DEF = "PrivilegeUsers.xml";
/**
* XML_PARAM_ROLES_FILE = "rolesXmlFile" :
*/
public static final String XML_PARAM_ROLES_FILE = "rolesXmlFile";
/**
* XML_PARAM_ROLES_FILE_DEF = "PrivilegeRoles.xml" :
*/
public static final String XML_PARAM_ROLES_FILE_DEF = "PrivilegeRoles.xml";
/**
* XML_PARAM_BASE_PATH = "basePath" :
*/
public static final String XML_PARAM_BASE_PATH = "basePath";
public static final String ROOT_PRIVILEGE = "Privilege";
public static final String CONTAINER = "Container";
public static final String POLICIES = "Policies";
public static final String PRIVILEGES = "Privileges";
public static final String ROOT_PRIVILEGE_USERS_AND_ROLES = "UsersAndRoles";
public static final String ROOT_CERTIFICATES = "Certificates";
public static final String HANDLER_USER_CHALLENGE = "UserChallengeHandler";
public static final String HANDLER_PERSISTENCE = "PersistenceHandler";
public static final String HANDLER_ENCRYPTION = "EncryptionHandler";
public static final String HANDLER_PASSWORD_STRENGTH = "PasswordStrengthHandler";
public static final String HANDLER_SSO = "SsoHandler";
public static final String HANDLER_PRIVILEGE = "PrivilegeHandler";
public static final String ROLES = "Roles";
public static final String ROLE = "Role";
public static final String USERS = "Users";
public static final String GROUPS = "Groups";
public static final String GROUP = "Group";
public static final String CERTIFICATE = "Certificate";
public static final String SESSION_DATA = "SessionData";
public static final String USER = "User";
public static final String HISTORY = "History";
public static final String FIRST_LOGIN = "FirstLogin";
public static final String LAST_LOGIN = "LastLogin";
public static final String LAST_PASSWORD_CHANGE = "LastPasswordChange";
public static final String PASSWORD_CHANGE_REQUESTED = "PasswordChangeRequested";
public static final String PRIVILEGE = "Privilege";
public static final String POLICY = "Policy";
public static final String PARAMETERS = "Parameters";
public static final String PARAMETER = "Parameter";
public static final String PROPERTIES = "Properties";
public static final String PROPERTY = "Property";
public static final String ALL_ALLOWED = "AllAllowed";
public static final String DENY = "Deny";
public static final String ALLOW = "Allow";
public static final String FIRSTNAME = "Firstname";
public static final String LASTNAME = "Lastname";
public static final String STATE = "State";
public static final String LOCALE = "Locale";
public static final String ATTR_CLASS = "class";
public static final String ATTR_LOGIN_TIME = "loginTime";
public static final String ATTR_KEEP_ALIVE = "keepAlive";
public static final String ATTR_LAST_ACCESS = "lastAccess";
public static final String ATTR_NAME = "name";
public static final String ATTR_VALUE = "value";
public static final String ATTR_POLICY = "policy";
public static final String ATTR_USER_ID = "userId";
public static final String ATTR_SESSION_ID = "sessionId";
public static final String ATTR_USAGE = "usage";
public static final String ATTR_USERNAME = "username";
public static final String ATTR_AUTH_TOKEN = "authToken";
public static final String ATTR_SOURCE = "source";
public static final String ATTR_LOCALE = "locale";
public static final String ATTR_PASSWORD = "password";
public static final String ATTR_SALT = "salt";
public static final String PARAM_HASH_ALGORITHM = "hashAlgorithm";
public static final String PARAM_HASH_ALGORITHM_NON_SALT = "hashAlgorithmNonSalt";
public static final String PARAM_HASH_ITERATIONS = "hashIterations";
public static final String PARAM_HASH_KEY_LENGTH = "hashKeyLength";
public static final String PARAM_USERS_FILE = "usersXmlFile";
public static final String PARAM_USERS_FILE_DEF = "PrivilegeUsers.xml";
public static final String PARAM_GROUPS_FILE = "groupsXmlFile";
public static final String PARAM_GROUPS_FILE_DEF = "PrivilegeGroups.xml";
public static final String PARAM_ROLES_FILE = "rolesXmlFile";
public static final String PARAM_ROLES_FILE_DEF = "PrivilegeRoles.xml";
public static final String PARAM_BASE_PATH = "basePath";
}

View File

@ -18,7 +18,7 @@ public class XmlHelper {
public static void writeStringMapElement(XMLStreamWriter xmlWriter, Map<String, String> parameterMap,
String elementName, String valueElementName) throws XMLStreamException {
writeStringMapElement(xmlWriter, parameterMap, elementName, valueElementName, XML_ATTR_VALUE);
writeStringMapElement(xmlWriter, parameterMap, elementName, valueElementName, ATTR_VALUE);
}
public static void writeStringMapElement(XMLStreamWriter xmlWriter, Map<String, String> parameterMap,
@ -32,7 +32,7 @@ public class XmlHelper {
propertyKeys.sort(null);
for (String propertyKey : propertyKeys) {
xmlWriter.writeEmptyElement(valueElementName);
xmlWriter.writeAttribute(XML_ATTR_NAME, propertyKey);
xmlWriter.writeAttribute(ATTR_NAME, propertyKey);
xmlWriter.writeAttribute(valueAttrName, parameterMap.get(propertyKey));
}

View File

@ -15,20 +15,18 @@
*/
package li.strolch.privilege.model;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import li.strolch.privilege.base.PrivilegeConstants;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.internal.User;
import li.strolch.utils.dbc.DBC;
import java.io.Serializable;
import java.time.ZonedDateTime;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import li.strolch.privilege.base.PrivilegeConstants;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.internal.User;
import li.strolch.utils.helper.StringHelper;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
/**
* The {@link Certificate} is the object a client keeps when accessing a Privilege enabled system. This object is the
@ -37,7 +35,7 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public final class Certificate implements Serializable {
public final class Certificate {
private final Usage usage;
private final String sessionId;
@ -50,6 +48,7 @@ public final class Certificate implements Serializable {
private final ZonedDateTime loginTime;
private final boolean keepAlive;
private final Set<String> userGroups;
private final Set<String> userRoles;
private final Map<String, String> propertyMap;
@ -64,49 +63,28 @@ public final class Certificate implements Serializable {
* by the {@link PrivilegeHandler}
* </p>
*
* @param usage
* the usage allowed for this certificate
* @param sessionId
* the users session id
* @param username
* the users login name
* @param firstName
* the users first name
* @param lastName
* the users last name
* @param authToken
* the authentication token defining the users unique session and is a private field of this certificate.
* @param locale
* the users {@link Locale}
* @param userRoles
* the user's roles
* @param propertyMap
* a {@link Map} containing string value pairs of properties for the logged in user. These properties can be
* edited and can be used for the user to change settings of this session
* @param usage the usage allowed for this certificate
* @param sessionId the users session id
* @param username the users login name
* @param firstName the users first name
* @param lastName the users last name
* @param authToken the authentication token defining the users unique session and is a private field of this
* certificate.
* @param locale the users {@link Locale}
* @param userRoles the user's roles
* @param propertyMap a {@link Map} containing string value pairs of properties for the logged in user. These
* properties can be edited and can be used for the user to change settings of this session
*/
public Certificate(Usage usage, String sessionId, String username, String firstName, String lastName,
UserState userState, String authToken, String source, ZonedDateTime loginTime, boolean keepAlive,
Locale locale, Set<String> userRoles, Map<String, String> propertyMap) {
Locale locale, Set<String> userGroups, Set<String> userRoles, Map<String, String> propertyMap) {
// validate arguments are not null
if (StringHelper.isEmpty(sessionId)) {
throw new PrivilegeException("sessionId is null!");
}
if (StringHelper.isEmpty(username)) {
throw new PrivilegeException("username is null!");
}
if (StringHelper.isEmpty(authToken)) {
throw new PrivilegeException("authToken is null!");
}
if (userState == null) {
throw new PrivilegeException("userState is null!");
}
if (usage == null) {
throw new PrivilegeException("usage is null!");
}
if (source == null) {
throw new PrivilegeException("source is null!");
}
DBC.PRE.assertNotEmpty("sessionId must not be empty", sessionId);
DBC.PRE.assertNotEmpty("username must not be empty", username);
DBC.PRE.assertNotEmpty("authToken must not be empty", authToken);
DBC.PRE.assertNotNull("userState must not be empty", userState);
DBC.PRE.assertNotNull("usage must not be empty", usage);
DBC.PRE.assertNotNull("source must not be null", source);
this.usage = usage;
this.sessionId = sessionId;
@ -126,11 +104,12 @@ public final class Certificate implements Serializable {
this.locale = locale;
if (propertyMap == null)
this.propertyMap = Collections.emptyMap();
this.propertyMap = Map.of();
else
this.propertyMap = Collections.unmodifiableMap(propertyMap);
this.propertyMap = Map.copyOf(propertyMap);
this.userRoles = Collections.unmodifiableSet(userRoles);
this.userGroups = Set.copyOf(userGroups);
this.userRoles = Set.copyOf(userRoles);
this.lastAccess = ZonedDateTime.now();
}
@ -150,15 +129,29 @@ public final class Certificate implements Serializable {
return this.usage;
}
public Set<String> getUserGroups() {
return this.userGroups;
}
public Set<String> getUserRoles() {
return this.userRoles;
}
/**
* Returns true if the user of this certificate has the given group
*
* @param group the group to check for
*
* @return true if the user of this certificate has the given group
*/
public boolean hasGroup(String group) {
return this.userGroups.contains(group);
}
/**
* Returns true if the user of this certificate has the given role
*
* @param role
* the role to check for
* @param role the role to check for
*
* @return true if the user of this certificate has the given role
*/
@ -178,8 +171,7 @@ public final class Certificate implements Serializable {
/**
* Returns the property with the given key
*
* @param key
* the key for which the property is to be returned
* @param key the key for which the property is to be returned
*
* @return the value of the property with the given key, or null if it does not exist
*/
@ -283,12 +275,12 @@ public final class Certificate implements Serializable {
builder.append(", username=");
builder.append(this.username);
if (StringHelper.isNotEmpty(this.firstname)) {
if (isNotEmpty(this.firstname)) {
builder.append(", firstname=");
builder.append(this.firstname);
}
if (StringHelper.isNotEmpty(this.lastname)) {
if (isNotEmpty(this.lastname)) {
builder.append(", lastname=");
builder.append(this.lastname);
}

View File

@ -1,85 +0,0 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.model;
import java.util.Set;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.policy.PrivilegePolicy;
/**
* <p>
* {@link IPrivilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it
* which defines the privileges a logged in user with that role has. If the {@link IPrivilege} has a {@link
* PrivilegePolicy} defined, then that policy will be used for finer granularity and with the deny and allow lists
* configured which is used to evaluate if privilege is granted to a {@link Restrictable}
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public interface IPrivilege {
/**
* @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
*/
PrivilegeRep asPrivilegeRep();
/**
* @return the name
*/
String getName();
/**
* @return the policy
*/
String getPolicy();
/**
* @return the allAllowed
*/
boolean isAllAllowed();
/**
* @return the allowList
*/
Set<String> getAllowList();
/**
* @return the denyList
*/
Set<String> getDenyList();
/**
* @return true if there are values in the allow list
*/
boolean hasAllowed();
/**
* @return if the value is in the allow list
*/
boolean isAllowed(String value);
/**
* @return true if there are values in the deny list
*/
boolean hasDenied();
/**
* @return true if the value is in the deny list
*/
boolean isDenied(String value);
}

View File

@ -0,0 +1,140 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.model;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
import java.util.HashSet;
import java.util.Set;
/**
* <p>
* {@link Privilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it which
* defines the privileges a logged in user with that role has. If the {@link Privilege} has a {@link PrivilegePolicy}
* defined, then that policy will be used for finer granularity and with the deny and allow lists configured which is
* used to evaluate if privilege is granted to a {@link Restrictable}
* </p>
*
* @param name the name of this privilege, which is unique to all privileges known in the
* {@link PrivilegeHandler}
* @param policy the {@link PrivilegePolicy} configured to evaluate if the privilege is granted. If null, then
* privilege is granted
* @param allAllowed a boolean defining if a {@link Role} with this {@link Privilege} has unrestricted access to a
* {@link Restrictable} in which case the deny and allow lists are ignored and can be null
* @param denyList a list of deny rules for this {@link Privilege}, can be null if all allowed
* @param allowList a list of allow rules for this {@link Privilege}, can be null if all allowed
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public record Privilege(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
public Privilege(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
DBC.PRE.assertNotEmpty("name must not be empty", name);
DBC.PRE.assertNotEmpty("policy must not be empty", policy);
DBC.PRE.assertNotNull("denyList must not be null", denyList);
DBC.PRE.assertNotNull("allowList must not be null", allowList);
this.name = name;
this.allAllowed = allAllowed;
this.policy = policy;
this.denyList = Set.copyOf(denyList);
this.allowList = Set.copyOf(allowList);
}
/**
* @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
*/
public PrivilegeRep asPrivilegeRep() {
return new PrivilegeRep(this.name, this.policy, this.allAllowed, new HashSet<>(this.denyList),
new HashSet<>(this.allowList));
}
public String getName() {
return this.name;
}
public String getPolicy() {
return this.policy;
}
public boolean isAllAllowed() {
return this.allAllowed;
}
public Set<String> getAllowList() {
return this.allowList;
}
public Set<String> getDenyList() {
return this.denyList;
}
public boolean hasAllowed() {
return !this.allowList.isEmpty();
}
public boolean isAllowed(String value) {
return this.allowList.contains(value);
}
public boolean hasDenied() {
return !this.allowList.isEmpty();
}
public boolean isDenied(String value) {
return this.denyList.contains(value);
}
@Override
public String toString() {
return "Privilege [name=" + this.name + ", policy=" + this.policy + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Privilege other = (Privilege) obj;
if (this.name == null)
return other.name == null;
return this.name.equals(other.name);
}
/**
* Constructs a {@link Privilege} from the {@link PrivilegeRep}
*
* @param privilegeRep the {@link PrivilegeRep} from which to create the {@link Privilege}
*/
public static Privilege of(PrivilegeRep privilegeRep) {
return new Privilege(privilegeRep.getName(), privilegeRep.getPolicy(), privilegeRep.isAllAllowed(),
privilegeRep.getDenyList(), privilegeRep.getAllowList());
}
}

View File

@ -15,14 +15,16 @@
*/
package li.strolch.privilege.model;
import java.text.MessageFormat;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.dbc.DBC;
import java.util.Map;
import java.util.Set;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.policy.PrivilegePolicy;
import static java.text.MessageFormat.format;
import static li.strolch.privilege.i18n.PrivilegeMessages.getString;
/**
* <p>
@ -36,19 +38,15 @@ import li.strolch.privilege.policy.PrivilegePolicy;
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PrivilegeContext {
public record PrivilegeContext(UserRep userRep, Certificate certificate, Map<String, Privilege> privileges,
Map<String, PrivilegePolicy> policies) {
//
// object state
//
private final UserRep userRep;
private final Certificate certificate;
private final Map<String, IPrivilege> privileges;
private final Map<String, PrivilegePolicy> policies;
public PrivilegeContext(UserRep userRep, Certificate certificate, Map<String, IPrivilege> privileges,
public PrivilegeContext(UserRep userRep, Certificate certificate, Map<String, Privilege> privileges,
Map<String, PrivilegePolicy> policies) {
DBC.PRE.assertNotNull("userRep must not be null", userRep);
DBC.PRE.assertNotNull("certificate must not be null", certificate);
DBC.PRE.assertNotNull("privileges must not be null", privileges);
DBC.PRE.assertNotNull("policies must not be null", policies);
this.userRep = userRep;
this.certificate = certificate;
this.privileges = Map.copyOf(privileges);
@ -85,35 +83,64 @@ public class PrivilegeContext {
public void assertHasPrivilege(String privilegeName) throws AccessDeniedException {
if (!this.privileges.containsKey(privilegeName)) {
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.user"),
userRep.getUsername(), privilegeName);
String msg = format(getString("Privilege.noprivilege.user"), userRep.getUsername(), privilegeName);
throw new AccessDeniedException(msg);
}
}
public boolean hasGroup(String groupName) {
return this.userRep.hasGroup(groupName);
}
public boolean hasRole(String roleName) {
return this.userRep.hasRole(roleName);
}
public void assertHasRole(String roleName) throws AccessDeniedException {
if (!this.userRep.hasRole(roleName)) {
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.role"),
userRep.getUsername(), roleName);
public void assertHasGroup(String groupName) throws AccessDeniedException {
if (!this.userRep.hasGroup(groupName)) {
String msg = format(getString("Privilege.noprivilege.group"), userRep.getUsername(), groupName);
throw new AccessDeniedException(msg);
}
}
public void assertHasRole(String roleName) throws AccessDeniedException {
if (!this.userRep.hasRole(roleName)) {
String msg = format(getString("Privilege.noprivilege.role"), userRep.getUsername(), roleName);
throw new AccessDeniedException(msg);
}
}
public void assertHasAnyGroup(String... groupNames) throws AccessDeniedException {
for (String groupName : groupNames) {
if (this.userRep.hasGroup(groupName))
return;
}
String msg = format(getString("Privilege.noprivilege.group"), userRep.getUsername(),
String.join(", ", groupNames));
throw new AccessDeniedException(msg);
}
public void assertHasAnyRole(String... roleNames) throws AccessDeniedException {
for (String roleName : roleNames) {
if (this.userRep.hasRole(roleName))
return;
}
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.role"),
userRep.getUsername(), String.join(", ", roleNames));
String msg = format(getString("Privilege.noprivilege.role"), userRep.getUsername(),
String.join(", ", roleNames));
throw new AccessDeniedException(msg);
}
public boolean hasAnyGroup(String... groupNames) throws AccessDeniedException {
for (String groupName : groupNames) {
if (this.userRep.hasGroup(groupName))
return true;
}
return false;
}
public boolean hasAnyRole(String... roleNames) throws AccessDeniedException {
for (String roleName : roleNames) {
if (this.userRep.hasRole(roleName))
@ -123,7 +150,7 @@ public class PrivilegeContext {
return false;
}
public IPrivilege getPrivilege(String privilegeName) throws AccessDeniedException {
public Privilege getPrivilege(String privilegeName) throws AccessDeniedException {
assertHasPrivilege(privilegeName);
return this.privileges.get(privilegeName);
}
@ -132,7 +159,7 @@ public class PrivilegeContext {
PrivilegePolicy policy = this.policies.get(policyName);
if (policy == null) {
String msg = "The PrivilegePolicy {0} does not exist on the PrivilegeContext!";
throw new PrivilegeException(MessageFormat.format(msg, policyName));
throw new PrivilegeException(format(msg, policyName));
}
return policy;
}
@ -148,15 +175,12 @@ public class PrivilegeContext {
*
* <p>This method uses the {@link SimpleRestrictable} to verify access</p>
*
* @param privilegeName
* the name of the privilege to verify
* @param privilegeValue
* the value
* @param privilegeName the name of the privilege to verify
* @param privilegeValue the value
*
* @throws AccessDeniedException
* if the user does not have access
* @throws PrivilegeException
* if there is an internal error due to wrongly configured privileges or programming errors
* @throws AccessDeniedException if the user does not have access
* @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
* errors
*/
public void validateAction(String privilegeName, String privilegeValue)
throws PrivilegeException, AccessDeniedException {
@ -168,22 +192,20 @@ public class PrivilegeContext {
* has the privilege, then this method returns with no exception and void, if the user does not have the privilege,
* then a {@link AccessDeniedException} is thrown.
*
* @param restrictable
* the {@link Restrictable} which the user wants to access
* @param restrictable the {@link Restrictable} which the user wants to access
*
* @throws AccessDeniedException
* if the user does not have access
* @throws PrivilegeException
* if there is an internal error due to wrongly configured privileges or programming errors
* @throws AccessDeniedException if the user does not have access
* @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
* errors
*/
public void validateAction(Restrictable restrictable) throws PrivilegeException, AccessDeniedException {
// the privilege for the restrictable
String privilegeName = restrictable.getPrivilegeName();
IPrivilege privilege = this.privileges.get(privilegeName);
Privilege privilege = this.privileges.get(privilegeName);
if (privilege == null) {
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.accessdenied.noprivilege"),
getUsername(), privilegeName, restrictable.getClass().getName(), restrictable.getPrivilegeValue());
String msg = format(getString("Privilege.accessdenied.noprivilege"), getUsername(), privilegeName,
restrictable.getClass().getName(), restrictable.getPrivilegeValue());
throw new AccessDeniedException(msg);
}
@ -199,19 +221,18 @@ public class PrivilegeContext {
* Validates if the user for this context has the privilege to access to the given {@link Restrictable}. Returning
* true if the user has the privilege, and false if not
*
* @param restrictable
* the {@link Restrictable} which the user wants to access
* @param restrictable the {@link Restrictable} which the user wants to access
*
* @return returns true if the user has the privilege, and false if not
*
* @throws PrivilegeException
* if there is an internal error due to wrongly configured privileges or programming errors
* @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
* errors
*/
public boolean hasPrivilege(Restrictable restrictable) throws PrivilegeException {
// the privilege for the restrictable
String privilegeName = restrictable.getPrivilegeName();
IPrivilege privilege = this.privileges.get(privilegeName);
Privilege privilege = this.privileges.get(privilegeName);
if (privilege == null)
return false;
@ -229,15 +250,13 @@ public class PrivilegeContext {
*
* <p>This method uses the {@link SimpleRestrictable} to verify access</p>
*
* @param privilegeName
* the name of the privilege to verify
* @param privilegeValue
* the value
* @param privilegeName the name of the privilege to verify
* @param privilegeValue the value
*
* @return returns true if the user has the privilege, and false if not
*
* @throws PrivilegeException
* if there is an internal error due to wrongly configured privileges or programming errors
* @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
* errors
*/
public boolean hasPrivilege(String privilegeName, String privilegeValue) throws PrivilegeException {
return hasPrivilege(new SimpleRestrictable(privilegeName, privilegeValue));

View File

@ -15,27 +15,26 @@
*/
package li.strolch.privilege.model;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.helper.StringHelper;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
* To keep certain details of the {@link IPrivilege} itself hidden from remote clients and make sure instances are only
* To keep certain details of the {@link Privilege} itself hidden from remote clients and make sure instances are only
* edited by users with the correct privilege, this representational version is allowed to be viewed by remote clients
* and simply wraps all public data from the {@link IPrivilege}
* and simply wraps all public data from the {@link Privilege}
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PrivilegeRep implements Serializable {
public class PrivilegeRep {
private String name;
private String policy;
@ -46,45 +45,34 @@ public class PrivilegeRep implements Serializable {
/**
* Default constructor
*
* @param name
* the name of this privilege, which is unique to all privileges known in the {@link PrivilegeHandler}
* @param policy
* the {@link PrivilegePolicy} configured to evaluate if the privilege is granted
* @param allAllowed
* a boolean defining if a {@link Role} with this {@link IPrivilege} has unrestricted access to a {@link
* Restrictable}
* @param denyList
* a list of deny rules for this {@link IPrivilege}
* @param allowList
* a list of allow rules for this {@link IPrivilege}
* @param name the name of this privilege, which is unique to all privileges known in the
* {@link PrivilegeHandler}
* @param policy the {@link PrivilegePolicy} configured to evaluate if the privilege is granted
* @param allAllowed a boolean defining if a {@link Role} with this {@link Privilege} has unrestricted access to a
* {@link Restrictable}
* @param denyList a list of deny rules for this {@link Privilege}
* @param allowList a list of allow rules for this {@link Privilege}
*/
public PrivilegeRep(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
this.name = trimOrEmpty(name);
this.policy = trimOrEmpty(policy);
this.allAllowed = allAllowed;
this.denyList = denyList;
this.allowList = allowList;
this.denyList = denyList == null ? Set.of() : Set.copyOf(denyList);
this.allowList = allowList == null ? Set.of() : Set.copyOf(allowList);
}
/**
* Validates that all required fields are set
*/
public void validate() {
if (StringHelper.isEmpty(this.name)) {
if (isEmpty(this.name))
throw new PrivilegeException("No name defined!");
}
if (StringHelper.isEmpty(this.policy)) {
throw new PrivilegeException("policy is null!");
}
if (this.denyList == null) {
if (isEmpty(this.policy))
throw new PrivilegeException("No policy defined!");
if (this.denyList == null)
throw new PrivilegeException("denyList is null");
}
if (this.allowList == null) {
if (this.allowList == null)
throw new PrivilegeException("allowList is null");
}
}
/**
@ -95,8 +83,7 @@ public class PrivilegeRep implements Serializable {
}
/**
* @param name
* the name to set
* @param name the name to set
*/
public void setName(String name) {
this.name = trimOrEmpty(name);
@ -110,8 +97,7 @@ public class PrivilegeRep implements Serializable {
}
/**
* @param policy
* the policy to set
* @param policy the policy to set
*/
public void setPolicy(String policy) {
this.policy = trimOrEmpty(policy);
@ -125,8 +111,7 @@ public class PrivilegeRep implements Serializable {
}
/**
* @param allAllowed
* the allAllowed to set
* @param allAllowed the allAllowed to set
*/
public void setAllAllowed(boolean allAllowed) {
this.allAllowed = allAllowed;
@ -136,12 +121,11 @@ public class PrivilegeRep implements Serializable {
* @return the denyList
*/
public Set<String> getDenyList() {
return this.denyList == null ? new HashSet<>() : this.denyList;
return this.denyList;
}
/**
* @param denyList
* the denyList to set
* @param denyList the denyList to set
*/
public void setDenyList(Set<String> denyList) {
this.denyList = denyList.stream().map(String::trim).collect(Collectors.toSet());
@ -151,12 +135,11 @@ public class PrivilegeRep implements Serializable {
* @return the allowList
*/
public Set<String> getAllowList() {
return this.allowList == null ? new HashSet<>() : this.allowList;
return this.allowList;
}
/**
* @param allowList
* the allowList to set
* @param allowList the allowList to set
*/
public void setAllowList(Set<String> allowList) {
this.allowList = allowList.stream().map(String::trim).collect(Collectors.toSet());
@ -169,11 +152,8 @@ public class PrivilegeRep implements Serializable {
*/
@Override
public String toString() {
return "PrivilegeRep [name=" + this.name + ", policy=" + this.policy + ", allAllowed=" + this.allAllowed
+ ", denyList=" + (this.denyList == null ? "null" : this.denyList.size()) + ", allowList=" + (
this.allowList == null ?
"null" :
this.allowList.size()) + "]";
return "PrivilegeRep [name=" + this.name + ", policy=" + this.policy + ", allAllowed=" + this.allAllowed +
", denyList=" + this.denyList.size() + ", allowList=" + this.allowList.size() + "]";
}
@Override
@ -193,10 +173,9 @@ public class PrivilegeRep implements Serializable {
if (getClass() != obj.getClass())
return false;
PrivilegeRep other = (PrivilegeRep) obj;
if (this.name == null) {
if (this.name == null)
return other.name == null;
} else
return this.name.equals(other.name);
return this.name.equals(other.name);
}
public <T> T accept(PrivilegeElementVisitor<T> visitor) {

View File

@ -21,7 +21,7 @@ import li.strolch.privilege.policy.PrivilegePolicy;
* <p>
* Objects implementing this interface are used to grant/restrict privileges to them. A {@link PrivilegePolicy}
* implements the logic on granting/restricting privileges for a {@link Restrictable} and the {@link
* #getPrivilegeName()} is used to find the {@link IPrivilege} which has the associated {@link PrivilegePolicy} for
* #getPrivilegeName()} is used to find the {@link Privilege} which has the associated {@link PrivilegePolicy} for
* evaluating access
* </p>
*
@ -30,9 +30,9 @@ import li.strolch.privilege.policy.PrivilegePolicy;
public interface Restrictable {
/**
* Returns the name of the {@link IPrivilege} which is to be used to validate privileges against
* Returns the name of the {@link Privilege} which is to be used to validate privileges against
*
* @return the name of the {@link IPrivilege} which is to be used to validate privileges against
* @return the name of the {@link Privilege} which is to be used to validate privileges against
*/
String getPrivilegeName();

View File

@ -15,16 +15,15 @@
*/
package li.strolch.privilege.model;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.internal.Role;
import li.strolch.utils.helper.StringHelper;
import li.strolch.utils.dbc.DBC;
import java.text.MessageFormat;
import java.util.List;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
* To keep certain details of the {@link Role} itself hidden from remote clients and make sure instances are only edited
@ -33,7 +32,7 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class RoleRep implements Serializable {
public class RoleRep {
private String name;
private List<PrivilegeRep> privileges;
@ -41,32 +40,28 @@ public class RoleRep implements Serializable {
/**
* Default constructor
*
* @param name
* the name of this role
* @param privileges
* the list of privileges granted to this role
* @param name the name of this role
* @param privileges the list of privileges granted to this role
*/
public RoleRep(String name, List<PrivilegeRep> privileges) {
this.name = trimOrEmpty(name);
this.privileges = privileges;
this.privileges = privileges == null ? List.of() : List.copyOf(privileges);
}
/**
* validates that all required fields are set
*/
public void validate() {
if (StringHelper.isEmpty(this.name))
if (isEmpty(this.name))
throw new PrivilegeException("name is null");
if (this.privileges != null && !this.privileges.isEmpty()) {
for (PrivilegeRep privilege : this.privileges) {
try {
privilege.validate();
} catch (Exception e) {
String msg = "Privilege {0} is invalid on role {1}";
msg = MessageFormat.format(msg, privilege.getName(), this.name);
throw new PrivilegeException(msg, e);
}
for (PrivilegeRep privilege : this.privileges) {
try {
privilege.validate();
} catch (Exception e) {
String msg = "Privilege {0} is invalid on role {1}";
msg = MessageFormat.format(msg, privilege.getName(), this.name);
throw new PrivilegeException(msg, e);
}
}
}
@ -79,8 +74,7 @@ public class RoleRep implements Serializable {
}
/**
* @param name
* the name to set
* @param name the name to set
*/
public void setName(String name) {
this.name = trimOrEmpty(name);
@ -92,17 +86,17 @@ public class RoleRep implements Serializable {
* @return the privileges assigned to this Role as a list
*/
public List<PrivilegeRep> getPrivileges() {
return this.privileges == null ? new ArrayList<>() : this.privileges;
return this.privileges;
}
/**
* Sets the privileges on this from a list
*
* @param privileges
* the list of privileges to assign to this role
* @param privileges the list of privileges to assign to this role
*/
public void setPrivileges(List<PrivilegeRep> privileges) {
this.privileges = privileges;
DBC.PRE.assertNotNull("privileges must not be null!", privileges);
this.privileges = List.copyOf(privileges);
}
/**
@ -112,8 +106,7 @@ public class RoleRep implements Serializable {
*/
@Override
public String toString() {
return "RoleRep [name=" + this.name + ", privilegeMap=" + (this.privileges == null ? "null" : this.privileges)
+ "]";
return "RoleRep [name=" + this.name + ", privilegeMap=" + this.privileges + "]";
}
@Override
@ -133,10 +126,9 @@ public class RoleRep implements Serializable {
if (getClass() != obj.getClass())
return false;
RoleRep other = (RoleRep) obj;
if (this.name == null) {
if (this.name == null)
return other.name == null;
} else
return this.name.equals(other.name);
return this.name.equals(other.name);
}
public <T> T accept(PrivilegeElementVisitor<T> visitor) {

View File

@ -26,10 +26,8 @@ public class SimpleRestrictable implements Restrictable {
private final Object value;
/**
* @param name
* the name of the privilege
* @param value
* the value allowed on the privilege
* @param name the name of the privilege
* @param value the value allowed on the privilege
*/
public SimpleRestrictable(String name, Object value) {
DBC.PRE.assertNotEmpty("name must not be empty", name);

View File

@ -15,20 +15,20 @@
*/
package li.strolch.privilege.model;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;
import li.strolch.privilege.base.PrivilegeConstants;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.model.internal.UserHistory;
import li.strolch.utils.helper.StringHelper;
import li.strolch.utils.dbc.DBC;
import java.text.MessageFormat;
import java.util.*;
import static java.util.stream.Collectors.toSet;
import static li.strolch.privilege.base.PrivilegeConstants.*;
import static li.strolch.utils.helper.StringHelper.isEmpty;
import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
* To keep certain details of the {@link User} itself hidden from remote clients and make sure instances are only edited
@ -37,7 +37,7 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class UserRep implements Serializable {
public class UserRep {
private String userId;
private String username;
@ -45,45 +45,42 @@ public class UserRep implements Serializable {
private String lastname;
private UserState userState;
private Locale locale;
private Set<String> groups;
private Set<String> roles;
private Map<String, String> properties;
private UserHistory history;
private boolean readOnly;
/**
* Default constructor
*
* @param userId
* the user's id
* @param username
* the user's login name
* @param firstname
* the user's first name
* @param lastname
* the user's last name
* @param userState
* the user's {@link UserState}
* @param roles
* the set of {@link Role}s assigned to this user
* @param locale
* the user's {@link Locale}
* @param propertyMap
* a {@link Map} containing string value pairs of properties for this user
* @param userId the user's id
* @param username the user's login name
* @param firstname the user's first name
* @param lastname the user's last name
* @param userState the user's {@link UserState}
* @param groups the set of {@link li.strolch.privilege.model.internal.Group}s assigned to this user
* @param roles the set of {@link Role}s assigned to this user
* @param locale the user's {@link Locale}
* @param propertyMap a {@link Map} containing string value pairs of properties for this user
*/
public UserRep(String userId, String username, String firstname, String lastname, UserState userState,
Set<String> roles, Locale locale, Map<String, String> propertyMap, UserHistory history) {
Set<String> groups, Set<String> roles, Locale locale, Map<String, String> propertyMap,
UserHistory history) {
this.userId = trimOrEmpty(userId);
this.username = trimOrEmpty(username);
this.firstname = trimOrEmpty(firstname);
this.lastname = trimOrEmpty(lastname);
this.userState = userState;
this.roles = roles == null ? null : roles.stream().map(String::trim).collect(Collectors.toSet());
this.groups = groups == null ? null : groups.stream().map(String::trim).collect(toSet());
this.roles = roles == null ? null : roles.stream().map(String::trim).collect(toSet());
this.locale = locale;
if (propertyMap != null) {
this.properties = new HashMap<>();
this.properties = new HashMap<>();
if (propertyMap != null)
propertyMap.forEach((key, value) -> this.properties.put(key.trim(), value.trim()));
}
this.history = history;
}
@ -97,30 +94,52 @@ public class UserRep implements Serializable {
* Validates that all required fields are set
*/
public void validate() {
if (isEmpty(this.userId))
throw new PrivilegeException("userId must not be empty");
if (isEmpty(this.username))
throw new PrivilegeException("username must not be empty");
if (StringHelper.isEmpty(this.userId))
throw new PrivilegeException("userId is null or empty");
if (StringHelper.isEmpty(this.username))
throw new PrivilegeException("username is null or empty");
// username must be at least 2 characters in length
if (this.username.length() < 2) {
String msg = MessageFormat.format("The given username ''{0}'' is shorter than 2 characters", this.username);
// username must be at least 3 characters in length
if (this.username.length() < 3) {
String msg = MessageFormat.format("The given username ''{0}'' is shorter than 3 characters", this.username);
throw new PrivilegeException(msg);
}
if (this.userState == null)
throw new PrivilegeException("userState is null");
throw new PrivilegeException("userState may not be null");
if (StringHelper.isEmpty(this.firstname))
throw new PrivilegeException("firstname is null or empty");
if (this.userState != UserState.SYSTEM) {
if (isEmpty(this.firstname))
throw new PrivilegeException("firstname may not be empty for non-system users");
if (isEmpty(this.lastname))
throw new PrivilegeException("lastname may not be empty for non-system users");
}
if (StringHelper.isEmpty(this.lastname))
throw new PrivilegeException("lastname is null or empty");
if (this.groups == null)
throw new PrivilegeException("groups may not be null");
if (this.roles == null)
throw new PrivilegeException("roles may not be null");
if (this.roles == null || this.roles.isEmpty())
throw new PrivilegeException("roles is null or empty");
if (this.groups.isEmpty() && this.roles.isEmpty())
throw new PrivilegeException("User must have at least one group or role assigned!");
}
public boolean isReadOnly() {
return readOnly;
}
public UserRep readOnly() {
assertNotReadonly();
this.readOnly = true;
this.groups = Set.copyOf(this.groups);
this.roles = Set.copyOf(this.roles);
this.properties = Map.copyOf(this.properties);
return this;
}
protected void assertNotReadonly() {
if (this.readOnly)
throw new IllegalStateException("User is currently readOnly, to modify get a copy!");
}
public boolean isSystemUser() {
@ -145,10 +164,10 @@ public class UserRep implements Serializable {
/**
* Set the userId
*
* @param userId
* to set
* @param userId to set
*/
public void setUserId(String userId) {
assertNotReadonly();
this.userId = trimOrEmpty(userId);
}
@ -160,10 +179,10 @@ public class UserRep implements Serializable {
}
/**
* @param username
* the username to set
* @param username the username to set
*/
public void setUsername(String username) {
assertNotReadonly();
this.username = trimOrEmpty(username);
}
@ -175,10 +194,10 @@ public class UserRep implements Serializable {
}
/**
* @param firstname
* the firstname to set
* @param firstname the firstname to set
*/
public void setFirstname(String firstname) {
assertNotReadonly();
this.firstname = trimOrEmpty(firstname);
}
@ -190,10 +209,10 @@ public class UserRep implements Serializable {
}
/**
* @param lastname
* the lastname to set
* @param lastname the lastname to set
*/
public void setLastname(String lastname) {
assertNotReadonly();
this.lastname = trimOrEmpty(lastname);
}
@ -205,13 +224,27 @@ public class UserRep implements Serializable {
}
/**
* @param userState
* the userState to set
* @param userState the userState to set
*/
public void setUserState(UserState userState) {
assertNotReadonly();
this.userState = userState;
}
public Set<String> getGroups() {
return groups;
}
public void setGroups(Set<String> groups) {
DBC.PRE.assertNotNull("groups must not be null!", groups);
assertNotReadonly();
this.groups = groups.stream().map(String::trim).collect(toSet());
}
public boolean hasGroup(String group) {
return this.groups != null && this.groups.contains(group);
}
/**
* @return the roles
*/
@ -220,23 +253,16 @@ public class UserRep implements Serializable {
}
/**
* @param roles
* the roles to set
* @param roles the roles to set
*/
public void setRoles(Set<String> roles) {
this.roles = roles.stream().map(String::trim).collect(Collectors.toSet());
DBC.PRE.assertNotNull("roles must not be null!", roles);
assertNotReadonly();
this.roles = roles.stream().map(String::trim).collect(toSet());
}
/**
* Returns true if this user has the given role
*
* @param role
* the role to check for
*
* @return returns true if this user has the given role
*/
public boolean hasRole(String role) {
return this.roles.contains(role);
return this.roles != null && this.roles.contains(role);
}
/**
@ -247,10 +273,10 @@ public class UserRep implements Serializable {
}
/**
* @param locale
* the locale to set
* @param locale the locale to set
*/
public void setLocale(Locale locale) {
assertNotReadonly();
this.locale = locale;
}
@ -261,17 +287,16 @@ public class UserRep implements Serializable {
*/
public UserHistory getHistory() {
if (this.history == null)
return new UserHistory();
return UserHistory.EMPTY;
return this.history;
}
/**
* Returns true if the the given property exists
* Returns true if the given property exists
*
* @param key
* the property key to check
* @param key the property key to check
*
* @return true if the the given property exists
* @return true if the given property exists
*/
public boolean hasProperty(String key) {
return this.properties.containsKey(key);
@ -280,39 +305,41 @@ public class UserRep implements Serializable {
/**
* Returns the property with the given key
*
* @param key
* the key for which the property is to be returned
* @param key the key for which the property is to be returned
*
* @return the property with the given key, or null if the property is not defined
*/
public String getProperty(String key) {
if (this.properties == null)
return null;
return this.properties.get(key);
}
/**
* Set the property with the key to the value
*
* @param key
* the key of the property to set
* @param value
* the value of the property to set
* @param key the key of the property to set
* @param value the value of the property to set
*/
public void setProperty(String key, String value) {
if (this.properties == null)
this.properties = new HashMap<>(1);
DBC.PRE.assertNotEmpty("key must not be empty!", key);
DBC.PRE.assertNotEmpty("value must not be empty!", value);
assertNotReadonly();
this.properties.put(key.trim(), value.trim());
}
public void setProperties(Map<String, String> properties) {
DBC.PRE.assertNotNull("properties must not be null!", properties);
assertNotReadonly();
this.properties = properties;
}
/**
* Returns the {@link Set} of keys of all properties
*
* @return the {@link Set} of keys of all properties
*/
public Set<String> getPropertyKeySet() {
if (this.properties == null)
return new HashSet<>();
if (this.readOnly)
return this.properties.keySet();
return new HashSet<>(this.properties.keySet());
}
@ -322,8 +349,8 @@ public class UserRep implements Serializable {
* @return the map of properties
*/
public Map<String, String> getProperties() {
if (this.properties == null)
return new HashMap<>();
if (this.readOnly)
return this.properties;
return new HashMap<>(this.properties);
}
@ -361,9 +388,9 @@ public class UserRep implements Serializable {
*/
@Override
public String toString() {
return "UserRep [userId=" + this.userId + ", username=" + this.username + ", firstname=" + this.firstname
+ ", lastname=" + this.lastname + ", userState=" + this.userState + ", locale=" + this.locale
+ ", roles=" + this.roles + "]";
return "UserRep [userId=" + this.userId + ", username=" + this.username + ", firstname=" + this.firstname +
", lastname=" + this.lastname + ", userState=" + this.userState + ", locale=" + this.locale +
", roles=" + this.roles + "]";
}
@Override
@ -391,11 +418,12 @@ public class UserRep implements Serializable {
public UserRep getCopy() {
Set<String> roles = new HashSet<>(this.roles);
Map<String, String> propertyMap = this.properties == null ? null : new HashMap<>(this.properties);
Set<String> groups = this.groups == null ? null : new HashSet<>(this.groups);
Set<String> roles = this.roles == null ? null : new HashSet<>(this.roles);
Map<String, String> propertyMap = new HashMap<>(this.properties);
return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState, roles,
this.locale, propertyMap, this.history == null ? new UserHistory() : this.history.getClone());
return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState, groups, roles,
this.locale, propertyMap, this.history == null ? UserHistory.EMPTY : this.history);
}
public <T> T accept(PrivilegeElementVisitor<T> visitor) {

View File

@ -0,0 +1,92 @@
package li.strolch.privilege.model.internal;
import li.strolch.privilege.base.PrivilegeConstants;
import li.strolch.utils.dbc.DBC;
import java.util.Map;
import java.util.Set;
import static li.strolch.privilege.base.PrivilegeConstants.*;
/**
* This entity represents a group with which {@link User Users} can be associated. This allows to put roles and
* properties which are always duplicated on users on to the group, and the User is then in the group, eliminating
* duplication.
*/
public record Group(String name, Set<String> roles, Map<String, String> propertyMap) {
public Group(String name, Set<String> roles, Map<String, String> propertyMap) {
DBC.PRE.assertNotEmpty("name must not be empty", name);
DBC.PRE.assertNotNull("roles must not be null", roles);
DBC.PRE.assertNotNull("propertyMap must not be null", propertyMap);
this.name = name;
this.roles = Set.copyOf(roles);
this.propertyMap = Map.copyOf(propertyMap);
}
/**
* Returns true if this group has the specified role
*
* @param role the name of the {@link Role} to check for
*
* @return true if this group has the specified role
*/
public boolean hasRole(String role) {
return this.roles.contains(role);
}
/**
* Returns the property with the given key
*
* @param key the key for which the property is to be returned
*
* @return the property with the given key, or null if the property is not defined
*/
public String getProperty(String key) {
return this.propertyMap.get(key);
}
/**
* Returns the {@link Set} of keys of all properties
*
* @return the {@link Set} of keys of all properties
*/
public Set<String> getPropertyKeySet() {
return this.propertyMap.keySet();
}
/**
* Returns the map of properties
*
* @return the map of properties
*/
public Map<String, String> getProperties() {
return this.propertyMap;
}
/**
* Returns the value of the property {@link PrivilegeConstants#REALM}
*
* @return the value of the property {@link PrivilegeConstants#REALM}
*/
public String getRealm() {
return getProperty(REALM);
}
/**
* Returns the value of the property {@link PrivilegeConstants#ORGANISATION}
*
* @return the value of the property {@link PrivilegeConstants#ORGANISATION}
*/
public String getOrganisation() {
return getProperty(ORGANISATION);
}
/**
* Returns the value of the property {@link PrivilegeConstants#LOCATION}
*
* @return the value of the property {@link PrivilegeConstants#LOCATION}
*/
public String getLocation() {
return getProperty(LOCATION);
}
}

View File

@ -2,48 +2,33 @@ package li.strolch.privilege.model.internal;
import static li.strolch.utils.helper.StringHelper.*;
public class PasswordCrypt {
public record PasswordCrypt(byte[] password, byte[] salt, String hashAlgorithm, int hashIterations, int hashKeyLength) {
private final byte[] password;
private final byte[] salt;
private final String hashAlgorithm;
private final int hashIterations;
private final int hashKeyLength;
public PasswordCrypt(byte[] password, byte[] salt) {
this.password = password;
this.salt = salt;
this.hashAlgorithm = null;
this.hashIterations = -1;
this.hashKeyLength = -1;
@Override
public String toString() {
return buildPasswordString();
}
public PasswordCrypt(byte[] password, byte[] salt, String hashAlgorithm, int hashIterations, int hashKeyLength) {
this.password = password;
this.salt = salt;
this.hashAlgorithm = hashAlgorithm;
this.hashIterations = hashIterations;
this.hashKeyLength = hashKeyLength;
public String buildPasswordString() {
if (this.password == null || this.salt == null || this.hashAlgorithm == null || this.hashIterations == -1 ||
this.hashKeyLength == -1) {
return null;
}
return buildPasswordString(this.hashAlgorithm, this.hashIterations, this.hashKeyLength, this.salt,
this.password);
}
public byte[] getPassword() {
return password;
public static String buildPasswordString(String hashAlgorithm, int hashIterations, int hashKeyLength, byte[] salt,
byte[] passwordArr) {
String algo = hashAlgorithm + "," + hashIterations + "," + hashKeyLength;
String hash = toHexString(salt);
String password = toHexString(passwordArr);
return "$" + algo + "$" + hash + "$" + password;
}
public byte[] getSalt() {
return salt;
}
public String getHashAlgorithm() {
return hashAlgorithm;
}
public int getHashIterations() {
return hashIterations;
}
public int getHashKeyLength() {
return hashKeyLength;
public static PasswordCrypt of(byte[] password, byte[] salt) {
return new PasswordCrypt(password, salt, null, -1, -1);
}
public static PasswordCrypt parse(String passwordS, String saltS) {
@ -55,14 +40,14 @@ public class PasswordCrypt {
salt = fromHexString(saltS.trim());
if (isEmpty(passwordS))
return new PasswordCrypt(null, salt);
return PasswordCrypt.of(null, salt);
passwordS = passwordS.trim();
byte[] password;
if (!passwordS.startsWith("$")) {
password = fromHexString(passwordS);
return new PasswordCrypt(password, salt);
return PasswordCrypt.of(password, salt);
}
String[] parts = passwordS.split("\\$");
@ -86,28 +71,4 @@ public class PasswordCrypt {
return new PasswordCrypt(password, salt, hashAlgorithm, hashIterations, hashKeyLength);
}
@Override
public String toString() {
return buildPasswordString();
}
public String buildPasswordString() {
if (this.password == null || this.salt == null || this.hashAlgorithm == null || this.hashIterations == -1 ||
this.hashKeyLength == -1) {
return null;
}
return buildPasswordString(getHashAlgorithm(), getHashIterations(), getHashKeyLength(), getSalt(),
getPassword());
}
public static String buildPasswordString(String hashAlgorithm, int hashIterations, int hashKeyLength, byte[] salt,
byte[] passwordArr) {
String algo = hashAlgorithm + "," + hashIterations + "," + hashKeyLength;
String hash = toHexString(salt);
String password = toHexString(passwordArr);
return "$" + algo + "$" + hash + "$" + password;
}
}

View File

@ -1,223 +0,0 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.model.internal;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.PrivilegeRep;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.policy.PrivilegePolicy;
import li.strolch.utils.helper.StringHelper;
/**
* <p>
* {@link IPrivilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it
* which defines the privileges a logged in user with that role has. If the {@link IPrivilege} has a {@link
* PrivilegePolicy} defined, then that policy will be used for finer granularity and with the deny and allow lists
* configured which is used to evaluate if privilege is granted to a {@link Restrictable}
* </p>
*
* <p>
* {@link IPrivilege}s have allow and deny rules which the configured {@link PrivilegeHandler} uses to
* </p>
*
* <p>
* Note: This is an internal object which is not to be serialized or passed to clients, {@link PrivilegeRep}s are used
* for that
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public final class PrivilegeImpl implements IPrivilege {
private final String name;
private final String policy;
private final boolean allAllowed;
private final Set<String> denyList;
private final Set<String> allowList;
/**
* Default constructor
*
* @param name
* the name of this privilege, which is unique to all privileges known in the {@link PrivilegeHandler}
* @param policy
* the {@link PrivilegePolicy} configured to evaluate if the privilege is granted. If null, then privilege is
* granted
* @param allAllowed
* a boolean defining if a {@link Role} with this {@link PrivilegeImpl} has unrestricted access to a {@link
* Restrictable} in which case the deny and allow lists are ignored and can be null
* @param denyList
* a list of deny rules for this {@link PrivilegeImpl}, can be null if all allowed
* @param allowList
* a list of allow rules for this {@link PrivilegeImpl}, can be null if all allowed
*/
public PrivilegeImpl(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
if (StringHelper.isEmpty(name)) {
throw new PrivilegeException("No name defined!");
}
if (StringHelper.isEmpty(policy)) {
throw new PrivilegeException(
MessageFormat.format("Policy may not be empty for Privilege {0}!", name));
}
if (denyList == null) {
throw new PrivilegeException(
MessageFormat.format("denyList is null for Privilege {0}!", name));
}
if (allowList == null) {
throw new PrivilegeException(
MessageFormat.format("allowList is null for Privilege {0}!", name));
}
this.name = name;
this.allAllowed = allAllowed;
this.policy = policy;
this.denyList = Collections.unmodifiableSet(denyList);
this.allowList = Collections.unmodifiableSet(allowList);
}
/**
* Constructs a {@link PrivilegeImpl} from the {@link PrivilegeRep}
*
* @param privilegeRep
* the {@link PrivilegeRep} from which to create the {@link PrivilegeImpl}
*/
public PrivilegeImpl(PrivilegeRep privilegeRep) {
this(privilegeRep.getName(), privilegeRep.getPolicy(), privilegeRep.isAllAllowed(), privilegeRep.getDenyList(),
privilegeRep.getAllowList());
}
/**
* @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
*/
@Override
public PrivilegeRep asPrivilegeRep() {
return new PrivilegeRep(this.name, this.policy, this.allAllowed, new HashSet<>(this.denyList),
new HashSet<>(this.allowList));
}
/**
* @return the name
*/
@Override
public String getName() {
return this.name;
}
/**
* @return the policy
*/
@Override
public String getPolicy() {
return this.policy;
}
/**
* @return the allAllowed
*/
@Override
public boolean isAllAllowed() {
return this.allAllowed;
}
/**
* @return the allowList
*/
@Override
public Set<String> getAllowList() {
return this.allowList;
}
/**
* @return the denyList
*/
@Override
public Set<String> getDenyList() {
return this.denyList;
}
/**
* @return true if there are values in the allow list
*/
@Override
public boolean hasAllowed() {
return !this.allowList.isEmpty();
}
/**
* @return if the value is in the allow list
*/
@Override
public boolean isAllowed(String value) {
return this.allowList.contains(value);
}
/**
* @return true if there are values in the deny list
*/
@Override
public boolean hasDenied() {
return !this.allowList.isEmpty();
}
/**
* @return true if the value is in the deny list
*/
@Override
public boolean isDenied(String value) {
return this.denyList.contains(value);
}
/**
* Returns a string representation of this object displaying its concrete type and its values
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Privilege [name=" + this.name + ", policy=" + this.policy + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PrivilegeImpl other = (PrivilegeImpl) obj;
if (this.name == null) {
return other.name == null;
} else
return this.name.equals(other.name);
}
}

View File

@ -15,14 +15,16 @@
*/
package li.strolch.privilege.model.internal;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeRep;
import li.strolch.privilege.model.RoleRep;
import li.strolch.utils.dbc.DBC;
import java.util.*;
import java.util.Map.Entry;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.PrivilegeRep;
import li.strolch.privilege.model.RoleRep;
import li.strolch.utils.helper.StringHelper;
import static li.strolch.utils.helper.StringHelper.isEmpty;
/**
* <p>
@ -37,57 +39,34 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public final class Role {
private final String name;
private final Map<String, IPrivilege> privilegeMap;
/**
* Default constructor
*
* @param name
* the name of the role
* @param privilegeMap
* a map of {@link IPrivilege}s granted to this role
*/
public Role(String name, Map<String, IPrivilege> privilegeMap) {
if (StringHelper.isEmpty(name)) {
throw new PrivilegeException("No name defined!");
}
if (privilegeMap == null) {
throw new PrivilegeException("No privileges defined!");
}
public record Role(String name, Map<String, Privilege> privilegeMap) {
public Role(String name, Map<String, Privilege> privilegeMap) {
DBC.PRE.assertNotEmpty("name must not be empty", name);
DBC.PRE.assertNotNull("privilegeMap must not be null", privilegeMap);
this.name = name;
this.privilegeMap = Collections.unmodifiableMap(privilegeMap);
this.privilegeMap = Map.copyOf(privilegeMap);
}
/**
* Construct {@link Role} from its representation {@link RoleRep}
*
* @param roleRep
* the representation from which to create the {@link Role}
* @param roleRep the representation from which to create the {@link Role}
*/
public Role(RoleRep roleRep) {
public static Role of(RoleRep roleRep) {
String name = roleRep.getName();
if (StringHelper.isEmpty(name)) {
if (isEmpty(name))
throw new PrivilegeException("No name defined!");
}
if (roleRep.getPrivileges() == null) {
if (roleRep.getPrivileges() == null)
throw new PrivilegeException("Privileges may not be null!");
}
// build privileges from rep
Map<String, IPrivilege> privilegeMap = new HashMap<>(roleRep.getPrivileges().size());
Map<String, Privilege> privilegeMap = new HashMap<>(roleRep.getPrivileges().size());
for (PrivilegeRep privilege : roleRep.getPrivileges()) {
privilegeMap.put(privilege.getName(), new PrivilegeImpl(privilege));
privilegeMap.put(privilege.getName(), Privilege.of(privilege));
}
this.name = name;
this.privilegeMap = Collections.unmodifiableMap(privilegeMap);
return new Role(name, privilegeMap);
}
/**
@ -98,30 +77,29 @@ public final class Role {
}
/**
* Returns the {@link Set} of names for the currently stored {@link IPrivilege Privileges}
* Returns the {@link Set} of names for the currently stored {@link Privilege Privileges}
*
* @return the {@link Set} of names for the currently stored {@link IPrivilege Privileges}
* @return the {@link Set} of names for the currently stored {@link Privilege Privileges}
*/
public Set<String> getPrivilegeNames() {
return this.privilegeMap.keySet();
}
/**
* Returns the {@link IPrivilege} for the given name, null if it does not exist
* Returns the {@link Privilege} for the given name, null if it does not exist
*
* @return the {@link IPrivilege} for the given name, null if it does not exist
* @return the {@link Privilege} for the given name, null if it does not exist
*/
public IPrivilege getPrivilege(String name) {
public Privilege getPrivilege(String name) {
return this.privilegeMap.get(name);
}
/**
* Determines if this {@link Role} has the {@link IPrivilege} with the given name
* Determines if this {@link Role} has the {@link Privilege} with the given name
*
* @param name
* the name of the {@link IPrivilege}
* @param name the name of the {@link Privilege}
*
* @return true if this {@link Role} has the {@link IPrivilege} with the given name
* @return true if this {@link Role} has the {@link Privilege} with the given name
*/
public boolean hasPrivilege(String name) {
return this.privilegeMap.containsKey(name);
@ -132,7 +110,7 @@ public final class Role {
*/
public RoleRep asRoleRep() {
List<PrivilegeRep> privileges = new ArrayList<>();
for (Entry<String, IPrivilege> entry : this.privilegeMap.entrySet()) {
for (Entry<String, Privilege> entry : this.privilegeMap.entrySet()) {
privileges.add(entry.getValue().asPrivilegeRep());
}
return new RoleRep(this.name, privileges);

View File

@ -16,12 +16,14 @@
package li.strolch.privilege.model.internal;
import li.strolch.privilege.base.PrivilegeConstants;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.UserRep;
import li.strolch.privilege.model.UserState;
import li.strolch.utils.helper.StringHelper;
import li.strolch.utils.dbc.DBC;
import java.util.*;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import static li.strolch.privilege.base.PrivilegeConstants.*;
@ -34,59 +36,36 @@ import static li.strolch.privilege.base.PrivilegeConstants.*;
* that
* </p>
*
* @param userId the user's id
* @param username the user's login name
* @param passwordCrypt the {@link PasswordCrypt} containing user's password information
* @param firstname the user's first name
* @param lastname the user's lastname
* @param userState the user's {@link UserState}
* @param groups the set of {@link Group}s assigned to this user
* @param roles the set of {@link Role}s assigned to this user
* @param locale the user's {@link Locale}
* @param propertyMap a {@link Map} containing string value pairs of properties for this user
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public final class User {
public record User(String userId, String username, PasswordCrypt passwordCrypt, String firstname, String lastname,
UserState userState, Set<String> groups, Set<String> roles, Locale locale,
Map<String, String> propertyMap, boolean passwordChangeRequested, UserHistory history) {
private final String userId;
private final String username;
private final PasswordCrypt passwordCrypt;
private final String firstname;
private final String lastname;
private final Set<String> roles;
private final UserState userState;
private final Map<String, String> propertyMap;
private final Locale locale;
private final boolean passwordChangeRequested;
private final UserHistory history;
/**
* Default constructor
*
* @param userId the user's id
* @param username the user's login name
* @param passwordCrypt the {@link PasswordCrypt} containing user's password information
* @param firstname the user's first name
* @param lastname the user's lastname
* @param userState the user's {@link UserState}
* @param roles the set of {@link Role}s assigned to this user
* @param locale the user's {@link Locale}
* @param propertyMap a {@link Map} containing string value pairs of properties for this user
*/
public User(String userId, String username, PasswordCrypt passwordCrypt, String firstname, String lastname,
UserState userState, Set<String> roles, Locale locale, Map<String, String> propertyMap,
UserState userState, Set<String> groups, Set<String> roles, Locale locale, Map<String, String> propertyMap,
boolean passwordChangeRequested, UserHistory history) {
if (StringHelper.isEmpty(userId))
throw new PrivilegeException("No UserId defined!");
if (userState == null)
throw new PrivilegeException("No userState defined!");
if (StringHelper.isEmpty(username))
throw new PrivilegeException("No username defined!");
if (userState != UserState.SYSTEM) {
if (StringHelper.isEmpty(lastname))
throw new PrivilegeException("No lastname defined!");
if (StringHelper.isEmpty(firstname))
throw new PrivilegeException("No firstname defined!");
}
DBC.PRE.assertNotEmpty("userId must not be empty", userId);
DBC.PRE.assertNotEmpty("username must not be empty", username);
DBC.PRE.assertNotNull("userState must not be null", userState);
DBC.PRE.assertNotNull("history must not be null", history);
if (history == null)
throw new PrivilegeException("History must not be null!");
if (userState != UserState.SYSTEM) {
DBC.PRE.assertNotEmpty("lastname must not be empty when not system user!", username);
DBC.PRE.assertNotEmpty("firstname must not be empty when not system user!", firstname);
}
// passwordCrypt may be null, meaning not able to login
// roles may be null, meaning not able to login and must be added later
@ -103,35 +82,19 @@ public final class User {
this.firstname = firstname;
this.lastname = lastname;
if (roles == null)
this.roles = Collections.emptySet();
else
this.roles = Set.copyOf(roles);
if (locale == null)
this.locale = Locale.getDefault();
else
this.locale = locale;
if (propertyMap == null)
this.propertyMap = Collections.emptyMap();
else
this.propertyMap = Map.copyOf(propertyMap);
this.groups = groups == null ? Set.of() : Set.copyOf(groups);
this.roles = roles == null ? Set.of() : Set.copyOf(roles);
this.locale = locale == null ? Locale.getDefault() : locale;
this.propertyMap = propertyMap == null ? Map.of() : Map.copyOf(propertyMap);
this.passwordChangeRequested = passwordChangeRequested;
this.history = history;
}
/**
* @return the userId
*/
public String getUserId() {
return this.userId;
}
/**
* @return the username
*/
public String getUsername() {
return this.username;
}
@ -145,48 +108,34 @@ public final class User {
return this.passwordCrypt;
}
/**
* @return the first name
*/
public String getFirstname() {
return this.firstname;
}
/**
* @return the last name
*/
public String getLastname() {
return this.lastname;
}
/**
* @return the userState
*/
public UserState getUserState() {
return this.userState;
}
/**
* @return the roles
*/
public Set<String> getGroups() {
return this.groups;
}
public Set<String> getRoles() {
return this.roles;
}
/**
* Returns true if this user has the specified role
*
* @param role the name of the {@link Role} to check for
*
* @return true if the this user has the specified role
*/
public boolean hasGroup(String group) {
return this.groups.contains(group);
}
public boolean hasRole(String role) {
return this.roles.contains(role);
}
/**
* @return the locale
*/
public Locale getLocale() {
return this.locale;
}
@ -195,11 +144,6 @@ public final class User {
return this.passwordChangeRequested;
}
/**
* Returns the History object
*
* @return the History object
*/
public UserHistory getHistory() {
return this.history;
}
@ -282,8 +226,8 @@ public final class User {
* @return a {@link UserRep} which is a representation of this object used to serialize and view on clients
*/
public UserRep asUserRep() {
return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState,
new HashSet<>(this.roles), this.locale, new HashMap<>(this.propertyMap), this.history.getClone());
return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState, this.groups,
this.roles, this.locale, new HashMap<>(this.propertyMap), this.history);
}
/**
@ -315,9 +259,13 @@ public final class User {
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (this.userId == null) {
if (this.userId == null)
return other.userId == null;
} else
return this.userId.equals(other.userId);
return this.userId.equals(other.userId);
}
public User withHistory(UserHistory history) {
return new User(this.userId, this.username, this.passwordCrypt, this.firstname, this.lastname, this.userState,
this.groups, this.roles, this.locale, this.propertyMap, this.passwordChangeRequested, history);
}
}

View File

@ -1,10 +1,11 @@
package li.strolch.privilege.model.internal;
import li.strolch.privilege.model.Usage;
import li.strolch.utils.dbc.DBC;
import java.time.LocalDateTime;
import li.strolch.privilege.model.Usage;
public class UserChallenge {
public final class UserChallenge {
private final User user;
private final String challenge;
private final String source;
@ -13,6 +14,10 @@ public class UserChallenge {
private boolean fulfilled;
public UserChallenge(Usage usage, User user, String challenge, String source) {
DBC.PRE.assertNotNull("usage may not be null", usage);
DBC.PRE.assertNotNull("user may not be null", user);
DBC.PRE.assertNotNull("challenge may not be empty", challenge);
DBC.PRE.assertNotNull("source may not be empty", source);
this.usage = usage;
this.user = user;
this.challenge = challenge;

View File

@ -1,32 +1,20 @@
package li.strolch.privilege.model.internal;
import java.io.Serializable;
import java.time.ZonedDateTime;
import li.strolch.utils.iso8601.ISO8601;
import static li.strolch.utils.iso8601.ISO8601.EMPTY_VALUE_ZONED_DATE;
public class UserHistory implements Serializable {
public record UserHistory(ZonedDateTime firstLogin, ZonedDateTime lastLogin, ZonedDateTime lastPasswordChange) {
private ZonedDateTime firstLogin;
private ZonedDateTime lastLogin;
private ZonedDateTime lastPasswordChange;
public UserHistory() {
this.firstLogin = ISO8601.EMPTY_VALUE_ZONED_DATE;
this.lastLogin = ISO8601.EMPTY_VALUE_ZONED_DATE;
this.lastPasswordChange = ISO8601.EMPTY_VALUE_ZONED_DATE;
}
public static final UserHistory EMPTY = new UserHistory(EMPTY_VALUE_ZONED_DATE, EMPTY_VALUE_ZONED_DATE,
EMPTY_VALUE_ZONED_DATE);
public ZonedDateTime getFirstLogin() {
return this.firstLogin;
}
public boolean isFirstLoginEmpty() {
return this.firstLogin.equals(ISO8601.EMPTY_VALUE_ZONED_DATE);
}
public void setFirstLogin(ZonedDateTime firstLogin) {
this.firstLogin = firstLogin;
return this.firstLogin.equals(EMPTY_VALUE_ZONED_DATE);
}
public ZonedDateTime getLastLogin() {
@ -34,11 +22,7 @@ public class UserHistory implements Serializable {
}
public boolean isLastLoginEmpty() {
return this.lastLogin.equals(ISO8601.EMPTY_VALUE_ZONED_DATE);
}
public void setLastLogin(ZonedDateTime lastLogin) {
this.lastLogin = lastLogin;
return this.lastLogin.equals(EMPTY_VALUE_ZONED_DATE);
}
public ZonedDateTime getLastPasswordChange() {
@ -46,22 +30,26 @@ public class UserHistory implements Serializable {
}
public boolean isLastPasswordChangeEmpty() {
return this.lastPasswordChange.equals(ISO8601.EMPTY_VALUE_ZONED_DATE);
}
public void setLastPasswordChange(ZonedDateTime lastPasswordChange) {
this.lastPasswordChange = lastPasswordChange;
return this.lastPasswordChange.equals(EMPTY_VALUE_ZONED_DATE);
}
public boolean isEmpty() {
return isFirstLoginEmpty() && isLastLoginEmpty() && isLastPasswordChangeEmpty();
}
public UserHistory getClone() {
UserHistory clone = new UserHistory();
clone.firstLogin = this.firstLogin;
clone.lastLogin = this.lastLogin;
clone.lastPasswordChange = this.lastPasswordChange;
return clone;
public UserHistory withFirstLogin(ZonedDateTime firstLogin) {
return new UserHistory(firstLogin, this.lastLogin, lastPasswordChange);
}
public UserHistory withLastLogin(ZonedDateTime lastLogin) {
return new UserHistory(this.firstLogin, lastLogin, this.lastPasswordChange);
}
public UserHistory withLogin(ZonedDateTime lastLogin) {
return new UserHistory(isFirstLoginEmpty() ? lastLogin : this.firstLogin, lastLogin, this.lastPasswordChange);
}
public UserHistory withLastPasswordChange(ZonedDateTime lastPasswordChange) {
return new UserHistory(this.firstLogin, this.lastLogin, lastPasswordChange);
}
}

View File

@ -22,7 +22,7 @@ import java.text.MessageFormat;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@ -38,10 +38,10 @@ public class DefaultPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, IPrivilege, Restrictable)
* @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Privilege, Restrictable)
*/
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
String privilegeValue = validatePrivilegeValue(privilege, restrictable);
@ -54,7 +54,7 @@ public class DefaultPrivilege implements PrivilegePolicy {
}
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable) {
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable) {
String privilegeValue = validatePrivilegeValue(privilege, restrictable);
@ -65,7 +65,7 @@ public class DefaultPrivilege implements PrivilegePolicy {
return checkByAllowDenyValues(ctx, privilege, restrictable, privilegeValue, false);
}
private String validatePrivilegeValue(IPrivilege privilege, Restrictable restrictable) {
private String validatePrivilegeValue(Privilege privilege, Restrictable restrictable) {
PrivilegePolicyHelper.preValidate(privilege, restrictable);
// get the value on which the action is to be performed

View File

@ -17,7 +17,7 @@ package li.strolch.privilege.policy;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@ -26,7 +26,7 @@ import li.strolch.privilege.model.internal.User;
/**
* <p>
* {@link PrivilegePolicy} implements logic to determine if a {@link User} which has the given {@link Role} and the
* given {@link IPrivilege} has access to the given {@link Restrictable}
* given {@link Privilege} has access to the given {@link Restrictable}
* </p>
*
* <p>
@ -38,29 +38,29 @@ import li.strolch.privilege.model.internal.User;
public interface PrivilegePolicy {
/**
* Checks if the given {@link Role} and the given {@link IPrivilege} has access to the given {@link Restrictable}
* Checks if the given {@link Role} and the given {@link Privilege} has access to the given {@link Restrictable}
*
* @param context
* the privilege context
* @param privilege
* the {@link IPrivilege} containing the permissions
* the {@link Privilege} containing the permissions
* @param restrictable
* the {@link Restrictable} to which the user wants access
*
* @throws AccessDeniedException
* if action not allowed
*/
void validateAction(PrivilegeContext context, IPrivilege privilege, Restrictable restrictable)
void validateAction(PrivilegeContext context, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException;
/**
* Returns true if the given {@link Role} and the given {@link IPrivilege} has access to the given {@link
* Returns true if the given {@link Role} and the given {@link Privilege} has access to the given {@link
* Restrictable}
*
* @param context
* the privilege context
* @param privilege
* the {@link IPrivilege} containing the permissions
* the {@link Privilege} containing the permissions
* @param restrictable
* the {@link Restrictable} to which the user wants access
*
@ -69,6 +69,6 @@ public interface PrivilegePolicy {
* @throws AccessDeniedException
* if something goes wrong with the validate
*/
boolean hasPrivilege(PrivilegeContext context, IPrivilege privilege, Restrictable restrictable)
boolean hasPrivilege(PrivilegeContext context, Privilege privilege, Restrictable restrictable)
throws PrivilegeException;
}

View File

@ -20,7 +20,7 @@ import java.text.MessageFormat;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.utils.helper.StringHelper;
@ -34,7 +34,7 @@ public class PrivilegePolicyHelper {
* Validates the given values and returns the privilege name
*
* @param privilege
* the {@link IPrivilege}
* the {@link Privilege}
* @param restrictable
* the {@link Restrictable}
*
@ -43,7 +43,7 @@ public class PrivilegePolicyHelper {
* @throws PrivilegeException
* if something is wrong
*/
public static String preValidate(IPrivilege privilege, Restrictable restrictable) throws PrivilegeException {
public static String preValidate(Privilege privilege, Restrictable restrictable) throws PrivilegeException {
if (privilege == null)
throw new PrivilegeException(PrivilegeMessages.getString("Privilege.privilegeNull"));
if (restrictable == null)
@ -88,7 +88,7 @@ public class PrivilegePolicyHelper {
* @throws AccessDeniedException
* if access is denied
*/
public static boolean checkByAllowDenyValues(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
public static boolean checkByAllowDenyValues(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
String privilegeValue, boolean assertHasPrivilege) throws AccessDeniedException {
// first check values not allowed
@ -102,7 +102,7 @@ public class PrivilegePolicyHelper {
return handleAccessDenied(ctx, privilege, restrictable, privilegeValue, assertHasPrivilege);
}
private static boolean handleAccessDenied(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
private static boolean handleAccessDenied(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
String privilegeValue, boolean assertHasPrivilege) {
if (assertHasPrivilege) {

View File

@ -24,7 +24,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@ -42,18 +42,18 @@ import li.strolch.utils.dbc.DBC;
public class RoleAccessPrivilege implements PrivilegePolicy {
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
private boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
private boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
String privilegeName = preValidate(privilege, restrictable);

View File

@ -24,7 +24,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.User;
@ -41,18 +41,18 @@ import li.strolch.utils.dbc.DBC;
public class UserAccessPrivilege implements PrivilegePolicy {
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
String privilegeName = preValidate(privilege, restrictable);

View File

@ -28,7 +28,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.User;
@ -43,13 +43,13 @@ import li.strolch.utils.dbc.DBC;
public class UserAccessWithSameOrganisationPrivilege extends UserAccessPrivilege {
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
@ -59,7 +59,7 @@ public class UserAccessWithSameOrganisationPrivilege extends UserAccessPrivilege
}
@Override
protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
String privilegeName = preValidate(privilege, restrictable);

View File

@ -24,7 +24,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
@ -44,18 +44,18 @@ import li.strolch.privilege.model.Restrictable;
public class UsernameFromCertificatePrivilege implements PrivilegePolicy {
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
preValidate(privilege, restrictable);

View File

@ -28,7 +28,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
@ -48,19 +48,19 @@ import li.strolch.privilege.model.Restrictable;
public class UsernameFromCertificateWithSameOrganisationPrivilege extends UsernameFromCertificatePrivilege {
@Override
public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
@Override
protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
preValidate(privilege, restrictable);

View File

@ -55,19 +55,19 @@ public class CertificateStubsSaxReader extends DefaultHandler {
public void startElement(String uri, String localName, String qName, Attributes attributes) {
switch (qName) {
case XML_ROOT_CERTIFICATES -> {
case ROOT_CERTIFICATES -> {
}
case XML_CERTIFICATE -> {
case CERTIFICATE -> {
CertificateStub stub = new CertificateStub();
stub.usage = Usage.valueOf(attributes.getValue(XML_ATTR_USAGE).trim());
stub.sessionId = attributes.getValue(XML_ATTR_SESSION_ID).trim();
stub.username = attributes.getValue(XML_ATTR_USERNAME).trim();
stub.authToken = attributes.getValue(XML_ATTR_AUTH_TOKEN).trim();
stub.source = attributes.getValue(XML_ATTR_SOURCE).trim();
stub.locale = Locale.forLanguageTag(attributes.getValue(XML_ATTR_LOCALE).trim());
stub.loginTime = ISO8601.parseToZdt(attributes.getValue(XML_ATTR_LOGIN_TIME).trim());
stub.lastAccess = ISO8601.parseToZdt(attributes.getValue(XML_ATTR_LAST_ACCESS).trim());
stub.keepAlive = Boolean.parseBoolean(attributes.getValue(XML_ATTR_KEEP_ALIVE).trim());
stub.usage = Usage.valueOf(attributes.getValue(ATTR_USAGE).trim());
stub.sessionId = attributes.getValue(ATTR_SESSION_ID).trim();
stub.username = attributes.getValue(ATTR_USERNAME).trim();
stub.authToken = attributes.getValue(ATTR_AUTH_TOKEN).trim();
stub.source = attributes.getValue(ATTR_SOURCE).trim();
stub.locale = Locale.forLanguageTag(attributes.getValue(ATTR_LOCALE).trim());
stub.loginTime = ISO8601.parseToZdt(attributes.getValue(ATTR_LOGIN_TIME).trim());
stub.lastAccess = ISO8601.parseToZdt(attributes.getValue(ATTR_LAST_ACCESS).trim());
stub.keepAlive = Boolean.parseBoolean(attributes.getValue(ATTR_KEEP_ALIVE).trim());
DBC.INTERIM.assertNotEmpty("sessionId missing on sessions data!", stub.sessionId);
DBC.INTERIM.assertNotEmpty("username missing on sessions data!", stub.username);
DBC.INTERIM.assertNotEmpty("authToken missing on sessions data!", stub.authToken);

View File

@ -50,41 +50,41 @@ public class CertificateStubsSaxWriter {
Writer ioWriter = new OutputStreamWriter(this.outputStream, StandardCharsets.UTF_8);
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
xmlWriter.writeStartElement(XML_ROOT_CERTIFICATES);
xmlWriter.writeStartElement(ROOT_CERTIFICATES);
List<Certificate> certificates = new ArrayList<>(this.certificates);
certificates.sort(comparing(Certificate::getSessionId));
for (Certificate cert : certificates) {
// create the certificate element
xmlWriter.writeStartElement(XML_CERTIFICATE);
xmlWriter.writeStartElement(CERTIFICATE);
// sessionId;
xmlWriter.writeAttribute(XML_ATTR_SESSION_ID, cert.getSessionId());
xmlWriter.writeAttribute(ATTR_SESSION_ID, cert.getSessionId());
// usage;
xmlWriter.writeAttribute(XML_ATTR_USAGE, cert.getUsage().name());
xmlWriter.writeAttribute(ATTR_USAGE, cert.getUsage().name());
// username;
xmlWriter.writeAttribute(XML_ATTR_USERNAME, cert.getUsername());
xmlWriter.writeAttribute(ATTR_USERNAME, cert.getUsername());
// authToken;
xmlWriter.writeAttribute(XML_ATTR_AUTH_TOKEN, cert.getAuthToken());
xmlWriter.writeAttribute(ATTR_AUTH_TOKEN, cert.getAuthToken());
// source;
xmlWriter.writeAttribute(XML_ATTR_SOURCE, cert.getSource());
xmlWriter.writeAttribute(ATTR_SOURCE, cert.getSource());
// locale;
xmlWriter.writeAttribute(XML_ATTR_LOCALE, cert.getLocale().toLanguageTag());
xmlWriter.writeAttribute(ATTR_LOCALE, cert.getLocale().toLanguageTag());
// loginTime;
xmlWriter.writeAttribute(XML_ATTR_LOGIN_TIME, ISO8601.toString(cert.getLoginTime()));
xmlWriter.writeAttribute(ATTR_LOGIN_TIME, ISO8601.toString(cert.getLoginTime()));
// lastAccess;
xmlWriter.writeAttribute(XML_ATTR_LAST_ACCESS, ISO8601.toString(cert.getLastAccess()));
xmlWriter.writeAttribute(ATTR_LAST_ACCESS, ISO8601.toString(cert.getLastAccess()));
// keepAlive;
xmlWriter.writeAttribute(XML_ATTR_KEEP_ALIVE, String.valueOf(cert.isKeepAlive()));
xmlWriter.writeAttribute(ATTR_KEEP_ALIVE, String.valueOf(cert.isKeepAlive()));
}
// and now end

View File

@ -47,9 +47,9 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (qName) {
case XML_CONTAINER -> this.buildersStack.push(new ContainerParser());
case XML_PARAMETERS -> this.buildersStack.push(new ParametersParser());
case XML_POLICIES -> this.buildersStack.push(new PoliciesParser());
case CONTAINER -> this.buildersStack.push(new ContainerParser());
case PARAMETERS -> this.buildersStack.push(new ParametersParser());
case POLICIES -> this.buildersStack.push(new PoliciesParser());
default -> {
// nothing to do, probably handle on stack
}
@ -72,7 +72,7 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
this.buildersStack.peek().endElement(uri, localName, qName);
ElementParser elementParser = switch (qName) {
case XML_CONTAINER, XML_PARAMETERS, XML_POLICIES -> this.buildersStack.pop();
case CONTAINER, PARAMETERS, POLICIES -> this.buildersStack.pop();
default -> null;
};
@ -88,35 +88,35 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
public void startElement(String uri, String localName, String qName, Attributes attributes) {
switch (qName) {
case XML_CONTAINER -> this.currentElement = qName;
case XML_HANDLER_PRIVILEGE -> {
case CONTAINER -> this.currentElement = qName;
case HANDLER_PRIVILEGE -> {
this.currentElement = qName;
String className = attributes.getValue(XML_ATTR_CLASS).trim();
String className = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().setPrivilegeHandlerClassName(className);
}
case XML_HANDLER_ENCRYPTION -> {
case HANDLER_ENCRYPTION -> {
this.currentElement = qName;
String className = attributes.getValue(XML_ATTR_CLASS).trim();
String className = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().setEncryptionHandlerClassName(className);
}
case XML_HANDLER_PASSWORD_STRENGTH -> {
case HANDLER_PASSWORD_STRENGTH -> {
this.currentElement = qName;
String className = attributes.getValue(XML_ATTR_CLASS).trim();
String className = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().setPasswordStrengthHandlerClassName(className);
}
case XML_HANDLER_PERSISTENCE -> {
case HANDLER_PERSISTENCE -> {
this.currentElement = qName;
String className = attributes.getValue(XML_ATTR_CLASS).trim();
String className = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().setPersistenceHandlerClassName(className);
}
case XML_HANDLER_USER_CHALLENGE -> {
case HANDLER_USER_CHALLENGE -> {
this.currentElement = qName;
String className = attributes.getValue(XML_ATTR_CLASS).trim();
String className = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().setUserChallengeHandlerClassName(className);
}
case XML_HANDLER_SSO -> {
case HANDLER_SSO -> {
this.currentElement = qName;
String className = attributes.getValue(XML_ATTR_CLASS).trim();
String className = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().setSsoHandlerClassName(className);
}
default -> throw new IllegalStateException("Unexpected value: " + qName);
@ -130,14 +130,14 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
final Map<String, String> params = parametersChild.getParameterMap();
switch (this.currentElement) {
case XML_CONTAINER -> getContainerModel().setParameterMap(params);
case XML_HANDLER_PRIVILEGE -> getContainerModel().setPrivilegeHandlerParameterMap(params);
case XML_HANDLER_ENCRYPTION -> getContainerModel().setEncryptionHandlerParameterMap(params);
case XML_HANDLER_PASSWORD_STRENGTH ->
case CONTAINER -> getContainerModel().setParameterMap(params);
case HANDLER_PRIVILEGE -> getContainerModel().setPrivilegeHandlerParameterMap(params);
case HANDLER_ENCRYPTION -> getContainerModel().setEncryptionHandlerParameterMap(params);
case HANDLER_PASSWORD_STRENGTH ->
getContainerModel().setPasswordStrengthHandlerParameterMap(params);
case XML_HANDLER_PERSISTENCE -> getContainerModel().setPersistenceHandlerParameterMap(params);
case XML_HANDLER_USER_CHALLENGE -> getContainerModel().setUserChallengeHandlerParameterMap(params);
case XML_HANDLER_SSO -> getContainerModel().setSsoHandlerParameterMap(params);
case HANDLER_PERSISTENCE -> getContainerModel().setPersistenceHandlerParameterMap(params);
case HANDLER_USER_CHALLENGE -> getContainerModel().setUserChallengeHandlerParameterMap(params);
case HANDLER_SSO -> getContainerModel().setSsoHandlerParameterMap(params);
default -> throw new IllegalStateException("Unexpected value: " + this.currentElement);
}
}
@ -151,9 +151,9 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equals(XML_PARAMETER)) {
String key = attributes.getValue(XML_ATTR_NAME).trim();
String value = attributes.getValue(XML_ATTR_VALUE).trim();
if (qName.equals(PARAMETER)) {
String key = attributes.getValue(ATTR_NAME).trim();
String value = attributes.getValue(ATTR_VALUE).trim();
this.parameterMap.put(key, value);
}
}
@ -172,9 +172,9 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equals(XML_POLICY)) {
String policyName = attributes.getValue(XML_ATTR_NAME).trim();
String policyClassName = attributes.getValue(XML_ATTR_CLASS).trim();
if (qName.equals(POLICY)) {
String policyName = attributes.getValue(ATTR_NAME).trim();
String policyClassName = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().addPolicy(policyName, policyClassName);
}

View File

@ -46,41 +46,41 @@ public class PrivilegeConfigSaxWriter {
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.configFile), StandardCharsets.UTF_8)) {
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
xmlWriter.writeStartElement(XML_ROOT_PRIVILEGE);
xmlWriter.writeStartElement(ROOT_PRIVILEGE);
// write container element
xmlWriter.writeStartElement(XML_CONTAINER);
writeStringMapElement(xmlWriter, this.containerModel.getParameterMap(), XML_PARAMETERS, XML_PARAMETER);
xmlWriter.writeStartElement(CONTAINER);
writeStringMapElement(xmlWriter, this.containerModel.getParameterMap(), PARAMETERS, PARAMETER);
{
// write PrivilegeHandler
if (this.containerModel.getPrivilegeHandlerClassName() != null)
writeHandler(xmlWriter, XML_HANDLER_PRIVILEGE, this.containerModel.getPrivilegeHandlerClassName(),
writeHandler(xmlWriter, HANDLER_PRIVILEGE, this.containerModel.getPrivilegeHandlerClassName(),
this.containerModel.getPrivilegeHandlerParameterMap());
// write EncryptionHandler
writeHandler(xmlWriter, XML_HANDLER_ENCRYPTION, this.containerModel.getEncryptionHandlerClassName(),
writeHandler(xmlWriter, HANDLER_ENCRYPTION, this.containerModel.getEncryptionHandlerClassName(),
this.containerModel.getEncryptionHandlerParameterMap());
// write PersistenceHandler
writeHandler(xmlWriter, XML_HANDLER_PERSISTENCE, this.containerModel.getPersistenceHandlerClassName(),
writeHandler(xmlWriter, HANDLER_PERSISTENCE, this.containerModel.getPersistenceHandlerClassName(),
this.containerModel.getPersistenceHandlerParameterMap());
// write PasswordStrengthHandler
if (this.containerModel.getPasswordStrengthHandlerClassName() != null)
writeHandler(xmlWriter, XML_HANDLER_PASSWORD_STRENGTH,
writeHandler(xmlWriter, HANDLER_PASSWORD_STRENGTH,
this.containerModel.getPasswordStrengthHandlerClassName(),
this.containerModel.getPasswordStrengthHandlerParameterMap());
// write UserChallengeHandler
if (this.containerModel.getUserChallengeHandlerClassName() != null)
writeHandler(xmlWriter, XML_HANDLER_USER_CHALLENGE,
writeHandler(xmlWriter, HANDLER_USER_CHALLENGE,
this.containerModel.getUserChallengeHandlerClassName(),
this.containerModel.getUserChallengeHandlerParameterMap());
// write SingleSignOnHandler
if (this.containerModel.getSsoHandlerClassName() != null)
writeHandler(xmlWriter, XML_HANDLER_SSO, this.containerModel.getSsoHandlerClassName(),
writeHandler(xmlWriter, HANDLER_SSO, this.containerModel.getSsoHandlerClassName(),
this.containerModel.getSsoHandlerParameterMap());
}
@ -89,7 +89,7 @@ public class PrivilegeConfigSaxWriter {
// Policies
Map<String, String> policies = new HashMap<>();
this.containerModel.getPolicies().forEach((key, value) -> policies.put(key, value.getName()));
writeStringMapElement(xmlWriter, policies, XML_POLICIES, XML_POLICY, XML_ATTR_CLASS);
writeStringMapElement(xmlWriter, policies, POLICIES, POLICY, ATTR_CLASS);
// and now end
xmlWriter.writeEndDocument();
@ -103,9 +103,9 @@ public class PrivilegeConfigSaxWriter {
xmlWriter.writeEmptyElement(handleName);
else
xmlWriter.writeStartElement(handleName);
xmlWriter.writeAttribute(XML_ATTR_CLASS, className);
xmlWriter.writeAttribute(ATTR_CLASS, className);
writeStringMapElement(xmlWriter, parameters, XML_PARAMETERS, XML_PARAMETER);
writeStringMapElement(xmlWriter, parameters, PARAMETERS, PARAMETER);
if (!parameters.isEmpty())
xmlWriter.writeEndElement();

View File

@ -0,0 +1,174 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.xml;
import li.strolch.privilege.model.internal.Group;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.text.MessageFormat;
import java.util.*;
import static li.strolch.privilege.helper.XmlConstants.*;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PrivilegeGroupsSaxReader extends DefaultHandler {
protected static final Logger logger = LoggerFactory.getLogger(PrivilegeGroupsSaxReader.class);
private final Deque<ElementParser> buildersStack = new ArrayDeque<>();
private final Map<String, Group> groups;
public PrivilegeGroupsSaxReader() {
this.groups = new HashMap<>();
}
/**
* @return the users
*/
public Map<String, Group> getGroups() {
return this.groups;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals(GROUP)) {
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(GroupParser.class)))
throw new IllegalArgumentException("Previous Group not closed!");
this.buildersStack.push(new GroupParser());
} else if (qName.equals(PROPERTIES)) {
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
throw new IllegalArgumentException("Previous Properties not closed!");
this.buildersStack.push(new PropertyParser());
}
if (!this.buildersStack.isEmpty())
this.buildersStack.peek().startElement(uri, localName, qName, attributes);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (!this.buildersStack.isEmpty())
this.buildersStack.peek().characters(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (!this.buildersStack.isEmpty())
this.buildersStack.peek().endElement(uri, localName, qName);
ElementParser elementParser = null;
if (qName.equals(GROUP)) {
elementParser = this.buildersStack.pop();
} else if (qName.equals(PROPERTIES)) {
elementParser = this.buildersStack.pop();
}
if (!this.buildersStack.isEmpty() && elementParser != null)
this.buildersStack.peek().notifyChild(elementParser);
}
// <User userId="1" username="admin" password="8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918">
// <Firstname>Application</Firstname>
// <Lastname>Administrator</Lastname>
// <State>ENABLED</State>
// <Locale>en-GB</Locale>
// <Roles>
// <Role>PrivilegeAdmin</Role>
// <Role>AppUser</Role>
// </Roles>
// <Properties>
// <Property name="organization" value="eitchnet.ch" />
// <Property name="organizationalUnit" value="Development" />
// </Properties>
// <History>
// <FirstLogin>2021-02-19T15:32:09.592+01:00</FirstLogin>
// <LastLogin>2021-02-19T15:32:09.592+01:00</LastLogin>
// <LastPasswordChange>2021-02-19T15:32:09.592+01:00</LastPasswordChange>
// </History>
// </User>
public class GroupParser extends ElementParserAdapter {
StringBuilder text;
String name;
final Set<String> roles;
Map<String, String> parameters;
public GroupParser() {
this.roles = new HashSet<>();
this.parameters = new HashMap<>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
this.text = new StringBuilder();
if (qName.equals(GROUP)) {
this.name = attributes.getValue(ATTR_NAME).trim();
}
}
@Override
public void characters(char[] ch, int start, int length) {
this.text.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) {
switch (qName) {
case ROLE -> this.roles.add(getText());
case GROUP -> {
Group group = new Group(this.name, this.roles, this.parameters);
logger.info(MessageFormat.format("New Group: {0}", group));
groups.put(this.name, group);
}
default -> {
if (!(qName.equals(GROUPS) //
|| qName.equals(ROLES) //
|| qName.equals(PARAMETER) //
|| qName.equals(PARAMETERS))) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
}
}
private String getText() {
return this.text.toString().trim();
}
@Override
public void notifyChild(ElementParser child) {
if (child instanceof PropertyParser) {
this.parameters = ((PropertyParser) child).parameterMap;
}
}
}
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.xml;
import javanet.staxutils.IndentingXMLStreamWriter;
import li.strolch.privilege.model.internal.Group;
import javax.xml.stream.XMLStreamException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static java.util.Comparator.comparing;
import static li.strolch.privilege.helper.XmlConstants.*;
import static li.strolch.privilege.helper.XmlHelper.*;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PrivilegeGroupsSaxWriter {
private final List<Group> groups;
private final File modelFile;
public PrivilegeGroupsSaxWriter(List<Group> groups, File modelFile) {
this.groups = groups;
this.modelFile = modelFile;
}
public void write() throws IOException, XMLStreamException {
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.modelFile), StandardCharsets.UTF_8)) {
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
xmlWriter.writeStartElement(GROUPS);
List<Group> groups = new ArrayList<>(this.groups);
groups.sort(comparing(g -> g.name().toLowerCase(Locale.ROOT)));
for (Group group : this.groups) {
// start the user element
xmlWriter.writeStartElement(GROUP);
xmlWriter.writeAttribute(ATTR_NAME, group.name());
// add all the role elements
if (!group.roles().isEmpty()) {
xmlWriter.writeStartElement(ROLES);
writeStringList(xmlWriter, ROLE, group.roles());
xmlWriter.writeEndElement();
}
// add the parameters
Map<String, String> properties = group.getProperties();
if (!properties.isEmpty())
writeStringMapElement(xmlWriter, properties, PROPERTIES, PROPERTY);
xmlWriter.writeEndElement();
}
// and now end
xmlWriter.writeEndDocument();
xmlWriter.flush();
}
}
}

View File

@ -15,8 +15,7 @@
*/
package li.strolch.privilege.xml;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.internal.PrivilegeImpl;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.internal.Role;
import li.strolch.utils.helper.StringHelper;
import org.slf4j.Logger;
@ -52,11 +51,11 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals(XML_ROLE)) {
if (qName.equals(ROLE)) {
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(RoleParser.class)))
throw new IllegalArgumentException("Previous Role not closed!");
this.buildersStack.push(new RoleParser());
} else if (qName.equals(XML_PROPERTIES)) {
} else if (qName.equals(PROPERTIES)) {
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
throw new IllegalArgumentException("Previous Properties not closed!");
this.buildersStack.push(new PropertyParser());
@ -79,9 +78,9 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
this.buildersStack.peek().endElement(uri, localName, qName);
ElementParser elementParser = null;
if (qName.equals(XML_ROLE)) {
if (qName.equals(ROLE)) {
elementParser = this.buildersStack.pop();
} else if (qName.equals(XML_PROPERTIES)) {
} else if (qName.equals(PROPERTIES)) {
elementParser = this.buildersStack.pop();
}
@ -114,7 +113,7 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
private Set<String> denyList;
private Set<String> allowList;
private Map<String, IPrivilege> privileges;
private Map<String, Privilege> privileges;
public RoleParser() {
init();
@ -139,12 +138,12 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
this.text = new StringBuilder();
switch (qName) {
case XML_ROLE -> this.roleName = attributes.getValue(XML_ATTR_NAME).trim();
case XML_PRIVILEGE -> {
this.privilegeName = attributes.getValue(XML_ATTR_NAME).trim();
this.privilegePolicy = attributes.getValue(XML_ATTR_POLICY).trim();
case ROLE -> this.roleName = attributes.getValue(ATTR_NAME).trim();
case PRIVILEGE -> {
this.privilegeName = attributes.getValue(ATTR_NAME).trim();
this.privilegePolicy = attributes.getValue(ATTR_POLICY).trim();
}
case XML_ALLOW, XML_DENY, XML_ALL_ALLOWED -> {
case ALLOW, DENY, ALL_ALLOWED -> {
}
// no-op
default -> throw new IllegalArgumentException("Unhandled tag " + qName);
@ -160,11 +159,11 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
@Override
public void endElement(String uri, String localName, String qName) {
switch (qName) {
case XML_ALL_ALLOWED -> this.allAllowed = StringHelper.parseBoolean(getText());
case XML_ALLOW -> this.allowList.add(getText());
case XML_DENY -> this.denyList.add(getText());
case XML_PRIVILEGE -> {
IPrivilege privilege = new PrivilegeImpl(this.privilegeName, this.privilegePolicy, this.allAllowed,
case ALL_ALLOWED -> this.allAllowed = StringHelper.parseBoolean(getText());
case ALLOW -> this.allowList.add(getText());
case DENY -> this.denyList.add(getText());
case PRIVILEGE -> {
Privilege privilege = new Privilege(this.privilegeName, this.privilegePolicy, this.allAllowed,
this.denyList, this.allowList);
this.privileges.put(this.privilegeName, privilege);
this.privilegeName = null;
@ -173,7 +172,7 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
this.denyList = new HashSet<>();
this.allowList = new HashSet<>();
}
case XML_ROLE -> {
case ROLE -> {
Role role = new Role(this.roleName, this.privileges);
roles.put(role.getName(), role);
logger.info(MessageFormat.format("New Role: {0}", role));
@ -196,11 +195,11 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equals(XML_PROPERTY)) {
String key = attributes.getValue(XML_ATTR_NAME).trim();
String value = attributes.getValue(XML_ATTR_VALUE).trim();
if (qName.equals(PROPERTY)) {
String key = attributes.getValue(ATTR_NAME).trim();
String value = attributes.getValue(ATTR_VALUE).trim();
this.parameterMap.put(key, value);
} else if (!qName.equals(XML_PROPERTIES)) {
} else if (!qName.equals(PROPERTIES)) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}

View File

@ -16,7 +16,7 @@
package li.strolch.privilege.xml;
import javanet.staxutils.IndentingXMLStreamWriter;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.internal.Role;
import javax.xml.stream.XMLStreamException;
@ -48,29 +48,29 @@ public class PrivilegeRolesSaxWriter {
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.modelFile), StandardCharsets.UTF_8)) {
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
xmlWriter.writeStartElement(XML_ROLES);
xmlWriter.writeStartElement(ROLES);
List<Role> roles = new ArrayList<>(this.roles);
roles.sort(comparing(role1 -> role1.getName().toLowerCase(Locale.ROOT)));
roles.sort(comparing(r -> r.getName().toLowerCase(Locale.ROOT)));
for (Role role : roles) {
// start the role element
xmlWriter.writeStartElement(XML_ROLE);
xmlWriter.writeAttribute(XML_ATTR_NAME, role.getName());
xmlWriter.writeStartElement(ROLE);
xmlWriter.writeAttribute(ATTR_NAME, role.getName());
List<String> privilegeNames = new ArrayList<>(role.getPrivilegeNames());
privilegeNames.sort(null);
for (String privilegeName : privilegeNames) {
IPrivilege privilege = role.getPrivilege(privilegeName);
Privilege privilege = role.getPrivilege(privilegeName);
xmlWriter.writeStartElement(XML_PRIVILEGE);
xmlWriter.writeAttribute(XML_ATTR_NAME, privilege.getName());
xmlWriter.writeAttribute(XML_ATTR_POLICY, privilege.getPolicy());
xmlWriter.writeStartElement(PRIVILEGE);
xmlWriter.writeAttribute(ATTR_NAME, privilege.getName());
xmlWriter.writeAttribute(ATTR_POLICY, privilege.getPolicy());
if (privilege.isAllAllowed())
writeStringElement(xmlWriter, XML_ALL_ALLOWED, "true");
writeStringList(xmlWriter, XML_DENY, privilege.getDenyList());
writeStringList(xmlWriter, XML_ALLOW, privilege.getAllowList());
writeStringElement(xmlWriter, ALL_ALLOWED, "true");
writeStringList(xmlWriter, DENY, privilege.getDenyList());
writeStringList(xmlWriter, ALLOW, privilege.getAllowList());
xmlWriter.writeEndElement();
}

View File

@ -16,6 +16,7 @@
package li.strolch.privilege.xml;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.Group;
import li.strolch.privilege.model.internal.PasswordCrypt;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.model.internal.UserHistory;
@ -57,11 +58,11 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equals(XML_USER)) {
if (qName.equals(USER)) {
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(UserParser.class)))
throw new IllegalArgumentException("Previous User not closed!");
this.buildersStack.push(new UserParser());
} else if (qName.equals(XML_PROPERTIES)) {
} else if (qName.equals(PROPERTIES)) {
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
throw new IllegalArgumentException("Previous Properties not closed!");
this.buildersStack.push(new PropertyParser());
@ -84,9 +85,9 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
this.buildersStack.peek().endElement(uri, localName, qName);
ElementParser elementParser = null;
if (qName.equals(XML_USER)) {
if (qName.equals(USER)) {
elementParser = this.buildersStack.pop();
} else if (qName.equals(XML_PROPERTIES)) {
} else if (qName.equals(PROPERTIES)) {
elementParser = this.buildersStack.pop();
}
@ -125,12 +126,14 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
String lastname;
UserState userState;
Locale locale;
final Set<String> groups;
final Set<String> userRoles;
Map<String, String> parameters;
UserHistory history;
boolean passwordChangeRequested;
public UserParser() {
this.groups = new HashSet<>();
this.userRoles = new HashSet<>();
}
@ -139,15 +142,15 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
this.text = new StringBuilder();
if (qName.equals(XML_USER)) {
this.userId = attributes.getValue(XML_ATTR_USER_ID).trim();
this.username = attributes.getValue(XML_ATTR_USERNAME).trim();
if (qName.equals(USER)) {
this.userId = attributes.getValue(ATTR_USER_ID).trim();
this.username = attributes.getValue(ATTR_USERNAME).trim();
String password = attributes.getValue(XML_ATTR_PASSWORD);
String salt = attributes.getValue(XML_ATTR_SALT);
String password = attributes.getValue(ATTR_PASSWORD);
String salt = attributes.getValue(ATTR_SALT);
this.passwordCrypt = PasswordCrypt.parse(password, salt);
} else if (qName.equals(XML_HISTORY)) {
this.history = new UserHistory();
} else if (qName.equals(HISTORY)) {
this.history = UserHistory.EMPTY;
}
}
@ -160,32 +163,35 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
public void endElement(String uri, String localName, String qName) {
switch (qName) {
case XML_FIRSTNAME -> this.firstName = getText();
case XML_LASTNAME -> this.lastname = getText();
case XML_STATE -> this.userState = UserState.valueOf(getText());
case XML_LOCALE -> this.locale = Locale.forLanguageTag(getText());
case XML_PASSWORD_CHANGE_REQUESTED -> this.passwordChangeRequested = Boolean.parseBoolean(getText());
case XML_FIRST_LOGIN -> this.history.setFirstLogin(ISO8601.parseToZdt(getText()));
case XML_LAST_LOGIN -> this.history.setLastLogin(ISO8601.parseToZdt(getText()));
case XML_LAST_PASSWORD_CHANGE -> this.history.setLastPasswordChange(ISO8601.parseToZdt(getText()));
case XML_ROLE -> this.userRoles.add(getText());
case XML_USER -> {
case FIRSTNAME -> this.firstName = getText();
case LASTNAME -> this.lastname = getText();
case STATE -> this.userState = UserState.valueOf(getText());
case LOCALE -> this.locale = Locale.forLanguageTag(getText());
case PASSWORD_CHANGE_REQUESTED -> this.passwordChangeRequested = Boolean.parseBoolean(getText());
case FIRST_LOGIN -> this.history = this.history.withFirstLogin(ISO8601.parseToZdt(getText()));
case LAST_LOGIN -> this.history = this.history.withLastLogin(ISO8601.parseToZdt(getText()));
case LAST_PASSWORD_CHANGE ->
this.history = this.history.withLastPasswordChange(ISO8601.parseToZdt(getText()));
case GROUP -> this.groups.add(getText());
case ROLE -> this.userRoles.add(getText());
case USER -> {
if (this.history == null)
this.history = new UserHistory();
this.history = UserHistory.EMPTY;
User user = new User(this.userId, this.username, this.passwordCrypt, this.firstName, this.lastname,
this.userState, this.userRoles, this.locale, this.parameters, this.passwordChangeRequested,
this.history);
this.userState, this.groups, this.userRoles, this.locale, this.parameters,
this.passwordChangeRequested, this.history);
logger.info(MessageFormat.format("New User: {0}", user));
String username = caseInsensitiveUsername ? user.getUsername().toLowerCase() : user.getUsername();
users.put(username, user);
}
default -> {
if (!(qName.equals(XML_ROLES) //
|| qName.equals(XML_PARAMETER) //
|| qName.equals(XML_HISTORY) //
|| qName.equals(XML_PARAMETERS))) {
if (!(qName.equals(ROLES) //
|| qName.equals(GROUPS) //
|| qName.equals(PARAMETER) //
|| qName.equals(HISTORY) //
|| qName.equals(PARAMETERS))) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
@ -203,29 +209,4 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
}
}
}
static class PropertyParser extends ElementParserAdapter {
// <Property name="organizationalUnit" value="Development" />
public final Map<String, String> parameterMap = new HashMap<>();
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equals(XML_PROPERTY)) {
String key = attributes.getValue(XML_ATTR_NAME).trim();
String value = attributes.getValue(XML_ATTR_VALUE).trim();
this.parameterMap.put(key, value);
} else {
if (!qName.equals(XML_PROPERTIES)) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
}
public Map<String, String> getParameterMap() {
return this.parameterMap;
}
}
}

View File

@ -47,8 +47,6 @@ public class PrivilegeUsersSaxWriter {
public PrivilegeUsersSaxWriter(List<User> users, File modelFile) {
this.users = users;
this.modelFile = modelFile;
this.users.sort(comparing(User::getUsername));
}
public void write() throws IOException, XMLStreamException {
@ -56,62 +54,68 @@ public class PrivilegeUsersSaxWriter {
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.modelFile), StandardCharsets.UTF_8)) {
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
xmlWriter.writeStartElement(XML_USERS);
xmlWriter.writeStartElement(USERS);
List<User> users = new ArrayList<>(this.users);
users.sort(comparing(u -> u.getUsername().toLowerCase(Locale.ROOT)));
for (User user : this.users) {
// start the user element
xmlWriter.writeStartElement(XML_USER);
xmlWriter.writeStartElement(USER);
xmlWriter.writeAttribute(XML_ATTR_USER_ID, user.getUserId());
xmlWriter.writeAttribute(XML_ATTR_USERNAME, user.getUsername());
xmlWriter.writeAttribute(ATTR_USER_ID, user.getUserId());
xmlWriter.writeAttribute(ATTR_USERNAME, user.getUsername());
writePassword(user, xmlWriter);
// add first name element
if (isNotEmpty(user.getFirstname()))
writeStringElement(xmlWriter, XML_FIRSTNAME, user.getFirstname());
writeStringElement(xmlWriter, FIRSTNAME, user.getFirstname());
// add last name element
if (isNotEmpty(user.getLastname()))
writeStringElement(xmlWriter, XML_LASTNAME, user.getLastname());
writeStringElement(xmlWriter, LASTNAME, user.getLastname());
// add state element
writeStringElement(xmlWriter, XML_STATE, user.getUserState().toString());
writeStringElement(xmlWriter, STATE, user.getUserState().toString());
// add locale element
writeStringElement(xmlWriter, XML_LOCALE, user.getLocale().toLanguageTag());
writeStringElement(xmlWriter, LOCALE, user.getLocale().toLanguageTag());
// add password change requested element
if (user.isPasswordChangeRequested())
writeStringElement(xmlWriter, XML_PASSWORD_CHANGE_REQUESTED, "true");
writeStringElement(xmlWriter, PASSWORD_CHANGE_REQUESTED, "true");
// add all the group elements
if (!user.getGroups().isEmpty()) {
xmlWriter.writeStartElement(GROUPS);
writeStringList(xmlWriter, GROUP, user.getGroups());
xmlWriter.writeEndElement();
}
// add all the role elements
if (!user.getRoles().isEmpty()) {
xmlWriter.writeStartElement(XML_ROLES);
writeStringList(xmlWriter, XML_ROLE, user.getRoles());
xmlWriter.writeStartElement(ROLES);
writeStringList(xmlWriter, ROLE, user.getRoles());
xmlWriter.writeEndElement();
}
// add the parameters
Map<String, String> properties = user.getProperties();
if (!properties.isEmpty()) {
writeStringMapElement(xmlWriter, properties, XML_PROPERTIES, XML_PROPERTY);
}
if (!properties.isEmpty())
writeStringMapElement(xmlWriter, properties, PROPERTIES, PROPERTY);
if (!user.isHistoryEmpty()) {
UserHistory history = user.getHistory();
xmlWriter.writeStartElement(XML_HISTORY);
xmlWriter.writeStartElement(HISTORY);
if (!history.isFirstLoginEmpty())
writeStringElement(xmlWriter, XML_FIRST_LOGIN, ISO8601.toString(history.getFirstLogin()));
writeStringElement(xmlWriter, FIRST_LOGIN, ISO8601.toString(history.getFirstLogin()));
if (!history.isLastLoginEmpty())
writeStringElement(xmlWriter, XML_LAST_LOGIN, ISO8601.toString(history.getLastLogin()));
writeStringElement(xmlWriter, LAST_LOGIN, ISO8601.toString(history.getLastLogin()));
if (!history.isLastPasswordChangeEmpty())
writeStringElement(xmlWriter, XML_LAST_PASSWORD_CHANGE,
writeStringElement(xmlWriter, LAST_PASSWORD_CHANGE,
ISO8601.toString(history.getLastPasswordChange()));
xmlWriter.writeEndElement();
@ -133,12 +137,12 @@ public class PrivilegeUsersSaxWriter {
String passwordString = passwordCrypt.buildPasswordString();
if (passwordString != null) {
xmlStreamWriter.writeAttribute(XML_ATTR_PASSWORD, passwordString);
xmlStreamWriter.writeAttribute(ATTR_PASSWORD, passwordString);
} else {
if (passwordCrypt.getPassword() != null)
xmlStreamWriter.writeAttribute(XML_ATTR_PASSWORD, toHexString(passwordCrypt.getPassword()));
if (passwordCrypt.getSalt() != null)
xmlStreamWriter.writeAttribute(XML_ATTR_SALT, toHexString(passwordCrypt.getSalt()));
if (passwordCrypt.password() != null)
xmlStreamWriter.writeAttribute(ATTR_PASSWORD, toHexString(passwordCrypt.password()));
if (passwordCrypt.salt() != null)
xmlStreamWriter.writeAttribute(ATTR_SALT, toHexString(passwordCrypt.salt()));
}
}
}

View File

@ -0,0 +1,33 @@
package li.strolch.privilege.xml;
import org.xml.sax.Attributes;
import java.util.HashMap;
import java.util.Map;
import static li.strolch.privilege.helper.XmlConstants.*;
class PropertyParser extends ElementParserAdapter {
// <Property name="organizationalUnit" value="Development" />
public final Map<String, String> parameterMap = new HashMap<>();
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if (qName.equals(PROPERTY)) {
String key = attributes.getValue(ATTR_NAME).trim();
String value = attributes.getValue(ATTR_VALUE).trim();
this.parameterMap.put(key, value);
} else {
if (!qName.equals(PROPERTIES)) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
}
public Map<String, String> getParameterMap() {
return this.parameterMap;
}
}

View File

@ -11,6 +11,7 @@ Privilege.privilegeNameEmpty=The PrivilegeName for the Restrictable is null or e
Privilege.privilegeNull=Privilege may not be null\!
Privilege.restrictableNull=Restrictable may not be null\!
Privilege.noprivilege=No Privilege exists with name {0}
Privilege.noprivilege.group=User {0} does not belong to group {1}
Privilege.noprivilege.role=User {0} does not have the role {1}
Privilege.noprivilege.user=User {0} does not have the privilege {1}
Privilege.roleAccessPrivilege.unknownPrivilege=Unhandled privilege {0} for policy {1}

View File

@ -1,12 +1,5 @@
package li.strolch.privilege.test;
import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.nio.file.Files;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.helper.PrivilegeInitializer;
@ -18,6 +11,13 @@ import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.nio.file.Files;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import static org.junit.Assert.assertNotNull;
public class AbstractPrivilegeTest {
protected static final Logger logger = LoggerFactory.getLogger(AbstractPrivilegeTest.class);
@ -57,13 +57,14 @@ public class AbstractPrivilegeTest {
}
}
protected static void prepareConfigs(String dst, String configFilename, String usersFilename,
protected static void prepareConfigs(String dst, String configFilename, String usersFilename, String groupsFilename,
String rolesFilename) {
try {
File configPath = new File("src/test/resources/config");
File privilegeConfigFile = new File(configPath, configFilename);
File privilegeUsersFile = new File(configPath, usersFilename);
File privilegeGroupsFile = new File(configPath, groupsFilename);
File privilegeRolesFile = new File(configPath, rolesFilename);
File targetPath = new File("target/" + dst);
@ -72,6 +73,7 @@ public class AbstractPrivilegeTest {
File dstConfig = new File(targetPath, configFilename);
File dstUsers = new File(targetPath, usersFilename);
File dstGroups = new File(targetPath, groupsFilename);
File dstRoles = new File(targetPath, rolesFilename);
// write config
@ -81,6 +83,7 @@ public class AbstractPrivilegeTest {
// copy model
Files.copy(privilegeUsersFile.toPath(), dstUsers.toPath());
Files.copy(privilegeGroupsFile.toPath(), dstGroups.toPath());
Files.copy(privilegeRolesFile.toPath(), dstRoles.toPath());
} catch (Exception e) {

View File

@ -20,9 +20,9 @@ public class CryptTest {
@BeforeClass
public static void beforeClass() {
Map<String, String> parameterMap = new HashMap<>();
parameterMap.put(XML_PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
parameterMap.put(XML_PARAM_HASH_ITERATIONS, "" + DEFAULT_SMALL_ITERATIONS);
parameterMap.put(XML_PARAM_HASH_KEY_LENGTH, "" + DEFAULT_KEY_LENGTH);
parameterMap.put(PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
parameterMap.put(PARAM_HASH_ITERATIONS, "" + DEFAULT_SMALL_ITERATIONS);
parameterMap.put(PARAM_HASH_KEY_LENGTH, "" + DEFAULT_KEY_LENGTH);
encryptionHandler = new DefaultEncryptionHandler();
encryptionHandler.initialize(parameterMap);
@ -41,7 +41,7 @@ public class CryptTest {
PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, salt, "PBKDF2WithHmacSHA512", 100000,
256);
assertArrayEquals(passwordCrypt.getPassword(), parsedCryptHash.getPassword());
assertArrayEquals(passwordCrypt.password(), parsedCryptHash.password());
}
@Test
@ -53,9 +53,9 @@ public class CryptTest {
assertNotNull(parsedCryptHash);
char[] password = "admin".toCharArray();
PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, parsedCryptHash.getSalt(),
PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, parsedCryptHash.salt(),
"PBKDF2WithHmacSHA512", 100000, 256);
assertArrayEquals(passwordCrypt.getPassword(), parsedCryptHash.getPassword());
assertArrayEquals(passwordCrypt.password(), parsedCryptHash.password());
}
}

View File

@ -16,7 +16,7 @@ public class PersistSessionsTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(PersistSessionsTest.class.getSimpleName());
prepareConfigs(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeUsers.xml",
"PrivilegeRoles.xml");
"PrivilegeGroups.xml", "PrivilegeRoles.xml");
}
@AfterClass

View File

@ -15,14 +15,16 @@
*/
package li.strolch.privilege.test;
import static org.junit.Assert.*;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Set;
import static org.junit.Assert.*;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -32,7 +34,7 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(PrivilegeConflictMergeTest.class.getSimpleName());
prepareConfigs(PrivilegeConflictMergeTest.class.getSimpleName(), "PrivilegeConfigMerge.xml",
"PrivilegeUsersMerge.xml", "PrivilegeRolesMerge.xml");
"PrivilegeUsersMerge.xml", "PrivilegeGroupsMerge.xml", "PrivilegeRolesMerge.xml");
}
@AfterClass
@ -49,7 +51,16 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
public void shouldMergePrivileges1() {
try {
login("userA", "admin".toCharArray());
IPrivilege privilege = this.ctx.getPrivilege("Foo");
assertEquals(Set.of(), this.ctx.getUserRep().getGroups());
assertFalse(this.ctx.hasGroup("GroupA1"));
assertFalse(this.ctx.hasGroup("GroupA2"));
assertEquals(Set.of("RoleA1", "RoleA2"), this.ctx.getUserRep().getRoles());
assertTrue(this.ctx.hasRole("RoleA1"));
assertTrue(this.ctx.hasRole("RoleA2"));
assertFalse(this.ctx.hasRole("RoleB2"));
assertNull(this.ctx.getUserRep().getLocation());
assertEquals(Set.of(), this.ctx.getUserRep().getPropertyKeySet());
Privilege privilege = this.ctx.getPrivilege("Foo");
assertTrue(privilege.isAllAllowed());
assertTrue(privilege.getAllowList().isEmpty());
assertTrue(privilege.getDenyList().isEmpty());
@ -63,7 +74,16 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
public void shouldMergePrivileges2() {
try {
login("userB", "admin".toCharArray());
IPrivilege privilege = this.ctx.getPrivilege("Bar");
assertEquals(Set.of(), this.ctx.getUserRep().getGroups());
assertFalse(this.ctx.hasGroup("GroupB1"));
assertFalse(this.ctx.hasGroup("GroupB2"));
assertEquals(Set.of("RoleB1", "RoleB2"), this.ctx.getUserRep().getRoles());
assertTrue(this.ctx.hasRole("RoleB1"));
assertTrue(this.ctx.hasRole("RoleB2"));
assertFalse(this.ctx.hasRole("RoleA2"));
assertNull(this.ctx.getUserRep().getLocation());
assertEquals(Set.of(), this.ctx.getUserRep().getPropertyKeySet());
Privilege privilege = this.ctx.getPrivilege("Bar");
assertFalse(privilege.isAllAllowed());
assertEquals(2, privilege.getAllowList().size());
assertEquals(2, privilege.getDenyList().size());
@ -71,4 +91,53 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
logout();
}
}
@Test
public void shouldMergePrivileges3() {
try {
login("userC", "admin".toCharArray());
assertEquals(Set.of("GroupA1", "GroupA2"), this.ctx.getUserRep().getGroups());
assertTrue(this.ctx.hasGroup("GroupA1"));
assertTrue(this.ctx.hasGroup("GroupA2"));
assertFalse(this.ctx.hasGroup("GroupB2"));
assertEquals(Set.of("RoleA1", "RoleA2"), this.ctx.getUserRep().getRoles());
assertTrue(this.ctx.hasRole("RoleA1"));
assertTrue(this.ctx.hasRole("RoleA2"));
assertFalse(this.ctx.hasRole("RoleB2"));
assertEquals("LocationA2", this.ctx.getUserRep().getLocation());
assertEquals(Set.of("location"), this.ctx.getUserRep().getPropertyKeySet());
Privilege privilege = this.ctx.getPrivilege("Foo");
assertTrue(privilege.isAllAllowed());
assertTrue(privilege.getAllowList().isEmpty());
assertTrue(privilege.getDenyList().isEmpty());
} finally {
logout();
}
}
@Test
public void shouldMergePrivileges4() {
try {
login("userD", "admin".toCharArray());
assertEquals(Set.of("GroupB1", "GroupB2"), this.ctx.getUserRep().getGroups());
assertTrue(this.ctx.hasGroup("GroupB1"));
assertTrue(this.ctx.hasGroup("GroupB2"));
assertFalse(this.ctx.hasGroup("GroupA2"));
assertEquals(Set.of("RoleB1", "RoleB2"), this.ctx.getUserRep().getRoles());
assertTrue(this.ctx.hasRole("RoleB1"));
assertTrue(this.ctx.hasRole("RoleB2"));
assertFalse(this.ctx.hasRole("RoleA2"));
assertEquals("LocationB2", this.ctx.getUserRep().getLocation());
assertEquals(Set.of("location"), this.ctx.getUserRep().getPropertyKeySet());
Privilege privilege = this.ctx.getPrivilege("Bar");
assertFalse(privilege.isAllAllowed());
assertEquals(2, privilege.getAllowList().size());
assertEquals(2, privilege.getDenyList().size());
assertEquals(Set.of("allow1", "allow2"), privilege.getAllowList());
assertEquals(Set.of("deny1", "deny2"), privilege.getDenyList());
} finally {
logout();
}
}
}

View File

@ -15,12 +15,6 @@
*/
package li.strolch.privilege.test;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import java.text.MessageFormat;
import java.util.*;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.InvalidCredentialsException;
import li.strolch.privilege.base.PrivilegeException;
@ -41,9 +35,15 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
import java.util.*;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
/**
* JUnit for performing Privilege tests. This JUnit is by no means complete, but checks the bare minimum.br />
*
* <p>
* TODO add more tests, especially with deny and allow lists
*
* @author Robert von Burg <eitch@eitchnet.ch>
@ -77,12 +77,12 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(PrivilegeTest.class.getSimpleName());
prepareConfigs(PrivilegeTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeUsers.xml",
"PrivilegeRoles.xml");
"PrivilegeGroups.xml", "PrivilegeRoles.xml");
}
@AfterClass
public static void destroy() {
removeConfigs(PrivilegeTest.class.getSimpleName());
//removeConfigs(PrivilegeTest.class.getSimpleName());
}
@Before
@ -209,7 +209,9 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
}
});
MatcherAssert.assertThat(exception.getMessage(), containsString(
"User system_admin2 does not have the privilege li.strolch.privilege.handler.SystemAction with value li.strolch.privilege.test.model.TestSystemUserActionDeny needed for Restrictable li.strolch.privilege.test.model.TestSystemUserActionDeny"));
"User system_admin2 does not have the privilege li.strolch.privilege.handler.SystemAction with value " +
"li.strolch.privilege.test.model.TestSystemUserActionDeny needed for Restrictable " +
"li.strolch.privilege.test.model.TestSystemUserActionDeny"));
}
/**
@ -252,7 +254,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
assertNotEquals("Admin", user.getLastname());
// let's add a new user bob
UserRep userRep = new UserRep(null, ADMIN, "The", "Admin", null, null, null, null, null);
UserRep userRep = new UserRep(null, ADMIN, "The", "Admin", null, null, null, null, null, null);
this.privilegeHandler.updateUser(certificate, userRep);
user = this.privilegeHandler.getUser(certificate, ADMIN);
@ -273,7 +275,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
// let's add a new user bob
UserRep userRep = new UserRep(null, BOB, null, null, null, null, null, null, null);
UserRep userRep = new UserRep(null, BOB, null, null, null, null, null, null, null, null);
this.privilegeHandler.updateUser(certificate, userRep);
} finally {
logout();
@ -291,7 +293,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
// let's add a new user bob
UserRep userRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null);
UserRep userRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null, null);
this.privilegeHandler.updateUser(certificate, userRep);
} finally {
logout();
@ -308,7 +310,24 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
UserRep selectorRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null);
UserRep selectorRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null, null);
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(1, users.size());
assertEquals(ADMIN, users.get(0).getUsername());
} finally {
logout();
}
}
@Test
public void shouldQueryUsersByGroups() {
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = this.ctx.getCertificate();
UserRep selectorRep = new UserRep(null, null, null, null, null, Set.of("GroupA"), null, null, null, null);
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(1, users.size());
assertEquals(ADMIN, users.get(0).getUsername());
@ -325,8 +344,8 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
UserRep selectorRep = new UserRep(null, null, null, null, null,
new HashSet<>(Collections.singletonList("PrivilegeAdmin")), null, null, null);
UserRep selectorRep = new UserRep(null, null, null, null, null, null, Set.of("PrivilegeAdmin"), null, null,
null);
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(2, users.size());
assertEquals(ADMIN, users.get(0).getUsername());
@ -344,7 +363,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
UserRep selectorRep = new UserRep(null, null, null, null, null,
new HashSet<>(Collections.singletonList(ROLE_TEMP)), null, null, null);
new HashSet<>(Collections.singletonList(ROLE_TEMP)), null, null, null, null);
List<UserRep> users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(0, users.size());
@ -593,7 +612,10 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
this.ctx.validateAction(restrictable);
fail("Should fail as bob does not have role app");
} catch (AccessDeniedException e) {
String msg = "User bob does not have the privilege li.strolch.privilege.test.model.TestRestrictable needed for Restrictable li.strolch.privilege.test.model.TestRestrictable and value li.strolch.privilege.test.model.TestRestrictable";
String msg =
"User bob does not have the privilege li.strolch.privilege.test.model.TestRestrictable needed for " +
"Restrictable li.strolch.privilege.test.model.TestRestrictable and value " +
"li.strolch.privilege.test.model.TestRestrictable";
assertEquals(msg, e.getLocalizedMessage());
} finally {
logout();
@ -656,7 +678,8 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// let's add a new user ted
HashSet<String> roles = new HashSet<>();
roles.add(ROLE_USER);
userRep = new UserRep(null, TED, "Ted", "Newman", UserState.ENABLED, roles, null, new HashMap<>(), null);
userRep = new UserRep(null, TED, "Ted", "Newman", UserState.ENABLED, Set.of(), roles, null, new HashMap<>(),
null);
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addUser(certificate, userRep, null);
logger.info("Added user " + TED);
@ -688,14 +711,14 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// auth as Bob
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// let's add a new user Ted
userRep = new UserRep("1", TED, "Ted", "And then Some", UserState.NEW, new HashSet<>(), null,
userRep = new UserRep("1", TED, "Ted", "And then Some", UserState.NEW, Set.of(), Set.of(), null,
new HashMap<>(), null);
certificate = this.ctx.getCertificate();
this.privilegeHandler.addUser(certificate, userRep, null);
fail("User bob may not add a user as bob does not have admin rights!");
} catch (PrivilegeException e) {
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.user"),
BOB, PrivilegeHandler.PRIVILEGE_ADD_USER);
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.user"), BOB,
PrivilegeHandler.PRIVILEGE_ADD_USER);
assertEquals(msg, e.getMessage());
} finally {
logout();
@ -768,8 +791,8 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
// let's add a new user bob
UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW,
new HashSet<>(Collections.singletonList(ROLE_MY)), null, new HashMap<>(), null);
UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW, Set.of(), Set.of(ROLE_MY), null,
new HashMap<>(), null);
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addUser(certificate, userRep, null);
logger.info("Added user " + BOB);

View File

@ -17,7 +17,7 @@ public class SsoHandlerTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(SsoHandlerTest.class.getSimpleName());
prepareConfigs(SsoHandlerTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeUsers.xml",
"PrivilegeRoles.xml");
"PrivilegeGroups.xml", "PrivilegeRoles.xml");
}
@AfterClass
@ -39,6 +39,7 @@ public class SsoHandlerTest extends AbstractPrivilegeTest {
data.put("username", "admin");
data.put("firstName", "Admin");
data.put("lastName", "Istrator");
data.put("groups", "AppUserLocationA");
data.put("roles", "PrivilegeAdmin, AppUser");
// auth

View File

@ -16,7 +16,7 @@
package li.strolch.privilege.test;
import li.strolch.privilege.handler.*;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.*;
import li.strolch.privilege.test.model.DummySsoHandler;
@ -80,6 +80,11 @@ public class XmlTest {
throw new RuntimeException("Tmp still exists and can not be deleted at " + tmpFile.getAbsolutePath());
}
tmpFile = new File(TARGET_TEST + "PrivilegeGroupsTest.xml");
if (tmpFile.exists() && !tmpFile.delete()) {
throw new RuntimeException("Tmp still exists and can not be deleted at " + tmpFile.getAbsolutePath());
}
tmpFile = new File(TARGET_TEST + "PrivilegeRolesTest.xml");
if (tmpFile.exists() && !tmpFile.delete()) {
throw new RuntimeException("Tmp still exists and can not be deleted at " + tmpFile.getAbsolutePath());
@ -194,12 +199,13 @@ public class XmlTest {
assertEquals("1", admin.getUserId());
assertEquals("admin", admin.getUsername());
assertEquals("cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344",
StringHelper.toHexString(admin.getPasswordCrypt().getPassword()));
assertEquals("61646d696e", StringHelper.toHexString(admin.getPasswordCrypt().getSalt()));
StringHelper.toHexString(admin.getPasswordCrypt().password()));
assertEquals("61646d696e", StringHelper.toHexString(admin.getPasswordCrypt().salt()));
assertEquals("Application", admin.getFirstname());
assertEquals("Administrator", admin.getLastname());
assertEquals(UserState.ENABLED, admin.getUserState());
assertEquals("en-GB", admin.getLocale().toLanguageTag());
assertEquals(Set.of("GroupA"), admin.getGroups());
MatcherAssert.assertThat(admin.getRoles(), containsInAnyOrder("PrivilegeAdmin", "AppUser"));
Map<String, String> properties = admin.getProperties();
assertEquals(new HashSet<>(Arrays.asList("organization", "organizationalUnit")), properties.keySet());
@ -215,8 +221,48 @@ public class XmlTest {
assertEquals("Administrator", systemAdmin.getLastname());
assertEquals(UserState.SYSTEM, systemAdmin.getUserState());
assertEquals("en-GB", systemAdmin.getLocale().toLanguageTag());
assertEquals(Set.of(), systemAdmin.getGroups());
MatcherAssert.assertThat(systemAdmin.getRoles(), containsInAnyOrder("system_admin_privileges"));
assertTrue(systemAdmin.getProperties().isEmpty());
// admin2
User admin2 = findUser("admin2", users);
assertEquals("1", admin2.getUserId());
assertEquals("admin2", admin2.getUsername());
assertEquals("8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
StringHelper.toHexString(admin2.getPasswordCrypt().password()));
assertEquals("Application", admin2.getFirstname());
assertEquals("Administrator", admin2.getLastname());
assertEquals(UserState.ENABLED, admin2.getUserState());
assertEquals("en-GB", admin2.getLocale().toLanguageTag());
MatcherAssert.assertThat(admin2.getGroups(), containsInAnyOrder("AppUserLocationA"));
MatcherAssert.assertThat(admin2.getRoles(), containsInAnyOrder("PrivilegeAdmin"));
properties = admin2.getProperties();
assertEquals(new HashSet<>(Arrays.asList("organization", "organizationalUnit")), properties.keySet());
assertEquals("eitchnet.ch", properties.get("organization"));
assertEquals("Development", properties.get("organizationalUnit"));
}
@Test
public void canReadGroups() {
PrivilegeGroupsSaxReader xmlHandler = new PrivilegeGroupsSaxReader();
File xmlFile = new File(SRC_TEST + "PrivilegeGroups.xml");
XmlHelper.parseDocument(xmlFile, xmlHandler);
Map<String, Group> groups = xmlHandler.getGroups();
assertNotNull(groups);
assertEquals(1, groups.size());
// group AppUserLocationA
Group group = groups.get("AppUserLocationA");
assertEquals("AppUserLocationA", group.name());
MatcherAssert.assertThat(group.roles(), containsInAnyOrder("AppUser", "ModelAccessor", "UserPrivileges"));
Map<String, String> properties = group.getProperties();
assertEquals(new HashSet<>(List.of("location")), properties.keySet());
assertEquals("LocationA", properties.get("location"));
}
@Test
@ -241,18 +287,18 @@ public class XmlTest {
Role privilegeAdmin = findRole("PrivilegeAdmin", roles);
assertEquals("PrivilegeAdmin", privilegeAdmin.getName());
assertEquals(18, privilegeAdmin.getPrivilegeNames().size());
IPrivilege privilegeAction = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ACTION);
Privilege privilegeAction = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ACTION);
assertFalse(privilegeAction.isAllAllowed());
assertEquals(5, privilegeAction.getAllowList().size());
assertEquals(0, privilegeAction.getDenyList().size());
assertEquals("DefaultPrivilege", privilegeAction.getPolicy());
IPrivilege privilegeAddRole = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ADD_ROLE);
Privilege privilegeAddRole = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ADD_ROLE);
assertTrue(privilegeAddRole.isAllAllowed());
assertEquals(0, privilegeAddRole.getAllowList().size());
assertEquals(0, privilegeAddRole.getDenyList().size());
IPrivilege privilegeRemRoleFromUser = privilegeAdmin.getPrivilege(
Privilege privilegeRemRoleFromUser = privilegeAdmin.getPrivilege(
PrivilegeHandler.PRIVILEGE_REMOVE_ROLE_FROM_USER);
assertTrue(privilegeRemRoleFromUser.isAllAllowed());
assertEquals(0, privilegeRemRoleFromUser.getAllowList().size());
@ -264,7 +310,7 @@ public class XmlTest {
assertEquals(new HashSet<>(Collections.singletonList("li.strolch.privilege.test.model.TestRestrictable")),
appUser.getPrivilegeNames());
IPrivilege testRestrictable = appUser.getPrivilege("li.strolch.privilege.test.model.TestRestrictable");
Privilege testRestrictable = appUser.getPrivilege("li.strolch.privilege.test.model.TestRestrictable");
assertEquals("li.strolch.privilege.test.model.TestRestrictable", testRestrictable.getName());
assertEquals("DefaultPrivilege", testRestrictable.getPolicy());
assertTrue(testRestrictable.isAllAllowed());
@ -279,7 +325,7 @@ public class XmlTest {
containsInAnyOrder("li.strolch.privilege.handler.SystemAction",
"li.strolch.privilege.test.model.TestSystemRestrictable"));
IPrivilege testSystemUserAction = systemAdminPrivileges.getPrivilege(
Privilege testSystemUserAction = systemAdminPrivileges.getPrivilege(
"li.strolch.privilege.handler.SystemAction");
assertEquals("li.strolch.privilege.handler.SystemAction", testSystemUserAction.getName());
assertEquals("DefaultPrivilege", testSystemUserAction.getPolicy());
@ -287,7 +333,7 @@ public class XmlTest {
assertEquals(1, testSystemUserAction.getAllowList().size());
assertEquals(1, testSystemUserAction.getDenyList().size());
IPrivilege testSystemRestrictable = systemAdminPrivileges.getPrivilege(
Privilege testSystemRestrictable = systemAdminPrivileges.getPrivilege(
"li.strolch.privilege.test.model.TestSystemRestrictable");
assertEquals("li.strolch.privilege.test.model.TestSystemRestrictable", testSystemRestrictable.getName());
assertEquals("DefaultPrivilege", testSystemRestrictable.getPolicy());
@ -302,7 +348,7 @@ public class XmlTest {
MatcherAssert.assertThat(restrictedRole.getPrivilegeNames(),
containsInAnyOrder("li.strolch.privilege.handler.SystemAction"));
IPrivilege testSystemUserAction2 = restrictedRole.getPrivilege("li.strolch.privilege.handler.SystemAction");
Privilege testSystemUserAction2 = restrictedRole.getPrivilege("li.strolch.privilege.handler.SystemAction");
assertEquals("li.strolch.privilege.handler.SystemAction", testSystemUserAction2.getName());
assertEquals("DefaultPrivilege", testSystemUserAction2.getPolicy());
assertFalse(testSystemUserAction2.isAllAllowed());
@ -326,29 +372,35 @@ public class XmlTest {
public void canWriteUsers() throws XMLStreamException, IOException {
Map<String, String> propertyMap;
Set<String> groups;
Set<String> userRoles;
List<User> users = new ArrayList<>();
propertyMap = new HashMap<>();
propertyMap.put("prop1", "value1");
groups = new HashSet<>();
groups.add("group1");
userRoles = new HashSet<>();
userRoles.add("role1");
UserHistory history = new UserHistory();
history.setFirstLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()));
UserHistory history = UserHistory.EMPTY.withFirstLogin(
ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()));
User user1 = new User("1", "user1",
new PasswordCrypt("blabla".getBytes(), "blabla".getBytes(), "PBKDF2WithHmacSHA512", 10000, 256), "Bob",
"White", UserState.DISABLED, userRoles, Locale.ENGLISH, propertyMap, false, history);
"White", UserState.DISABLED, groups, userRoles, Locale.ENGLISH, propertyMap, false, history);
users.add(user1);
propertyMap = new HashMap<>();
propertyMap.put("prop2", "value2");
groups = new HashSet<>();
groups.add("group2");
userRoles = new HashSet<>();
userRoles.add("role2");
history = new UserHistory();
history.setFirstLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()));
history.setLastLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 5, 2, 3, 4, 5), ZoneId.systemDefault()));
history = UserHistory.EMPTY.withFirstLogin(
ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()))
.withLastLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 5, 2, 3, 4, 5), ZoneId.systemDefault()));
User user2 = new User("2", "user2", new PasswordCrypt("haha".getBytes(), "haha".getBytes(), null, -1, -1),
"Leonard", "Sheldon", UserState.ENABLED, userRoles, Locale.ENGLISH, propertyMap, false, history);
"Leonard", "Sheldon", UserState.ENABLED, groups, userRoles, Locale.ENGLISH, propertyMap, false,
history);
users.add(user2);
File modelFile = new File(TARGET_TEST + "PrivilegeUsersTest.xml");
@ -370,8 +422,8 @@ public class XmlTest {
assertEquals(user1.getFirstname(), parsedUser1.getFirstname());
assertEquals(user1.getLastname(), parsedUser1.getLastname());
assertEquals(user1.getLocale(), parsedUser1.getLocale());
assertArrayEquals(user1.getPasswordCrypt().getPassword(), parsedUser1.getPasswordCrypt().getPassword());
assertArrayEquals(user1.getPasswordCrypt().getSalt(), parsedUser1.getPasswordCrypt().getSalt());
assertArrayEquals(user1.getPasswordCrypt().password(), parsedUser1.getPasswordCrypt().password());
assertArrayEquals(user1.getPasswordCrypt().salt(), parsedUser1.getPasswordCrypt().salt());
assertEquals(user1.getProperties(), parsedUser1.getProperties());
assertEquals(user1.getUserId(), parsedUser1.getUserId());
assertEquals(user1.getUserState(), parsedUser1.getUserState());
@ -380,22 +432,57 @@ public class XmlTest {
assertEquals(user2.getFirstname(), parsedUser2.getFirstname());
assertEquals(user2.getLastname(), parsedUser2.getLastname());
assertEquals(user2.getLocale(), parsedUser2.getLocale());
assertArrayEquals(user2.getPasswordCrypt().getPassword(), parsedUser2.getPasswordCrypt().getPassword());
assertArrayEquals(user2.getPasswordCrypt().getSalt(), parsedUser2.getPasswordCrypt().getSalt());
assertArrayEquals(user2.getPasswordCrypt().password(), parsedUser2.getPasswordCrypt().password());
assertArrayEquals(user2.getPasswordCrypt().salt(), parsedUser2.getPasswordCrypt().salt());
assertEquals(user2.getProperties(), parsedUser2.getProperties());
assertEquals(user2.getUserId(), parsedUser2.getUserId());
assertEquals(user2.getUserState(), parsedUser2.getUserState());
assertEquals(user2.getRoles(), parsedUser2.getRoles());
}
@Test
public void canWriteGroups() throws XMLStreamException, IOException {
Map<String, String> propertyMap;
Set<String> roles;
List<Group> groups = new ArrayList<>();
propertyMap = new HashMap<>();
propertyMap.put("prop1", "value1");
roles = new HashSet<>();
roles.add("role1");
Group newGroup = new Group("group1", roles, propertyMap);
groups.add(newGroup);
File modelFile = new File(TARGET_TEST + "PrivilegeGroupsTest.xml");
PrivilegeGroupsSaxWriter configSaxWriter = new PrivilegeGroupsSaxWriter(groups, modelFile);
configSaxWriter.write();
PrivilegeGroupsSaxReader xmlHandler = new PrivilegeGroupsSaxReader();
XmlHelper.parseDocument(modelFile, xmlHandler);
Map<String, Group> parsedGroups = xmlHandler.getGroups();
assertNotNull(parsedGroups);
assertEquals(1, parsedGroups.size());
// group group1
Group parsedGroup1 = parsedGroups.get("group1");
assertNotNull(parsedGroup1);
assertEquals("group1", parsedGroup1.name());
MatcherAssert.assertThat(parsedGroup1.roles(), containsInAnyOrder("role1"));
Map<String, String> properties = parsedGroup1.getProperties();
assertEquals(new HashSet<>(List.of("prop1")), properties.keySet());
assertEquals("value1", properties.get("prop1"));
}
@Test
public void canWriteRoles() throws XMLStreamException, IOException {
Map<String, IPrivilege> privilegeMap;
Map<String, Privilege> privilegeMap;
List<Role> roles = new ArrayList<>();
Set<String> list = Collections.emptySet();
privilegeMap = new HashMap<>();
privilegeMap.put("priv1", new PrivilegeImpl("priv1", "DefaultPrivilege", true, list, list));
privilegeMap.put("priv1", new Privilege("priv1", "DefaultPrivilege", true, list, list));
Role role1 = new Role("role1", privilegeMap);
roles.add(role1);
@ -404,7 +491,7 @@ public class XmlTest {
denyList.add("myself");
Set<String> allowList = new HashSet<>();
allowList.add("other");
privilegeMap.put("priv2", new PrivilegeImpl("priv2", "DefaultPrivilege", false, denyList, allowList));
privilegeMap.put("priv2", new Privilege("priv2", "DefaultPrivilege", false, denyList, allowList));
Role role2 = new Role("role2", privilegeMap);
roles.add(role2);
@ -428,8 +515,8 @@ public class XmlTest {
Set<String> privilegeNames = role1.getPrivilegeNames();
assertEquals(privilegeNames, parsedRole1.getPrivilegeNames());
for (String privilegeName : privilegeNames) {
IPrivilege privilege = role1.getPrivilege(privilegeName);
IPrivilege privilege2 = parsedRole1.getPrivilege(privilegeName);
Privilege privilege = role1.getPrivilege(privilegeName);
Privilege privilege2 = parsedRole1.getPrivilege(privilegeName);
assertNotNull(privilege);
assertNotNull(privilege2);
@ -443,8 +530,8 @@ public class XmlTest {
assertEquals(role2.getPrivilegeNames(), parsedRole2.getPrivilegeNames());
privilegeNames = role2.getPrivilegeNames();
for (String privilegeName : privilegeNames) {
IPrivilege privilege = role2.getPrivilege(privilegeName);
IPrivilege privilege2 = parsedRole2.getPrivilege(privilegeName);
Privilege privilege = role2.getPrivilege(privilegeName);
Privilege privilege2 = parsedRole2.getPrivilege(privilegeName);
assertNotNull(privilege);
assertNotNull(privilege2);

View File

@ -28,9 +28,10 @@ public class DummySsoHandler implements SingleSignOnHandler {
@SuppressWarnings("unchecked") Map<String, String> map = (Map<String, String>) data;
Set<String> groups = Arrays.stream(map.get("groups").split(",")).map(String::trim).collect(Collectors.toSet());
Set<String> roles = Arrays.stream(map.get("roles").split(",")).map(String::trim).collect(Collectors.toSet());
Map<String, String> properties = new HashMap<>();
return new User(map.get("userId"), map.get("username"), null, map.get("firstName"), map.get("lastName"),
UserState.REMOTE, roles, Locale.ENGLISH, properties, false, new UserHistory());
UserState.REMOTE, groups, roles, Locale.ENGLISH, properties, false, UserHistory.EMPTY);
}
}

View File

@ -27,6 +27,7 @@
<Parameters>
<Parameter name="basePath" value="target/${target}"/>
<Parameter name="usersXmlFile" value="PrivilegeUsersMerge.xml"/>
<Parameter name="groupsXmlFile" value="PrivilegeGroupsMerge.xml"/>
<Parameter name="rolesXmlFile" value="PrivilegeRolesMerge.xml"/>
</Parameters>
</PersistenceHandler>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Groups>
<Group name="AppUserLocationA">
<Roles>
<Role>AppUser</Role>
<Role>ModelAccessor</Role>
<Role>UserPrivileges</Role>
</Roles>
<Properties>
<Property name="location" value="LocationA"/>
</Properties>
</Group>
</Groups>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Groups>
<Group name="GroupA1">
<Roles>
<Role>RoleA1</Role>
</Roles>
<Properties>
<Property name="location" value="LocationA1"/>
</Properties>
</Group>
<Group name="GroupA2">
<Roles>
<Role>RoleA2</Role>
</Roles>
<Properties>
<Property name="location" value="LocationA2"/>
</Properties>
</Group>
<Group name="GroupB1">
<Roles>
<Role>RoleB1</Role>
</Roles>
<Properties>
<Property name="location" value="LocationB1"/>
</Properties>
</Group>
<Group name="GroupB2">
<Roles>
<Role>RoleB2</Role>
</Roles>
<Properties>
<Property name="location" value="LocationB2"/>
</Properties>
</Group>
</Groups>

View File

@ -6,6 +6,9 @@
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Groups>
<Group>GroupA</Group>
</Groups>
<Roles>
<Role>PrivilegeAdmin</Role>
<Role>AppUser</Role>
@ -21,9 +24,11 @@
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Groups>
<Group>AppUserLocationA</Group>
</Groups>
<Roles>
<Role>PrivilegeAdmin</Role>
<Role>AppUser</Role>
</Roles>
<Properties>
<Property name="organization" value="eitchnet.ch"/>

View File

@ -23,4 +23,26 @@
</Roles>
</User>
<User userId="3" username="userC" password="cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344" salt="61646d696e">
<Firstname>System User</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Groups>
<Group>GroupA1</Group>
<Group>GroupA2</Group>
</Groups>
</User>
<User userId="4" username="userD" password="cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344" salt="61646d696e">
<Firstname>System User</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Groups>
<Group>GroupB1</Group>
<Group>GroupB2</Group>
</Groups>
</User>
</Users>

View File

@ -5,7 +5,7 @@ import static li.strolch.report.ReportConstants.TYPE_REPORT;
import java.util.Set;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.search.ResourceSearch;
/**
@ -18,7 +18,7 @@ public class ReportSearch extends ResourceSearch {
public ReportSearch(StrolchTransaction tx) {
types(TYPE_REPORT);
IPrivilege reportPrivilege = tx.getPrivilegeContext().getPrivilege(ReportSearch.class.getName());
Privilege reportPrivilege = tx.getPrivilegeContext().getPrivilege(ReportSearch.class.getName());
if (!reportPrivilege.isAllAllowed()) {
Set<String> allowedReportIds = reportPrivilege.getAllowList();
where(id().isIn(allowedReportIds));

View File

@ -15,11 +15,6 @@
*/
package li.strolch.command.privilege.users;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.*;
import li.strolch.command.AbstractRealmCommandTest;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.UserRep;
@ -27,6 +22,11 @@ import li.strolch.privilege.model.UserState;
import li.strolch.service.api.Command;
import li.strolch.service.privilege.users.PrivilegeAddUserCommand;
import java.util.*;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -40,12 +40,14 @@ public class PrivilegeAddUserCommandTest extends AbstractRealmCommandTest {
@Override
protected Command getCommandInstance(StrolchTransaction tx) {
Set<String> groups = new HashSet<>();
groups.add("AppGroups");
Set<String> roles = new HashSet<>();
roles.add("AppUser");
Map<String, String> propertyMap = new HashMap<>();
UserRep user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, roles, Locale.getDefault(),
propertyMap, null);
UserRep user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, groups, roles,
Locale.getDefault(), propertyMap, null);
PrivilegeAddUserCommand command = new PrivilegeAddUserCommand(tx);
command.setUserIn(user);

View File

@ -43,12 +43,14 @@ public class PrivilegeAddUserServiceTest extends AbstractRealmServiceTest<Privil
@Override
protected PrivilegeUserArgument getArgInstance() {
Set<String> groups = new HashSet<>();
groups.add("AppGroups");
Set<String> roles = new HashSet<>();
roles.add("AppUser");
Map<String, String> propertyMap = new HashMap<>();
PrivilegeUserArgument arg = new PrivilegeUserArgument();
arg.user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, roles, Locale.getDefault(),
arg.user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, groups, roles, Locale.getDefault(),
propertyMap, null);
return arg;

View File

@ -33,6 +33,7 @@ import li.strolch.service.test.model.GreetingResult;
import li.strolch.service.test.model.GreetingService;
import li.strolch.service.test.model.GreetingService.GreetingArgument;
import li.strolch.service.test.model.TestService;
import li.strolch.utils.dbc.DBC;
import org.junit.Test;
/**
@ -42,11 +43,11 @@ public class ServiceTest extends AbstractServiceTest {
@Test
public void shouldFailInvalidCertificate1() {
assertThrows(PrivilegeException.class, () -> {
assertThrows(DBC.DbcException.class, () -> {
TestService testService = new TestService();
getServiceHandler().doService(
new Certificate(null, null, null, null, null, null, null, null, ZonedDateTime.now(), false, null,
new HashSet<>(), null), testService);
new HashSet<>(), new HashSet<>(), null), testService);
});
}
@ -54,7 +55,7 @@ public class ServiceTest extends AbstractServiceTest {
public void shouldFailInvalidCertificate2() {
TestService testService = new TestService();
Certificate badCert = new Certificate(Usage.ANY, "1", "bob", "Bob", "Brown", UserState.ENABLED, "dsdf", "asd",
ZonedDateTime.now(), false, null, new HashSet<>(), null);
ZonedDateTime.now(), false, null, new HashSet<>(), new HashSet<>(), null);
ServiceResult svcResult = getServiceHandler().doService(badCert, testService);
assertThat(svcResult.getThrowable(), instanceOf(NotAuthenticatedException.class));
}
@ -67,8 +68,7 @@ public class ServiceTest extends AbstractServiceTest {
try {
TestService testService = new TestService();
ServiceResult svcResult = getServiceHandler().doService(certificate, testService);
assertThat(svcResult.getMessage(),
containsString("User jill may not perform service TestService"));
assertThat(svcResult.getMessage(), containsString("User jill may not perform service TestService"));
assertThat(svcResult.getThrowable(), instanceOf(AccessDeniedException.class));
} finally {
runtimeMock.getPrivilegeHandler().invalidate(certificate);

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Groups>
<Group name="AppGroups">
<Roles>
<Role>AppGroup</Role>
</Roles>
</Group>
</Groups>

View File

@ -1,174 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<Roles>
<Role name="agent">
<Privilege name="li.strolch.privilege.handler.SystemAction" policy="DefaultPrivilege">
<Allow>li.strolch.runtime.privilege.StrolchSystemAction</Allow>
<Allow>li.strolch.runtime.privilege.StrolchSystemActionWithResult</Allow>
<Allow>li.strolch.persistence.postgresql.PostgreSqlSchemaInitializer</Allow>
</Privilege>
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.search.StrolchSearch" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Role name="agent">
<Privilege name="li.strolch.privilege.handler.SystemAction" policy="DefaultPrivilege">
<Allow>li.strolch.runtime.privilege.StrolchSystemAction</Allow>
<Allow>li.strolch.runtime.privilege.StrolchSystemActionWithResult</Allow>
<Allow>li.strolch.persistence.postgresql.PostgreSqlSchemaInitializer</Allow>
</Privilege>
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.search.StrolchSearch" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="AddResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="AddOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="AddActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="UpdateResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="UpdateOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="UpdateActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RemoveResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RemoveOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RemoveActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Privilege name="GetResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="AddResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="AddOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="AddActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="UpdateResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="UpdateOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="UpdateActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RemoveResource" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RemoveOrder" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RemoveActivity" policy="ModelPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.search.StrolchSearch" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Role name="AppGroup">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.search.StrolchSearch" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Privilege name="GetResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="GetOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="GetActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="AddResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="AddOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="AddActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="UpdateResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="UpdateOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="UpdateActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="RemoveResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="RemoveOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="RemoveActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.search.StrolchSearch" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Role name="PrivilegeAdmin">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<Allow>li.strolch.service.privilege.users.PrivilegeUpdateUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeUpdateUserRolesService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeSetUserPasswordService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeSetUserLocaleService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeRemoveUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeRemoveRoleFromUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeAddUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeAddRoleToUserService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeUpdateRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeRemoveRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeRemovePrivilegeFromRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeAddRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeAddOrReplacePrivilegeOnRoleService</Allow>
</Privilege>
<Privilege name="PrivilegeAddUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeRemoveUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="InvalidateSession" policy="UserSessionAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeSetUserPassword" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RequirePasswordChange" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeSetUserLocale" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeAction" policy="DefaultPrivilege">
<Allow>Reload</Allow>
<Allow>GetPolicies</Allow>
<Allow>Persist</Allow>
<Allow>GetCertificates</Allow>
<Allow>PersistSessions</Allow>
</Privilege>
<Privilege name="PrivilegeGetUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeSetUserState" policy="UserAccessPrivilege">
<Deny>SYSTEM</Deny>
<Allow>DISABLED</Allow>
<Allow>ENABLED</Allow>
</Privilege>
<Privilege name="PrivilegeAddRoleToUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeGetRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetSession" policy="UserSessionAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeModifyUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeRemoveRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeRemoveRoleFromUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeModifyRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeAddRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Privilege name="GetResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="GetOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="GetActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="AddResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="AddOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="AddActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="UpdateResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="UpdateOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="UpdateActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="RemoveResource" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="RemoveOrder" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
<Privilege name="RemoveActivity" policy="ModelPrivilege">
<Allow>Bike</Allow>
</Privilege>
</Role>
<Role name="PrivilegeAdmin">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<Allow>li.strolch.service.privilege.users.PrivilegeUpdateUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeUpdateUserRolesService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeSetUserPasswordService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeSetUserLocaleService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeRemoveUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeRemoveRoleFromUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeAddUserService</Allow>
<Allow>li.strolch.service.privilege.users.PrivilegeAddRoleToUserService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeUpdateRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeRemoveRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeRemovePrivilegeFromRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeAddRoleService</Allow>
<Allow>li.strolch.service.privilege.roles.PrivilegeAddOrReplacePrivilegeOnRoleService</Allow>
</Privilege>
<Privilege name="PrivilegeAddUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeRemoveUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="InvalidateSession" policy="UserSessionAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeSetUserPassword" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="RequirePasswordChange" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeSetUserLocale" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeAction" policy="DefaultPrivilege">
<Allow>Reload</Allow>
<Allow>GetPolicies</Allow>
<Allow>Persist</Allow>
<Allow>GetCertificates</Allow>
<Allow>PersistSessions</Allow>
</Privilege>
<Privilege name="PrivilegeGetUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeSetUserState" policy="UserAccessPrivilege">
<Deny>SYSTEM</Deny>
<Allow>DISABLED</Allow>
<Allow>ENABLED</Allow>
</Privilege>
<Privilege name="PrivilegeAddRoleToUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeGetRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="GetSession" policy="UserSessionAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeModifyUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeRemoveRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeRemoveRoleFromUser" policy="UserAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeModifyRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="PrivilegeAddRole" policy="RoleAccessPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>

View File

@ -1,28 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="3" username="test" password="fdd9d2def3475e1d5cc87107b87e14fd6adbca664c2874fc379a1e53931c0428" salt="74657374">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Roles>
<Role>AppUser</Role>
</Roles>
</User>
<User userId="3" username="admin" password="cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344" salt="61646d696e">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Roles>
<Role>AppUser</Role>
<Role>PrivilegeAdmin</Role>
</Roles>
</User>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="3" username="test" password="fdd9d2def3475e1d5cc87107b87e14fd6adbca664c2874fc379a1e53931c0428" salt="74657374">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Roles>
<Role>AppUser</Role>
</Roles>
</User>
<User userId="3" username="admin" password="cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344" salt="61646d696e">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en-GB</Locale>
<Roles>
<Role>AppUser</Role>
<Role>PrivilegeAdmin</Role>
</Roles>
</User>
</Users>

View File

@ -37,7 +37,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.InvalidCredentialsException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Usage;
import li.strolch.rest.RestfulStrolchComponent;
@ -401,7 +401,7 @@ public class AuthenticationService {
loginResult.add("privileges", privArr);
for (String name : privilegeContext.getPrivilegeNames()) {
IPrivilege privilege = privilegeContext.getPrivilege(name);
Privilege privilege = privilegeContext.getPrivilege(name);
JsonObject privObj = new JsonObject();
privArr.add(privObj);

View File

@ -33,7 +33,7 @@ import li.strolch.job.StrolchJob;
import li.strolch.job.StrolchJobsHandler;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
@ -76,7 +76,7 @@ public class StrolchJobsResource {
if (ctx.hasRole(ROLE_STROLCH_ADMIN))
return true;
IPrivilege privilege = ctx.getPrivilege(StrolchJob.class.getName());
Privilege privilege = ctx.getPrivilege(StrolchJob.class.getName());
return privilege.isAllAllowed() || privilege.getAllowList().contains(job.getClass().getName());
}) //
.sorted(comparing(StrolchJob::getName)) //