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

io.imunity.furms.unity.users.UnityUsersDAO Maven / Gradle / Ivy

There is a newer version: 4.3.1
Show newest version
/*
 * Copyright (c) 2020 Bixbit s.c. All rights reserved.
 *  See LICENSE file for licensing information.
 */

package io.imunity.furms.unity.users;

import com.fasterxml.jackson.databind.node.ObjectNode;
import io.imunity.furms.domain.authz.roles.ResourceId;
import io.imunity.furms.domain.authz.roles.Role;
import io.imunity.furms.domain.invitations.Invitation;
import io.imunity.furms.domain.invitations.InvitationCode;
import io.imunity.furms.domain.users.AllUsersAndFenixAdmins;
import io.imunity.furms.domain.users.FURMSUser;
import io.imunity.furms.domain.users.FenixUserId;
import io.imunity.furms.domain.users.GroupedUsers;
import io.imunity.furms.domain.users.PersistentId;
import io.imunity.furms.domain.users.UserAttribute;
import io.imunity.furms.domain.users.UserAttributes;
import io.imunity.furms.domain.users.UserStatus;
import io.imunity.furms.spi.exceptions.UnityFailureException;
import io.imunity.furms.spi.invitations.InvitationDAO;
import io.imunity.furms.spi.users.UsersDAO;
import io.imunity.furms.unity.client.UnityClient;
import io.imunity.furms.unity.client.UnityGroupParser;
import io.imunity.furms.unity.client.users.UserService;
import io.imunity.furms.unity.common.AttributeValueMapper;
import io.imunity.furms.unity.common.UnityConst;
import io.imunity.furms.unity.common.UnityPaths;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import org.springframework.web.util.UriComponentsBuilder;
import pl.edu.icm.unity.types.basic.Attribute;
import pl.edu.icm.unity.types.basic.EntityState;

import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static io.imunity.furms.domain.authz.roles.Role.FENIX_ADMIN;
import static io.imunity.furms.unity.client.UnityGroupParser.usersGroupPredicate4Attr;
import static io.imunity.furms.unity.common.UnityConst.FENIX_GROUP;
import static io.imunity.furms.unity.common.UnityConst.FENIX_PATTERN;
import static io.imunity.furms.unity.common.UnityConst.ID;
import static io.imunity.furms.unity.common.UnityConst.IDENTIFIER_IDENTITY;
import static io.imunity.furms.unity.common.UnityConst.PERSISTENT_IDENTITY;
import static io.imunity.furms.unity.common.UnityPaths.ENTITY_BASE;
import static io.imunity.furms.unity.common.UnityPaths.GROUP_ATTRIBUTES;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toMap;

@Component
class UnityUsersDAO implements UsersDAO {

	private final UnityClient unityClient;
	private final UserService userService;
	private final InvitationDAO invitationDAO;

	UnityUsersDAO(UnityClient unityClient, UserService userService, InvitationDAO invitationDAO) {
		this.unityClient = unityClient;
		this.userService = userService;
		this.invitationDAO = invitationDAO;
	}

	@Override
	public List getAllUsers() {
		return userService.getAllUsersFromGroup(FENIX_GROUP, attr -> true);
	}

	@Override
	public InvitationCode inviteUser(ResourceId resourceId, Role role, String email, Instant invitationExpiration) {
		InvitationCode code = invitationDAO.createInvitation(resourceId, role, email, invitationExpiration);
		invitationDAO.sendInvitation(code);
		return code;
	}

	@Override
	public InvitationCode findByRegistrationId(String registrationId) {
		return invitationDAO.findInvitationCode(registrationId);
	}

	@Override
	public void removeInvitation(InvitationCode invitationCode) {
		invitationDAO.removeInvitation(invitationCode);
	}

	@Override
	public void resendInvitation(Invitation invitation, Instant invitationExpiration) {
		invitationDAO.updateInvitation(invitation.resourceId, invitation.role, invitation.email, invitation.code, invitationExpiration);
		invitationDAO.sendInvitation(invitation.code);
	}

	@Override
	public void resendInvitation(Invitation invitation, Instant invitationExpiration, Role role) {
		invitationDAO.updateInvitation(invitation.resourceId, role, invitation.email, invitation.code, invitationExpiration);
		invitationDAO.sendInvitation(invitation.code);
	}

	@Override
	public void setUserStatus(FenixUserId fenixUserId, UserStatus status) {
		EntityState unityStatus = status == UserStatus.ENABLED ? EntityState.valid : EntityState.disabled;
		String uri = UriComponentsBuilder.newInstance()
			.path(ENTITY_BASE)
			.path(fenixUserId.id)
			.path("/status/")
			.path(unityStatus.name())
			.toUriString();
		try {
			unityClient.put(uri, null, Map.of("identityType", "identifier"));
		} catch (WebClientResponseException e) {
			throw new UnityFailureException(e.getMessage(), e);
		}
	}

	@Override
	public UserStatus getUserStatus(FenixUserId fenixUserId) {
		String uri = UriComponentsBuilder.newInstance()
				.path(ENTITY_BASE)
				.path(fenixUserId.id)
				.toUriString();
		try {
			ObjectNode response = unityClient.get(uri, ObjectNode.class, Map.of("identityType", "identifier"));
			String statusStr = response.get("entityInformation").get("state").asText();
			EntityState unityState = EntityState.valueOf(statusStr);
			return unityState == EntityState.valid ? UserStatus.ENABLED : UserStatus.DISABLED;
		} catch (WebClientResponseException e) {
			throw new UnityFailureException(e.getMessage(), e);
		}
	}

