From 5dc94514e13d142de8e2532b3bec18b28c7855dd Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Fri, 16 Oct 2015 13:16:27 +0200 Subject: [PATCH] [Major] Added persisting of sessions --- config/PrivilegeConfig.xml | 6 +- config/PrivilegeConfigMerge.xml | 2 +- .../handler/DefaultPrivilegeHandler.java | 239 ++++++++++++++++-- .../privilege/handler/PrivilegeHandler.java | 56 ++++ .../handler/XmlPersistenceHandler.java | 8 +- .../privilege/helper/XmlConstants.java | 40 +++ .../eitchnet/privilege/model/Certificate.java | 32 +-- .../eitchnet/privilege/model/UserState.java | 4 + .../xml/CertificateStubsDomWriter.java | 79 ++++++ .../xml/CertificateStubsSaxReader.java | 114 +++++++++ .../xml/PrivilegeConfigSaxReader.java | 11 +- .../privilege/test/AbstractPrivilegeTest.java | 112 ++++++++ .../privilege/test/PersistSessionsTest.java | 47 ++++ .../test/PrivilegeConflictMergeTest.java | 99 +------- .../privilege/test/PrivilegeTest.java | 111 ++------ .../ch/eitchnet/privilege/test/XmlTest.java | 2 +- 16 files changed, 729 insertions(+), 233 deletions(-) create mode 100644 src/main/java/ch/eitchnet/privilege/xml/CertificateStubsDomWriter.java create mode 100644 src/main/java/ch/eitchnet/privilege/xml/CertificateStubsSaxReader.java create mode 100644 src/test/java/ch/eitchnet/privilege/test/AbstractPrivilegeTest.java create mode 100644 src/test/java/ch/eitchnet/privilege/test/PersistSessionsTest.java diff --git a/config/PrivilegeConfig.xml b/config/PrivilegeConfig.xml index 9dd3e2b11..4d293aca2 100644 --- a/config/PrivilegeConfig.xml +++ b/config/PrivilegeConfig.xml @@ -5,6 +5,10 @@ + + + + @@ -17,7 +21,7 @@ - + diff --git a/config/PrivilegeConfigMerge.xml b/config/PrivilegeConfigMerge.xml index 923189b53..8838bc468 100644 --- a/config/PrivilegeConfigMerge.xml +++ b/config/PrivilegeConfigMerge.xml @@ -17,7 +17,7 @@ - + diff --git a/src/main/java/ch/eitchnet/privilege/handler/DefaultPrivilegeHandler.java b/src/main/java/ch/eitchnet/privilege/handler/DefaultPrivilegeHandler.java index dcd77042e..818e3fb17 100644 --- a/src/main/java/ch/eitchnet/privilege/handler/DefaultPrivilegeHandler.java +++ b/src/main/java/ch/eitchnet/privilege/handler/DefaultPrivilegeHandler.java @@ -15,6 +15,11 @@ */ package ch.eitchnet.privilege.handler; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -31,6 +36,8 @@ import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.crypto.SecretKey; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +56,11 @@ import ch.eitchnet.privilege.model.internal.PrivilegeImpl; import ch.eitchnet.privilege.model.internal.Role; import ch.eitchnet.privilege.model.internal.User; import ch.eitchnet.privilege.policy.PrivilegePolicy; +import ch.eitchnet.privilege.xml.CertificateStubsDomWriter; +import ch.eitchnet.privilege.xml.CertificateStubsSaxReader; +import ch.eitchnet.privilege.xml.CertificateStubsSaxReader.CertificateStub; import ch.eitchnet.utils.collections.Tuple; +import ch.eitchnet.utils.helper.AesCryptoHelper; import ch.eitchnet.utils.helper.StringHelper; /** @@ -107,6 +118,21 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { */ private boolean autoPersistOnUserChangesData; + /** + * flag to define if sessions should be persisted + */ + private boolean persistSessions; + + /** + * Path to sessions file for persistence + */ + private File persistSessionsPath; + + /** + * Secret key + */ + private SecretKey secretKey; + private PrivilegeConflictResolution privilegeConflictResolution; @Override @@ -159,6 +185,16 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { return policyDef; } + @Override + public List getCertificates(Certificate certificate) { + + // validate user actually has this type of privilege + PrivilegeContext prvCtx = getPrivilegeContext(certificate); + prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_ACTION, PRIVILEGE_ACTION_GET_CERTIFICATES)); + + return this.privilegeContextMap.values().stream().map(p -> p.getCertificate()).collect(Collectors.toList()); + } + @Override public List getRoles(Certificate certificate) { @@ -958,8 +994,6 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { @Override public Certificate authenticate(String username, byte[] password) { - // create certificate - Certificate certificate; try { // username must be at least 2 characters in length if (username == null || username.length() < 2) { @@ -984,16 +1018,23 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { String sessionId = UUID.randomUUID().toString(); // create a new certificate, with details of the user - certificate = new Certificate(sessionId, new Date(), username, user.getFirstname(), user.getLastname(), - authToken, user.getLocale(), userRoles, new HashMap<>(user.getProperties())); + Certificate certificate = new Certificate(sessionId, username, user.getFirstname(), user.getLastname(), + user.getUserState(), authToken, new Date(), user.getLocale(), userRoles, + new HashMap<>(user.getProperties())); + certificate.setLastAccess(new Date()); PrivilegeContext privilegeContext = buildPrivilegeContext(certificate, user); this.privilegeContextMap.put(sessionId, privilegeContext); + persistSessions(); + // log DefaultPrivilegeHandler.logger .info(MessageFormat.format("User {0} authenticated: {1}", username, certificate)); //$NON-NLS-1$ + // return the certificate + return certificate; + } catch (RuntimeException e) { String msg = "User {0} Failed to authenticate: {1}"; //$NON-NLS-1$ msg = MessageFormat.format(msg, username, e.getMessage()); @@ -1002,9 +1043,88 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { } finally { clearPassword(password); } + } - // return the certificate - return certificate; + private boolean persistSessions() { + if (!this.persistSessions) + return false; + + List sessions = this.privilegeContextMap.values().stream().map(p -> p.getCertificate()) + .filter(c -> !c.getUserState().isSystem()).collect(Collectors.toList()); + + try (OutputStream outputStream = AesCryptoHelper.wrapEncrypt(this.secretKey, + new FileOutputStream(this.persistSessionsPath))) { + + CertificateStubsDomWriter writer = new CertificateStubsDomWriter(sessions, outputStream); + writer.write(); + outputStream.flush(); + + } catch (Exception e) { + throw new PrivilegeException("Failed to persist sessions!", e); + } + + return true; + } + + private boolean loadSessions() { + if (!this.persistSessions) { + logger.info("Persisteding of sessions not enabled, so not loading!."); + return false; + } + + if (!this.persistSessionsPath.exists()) { + logger.info("No persisted sessions exist to be loaded."); + return false; + } + + if (!this.persistSessionsPath.isFile()) + throw new PrivilegeException( + "Sessions data file is not a file but exists at " + this.persistSessionsPath.getAbsolutePath()); + + List certificateStubs; + try (InputStream inputStream = AesCryptoHelper.wrapDecrypt(this.secretKey, + new FileInputStream(this.persistSessionsPath))) { + + CertificateStubsSaxReader reader = new CertificateStubsSaxReader(inputStream); + certificateStubs = reader.read(); + + } catch (Exception e) { + throw new PrivilegeException("Failed to load sessions!", e); + } + + if (certificateStubs.isEmpty()) { + logger.info("No persisted sessions exist to be loaded."); + return false; + } + + for (CertificateStub certificateStub : certificateStubs) { + String username = certificateStub.getUsername(); + String sessionId = certificateStub.getSessionId(); + String authToken = certificateStub.getAuthToken(); + User user = this.persistenceHandler.getUser(username); + if (user == null) { + logger.error("Ignoring session data for missing user " + username); + continue; + } + + Set userRoles = user.getRoles(); + if (userRoles.isEmpty()) { + logger.error("Ignoring session data for user " + username + " which has not roles defined!"); + continue; + } + + // create a new certificate, with details of the user + Certificate certificate = new Certificate(sessionId, username, user.getFirstname(), user.getLastname(), + user.getUserState(), authToken, certificateStub.getLoginTime(), certificateStub.getLocale(), + userRoles, new HashMap<>(user.getProperties())); + certificate.setLastAccess(certificateStub.getLastAccess()); + + PrivilegeContext privilegeContext = buildPrivilegeContext(certificate, user); + this.privilegeContextMap.put(sessionId, privilegeContext); + } + + logger.info("Loaded " + this.privilegeContextMap.size() + " sessions."); + return true; } /** @@ -1146,6 +1266,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { // remove registration PrivilegeContext privilegeContext = this.privilegeContextMap.remove(certificate.getSessionId()); + // persist sessions + persistSessions(); + // return true if object was really removed boolean loggedOut = privilegeContext != null; if (loggedOut) @@ -1236,6 +1359,16 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { return this.persistenceHandler.persist(); } + @Override + public boolean persistSessions(Certificate certificate) { + + // validate who is doing this + PrivilegeContext prvCtx = getPrivilegeContext(certificate); + prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_ACTION, PRIVILEGE_ACTION_PERSIST_SESSIONS)); + + return persistSessions(); + } + @Override public boolean reload(Certificate certificate) { @@ -1273,8 +1406,29 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { this.encryptionHandler = encryptionHandler; this.persistenceHandler = persistenceHandler; + handleAutoPersistOnUserDataChange(parameterMap); + handlePersistSessionsParam(parameterMap); + handleConflictResolutionParam(parameterMap); + handleSecretParams(parameterMap); + + // validate policies on privileges of Roles + for (Role role : persistenceHandler.getAllRoles()) { + validatePolicies(role); + } + + // validate privilege conflicts + validatePrivilegeConflicts(); + + this.privilegeContextMap = Collections.synchronizedMap(new HashMap()); + + loadSessions(); + + this.initialized = true; + } + + private void handleAutoPersistOnUserDataChange(Map parameterMap) { String autoPersistS = parameterMap.get(PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA); - if (autoPersistS == null || autoPersistS.equals(Boolean.FALSE.toString())) { + if (StringHelper.isEmpty(autoPersistS) || autoPersistS.equals(Boolean.FALSE.toString())) { this.autoPersistOnUserChangesData = false; } else if (autoPersistS.equals(Boolean.TRUE.toString())) { this.autoPersistOnUserChangesData = true; @@ -1283,8 +1437,48 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { String msg = "Parameter {0} has illegal value {1}. Overriding with {2}"; //$NON-NLS-1$ msg = MessageFormat.format(msg, PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA, autoPersistS, Boolean.FALSE); logger.error(msg); + this.autoPersistOnUserChangesData = false; } + } + private void handlePersistSessionsParam(Map parameterMap) { + String persistSessionsS = parameterMap.get(PARAM_PERSIST_SESSIONS); + if (StringHelper.isEmpty(persistSessionsS) || persistSessionsS.equals(Boolean.FALSE.toString())) { + this.persistSessions = false; + } else if (persistSessionsS.equals(Boolean.TRUE.toString())) { + this.persistSessions = true; + + String persistSessionsPathS = parameterMap.get(PARAM_PERSIST_SESSIONS_PATH); + if (StringHelper.isEmpty(persistSessionsPathS)) { + String msg = "Parameter {0} has illegal value {1}."; //$NON-NLS-1$ + msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS_PATH, persistSessionsPathS); + throw new PrivilegeException(msg); + } + + File persistSessionsPath = new File(persistSessionsPathS); + if (!persistSessionsPath.getParentFile().isDirectory()) { + String msg = "Path for param {0} is invalid as parent does not exist or is not a directory. Value: {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS_PATH, persistSessionsPath.getAbsolutePath()); + throw new PrivilegeException(msg); + } + + if (persistSessionsPath.exists() && (!persistSessionsPath.isFile() || !persistSessionsPath.canWrite())) { + String msg = "Path for param {0} is invalid as file exists but is not a file or not writeable. Value: {1}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS_PATH, persistSessionsPath.getAbsolutePath()); + throw new PrivilegeException(msg); + } + + this.persistSessionsPath = persistSessionsPath; + logger.info("Enabling persistence of sessions."); //$NON-NLS-1$ + } else { + String msg = "Parameter {0} has illegal value {1}. Overriding with {2}"; //$NON-NLS-1$ + msg = MessageFormat.format(msg, PARAM_PERSIST_SESSIONS, persistSessionsS, Boolean.FALSE); + logger.error(msg); + this.persistSessions = false; + } + } + + private void handleConflictResolutionParam(Map parameterMap) { String privilegeConflictResolutionS = parameterMap.get(PARAM_PRIVILEGE_CONFLICT_RESOLUTION); if (privilegeConflictResolutionS == null) { this.privilegeConflictResolution = PrivilegeConflictResolution.STRICT; @@ -1301,17 +1495,28 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { } } logger.info("Privilege conflict resolution set to " + this.privilegeConflictResolution); //$NON-NLS-1$ + } - // validate policies on privileges of Roles - for (Role role : persistenceHandler.getAllRoles()) { - validatePolicies(role); + private void handleSecretParams(Map parameterMap) { + + if (!this.persistSessions) + return; + + String secretKeyS = parameterMap.get(PARAM_SECRET_KEY); + if (StringHelper.isEmpty(secretKeyS)) { + String msg = "Parameter {0} may not be empty if parameter {1} is enabled."; //$NON-NLS-1$ + msg = MessageFormat.format(msg, PARAM_SECRET_KEY, PARAM_PRIVILEGE_CONFLICT_RESOLUTION); + throw new PrivilegeException(msg); } - // validate privilege conflicts - validatePrivilegeConflicts(); + String secretSaltS = parameterMap.get(PARAM_SECRET_SALT); + if (StringHelper.isEmpty(secretSaltS)) { + String msg = "Parameter {0} may not be empty if parameter {1} is enabled."; //$NON-NLS-1$ + msg = MessageFormat.format(msg, PARAM_SECRET_SALT, PARAM_PRIVILEGE_CONFLICT_RESOLUTION); + throw new PrivilegeException(msg); + } - this.privilegeContextMap = Collections.synchronizedMap(new HashMap()); - this.initialized = true; + this.secretKey = AesCryptoHelper.buildSecret(secretKeyS.toCharArray(), secretSaltS.getBytes()); } private void validatePrivilegeConflicts() { @@ -1502,8 +1707,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler { String sessionId = UUID.randomUUID().toString(); // create a new certificate, with details of the user - Certificate systemUserCertificate = new Certificate(sessionId, new Date(), systemUsername, user.getFirstname(), - user.getLastname(), authToken, user.getLocale(), user.getRoles(), new HashMap<>(user.getProperties())); + Certificate systemUserCertificate = new Certificate(sessionId, systemUsername, user.getFirstname(), + user.getLastname(), user.getUserState(), authToken, new Date(), user.getLocale(), user.getRoles(), + new HashMap<>(user.getProperties())); + systemUserCertificate.setLastAccess(new Date()); // create and save a new privilege context PrivilegeContext privilegeContext = buildPrivilegeContext(systemUserCertificate, user); diff --git a/src/main/java/ch/eitchnet/privilege/handler/PrivilegeHandler.java b/src/main/java/ch/eitchnet/privilege/handler/PrivilegeHandler.java index b6e0f8856..cb612278d 100644 --- a/src/main/java/ch/eitchnet/privilege/handler/PrivilegeHandler.java +++ b/src/main/java/ch/eitchnet/privilege/handler/PrivilegeHandler.java @@ -55,6 +55,11 @@ public interface PrivilegeHandler { * allAllowed */ public static final String PRIVILEGE_ACTION_PERSIST = "Persist"; + /** + * For Privilege "PrivilegeAction" value required to be able to persist session if not exempted by + * allAllowed + */ + public static final String PRIVILEGE_ACTION_PERSIST_SESSIONS = "PersistSessions"; /** * For Privilege "PrivilegeAction" value required to be able to reload changes if not exempted by * allAllowed @@ -65,6 +70,14 @@ public interface PrivilegeHandler { * allAllowed */ public static final String PRIVILEGE_ACTION_GET_POLICIES = "GetPolicies"; + /** + * For Privilege "PrivilegeAction" value required to get a certificate if not allAllowed + */ + public static final String PRIVILEGE_ACTION_GET_CERTIFICATE = "GetCertificate"; + /** + * For Privilege "PrivilegeAction" value required to get all certificates if not allAllowed + */ + public static final String PRIVILEGE_ACTION_GET_CERTIFICATES = "GetCertificates"; /// @@ -131,11 +144,31 @@ public interface PrivilegeHandler { /// + /** + * configuration parameter to define a secret_key + */ + public static final String PARAM_SECRET_KEY = "secretKey"; //$NON-NLS-1$ + + /** + * configuration parameter to define a secret salt + */ + public static final String PARAM_SECRET_SALT = "secretSalt"; //$NON-NLS-1$ + /** * configuration parameter to define automatic persisting on password change */ public static final String PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA = "autoPersistOnUserChangesData"; //$NON-NLS-1$ + /** + * configuration parameter to define if sessions should be persisted + */ + public static final String PARAM_PERSIST_SESSIONS = "persistSessions"; //$NON-NLS-1$ + + /** + * configuration parameter to define where sessions are to be persisted + */ + public static final String PARAM_PERSIST_SESSIONS_PATH = "persistSessionsPath"; //$NON-NLS-1$ + /** * configuration parameter to define {@link PrivilegeConflictResolution} */ @@ -175,6 +208,16 @@ public interface PrivilegeHandler { */ public Map getPolicyDefs(Certificate certificate); + /** + * Returns the list of {@link Certificate Certificates} + * + * @param certificate + * the {@link Certificate} of the user which has the privilege to perform this action + * + * @return the list of {@link Certificate Certificates} + */ + public List getCertificates(Certificate certificate); + /** * Returns all {@link RoleRep RoleReps} * @@ -607,6 +650,19 @@ public interface PrivilegeHandler { */ public boolean persist(Certificate certificate) throws AccessDeniedException; + /** + * Persists all currently active sessions + * + * @param certificate + * the {@link Certificate} of the user which has the privilege to perform this action + * + * @return true if changes were persisted, false if not (i.e. not enabled) + * + * @throws AccessDeniedException + * if the users of the given certificate does not have the privilege to perform this action + */ + public boolean persistSessions(Certificate certificate) throws AccessDeniedException; + /** * Special method to perform work as a System user, meaning the given systemUsername corresponds to an account which * has the state {@link UserState#SYSTEM} and this user must have privilege to perform the concrete implementation diff --git a/src/main/java/ch/eitchnet/privilege/handler/XmlPersistenceHandler.java b/src/main/java/ch/eitchnet/privilege/handler/XmlPersistenceHandler.java index 0d31c1048..40e4b1dc4 100644 --- a/src/main/java/ch/eitchnet/privilege/handler/XmlPersistenceHandler.java +++ b/src/main/java/ch/eitchnet/privilege/handler/XmlPersistenceHandler.java @@ -104,8 +104,8 @@ public class XmlPersistenceHandler implements PersistenceHandler { @Override public void replaceUser(User user) { if (!this.userMap.containsKey(user.getUsername())) - throw new IllegalStateException(MessageFormat.format( - "The user {0} can not be replaced as it does not exiset!", user.getUsername())); + throw new IllegalStateException(MessageFormat + .format("The user {0} can not be replaced as it does not exiset!", user.getUsername())); this.userMap.put(user.getUsername(), user); this.userMapDirty = true; } @@ -121,8 +121,8 @@ public class XmlPersistenceHandler implements PersistenceHandler { @Override public void replaceRole(Role role) { if (!this.roleMap.containsKey(role.getName())) - throw new IllegalStateException(MessageFormat.format( - "The role {0} can not be replaced as it does not exist!", role.getName())); + throw new IllegalStateException( + MessageFormat.format("The role {0} can not be replaced as it does not exist!", role.getName())); this.roleMap.put(role.getName(), role); this.roleMapDirty = true; } diff --git a/src/main/java/ch/eitchnet/privilege/helper/XmlConstants.java b/src/main/java/ch/eitchnet/privilege/helper/XmlConstants.java index d4a0c1e9d..83ff72744 100644 --- a/src/main/java/ch/eitchnet/privilege/helper/XmlConstants.java +++ b/src/main/java/ch/eitchnet/privilege/helper/XmlConstants.java @@ -48,6 +48,11 @@ public class XmlConstants { */ 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_PERSISTENCE = "PersistenceHandler" : */ @@ -78,6 +83,16 @@ public class XmlConstants { */ 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" */ @@ -153,6 +168,16 @@ public class XmlConstants { */ public static final String XML_ATTR_CLASS = "class"; + /** + * XML_ATTR_LOGIN_TIME = "loginTime" : + */ + public static final String XML_ATTR_LOGIN_TIME = "loginTime"; + + /** + * XML_ATTR_LAST_ACCESS = "lastAccess" : + */ + public static final String XML_ATTR_LAST_ACCESS = "lastAccess"; + /** * XML_ATTR_NAME = "name" : */ @@ -173,11 +198,26 @@ public class XmlConstants { */ 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_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_LOCALE = "locale" : + */ + public static final String XML_ATTR_LOCALE = "locale"; + /** * XML_ATTR_PASSWORD = "password" : */ diff --git a/src/main/java/ch/eitchnet/privilege/model/Certificate.java b/src/main/java/ch/eitchnet/privilege/model/Certificate.java index 2255300ca..d170ab45b 100644 --- a/src/main/java/ch/eitchnet/privilege/model/Certificate.java +++ b/src/main/java/ch/eitchnet/privilege/model/Certificate.java @@ -18,7 +18,6 @@ package ch.eitchnet.privilege.model; import java.io.Serializable; import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -40,15 +39,15 @@ public final class Certificate implements Serializable { private static final long serialVersionUID = 1L; private final String sessionId; - private final Date loginTime; private final String username; private final String firstname; private final String lastname; + private final UserState userState; private final String authToken; + private final Date loginTime; private final Set userRoles; private final Map propertyMap; - private final Map sessionDataMap; private Locale locale; private Date lastAccess; @@ -79,8 +78,8 @@ public final class Certificate implements Serializable { * 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(String sessionId, Date loginTime, String username, String firstname, String lastname, - String authToken, Locale locale, Set userRoles, Map propertyMap) { + public Certificate(String sessionId, String username, String firstname, String lastname, UserState userState, + String authToken, Date loginTime, Locale locale, Set userRoles, Map propertyMap) { // validate arguments are not null if (StringHelper.isEmpty(sessionId)) { @@ -92,13 +91,17 @@ public final class Certificate implements Serializable { if (StringHelper.isEmpty(authToken)) { throw new PrivilegeException("authToken is null!"); //$NON-NLS-1$ } + if (userState == null) { + throw new PrivilegeException("userState is null!"); //$NON-NLS-1$ + } this.sessionId = sessionId; - this.loginTime = loginTime; this.username = username; this.firstname = firstname; this.lastname = lastname; + this.userState = userState; this.authToken = authToken; + this.loginTime = loginTime; // if no locale is given, set default if (locale == null) @@ -112,7 +115,6 @@ public final class Certificate implements Serializable { this.propertyMap = Collections.unmodifiableMap(propertyMap); this.userRoles = Collections.unmodifiableSet(userRoles); - this.sessionDataMap = new HashMap<>(); } /** @@ -157,15 +159,6 @@ public final class Certificate implements Serializable { return this.propertyMap.get(key); } - /** - * Returns a mutable {@link Map} for storing session relevant data - * - * @return the sessionDataMap - */ - public Map getSessionDataMap() { - return this.sessionDataMap; - } - /** * @return the locale */ @@ -209,6 +202,13 @@ public final class Certificate implements Serializable { return this.lastname; } + /** + * @return the userState + */ + public UserState getUserState() { + return userState; + } + /** * @return the loginTime */ diff --git a/src/main/java/ch/eitchnet/privilege/model/UserState.java b/src/main/java/ch/eitchnet/privilege/model/UserState.java index 2272002d3..b78e492ff 100644 --- a/src/main/java/ch/eitchnet/privilege/model/UserState.java +++ b/src/main/java/ch/eitchnet/privilege/model/UserState.java @@ -53,4 +53,8 @@ public enum UserState { * This is the System user state which is special and thus exempted from normal uses */ SYSTEM; + + public boolean isSystem() { + return this == UserState.SYSTEM; + } } diff --git a/src/main/java/ch/eitchnet/privilege/xml/CertificateStubsDomWriter.java b/src/main/java/ch/eitchnet/privilege/xml/CertificateStubsDomWriter.java new file mode 100644 index 000000000..7dab6d30e --- /dev/null +++ b/src/main/java/ch/eitchnet/privilege/xml/CertificateStubsDomWriter.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013 Robert von Burg + * + * 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 ch.eitchnet.privilege.xml; + +import java.io.OutputStream; +import java.util.List; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import ch.eitchnet.privilege.helper.XmlConstants; +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.utils.helper.XmlHelper; +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; + +/** + * @author Robert von Burg + */ +public class CertificateStubsDomWriter { + + private List certificates; + private OutputStream outputStream; + + public CertificateStubsDomWriter(List certificates, OutputStream outputStream) { + this.certificates = certificates; + this.outputStream = outputStream; + } + + public void write() { + + // create document root + Document doc = XmlHelper.createDocument(); + Element rootElement = doc.createElement(XmlConstants.XML_ROOT_CERTIFICATES); + doc.appendChild(rootElement); + + this.certificates.stream().sorted((c1, c2) -> c1.getSessionId().compareTo(c2.getSessionId())).forEach(cert -> { + + // create the certificate element + Element certElement = doc.createElement(XmlConstants.XML_CERTIFICATE); + rootElement.appendChild(certElement); + + // sessionId; + certElement.setAttribute(XmlConstants.XML_ATTR_SESSION_ID, cert.getSessionId()); + + // username; + certElement.setAttribute(XmlConstants.XML_ATTR_USERNAME, cert.getUsername()); + + // authToken; + certElement.setAttribute(XmlConstants.XML_ATTR_AUTH_TOKEN, cert.getAuthToken()); + + // locale; + certElement.setAttribute(XmlConstants.XML_ATTR_LOCALE, cert.getLocale().toString()); + + // loginTime; + certElement.setAttribute(XmlConstants.XML_ATTR_LOGIN_TIME, + ISO8601FormatFactory.getInstance().formatDate(cert.getLoginTime())); + + // lastAccess; + certElement.setAttribute(XmlConstants.XML_ATTR_LAST_ACCESS, + ISO8601FormatFactory.getInstance().formatDate(cert.getLastAccess())); + }); + + // write the container file to disk + XmlHelper.writeDocument(doc, this.outputStream); + } +} diff --git a/src/main/java/ch/eitchnet/privilege/xml/CertificateStubsSaxReader.java b/src/main/java/ch/eitchnet/privilege/xml/CertificateStubsSaxReader.java new file mode 100644 index 000000000..0cbfdb3c2 --- /dev/null +++ b/src/main/java/ch/eitchnet/privilege/xml/CertificateStubsSaxReader.java @@ -0,0 +1,114 @@ +/* + * Copyright 2013 Robert von Burg + * + * 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 ch.eitchnet.privilege.xml; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import ch.eitchnet.privilege.base.PrivilegeException; +import ch.eitchnet.privilege.helper.XmlConstants; +import ch.eitchnet.utils.dbc.DBC; +import ch.eitchnet.utils.helper.XmlHelper; +import ch.eitchnet.utils.iso8601.ISO8601FormatFactory; + +/** + * @author Robert von Burg + */ +public class CertificateStubsSaxReader extends DefaultHandler { + + private InputStream inputStream; + private List stubs; + + public CertificateStubsSaxReader(InputStream inputStream) { + this.inputStream = inputStream; + } + + public List read() { + this.stubs = new ArrayList<>(); + XmlHelper.parseDocument(this.inputStream, this); + return stubs; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + + switch (qName) { + case XmlConstants.XML_ROOT_CERTIFICATES: + break; + case XmlConstants.XML_CERTIFICATE: + + CertificateStub stub = new CertificateStub(); + stub.sessionId = attributes.getValue(XmlConstants.XML_ATTR_SESSION_ID); + stub.username = attributes.getValue(XmlConstants.XML_ATTR_USERNAME); + stub.authToken = attributes.getValue(XmlConstants.XML_ATTR_AUTH_TOKEN); + stub.locale = new Locale(attributes.getValue(XmlConstants.XML_ATTR_LOCALE)); + stub.loginTime = ISO8601FormatFactory.getInstance() + .parseDate(attributes.getValue(XmlConstants.XML_ATTR_LOGIN_TIME)); + stub.lastAccess = ISO8601FormatFactory.getInstance() + .parseDate(attributes.getValue(XmlConstants.XML_ATTR_LAST_ACCESS)); + + 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); + + this.stubs.add(stub); + break; + + default: + throw new PrivilegeException("Unhandled tag " + qName); + } + } + + public class CertificateStub { + private String sessionId; + private String username; + private String authToken; + private Locale locale; + private Date loginTime; + private Date lastAccess; + + public String getSessionId() { + return sessionId; + } + + public String getUsername() { + return username; + } + + public String getAuthToken() { + return authToken; + } + + public Locale getLocale() { + return locale; + } + + public Date getLoginTime() { + return loginTime; + } + + public Date getLastAccess() { + return lastAccess; + } + } +} diff --git a/src/main/java/ch/eitchnet/privilege/xml/PrivilegeConfigSaxReader.java b/src/main/java/ch/eitchnet/privilege/xml/PrivilegeConfigSaxReader.java index c1b31c5a2..660a4544d 100644 --- a/src/main/java/ch/eitchnet/privilege/xml/PrivilegeConfigSaxReader.java +++ b/src/main/java/ch/eitchnet/privilege/xml/PrivilegeConfigSaxReader.java @@ -32,8 +32,6 @@ import ch.eitchnet.privilege.model.internal.PrivilegeContainerModel; */ public class PrivilegeConfigSaxReader extends DefaultHandler { - // private static final Logger logger = LoggerFactory.getLogger(PrivilegeConfigSaxReader.class); - private Deque buildersStack = new ArrayDeque(); private PrivilegeContainerModel containerModel; @@ -109,7 +107,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler { private String currentElement; @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { if (qName.equals(XmlConstants.XML_CONTAINER)) { this.currentElement = qName; } else if (qName.equals(XmlConstants.XML_HANDLER_ENCRYPTION)) { @@ -147,7 +146,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler { private Map parameterMap = new HashMap(); @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { if (qName.equals(XmlConstants.XML_PARAMETER)) { String key = attributes.getValue(XmlConstants.XML_ATTR_NAME); String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE); @@ -168,7 +168,8 @@ public class PrivilegeConfigSaxReader extends DefaultHandler { // @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + public void startElement(String uri, String localName, String qName, Attributes attributes) + throws SAXException { if (qName.equals(XmlConstants.XML_POLICY)) { String policyName = attributes.getValue(XmlConstants.XML_ATTR_NAME); String policyClassName = attributes.getValue(XmlConstants.XML_ATTR_CLASS); diff --git a/src/test/java/ch/eitchnet/privilege/test/AbstractPrivilegeTest.java b/src/test/java/ch/eitchnet/privilege/test/AbstractPrivilegeTest.java new file mode 100644 index 000000000..b7b2e1c57 --- /dev/null +++ b/src/test/java/ch/eitchnet/privilege/test/AbstractPrivilegeTest.java @@ -0,0 +1,112 @@ +package ch.eitchnet.privilege.test; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.nio.file.Files; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.eitchnet.privilege.base.PrivilegeException; +import ch.eitchnet.privilege.handler.PrivilegeHandler; +import ch.eitchnet.privilege.helper.PrivilegeInitializationHelper; +import ch.eitchnet.privilege.model.Certificate; +import ch.eitchnet.privilege.model.PrivilegeContext; +import ch.eitchnet.utils.helper.FileHelper; + +public class AbstractPrivilegeTest { + + protected static final Logger logger = LoggerFactory.getLogger(AbstractPrivilegeTest.class); + + protected PrivilegeHandler privilegeHandler; + protected PrivilegeContext ctx; + + protected void login(String username, byte[] password) { + Certificate certificate = privilegeHandler.authenticate(username, password); + assertTrue("Certificate is null!", certificate != null); + PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate); + this.ctx = privilegeContext; + } + + protected void logout() { + if (this.ctx != null) { + try { + PrivilegeContext privilegeContext = this.ctx; + this.ctx = null; + privilegeHandler.invalidateSession(privilegeContext.getCertificate()); + } catch (PrivilegeException e) { + String msg = "There is no PrivilegeContext currently bound to the ThreadLocal!"; + if (!e.getMessage().equals(msg)) + throw e; + } + } + } + + protected static void prepareConfigs(String dst, String configFilename, String modelFilename) { + try { + String pwd = System.getProperty("user.dir"); + + File configPath = new File(pwd, "config"); + + File privilegeConfigFile = new File(configPath, configFilename); + File privilegeModelFile = new File(configPath, modelFilename); + + File targetPath = new File(pwd, "target/" + dst); + if (!targetPath.mkdirs()) + throw new RuntimeException("Could not create parent " + targetPath); + + File dstConfig = new File(targetPath, configFilename); + File dstModel = new File(targetPath, modelFilename); + + // write config + String config = new String(Files.readAllBytes(privilegeConfigFile.toPath()), "UTF-8"); + config = config.replace("${target}", dst); + Files.write(dstConfig.toPath(), config.getBytes("UTF-8")); + + // copy model + Files.copy(privilegeModelFile.toPath(), dstModel.toPath()); + + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException("Initialization failed", e); + } + } + + protected static void removeConfigs(String dst) { + try { + String pwd = System.getProperty("user.dir"); + File targetPath = new File(pwd, "target"); + targetPath = new File(targetPath, dst); + if (targetPath.exists() && !FileHelper.deleteFile(targetPath, true)) { + throw new RuntimeException( + "Tmp configuration still exists and can not be deleted at " + targetPath.getAbsolutePath()); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException("Initialization failed", e); + } + } + + protected static File getPrivilegeConfigFile(String dst, String configFilename) { + try { + String pwd = System.getProperty("user.dir"); + File targetPath = new File(pwd, "target"); + targetPath = new File(targetPath, dst); + return new File(targetPath, configFilename); + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException("Initialization failed", e); + } + } + + protected void initialize(String dst, String configFilename) { + try { + File privilegeConfigFile = getPrivilegeConfigFile(dst, configFilename); + this.privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile); + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException("Initialization failed", e); + } + } +} diff --git a/src/test/java/ch/eitchnet/privilege/test/PersistSessionsTest.java b/src/test/java/ch/eitchnet/privilege/test/PersistSessionsTest.java new file mode 100644 index 000000000..a032c980a --- /dev/null +++ b/src/test/java/ch/eitchnet/privilege/test/PersistSessionsTest.java @@ -0,0 +1,47 @@ +package ch.eitchnet.privilege.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PersistSessionsTest extends AbstractPrivilegeTest { + + @BeforeClass + public static void init() throws Exception { + removeConfigs(PersistSessionsTest.class.getSimpleName()); + prepareConfigs(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeModel.xml"); + } + + @AfterClass + public static void destroy() throws Exception { + removeConfigs(PersistSessionsTest.class.getSimpleName()); + } + + @Before + public void setup() throws Exception { + initialize(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml"); + } + + @Test + public void shouldPersistAndReloadSessions() { + + // assert no sessions file + File sessionsFile = new File("target/PersistSessionsTest/sessions.dat"); + assertFalse("Sessions File should no yet exist", sessionsFile.exists()); + + // login and assert sessions file was written + login("admin", "admin".getBytes()); + this.privilegeHandler.isCertificateValid(ctx.getCertificate()); + assertTrue("Sessions File should have been created!", sessionsFile.isFile()); + + // re-initialize and assert still logged in + initialize(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml"); + this.privilegeHandler.isCertificateValid(ctx.getCertificate()); + } +} diff --git a/src/test/java/ch/eitchnet/privilege/test/PrivilegeConflictMergeTest.java b/src/test/java/ch/eitchnet/privilege/test/PrivilegeConflictMergeTest.java index ab9a352e1..f78edbb23 100644 --- a/src/test/java/ch/eitchnet/privilege/test/PrivilegeConflictMergeTest.java +++ b/src/test/java/ch/eitchnet/privilege/test/PrivilegeConflictMergeTest.java @@ -19,120 +19,33 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.io.File; - import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ch.eitchnet.privilege.base.PrivilegeException; -import ch.eitchnet.privilege.handler.PrivilegeHandler; -import ch.eitchnet.privilege.helper.PrivilegeInitializationHelper; -import ch.eitchnet.privilege.model.Certificate; import ch.eitchnet.privilege.model.IPrivilege; -import ch.eitchnet.privilege.model.PrivilegeContext; -import ch.eitchnet.utils.helper.FileHelper; /** * @author Robert von Burg */ -public class PrivilegeConflictMergeTest { - - private static final Logger logger = LoggerFactory.getLogger(PrivilegeConflictMergeTest.class); +public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest { @BeforeClass public static void init() throws Exception { - try { - destroy(); - - // copy configuration to tmp - String pwd = System.getProperty("user.dir"); - - File origPrivilegeModelFile = new File(pwd + "/config/PrivilegeModelMerge.xml"); - File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModelMerge.xml"); - if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) { - throw new RuntimeException("Tmp configuration still exists and can not be deleted at " - + tmpPrivilegeModelFile.getAbsolutePath()); - } - - File parentFile = tmpPrivilegeModelFile.getParentFile(); - if (!parentFile.exists()) { - if (!parentFile.mkdirs()) - throw new RuntimeException("Could not create parent for tmp " + tmpPrivilegeModelFile); - } - - if (!FileHelper.copy(origPrivilegeModelFile, tmpPrivilegeModelFile, true)) - throw new RuntimeException("Failed to copy " + origPrivilegeModelFile + " to " + tmpPrivilegeModelFile); - - } catch (Exception e) { - logger.error(e.getMessage(), e); - - throw new RuntimeException("Initialization failed: " + e.getLocalizedMessage(), e); - } + removeConfigs(PrivilegeConflictMergeTest.class.getSimpleName()); + prepareConfigs(PrivilegeConflictMergeTest.class.getSimpleName(), "PrivilegeConfigMerge.xml", + "PrivilegeModelMerge.xml"); } @AfterClass public static void destroy() throws Exception { - - // delete temporary file - String pwd = System.getProperty("user.dir"); - - File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModelMerge.xml"); - if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) { - throw new RuntimeException("Tmp configuration still exists and can not be deleted at " - + tmpPrivilegeModelFile.getAbsolutePath()); - } - - // and temporary parent - File parentFile = tmpPrivilegeModelFile.getParentFile(); - if (parentFile.exists() && !parentFile.delete()) { - throw new RuntimeException("Could not remove temporary parent for tmp " + tmpPrivilegeModelFile); - } + removeConfigs(PrivilegeConflictMergeTest.class.getSimpleName()); } - private PrivilegeHandler privilegeHandler; - private PrivilegeContext ctx; - @Before public void setup() throws Exception { - try { - - String pwd = System.getProperty("user.dir"); - - File privilegeConfigFile = new File(pwd + "/config/PrivilegeConfigMerge.xml"); - - // initialize privilege - privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile); - - } catch (Exception e) { - logger.error(e.getMessage(), e); - - throw new RuntimeException("Setup failed: " + e.getLocalizedMessage(), e); - } - } - - private void login(String username, byte[] password) { - Certificate certificate = privilegeHandler.authenticate(username, password); - assertTrue("Certificate is null!", certificate != null); - PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate); - this.ctx = privilegeContext; - } - - private void logout() { - if (this.ctx != null) { - try { - PrivilegeContext privilegeContext = this.ctx; - this.ctx = null; - privilegeHandler.invalidateSession(privilegeContext.getCertificate()); - } catch (PrivilegeException e) { - String msg = "There is no PrivilegeContext currently bound to the ThreadLocal!"; - if (!e.getMessage().equals(msg)) - throw e; - } - } + initialize(PrivilegeConflictMergeTest.class.getSimpleName(), "PrivilegeConfigMerge.xml"); } @Test diff --git a/src/test/java/ch/eitchnet/privilege/test/PrivilegeTest.java b/src/test/java/ch/eitchnet/privilege/test/PrivilegeTest.java index 3d29e60d7..0cb60c782 100644 --- a/src/test/java/ch/eitchnet/privilege/test/PrivilegeTest.java +++ b/src/test/java/ch/eitchnet/privilege/test/PrivilegeTest.java @@ -17,10 +17,8 @@ package ch.eitchnet.privilege.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.io.File; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -42,10 +40,8 @@ import org.slf4j.LoggerFactory; import ch.eitchnet.privilege.base.AccessDeniedException; import ch.eitchnet.privilege.base.PrivilegeException; import ch.eitchnet.privilege.handler.PrivilegeHandler; -import ch.eitchnet.privilege.helper.PrivilegeInitializationHelper; import ch.eitchnet.privilege.i18n.PrivilegeMessages; import ch.eitchnet.privilege.model.Certificate; -import ch.eitchnet.privilege.model.PrivilegeContext; import ch.eitchnet.privilege.model.PrivilegeRep; import ch.eitchnet.privilege.model.Restrictable; import ch.eitchnet.privilege.model.RoleRep; @@ -55,7 +51,6 @@ import ch.eitchnet.privilege.test.model.TestRestrictable; import ch.eitchnet.privilege.test.model.TestSystemUserAction; import ch.eitchnet.privilege.test.model.TestSystemUserActionDeny; import ch.eitchnet.utils.helper.ArraysHelper; -import ch.eitchnet.utils.helper.FileHelper; /** * JUnit for performing Privilege tests. This JUnit is by no means complete, but checks the bare minimum.br /> @@ -65,7 +60,7 @@ import ch.eitchnet.utils.helper.FileHelper; * @author Robert von Burg */ @SuppressWarnings("nls") -public class PrivilegeTest { +public class PrivilegeTest extends AbstractPrivilegeTest { private static final String ROLE_PRIVILEGE_ADMIN = "PrivilegeAdmin"; private static final String PRIVILEGE_USER_ACCESS = "UserAccessPrivilege"; @@ -91,96 +86,20 @@ public class PrivilegeTest { @Rule public ExpectedException exception = ExpectedException.none(); - private static PrivilegeHandler privilegeHandler; - private PrivilegeContext ctx; - @BeforeClass public static void init() throws Exception { - try { - destroy(); - - // copy configuration to tmp - String pwd = System.getProperty("user.dir"); - - File origPrivilegeModelFile = new File(pwd + "/config/PrivilegeModel.xml"); - File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModel.xml"); - if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) { - throw new RuntimeException("Tmp configuration still exists and can not be deleted at " - + tmpPrivilegeModelFile.getAbsolutePath()); - } - - File parentFile = tmpPrivilegeModelFile.getParentFile(); - if (!parentFile.exists()) { - if (!parentFile.mkdirs()) - throw new RuntimeException("Could not create parent for tmp " + tmpPrivilegeModelFile); - } - - if (!FileHelper.copy(origPrivilegeModelFile, tmpPrivilegeModelFile, true)) - throw new RuntimeException("Failed to copy " + origPrivilegeModelFile + " to " + tmpPrivilegeModelFile); - - } catch (Exception e) { - logger.error(e.getMessage(), e); - - throw new RuntimeException("Initialization failed: " + e.getLocalizedMessage(), e); - } + removeConfigs(PrivilegeTest.class.getSimpleName()); + prepareConfigs(PrivilegeTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeModel.xml"); } @AfterClass public static void destroy() throws Exception { - - // delete temporary file - String pwd = System.getProperty("user.dir"); - - File tmpPrivilegeModelFile = new File(pwd + "/target/testPrivilege/PrivilegeModel.xml"); - if (tmpPrivilegeModelFile.exists() && !tmpPrivilegeModelFile.delete()) { - throw new RuntimeException("Tmp configuration still exists and can not be deleted at " - + tmpPrivilegeModelFile.getAbsolutePath()); - } - - // and temporary parent - File parentFile = tmpPrivilegeModelFile.getParentFile(); - if (parentFile.exists() && !parentFile.delete()) { - throw new RuntimeException("Could not remove temporary parent for tmp " + tmpPrivilegeModelFile); - } + removeConfigs(PrivilegeTest.class.getSimpleName()); } @Before public void setup() throws Exception { - try { - - String pwd = System.getProperty("user.dir"); - - File privilegeConfigFile = new File(pwd + "/config/PrivilegeConfig.xml"); - - // initialize privilege - privilegeHandler = PrivilegeInitializationHelper.initializeFromXml(privilegeConfigFile); - - } catch (Exception e) { - logger.error(e.getMessage(), e); - - throw new RuntimeException("Setup failed: " + e.getLocalizedMessage(), e); - } - } - - private void login(String username, byte[] password) { - Certificate certificate = privilegeHandler.authenticate(username, password); - assertTrue("Certificate is null!", certificate != null); - PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate); - this.ctx = privilegeContext; - } - - private void logout() { - if (this.ctx != null) { - try { - PrivilegeContext privilegeContext = this.ctx; - this.ctx = null; - privilegeHandler.invalidateSession(privilegeContext.getCertificate()); - } catch (PrivilegeException e) { - String msg = "There is no PrivilegeContext currently bound to the ThreadLocal!"; - if (!e.getMessage().equals(msg)) - throw e; - } - } + initialize(PrivilegeTest.class.getSimpleName(), "PrivilegeConfig.xml"); } @Test @@ -258,8 +177,8 @@ public class PrivilegeTest { @Test public void testPerformSystemRestrictableFailPrivilege() throws Exception { this.exception.expect(PrivilegeException.class); - this.exception - .expectMessage("User system_admin does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction"); + this.exception.expectMessage( + "User system_admin does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction"); try { // create the action to be performed as a system user TestSystemUserActionDeny action = new TestSystemUserActionDeny(); @@ -277,8 +196,8 @@ public class PrivilegeTest { @Test public void testPerformSystemRestrictableFailNoAdditionalPrivilege() throws Exception { this.exception.expect(PrivilegeException.class); - this.exception - .expectMessage("User system_admin2 does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction needed for Restrictable ch.eitchnet.privilege.test.model.TestSystemUserActionDeny"); + this.exception.expectMessage( + "User system_admin2 does not have the privilege ch.eitchnet.privilege.handler.SystemUserAction needed for Restrictable ch.eitchnet.privilege.test.model.TestSystemUserActionDeny"); try { // create the action to be performed as a system user TestSystemUserActionDeny action = new TestSystemUserActionDeny(); @@ -398,8 +317,8 @@ public class PrivilegeTest { Certificate certificate = this.ctx.getCertificate(); - UserRep selectorRep = new UserRep(null, null, null, null, null, new HashSet<>( - Arrays.asList("PrivilegeAdmin")), null, null); + UserRep selectorRep = new UserRep(null, null, null, null, null, + new HashSet<>(Arrays.asList("PrivilegeAdmin")), null, null); List users = privilegeHandler.queryUsers(certificate, selectorRep); assertEquals(1, users.size()); assertEquals(ADMIN, users.get(0).getUsername()); @@ -590,8 +509,8 @@ public class PrivilegeTest { PrivilegeRep passwordRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_PASSWORD, PRIVILEGE_USER_ACCESS, false, Collections.emptySet(), Collections.emptySet()); - PrivilegeRep localeRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_LOCALE, - PRIVILEGE_USER_ACCESS, false, Collections.emptySet(), Collections.emptySet()); + PrivilegeRep localeRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_LOCALE, PRIVILEGE_USER_ACCESS, + false, Collections.emptySet(), Collections.emptySet()); RoleRep roleRep = new RoleRep(ROLE_CHANGE_PW, Arrays.asList(passwordRep, localeRep)); @@ -818,8 +737,8 @@ public class PrivilegeTest { 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( - Arrays.asList(ROLE_MY)), null, new HashMap()); + UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW, + new HashSet(Arrays.asList(ROLE_MY)), null, new HashMap()); Certificate certificate = this.ctx.getCertificate(); privilegeHandler.addUser(certificate, userRep, null); logger.info("Added user " + BOB); diff --git a/src/test/java/ch/eitchnet/privilege/test/XmlTest.java b/src/test/java/ch/eitchnet/privilege/test/XmlTest.java index 5186dba16..4dfc029b3 100644 --- a/src/test/java/ch/eitchnet/privilege/test/XmlTest.java +++ b/src/test/java/ch/eitchnet/privilege/test/XmlTest.java @@ -120,7 +120,7 @@ public class XmlTest { assertNotNull(containerModel.getPersistenceHandlerClassName()); assertNotNull(containerModel.getPersistenceHandlerParameterMap()); - assertEquals(2, containerModel.getParameterMap().size()); + assertEquals(6, containerModel.getParameterMap().size()); assertEquals(3, containerModel.getPolicies().size()); assertEquals(1, containerModel.getEncryptionHandlerParameterMap().size()); assertEquals(2, containerModel.getPersistenceHandlerParameterMap().size());