[Major] Refactored PrivilegeHandler, adding locking, no synchronized blocks and methods
This commit is contained in:
parent
10f201ad9d
commit
6d05ff4803
|
@ -36,7 +36,7 @@ import li.strolch.model.audit.Audit;
|
|||
import li.strolch.persistence.api.StrolchTransaction;
|
||||
import li.strolch.privilege.base.PrivilegeException;
|
||||
import li.strolch.privilege.handler.*;
|
||||
import li.strolch.privilege.helper.PrivilegeInitializationHelper;
|
||||
import li.strolch.privilege.helper.PrivilegeInitializer;
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
import li.strolch.privilege.model.PrivilegeContext;
|
||||
import li.strolch.privilege.model.Usage;
|
||||
|
@ -65,8 +65,8 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
|
|||
|
||||
// initialize privilege
|
||||
RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
|
||||
File privilegeConfigFile = configuration
|
||||
.getConfigFile(PROP_PRIVILEGE_CONFIG_FILE, PRIVILEGE_CONFIG_XML, runtimeConfiguration);
|
||||
File privilegeConfigFile = configuration.getConfigFile(PROP_PRIVILEGE_CONFIG_FILE, PRIVILEGE_CONFIG_XML,
|
||||
runtimeConfiguration);
|
||||
this.privilegeHandler = initializeFromXml(configuration, privilegeConfigFile);
|
||||
}
|
||||
|
||||
|
@ -81,8 +81,8 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
|
|||
|
||||
ComponentConfiguration configuration = getConfiguration();
|
||||
RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
|
||||
File privilegeConfigFile = configuration
|
||||
.getConfigFile(PROP_PRIVILEGE_CONFIG_FILE, PRIVILEGE_CONFIG_XML, runtimeConfiguration);
|
||||
File privilegeConfigFile = configuration.getConfigFile(PROP_PRIVILEGE_CONFIG_FILE, PRIVILEGE_CONFIG_XML,
|
||||
runtimeConfiguration);
|
||||
this.privilegeHandler = initializeFromXml(configuration, privilegeConfigFile);
|
||||
}
|
||||
|
||||
|
@ -92,8 +92,8 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
|
|||
* @param privilegeXmlFile
|
||||
* a {@link File} reference to the XML file containing the configuration for Privilege
|
||||
*
|
||||
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and {@link
|
||||
* PersistenceHandler} are set and initialized as well
|
||||
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and
|
||||
* {@link PersistenceHandler} are set and initialized as well
|
||||
*/
|
||||
private li.strolch.privilege.handler.PrivilegeHandler initializeFromXml(ComponentConfiguration configuration,
|
||||
File privilegeXmlFile) {
|
||||
|
@ -129,7 +129,7 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
|
|||
xmlParams.put(XML_PARAM_BASE_PATH, configPath.getPath());
|
||||
}
|
||||
|
||||
return PrivilegeInitializationHelper.initializeFromXml(containerModel);
|
||||
return new PrivilegeInitializer(getScheduledExecutor(getName())).initializeFromXml(containerModel);
|
||||
|
||||
} catch (Exception e) {
|
||||
String msg = "Failed to load Privilege configuration from {0}";
|
||||
|
@ -260,8 +260,8 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
|
|||
|
||||
@Override
|
||||
public <T> T runAsAgentWithResult(PrivilegedRunnableWithResult<T> runnable) throws Exception {
|
||||
return this.privilegeHandler
|
||||
.runWithResult(StrolchConstants.SYSTEM_USER_AGENT, new StrolchSystemActionWithResult<>(runnable));
|
||||
return this.privilegeHandler.runWithResult(StrolchConstants.SYSTEM_USER_AGENT,
|
||||
new StrolchSystemActionWithResult<>(runnable));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Hashtable;
|
|||
import java.util.Locale;
|
||||
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;
|
||||
|
@ -26,12 +27,12 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
|
|||
private String domain;
|
||||
|
||||
@Override
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
public synchronized 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(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
super.initialize(executorService, parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
userChallengeHandler, ssoHandler, policyMap);
|
||||
|
||||
this.providerUrl = parameterMap.get("providerUrl");
|
||||
|
|
|
@ -27,6 +27,10 @@ import java.nio.file.Files;
|
|||
import java.time.ZonedDateTime;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -38,6 +42,7 @@ import li.strolch.privilege.xml.CertificateStubsDomWriter;
|
|||
import li.strolch.privilege.xml.CertificateStubsSaxReader;
|
||||
import li.strolch.privilege.xml.CertificateStubsSaxReader.CertificateStub;
|
||||
import li.strolch.utils.collections.Tuple;
|
||||
import li.strolch.utils.concurrent.ElementLockingHandler;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
import li.strolch.utils.helper.AesCryptoHelper;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -139,6 +144,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
private Map<String, String> parameterMap;
|
||||
|
||||
private ElementLockingHandler<String> lockingHandler;
|
||||
private ScheduledExecutorService executorService;
|
||||
private Future<?> persistSessionsTask;
|
||||
|
||||
@Override
|
||||
public SingleSignOnHandler getSsoHandler() {
|
||||
return this.ssoHandler;
|
||||
|
@ -381,6 +390,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep addUser(Certificate certificate, UserRep userRepParam, char[] password) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(userRepParam.getUsername(),
|
||||
() -> internalAddUser(certificate, userRepParam, password));
|
||||
}
|
||||
|
||||
public UserRep internalAddUser(Certificate certificate, UserRep userRepParam, char[] password) {
|
||||
try {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
|
@ -449,6 +463,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public void addOrUpdateUsers(Certificate certificate, List<UserRep> userReps) throws PrivilegeException {
|
||||
this.lockingHandler.lockedExecute(PrivilegeHandler.class.getSimpleName(),
|
||||
() -> internalAddOrUpdateUsers(certificate, userReps));
|
||||
}
|
||||
|
||||
private void internalAddOrUpdateUsers(Certificate certificate, List<UserRep> userReps) throws PrivilegeException {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -525,7 +544,12 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UserRep replaceUser(Certificate certificate, UserRep userRep, char[] password) {
|
||||
public UserRep replaceUser(Certificate certificate, UserRep userRep, char[] password) throws PrivilegeException {
|
||||
return this.lockingHandler.lockedExecuteWithResult(userRep.getUsername(),
|
||||
() -> internalReplaceUser(certificate, userRep, password));
|
||||
}
|
||||
|
||||
private UserRep internalReplaceUser(Certificate certificate, UserRep userRep, char[] password) {
|
||||
try {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
|
@ -616,6 +640,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep updateUser(Certificate certificate, UserRep userRep) throws PrivilegeException {
|
||||
return this.lockingHandler.lockedExecuteWithResult(userRep.getUsername(),
|
||||
() -> internalUpdateUser(certificate, userRep));
|
||||
}
|
||||
|
||||
public UserRep internalUpdateUser(Certificate certificate, UserRep userRep) throws PrivilegeException {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -687,6 +716,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep removeUser(Certificate certificate, String username) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username, () -> internalRemoveUser(certificate, username));
|
||||
}
|
||||
|
||||
private UserRep internalRemoveUser(Certificate certificate, String username) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -713,6 +746,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep addRoleToUser(Certificate certificate, String username, String roleName) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username,
|
||||
() -> internalAddRoleToUser(certificate, username, roleName));
|
||||
}
|
||||
|
||||
private UserRep internalAddRoleToUser(Certificate certificate, String username, String roleName) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -765,6 +803,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep removeRoleFromUser(Certificate certificate, String username, String roleName) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username,
|
||||
() -> internalRemoveRoleFromUser(certificate, username, roleName));
|
||||
}
|
||||
|
||||
private UserRep internalRemoveRoleFromUser(Certificate certificate, String username, String roleName) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -808,6 +851,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep setUserLocale(Certificate certificate, String username, Locale locale) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username,
|
||||
() -> internalSetUserLocale(certificate, username, locale));
|
||||
}
|
||||
|
||||
private UserRep internalSetUserLocale(Certificate certificate, String username, Locale locale) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -845,6 +893,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public void requirePasswordChange(Certificate certificate, String username) throws PrivilegeException {
|
||||
this.lockingHandler.lockedExecute(username, () -> internalRequirePasswordChange(certificate, username));
|
||||
}
|
||||
|
||||
private void internalRequirePasswordChange(Certificate certificate, String username) throws PrivilegeException {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -878,6 +930,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public void setUserPassword(Certificate certificate, String username, char[] password) {
|
||||
this.lockingHandler.lockedExecute(username, () -> internalSetUserPassword(certificate, username, password));
|
||||
}
|
||||
|
||||
private void internalSetUserPassword(Certificate certificate, String username, char[] password) {
|
||||
try {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
|
@ -944,6 +1000,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public UserRep setUserState(Certificate certificate, String username, UserState state) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username,
|
||||
() -> internalSetUserState(certificate, username, state));
|
||||
}
|
||||
|
||||
private UserRep internalSetUserState(Certificate certificate, String username, UserState state) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -974,6 +1035,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public RoleRep addRole(Certificate certificate, RoleRep roleRep) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(roleRep.getName(),
|
||||
() -> internalAddRole(certificate, roleRep));
|
||||
}
|
||||
|
||||
private RoleRep internalAddRole(Certificate certificate, RoleRep roleRep) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -1007,6 +1073,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public RoleRep replaceRole(Certificate certificate, RoleRep roleRep) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(roleRep.getName(),
|
||||
() -> internalReplaceRole(certificate, roleRep));
|
||||
}
|
||||
|
||||
private RoleRep internalReplaceRole(Certificate certificate, RoleRep roleRep) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -1047,6 +1118,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public RoleRep removeRole(Certificate certificate, String roleName) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(roleName, () -> internalRemoveRole(certificate, roleName));
|
||||
}
|
||||
|
||||
private RoleRep internalRemoveRole(Certificate certificate, String roleName) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -1083,6 +1158,12 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public RoleRep addOrReplacePrivilegeOnRole(Certificate certificate, String roleName, PrivilegeRep privilegeRep) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(roleName,
|
||||
() -> internalAddOrReplacePrivilegeOnRole(certificate, roleName, privilegeRep));
|
||||
}
|
||||
|
||||
private RoleRep internalAddOrReplacePrivilegeOnRole(Certificate certificate, String roleName,
|
||||
PrivilegeRep privilegeRep) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -1142,6 +1223,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public RoleRep removePrivilegeFromRole(Certificate certificate, String roleName, String privilegeName) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(roleName,
|
||||
() -> internalRemovePrivilegeFromRole(certificate, roleName, privilegeName));
|
||||
}
|
||||
|
||||
private RoleRep internalRemovePrivilegeFromRole(Certificate certificate, String roleName, String privilegeName) {
|
||||
|
||||
// validate user actually has this type of privilege
|
||||
PrivilegeContext prvCtx = validate(certificate);
|
||||
|
@ -1192,16 +1278,14 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* the new user to update with
|
||||
*/
|
||||
private void updateExistingSessionsForUser(User newUser) {
|
||||
synchronized (this.privilegeContextMap) {
|
||||
List<PrivilegeContext> ctxs = new ArrayList<>(this.privilegeContextMap.values());
|
||||
for (PrivilegeContext ctx : ctxs) {
|
||||
if (ctx.getUserRep().getUsername().equals(newUser.getUsername())) {
|
||||
Certificate cert = ctx.getCertificate();
|
||||
cert = buildCertificate(cert.getUsage(), newUser, cert.getAuthToken(), cert.getSessionId(),
|
||||
cert.getSource(), cert.getLoginTime(), cert.isKeepAlive());
|
||||
PrivilegeContext privilegeContext = buildPrivilegeContext(cert, newUser);
|
||||
this.privilegeContextMap.put(cert.getSessionId(), privilegeContext);
|
||||
}
|
||||
List<PrivilegeContext> contexts = new ArrayList<>(this.privilegeContextMap.values());
|
||||
for (PrivilegeContext ctx : contexts) {
|
||||
if (ctx.getUserRep().getUsername().equals(newUser.getUsername())) {
|
||||
Certificate cert = ctx.getCertificate();
|
||||
cert = buildCertificate(cert.getUsage(), newUser, cert.getAuthToken(), cert.getSessionId(),
|
||||
cert.getSource(), cert.getLoginTime(), cert.isKeepAlive());
|
||||
PrivilegeContext privilegeContext = buildPrivilegeContext(cert, newUser);
|
||||
this.privilegeContextMap.put(cert.getSessionId(), privilegeContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1213,34 +1297,27 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* the role to update with
|
||||
*/
|
||||
private void updateExistingSessionsWithNewRole(Role role) {
|
||||
synchronized (this.privilegeContextMap) {
|
||||
List<PrivilegeContext> ctxs = new ArrayList<>(this.privilegeContextMap.values());
|
||||
for (PrivilegeContext ctx : ctxs) {
|
||||
if (ctx.getUserRep().hasRole(role.getName())) {
|
||||
User user = this.persistenceHandler.getUser(ctx.getUsername());
|
||||
if (user == null)
|
||||
continue;
|
||||
List<PrivilegeContext> contexts = new ArrayList<>(this.privilegeContextMap.values());
|
||||
for (PrivilegeContext ctx : contexts) {
|
||||
if (ctx.getUserRep().hasRole(role.getName())) {
|
||||
User user = this.persistenceHandler.getUser(ctx.getUsername());
|
||||
if (user == null)
|
||||
continue;
|
||||
|
||||
Certificate cert = ctx.getCertificate();
|
||||
cert = buildCertificate(cert.getUsage(), user, cert.getAuthToken(), cert.getSessionId(),
|
||||
cert.getSource(), cert.getLoginTime(), cert.isKeepAlive());
|
||||
PrivilegeContext privilegeContext = buildPrivilegeContext(cert, user);
|
||||
this.privilegeContextMap.put(cert.getSessionId(), privilegeContext);
|
||||
}
|
||||
Certificate cert = ctx.getCertificate();
|
||||
cert = buildCertificate(cert.getUsage(), user, cert.getAuthToken(), cert.getSessionId(),
|
||||
cert.getSource(), cert.getLoginTime(), cert.isKeepAlive());
|
||||
PrivilegeContext privilegeContext = buildPrivilegeContext(cert, user);
|
||||
this.privilegeContextMap.put(cert.getSessionId(), privilegeContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidSessionsFor(User user) {
|
||||
List<PrivilegeContext> ctxs;
|
||||
synchronized (this.privilegeContextMap) {
|
||||
ctxs = new ArrayList<>(this.privilegeContextMap.values());
|
||||
}
|
||||
|
||||
for (PrivilegeContext ctx : ctxs) {
|
||||
if (ctx.getUserRep().getUsername().equals(user.getUsername())) {
|
||||
List<PrivilegeContext> contexts = new ArrayList<>(this.privilegeContextMap.values());
|
||||
for (PrivilegeContext ctx : contexts) {
|
||||
if (ctx.getUserRep().getUsername().equals(user.getUsername()))
|
||||
invalidate(ctx.getCertificate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1251,6 +1328,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public void initiateChallengeFor(Usage usage, String username, String source) {
|
||||
this.lockingHandler.lockedExecute(username, () -> internalInitiateChallengeFor(usage, username, source));
|
||||
}
|
||||
|
||||
private void internalInitiateChallengeFor(Usage usage, String username, String source) {
|
||||
DBC.PRE.assertNotEmpty("source must not be empty!", source);
|
||||
|
||||
// get User
|
||||
|
@ -1272,6 +1353,12 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public Certificate validateChallenge(String username, String challenge, String source) throws PrivilegeException {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username,
|
||||
() -> internalValidateChallenge(username, challenge, source));
|
||||
}
|
||||
|
||||
private Certificate internalValidateChallenge(String username, String challenge, String source)
|
||||
throws PrivilegeException {
|
||||
DBC.PRE.assertNotEmpty("source must not be empty!", source);
|
||||
|
||||
// get User
|
||||
|
@ -1311,6 +1398,12 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public Certificate authenticate(String username, char[] password, String source, Usage usage, boolean keepAlive) {
|
||||
return this.lockingHandler.lockedExecuteWithResult(username,
|
||||
() -> internalAuthenticate(username, password, source, usage, keepAlive));
|
||||
}
|
||||
|
||||
private Certificate internalAuthenticate(String username, char[] password, String source, Usage usage,
|
||||
boolean keepAlive) {
|
||||
DBC.PRE.assertNotEmpty("source must not be empty!", source);
|
||||
|
||||
try {
|
||||
|
@ -1381,13 +1474,20 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Certificate authenticateSingleSignOn(Object data, String source, boolean keepAlive)
|
||||
throws PrivilegeException {
|
||||
public Certificate authenticateSingleSignOn(Object data, String source, boolean keepAlive) {
|
||||
DBC.PRE.assertNotEmpty("source must not be empty!", source);
|
||||
if (this.ssoHandler == null)
|
||||
throw new IllegalStateException("The SSO Handler is not configured!");
|
||||
|
||||
User user = this.ssoHandler.authenticateSingleSignOn(data);
|
||||
|
||||
return this.lockingHandler.lockedExecuteWithResult(user.getUsername(),
|
||||
() -> internalAuthenticateSingleSignOn(user, source, keepAlive));
|
||||
}
|
||||
|
||||
private Certificate internalAuthenticateSingleSignOn(User user, String source, boolean keepAlive)
|
||||
throws PrivilegeException {
|
||||
|
||||
DBC.PRE.assertEquals("SSO Users must have UserState.REMOTE!", UserState.REMOTE, user.getUserState());
|
||||
user.getHistory().setLastLogin(ZonedDateTime.now());
|
||||
|
||||
|
@ -1427,6 +1527,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
|
||||
@Override
|
||||
public Certificate refresh(Certificate certificate, String source) throws AccessDeniedException {
|
||||
return this.lockingHandler.lockedExecuteWithResult(certificate.getUsername(),
|
||||
() -> internalRefresh(certificate, source));
|
||||
}
|
||||
|
||||
private Certificate internalRefresh(Certificate certificate, String source) throws AccessDeniedException {
|
||||
DBC.PRE.assertNotNull("certificate must not be null!", certificate);
|
||||
|
||||
try {
|
||||
|
@ -1490,29 +1595,36 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
user.getLocale(), userRoles, new HashMap<>(user.getProperties()));
|
||||
}
|
||||
|
||||
private synchronized boolean persistSessions() {
|
||||
private boolean persistSessions() {
|
||||
if (!this.persistSessions)
|
||||
return false;
|
||||
|
||||
List<Certificate> sessions = new ArrayList<>(this.privilegeContextMap.values()).stream()
|
||||
.map(PrivilegeContext::getCertificate)
|
||||
.filter(c -> !c.getUserState().isSystem())
|
||||
.collect(Collectors.toList());
|
||||
// async execution, max. once per second
|
||||
if (this.persistSessionsTask != null)
|
||||
this.persistSessionsTask.cancel(true);
|
||||
this.persistSessionsTask = this.executorService.schedule(
|
||||
() -> this.lockingHandler.lockedExecute("persist-sessions", () -> {
|
||||
|
||||
try (OutputStream fout = Files.newOutputStream(this.persistSessionsPath.toPath());
|
||||
OutputStream outputStream = AesCryptoHelper.wrapEncrypt(this.secretKey, fout)) {
|
||||
List<Certificate> sessions = new ArrayList<>(this.privilegeContextMap.values()).stream()
|
||||
.map(PrivilegeContext::getCertificate)
|
||||
.filter(c -> !c.getUserState().isSystem())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
CertificateStubsDomWriter writer = new CertificateStubsDomWriter(sessions, outputStream);
|
||||
writer.write();
|
||||
outputStream.flush();
|
||||
try (OutputStream out = Files.newOutputStream(this.persistSessionsPath.toPath());
|
||||
OutputStream outputStream = AesCryptoHelper.wrapEncrypt(this.secretKey, out)) {
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to persist sessions!", e);
|
||||
if (this.persistSessionsPath.exists() && !this.persistSessionsPath.delete()) {
|
||||
logger.error("Failed to delete sessions file after failing to write to it, at "
|
||||
+ this.persistSessionsPath.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
CertificateStubsDomWriter writer = new CertificateStubsDomWriter(sessions, outputStream);
|
||||
writer.write();
|
||||
outputStream.flush();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to persist sessions!", e);
|
||||
if (this.persistSessionsPath.exists() && !this.persistSessionsPath.delete()) {
|
||||
logger.error("Failed to delete sessions file after failing to write to it, at "
|
||||
+ this.persistSessionsPath.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}), 1, TimeUnit.SECONDS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1605,7 +1717,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* @throws InvalidCredentialsException
|
||||
* if the given credentials are invalid, the user does not exist, or has no password set
|
||||
*/
|
||||
protected synchronized User checkCredentialsAndUserState(String username, char[] password)
|
||||
protected User checkCredentialsAndUserState(String username, char[] password)
|
||||
throws InvalidCredentialsException, AccessDeniedException {
|
||||
|
||||
// and validate the password
|
||||
|
@ -1905,6 +2017,16 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
return persistSessions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.lockingHandler.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.lockingHandler.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reload(Certificate certificate, String source) {
|
||||
|
||||
|
@ -1936,16 +2058,18 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
* map of {@link PrivilegePolicy} classes
|
||||
*
|
||||
* @throws PrivilegeException
|
||||
* if the this method is called multiple times or an initialization exception occurs
|
||||
* if this method is called multiple times or an initialization exception occurs
|
||||
*/
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
public synchronized void initialize(ScheduledExecutorService executorService, Map<String, String> parameterMap,
|
||||
EncryptionHandler encryptionHandler, PasswordStrengthHandler passwordStrengthHandler,
|
||||
PersistenceHandler persistenceHandler, UserChallengeHandler userChallengeHandler,
|
||||
SingleSignOnHandler ssoHandler, Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
|
||||
if (this.initialized)
|
||||
throw new PrivilegeModelException("Already initialized!");
|
||||
|
||||
this.executorService = executorService;
|
||||
this.lockingHandler = new ElementLockingHandler<>(executorService, TimeUnit.SECONDS, 10L);
|
||||
this.policyMap = policyMap;
|
||||
this.encryptionHandler = encryptionHandler;
|
||||
this.passwordStrengthHandler = passwordStrengthHandler;
|
||||
|
@ -1969,7 +2093,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
// validate privilege conflicts
|
||||
validatePrivilegeConflicts();
|
||||
|
||||
this.privilegeContextMap = Collections.synchronizedMap(new HashMap<>());
|
||||
this.privilegeContextMap = new ConcurrentHashMap<>();
|
||||
|
||||
loadSessions();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import javax.naming.directory.Attributes;
|
|||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
@ -29,12 +30,12 @@ public class JsonConfigLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
|
|||
private HashMap<String, String> userLdapGroupOverrides;
|
||||
|
||||
@Override
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
public synchronized 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(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
super.initialize(executorService, parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
userChallengeHandler, ssoHandler, policyMap);
|
||||
|
||||
this.realm = parameterMap.get(REALM);
|
||||
|
@ -48,9 +49,8 @@ public class JsonConfigLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
|
|||
DBC.PRE.assertNotEmpty("configFile param must be set!", configFileS);
|
||||
File configFile = new File(configFileS);
|
||||
if (!configFile.exists() || !configFile.isFile() || !configFile.canRead())
|
||||
throw new IllegalStateException(
|
||||
"configFile does not exist, is not a file, or can not be read at path " + configFile
|
||||
.getAbsolutePath());
|
||||
throw new IllegalStateException("configFile does not exist, is not a file, or can not be read at path "
|
||||
+ configFile.getAbsolutePath());
|
||||
|
||||
// parse the configuration file
|
||||
JsonObject configJ;
|
||||
|
@ -133,7 +133,8 @@ public class JsonConfigLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
|
|||
logger.info("Overriding LDAP group for user " + username + " to " + overrideGroup);
|
||||
}
|
||||
|
||||
Set<String> relevantLdapGroups = ldapGroups.stream().filter(s -> this.ldapGroupNames.contains(s))
|
||||
Set<String> relevantLdapGroups = ldapGroups.stream()
|
||||
.filter(s -> this.ldapGroupNames.contains(s))
|
||||
.collect(toSet());
|
||||
if (relevantLdapGroups.isEmpty())
|
||||
throw new IllegalStateException("User " + username
|
||||
|
|
|
@ -823,6 +823,16 @@ public interface PrivilegeHandler {
|
|||
*/
|
||||
void validatePassword(Locale locale, char[] password) throws PasswordStrengthException;
|
||||
|
||||
/**
|
||||
* Starts the privilege handler, starting any threads and services which might be needed
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Stops the privilege handler, starting any threads and services which might be needed
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Informs this {@link PersistenceHandler} to reload the data from the backend
|
||||
|
|
|
@ -6,6 +6,7 @@ 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;
|
||||
|
@ -25,12 +26,12 @@ public class SimpleLdapPrivilegeHandler extends BaseLdapPrivilegeHandler {
|
|||
private String realm;
|
||||
|
||||
@Override
|
||||
public synchronized void initialize(Map<String, String> parameterMap, EncryptionHandler encryptionHandler,
|
||||
PasswordStrengthHandler passwordStrengthHandler, PersistenceHandler persistenceHandler,
|
||||
UserChallengeHandler userChallengeHandler, SingleSignOnHandler ssoHandler,
|
||||
Map<String, Class<PrivilegePolicy>> policyMap) {
|
||||
public synchronized 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(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
super.initialize(executorService, parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
userChallengeHandler, ssoHandler, policyMap);
|
||||
|
||||
this.organisation = parameterMap.getOrDefault(ORGANISATION, "");
|
||||
|
|
|
@ -21,7 +21,10 @@ import static li.strolch.privilege.helper.XmlConstants.*;
|
|||
import static li.strolch.utils.helper.StringHelper.formatNanoDuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import li.strolch.privilege.base.PrivilegeException;
|
||||
import li.strolch.privilege.helper.XmlConstants;
|
||||
|
@ -46,8 +49,8 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
|||
|
||||
protected static final Logger logger = LoggerFactory.getLogger(XmlPersistenceHandler.class);
|
||||
|
||||
private Map<String, User> userMap;
|
||||
private Map<String, Role> roleMap;
|
||||
private final Map<String, User> userMap;
|
||||
private final Map<String, Role> roleMap;
|
||||
|
||||
private boolean userMapDirty;
|
||||
private boolean roleMapDirty;
|
||||
|
@ -59,6 +62,11 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
|||
|
||||
private boolean caseInsensitiveUsername;
|
||||
|
||||
public XmlPersistenceHandler() {
|
||||
this.roleMap = new ConcurrentHashMap<>();
|
||||
this.userMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParameterMap() {
|
||||
return this.parameterMap;
|
||||
|
@ -212,27 +220,23 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
|||
@Override
|
||||
public boolean reload() {
|
||||
|
||||
this.roleMap = Collections.synchronizedMap(new HashMap<>());
|
||||
this.userMap = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
// parse models xml file to XML document
|
||||
PrivilegeUsersSaxReader usersXmlHandler = new PrivilegeUsersSaxReader();
|
||||
PrivilegeUsersSaxReader usersXmlHandler = new PrivilegeUsersSaxReader(this.caseInsensitiveUsername);
|
||||
XmlHelper.parseDocument(this.usersPath, usersXmlHandler);
|
||||
|
||||
PrivilegeRolesSaxReader rolesXmlHandler = new PrivilegeRolesSaxReader();
|
||||
XmlHelper.parseDocument(this.rolesPath, rolesXmlHandler);
|
||||
|
||||
// ROLES
|
||||
List<Role> roles = rolesXmlHandler.getRoles();
|
||||
for (Role role : roles) {
|
||||
this.roleMap.put(role.getName(), role);
|
||||
synchronized (this.roleMap) {
|
||||
this.roleMap.clear();
|
||||
this.roleMap.putAll(rolesXmlHandler.getRoles());
|
||||
}
|
||||
|
||||
// USERS
|
||||
List<User> users = usersXmlHandler.getUsers();
|
||||
for (User user : users) {
|
||||
this.userMap
|
||||
.put(this.caseInsensitiveUsername ? user.getUsername().toLowerCase() : user.getUsername(), user);
|
||||
synchronized (this.userMap) {
|
||||
this.userMap.clear();
|
||||
this.userMap.putAll(usersXmlHandler.getUsers());
|
||||
}
|
||||
|
||||
this.userMapDirty = false;
|
||||
|
@ -242,7 +246,7 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
|||
logger.info(format("Read {0} Roles", this.roleMap.size()));
|
||||
|
||||
// validate referenced roles exist
|
||||
for (User user : users) {
|
||||
for (User user : this.userMap.values()) {
|
||||
for (String roleName : user.getRoles()) {
|
||||
|
||||
// validate that role exists
|
||||
|
|
|
@ -1,200 +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.helper;
|
||||
|
||||
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.privilege.base.PrivilegeException;
|
||||
import li.strolch.privilege.handler.*;
|
||||
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
|
||||
import li.strolch.privilege.policy.PrivilegePolicy;
|
||||
import li.strolch.privilege.xml.PrivilegeConfigSaxReader;
|
||||
import li.strolch.utils.helper.ClassHelper;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class implements the initializing of the {@link PrivilegeHandler} by loading an XML file containing the
|
||||
* configuration
|
||||
*
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeInitializationHelper {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PrivilegeInitializationHelper.class);
|
||||
|
||||
/**
|
||||
* Initializes the {@link DefaultPrivilegeHandler} from the configuration file
|
||||
*
|
||||
* @param privilegeXmlFile
|
||||
* a {@link File} reference to the XML file containing the configuration for Privilege
|
||||
*
|
||||
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and {@link
|
||||
* PersistenceHandler} are set and initialized as well
|
||||
*/
|
||||
public static PrivilegeHandler initializeFromXml(File privilegeXmlFile) {
|
||||
|
||||
// make sure file exists
|
||||
if (!privilegeXmlFile.exists()) {
|
||||
String msg = "Privilege file does not exist at path {0}";
|
||||
msg = MessageFormat.format(msg, privilegeXmlFile.getAbsolutePath());
|
||||
throw new PrivilegeException(msg);
|
||||
}
|
||||
|
||||
// delegate using input stream
|
||||
try (InputStream fin = Files.newInputStream(privilegeXmlFile.toPath())) {
|
||||
return initializeFromXml(fin);
|
||||
} catch (Exception e) {
|
||||
String msg = "Failed to load configuration from {0}";
|
||||
msg = MessageFormat.format(msg, privilegeXmlFile.getAbsolutePath());
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the {@link PrivilegeHandler} by loading from the given input stream. This stream must be a valid XML
|
||||
* source
|
||||
*
|
||||
* @param privilegeConfigInputStream
|
||||
* the XML stream containing the privilege configuration
|
||||
*
|
||||
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and {@link
|
||||
* PersistenceHandler} are set and initialized as well
|
||||
*/
|
||||
public static PrivilegeHandler initializeFromXml(InputStream privilegeConfigInputStream) {
|
||||
|
||||
// parse configuration file
|
||||
PrivilegeContainerModel containerModel = new PrivilegeContainerModel();
|
||||
PrivilegeConfigSaxReader xmlHandler = new PrivilegeConfigSaxReader(containerModel);
|
||||
XmlHelper.parseDocument(privilegeConfigInputStream, xmlHandler);
|
||||
|
||||
return initializeFromXml(containerModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the {@link PrivilegeHandler} by initializing from the given {@link PrivilegeContainerModel}
|
||||
*
|
||||
* @param containerModel
|
||||
* the configuration for the {@link PrivilegeHandler}
|
||||
*
|
||||
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and {@link
|
||||
* PersistenceHandler} are set and initialized as well
|
||||
*/
|
||||
public static PrivilegeHandler initializeFromXml(PrivilegeContainerModel containerModel) {
|
||||
|
||||
// initialize encryption handler
|
||||
String encryptionHandlerClassName = containerModel.getEncryptionHandlerClassName();
|
||||
EncryptionHandler encryptionHandler = ClassHelper.instantiateClass(encryptionHandlerClassName);
|
||||
Map<String, String> parameterMap = containerModel.getEncryptionHandlerParameterMap();
|
||||
try {
|
||||
encryptionHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "EncryptionHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, encryptionHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
// initialize password strength handler
|
||||
String passwordStrengthHandlerClassName = containerModel.getPasswordStrengthHandlerClassName();
|
||||
if (isEmpty(passwordStrengthHandlerClassName)) {
|
||||
logger.info("No PasswordStrengthHandler defined, using " + SimplePasswordStrengthHandler.class.getName());
|
||||
passwordStrengthHandlerClassName = SimplePasswordStrengthHandler.class.getName();
|
||||
}
|
||||
PasswordStrengthHandler passwordStrengthHandler = ClassHelper
|
||||
.instantiateClass(passwordStrengthHandlerClassName);
|
||||
parameterMap = containerModel.getPasswordStrengthHandlerParameterMap();
|
||||
try {
|
||||
passwordStrengthHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PasswordStrengthHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, passwordStrengthHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
// initialize persistence handler
|
||||
String persistenceHandlerClassName = containerModel.getPersistenceHandlerClassName();
|
||||
PersistenceHandler persistenceHandler = ClassHelper.instantiateClass(persistenceHandlerClassName);
|
||||
parameterMap = containerModel.getPersistenceHandlerParameterMap();
|
||||
try {
|
||||
persistenceHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PersistenceHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, persistenceHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
// initialize challenge handler
|
||||
UserChallengeHandler challengeHandler;
|
||||
String challengeHandlerClassName = containerModel.getUserChallengeHandlerClassName();
|
||||
challengeHandler = ClassHelper.instantiateClass(challengeHandlerClassName);
|
||||
parameterMap = containerModel.getUserChallengeHandlerParameterMap();
|
||||
try {
|
||||
challengeHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "UserChallengeHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, persistenceHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
// initialize SSO handler
|
||||
SingleSignOnHandler ssoHandler;
|
||||
if (containerModel.getSsoHandlerClassName() == null) {
|
||||
ssoHandler = null;
|
||||
} else {
|
||||
String ssoHandlerClassName = containerModel.getSsoHandlerClassName();
|
||||
ssoHandler = ClassHelper.instantiateClass(ssoHandlerClassName);
|
||||
parameterMap = containerModel.getSsoHandlerParameterMap();
|
||||
try {
|
||||
ssoHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "SingleSignOnHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, ssoHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
// initialize privilege handler
|
||||
DefaultPrivilegeHandler privilegeHandler;
|
||||
parameterMap = containerModel.getParameterMap();
|
||||
|
||||
if (containerModel.getPrivilegeHandlerClassName() == null) {
|
||||
privilegeHandler = new DefaultPrivilegeHandler();
|
||||
} else {
|
||||
String privilegeHandlerClassName = containerModel.getPrivilegeHandlerClassName();
|
||||
privilegeHandler = ClassHelper.instantiateClass(privilegeHandlerClassName);
|
||||
parameterMap.putAll(containerModel.getPrivilegeHandlerParameterMap());
|
||||
}
|
||||
|
||||
Map<String, Class<PrivilegePolicy>> policyMap = containerModel.getPolicies();
|
||||
try {
|
||||
privilegeHandler.initialize(parameterMap, encryptionHandler, passwordStrengthHandler, persistenceHandler,
|
||||
challengeHandler, ssoHandler, policyMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PrivilegeHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, privilegeHandler.getClass().getName());
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return privilegeHandler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* 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.helper;
|
||||
|
||||
import static li.strolch.utils.helper.ClassHelper.instantiateClass;
|
||||
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import li.strolch.privilege.base.PrivilegeException;
|
||||
import li.strolch.privilege.handler.*;
|
||||
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
|
||||
import li.strolch.privilege.policy.PrivilegePolicy;
|
||||
import li.strolch.privilege.xml.PrivilegeConfigSaxReader;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class implements the initializing of the {@link PrivilegeHandler} by loading an XML file containing the
|
||||
* configuration
|
||||
*
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeInitializer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PrivilegeInitializer.class);
|
||||
|
||||
private final ScheduledExecutorService executorService;
|
||||
|
||||
private PrivilegeContainerModel containerModel;
|
||||
private EncryptionHandler encryptionHandler;
|
||||
private PasswordStrengthHandler passwordStrengthHandler;
|
||||
private PersistenceHandler persistenceHandler;
|
||||
private UserChallengeHandler challengeHandler;
|
||||
private SingleSignOnHandler ssoHandler;
|
||||
private PrivilegeHandler privilegeHandler;
|
||||
|
||||
public PrivilegeInitializer(ScheduledExecutorService executorService) {
|
||||
DBC.PRE.assertNotNull("executorService may not be null", executorService);
|
||||
this.executorService = executorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the {@link PrivilegeHandler} from the configuration file
|
||||
*
|
||||
* @param privilegeXmlFile
|
||||
* a {@link File} reference to the XML file containing the configuration for Privilege
|
||||
*
|
||||
* @return the initialized {@link PrivilegeHandler} where the {@link EncryptionHandler} and
|
||||
* {@link PersistenceHandler} are set and initialized as well
|
||||
*/
|
||||
public PrivilegeHandler initializeFromXml(File privilegeXmlFile) {
|
||||
|
||||
// make sure file exists
|
||||
if (!privilegeXmlFile.exists()) {
|
||||
String msg = "Privilege file does not exist at path {0}";
|
||||
msg = MessageFormat.format(msg, privilegeXmlFile.getAbsolutePath());
|
||||
throw new PrivilegeException(msg);
|
||||
}
|
||||
|
||||
// delegate using input stream
|
||||
try (InputStream fin = Files.newInputStream(privilegeXmlFile.toPath())) {
|
||||
this.containerModel = parseXmlConfiguration(fin);
|
||||
} catch (Exception e) {
|
||||
String msg = "Failed to load configuration from {0}";
|
||||
msg = MessageFormat.format(msg, privilegeXmlFile.getAbsolutePath());
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
initializeComponents();
|
||||
this.privilegeHandler = initializedPrivilegeHandler();
|
||||
return this.privilegeHandler;
|
||||
}
|
||||
|
||||
public PrivilegeHandler initializeFromXml(PrivilegeContainerModel containerModel) {
|
||||
this.containerModel = containerModel;
|
||||
initializeComponents();
|
||||
this.privilegeHandler = initializedPrivilegeHandler();
|
||||
return this.privilegeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the privilege XML configuration from the given stream
|
||||
*
|
||||
* @param privilegeConfigInputStream
|
||||
* the XML stream containing the privilege configuration
|
||||
*/
|
||||
public PrivilegeContainerModel parseXmlConfiguration(InputStream privilegeConfigInputStream) {
|
||||
|
||||
// parse configuration file
|
||||
PrivilegeContainerModel containerModel = new PrivilegeContainerModel();
|
||||
PrivilegeConfigSaxReader xmlHandler = new PrivilegeConfigSaxReader(containerModel);
|
||||
XmlHelper.parseDocument(privilegeConfigInputStream, xmlHandler);
|
||||
|
||||
return containerModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the privilege handlers from the given container model
|
||||
*/
|
||||
private void initializeComponents() {
|
||||
|
||||
this.encryptionHandler = initializedEncryptionHandler();
|
||||
this.passwordStrengthHandler = initializePasswordStrengthHandler();
|
||||
this.persistenceHandler = initializePersistenceHandler();
|
||||
this.challengeHandler = initializeUserChallengeHandler();
|
||||
this.ssoHandler = initializeSingleSignOnHandler();
|
||||
}
|
||||
|
||||
private PrivilegeHandler initializedPrivilegeHandler() {
|
||||
DefaultPrivilegeHandler privilegeHandler;
|
||||
Map<String, String> parameterMap = this.containerModel.getParameterMap();
|
||||
|
||||
if (this.containerModel.getPrivilegeHandlerClassName() == null) {
|
||||
privilegeHandler = new DefaultPrivilegeHandler();
|
||||
} else {
|
||||
String privilegeHandlerClassName = this.containerModel.getPrivilegeHandlerClassName();
|
||||
privilegeHandler = instantiateClass(privilegeHandlerClassName);
|
||||
parameterMap.putAll(this.containerModel.getPrivilegeHandlerParameterMap());
|
||||
}
|
||||
|
||||
Map<String, Class<PrivilegePolicy>> policyMap = this.containerModel.getPolicies();
|
||||
try {
|
||||
privilegeHandler.initialize(this.executorService, parameterMap, this.encryptionHandler,
|
||||
this.passwordStrengthHandler, this.persistenceHandler, this.challengeHandler, this.ssoHandler,
|
||||
policyMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PrivilegeHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, privilegeHandler.getClass().getName());
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return privilegeHandler;
|
||||
}
|
||||
|
||||
private SingleSignOnHandler initializeSingleSignOnHandler() {
|
||||
if (this.containerModel.getSsoHandlerClassName() == null)
|
||||
return null;
|
||||
|
||||
String ssoHandlerClassName = this.containerModel.getSsoHandlerClassName();
|
||||
SingleSignOnHandler ssoHandler = instantiateClass(ssoHandlerClassName);
|
||||
Map<String, String> parameterMap = this.containerModel.getSsoHandlerParameterMap();
|
||||
|
||||
try {
|
||||
ssoHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "SingleSignOnHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, ssoHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return ssoHandler;
|
||||
}
|
||||
|
||||
private UserChallengeHandler initializeUserChallengeHandler() {
|
||||
String challengeHandlerClassName = this.containerModel.getUserChallengeHandlerClassName();
|
||||
UserChallengeHandler challengeHandler = instantiateClass(challengeHandlerClassName);
|
||||
Map<String, String> parameterMap = this.containerModel.getUserChallengeHandlerParameterMap();
|
||||
|
||||
try {
|
||||
challengeHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "UserChallengeHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, challengeHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return challengeHandler;
|
||||
}
|
||||
|
||||
private PersistenceHandler initializePersistenceHandler() {
|
||||
String persistenceHandlerClassName = this.containerModel.getPersistenceHandlerClassName();
|
||||
PersistenceHandler persistenceHandler = instantiateClass(persistenceHandlerClassName);
|
||||
Map<String, String> parameterMap = this.containerModel.getPersistenceHandlerParameterMap();
|
||||
|
||||
try {
|
||||
persistenceHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PersistenceHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, persistenceHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return persistenceHandler;
|
||||
}
|
||||
|
||||
private PasswordStrengthHandler initializePasswordStrengthHandler() {
|
||||
String passwordStrengthHandlerClassName = this.containerModel.getPasswordStrengthHandlerClassName();
|
||||
if (isEmpty(passwordStrengthHandlerClassName)) {
|
||||
logger.info("No PasswordStrengthHandler defined, using " + SimplePasswordStrengthHandler.class.getName());
|
||||
passwordStrengthHandlerClassName = SimplePasswordStrengthHandler.class.getName();
|
||||
}
|
||||
|
||||
PasswordStrengthHandler passwordStrengthHandler = instantiateClass(passwordStrengthHandlerClassName);
|
||||
Map<String, String> parameterMap = this.containerModel.getPasswordStrengthHandlerParameterMap();
|
||||
|
||||
try {
|
||||
passwordStrengthHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "PasswordStrengthHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, passwordStrengthHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return passwordStrengthHandler;
|
||||
}
|
||||
|
||||
private EncryptionHandler initializedEncryptionHandler() {
|
||||
String encryptionHandlerClassName = this.containerModel.getEncryptionHandlerClassName();
|
||||
EncryptionHandler encryptionHandler = instantiateClass(encryptionHandlerClassName);
|
||||
Map<String, String> parameterMap = this.containerModel.getEncryptionHandlerParameterMap();
|
||||
|
||||
try {
|
||||
encryptionHandler.initialize(parameterMap);
|
||||
} catch (Exception e) {
|
||||
String msg = "EncryptionHandler {0} could not be initialized";
|
||||
msg = MessageFormat.format(msg, encryptionHandlerClassName);
|
||||
throw new PrivilegeException(msg, e);
|
||||
}
|
||||
|
||||
return encryptionHandler;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package li.strolch.privilege.helper;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesDomWriter;
|
||||
|
@ -26,7 +28,8 @@ public class WriteRolesFileHelper {
|
|||
PrivilegeRolesSaxReader xmlHandler = new PrivilegeRolesSaxReader();
|
||||
XmlHelper.parseDocument(src, xmlHandler);
|
||||
|
||||
List<Role> roles = xmlHandler.getRoles();
|
||||
Map<String, Role> rolesMap = xmlHandler.getRoles();
|
||||
List<Role> roles = new ArrayList<>(rolesMap.values());
|
||||
|
||||
PrivilegeRolesDomWriter configSaxWriter = new PrivilegeRolesDomWriter(roles, dst);
|
||||
configSaxWriter.write();
|
||||
|
|
|
@ -38,13 +38,13 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
|
||||
private final Deque<ElementParser> buildersStack = new ArrayDeque<>();
|
||||
|
||||
private final List<Role> roles;
|
||||
private final Map<String, Role> roles;
|
||||
|
||||
public PrivilegeRolesSaxReader() {
|
||||
this.roles = new ArrayList<>();
|
||||
this.roles = new HashMap<>();
|
||||
}
|
||||
|
||||
public List<Role> getRoles() {
|
||||
public Map<String, Role> getRoles() {
|
||||
return this.roles;
|
||||
}
|
||||
|
||||
|
@ -84,19 +84,19 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
this.buildersStack.peek().notifyChild(elementParser);
|
||||
}
|
||||
|
||||
// <Role name="AppUser">
|
||||
// <Privilege name="li.strolch.privilege.test.model.TestRestrictable">
|
||||
// <AllAllowed>true</AllAllowed>
|
||||
// </Privilege>
|
||||
// </Role>
|
||||
// <Role name="system_admin_privileges">
|
||||
// <Privilege name="li.strolch.privilege.test.model.TestSystemUserAction">
|
||||
// <AllAllowed>true</AllAllowed>
|
||||
// </Privilege>
|
||||
// <Privilege name="li.strolch.privilege.test.model.TestSystemRestrictable">
|
||||
// <AllAllowed>true</AllAllowed>
|
||||
// </Privilege>
|
||||
// </Role>
|
||||
// <Role name="AppUser">
|
||||
// <Privilege name="li.strolch.privilege.test.model.TestRestrictable">
|
||||
// <AllAllowed>true</AllAllowed>
|
||||
// </Privilege>
|
||||
// </Role>
|
||||
// <Role name="system_admin_privileges">
|
||||
// <Privilege name="li.strolch.privilege.test.model.TestSystemUserAction">
|
||||
// <AllAllowed>true</AllAllowed>
|
||||
// </Privilege>
|
||||
// <Privilege name="li.strolch.privilege.test.model.TestSystemRestrictable">
|
||||
// <AllAllowed>true</AllAllowed>
|
||||
// </Privilege>
|
||||
// </Role>
|
||||
|
||||
public class RoleParser extends ElementParserAdapter {
|
||||
|
||||
|
@ -177,7 +177,7 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
}
|
||||
case XmlConstants.XML_ROLE -> {
|
||||
Role role = new Role(this.roleName, this.privileges);
|
||||
getRoles().add(role);
|
||||
roles.put(role.getName(), role);
|
||||
logger.info(MessageFormat.format("New Role: {0}", role));
|
||||
init();
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
|
||||
static class PropertyParser extends ElementParserAdapter {
|
||||
|
||||
// <Property name="organizationalUnit" value="Development" />
|
||||
// <Property name="organizationalUnit" value="Development" />
|
||||
|
||||
public final Map<String, String> parameterMap = new HashMap<>();
|
||||
|
||||
|
@ -197,9 +197,7 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME).trim();
|
||||
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE).trim();
|
||||
this.parameterMap.put(key, value);
|
||||
} else if (qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
// NO-OP
|
||||
} else {
|
||||
} else if (!qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,16 +40,18 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
|
||||
private final Deque<ElementParser> buildersStack = new ArrayDeque<>();
|
||||
|
||||
private final List<User> users;
|
||||
private final Map<String, User> users;
|
||||
private final boolean caseInsensitiveUsername;
|
||||
|
||||
public PrivilegeUsersSaxReader() {
|
||||
this.users = new ArrayList<>();
|
||||
public PrivilegeUsersSaxReader(boolean caseInsensitiveUsername) {
|
||||
this.caseInsensitiveUsername = caseInsensitiveUsername;
|
||||
this.users = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the users
|
||||
*/
|
||||
public List<User> getUsers() {
|
||||
public Map<String, User> getUsers() {
|
||||
return this.users;
|
||||
}
|
||||
|
||||
|
@ -88,25 +90,25 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
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>
|
||||
// <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 UserParser extends ElementParserAdapter {
|
||||
|
||||
|
@ -210,11 +212,14 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
case XML_USER -> {
|
||||
if (this.history == null)
|
||||
this.history = new UserHistory();
|
||||
|
||||
User user = new User(this.userId, this.username, this.password, this.salt, this.hashAlgorithm,
|
||||
hashIterations, hashKeyLength, this.firstName, this.lastname, this.userState, this.userRoles,
|
||||
this.locale, this.parameters, this.passwordChangeRequested, this.history);
|
||||
|
||||
logger.info(MessageFormat.format("New User: {0}", user));
|
||||
getUsers().add(user);
|
||||
String username = caseInsensitiveUsername ? user.getUsername().toLowerCase() : user.getUsername();
|
||||
users.put(username, user);
|
||||
}
|
||||
default -> {
|
||||
if (!(qName.equals(XML_ROLES) //
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package li.strolch.privilege.test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
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.PrivilegeInitializationHelper;
|
||||
import li.strolch.privilege.helper.PrivilegeInitializer;
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
import li.strolch.privilege.model.PrivilegeContext;
|
||||
import li.strolch.utils.helper.FileHelper;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -18,12 +22,24 @@ public class AbstractPrivilegeTest {
|
|||
|
||||
protected static final Logger logger = LoggerFactory.getLogger(AbstractPrivilegeTest.class);
|
||||
|
||||
protected static ScheduledExecutorService executorService;
|
||||
protected PrivilegeHandler privilegeHandler;
|
||||
protected PrivilegeContext ctx;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
executorService = Executors.newScheduledThreadPool(1);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void afterClass() {
|
||||
if (executorService != null)
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
|
||||
protected void login(String username, char[] password) {
|
||||
Certificate certificate = privilegeHandler.authenticate(username, password, false);
|
||||
assertTrue("Certificate is null!", certificate != null);
|
||||
assertNotNull("Certificate is null!", certificate);
|
||||
this.ctx = privilegeHandler.validate(certificate);
|
||||
}
|
||||
|
||||
|
@ -101,7 +117,7 @@ public class AbstractPrivilegeTest {
|
|||
protected void initialize(String dst, String configFilename) {
|
||||
try {
|
||||
File privilegeConfigFile = getPrivilegeConfigFile(dst, configFilename);
|
||||
this.privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile);
|
||||
this.privilegeHandler = new PrivilegeInitializer(executorService).initializeFromXml(privilegeConfigFile);
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
throw new RuntimeException("Initialization failed", e);
|
||||
|
|
|
@ -30,7 +30,7 @@ public class PersistSessionsTest extends AbstractPrivilegeTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void shouldPersistAndReloadSessions() {
|
||||
public void shouldPersistAndReloadSessions() throws InterruptedException {
|
||||
|
||||
// assert no sessions file
|
||||
File sessionsFile = new File("target/PersistSessionsTest/sessions.dat");
|
||||
|
@ -39,6 +39,8 @@ public class PersistSessionsTest extends AbstractPrivilegeTest {
|
|||
// login and assert sessions file was written
|
||||
login("admin", "admin".toCharArray());
|
||||
this.privilegeHandler.validate(ctx.getCertificate());
|
||||
// persisting is async, once per second
|
||||
Thread.sleep(1200L);
|
||||
assertTrue("Sessions File should have been created!", sessionsFile.isFile());
|
||||
|
||||
// re-initialize and assert still logged in
|
||||
|
|
|
@ -112,8 +112,6 @@ public class XmlTest {
|
|||
assertEquals(4, containerModel.getPolicies().size());
|
||||
assertEquals(3, containerModel.getEncryptionHandlerParameterMap().size());
|
||||
assertEquals(3, containerModel.getPersistenceHandlerParameterMap().size());
|
||||
|
||||
// TODO extend assertions to actual model
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -150,11 +148,11 @@ public class XmlTest {
|
|||
@Test
|
||||
public void canReadUsers() {
|
||||
|
||||
PrivilegeUsersSaxReader xmlHandler = new PrivilegeUsersSaxReader();
|
||||
PrivilegeUsersSaxReader xmlHandler = new PrivilegeUsersSaxReader(true);
|
||||
File xmlFile = new File(SRC_TEST + "PrivilegeUsers.xml");
|
||||
XmlHelper.parseDocument(xmlFile, xmlHandler);
|
||||
|
||||
List<User> users = xmlHandler.getUsers();
|
||||
Map<String, User> users = xmlHandler.getUsers();
|
||||
assertNotNull(users);
|
||||
|
||||
assertEquals(4, users.size());
|
||||
|
@ -201,7 +199,7 @@ public class XmlTest {
|
|||
File xmlFile = new File(SRC_TEST + "PrivilegeRoles.xml");
|
||||
XmlHelper.parseDocument(xmlFile, xmlHandler);
|
||||
|
||||
List<Role> roles = xmlHandler.getRoles();
|
||||
Map<String, Role> roles = xmlHandler.getRoles();
|
||||
assertNotNull(roles);
|
||||
|
||||
assertEquals(6, roles.size());
|
||||
|
@ -227,8 +225,8 @@ public class XmlTest {
|
|||
assertEquals(0, privilegeAddRole.getAllowList().size());
|
||||
assertEquals(0, privilegeAddRole.getDenyList().size());
|
||||
|
||||
IPrivilege privilegeRemRoleFromUser = privilegeAdmin
|
||||
.getPrivilege(PrivilegeHandler.PRIVILEGE_REMOVE_ROLE_FROM_USER);
|
||||
IPrivilege privilegeRemRoleFromUser = privilegeAdmin.getPrivilege(
|
||||
PrivilegeHandler.PRIVILEGE_REMOVE_ROLE_FROM_USER);
|
||||
assertTrue(privilegeRemRoleFromUser.isAllAllowed());
|
||||
assertEquals(0, privilegeRemRoleFromUser.getAllowList().size());
|
||||
assertEquals(0, privilegeRemRoleFromUser.getDenyList().size());
|
||||
|
@ -254,16 +252,16 @@ public class XmlTest {
|
|||
containsInAnyOrder("li.strolch.privilege.handler.SystemAction",
|
||||
"li.strolch.privilege.test.model.TestSystemRestrictable"));
|
||||
|
||||
IPrivilege testSystemUserAction = systemAdminPrivileges
|
||||
.getPrivilege("li.strolch.privilege.handler.SystemAction");
|
||||
IPrivilege testSystemUserAction = systemAdminPrivileges.getPrivilege(
|
||||
"li.strolch.privilege.handler.SystemAction");
|
||||
assertEquals("li.strolch.privilege.handler.SystemAction", testSystemUserAction.getName());
|
||||
assertEquals("DefaultPrivilege", testSystemUserAction.getPolicy());
|
||||
assertFalse(testSystemUserAction.isAllAllowed());
|
||||
assertEquals(1, testSystemUserAction.getAllowList().size());
|
||||
assertEquals(1, testSystemUserAction.getDenyList().size());
|
||||
|
||||
IPrivilege testSystemRestrictable = systemAdminPrivileges
|
||||
.getPrivilege("li.strolch.privilege.test.model.TestSystemRestrictable");
|
||||
IPrivilege testSystemRestrictable = systemAdminPrivileges.getPrivilege(
|
||||
"li.strolch.privilege.test.model.TestSystemRestrictable");
|
||||
assertEquals("li.strolch.privilege.test.model.TestSystemRestrictable", testSystemRestrictable.getName());
|
||||
assertEquals("DefaultPrivilege", testSystemRestrictable.getPolicy());
|
||||
assertTrue(testSystemRestrictable.isAllAllowed());
|
||||
|
@ -287,22 +285,14 @@ public class XmlTest {
|
|||
MatcherAssert.assertThat(testSystemUserAction2.getDenyList(), containsInAnyOrder("goodbye"));
|
||||
}
|
||||
|
||||
private User findUser(String username, List<User> users) {
|
||||
for (User user : users) {
|
||||
if (user.getUsername().equals(username))
|
||||
return user;
|
||||
}
|
||||
|
||||
throw new RuntimeException("No user exists with username " + username);
|
||||
private User findUser(String username, Map<String, User> users) {
|
||||
return Optional.ofNullable(users.get(username))
|
||||
.orElseThrow(() -> new IllegalStateException("User " + username + " does not exist!"));
|
||||
}
|
||||
|
||||
private Role findRole(String name, List<Role> roles) {
|
||||
for (Role role : roles) {
|
||||
if (role.getName().equals(name))
|
||||
return role;
|
||||
}
|
||||
|
||||
throw new RuntimeException("No role exists with name " + name);
|
||||
private Role findRole(String name, Map<String, Role> roles) {
|
||||
return Optional.ofNullable(roles.get(name))
|
||||
.orElseThrow(() -> new IllegalStateException("Role " + name + " does not exist!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -337,16 +327,22 @@ public class XmlTest {
|
|||
PrivilegeUsersDomWriter configSaxWriter = new PrivilegeUsersDomWriter(users, modelFile);
|
||||
configSaxWriter.write();
|
||||
|
||||
PrivilegeUsersSaxReader xmlHandler = new PrivilegeUsersSaxReader();
|
||||
PrivilegeUsersSaxReader xmlHandler = new PrivilegeUsersSaxReader(true);
|
||||
XmlHelper.parseDocument(modelFile, xmlHandler);
|
||||
|
||||
List<User> parsedUsers = xmlHandler.getUsers();
|
||||
Map<String, User> parsedUsers = xmlHandler.getUsers();
|
||||
assertNotNull(parsedUsers);
|
||||
assertEquals(2, parsedUsers.size());
|
||||
|
||||
User parsedUser1 = parsedUsers.stream().filter(u -> u.getUsername().equals("user1")).findAny()
|
||||
User parsedUser1 = parsedUsers.values()
|
||||
.stream()
|
||||
.filter(u -> u.getUsername().equals("user1"))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new RuntimeException("user1 missing!"));
|
||||
User parsedUser2 = parsedUsers.stream().filter(u -> u.getUsername().equals("user2")).findAny()
|
||||
User parsedUser2 = parsedUsers.values()
|
||||
.stream()
|
||||
.filter(u -> u.getUsername().equals("user2"))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new RuntimeException("user2 missing!"));
|
||||
|
||||
assertEquals(user1.getFirstname(), parsedUser1.getFirstname());
|
||||
|
@ -397,14 +393,20 @@ public class XmlTest {
|
|||
PrivilegeRolesSaxReader xmlHandler = new PrivilegeRolesSaxReader();
|
||||
XmlHelper.parseDocument(modelFile, xmlHandler);
|
||||
|
||||
List<Role> parsedRoles = xmlHandler.getRoles();
|
||||
Map<String, Role> parsedRoles = xmlHandler.getRoles();
|
||||
assertNotNull(parsedRoles);
|
||||
assertEquals(2, parsedRoles.size());
|
||||
|
||||
assertEquals(2, parsedRoles.size());
|
||||
Role parsedRole1 = parsedRoles.stream().filter(r -> r.getName().equals("role1")).findAny()
|
||||
Role parsedRole1 = parsedRoles.values()
|
||||
.stream()
|
||||
.filter(r -> r.getName().equals("role1"))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new RuntimeException("role1 missing!"));
|
||||
Role parsedRole2 = parsedRoles.stream().filter(r -> r.getName().equals("role2")).findAny()
|
||||
Role parsedRole2 = parsedRoles.values()
|
||||
.stream()
|
||||
.filter(r -> r.getName().equals("role2"))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new RuntimeException("role2 missing!"));
|
||||
|
||||
Set<String> privilegeNames = role1.getPrivilegeNames();
|
||||
|
|
Loading…
Reference in New Issue