[Major] major rewrite of the privilege validation.

Now the PrivilegeContext object is central and once the user logged in,
this object is bound to a ThreadLocal. From then there is no further
need to interact with the PrivilegeHandler - this allows for
authenticated users to get a remote copy of the PrivilegeContext so that
on a remote client, the user can check for permissions, without having
to do the round trip to the server.

A code review of this change would be good, but preliminary tests show
that it works. A test should now be implemented to check if getting a
remote copy also allows for authorization.
This commit is contained in:
Robert von Burg 2013-04-09 07:33:32 +02:00
parent 9261494667
commit 93022ba559
31 changed files with 1061 additions and 1004 deletions

55
config/Model.xml Normal file
View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<UsersAndRoles>
<Roles>
<Role name="PrivilegeAdmin" />
<Role name="AppUser">
<Privilege name="ch.eitchnet.privilege.test.model.TestRestrictable">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="system_admin_privileges">
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemUserAction">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemRestrictable">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>
<Users>
<User userId="1" username="admin" password="admin">
<Firstname>Application</Firstname>
<Surname>Administrator</Surname>
<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>
</User>
<User userId="2" username="system_admin" password="admin">
<Firstname>System User</Firstname>
<Surname>Administrator</Surname>
<State>SYSTEM</State>
<Locale>en_GB</Locale>
<Roles>
<Role>system_admin_privileges</Role>
</Roles>
</User>
</Users>
</UsersAndRoles>

View File

@ -39,7 +39,7 @@ along with Privilege. If not, see <http://www.gnu.org/licenses/>.
<PersistenceHandler class="ch.eitchnet.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="basePath" value="./target/test" />
<Parameter name="basePath" value="./target/testPrivilege" />
<Parameter name="modelXmlFile" value="PrivilegeModel.xml" />
</Parameters>
</PersistenceHandler>

View File

@ -1,26 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2010, 2011
Robert von Burg <eitch@eitchnet.ch>
This file is part of Privilege.
Privilege is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Privilege is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Privilege. If not, see <http://www.gnu.org/licenses/>.
-->
<!-- Copyright (c) 2010, 2011 Robert von Burg <eitch@eitchnet.ch> This file is part of Privilege. Privilege is free software:
you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any later version. Privilege is distributed in
the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of
the GNU Lesser General Public License along with Privilege. If not, see <http://www.gnu.org/licenses/>. -->
<UsersAndRoles>
<Users>
@ -39,7 +23,7 @@ along with Privilege. If not, see <http://www.gnu.org/licenses/>.
<Property name="organizationalUnit" value="Development" />
</Properties>
</User>
<User userId="2" username="system_admin" password="bb06d5caae150999027a8cb68956564d3ae0f3662aee02eea96253df3dc49bf7">
<Firstname>System User</Firstname>
<Surname>Administrator</Surname>
@ -48,7 +32,7 @@ along with Privilege. If not, see <http://www.gnu.org/licenses/>.
<Roles>
<Role>system_admin_privileges</Role>
</Roles>
</User>
</Users>
@ -58,20 +42,20 @@ along with Privilege. If not, see <http://www.gnu.org/licenses/>.
<Role name="PrivilegeAdmin" />
<Role name="AppUser">
<Privilege name="ch.eitchnet.privilege.test.model.TestRestrictable">
<Privilege name="ch.eitchnet.privilege.test.model.TestRestrictable" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="system_admin_privileges">
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemUserAction">
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemUserAction" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemRestrictable">
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemRestrictable" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
<Role name="restrictedRole">
<Privilege name="ch.eitchnet.privilege.test.model.TestSystemUserAction" policy="DefaultPrivilege">
<Allow>hello</Allow>

View File

@ -5,7 +5,7 @@
<groupId>ch.eitchnet</groupId>
<artifactId>ch.eitchnet.privilege</artifactId>
<packaging>jar</packaging>
<version>0.1.0-SNAPSHOT</version>
<version>0.2.0-SNAPSHOT</version>
<name>ch.eitchnet.privilege</name>
<url>https://github.com/eitch/ch.eitchnet.privilege</url>

View File

@ -19,6 +19,7 @@
*/
package ch.eitchnet.privilege.handler;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -35,14 +36,14 @@ import ch.eitchnet.privilege.base.AccessDeniedException;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.helper.ClassHelper;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.PrivilegeContext;
import ch.eitchnet.privilege.model.PrivilegeRep;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.model.RoleRep;
import ch.eitchnet.privilege.model.UserRep;
import ch.eitchnet.privilege.model.UserState;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.PrivilegeImpl;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.Session;
import ch.eitchnet.privilege.model.internal.User;
import ch.eitchnet.privilege.policy.PrivilegePolicy;
@ -72,7 +73,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
private static final String PARAM_AUTO_PERSIST_ON_PASSWORD_CHANGE = "autoPersistOnPasswordChange";
/**
* log4j logger
* slf4j logger
*/
protected static final Logger logger = LoggerFactory.getLogger(DefaultPrivilegeHandler.class);
@ -82,14 +83,9 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
private long lastSessionId;
/**
* This map stores certificates for system users as a cache
* Map keeping a reference to all active sessions
*/
private Map<String, Certificate> systemUserCertificateMap;
/**
* Map keeping a reference to all active sessions with their certificates
*/
private Map<String, CertificateSessionPair> sessionMap;
private Map<String, PrivilegeContext> privilegeContextMap;
/**
* Map of {@link PrivilegePolicy} classes
@ -132,41 +128,6 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
return user.asUserRep();
}
/**
* <p>
* This method instantiates a {@link PrivilegePolicy} object from the given policyName. The {@link PrivilegePolicy}
* is not stored in a database. The privilege name is a class name and is then used to instantiate a new
* {@link PrivilegePolicy} object
* </p>
*
* @param policyName
* the class name of the {@link PrivilegePolicy} object to return
*
* @return the {@link PrivilegePolicy} object
*
* @throws PrivilegeException
* if the {@link PrivilegePolicy} object for the given policy name could not be instantiated
*/
private PrivilegePolicy getPolicy(String policyName) {
// get the policies class
Class<PrivilegePolicy> policyClazz = this.policyMap.get(policyName);
if (policyClazz == null) {
return null;
}
// instantiate the policy
PrivilegePolicy policy;
try {
policy = ClassHelper.instantiateClass(policyClazz);
} catch (Exception e) {
throw new PrivilegeException("The class for the policy with the name " + policyName + " does not exist!"
+ policyName, e);
}
return policy;
}
@Override
public List<UserRep> queryUsers(UserRep selectorRep) {
@ -377,8 +338,15 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
}
// create new role with the additional privilege
Privilege newPrivilege = new Privilege(privilegeRep);
Map<String, Privilege> privilegeMap = new HashMap<String, Privilege>(role.getPrivilegeMap());
IPrivilege newPrivilege = new PrivilegeImpl(privilegeRep);
// copy existing privileges
Set<String> existingPrivilegeNames = role.getPrivilegeNames();
Map<String, IPrivilege> privilegeMap = new HashMap<String, IPrivilege>(existingPrivilegeNames.size() + 1);
for (String name : existingPrivilegeNames) {
IPrivilege privilege = role.getPrivilege(name);
privilegeMap.put(name, privilege);
}
// add new one
privilegeMap.put(newPrivilege.getName(), newPrivilege);
Role newRole = new Role(role.getName(), privilegeMap);
@ -438,9 +406,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
if (!role.hasPrivilege(privilegeName))
throw new PrivilegeException("Role " + roleName + " does not have Privilege " + privilegeName);
// create new set of privileges with out the to remove privilege
Map<String, Privilege> newPrivileges = new HashMap<String, Privilege>(role.getPrivilegeMap().size() - 1);
for (Privilege privilege : role.getPrivilegeMap().values()) {
// create new set of privileges with out the to removed privilege
Set<String> privilegeNames = role.getPrivilegeNames();
Map<String, IPrivilege> newPrivileges = new HashMap<String, IPrivilege>(privilegeNames.size() - 1);
for (String name : privilegeNames) {
IPrivilege privilege = role.getPrivilege(name);
if (!privilege.getName().equals(privilegeName))
newPrivileges.put(privilege.getName(), privilege);
}
@ -666,7 +636,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
+ " and can not login!");
// validate user has at least one role
if (user.getRoles().isEmpty()) {
Set<String> userRoles = user.getRoles();
if (userRoles.isEmpty()) {
throw new PrivilegeException("User " + username + " does not have any roles defined!");
}
@ -678,15 +649,14 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
String sessionId = nextSessionId();
// create a new certificate, with details of the user
certificate = new Certificate(sessionId, username, authToken, authPassword, user.getLocale(),
new HashMap<String, String>(user.getProperties()));
certificate = new Certificate(sessionId, System.currentTimeMillis(), username, authToken, authPassword,
user.getLocale(), new HashMap<String, String>(user.getProperties()));
// create and save a new session
Session session = new Session(sessionId, username, authToken, authPassword, System.currentTimeMillis());
this.sessionMap.put(sessionId, new CertificateSessionPair(session, certificate));
PrivilegeContext privilegeContext = buildPrivilegeContext(certificate, user);
this.privilegeContextMap.put(sessionId, privilegeContext);
// log
DefaultPrivilegeHandler.logger.info("User " + username + " authenticated: " + session);
DefaultPrivilegeHandler.logger.info("User " + username + " authenticated: " + certificate);
} catch (RuntimeException e) {
DefaultPrivilegeHandler.logger.error("User " + username + " Failed to authenticate: "
@ -700,6 +670,56 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
return certificate;
}
/**
* Builds a {@link PrivilegeContext} for the given {@link User} and its {@link Certificate}
*
* @param certificate
* @param user
*
* @return
*/
private PrivilegeContext buildPrivilegeContext(Certificate certificate, User user) {
Set<String> userRoles = user.getRoles();
Map<String, IPrivilege> privileges = new HashMap<String, IPrivilege>();
Map<String, PrivilegePolicy> policies = new HashMap<String, PrivilegePolicy>();
// get a cache of the privileges and policies for this user
for (String roleName : userRoles) {
Role role = this.persistenceHandler.getRole(roleName);
Set<String> privilegeNames = role.getPrivilegeNames();
for (String privilegeName : privilegeNames) {
// cache the privilege
if (privileges.containsKey(privilegeName))
continue;
IPrivilege privilege = role.getPrivilege(privilegeName);
if (privilege == null) {
throw new PrivilegeException(MessageFormat.format("The Privilege {0} does not exist for role {1}",
privilegeName, roleName));
}
privileges.put(privilegeName, privilege);
// cache the policy for the privilege
String policyName = privilege.getPolicy();
if (policies.containsKey(policyName))
continue;
PrivilegePolicy policy = getPolicy(policyName);
if (policy == null) {
throw new PrivilegeException(MessageFormat.format(
"The Policy {0} does not exist for Privilege {1}", policyName, privilegeName));
}
policies.put(policyName, policy);
}
}
UserRep userRep = user.asUserRep();
PrivilegeContext privilegeContext = new PrivilegeContext(userRep, certificate, privileges, policies);
return privilegeContext;
}
@Override
public boolean invalidateSession(Certificate certificate) {
@ -707,10 +727,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
isCertificateValid(certificate);
// remove registration
CertificateSessionPair certificateSessionPair = this.sessionMap.remove(certificate.getSessionId());
PrivilegeContext privilegeContext = this.privilegeContextMap.remove(certificate.getSessionId());
// return true if object was really removed
boolean loggedOut = certificateSessionPair != null;
boolean loggedOut = privilegeContext != null;
if (loggedOut)
DefaultPrivilegeHandler.logger.info("User " + certificate.getUsername() + " logged out.");
else
@ -718,136 +738,6 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
return loggedOut;
}
/**
* Checks if the action is allowed by iterating the roles of the certificates user and then delegating to
* {@link #actionAllowed(Role, Restrictable)}
*
* @throws AccessDeniedException
* if the {@link Certificate} is not for a currently logged in {@link User} or if the user may not
* perform the action defined by the {@link Restrictable} implementation
*
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#actionAllowed(ch.eitchnet.privilege.model.Certificate,
* ch.eitchnet.privilege.model.Restrictable)
*/
@Override
public void actionAllowed(Certificate certificate, Restrictable restrictable) {
// TODO What is better, validate from {@link Restrictable} to {@link User} or the opposite direction?
// first validate certificate
isCertificateValid(certificate);
// restrictable must not be null
if (restrictable == null)
throw new PrivilegeException("Restrictable may not be null!");
// get user object
User user = this.persistenceHandler.getUser(certificate.getUsername());
if (user == null) {
throw new PrivilegeException(
"Oh boy, how did this happen: No User in user map although the certificate is valid!");
}
String privilegeName = restrictable.getPrivilegeName();
// now iterate roles and validate on policies
for (String roleName : user.getRoles()) {
Role role = this.persistenceHandler.getRole(roleName);
if (role == null) {
DefaultPrivilegeHandler.logger.error("No role is defined with name " + roleName
+ " which is configured for user " + user);
continue;
}
// ignore if this role does not have the privilege
if (!role.hasPrivilege(privilegeName))
continue;
// if action is allowed, then break iteration as a privilege match has been made
if (actionAllowed(role, restrictable))
return;
}
throw new AccessDeniedException("User " + user.getUsername() + " does not have Privilege " + privilegeName
+ " needed for Restrictable " + restrictable.getClass().getName());
}
/**
* Checks if the {@link RoleRep} has access to the {@link Restrictable} by delegating to
* {@link PrivilegePolicy#actionAllowed(Role, Privilege, Restrictable)}
*
* @see ch.eitchnet.privilege.handler.PrivilegeHandler#actionAllowed(ch.eitchnet.privilege.model.RoleRep,
* ch.eitchnet.privilege.model.Restrictable)
*/
@Override
public void actionAllowed(RoleRep roleRep, Restrictable restrictable) {
// user and restrictable must not be null
if (roleRep == null)
throw new PrivilegeException("Role may not be null!");
else if (restrictable == null)
throw new PrivilegeException("Restrictable may not be null!");
// get role for the roleRep
Role role = this.persistenceHandler.getRole(roleRep.getName());
// validate that the role exists
if (role == null) {
throw new PrivilegeException("No Role exists with the name " + roleRep.getName());
}
// delegate to method with Role
actionAllowed(role, restrictable);
}
/**
* Checks if the {@link Role} has access to the {@link Restrictable} by delegating to
* {@link PrivilegePolicy#actionAllowed(Role, Privilege, Restrictable)}
*
* @param role
* the role which wants to perform the action
* @param restrictable
* the {@link Restrictable} which is to be checked for authorization
*/
private boolean actionAllowed(Role role, Restrictable restrictable) {
// validate PrivilegeName for this restrictable
String privilegeName = restrictable.getPrivilegeName();
if (privilegeName == null || privilegeName.length() < 3) {
throw new PrivilegeException(
"The PrivilegeName may not be shorter than 3 characters. Invalid Restrictable "
+ restrictable.getClass().getName());
}
// If the role does not have this privilege, then stop as another role might have this privilege
if (!role.hasPrivilege(privilegeName)) {
return false;
}
// get the privilege for this restrictable
Privilege privilege = role.getPrivilegeMap().get(privilegeName);
// check if all is allowed
if (privilege.isAllAllowed()) {
return true;
}
// otherwise delegate checking to the policy configured for this privilege
PrivilegePolicy policy = getPolicy(privilege.getPolicy());
if (policy == null) {
throw new PrivilegeException("PrivilegePolicy " + privilege.getPolicy() + " does not exist for Privilege "
+ privilegeName);
}
// delegate checking to privilege policy
policy.actionAllowed(role, privilege, restrictable);
// the policy must throw an exception if action not allowed,
// so return true if we arrive here
return true;
}
@Override
public void isCertificateValid(Certificate certificate) {
@ -856,24 +746,17 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
throw new PrivilegeException("Certificate may not be null!");
// first see if a session exists for this certificate
CertificateSessionPair certificateSessionPair = this.sessionMap.get(certificate.getSessionId());
if (certificateSessionPair == null)
PrivilegeContext privilegeContext = this.privilegeContextMap.get(certificate.getSessionId());
if (privilegeContext == null)
throw new AccessDeniedException("There is no session information for " + certificate.toString());
// validate certificate has not been tampered with
Certificate sessionCertificate = certificateSessionPair.certificate;
Certificate sessionCertificate = privilegeContext.getCertificate();
if (!sessionCertificate.equals(certificate))
throw new PrivilegeException("Received illegal certificate for session id " + certificate.getSessionId());
// TODO is validating authToken overkill since the two certificates have already been checked on equality?
// validate authToken from certificate using the sessions authPassword
String authToken = certificate.getAuthToken(certificateSessionPair.session.getAuthPassword());
if (authToken == null || !authToken.equals(certificateSessionPair.session.getAuthToken()))
throw new PrivilegeException("Received illegal certificate data for session id "
+ certificate.getSessionId());
// get user object
User user = this.persistenceHandler.getUser(certificateSessionPair.session.getUsername());
User user = this.persistenceHandler.getUser(privilegeContext.getUsername());
// if user exists, then certificate is valid
if (user == null) {
@ -884,6 +767,15 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
// everything is ok
}
@Override
public PrivilegeContext getPrivilegeContext(Certificate certificate) throws PrivilegeException {
// first validate certificate
isCertificateValid(certificate);
return this.privilegeContextMap.get(certificate.getSessionId());
}
@Override
public void validateIsPrivilegeAdmin(Certificate certificate) throws PrivilegeException {
@ -975,8 +867,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
}
this.lastSessionId = 0l;
this.sessionMap = Collections.synchronizedMap(new HashMap<String, CertificateSessionPair>());
this.systemUserCertificateMap = Collections.synchronizedMap(new HashMap<String, Certificate>());
this.privilegeContextMap = Collections.synchronizedMap(new HashMap<String, PrivilegeContext>());
this.initialized = true;
}
@ -987,7 +878,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
* the role for which the policies are to be checked
*/
private void validatePolicies(Role role) {
for (Privilege privilege : role.getPrivilegeMap().values()) {
for (String privilegeName : role.getPrivilegeNames()) {
IPrivilege privilege = role.getPrivilege(privilegeName);
String policy = privilege.getPolicy();
if (policy != null && !this.policyMap.containsKey(policy)) {
throw new PrivilegeException("Policy " + policy + " for Privilege " + privilege.getName()
@ -1003,37 +895,6 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
return Long.toString(++this.lastSessionId % Long.MAX_VALUE);
}
/**
* An internal class used to keep a record of sessions with the certificate
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
protected class CertificateSessionPair {
/**
* The {@link Session}
*/
public final Session session;
/**
* The {@link Certificate}
*/
public final Certificate certificate;
/**
* Creates a new {@link CertificateSessionPair} with the given session and certificate
*
* @param session
* the session
* @param certificate
* the certificate
*/
public CertificateSessionPair(Session session, Certificate certificate) {
this.session = session;
this.certificate = certificate;
}
}
/**
* Passwords should not be kept as strings, as string are immutable, this method thus clears the byte array so that
* the password is not in memory anymore
@ -1071,10 +932,10 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
checkPrivilege(actionClassname, systemUser);
// get certificate for this system user
Certificate systemUserCertificate = getSystemUserCertificate(systemUsername);
PrivilegeContext systemUserPrivilegeContext = getSystemUserPrivilegeContext(systemUsername);
// perform the action
action.execute(systemUserCertificate);
action.execute(systemUserPrivilegeContext);
}
/**
@ -1113,14 +974,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
*
* @return the {@link Certificate} for this system user
*/
private Certificate getSystemUserCertificate(String systemUsername) {
// see if a certificate has already been created for this system user
Certificate systemUserCertificate = this.systemUserCertificateMap.get(systemUsername);
if (systemUserCertificate != null)
return systemUserCertificate;
// otherwise log this system user in, by performing a slightly different authentication
private PrivilegeContext getSystemUserPrivilegeContext(String systemUsername) {
// we only work with hashed passwords
String passwordHash = this.encryptionHandler.convertToHash(systemUsername.getBytes());
@ -1156,17 +1010,51 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
String sessionId = nextSessionId();
// create a new certificate, with details of the user
systemUserCertificate = new Certificate(sessionId, systemUsername, authToken, authPassword, user.getLocale(),
new HashMap<String, String>(user.getProperties()));
Certificate systemUserCertificate = new Certificate(sessionId, System.currentTimeMillis(), systemUsername,
authToken, authPassword, user.getLocale(), new HashMap<String, String>(user.getProperties()));
// create and save a new session
Session session = new Session(sessionId, systemUsername, authToken, authPassword, System.currentTimeMillis());
this.sessionMap.put(sessionId, new CertificateSessionPair(session, systemUserCertificate));
// create and save a new privilege context
PrivilegeContext privilegeContext = buildPrivilegeContext(systemUserCertificate, user);
// log
DefaultPrivilegeHandler.logger.info("The system user " + systemUsername + " is logged in with session "
+ session);
+ systemUserCertificate);
return systemUserCertificate;
return privilegeContext;
}
/**
* <p>
* This method instantiates a {@link PrivilegePolicy} object from the given policyName. The {@link PrivilegePolicy}
* is not stored in a database. The privilege name is a class name and is then used to instantiate a new
* {@link PrivilegePolicy} object
* </p>
*
* @param policyName
* the class name of the {@link PrivilegePolicy} object to return
*
* @return the {@link PrivilegePolicy} object
*
* @throws PrivilegeException
* if the {@link PrivilegePolicy} object for the given policy name could not be instantiated
*/
private PrivilegePolicy getPolicy(String policyName) {
// get the policies class
Class<PrivilegePolicy> policyClazz = this.policyMap.get(policyName);
if (policyClazz == null) {
return null;
}
// instantiate the policy
PrivilegePolicy policy;
try {
policy = ClassHelper.instantiateClass(policyClazz);
} catch (Exception e) {
throw new PrivilegeException("The class for the policy with the name " + policyName + " does not exist!"
+ policyName, e);
}
return policy;
}
}

View File

@ -22,8 +22,8 @@ package ch.eitchnet.privilege.handler;
import java.util.List;
import java.util.Map;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.User;
import ch.eitchnet.privilege.policy.PrivilegePolicy;
@ -37,7 +37,7 @@ import ch.eitchnet.privilege.policy.PrivilegePolicy;
* <p>
* The {@link PersistenceHandler} also serves the special {@link PrivilegePolicy} objects. These policies are special
* objects which implement an algorithm to define if an action is allowed on a {@link Restrictable} by a {@link Role}
* and {@link Privilege}
* and {@link IPrivilege}
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>

View File

@ -25,14 +25,13 @@ import java.util.Locale;
import ch.eitchnet.privilege.base.AccessDeniedException;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.PrivilegeContext;
import ch.eitchnet.privilege.model.PrivilegeRep;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.model.RoleRep;
import ch.eitchnet.privilege.model.UserRep;
import ch.eitchnet.privilege.model.UserState;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.Session;
import ch.eitchnet.privilege.model.internal.User;
/**
@ -222,7 +221,7 @@ public interface PrivilegeHandler {
* @param roleName
* the roleName of the {@link Role} to which the privilege should be added
* @param privilegeRep
* the representation of the {@link Privilege} which should be added to the {@link Role}
* the representation of the {@link IPrivilege} which should be added to the {@link Role}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
@ -335,49 +334,15 @@ public interface PrivilegeHandler {
public Certificate authenticate(String username, byte[] password) throws AccessDeniedException;
/**
* Invalidates the {@link Session} for the given {@link Certificate}, effectively logging out the user who was
* authenticated with the credentials associated to the given {@link Certificate}
* Invalidates the session for the given {@link Certificate}, effectively logging out the user who was authenticated
* with the credentials associated to the given {@link Certificate}
*
* @param certificate
* the {@link Certificate} for which the {@link Session} is to be invalidated
* @return true if the {@link Session} was still valid and is now invalidated, false otherwise
* the {@link Certificate} for which the session is to be invalidated
* @return true if the session was still valid and is now invalidated, false otherwise
*/
public boolean invalidateSession(Certificate certificate);
/**
* Checks if the {@link User} registered to the given {@link Certificate} is allowed to access the
* {@link Restrictable}
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param restrictable
* the {@link Restrictable} to which the user wants access
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action defined by the {@link Restrictable}
* implementation
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public void actionAllowed(Certificate certificate, Restrictable restrictable) throws AccessDeniedException,
PrivilegeException;
/**
* Checks if the {@link RoleRep} is allowed to access the {@link Restrictable}
*
* @param roleRep
* the {@link RoleRep} for which access to the {@link Restrictable} is to be checked
* @param restrictable
* the {@link Restrictable} to which access is to be checked
*
* @throws PrivilegeException
* if the {@link Role} does not exist
* @throws AccessDeniedException
* if the role may not perform the action defined by the {@link Restrictable} implementation
*/
public void actionAllowed(RoleRep roleRep, Restrictable restrictable) throws PrivilegeException,
AccessDeniedException;
/**
* Checks if the given {@link Certificate} is valid. This means that the certificate is for a valid session and that
* the user exists for the certificate. This method checks if the {@link Certificate} has been tampered with
@ -390,6 +355,20 @@ public interface PrivilegeHandler {
*/
public void isCertificateValid(Certificate certificate) throws PrivilegeException;
/**
* Returns the {@link PrivilegeContext} for the given {@link Certificate}. The {@link PrivilegeContext} is an
* encapsulated state of a user's privileges so that for the duration of a user's call, the user can perform their
* actions and do not need to access the {@link PrivilegeHandler} anymore
*
* @param certificate
* a valid {@link Certificate} for which a {@link PrivilegeContext} is to be returned
* @return the {@link PrivilegeContext} for the given {@link Certificate}
*
* @throws PrivilegeException
* if there is a configuration error or the {@link Certificate} is invalid
*/
public PrivilegeContext getPrivilegeContext(Certificate certificate) throws PrivilegeException;
/**
* <p>
* Validates if this {@link Certificate} is for a {@link ch.eitchnet.privilege.model.internal.User} with

View File

@ -20,6 +20,7 @@
package ch.eitchnet.privilege.handler;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.PrivilegeContext;
/**
* With this interface system actions, which are to be performed in an automated fashion, i.e. by cron jobs, can be
@ -34,8 +35,11 @@ public interface SystemUserAction {
* This method will be called by the {@link PrivilegeHandler} when an authorized {@link Certificate} has been
* generated to allow this action to properly validate its execution
*
* @param certificate
* the {@link Certificate} which was generated for a valid system user
* TODO: I'm not really happy with this... we might want to pass the certificate and then force the action to
* validate it to get the {@link PrivilegeContext} - we don't want the {@link PrivilegeContext} to live forever...
*
* @param privilegeContext
* the {@link PrivilegeContext} which was generated for a valid system user
*/
public void execute(Certificate certificate);
public void execute(PrivilegeContext privilegeContext);
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2012
*
* This file is part of ???????????????
*
* ?????????????? is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Privilege is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ????????????????. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.eitchnet.privilege.helper;
import ch.eitchnet.privilege.model.Certificate;
/**
* This {@link ThreadLocal} holds a reference to the {@link Certificate} which allows any code segment to perform
* further authorization before executing
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class CertificateThreadLocal extends ThreadLocal<Certificate> {
private static final CertificateThreadLocal instance;
static {
instance = new CertificateThreadLocal();
}
public static CertificateThreadLocal getInstance() {
return CertificateThreadLocal.instance;
}
public static Certificate getCertificate() {
return CertificateThreadLocal.instance.get();
}
public static void setCertificate(Certificate certificate) {
CertificateThreadLocal.instance.set(certificate);
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2012, Robert von Burg
*
* All rights reserved.
*
* This file is part of the XXX.
*
* XXX is free software: you can redistribute
* it and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* XXX is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XXX. If not, see
* <http://www.gnu.org/licenses/>.
*/
package ch.eitchnet.privilege.i18n;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*
*/
public class PrivilegeMessages {
private static final String BUNDLE_NAME = "ch.eitchnet.privilege.i18n.PrivilegeMessages"; //$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
private PrivilegeMessages() {
}
public static String getString(String key) {
try {
return RESOURCE_BUNDLE.getString(key);
} catch (MissingResourceException e) {
return '!' + key + '!';
}
}
}

View File

@ -0,0 +1,6 @@
Privilege.accessdenied.noprivilege=User {0} does not have Privilege {1} needed for Restrictable {2}
Privilege.illegalArgument.nonstring=\ {1} has returned a non-string privilege value\!
Privilege.illegalArgument.privilegeNameMismatch=The passed privilege has the name {0} but the restrictable is referencing privilege {1}
Privilege.privilegeNameEmpty=The PrivilegeName for the Restrictable is null or empty: {0}
Privilege.privilegeNull=Privilege may not be null\!
Privilege.restrictableNull=Restrictable may not be null\!

View File

@ -25,7 +25,7 @@ import java.util.Map;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.handler.PrivilegeHandler;
import ch.eitchnet.privilege.model.internal.Session;
import ch.eitchnet.utils.helper.StringHelper;
/**
* The {@link Certificate} is the object a client keeps when accessing a Privilege enabled system. This object is the
@ -39,6 +39,7 @@ public final class Certificate implements Serializable {
private static final long serialVersionUID = 1L;
private final String sessionId;
private final long loginTime;
private final String username;
private final String authToken;
private final String authPassword;
@ -72,15 +73,25 @@ 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, String username, String authToken, String authPassword, Locale locale,
Map<String, String> propertyMap) {
public Certificate(String sessionId, long loginTime, String username, String authToken, String authPassword,
Locale locale, Map<String, String> propertyMap) {
// validate arguments are not null
if (sessionId == null || username == null || authToken == null || authPassword == null) {
throw new PrivilegeException("One of the arguments is null!");
if (StringHelper.isEmpty(sessionId)) {
throw new PrivilegeException("sessionId is null!");
}
if (StringHelper.isEmpty(username)) {
throw new PrivilegeException("username is null!");
}
if (StringHelper.isEmpty(authToken)) {
throw new PrivilegeException("authToken is null!");
}
if (StringHelper.isEmpty(authPassword)) {
throw new PrivilegeException("authPassword is null!");
}
this.sessionId = sessionId;
this.loginTime = loginTime;
this.username = username;
this.authToken = authToken;
this.authPassword = authPassword;
@ -130,6 +141,13 @@ public final class Certificate implements Serializable {
return this.username;
}
/**
* @return the loginTime
*/
public long getLoginTime() {
return this.loginTime;
}
/**
* Returns the authToken if the given authPassword is correct, null otherwise
*

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2012, Robert von Burg
*
* All rights reserved.
*
* This file is part of the XXX.
*
* XXX is free software: you can redistribute
* it and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* XXX is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XXX. If not, see
* <http://www.gnu.org/licenses/>.
*/
package ch.eitchnet.privilege.model;
import java.util.Set;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.policy.PrivilegePolicy;
/**
* <p>
* {@link IPrivilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it
* which defines the privileges a logged in user with that role has. If the {@link IPrivilege} has a
* {@link PrivilegePolicy} defined, then that policy will be used for finer granularity and with the deny and allow
* lists configured which is used to evaluate if privilege is granted to a {@link Restrictable}
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*
*/
public interface IPrivilege {
/**
* @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
*/
public abstract PrivilegeRep asPrivilegeRep();
/**
* @return the name
*/
public abstract String getName();
/**
* @return the policy
*/
public abstract String getPolicy();
/**
* @return the allAllowed
*/
public abstract boolean isAllAllowed();
/**
* @return the allowList
*/
public abstract Set<String> getAllowList();
/**
* @return the denyList
*/
public abstract Set<String> getDenyList();
/**
* @return true if there are values in the allow list
*/
public abstract boolean hasAllowed();
/**
* @return if the value is in the allow list
*/
public abstract boolean isAllowed(String value);
/**
* @return true if there are values in the deny list
*/
public abstract boolean hasDenied();
/**
* @return true if the value is in the deny list
*/
public abstract boolean isDenied(String value);
}

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2012, Robert von Burg
*
* All rights reserved.
*
* This file is part of the XXX.
*
* XXX is free software: you can redistribute
* it and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* XXX is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XXX. If not, see
* <http://www.gnu.org/licenses/>.
*/
package ch.eitchnet.privilege.model;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import ch.eitchnet.privilege.base.AccessDeniedException;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.i18n.PrivilegeMessages;
import ch.eitchnet.privilege.policy.PrivilegePolicy;
/**
* This context gives access to a logged in user's privilege data e.g. the {@link UserRep}, {@link Certificate} and the
* user's list of {@link PrivilegeRep}
*
* <p>
* Note: This is an internal object which is not to be serialized to clients
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PrivilegeContext {
//
// object state
//
private UserRep userRep;
private Certificate certificate;
private Map<String, IPrivilege> privileges;
private Map<String, PrivilegePolicy> policies;
public PrivilegeContext(UserRep userRep, Certificate certificate, Map<String, IPrivilege> privileges,
Map<String, PrivilegePolicy> policies) {
this.userRep = userRep;
this.certificate = certificate;
this.privileges = Collections.unmodifiableMap(new HashMap<String, IPrivilege>(privileges));
this.policies = Collections.unmodifiableMap(new HashMap<String, PrivilegePolicy>(policies));
}
public UserRep getUserRep() {
return this.userRep;
}
public Certificate getCertificate() {
return this.certificate;
}
public String getUsername() {
return this.userRep.getUsername();
}
public Set<String> getPrivilegeNames() {
return this.privileges.keySet();
}
//
// business logic
//
/**
* Validates if the user for this context has the privilege to access to the given {@link Restrictable}. If the user
* has the privilege, then this method returns with no exception and void, if the user does not have the privilege,
* then a {@link AccessDeniedException} is thrown.
*
* @param restrictable
* the {@link Restrictable} which the user wants to access
*
* @throws AccessDeniedException
* if the user does not have access
* @throws PrivilegeException
* if there is an internal error due to wrongly configured privileges or programming errors
*/
public void validateAction(Restrictable restrictable) throws AccessDeniedException, PrivilegeException {
// the the privilege for the restrictable
String privilegeName = restrictable.getPrivilegeName();
IPrivilege privilege = this.privileges.get(privilegeName);
if (privilege == null) {
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.accessdenied.noprivilege"),
getUsername(), privilegeName, restrictable.getClass().getName());
throw new AccessDeniedException(msg);
}
// get the policy referenced by the restrictable
String policyName = privilege.getPolicy();
PrivilegePolicy policy = this.policies.get(policyName);
if (policy == null) {
String msg = "The PrivilegePolicy {0} does not exist on the PrivilegeContext!";
throw new PrivilegeException(MessageFormat.format(msg, policyName));
}
// delegate to the policy
policy.validateAction(privilege, restrictable);
}
//
// ThreadLocal binding
//
private static final ThreadLocal<PrivilegeContext> threadLocal = new ThreadLocal<PrivilegeContext>();
/**
* Returns the currently {@link ThreadLocal} bound {@link PrivilegeContext} or throws a {@link PrivilegeException}
* if none is set
*
* @return the currently {@link ThreadLocal} bound {@link PrivilegeContext} or throws a {@link PrivilegeException}
* if none is set
*
* @throws PrivilegeException
* if no {@link PrivilegeContext} is set
*/
public static PrivilegeContext get() throws PrivilegeException {
PrivilegeContext privilegeContext = PrivilegeContext.threadLocal.get();
if (privilegeContext == null) {
throw new PrivilegeException("There is no PrivilegeContext currently bound to the ThreadLocal!");
}
return privilegeContext;
}
/**
* Bind a {@link PrivilegeContext} to the {@link ThreadLocal} or throws a {@link PrivilegeException} if one is
* already bound
*
* @param privilegeContext
* the {@link PrivilegeContext} to bind
*
* @throws PrivilegeException
* if e {@link PrivilegeContext} is already bound
*/
public static void set(PrivilegeContext privilegeContext) throws PrivilegeException {
PrivilegeContext currentContext = PrivilegeContext.threadLocal.get();
if (privilegeContext != null && currentContext != null) {
throw new PrivilegeException("There already is a PrivilegeContext bound to the ThreadLocal!");
}
PrivilegeContext.threadLocal.set(privilegeContext);
}
}

View File

@ -24,14 +24,14 @@ import java.util.Set;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.handler.PrivilegeHandler;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.policy.PrivilegePolicy;
import ch.eitchnet.utils.helper.StringHelper;
/**
* To keep certain details of the {@link Privilege} itself hidden from remote clients and make sure instances are only
* To keep certain details of the {@link IPrivilege} itself hidden from remote clients and make sure instances are only
* edited by users with the correct privilege, this representational version is allowed to be viewed by remote clients
* and simply wraps all public data from the {@link Privilege}
* and simply wraps all public data from the {@link IPrivilege}
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -53,12 +53,12 @@ public class PrivilegeRep implements Serializable {
* @param policy
* the {@link PrivilegePolicy} configured to evaluate if the privilege is granted
* @param allAllowed
* a boolean defining if a {@link Role} with this {@link Privilege} has unrestricted access to a
* a boolean defining if a {@link Role} with this {@link IPrivilege} has unrestricted access to a
* {@link Restrictable}
* @param denyList
* a list of deny rules for this {@link Privilege}
* a list of deny rules for this {@link IPrivilege}
* @param allowList
* a list of allow rules for this {@link Privilege}
* a list of allow rules for this {@link IPrivilege}
*/
public PrivilegeRep(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
this.name = name;
@ -66,6 +66,29 @@ public class PrivilegeRep implements Serializable {
this.allAllowed = allAllowed;
this.denyList = denyList;
this.allowList = allowList;
validate();
}
/**
* Validates that all required fields are set
*/
public void validate() {
if (StringHelper.isEmpty(this.name)) {
throw new PrivilegeException("No name defined!");
}
if (StringHelper.isEmpty(this.policy)) {
throw new PrivilegeException("policy is null!");
}
if (this.denyList == null) {
throw new PrivilegeException("denyList is null");
}
if (this.allowList == null) {
throw new PrivilegeException("allowList is null");
}
}
/**
@ -143,48 +166,6 @@ public class PrivilegeRep implements Serializable {
this.allowList = allowList;
}
/**
* <p>
* Validates this {@link PrivilegeRep} so that a {@link Privilege} object can later be created from it
* </p>
*
* TODO write comment on how validation is done
*/
public void validate() {
if (this.name == null || this.name.isEmpty()) {
throw new PrivilegeException("No name defined!");
}
// if not all allowed, then validate that deny and allow lists are defined
if (this.allAllowed) {
// all allowed means no policy will be used
if (this.policy != null && !this.policy.isEmpty()) {
throw new PrivilegeException("All is allowed, so Policy may not be set!");
}
if (this.denyList != null && !this.denyList.isEmpty())
throw new PrivilegeException("All is allowed, so deny list must be null");
if (this.allowList != null && !this.allowList.isEmpty())
throw new PrivilegeException("All is allowed, so allow list must be null");
} else {
// not all allowed, so policy must be set
if (this.policy == null || this.policy.isEmpty()) {
throw new PrivilegeException("All is not allowed, so Policy must be defined!");
}
if (this.denyList == null) {
throw new PrivilegeException("All is not allowed, so deny list must be set, even if empty");
}
if (this.allowList == null) {
throw new PrivilegeException("All is not allowed, so allow list must be set, even if empty");
}
}
}
/**
* Returns a string representation of this object displaying its concrete type and its values
*

View File

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

View File

@ -22,7 +22,9 @@ package ch.eitchnet.privilege.model;
import java.io.Serializable;
import java.util.Map;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.utils.helper.StringHelper;
/**
* To keep certain details of the {@link Role} itself hidden from remote clients and make sure instances are only edited
@ -47,8 +49,19 @@ public class RoleRep implements Serializable {
* the map of privileges granted to this role
*/
public RoleRep(String name, Map<String, PrivilegeRep> privilegeMap) {
this.name = name;
this.privilegeMap = privilegeMap;
validate();
}
/**
* validates that all required fields are set
*/
public void validate() {
if (StringHelper.isEmpty(this.name))
throw new PrivilegeException("name is null");
}
/**

View File

@ -24,8 +24,10 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.User;
import ch.eitchnet.utils.helper.StringHelper;
/**
* To keep certain details of the {@link User} itself hidden from remote clients and make sure instances are only edited
@ -77,6 +79,32 @@ public class UserRep implements Serializable {
this.roles = roles;
this.locale = locale;
this.propertyMap = propertyMap;
validate();
}
/**
* Validates that all required fields are set
*/
public void validate() {
if (StringHelper.isEmpty(this.userId))
throw new PrivilegeException("userId is null or empty");
if (StringHelper.isEmpty(this.username))
throw new PrivilegeException("username is null or empty");
if (StringHelper.isEmpty(this.firstname))
throw new PrivilegeException("firstname is null or empty");
if (StringHelper.isEmpty(this.surname))
throw new PrivilegeException("surname is null or empty");
if (this.userState == null)
throw new PrivilegeException("userState is null");
if (this.roles == null)
throw new PrivilegeException("roles is null");
}
/**

View File

@ -32,6 +32,10 @@ import ch.eitchnet.privilege.policy.PrivilegePolicy;
* This class is used during XML parsing to hold the model before it is properly validated and made accessible through
* the {@link PrivilegeHandler}
*
* <p>
* Note: This is an internal object which is not to be serialized or passed to clients
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class PrivilegeContainerModel {

View File

@ -25,20 +25,22 @@ import java.util.Set;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.handler.PrivilegeHandler;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.PrivilegeRep;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.policy.PrivilegePolicy;
import ch.eitchnet.utils.helper.StringHelper;
/**
* <p>
* {@link Privilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it which
* defines the privileges a logged in user with that role has. If the {@link Privilege} has a {@link PrivilegePolicy}
* defined, then that policy will be used for finer granularity and with the deny and allow lists configured which is
* used to evaluate if privilege is granted to a {@link Restrictable}
* {@link IPrivilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it
* which defines the privileges a logged in user with that role has. If the {@link IPrivilege} has a
* {@link PrivilegePolicy} defined, then that policy will be used for finer granularity and with the deny and allow
* lists configured which is used to evaluate if privilege is granted to a {@link Restrictable}
* </p>
*
* <p>
* {@link Privilege}s have allow and deny rules which the configured {@link PrivilegeHandler} uses to
* {@link IPrivilege}s have allow and deny rules which the configured {@link PrivilegeHandler} uses to
* </p>
*
* <p>
@ -48,7 +50,7 @@ import ch.eitchnet.privilege.policy.PrivilegePolicy;
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public final class Privilege {
public final class PrivilegeImpl implements IPrivilege {
private final String name;
private final String policy;
@ -65,66 +67,59 @@ public final class Privilege {
* the {@link PrivilegePolicy} configured to evaluate if the privilege is granted. If null, then
* privilege is granted
* @param allAllowed
* a boolean defining if a {@link Role} with this {@link Privilege} has unrestricted access to a
* a boolean defining if a {@link Role} with this {@link PrivilegeImpl} has unrestricted access to a
* {@link Restrictable} in which case the deny and allow lists are ignored and can be null
* @param denyList
* a list of deny rules for this {@link Privilege}, can be null if all allowed
* a list of deny rules for this {@link PrivilegeImpl}, can be null if all allowed
* @param allowList
* a list of allow rules for this {@link Privilege}, can be null if all allowed
* a list of allow rules for this {@link PrivilegeImpl}, can be null if all allowed
*/
public Privilege(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
public PrivilegeImpl(String name, String policy, boolean allAllowed, Set<String> denyList, Set<String> allowList) {
if (name == null || name.isEmpty()) {
if (StringHelper.isEmpty(name)) {
throw new PrivilegeException("No name defined!");
}
this.name = name;
// if not all allowed, then validate that deny and allow lists are defined
if (allAllowed) {
this.allAllowed = true;
// all allowed means no policy will be used
this.policy = null;
this.denyList = Collections.emptySet();
this.allowList = Collections.emptySet();
} else {
this.allAllowed = false;
// not all allowed, so policy must be set
if (policy == null || policy.isEmpty()) {
throw new PrivilegeException("All is not allowed and no Policy defined!");
}
this.policy = policy;
if (denyList == null) {
throw new PrivilegeException("All is not allowed and no denyList defined!");
}
this.denyList = Collections.unmodifiableSet(denyList);
if (allowList == null) {
throw new PrivilegeException("All is not allowed and no allowList defined!");
}
this.allowList = Collections.unmodifiableSet(allowList);
if (StringHelper.isEmpty(policy)) {
throw new PrivilegeException("Policy may not be empty!");
}
if (denyList == null) {
throw new PrivilegeException("denyList is null!");
}
if (allowList == null) {
throw new PrivilegeException("allowList is null!");
}
this.name = name;
this.allAllowed = allAllowed;
this.policy = policy;
this.denyList = Collections.unmodifiableSet(denyList);
this.allowList = Collections.unmodifiableSet(allowList);
}
/**
* Constructs a {@link Privilege} from the {@link PrivilegeRep}
* Constructs a {@link PrivilegeImpl} from the {@link PrivilegeRep}
*
* @param privilegeRep
* the {@link PrivilegeRep} from which to create the {@link Privilege}
* the {@link PrivilegeRep} from which to create the {@link PrivilegeImpl}
*/
public Privilege(PrivilegeRep privilegeRep) {
public PrivilegeImpl(PrivilegeRep privilegeRep) {
this(privilegeRep.getName(), privilegeRep.getPolicy(), privilegeRep.isAllAllowed(), privilegeRep.getDenyList(),
privilegeRep.getDenyList());
}
/**
* @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
*/
@Override
public PrivilegeRep asPrivilegeRep() {
return new PrivilegeRep(this.name, this.policy, this.allAllowed, new HashSet<String>(this.denyList),
new HashSet<String>(this.allowList));
}
/**
* @return the name
*/
@Override
public String getName() {
return this.name;
}
@ -132,6 +127,7 @@ public final class Privilege {
/**
* @return the policy
*/
@Override
public String getPolicy() {
return this.policy;
}
@ -139,6 +135,7 @@ public final class Privilege {
/**
* @return the allAllowed
*/
@Override
public boolean isAllAllowed() {
return this.allAllowed;
}
@ -146,6 +143,7 @@ public final class Privilege {
/**
* @return the allowList
*/
@Override
public Set<String> getAllowList() {
return this.allowList;
}
@ -153,16 +151,41 @@ public final class Privilege {
/**
* @return the denyList
*/
@Override
public Set<String> getDenyList() {
return this.denyList;
}
/**
* @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
* @return true if there are values in the allow list
*/
public PrivilegeRep asPrivilegeRep() {
return new PrivilegeRep(this.name, this.policy, this.allAllowed, new HashSet<String>(this.denyList),
new HashSet<String>(this.allowList));
@Override
public boolean hasAllowed() {
return !this.allowList.isEmpty();
}
/**
* @return if the value is in the allow list
*/
@Override
public boolean isAllowed(String value) {
return this.allowList.contains(value);
}
/**
* @return true if there are values in the deny list
*/
@Override
public boolean hasDenied() {
return !this.allowList.isEmpty();
}
/**
* @return true if the value is in the deny list
*/
@Override
public boolean isDenied(String value) {
return this.denyList.contains(value);
}
/**
@ -197,7 +220,7 @@ public final class Privilege {
return false;
if (getClass() != obj.getClass())
return false;
Privilege other = (Privilege) obj;
PrivilegeImpl other = (PrivilegeImpl) obj;
if (this.name == null) {
if (other.name != null)
return false;

View File

@ -22,10 +22,13 @@ package ch.eitchnet.privilege.model.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.PrivilegeRep;
import ch.eitchnet.privilege.model.RoleRep;
import ch.eitchnet.utils.helper.StringHelper;
/**
* <p>
@ -43,7 +46,7 @@ import ch.eitchnet.privilege.model.RoleRep;
public final class Role {
private final String name;
private final Map<String, Privilege> privilegeMap;
private final Map<String, IPrivilege> privilegeMap;
/**
* Default constructor
@ -51,11 +54,11 @@ public final class Role {
* @param name
* the name of the role
* @param privilegeMap
* a map of {@link Privilege}s granted to this role
* a map of {@link IPrivilege}s granted to this role
*/
public Role(String name, Map<String, Privilege> privilegeMap) {
public Role(String name, Map<String, IPrivilege> privilegeMap) {
if (name == null || name.isEmpty()) {
if (StringHelper.isEmpty(name)) {
throw new PrivilegeException("No name defined!");
}
if (privilegeMap == null) {
@ -75,7 +78,7 @@ public final class Role {
public Role(RoleRep roleRep) {
String name = roleRep.getName();
if (name == null || name.isEmpty()) {
if (StringHelper.isEmpty(name)) {
throw new PrivilegeException("No name defined!");
}
@ -84,9 +87,9 @@ public final class Role {
}
// build privileges from reps
Map<String, Privilege> privilegeMap = new HashMap<String, Privilege>(roleRep.getPrivilegeMap().size());
Map<String, IPrivilege> privilegeMap = new HashMap<String, IPrivilege>(roleRep.getPrivilegeMap().size());
for (String privilegeName : roleRep.getPrivilegeMap().keySet()) {
privilegeMap.put(privilegeName, new Privilege(roleRep.getPrivilegeMap().get(privilegeName)));
privilegeMap.put(privilegeName, new PrivilegeImpl(roleRep.getPrivilegeMap().get(privilegeName)));
}
this.name = name;
@ -101,21 +104,30 @@ public final class Role {
}
/**
* Returns the {@link Map} of {@link Privilege}s which are granted to this {@link Role}
* Returns the {@link Set} of names for the currently stored {@link IPrivilege Privileges}
*
* @return the {@link Map} of {@link Privilege}s which are granted to this {@link Role}
* @return the {@link Set} of names for the currently stored {@link IPrivilege Privileges}
*/
public Map<String, Privilege> getPrivilegeMap() {
return this.privilegeMap;
public Set<String> getPrivilegeNames() {
return this.privilegeMap.keySet();
}
/**
* Determines if this {@link Role} has the {@link Privilege} with the given name
* Returns the {@link IPrivilege} for the given name, null if it does not exist
*
* @return the {@link IPrivilege} for the given name, null if it does not exist
*/
public IPrivilege getPrivilege(String name) {
return this.privilegeMap.get(name);
}
/**
* Determines if this {@link Role} has the {@link IPrivilege} with the given name
*
* @param name
* the name of the {@link Privilege}
* the name of the {@link IPrivilege}
*
* @return true if this {@link Role} has the {@link Privilege} with the given name
* @return true if this {@link Role} has the {@link IPrivilege} with the given name
*/
public boolean hasPrivilege(String name) {
return this.privilegeMap.containsKey(name);

View File

@ -1,191 +0,0 @@
/*
* Copyright (c) 2010 - 2012
*
* This file is part of Privilege.
*
* Privilege is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Privilege is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Privilege. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.eitchnet.privilege.model.internal;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.handler.PrivilegeHandler;
import ch.eitchnet.privilege.model.Certificate;
/**
* <p>
* A {@link Session} is linked to currently logged in user. The {@link PrivilegeHandler} creates an instance of this
* class once a {@link User} has successfully logged in and keeps this object private but hands out a
* {@link Certificate} which the user must use every time a privilege needs to be granted
* </p>
*
* <p>
* Note: This is an internal object which is not to be serialized or passed to clients, the client must keep his
* {@link Certificate} which is used for accessing privileges
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public final class Session {
private final String sessionId;
private final String username;
private final long loginTime;
private final String authToken;
private final String authPassword;
/**
* Default constructor
*
* <p>
* Note, both the authentication token and password are private fields which are generated on login and only known
* by the {@link PrivilegeHandler}
* </p>
*
* @param sessionId
* the users session id
* @param username
* the users login name
* @param authToken
* the authentication token defining the users unique session and is a private field of this session. It
* corresponds with the authentication token on the {@link Certificate}
* @param authPassword
* the password to access the authentication token, this is not known to the client but set by the
* {@link PrivilegeHandler} on authentication. It corresponds with the authentication password on the
* {@link Certificate}
* @param loginTime
* the time the user logged in
*/
public Session(String sessionId, String username, String authToken, String authPassword, long loginTime) {
if (sessionId == null || sessionId.isEmpty()) {
throw new PrivilegeException("No sessionId defined!");
}
if (username == null || username.isEmpty()) {
throw new PrivilegeException("No username defined!");
}
if (authToken == null || authToken.isEmpty()) {
throw new PrivilegeException("No authToken defined!");
}
if (authPassword == null || authPassword.isEmpty()) {
throw new PrivilegeException("No authPassword defined!");
}
this.sessionId = sessionId;
this.username = username;
this.authToken = authToken;
this.authPassword = authPassword;
this.loginTime = loginTime;
}
/**
* @return the sessionId
*/
public String getSessionId() {
return this.sessionId;
}
/**
* @return the authToken
*/
public String getAuthToken() {
return this.authToken;
}
/**
* @return the authPassword
*/
public String getAuthPassword() {
return this.authPassword;
}
/**
* @return the username
*/
public String getUsername() {
return this.username;
}
/**
* @return the loginTime
*/
public long getLoginTime() {
return this.loginTime;
}
/**
* Returns a string representation of this object displaying its concrete type and its values
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Session [sessionId=");
builder.append(this.sessionId);
builder.append(", username=");
builder.append(this.username);
builder.append(", loginTime=");
builder.append(this.loginTime);
builder.append("]");
return builder.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.authPassword == null) ? 0 : this.authPassword.hashCode());
result = prime * result + ((this.authToken == null) ? 0 : this.authToken.hashCode());
result = prime * result + (int) (this.loginTime ^ (this.loginTime >>> 32));
result = prime * result + ((this.sessionId == null) ? 0 : this.sessionId.hashCode());
result = prime * result + ((this.username == null) ? 0 : this.username.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Session other = (Session) obj;
if (this.authPassword == null) {
if (other.authPassword != null)
return false;
} else if (!this.authPassword.equals(other.authPassword))
return false;
if (this.authToken == null) {
if (other.authToken != null)
return false;
} else if (!this.authToken.equals(other.authToken))
return false;
if (this.loginTime != other.loginTime)
return false;
if (this.sessionId == null) {
if (other.sessionId != null)
return false;
} else if (!this.sessionId.equals(other.sessionId))
return false;
if (this.username == null) {
if (other.username != null)
return false;
} else if (!this.username.equals(other.username))
return false;
return true;
}
}

View File

@ -29,6 +29,7 @@ import java.util.Set;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.model.UserRep;
import ch.eitchnet.privilege.model.UserState;
import ch.eitchnet.utils.helper.StringHelper;
/**
* This class defines the actual login information for a given user which can be granted privileges. Every user is
@ -84,16 +85,16 @@ public final class User {
public User(String userId, String username, String password, String firstname, String surname, UserState userState,
Set<String> roles, Locale locale, Map<String, String> propertyMap) {
if (userId == null || userId.isEmpty()) {
if (StringHelper.isEmpty(userId)) {
throw new PrivilegeException("No UserId defined!");
}
if (username == null || username.isEmpty()) {
if (StringHelper.isEmpty(username)) {
throw new PrivilegeException("No username defined!");
}
if (firstname == null || firstname.isEmpty()) {
if (StringHelper.isEmpty(firstname)) {
throw new PrivilegeException("No firstname defined!");
}
if (surname == null || surname.isEmpty()) {
if (StringHelper.isEmpty(surname)) {
throw new PrivilegeException("No surname defined!");
}
if (userState == null) {

View File

@ -19,11 +19,16 @@
*/
package ch.eitchnet.privilege.policy;
import java.text.MessageFormat;
import ch.eitchnet.privilege.base.AccessDeniedException;
import ch.eitchnet.privilege.base.PrivilegeException;
import ch.eitchnet.privilege.i18n.PrivilegeMessages;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.PrivilegeContext;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.utils.helper.StringHelper;
/**
* This is a simple implementation of {@link PrivilegePolicy} which uses the {@link Restrictable#getPrivilegeName()} to
@ -36,53 +41,62 @@ public class DefaultPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
* @see ch.eitchnet.privilege.policy.PrivilegePolicy#actionAllowed(ch.eitchnet.privilege.model.internal.Role,
* ch.eitchnet.privilege.model.internal.Privilege, ch.eitchnet.privilege.model.Restrictable)
* @see ch.eitchnet.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Restrictable)
*/
@Override
public void actionAllowed(Role role, Privilege privilege, Restrictable restrictable) {
public void validateAction(IPrivilege privilege, Restrictable restrictable) {
// validate user is not null
if (role == null)
throw new PrivilegeException("Role may not be null!");
if (privilege == null)
throw new PrivilegeException(PrivilegeMessages.getString("Privilege.privilegeNull")); //$NON-NLS-1$
if (restrictable == null)
throw new PrivilegeException(PrivilegeMessages.getString("Privilege.restrictableNull")); //$NON-NLS-1$
// get the PrivilegeName
String privilegeName = restrictable.getPrivilegeName();
if (privilegeName == null || privilegeName.isEmpty()) {
throw new PrivilegeException("The PrivilegeName for the Restrictable is null or empty: " + restrictable);
if (StringHelper.isEmpty(privilegeName)) {
String msg = PrivilegeMessages.getString("Privilege.privilegeNameEmpty"); //$NON-NLS-1$
throw new PrivilegeException(MessageFormat.format(msg, restrictable));
}
// we want the privileges names to match
if (!privilege.getName().equals(privilegeName)) {
throw new PrivilegeException(MessageFormat.format(
PrivilegeMessages.getString("Privilege.illegalArgument.privilegeNameMismatch"), //$NON-NLS-1$
privilege.getName(), privilegeName));
}
// if everything is allowed, then no need to carry on
if (privilege.isAllAllowed())
return;
// get the value on which the action is to be performed
Object object = restrictable.getPrivilegeValue();
// DefaultPrivilege policy expects the privilege value to be a string
if (!(object instanceof String)) {
throw new PrivilegeException(Restrictable.class.getName() + " " + restrictable.getClass().getSimpleName()
+ " has returned a non-string privilege value!");
String msg = Restrictable.class.getName()
+ PrivilegeMessages.getString("Privilege.illegalArgument.nonstring"); //$NON-NLS-1$
msg = MessageFormat.format(msg, restrictable.getClass().getSimpleName());
throw new PrivilegeException(msg);
}
String privilegeValue = (String) object;
// first check values not allowed
for (String denied : privilege.getDenyList()) {
// if value in deny list
if (denied.equals(privilegeValue)) {
// then throw access denied
throw new AccessDeniedException("Role " + role.getName() + " does not have Privilege " + privilegeName
+ " needed for Restrictable " + restrictable.getClass().getName());
}
if (privilege.isDenied(privilegeValue)) {
// then throw access denied
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.accessdenied.noprivilege"),
PrivilegeContext.get().getUsername(), privilegeName, restrictable.getClass().getName());
throw new AccessDeniedException(msg);
}
// now check values allowed
for (String allowed : privilege.getAllowList()) {
if (allowed.equals(privilegeValue))
return;
}
if (privilege.isAllowed(privilegeValue))
return;
// default is not allowed
throw new AccessDeniedException("Role " + role.getName() + " does not have Privilege " + privilegeName
+ " needed for Restrictable " + restrictable.getClass().getName());
String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.accessdenied.noprivilege"),
PrivilegeContext.get().getUsername(), privilegeName, restrictable.getClass().getName());
throw new AccessDeniedException(msg);
}
}

View File

@ -20,20 +20,19 @@
package ch.eitchnet.privilege.policy;
import ch.eitchnet.privilege.base.AccessDeniedException;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.Restrictable;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.User;
/**
* <p>
* {@link PrivilegePolicy} implements logic to determine if a {@link User} which has the given {@link Role} and the
* given {@link Privilege} has access to the given {@link Restrictable}
* given {@link IPrivilege} has access to the given {@link Restrictable}
* </p>
*
* <p>
* Re-think this interface and especially the {@link #actionAllowed(Role, Privilege, Restrictable)}-method... maybe we
* need one with out the {@link Privilege} in its signature?
* TODO
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
@ -41,17 +40,15 @@ import ch.eitchnet.privilege.model.internal.User;
public interface PrivilegePolicy {
/**
* Checks if the given {@link Role} and the given {@link Privilege} has access to the given {@link Restrictable}
* Checks if the given {@link Role} and the given {@link IPrivilege} has access to the given {@link Restrictable}
*
* @param role
* the {@link Role} trying to access the {@link Restrictable}
* @param privilege
* the {@link Privilege} to check with
* the {@link IPrivilege} containing the permissions
* @param restrictable
* the {@link Restrictable} to which the user wants access
*
* @throws AccessDeniedException
* if action not allowed
*/
public void actionAllowed(Role role, Privilege privilege, Restrictable restrictable) throws AccessDeniedException;
public void validateAction(IPrivilege privilege, Restrictable restrictable) throws AccessDeniedException;
}

View File

@ -29,7 +29,7 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import ch.eitchnet.privilege.helper.XmlConstants;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.User;
import ch.eitchnet.utils.helper.XmlHelper;
@ -124,7 +124,8 @@ public class PrivilegeModelDomWriter {
roleElement.setAttribute(XmlConstants.XML_ATTR_NAME, role.getName());
for (Privilege privilege : role.getPrivilegeMap().values()) {
for (String privilegeName : role.getPrivilegeNames()) {
IPrivilege privilege = role.getPrivilege(privilegeName);
// create the privilege element
Element privilegeElement = doc.createElement(XmlConstants.XML_PRIVILEGE);

View File

@ -36,8 +36,9 @@ import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.UserState;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.PrivilegeImpl;
import ch.eitchnet.privilege.model.internal.Role;
import ch.eitchnet.privilege.model.internal.User;
import ch.eitchnet.utils.helper.StringHelper;
@ -149,7 +150,7 @@ public class PrivilegeModelSaxReader extends DefaultHandler {
private Set<String> denyList;
private Set<String> allowList;
private Map<String, Privilege> privileges;
private Map<String, IPrivilege> privileges;
/**
*
@ -162,7 +163,7 @@ public class PrivilegeModelSaxReader extends DefaultHandler {
*
*/
private void init() {
this.privileges = new HashMap<String, Privilege>();
this.privileges = new HashMap<String, IPrivilege>();
this.text = null;
@ -204,7 +205,7 @@ public class PrivilegeModelSaxReader extends DefaultHandler {
this.denyList.add(this.text.toString().trim());
} else if (qName.equals("Privilege")) {
Privilege privilege = new Privilege(this.privilegeName, this.privilegePolicy, this.allAllowed,
IPrivilege privilege = new PrivilegeImpl(this.privilegeName, this.privilegePolicy, this.allAllowed,
this.denyList, this.allowList);
this.privileges.put(this.privilegeName, privilege);

View File

@ -36,8 +36,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.CertificateThreadLocal;
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;
@ -47,6 +47,7 @@ import ch.eitchnet.privilege.test.model.TestRestrictable;
import ch.eitchnet.privilege.test.model.TestSystemUserAction;
import ch.eitchnet.privilege.test.model.TestSystemUserActionDeny;
import ch.eitchnet.privilege.xml.InitializationHelper;
import ch.eitchnet.utils.helper.ArraysHelper;
import ch.eitchnet.utils.helper.FileHelper;
/**
@ -82,11 +83,13 @@ public class PrivilegeTest {
@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/test/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());
@ -102,7 +105,7 @@ public class PrivilegeTest {
throw new RuntimeException("Failed to copy " + origPrivilegeModelFile + " to " + tmpPrivilegeModelFile);
} catch (Exception e) {
PrivilegeTest.logger.error(e.getMessage(), e);
logger.error(e.getMessage(), e);
throw new RuntimeException("Initialization failed: " + e.getLocalizedMessage(), e);
}
@ -114,7 +117,7 @@ public class PrivilegeTest {
// delete temporary file
String pwd = System.getProperty("user.dir");
File tmpPrivilegeModelFile = new File(pwd + "/target/test/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());
@ -136,154 +139,139 @@ public class PrivilegeTest {
File privilegeConfigFile = new File(pwd + "/config/Privilege.xml");
// initialize privilege
PrivilegeTest.privilegeHandler = InitializationHelper.initializeFromXml(privilegeConfigFile);
privilegeHandler = InitializationHelper.initializeFromXml(privilegeConfigFile);
} catch (Exception e) {
PrivilegeTest.logger.error(e.getMessage(), e);
logger.error(e.getMessage(), e);
throw new RuntimeException("Setup failed: " + e.getLocalizedMessage(), e);
}
}
private byte[] copyBytes(byte[] bytes) {
byte[] copy = new byte[bytes.length];
System.arraycopy(bytes, 0, copy, 0, bytes.length);
return copy;
private void login(String username, byte[] password) {
Certificate certificate = privilegeHandler.authenticate(username, password);
Assert.assertTrue("Certificate is null!", certificate != null);
PrivilegeContext privilegeContext = privilegeHandler.getPrivilegeContext(certificate);
PrivilegeContext.set(privilegeContext);
}
private void logout() {
try {
PrivilegeContext privilegeContext = PrivilegeContext.get();
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;
} finally {
PrivilegeContext.set(null);
}
}
/**
* @throws Exception
* if something goes wrong
*/
@Test
public void testAuthenticationOk() throws Exception {
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
Assert.assertTrue("Certificate is null!", certificate != null);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
} finally {
logout();
}
}
/**
* @throws Exception
* if something goes wrong
*/
@Test(expected = AccessDeniedException.class)
public void testFailAuthenticationNOk() throws Exception {
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_BAD));
Assert.assertTrue("Certificate is null!", certificate != null);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
login(ADMIN, ArraysHelper.copyOf(PASS_BAD));
} finally {
logout();
}
}
/**
* @throws Exception
* if something goes wrong
*/
@Test(expected = PrivilegeException.class)
public void testFailAuthenticationPWNull() throws Exception {
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN, null);
Assert.assertTrue("Certificate is null!", certificate != null);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
login(ADMIN, null);
} finally {
logout();
}
}
/**
* @throws Exception
* if something goes wrong
*/
@Test
public void testAddRoleTemp() throws Exception {
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Map<String, PrivilegeRep> privilegeMap = new HashMap<String, PrivilegeRep>();
RoleRep roleRep = new RoleRep(PrivilegeTest.ROLE_TEMP, privilegeMap);
Map<String, PrivilegeRep> privilegeMap = new HashMap<String, PrivilegeRep>();
RoleRep roleRep = new RoleRep(ROLE_TEMP, privilegeMap);
PrivilegeTest.privilegeHandler.addOrReplaceRole(certificate, roleRep);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addOrReplaceRole(certificate, roleRep);
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
/**
* @throws Exception
* if something goes wrong
*/
@Test
public void testPerformRestrictableAsAdmin() throws Exception {
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
Assert.assertTrue("Certificate is null!", certificate != null);
// see if admin can perform restrictable
Restrictable restrictable = new TestRestrictable();
PrivilegeContext.get().validateAction(restrictable);
// see if eitch can perform restrictable
Restrictable restrictable = new TestRestrictable();
PrivilegeTest.privilegeHandler.actionAllowed(certificate, restrictable);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
} finally {
logout();
}
}
/**
* Tests if an action can be performed as a system user
*
* @throws Exception
* if something goes wrong
*/
@Test
public void testPerformSystemRestrictable() throws Exception {
// create the action to be performed as a system user
TestSystemUserAction action = new TestSystemUserAction(PrivilegeTest.privilegeHandler);
// and then perform the action
PrivilegeTest.privilegeHandler.runAsSystem(PrivilegeTest.SYSTEM_USER_ADMIN, action);
// create the action to be performed as a system user and then perform the action
TestSystemUserAction action = new TestSystemUserAction();
privilegeHandler.runAsSystem(SYSTEM_USER_ADMIN, action);
}
/**
* Checks that the system user can not perform a valid action, but illegal privilege
*
* @throws Exception
* if something goes wrong
*/
@Test(expected = PrivilegeException.class)
public void testPerformSystemRestrictableFailPrivilege() throws Exception {
try {
// create the action to be performed as a system user
TestSystemUserActionDeny action = new TestSystemUserActionDeny();
// create the action to be performed as a system user
TestSystemUserActionDeny action = new TestSystemUserActionDeny(PrivilegeTest.privilegeHandler);
// and then perform the action
PrivilegeTest.privilegeHandler.runAsSystem(PrivilegeTest.SYSTEM_USER_ADMIN, action);
// and then perform the action
privilegeHandler.runAsSystem(SYSTEM_USER_ADMIN, action);
} finally {
logout();
}
}
/**
* System user may not login
*
* @throws Exception
* if something goes wrong
*/
@Test(expected = AccessDeniedException.class)
public void testLoginSystemUser() throws Exception {
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.SYSTEM_USER_ADMIN,
PrivilegeTest.SYSTEM_USER_ADMIN.getBytes());
try {
login(SYSTEM_USER_ADMIN, SYSTEM_USER_ADMIN.getBytes());
} finally {
logout();
}
}
@Test
public void testCertificateThreadLocal() {
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
Assert.assertTrue("Certificate is null!", certificate != null);
// set certificate into thread local
CertificateThreadLocal.getInstance().set(certificate);
// see if bob can perform restrictable by returning certificate from CertificateThreadLocal
Restrictable restrictable = new TestRestrictable();
public void testPrivilegeContext() {
try {
PrivilegeTest.privilegeHandler.actionAllowed(CertificateThreadLocal.getInstance().get(), restrictable);
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Restrictable restrictable = new TestRestrictable();
PrivilegeContext.get().validateAction(restrictable);
} finally {
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
logout();
}
}
@ -308,8 +296,6 @@ public class PrivilegeTest {
* <li>perform restrictable as bob</li>
* </ul>
*
* @throws Exception
* if something goes wrong
*/
@Test
public void testUserStory() throws Exception {
@ -334,216 +320,243 @@ public class PrivilegeTest {
}
private void performRestrictableAsBob() {
Certificate certificate;
// testPerformRestrictableAsBob
// Tests if the user bob, who now has AppUser role can perform restrictable
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
Assert.assertTrue("Certificate is null!", certificate != null);
// see if bob can perform restrictable
Restrictable restrictable = new TestRestrictable();
PrivilegeTest.privilegeHandler.actionAllowed(certificate, restrictable);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testPerformRestrictableAsBob
// Tests if the user bob, who now has AppUser role can perform restrictable
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// see if bob can perform restrictable
Restrictable restrictable = new TestRestrictable();
PrivilegeContext.get().validateAction(restrictable);
} finally {
logout();
}
}
private void addRoleAppToBob() {
Certificate certificate;
// testAddAppRoleToBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
PrivilegeTest.privilegeHandler.addRoleToUser(certificate, PrivilegeTest.BOB, PrivilegeTest.ROLE_APP_USER);
PrivilegeTest.logger.info("Added " + PrivilegeTest.ROLE_APP_USER + " to " + PrivilegeTest.BOB);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testAddAppRoleToBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addRoleToUser(certificate, BOB, ROLE_APP_USER);
logger.info("Added " + ROLE_APP_USER + " to " + BOB);
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
private void failPerformRestrictableAsBobNoRoleApp() {
Certificate certificate;
// testFailPerformRestrictableAsBob
// Tests if the user bob, who does not have AppUser role can perform restrictable
// this will fail as bob does not have role app
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
Assert.assertTrue("Certificate is null!", certificate != null);
// see if bob can perform restrictable
Restrictable restrictable = new TestRestrictable();
try {
PrivilegeTest.privilegeHandler.actionAllowed(certificate, restrictable);
// testFailPerformRestrictableAsBob
// Tests if the user bob, who does not have AppUser role can perform restrictable
// this will fail as bob does not have role app
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// see if bob can perform restrictable
Restrictable restrictable = new TestRestrictable();
PrivilegeContext.get().validateAction(restrictable);
Assert.fail("Should fail as bob does not have role app");
} catch (AccessDeniedException e) {
String msg = "User bob does not have Privilege ch.eitchnet.privilege.test.model.TestRestrictable needed for Restrictable ch.eitchnet.privilege.test.model.TestRestrictable";
Assert.assertEquals(msg, e.getLocalizedMessage());
} finally {
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
logout();
}
}
private void authAsTed() {
Certificate certificate;
// testAuthAsTed
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.TED, copyBytes(PrivilegeTest.PASS_TED));
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testAuthAsTed
login(TED, ArraysHelper.copyOf(PASS_TED));
} finally {
logout();
}
}
private void tedChangesOwnPass() {
Certificate certificate;
// testTedChangesOwnPwd
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.TED, copyBytes(PrivilegeTest.PASS_DEF));
PrivilegeTest.privilegeHandler.setUserPassword(certificate, PrivilegeTest.TED,
copyBytes(PrivilegeTest.PASS_TED));
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testTedChangesOwnPwd
login(TED, ArraysHelper.copyOf(PASS_DEF));
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.setUserPassword(certificate, TED, ArraysHelper.copyOf(PASS_TED));
} finally {
logout();
}
}
private void setPassForTedAsBob() {
Certificate certificate;
// testSetTedPwdAsBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
Assert.assertTrue("Certificate is null!", certificate != null);
// set ted's password to default
PrivilegeTest.privilegeHandler.setUserPassword(certificate, PrivilegeTest.TED,
copyBytes(PrivilegeTest.PASS_DEF));
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testSetTedPwdAsBob
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// set ted's password to default
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.setUserPassword(certificate, TED, ArraysHelper.copyOf(PASS_DEF));
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
private void failAuthAsTedNoPass() {
// testFailAuthAsTedNoPass
// Will fail because user ted has no password
try {
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.TED, copyBytes(PrivilegeTest.PASS_TED));
// testFailAuthAsTedNoPass
// Will fail because user ted has no password
login(TED, ArraysHelper.copyOf(PASS_TED));
org.junit.Assert.fail("User Ted may not authenticate because the user has no password!");
} catch (PrivilegeException e) {
String msg = "User ted has no password and may not login!";
Assert.assertEquals(msg, e.getMessage());
} finally {
logout();
}
}
private void addTedAsBob() {
Certificate certificate;
UserRep userRep;
// testAddUserTedAsBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
Assert.assertTrue("Certificate is null!", certificate != null);
// let's add a new user ted
HashSet<String> roles = new HashSet<String>();
roles.add(PrivilegeTest.ROLE_USER);
userRep = new UserRep("2", PrivilegeTest.TED, "Ted", "Newman", UserState.ENABLED, roles, null,
new HashMap<String, String>());
PrivilegeTest.privilegeHandler.addOrReplaceUser(certificate, userRep, null);
PrivilegeTest.logger.info("Added user " + PrivilegeTest.TED);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
UserRep userRep;
// testAddUserTedAsBob
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// let's add a new user ted
HashSet<String> roles = new HashSet<String>();
roles.add(ROLE_USER);
userRep = new UserRep("2", TED, "Ted", "Newman", UserState.ENABLED, roles, null,
new HashMap<String, String>());
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addOrReplaceUser(certificate, userRep, null);
logger.info("Added user " + TED);
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
private void addRoleAdminToBob() {
Certificate certificate;
// testAddAdminRoleToBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
PrivilegeTest.privilegeHandler.addRoleToUser(certificate, PrivilegeTest.BOB,
PrivilegeHandler.PRIVILEGE_ADMIN_ROLE);
PrivilegeTest.logger.info("Added " + PrivilegeHandler.PRIVILEGE_ADMIN_ROLE + " to " + PrivilegeTest.ADMIN);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testAddAdminRoleToBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addRoleToUser(certificate, BOB, PrivilegeHandler.PRIVILEGE_ADMIN_ROLE);
logger.info("Added " + PrivilegeHandler.PRIVILEGE_ADMIN_ROLE + " to " + ADMIN);
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
private void failAddTedAsBobNotAdmin() {
Certificate certificate;
UserRep userRep;
// testFailAddUserTedAsBob
// Will fail because user bob does not have admin rights
// auth as Bob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
// let's add a new user Ted
userRep = new UserRep("1", PrivilegeTest.TED, "Ted", "And then Some", UserState.NEW, new HashSet<String>(),
null, new HashMap<String, String>());
Certificate certificate = null;
try {
PrivilegeTest.privilegeHandler.addOrReplaceUser(certificate, userRep, null);
UserRep userRep;
// testFailAddUserTedAsBob
// Will fail because user bob does not have admin rights
// auth as Bob
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// let's add a new user Ted
userRep = new UserRep("1", TED, "Ted", "And then Some", UserState.NEW, new HashSet<String>(), null,
new HashMap<String, String>());
certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addOrReplaceUser(certificate, userRep, null);
Assert.fail("User bob may not add a user as bob does not have admin rights!");
} catch (PrivilegeException e) {
String msg = "User does not have PrivilegeAdmin role! Certificate: " + certificate.toString();
String msg = "User does not have PrivilegeAdmin role! Certificate: " + certificate;
Assert.assertEquals(msg, e.getMessage());
} finally {
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
logout();
}
}
private void authAsBob() {
Certificate certificate;
// testAuthAsBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testAuthAsBob
login(BOB, ArraysHelper.copyOf(PASS_BOB));
} finally {
logout();
}
}
private void addRoleUserToBob() {
Certificate certificate;
// testAddRoleUserToBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
PrivilegeTest.privilegeHandler.addRoleToUser(certificate, PrivilegeTest.BOB, PrivilegeTest.ROLE_USER);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testAddRoleUserToBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addRoleToUser(certificate, BOB, ROLE_USER);
privilegeHandler.persist(certificate);
logout();
} finally {
logout();
}
}
private void addRoleUser() {
Certificate certificate;
// add role user
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
Map<String, PrivilegeRep> privilegeMap = new HashMap<String, PrivilegeRep>();
RoleRep roleRep = new RoleRep(PrivilegeTest.ROLE_USER, privilegeMap);
PrivilegeTest.privilegeHandler.addOrReplaceRole(certificate, roleRep);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// add role user
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Map<String, PrivilegeRep> privilegeMap = new HashMap<String, PrivilegeRep>();
RoleRep roleRep = new RoleRep(ROLE_USER, privilegeMap);
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addOrReplaceRole(certificate, roleRep);
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
private void failAuthAsBobNoRole() {
// testFailAuthUserBob
// Will fail as user bob has no role
try {
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
// testFailAuthUserBob
// Will fail as user bob has no role
privilegeHandler.authenticate(BOB, ArraysHelper.copyOf(PASS_BOB));
org.junit.Assert.fail("User Bob may not authenticate because the user has no role");
} catch (PrivilegeException e) {
String msg = "User bob does not have any roles defined!";
Assert.assertEquals(msg, e.getMessage());
} finally {
logout();
}
}
private void enableBob() {
Certificate certificate;
// testEnableUserBob
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
PrivilegeTest.privilegeHandler.setUserState(certificate, PrivilegeTest.BOB, UserState.ENABLED);
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
try {
// testEnableUserBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.setUserState(certificate, BOB, UserState.ENABLED);
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
private void failAuthAsBobNotEnabled() {
// testFailAuthAsBob
// Will fail because user bob is not yet enabled
try {
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
// testFailAuthAsBob
// Will fail because user bob is not yet enabled
privilegeHandler.authenticate(BOB, ArraysHelper.copyOf(PASS_BOB));
org.junit.Assert.fail("User Bob may not authenticate because the user is not yet enabled!");
} catch (PrivilegeException e) {
String msg = "User bob does not have state ENABLED and can not login!";
Assert.assertEquals(msg, e.getMessage());
} finally {
logout();
}
}
private void addBobAsAdmin() {
Certificate certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
copyBytes(PrivilegeTest.PASS_ADMIN));
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
// let's add a new user bob
UserRep userRep = new UserRep("1", PrivilegeTest.BOB, "Bob", "Newman", UserState.NEW, new HashSet<String>(),
null, new HashMap<String, String>());
PrivilegeTest.privilegeHandler.addOrReplaceUser(certificate, userRep, null);
PrivilegeTest.logger.info("Added user " + PrivilegeTest.BOB);
// let's add a new user bob
UserRep userRep = new UserRep("1", BOB, "Bob", "Newman", UserState.NEW, new HashSet<String>(), null,
new HashMap<String, String>());
Certificate certificate = PrivilegeContext.get().getCertificate();
privilegeHandler.addOrReplaceUser(certificate, userRep, null);
logger.info("Added user " + BOB);
// set bob's password
PrivilegeTest.privilegeHandler.setUserPassword(certificate, PrivilegeTest.BOB,
copyBytes(PrivilegeTest.PASS_BOB));
PrivilegeTest.logger.info("Set Bob's password");
privilegeHandler.persist(certificate);
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
// set bob's password
privilegeHandler.setUserPassword(certificate, BOB, ArraysHelper.copyOf(PASS_BOB));
logger.info("Set Bob's password");
privilegeHandler.persist(certificate);
} finally {
logout();
}
}
}

View File

@ -23,6 +23,7 @@ package ch.eitchnet.privilege.test;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -40,9 +41,10 @@ import org.slf4j.LoggerFactory;
import ch.eitchnet.privilege.handler.DefaultEncryptionHandler;
import ch.eitchnet.privilege.handler.XmlPersistenceHandler;
import ch.eitchnet.privilege.model.IPrivilege;
import ch.eitchnet.privilege.model.UserState;
import ch.eitchnet.privilege.model.internal.Privilege;
import ch.eitchnet.privilege.model.internal.PrivilegeContainerModel;
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.xml.PrivilegeConfigDomWriter;
@ -71,6 +73,7 @@ public class XmlTest {
*/
@BeforeClass
public static void init() throws Exception {
destroy();
File tmpDir = new File("target/test");
if (tmpDir.exists())
@ -179,7 +182,7 @@ public class XmlTest {
Map<String, String> propertyMap;
Set<String> userRoles;
Map<String, Privilege> privilegeMap;
Map<String, IPrivilege> privilegeMap;
List<User> users = new ArrayList<User>();
propertyMap = new HashMap<String, String>();
@ -197,16 +200,17 @@ public class XmlTest {
propertyMap));
List<Role> roles = new ArrayList<Role>();
privilegeMap = new HashMap<String, Privilege>();
privilegeMap.put("priv1", new Privilege("priv1", "DefaultPrivilege", true, null, null));
Set<String> list = Collections.emptySet();
privilegeMap = new HashMap<String, IPrivilege>();
privilegeMap.put("priv1", new PrivilegeImpl("priv1", "DefaultPrivilege", true, list, list));
roles.add(new Role("role1", privilegeMap));
privilegeMap = new HashMap<String, Privilege>();
privilegeMap = new HashMap<String, IPrivilege>();
Set<String> denyList = new HashSet<String>();
denyList.add("myself");
Set<String> allowList = new HashSet<String>();
allowList.add("other");
privilegeMap.put("priv2", new Privilege("priv2", "DefaultPrivilege", false, denyList, allowList));
privilegeMap.put("priv2", new PrivilegeImpl("priv2", "DefaultPrivilege", false, denyList, allowList));
roles.add(new Role("role2", privilegeMap));
File modelFile = new File("./target/test/PrivilegeModelTest.xml");
@ -214,6 +218,6 @@ public class XmlTest {
configSaxWriter.write();
String fileHash = StringHelper.getHexString(FileHelper.hashFileSha256(modelFile));
Assert.assertEquals("8E1E82278162F21B1654C2E059570BBCB3CB63B053C1DD784BC8E225E8CFD04F", fileHash);
Assert.assertEquals("9007F172BBD7BA51BA3E67199CE0AFCBC8645AF0AC02028ABE54BA6A2FC134B0", fileHash);
}
}

View File

@ -19,34 +19,20 @@
*/
package ch.eitchnet.privilege.test.model;
import ch.eitchnet.privilege.handler.PrivilegeHandler;
import ch.eitchnet.privilege.handler.SystemUserAction;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.PrivilegeContext;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*
*
*/
public class TestSystemUserAction implements SystemUserAction {
private PrivilegeHandler handler;
/**
*
*/
public TestSystemUserAction(PrivilegeHandler handler) {
this.handler = handler;
}
/**
* @see ch.eitchnet.privilege.handler.SystemUserAction#execute(ch.eitchnet.privilege.model.Certificate)
*/
@Override
public void execute(Certificate certificate) {
public void execute(PrivilegeContext context) {
TestSystemRestrictable restrictable = new TestSystemRestrictable();
this.handler.actionAllowed(certificate, restrictable);
PrivilegeContext.set(context);
context.validateAction(restrictable);
PrivilegeContext.set(null);
}
}

View File

@ -19,9 +19,8 @@
*/
package ch.eitchnet.privilege.test.model;
import ch.eitchnet.privilege.handler.PrivilegeHandler;
import ch.eitchnet.privilege.handler.SystemUserAction;
import ch.eitchnet.privilege.model.Certificate;
import ch.eitchnet.privilege.model.PrivilegeContext;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
@ -29,22 +28,9 @@ import ch.eitchnet.privilege.model.Certificate;
*/
public class TestSystemUserActionDeny implements SystemUserAction {
private PrivilegeHandler handler;
/**
*
*/
public TestSystemUserActionDeny(PrivilegeHandler handler) {
this.handler = handler;
}
/**
* @see ch.eitchnet.privilege.handler.SystemUserAction#execute(ch.eitchnet.privilege.model.Certificate)
*/
@Override
public void execute(Certificate certificate) {
public void execute(PrivilegeContext privilegeContext) {
TestRestrictable restrictable = new TestRestrictable();
this.handler.actionAllowed(certificate, restrictable);
privilegeContext.validateAction(restrictable);
}
}