[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:
parent
9261494667
commit
93022ba559
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
@ -58,16 +42,16 @@ 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>
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 + '!';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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\!
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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!");
|
||||
if (StringHelper.isEmpty(policy)) {
|
||||
throw new PrivilegeException("Policy may not be empty!");
|
||||
}
|
||||
this.policy = policy;
|
||||
|
||||
if (denyList == null) {
|
||||
throw new PrivilegeException("All is not allowed and no denyList defined!");
|
||||
throw new PrivilegeException("denyList is null!");
|
||||
}
|
||||
this.denyList = Collections.unmodifiableSet(denyList);
|
||||
|
||||
if (allowList == null) {
|
||||
throw new PrivilegeException("All is not allowed and no allowList defined!");
|
||||
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;
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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)) {
|
||||
|
||||
if (privilege.isDenied(privilegeValue)) {
|
||||
// then throw access denied
|
||||
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);
|
||||
}
|
||||
|
||||
// now check values allowed
|
||||
for (String allowed : privilege.getAllowList()) {
|
||||
if (allowed.equals(privilegeValue))
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
RoleRep roleRep = new RoleRep(ROLE_TEMP, privilegeMap);
|
||||
|
||||
PrivilegeTest.privilegeHandler.addOrReplaceRole(certificate, roleRep);
|
||||
Certificate certificate = PrivilegeContext.get().getCertificate();
|
||||
privilegeHandler.addOrReplaceRole(certificate, roleRep);
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(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 eitch can perform restrictable
|
||||
// see if admin can perform restrictable
|
||||
Restrictable restrictable = new TestRestrictable();
|
||||
PrivilegeTest.privilegeHandler.actionAllowed(certificate, restrictable);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
PrivilegeContext.get().validateAction(restrictable);
|
||||
|
||||
} 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(PrivilegeTest.privilegeHandler);
|
||||
TestSystemUserActionDeny action = new TestSystemUserActionDeny();
|
||||
|
||||
// and then perform the action
|
||||
PrivilegeTest.privilegeHandler.runAsSystem(PrivilegeTest.SYSTEM_USER_ADMIN, 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;
|
||||
try {
|
||||
// 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);
|
||||
login(BOB, ArraysHelper.copyOf(PASS_BOB));
|
||||
// see if bob can perform restrictable
|
||||
Restrictable restrictable = new TestRestrictable();
|
||||
PrivilegeTest.privilegeHandler.actionAllowed(certificate, restrictable);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
PrivilegeContext.get().validateAction(restrictable);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoleAppToBob() {
|
||||
Certificate certificate;
|
||||
try {
|
||||
// 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);
|
||||
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);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void failPerformRestrictableAsBobNoRoleApp() {
|
||||
Certificate certificate;
|
||||
try {
|
||||
// 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);
|
||||
login(BOB, ArraysHelper.copyOf(PASS_BOB));
|
||||
// see if bob can perform restrictable
|
||||
Restrictable restrictable = new TestRestrictable();
|
||||
try {
|
||||
PrivilegeTest.privilegeHandler.actionAllowed(certificate, restrictable);
|
||||
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;
|
||||
try {
|
||||
// testAuthAsTed
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.TED, copyBytes(PrivilegeTest.PASS_TED));
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
login(TED, ArraysHelper.copyOf(PASS_TED));
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void tedChangesOwnPass() {
|
||||
Certificate certificate;
|
||||
try {
|
||||
// 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);
|
||||
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;
|
||||
try {
|
||||
// testSetTedPwdAsBob
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
|
||||
Assert.assertTrue("Certificate is null!", certificate != null);
|
||||
login(BOB, ArraysHelper.copyOf(PASS_BOB));
|
||||
// set ted's password to default
|
||||
PrivilegeTest.privilegeHandler.setUserPassword(certificate, PrivilegeTest.TED,
|
||||
copyBytes(PrivilegeTest.PASS_DEF));
|
||||
Certificate certificate = PrivilegeContext.get().getCertificate();
|
||||
privilegeHandler.setUserPassword(certificate, TED, ArraysHelper.copyOf(PASS_DEF));
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void failAuthAsTedNoPass() {
|
||||
try {
|
||||
// testFailAuthAsTedNoPass
|
||||
// Will fail because user ted has no password
|
||||
try {
|
||||
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.TED, copyBytes(PrivilegeTest.PASS_TED));
|
||||
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;
|
||||
try {
|
||||
UserRep userRep;
|
||||
// testAddUserTedAsBob
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
|
||||
Assert.assertTrue("Certificate is null!", certificate != null);
|
||||
login(BOB, ArraysHelper.copyOf(PASS_BOB));
|
||||
// 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,
|
||||
roles.add(ROLE_USER);
|
||||
userRep = new UserRep("2", TED, "Ted", "Newman", UserState.ENABLED, roles, null,
|
||||
new HashMap<String, String>());
|
||||
PrivilegeTest.privilegeHandler.addOrReplaceUser(certificate, userRep, null);
|
||||
PrivilegeTest.logger.info("Added user " + PrivilegeTest.TED);
|
||||
Certificate certificate = PrivilegeContext.get().getCertificate();
|
||||
privilegeHandler.addOrReplaceUser(certificate, userRep, null);
|
||||
logger.info("Added user " + TED);
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoleAdminToBob() {
|
||||
Certificate certificate;
|
||||
try {
|
||||
// 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);
|
||||
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);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void failAddTedAsBobNotAdmin() {
|
||||
Certificate certificate;
|
||||
Certificate certificate = null;
|
||||
try {
|
||||
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));
|
||||
login(BOB, ArraysHelper.copyOf(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>());
|
||||
try {
|
||||
PrivilegeTest.privilegeHandler.addOrReplaceUser(certificate, userRep, null);
|
||||
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;
|
||||
try {
|
||||
// testAuthAsBob
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
login(BOB, ArraysHelper.copyOf(PASS_BOB));
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoleUserToBob() {
|
||||
Certificate certificate;
|
||||
try {
|
||||
// testAddRoleUserToBob
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
|
||||
copyBytes(PrivilegeTest.PASS_ADMIN));
|
||||
PrivilegeTest.privilegeHandler.addRoleToUser(certificate, PrivilegeTest.BOB, PrivilegeTest.ROLE_USER);
|
||||
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
|
||||
Certificate certificate = PrivilegeContext.get().getCertificate();
|
||||
privilegeHandler.addRoleToUser(certificate, BOB, ROLE_USER);
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
logout();
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void addRoleUser() {
|
||||
Certificate certificate;
|
||||
try {
|
||||
// add role user
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
|
||||
copyBytes(PrivilegeTest.PASS_ADMIN));
|
||||
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
|
||||
Map<String, PrivilegeRep> privilegeMap = new HashMap<String, PrivilegeRep>();
|
||||
RoleRep roleRep = new RoleRep(PrivilegeTest.ROLE_USER, privilegeMap);
|
||||
PrivilegeTest.privilegeHandler.addOrReplaceRole(certificate, roleRep);
|
||||
RoleRep roleRep = new RoleRep(ROLE_USER, privilegeMap);
|
||||
Certificate certificate = PrivilegeContext.get().getCertificate();
|
||||
privilegeHandler.addOrReplaceRole(certificate, roleRep);
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void failAuthAsBobNoRole() {
|
||||
try {
|
||||
// testFailAuthUserBob
|
||||
// Will fail as user bob has no role
|
||||
try {
|
||||
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
|
||||
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;
|
||||
try {
|
||||
// testEnableUserBob
|
||||
certificate = PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.ADMIN,
|
||||
copyBytes(PrivilegeTest.PASS_ADMIN));
|
||||
PrivilegeTest.privilegeHandler.setUserState(certificate, PrivilegeTest.BOB, UserState.ENABLED);
|
||||
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
|
||||
Certificate certificate = PrivilegeContext.get().getCertificate();
|
||||
privilegeHandler.setUserState(certificate, BOB, UserState.ENABLED);
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
|
||||
private void failAuthAsBobNotEnabled() {
|
||||
try {
|
||||
// testFailAuthAsBob
|
||||
// Will fail because user bob is not yet enabled
|
||||
try {
|
||||
PrivilegeTest.privilegeHandler.authenticate(PrivilegeTest.BOB, copyBytes(PrivilegeTest.PASS_BOB));
|
||||
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);
|
||||
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.setUserPassword(certificate, BOB, ArraysHelper.copyOf(PASS_BOB));
|
||||
logger.info("Set Bob's password");
|
||||
privilegeHandler.persist(certificate);
|
||||
PrivilegeTest.privilegeHandler.invalidateSession(certificate);
|
||||
} finally {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,24 +28,11 @@ import ch.eitchnet.privilege.model.Certificate;
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue