org.ligoj.app.iam.IUserRepository Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of plugin-api Show documentation
Show all versions of plugin-api Show documentation
Plugin API definition and compatibility following semver
The newest version!
/*
* Licensed under MIT (https://github.com/ligoj/ligoj/blob/master/LICENSE)
*/
package org.ligoj.app.iam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.ligoj.bootstrap.core.resource.BusinessException;
import org.ligoj.bootstrap.core.validation.ValidationJsonException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.Nullable;
import java.util.*;
/**
* User repository
*/
public interface IUserRepository {
/**
* Return the {@link UserOrg} corresponding to the given identifier without using cache. The remote repository is
* checked using the local unique identifier.
*
* @param id The local user identifier.
* @return The found user or null
when not found. Groups are not fetched for this operation.
*/
UserOrg findByIdNoCache(String id);
/**
* Return the {@link UserOrg} corresponding to the given attribute/value without using cache for the query, but
* using it to resolve the user.
*
* @param attribute the attribute name to match.
* @param value the attribute value to match.
* @return the found user or null
when not found. Groups are not fetched for this operation.
*/
default UserOrg findOneBy(final String attribute, final String value) {
return findAllBy(attribute, value).stream().findFirst().orElse(null);
}
/**
* Return all {@link UserOrg} corresponding to the given attribute/value without using cache for the query, but
* using it to resolve the user. If the user is not found in the cache, the fresh data is used.
*
* @param attribute the attribute name to match.
* @param value the attribute value to match.
* @return the found users or empty list.
*/
List findAllBy(String attribute, String value);
/**
* Return all user entries. Cache manager is involved.
*
* @return all user entries. Key is the user identifier.
*/
Map findAll();
/**
* Return all user entries. Cache manager is not involved, poor performance is expected.
*
* @param groups The available and resolved groups.
* @return all user entries. Key is the user identifier.
* @since 3.0.2
*/
default Map findAllNoCache(Map groups) {
return findAll();
}
/**
* Return the users members (UIDs) of the given groups and matching to the given pattern.
*
* @param requiredGroups Filtered groups to be member of returned users. The users must be member of one of these
* groups. When null
, there is no constraint.
* @param companies Filtered companies (DNs) to be member of returned users.
* @param criteria the optional criteria used to check identifier (UID), first name and last name.
* @param pageable the ordering and page data.
* @return the UID of users matching all above criteria.
*/
Page findAll(Collection requiredGroups, Set companies, String criteria,
Pageable pageable);
/**
* Return the {@link UserOrg} corresponding to the given identifier using the user cache.
*
* @param id the user identifier.
* @return the {@link UserOrg} corresponding to the given identifier. May be null
.
*/
default UserOrg findById(final String id) {
return findAll().get(id);
}
/**
* Return the {@link UserOrg} corresponding to the given identifier using the user cache and the relevant security
* to check the current user has the rights to perform this request.
*
* @param principal The user requesting this data.
* @param id the user to find.
* @return the {@link UserOrg} corresponding to the given identifier. Never null
.
* @throws ValidationJsonException If no user is found.
*/
default UserOrg findByIdExpected(final String principal, final String id) {
// Check the user exists
final var rawUser = findByIdExpected(id);
if (getCompanyRepository().findById(principal, rawUser.getCompany()) == null) {
// No available delegation -> no result
throw new ValidationJsonException("id", BusinessException.KEY_UNKNOWN_ID, "0", "user", "1", principal);
}
return rawUser;
}
/**
* Return the {@link UserOrg} corresponding to the given identifier using the user cache.
*
* @param id The user identifier.
* @return the {@link UserOrg} corresponding to the given identifier. Never null
.
* @throws ValidationJsonException If no user is found.
*/
default UserOrg findByIdExpected(final String id) {
return Optional.ofNullable(findById(id))
.orElseThrow(() -> new ValidationJsonException("id", "unknown-id", "0", "user", "1", id));
}
/**
* Return the {@link ICompanyRepository} to use to resolve the company of the managed users.
*
* @return the {@link ICompanyRepository} to use to resolve the company of the managed users.
*/
default ICompanyRepository getCompanyRepository() {
return null;
}
/**
* Return the {@link IGroupRepository} to use to resolve the group of the managed users.
*
* @return the {@link IGroupRepository} to use to resolve the group of the managed users.
*/
default IGroupRepository getGroupRepository() {
return null;
}
/**
* Check the user credentials.
*
* @param name the user's name.
* @param password the user's password.
* @return Authenticated {@link UserOrg}.
*/
UserOrg authenticate(String name, String password);
/**
* Return user token based on salted password.
*
* @param id The user identifier.
* @return User token based on salted password or null
.
*/
String getToken(String id);
/**
* Reset user password to the given value. The given password is not stored inside the given {@link UserOrg}
* instance, but only in the remote storage, and in a hashed form.
*
* @param user The user to update.
* @param password The raw new password. Will be hashed.
*/
void setPassword(UserOrg user, String password);
/**
* Reset user password to the given value. The given password is not stored inside the given {@link UserOrg}
* instance, but only in the remote storage, and in a hashed form. Some LDAP modules such as PPolicy requires a
* fully authenticated of the target user to apply the password policy.
*
* @param user The user to update.
* @param password The user current password. When null
, a new temporary password will be generated
* to guarantee the authentication before performing any change.
* @param newPassword The raw new password. Will be hashed.
*/
void setPassword(UserOrg user, @Nullable String password, String newPassword);
/**
* Return a safe {@link UserOrg} instance, even if the user is not in LDAP directory.
*
* @param id The user identifier. Must not be null
.
* @return a not null
{@link UserOrg} instance with at least identifier attribute.
*/
default UserOrg toUser(final String id) {
if (id == null) {
return null;
}
// Non null user name
var result = findById(id);
if (result == null) {
result = new UserOrg();
result.setId(id);
}
return result;
}
/**
* Base DN for internal people.
*
* @return Base DN for internal people.
*/
String getPeopleInternalBaseDn();
/**
* Execute LDAP modifications for each change between entries. Cache is also updated.
*
* @param user The user to update. The properties will be copied, this instance will not be the one stored
* internally.
*/
void updateUser(UserOrg user);
/**
* Move a user from his/her location to the target company. Cache is also updated, and the company of given user is
* replaced by the given company.
*
* @param user The LDAP user to disable.
* @param company The target company.
*/
void move(UserOrg user, CompanyOrg company);
/**
* Restore a user from the isolated to the previous company of this user and unlock this user.
*
* @param user The LDAP user to disable.
*/
void restore(UserOrg user);
/**
* Unlock a user :
*
* - Check the user is not isolated
* - Check the user is locked
* - Clear the locked flag
*
* Note the password stills as is. If this user was previously locked, the password stills cleared.
* Depending on the final implementation, other attributes or changes may be added. Such as PPolicy for LDAP when
* supported.
*
* @param user The LDAP user to disable.
* @see #lock(String, UserOrg)
*/
void unlock(UserOrg user);
/**
* Isolate an user to the quarantine zone :
*
* - Clear the password to prevent new authentication
* - Set the disabled flag.
* - Move the user to the quarantine zone, DN is also update.
* - Set the previous company.
*
*
* @param principal User requesting the lock.
* @param user The LDAP user to disable.
*/
void isolate(String principal, UserOrg user);
/**
* Lock a user :
*
* - Clear the password to prevent new authentication
* - Set the disabled flag.
*
* Depending on the final implementation, other attributes or changes may be added. Such as PPolicy for LDAP when
* supported.
*
* @param principal User requesting the lock.
* @param user The LDAP user to disable.
* @see #unlock(UserOrg)
*/
void lock(String principal, UserOrg user);
/**
* Delete the given user.
*
* @param user the LDAP user.
*/
void delete(UserOrg user);
/**
* Update membership of given user.
*
* @param groups the target groups CN, not normalized.
* @param user the target user.
* @return the updated attributes and related changes. Currently only `groups` attributes is supported and contains only the
*/
default UserUpdateResult updateMembership(Collection groups, UserOrg user) {
final var result = new UserUpdateResult();
result.setAddedGroups(CollectionUtils.subtract(groups, user.getGroups()));
result.setRemovedGroups( CollectionUtils.subtract(user.getGroups(), groups));
// Add new groups
addUserToGroups(user,result.getAddedGroups());
// Remove old groups
removeUserFromGroups(user, result.getRemovedGroups());
return result;
}
/**
* Add the user from the given groups. Cache is also updated.
*
* @param user The user to add to the given groups.
* @param groups the groups to add, normalized.
*/
default void addUserToGroups(final UserOrg user, final Collection groups) {
final var repository = getGroupRepository();
groups.forEach(g -> repository.addUser(user, g));
}
/**
* Remove the user from the given groups.Cache is also updated.
*
* @param user The user to remove from the given groups.
* @param groups the groups to remove, normalized.
*/
default void removeUserFromGroups(final UserOrg user, final Collection groups) {
final var repository = getGroupRepository();
groups.forEach(g -> repository.removeUser(user, g));
}
/**
* Create an entry.
*
* @param entry User to add to LDAP.
* @return the formal parameter.
*/
UserOrg create(UserOrg entry);
/**
* Rebuild the DN from the given user.
*
* @param newUser The user source where the DN need to be computed.
* @return the DN from the given user. May be different from the {@link UserOrg#getDn()}
*/
String toDn(UserOrg newUser);
/**
* Check and update the user lock status without using cache. This will check only
* pwdAccountLockedTime
, PPolicy attribute.
*
* @param user Target user to check.
*/
default void checkLockStatus(UserOrg user) {
// By default not supported
}
/**
* Return optional custom attributes.
*
* @return Optional custom attributes.
*/
default String[] getCustomAttributes() {
return ArrayUtils.EMPTY_STRING_ARRAY;
}
}