	@Override
	public Optional findById(PersistentId userId) {
		return userService.getUser(userId);
	}

	@Override
	public Optional findById(FenixUserId userId) {
		return userService.getUser(userId);
	}
	
	@Override
	public PersistentId getPersistentId(FenixUserId userId) {
		return userService.getPersistentId(userId);
	}
	
	@Override
	public FenixUserId getFenixUserId(PersistentId userId) {
		return userService.getFenixUserId(userId);
	}

	@Override
	public UserAttributes getUserAttributes(FenixUserId fenixUserId) {
		Map> userAttributes = fetchUserAttributes(fenixUserId);
		Set userGroups = fetchUserGroups(fenixUserId);
		return getUserAttributes(userAttributes, userGroups);
	}

	@Override
	public UserAttributes getUserAttributes(PersistentId persistentId) {
		Map> userAttributes = fetchUserAttributes(persistentId);
		Set userGroups = fetchUserGroups(persistentId);
		return getUserAttributes(userAttributes, userGroups);
	}

	private UserAttributes getUserAttributes(Map> userAttributes, Set userGroups) {
		Map> resourceToAttributesMap = getResourceToAttributesMap(userAttributes);
		Map> resourceToAttributesMapComplete = addEmptyMemberships(
			resourceToAttributesMap, userGroups);
		List rootAttributes = userAttributes.getOrDefault(UnityConst.ROOT_GROUP, emptyList());
		return new UserAttributes(toFurmsAttributes(rootAttributes),
			toFurmsAttributesMap(resourceToAttributesMapComplete));
	}

	@Override
	public AllUsersAndFenixAdmins getAllUsersAndFenixAdmins() {
		GroupedUsers groupedUsers = userService.getUsersFromGroupsFilteredByRoles(Map.of(
			FENIX_PATTERN,
			Set.of(FENIX_ADMIN),
			FENIX_GROUP,
			Set.of()
		));
		return new AllUsersAndFenixAdmins(groupedUsers.getUsers(FENIX_GROUP), groupedUsers.getUsers(FENIX_PATTERN));
	}

	private Map> addEmptyMemberships(
			Map> resourceToAttributesMap, Set userGroups)
	{
		Map> ret = new HashMap<>(resourceToAttributesMap);
		userGroups.stream()
			.filter(UnityGroupParser.COMMUNITY_BASE_GROUP_PREDICATE)
			.map(UnityGroupParser::getResourceId)
			.filter(resourceId -> !resourceToAttributesMap.containsKey(resourceId))
			.forEach(resourceId -> ret.put(resourceId, Collections.emptySet()));
		
		return ret;
	}

	private Map> toFurmsAttributesMap(
			Map> unityAttributesMap) {
		return unityAttributesMap.entrySet().stream()
				.collect(Collectors.toMap(Map.Entry::getKey, entry -> toFurmsAttributes(entry.getValue())));
	}
	
	private Set toFurmsAttributes(Collection unityAttributes) {
		return unityAttributes.stream()
				.map(this::toFurmsAttribute)
				.collect(Collectors.toSet());
	}
	
	private UserAttribute toFurmsAttribute(Attribute unityAttribute) {
		return new UserAttribute(unityAttribute.getName(), 
				unityAttribute.getValues().stream()
					.map(value -> AttributeValueMapper.toFurmsAttributeValue(unityAttribute, value))
					.collect(Collectors.toList()));
	}
	
	private Map> fetchUserAttributes(FenixUserId fenixUserId) {
		return fetchUserAttributes(fenixUserId.id, IDENTIFIER_IDENTITY);
	}

	private Map> fetchUserAttributes(PersistentId persistentId) {
		return fetchUserAttributes(persistentId.id, PERSISTENT_IDENTITY);
	}

	private Map> fetchUserAttributes(String id, String identityType) {
		String path = UriComponentsBuilder.newInstance()
			.pathSegment(GROUP_ATTRIBUTES)
			.uriVariables(Map.of(ID, id))
			.build()
			.toUriString();

		try {
			return unityClient.getWithListParam(path, new ParameterizedTypeReference<>() {
				},
				Map.of("groupsPatterns", List.of("/", "/fenix/**/users"),
					"identityType", List.of(identityType)));
		} catch (WebClientResponseException e) {
			throw new UnityFailureException(e.getMessage(), e);
		}
	}

	private Set fetchUserGroups(FenixUserId fenixUserId) {
		return fetchUserGroups(fenixUserId.id, IDENTIFIER_IDENTITY);
	}

	private Set fetchUserGroups(PersistentId persistentId) {
		return fetchUserGroups(persistentId.id, PERSISTENT_IDENTITY);
	}

	private Set fetchUserGroups(String id, String identityType) {
		String path = UriComponentsBuilder.newInstance()
			.pathSegment(UnityPaths.ENTITY_GROUPS)
			.uriVariables(Map.of(ID, id))
			.build()
			.toUriString();

		try {
			return unityClient.get(path, new ParameterizedTypeReference<>() {
				},
				Map.of("identityType", identityType));
		} catch (WebClientResponseException e) {
			throw new UnityFailureException(e.getMessage(), e);
		}
	}

	private static Map> getResourceToAttributesMap(Map> attributes) {
		return attributes.values().stream()
			.flatMap(Collection::stream)
			.filter(usersGroupPredicate4Attr)
			.collect(Collectors.groupingBy(UnityGroupParser::attr2Resource, Collectors.toSet()))
			.entrySet().stream()
			.filter(mapEntry -> !mapEntry.getValue().isEmpty())
			.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy