/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package edu.harvard.iq.dataverse; import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean; import edu.harvard.iq.dataverse.authorization.DataverseRole; import edu.harvard.iq.dataverse.authorization.Permission; import edu.harvard.iq.dataverse.authorization.RoleAssignee; import edu.harvard.iq.dataverse.authorization.RoleAssigneeDisplayInfo; import edu.harvard.iq.dataverse.authorization.groups.Group; import edu.harvard.iq.dataverse.authorization.groups.GroupServiceBean; import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; import edu.harvard.iq.dataverse.engine.command.impl.AssignRoleCommand; import edu.harvard.iq.dataverse.engine.command.impl.RevokeRoleCommand; import edu.harvard.iq.dataverse.util.JsfHelper; import static edu.harvard.iq.dataverse.util.JsfHelper.JH; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.EJB; import javax.faces.application.FacesMessage; import javax.faces.event.ActionEvent; import javax.faces.view.ViewScoped; import javax.inject.Inject; import javax.inject.Named; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.apache.commons.lang.StringUtils; import org.primefaces.event.SelectEvent; import org.primefaces.event.ToggleSelectEvent; import org.primefaces.event.UnselectEvent; /** * * @author gdurand */ @ViewScoped @Named public class ManageFilePermissionsPage implements java.io.Serializable { private static final Logger logger = Logger.getLogger(ManageFilePermissionsPage.class.getCanonicalName()); @EJB DatasetServiceBean datasetService; @EJB DataFileServiceBean datafileService; @EJB DataverseRoleServiceBean roleService; @EJB RoleAssigneeServiceBean roleAssigneeService; @EJB PermissionServiceBean permissionService; @EJB AuthenticationServiceBean authenticationService; @EJB ExplicitGroupServiceBean explicitGroupService; @EJB GroupServiceBean groupService; @EJB UserNotificationServiceBean userNotificationService; @EJB EjbDataverseEngine commandEngine; @Inject DataverseRequestServiceBean dvRequestService; @Inject PermissionsWrapper permissionsWrapper; @PersistenceContext(unitName = "VDCNet-ejbPU") EntityManager em; @Inject DataverseSession session; Dataset dataset = new Dataset(); private final TreeMap<RoleAssignee,List<RoleAssignmentRow>> roleAssigneeMap = new TreeMap<>(); private final TreeMap<DataFile,List<RoleAssignmentRow>> fileMap = new TreeMap<>(); private final TreeMap<AuthenticatedUser,List<DataFile>> fileAccessRequestMap = new TreeMap<>(); public Dataset getDataset() { return dataset; } public void setDataset(Dataset dataset) { this.dataset = dataset; } public TreeMap<RoleAssignee, List<RoleAssignmentRow>> getRoleAssigneeMap() { return roleAssigneeMap; } public TreeMap<DataFile, List<RoleAssignmentRow>> getFileMap() { return fileMap; } public TreeMap<AuthenticatedUser, List<DataFile>> getFileAccessRequestMap() { return fileAccessRequestMap; } public String init() { if (dataset.getId() != null) { dataset = datasetService.find(dataset.getId()); } // check if dvObject exists and user has permission if (dataset == null) { return permissionsWrapper.notFound(); } if (!permissionService.on(dataset).has(Permission.ManageDatasetPermissions)) { return permissionsWrapper.notAuthorized(); } initMaps(); return ""; } private void initMaps() { // initialize files and usergroup list roleAssigneeMap.clear(); fileMap.clear(); fileAccessRequestMap.clear(); for (DataFile file : dataset.getFiles()) { // only include if the file is restricted (or it's draft version is restricted) //Added a null check in case there are files that have no metadata records SEK if (file.getFileMetadata() != null && (file.isRestricted() || file.getFileMetadata().isRestricted())) { // we get the direct role assignments assigned to the file List<RoleAssignment> ras = roleService.directRoleAssignments(file); List<RoleAssignmentRow> raList = new ArrayList<>(ras.size()); for (RoleAssignment ra : ras) { // for files, only show role assignments which can download if (ra.getRole().permissions().contains(Permission.DownloadFile)) { raList.add(new RoleAssignmentRow(ra, roleAssigneeService.getRoleAssignee(ra.getAssigneeIdentifier()).getDisplayInfo())); addFileToRoleAssignee(ra); } } fileMap.put(file, raList); // populate the file access requests map for (AuthenticatedUser au : file.getFileAccessRequesters()) { List<DataFile> requestedFiles = fileAccessRequestMap.get(au); if (requestedFiles == null) { requestedFiles = new ArrayList<>(); fileAccessRequestMap.put(au, requestedFiles); } requestedFiles.add(file); } } } } private void addFileToRoleAssignee(RoleAssignment assignment) { RoleAssignee ra = roleAssigneeService.getRoleAssignee(assignment.getAssigneeIdentifier()); List<RoleAssignmentRow> assignments = roleAssigneeMap.get(ra); if (assignments == null) { assignments = new ArrayList<>(); roleAssigneeMap.put(ra, assignments); } assignments.add(new RoleAssignmentRow(assignment, ra.getDisplayInfo())); } /* main page */ public void removeRoleAssignments(List<RoleAssignmentRow> raRows) { for (RoleAssignmentRow raRow : raRows) { revokeRole(raRow.getId()); } initMaps(); showUserGroupMessages(); } /* view / remove roles dialog */ private DataFile selectedFile; private RoleAssignee selectedRoleAssignee; private List<RoleAssignmentRow> roleAssignments; private List<RoleAssignmentRow> selectedRoleAssignmentRows; public DataFile getSelectedFile() { return selectedFile; } public void setSelectedFile(DataFile selectedFile) { this.selectedFile = selectedFile; } public RoleAssignee getSelectedRoleAssignee() { return selectedRoleAssignee; } public void setSelectedRoleAssignee(RoleAssignee selectedRoleAssignee) { this.selectedRoleAssignee = selectedRoleAssignee; } public List<RoleAssignmentRow> getRoleAssignments() { return roleAssignments; } public void setRoleAssignments(List<RoleAssignmentRow> roleAssignments) { this.roleAssignments = roleAssignments; } public List<RoleAssignmentRow> getSelectedRoleAssignmentRows() { return selectedRoleAssignmentRows; } public void setSelectedRoleAssignmentRows(List<RoleAssignmentRow> selectedRoleAssignmentRows) { this.selectedRoleAssignmentRows = selectedRoleAssignmentRows; } public void initViewRemoveDialogByFile(DataFile file, List<RoleAssignmentRow> raRows) { setSelectedRoleAssignmentRows(new ArrayList()); this.selectedFile = file; this.selectedRoleAssignee = null; this.roleAssignments = raRows; showFileMessages(); } public void initViewRemoveDialogByRoleAssignee(RoleAssignee ra, List<RoleAssignmentRow> raRows) { setSelectedRoleAssignmentRows(new ArrayList()); this.selectedFile = null; this.selectedRoleAssignee = ra; this.roleAssignments = raRows; showUserGroupMessages(); } public void removeRoleAssignments() { for (RoleAssignmentRow raRow : selectedRoleAssignmentRows) { revokeRole(raRow.getId()); } initMaps(); } // internal method used by removeRoleAssignments private void revokeRole(Long roleAssignmentId) { try { RoleAssignment ra = em.find(RoleAssignment.class, roleAssignmentId); commandEngine.submit(new RevokeRoleCommand(ra, dvRequestService.getDataverseRequest())); JsfHelper.addSuccessMessage(ra.getRole().getName() + " role for " + roleAssigneeService.getRoleAssignee(ra.getAssigneeIdentifier()).getDisplayInfo().getTitle() + " was removed."); } catch (PermissionException ex) { JH.addMessage(FacesMessage.SEVERITY_ERROR, "The role assignment was not able to be removed.", "Permissions " + ex.getRequiredPermissions().toString() + " missing."); } catch (CommandException ex) { JH.addMessage(FacesMessage.SEVERITY_FATAL, "The role assignment could not be removed."); logger.log(Level.SEVERE, "Error removing role assignment: " + ex.getMessage(), ex); } } /* grant access dialog */ private List<RoleAssignee> selectedRoleAssignees; private List<DataFile> selectedFiles = new ArrayList<>(); private AuthenticatedUser fileRequester; public List<RoleAssignee> getSelectedRoleAssignees() { return selectedRoleAssignees; } public void setSelectedRoleAssignees(List<RoleAssignee> selectedRoleAssignees) { this.selectedRoleAssignees = selectedRoleAssignees; } public List<DataFile> getSelectedFiles() { return selectedFiles; } public void setSelectedFiles(List<DataFile> selectedFiles) { this.selectedFiles = selectedFiles; } public AuthenticatedUser getFileRequester() { return fileRequester; } public void initAssignDialog(ActionEvent ae) { fileRequester = null; selectedRoleAssignees = null; selectedFiles.clear(); showUserGroupMessages(); } public void initAssignDialogByFile(DataFile file) { fileRequester = null; selectedRoleAssignees = null; selectedFiles.clear(); selectedFiles.add(file); showFileMessages(); } public void initAssignDialogForFileRequester(AuthenticatedUser au) { fileRequester = au; selectedRoleAssignees = null; selectedFiles.clear(); selectedFiles.addAll(fileAccessRequestMap.get(au)); showUserGroupMessages(); } public List<RoleAssignee> completeRoleAssignee(String query) { return roleAssigneeService.filterRoleAssignees(query, dataset, selectedRoleAssignees); } public void grantAccess(ActionEvent evt) { // Find the built in file downloader role (currently by alias) DataverseRole fileDownloaderRole = roleService.findBuiltinRoleByAlias(DataverseRole.FILE_DOWNLOADER); for (RoleAssignee roleAssignee : selectedRoleAssignees) { boolean sendNotification = false; for (DataFile file : selectedFiles) { if (assignRole(roleAssignee, file, fileDownloaderRole)) { if (file.isReleased()) { sendNotification = true; } // remove request, if it exist if (file.getFileAccessRequesters().remove(roleAssignee)) { datafileService.save(file); } } } if (sendNotification) { for (AuthenticatedUser au : roleAssigneeService.getExplicitUsers(roleAssignee)) { userNotificationService.sendNotification(au, new Timestamp(new Date().getTime()), UserNotification.Type.GRANTFILEACCESS, dataset.getId()); } } } initMaps(); } public void grantAccessToRequests(AuthenticatedUser au) { grantAccessToRequests(au, selectedFiles); } public void grantAccessToAllRequests(AuthenticatedUser au) { grantAccessToRequests(au, fileAccessRequestMap.get(au)); } private void grantAccessToRequests(AuthenticatedUser au, List<DataFile> files) { boolean actionPerformed = false; // Find the built in file downloader role (currently by alias) DataverseRole fileDownloaderRole = roleService.findBuiltinRoleByAlias(DataverseRole.FILE_DOWNLOADER); for (DataFile file : files) { if (assignRole(au, file, fileDownloaderRole)) { file.getFileAccessRequesters().remove(au); datafileService.save(file); actionPerformed = true; } } if (actionPerformed) { JsfHelper.addSuccessMessage("File Access request by " + au.getDisplayInfo().getTitle() + " was granted."); userNotificationService.sendNotification(au, new Timestamp(new Date().getTime()), UserNotification.Type.GRANTFILEACCESS, dataset.getId()); initMaps(); } } public void rejectAccessToRequests(AuthenticatedUser au) { rejectAccessToRequests(au, selectedFiles); } public void rejectAccessToAllRequests(AuthenticatedUser au) { rejectAccessToRequests(au, fileAccessRequestMap.get(au)); } private void rejectAccessToRequests(AuthenticatedUser au, List<DataFile> files) { boolean actionPerformed = false; for (DataFile file : files) { file.getFileAccessRequesters().remove(au); datafileService.save(file); actionPerformed = true; } if (actionPerformed) { JsfHelper.addSuccessMessage("File Access request by " + au.getDisplayInfo().getTitle() + " was rejected."); userNotificationService.sendNotification(au, new Timestamp(new Date().getTime()), UserNotification.Type.REJECTFILEACCESS, dataset.getId()); initMaps(); } } private boolean assignRole(RoleAssignee ra, DataFile file, DataverseRole r) { try { String privateUrlToken = null; commandEngine.submit(new AssignRoleCommand(ra, r, file, dvRequestService.getDataverseRequest(), privateUrlToken)); JsfHelper.addSuccessMessage(r.getName() + " role assigned to " + ra.getDisplayInfo().getTitle() + " for " + file.getDisplayName() + "."); } catch (PermissionException ex) { JH.addMessage(FacesMessage.SEVERITY_ERROR, "The role was not able to be assigned.", "Permissions " + ex.getRequiredPermissions().toString() + " missing."); return false; } catch (CommandException ex) { //JH.addMessage(FacesMessage.SEVERITY_FATAL, "The role was not able to be assigned."); String message = r.getName() + " role could NOT be assigned to " + ra.getDisplayInfo().getTitle() + " for " + file.getDisplayName() + "."; JsfHelper.addErrorMessage(message); logger.log(Level.SEVERE, "Error assiging role: " + ex.getMessage(), ex); return false; } return true; } boolean renderUserGroupMessages = false; boolean renderFileMessages = false; public void showUserGroupMessages() { renderUserGroupMessages = true; renderFileMessages = false; } private void showFileMessages() { renderUserGroupMessages = false; renderFileMessages = true; } public boolean isRenderUserGroupMessages() { return renderUserGroupMessages; } public void setRenderUserGroupMessages(boolean renderUserGroupMessages) { this.renderUserGroupMessages = renderUserGroupMessages; } public boolean isRenderFileMessages() { return renderFileMessages; } public void setRenderFileMessages(boolean renderFileMessages) { this.renderFileMessages = renderFileMessages; } // inner class used fordisplay of role assignments public static class RoleAssignmentRow { private final RoleAssigneeDisplayInfo assigneeDisplayInfo; private final RoleAssignment ra; public RoleAssignmentRow(RoleAssignment anRa, RoleAssigneeDisplayInfo disInf) { this.ra = anRa; this.assigneeDisplayInfo = disInf; } public RoleAssigneeDisplayInfo getAssigneeDisplayInfo() { return assigneeDisplayInfo; } public DvObject getDefinitionPoint() { return ra.getDefinitionPoint(); } public Long getId() { return ra.getId(); } } }