Skip to content
InvitedRegistrationManager.java 8.17 KiB
Newer Older
package it.inaf.ia2.gms.manager;

import it.inaf.ia2.gms.authn.SessionData;
import it.inaf.ia2.gms.exception.BadRequestException;
import it.inaf.ia2.gms.exception.NotFoundException;
import it.inaf.ia2.gms.exception.UnauthorizedException;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.model.response.InvitedRegistrationItem;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.InvitedRegistrationDAO;
import it.inaf.ia2.gms.persistence.LoggingDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.InvitedRegistration;
import it.inaf.ia2.gms.persistence.model.MembershipEntity;
import it.inaf.ia2.gms.service.PermissionsService;
import it.inaf.ia2.rap.client.RapClient;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class InvitedRegistrationManager extends UserAwareComponent {

    private static final String INVITED_REGISTRATION = "invited-registration";

    @Autowired
    private GroupsDAO groupsDAO;

    @Autowired
    private MembershipsDAO membershipsDAO;

    @Autowired
    private PermissionsService permissionsService;

    @Autowired
    private PermissionsManager permissionsManager;

    @Autowired
    private InvitedRegistrationDAO invitedRegistrationDAO;

    @Autowired
    private RapClient rapClient;

    @Autowired
    private SessionData sessionData;
    private LoggingDAO loggingDAO;

    @Autowired(required = false)
    private HttpSession httpSession;

    public void addInvitedRegistration(String tokenHash, String email, Map<GroupEntity, Permission> groupsPermissions) {

        Map<String, Permission> groupIdsPermissions = new HashMap<>();
        for (Map.Entry<GroupEntity, Permission> entry : groupsPermissions.entrySet()) {
            GroupEntity group = entry.getKey();
            if (permissionsManager.getCurrentUserPermission(group) != Permission.ADMIN) {
                throw new UnauthorizedException("You don't have the permission to perform invited registrations");
            }
            groupIdsPermissions.put(group.getId(), entry.getValue());
        }

        InvitedRegistration invitedRegistration = new InvitedRegistration()
                .setId(UUID.randomUUID().toString().replaceAll("-", ""))
                .setEmail(email)
                .setTokenHash(tokenHash)
                .setGroupsPermissions(groupIdsPermissions);

        invitedRegistrationDAO.addInvitedRegistration(invitedRegistration);
    }

    public InvitedRegistration getInvitedRegistrationFromToken(String token) {

        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(token.getBytes(StandardCharsets.UTF_8));
            String tokenHash = Base64.getEncoder().encodeToString(hash);

            InvitedRegistration invitedRegistration = invitedRegistrationDAO.getInvitedRegistrationFromToken(tokenHash)
                    .orElseThrow(() -> new NotFoundException("No invited registrations found for this token"));

            httpSession.setAttribute(INVITED_REGISTRATION, invitedRegistration);

            loggingDAO.logAction("Started invited registration for email " + invitedRegistration.getEmail());

            return invitedRegistration;
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException(ex);
        }
    }

    public Optional<List<InvitedRegistration>> completeInvitedRegistrationIfNecessary() {
        List<InvitedRegistration> invitedRegistrations = completeInvitedRegistrationIfNecessary(sessionData.getUserId());
        InvitedRegistration invitedRegistrationFromToken = (InvitedRegistration) httpSession.getAttribute(INVITED_REGISTRATION);
        if (invitedRegistrationFromToken != null) {
            boolean alreadyDone = invitedRegistrations.stream().map(reg -> reg.getId())
                    .anyMatch(id -> id.equals(invitedRegistrationFromToken.getId()));
            if (!alreadyDone) {
                completeInvitedRegistration(invitedRegistrationFromToken);
                invitedRegistrations.add(invitedRegistrationFromToken);
            httpSession.removeAttribute(INVITED_REGISTRATION);
        }
        return Optional.ofNullable(invitedRegistrations.isEmpty() ? null : invitedRegistrations);
    }
    /**
     * This method can be called from web service, since it doesn't rely on
     * session.
     */
    public List<InvitedRegistration> completeInvitedRegistrationIfNecessary(String userId) {

        List<InvitedRegistration> invitedRegistrations = new ArrayList<>();

        List<String> emailAddresses = rapClient.getUser(userId).getIdentities().stream()
                .map(identity -> identity.getEmail())
                .collect(Collectors.toList());

        for (InvitedRegistration invitedRegistration : invitedRegistrationDAO.getInvitedRegistrationsFromEmailAddresses(emailAddresses)) {
            completeInvitedRegistration(invitedRegistration);
            invitedRegistrations.add(invitedRegistration);
        }

        return invitedRegistrations;
    }

    private void completeInvitedRegistration(InvitedRegistration invitedRegistration) {
        for (Map.Entry<String, Permission> entry : invitedRegistration.getGroupsPermissions().entrySet()) {
            String groupId = entry.getKey();
            String userId = getCurrentUserId();

            GroupEntity groupEntity = groupsDAO.findGroupById(groupId).get();

            MembershipEntity membershipEntity = new MembershipEntity();
            membershipEntity.setUserId(userId);
            membershipEntity.setGroupId(groupId);
            membershipsDAO.addMember(membershipEntity);

            permissionsService.addPermission(groupEntity, userId, entry.getValue());
        invitedRegistration.setUserId(getCurrentUserId());
        // FIXME (workaround): separated update for user and done in order to use triggers
        invitedRegistrationDAO.setRegistrationUser(invitedRegistration);
        invitedRegistrationDAO.setRegistrationDone(invitedRegistration);

    public List<InvitedRegistrationItem> getInvitedRegistrationsForGroup(GroupEntity group) {

        if (permissionsManager.getCurrentUserPermission(group) != Permission.ADMIN) {
            return null;
        }

        List<InvitedRegistrationItem> items = new ArrayList<>();

        for (InvitedRegistration reg : invitedRegistrationDAO.getPendingInvitedRegistrationsForGroup(group.getId())) {

            Map<String, Permission> map = reg.getGroupsPermissions();

            if (map != null) {
                for (Permission permission : map.values()) {
                    InvitedRegistrationItem item = new InvitedRegistrationItem()
                            .setId(reg.getId())
                            .setEmail(reg.getEmail())
                            .setPermission(permission)
                            .setCreationTime(reg.getCreationTime());
                    items.add(item);
                }
            }
        }

        return items;
    }

    public void deleteInvitedRegistration(String registrationId, String groupId) {

        GroupEntity group = groupsDAO.findGroupById(groupId)
                .orElseThrow(() -> new BadRequestException("No group found for given id: " + groupId));

        if (permissionsManager.getUserPermission(group, getCurrentUserId()) != Permission.ADMIN) {
            throw new UnauthorizedException("Only administrators can delete invited registrations!");
        }

        invitedRegistrationDAO.deleteInvitedRegistrationRequest(registrationId, groupId);

        loggingDAO.logAction("Deleted invited registration request. "
                + "[request_id=" + registrationId + ", group_id=" + groupId
                + ", group_name=" + group.getName() + "]");
    }