All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ligoj.app.iam.IUserRepository Maven / Gradle / Ivy

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; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy