/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.handler;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeConflictResolution;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.IPrivilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.PrivilegeRep;
import li.strolch.privilege.model.RoleRep;
import li.strolch.privilege.model.UserRep;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.policy.PrivilegePolicy;
/**
* The {@link PrivilegeHandler} is the centrally exposed API for accessing the privilege library. It exposes all needed
* methods to access Privilege data model objects, modify them and validate if users or roles have privileges to perform
* an action
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public interface PrivilegeHandler {
///
/**
* Privilege "PrivilegeAction" which is used for privileges which are not further categorized e.g. s
* {@link #PRIVILEGE_ACTION_PERSIST} and {@link #PRIVILEGE_ACTION_GET_POLICIES}
*/
public static final String PRIVILEGE_ACTION = "PrivilegeAction";
/**
* For Privilege "PrivilegeAction" value required to be able to persist changes if not exempted by auto persist or
* <code>allAllowed</code>
*/
public static final String PRIVILEGE_ACTION_PERSIST = "Persist";
/**
* For Privilege "PrivilegeAction" value required to be able to persist session if not exempted by
* <code>allAllowed</code>
*/
public static final String PRIVILEGE_ACTION_PERSIST_SESSIONS = "PersistSessions";
/**
* For Privilege "PrivilegeAction" value required to be able to reload changes if not exempted by
* <code>allAllowed</code>
*/
public static final String PRIVILEGE_ACTION_RELOAD = "Reload";
/**
* For Privilege "PrivilegeAction" value required to get currently configured policies if not
* <code>allAllowed</code>
*/
public static final String PRIVILEGE_ACTION_GET_POLICIES = "GetPolicies";
/**
* For Privilege "PrivilegeAction" value required to get a certificate if not <code>allAllowed</code>
*/
public static final String PRIVILEGE_ACTION_GET_CERTIFICATE = "GetCertificate";
/**
* For Privilege "PrivilegeAction" value required to get all certificates if not <code>allAllowed</code>
*/
public static final String PRIVILEGE_ACTION_GET_CERTIFICATES = "GetCertificates";
///
/**
* Privilege "PrivilegeGetRole" which is used to validate that a user can get a specific role
*/
public static final String PRIVILEGE_GET_ROLE = "PrivilegeGetRole";
/**
* Privilege "PrivilegeAddRole" which is used to validate that a user can add a specific role
*/
public static final String PRIVILEGE_ADD_ROLE = "PrivilegeAddRole";
/**
* Privilege "PrivilegeRemoveRole" which is used to validate that a user can remove a specific role
*/
public static final String PRIVILEGE_REMOVE_ROLE = "PrivilegeRemoveRole";
/**
* Privilege "PrivilegeModifyRole" which is used to validate that a user can modify a specific role. <b>Note:</b>
* This includes modifying of the privileges on the role
*/
public static final String PRIVILEGE_MODIFY_ROLE = "PrivilegeModifyRole";
///
/**
* Privilege "PrivilegeGetUser" which is used to validate that a user can get a specific user
*/
public static final String PRIVILEGE_GET_USER = "PrivilegeGetUser";
/**
* Privilege "PrivilegeAddUser" which is used to validate that a user can add a specific user
*/
public static final String PRIVILEGE_ADD_USER = "PrivilegeAddUser";
/**
* Privilege "PrivilegeRemoveUser" which is used to validate that a user can remove a specific user
*/
public static final String PRIVILEGE_REMOVE_USER = "PrivilegeRemoveUser";
/**
* Privilege "PrivilegeModifyUser" which is used to validate that a user can modify a specific user
*/
public static final String PRIVILEGE_MODIFY_USER = "PrivilegeModifyUser";
/**
* Privilege "PrivilegeAddRoleToUser" which is used to validate that a user can add a specific role to a specific
* user
*/
public static final String PRIVILEGE_ADD_ROLE_TO_USER = "PrivilegeAddRoleToUser";
/**
* Privilege "PrivilegeRemoveRoleFromUser" which is used to validate that a user can remove a specific role from a
* specific user
*/
public static final String PRIVILEGE_REMOVE_ROLE_FROM_USER = "PrivilegeRemoveRoleFromUser";
/**
* Privilege "PRIVILEGE_SET_USER_LOCALE" which is used to validate that a user can set the locale of a user, or
* their own
*/
public static final String PRIVILEGE_SET_USER_LOCALE = "PrivilegeSetUserLocale";
/**
* Privilege "PRIVILEGE_SET_USER_STATE" which is used to validate that a user can set the state of a user
*/
public static final String PRIVILEGE_SET_USER_STATE = "PrivilegeSetUserState";
/**
* Privilege "PRIVILEGE_SET_USER_PASSWORD" which is used to validate that a user can set the password of a user, or
* their own
*/
public static final String PRIVILEGE_SET_USER_PASSWORD = "PrivilegeSetUserPassword";
///
/**
* configuration parameter to define a secret_key
*/
public static final String PARAM_SECRET_KEY = "secretKey"; //$NON-NLS-1$
/**
* configuration parameter to define a secret salt
*/
public static final String PARAM_SECRET_SALT = "secretSalt"; //$NON-NLS-1$
/**
* configuration parameter to define automatic persisting on password change
*/
public static final String PARAM_AUTO_PERSIST_ON_USER_CHANGES_DATA = "autoPersistOnUserChangesData"; //$NON-NLS-1$
/**
* configuration parameter to define if sessions should be persisted
*/
public static final String PARAM_PERSIST_SESSIONS = "persistSessions"; //$NON-NLS-1$
/**
* configuration parameter to define where sessions are to be persisted
*/
public static final String PARAM_PERSIST_SESSIONS_PATH = "persistSessionsPath"; //$NON-NLS-1$
/**
* configuration parameter to define {@link PrivilegeConflictResolution}
*/
public static final String PARAM_PRIVILEGE_CONFLICT_RESOLUTION = "privilegeConflictResolution";
/**
* Returns a {@link UserRep} for the given username
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the name of the {@link UserRep} to return
*
* @return the {@link UserRep} for the given username, or null if it was not found
*/
public UserRep getUser(Certificate certificate, String username);
/**
* Returns a {@link RoleRep} for the given roleName
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param roleName
* the name of the {@link RoleRep} to return
*
* @return the {@link RoleRep} for the given roleName, or null if it was not found
*/
public RoleRep getRole(Certificate certificate, String roleName);
/**
* Returns the map of {@link PrivilegePolicy} definitions
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return the map of {@link PrivilegePolicy} definitions
*/
public Map<String, String> getPolicyDefs(Certificate certificate);
/**
* Returns the list of {@link Certificate Certificates}
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return the list of {@link Certificate Certificates}
*/
public List<Certificate> getCertificates(Certificate certificate);
/**
* Returns all {@link RoleRep RoleReps}
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return the list of {@link RoleRep RoleReps}
*/
public List<RoleRep> getRoles(Certificate certificate);
/**
* Returns all {@link UserRep UserReps}
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return the list of {@link UserRep UserReps}
*/
public List<UserRep> getUsers(Certificate certificate);
/**
* Method to query {@link UserRep} which meet the criteria set in the given {@link UserRep}. Null fields mean the
* fields are irrelevant.
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param selectorRep
* the {@link UserRep} to use as criteria selection
*
* @return a list of {@link UserRep}s which fit the given criteria
*/
public List<UserRep> queryUsers(Certificate certificate, UserRep selectorRep);
/**
* Removes the user with the given username
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the username of the user to remove
*
* @return the {@link UserRep} of the user removed, or null if the user did not exist
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public UserRep removeUser(Certificate certificate, String username)
throws AccessDeniedException, PrivilegeException;
/**
* Removes the role with the given roleName from the user with the given username
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the username of the user from which the role is to be removed
* @param roleName
* the roleName of the role to remove from the user
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public UserRep removeRoleFromUser(Certificate certificate, String username, String roleName)
throws AccessDeniedException, PrivilegeException;
/**
* Removes the role with the given roleName
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param roleName
* the roleName of the role to remove
*
* @return the {@link RoleRep} of the role removed, or null if the role did not exist
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or the role is still in use by a user
*/
public RoleRep removeRole(Certificate certificate, String roleName)
throws AccessDeniedException, PrivilegeException;
/**
* Removes the privilege with the given privilegeName from the role with the given roleName
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param roleName
* the roleName of the role from which the privilege is to be removed
* @param privilegeName
* the privilegeName of the privilege to remove from the role
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public RoleRep removePrivilegeFromRole(Certificate certificate, String roleName, String privilegeName)
throws AccessDeniedException, PrivilegeException;
/**
* <p>
* Adds a new user with the information from this {@link UserRep}
* </p>
*
* <p>
* If the password given is null, then the user is created, but can not not login! Otherwise the password must meet
* the requirements of the implementation under {@link PrivilegeHandler#validatePassword(byte[])}
* </p>
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param userRep
* the {@link UserRep} containing the information to create the new {@link User}
* @param password
* the password of the new user. If the password is null, then this is accepted but the user can not
* login, otherwise the password must be validated against
* {@link PrivilegeHandler#validatePassword(byte[])}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or the user already exists
*/
public UserRep addUser(Certificate certificate, UserRep userRep, byte[] password)
throws AccessDeniedException, PrivilegeException;
/**
* <p>
* Updates the fields for the user with the given user. All fields on the given {@link UserRep} which are non-null
* will be updated on the existing user. The username on the given {@link UserRep} must be set and correspond to an
* existing user.
* </p>
*
* The following fields are considered updateable:
* <ul>
* <li>{@link UserRep#getFirstname()}</li>
* <li>{@link UserRep#getLastname()}</li>
* <li>{@link UserRep#getLocale()}</li>
* <li>{@link UserRep#getProperties()} - the existing properties will be replaced with the given properties</li>
* </ul>
*
* <p>
* Any other fields will be ignored
* </p>
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param userRep
* the {@link UserRep} with the fields set to their new values
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or if the user does not exist
*/
public UserRep updateUser(Certificate certificate, UserRep userRep)
throws AccessDeniedException, PrivilegeException;
/**
* <p>
* Replaces the existing user with the information from this {@link UserRep} if the user already exists
* </p>
*
* <p>
* If the password given is null, then the user is created, but can not not login! Otherwise the password must meet
* the requirements of the implementation under {@link PrivilegeHandler#validatePassword(byte[])}
* </p>
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param userRep
* the {@link UserRep} containing the information to replace the existing {@link User}
* @param password
* the password of the new user. If the password is null, then this is accepted but the user can not
* login, otherwise the password must be validated against
* {@link PrivilegeHandler#validatePassword(byte[])}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or if the user does not exist
*/
public UserRep replaceUser(Certificate certificate, UserRep userRep, byte[] password)
throws AccessDeniedException, PrivilegeException;
/**
* Adds a new role with the information from this {@link RoleRep}
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param roleRep
* the {@link RoleRep} containing the information to create the new {@link Role}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or if the role already exists
*/
public RoleRep addRole(Certificate certificate, RoleRep roleRep) throws AccessDeniedException, PrivilegeException;
/**
* Replaces the existing role with the information from this {@link RoleRep}
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param roleRep
* the {@link RoleRep} containing the information to replace the existing {@link Role}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or if the role does not exist
*/
public RoleRep replaceRole(Certificate certificate, RoleRep roleRep)
throws AccessDeniedException, PrivilegeException;
/**
* Adds the role with the given roleName to the {@link User} with the given username
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the username of the {@link User} to which the role should be added
* @param roleName
* the roleName of the {@link Role} which should be added to the {@link User}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or if the role does not exist
*/
public UserRep addRoleToUser(Certificate certificate, String username, String roleName)
throws AccessDeniedException, PrivilegeException;
/**
* Adds the {@link PrivilegeRep} to the {@link Role} with the given roleName or replaces it, if it already exists
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param roleName
* the roleName of the {@link Role} to which the privilege should be added
* @param privilegeRep
* the representation of the {@link IPrivilege} which should be added or replaced on the {@link Role}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate or the role does not exist
*/
public RoleRep addOrReplacePrivilegeOnRole(Certificate certificate, String roleName, PrivilegeRep privilegeRep)
throws AccessDeniedException, PrivilegeException;
/**
* <p>
* Changes the password for the {@link User} with the given username. If the password is null, then the {@link User}
* can not login anymore. Otherwise the password must meet the requirements of the implementation under
* {@link PrivilegeHandler#validatePassword(byte[])}
* </p>
*
* <p>
* It should be possible for a user to change their own password
* </p>
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the username of the {@link User} for which the password is to be changed
* @param password
* the new password for this user. If the password is null, then the {@link User} can not login anymore.
* Otherwise the password must meet the requirements of the implementation under
* {@link PrivilegeHandler#validatePassword(byte[])}
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public void setUserPassword(Certificate certificate, String username, byte[] password)
throws AccessDeniedException, PrivilegeException;
/**
* Changes the {@link UserState} of the user
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the username of the {@link User} for which the {@link UserState} is to be changed
* @param state
* the new state for the user
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public UserRep setUserState(Certificate certificate, String username, UserState state)
throws AccessDeniedException, PrivilegeException;
/**
* Changes the {@link Locale} of the user
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
* @param username
* the username of the {@link User} for which the {@link Locale} is to be changed
* @param locale
* the new {@link Locale} for the user
*
* @throws AccessDeniedException
* if the user for this certificate may not perform the action
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public UserRep setUserLocale(Certificate certificate, String username, Locale locale)
throws AccessDeniedException, PrivilegeException;
/**
* Authenticates a user by validating that a {@link User} for the given username and password exist and then returns
* a {@link Certificate} with which this user may then perform actions
*
* @param username
* the username of the {@link User} which is registered in the {@link PersistenceHandler}
* @param password
* the password with which this user is to be authenticated. Null passwords are not accepted and they
* must meet the requirements of the {@link #validatePassword(byte[])}-method
*
* @return a {@link Certificate} with which this user may then perform actions
*
* @throws AccessDeniedException
* if the user credentials are not valid
*/
public Certificate authenticate(String username, byte[] password) throws AccessDeniedException;
/**
* 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 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 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
*
* @param certificate
* the {@link Certificate} to check
*
* @throws PrivilegeException
* if there is anything wrong with this certificate
*/
public void isCertificateValid(Certificate certificate) throws PrivilegeException;
/**
* Checks that the given password belongs to the given {@link Certificate}. If it doesn't, then a
* {@link PrivilegeException} is thrown
*
* @param certificate
* the certificate for which to check the password
* @param password
* the password to check against the user from the certificate
*
* @throws PrivilegeException
* if the certificate is invalid or the password does not match
*/
public void checkPassword(Certificate certificate, byte[] password) 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;
/**
* Validate that the given password meets certain requirements. What these requirements are is a decision made by
* the concrete implementation
*
* @param password
* the password to be validated to meet certain requirements
*
* @throws PrivilegeException
* if the password does not implement the requirement of the concrete implementation
*/
public void validatePassword(byte[] password) throws PrivilegeException;
/**
* <p>
* Informs this {@link PersistenceHandler} to reload the data from the backend
* </p>
*
* <b>Note:</b> It depends on the underlying {@link PersistenceHandler} implementation if data really is read
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return true if the reload was successful, false if something went wrong
*
* @throws AccessDeniedException
* if the users of the given certificate does not have the privilege to perform this action
*/
public boolean reload(Certificate certificate);
/**
* Persists any changes to the privilege data model. Changes are thus not persisted immediately, but must be
* actively performed
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return true if changes were persisted, false if no changes were persisted
*
* @throws AccessDeniedException
* if the users of the given certificate does not have the privilege to perform this action
*/
public boolean persist(Certificate certificate) throws AccessDeniedException;
/**
* Persists all currently active sessions
*
* @param certificate
* the {@link Certificate} of the user which has the privilege to perform this action
*
* @return true if changes were persisted, false if not (i.e. not enabled)
*
* @throws AccessDeniedException
* if the users of the given certificate does not have the privilege to perform this action
*/
public boolean persistSessions(Certificate certificate) throws AccessDeniedException;
/**
* Special method to perform work as a System user, meaning the given systemUsername corresponds to an account which
* has the state {@link UserState#SYSTEM} and this user must have privilege to perform the concrete implementation
* of the given {@link SystemUserAction} instance
*
*
* @param systemUsername
* the username of the system user to perform the action as
* @param action
* the action to be performed as the system user
*
* @return the action
*
* @throws PrivilegeException
*/
public <T extends SystemUserAction> T runAsSystem(String systemUsername, T action) throws PrivilegeException;
/**
* Returns the {@link EncryptionHandler} instance
*
* @return the {@link EncryptionHandler} instance
*/
public EncryptionHandler getEncryptionHandler() throws PrivilegeException;
}