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.ArrayList; import java.util.Base64; import java.util.HashMap; import java.util.List; 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; @Autowired private LoggingDAO loggingDAO; @Autowired(required = false) private HttpSession httpSession; public void addInvitedRegistration(String tokenHash, String email, Map groupsPermissions) { Map groupIdsPermissions = new HashMap<>(); for (Map.Entry 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> completeInvitedRegistrationIfNecessary() { List 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 completeInvitedRegistrationIfNecessary(String userId) { List invitedRegistrations = new ArrayList<>(); List 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 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 getInvitedRegistrationsForGroup(GroupEntity group) { if (permissionsManager.getCurrentUserPermission(group) != Permission.ADMIN) { return null; } List items = new ArrayList<>(); for (InvitedRegistration reg : invitedRegistrationDAO.getPendingInvitedRegistrationsForGroup(group.getId())) { Map 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() + "]"); } }