package edu.harvard.iq.dataverse;
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
import edu.harvard.iq.dataverse.authorization.RoleAssignee;
import edu.harvard.iq.dataverse.authorization.groups.Group;
import edu.harvard.iq.dataverse.authorization.groups.GroupException;
import edu.harvard.iq.dataverse.authorization.groups.GroupServiceBean;
import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroup;
import edu.harvard.iq.dataverse.authorization.groups.impl.explicit.ExplicitGroupServiceBean;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.impl.CreateExplicitGroupCommand;
import edu.harvard.iq.dataverse.engine.command.impl.DeleteExplicitGroupCommand;
import edu.harvard.iq.dataverse.engine.command.impl.UpdateExplicitGroupCommand;
import edu.harvard.iq.dataverse.util.JsfHelper;
import static edu.harvard.iq.dataverse.util.JsfHelper.JH;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
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;
/**
* @author michaelsuo
*/
@ViewScoped
@Named
public class ManageGroupsPage implements java.io.Serializable {
private static final Logger logger = Logger.getLogger(ManageGroupsPage.class.getCanonicalName());
@EJB
DataverseServiceBean dataverseService;
@EJB
ExplicitGroupServiceBean explicitGroupService;
@EJB
EjbDataverseEngine engineService;
@EJB
RoleAssigneeServiceBean roleAssigneeService;
@EJB
AuthenticationServiceBean authenticationService;
@EJB
GroupServiceBean groupService;
@Inject
DataverseRequestServiceBean dvRequestService;
@Inject
PermissionsWrapper permissionsWrapper;
@PersistenceContext(unitName = "VDCNet-ejbPU")
EntityManager em;
@Inject
DataversePage dvpage;
@Inject
GuestbookPage guestbookPage;
@Inject
DataverseSession session;
private List<ExplicitGroup> explicitGroups;
private Dataverse dataverse;
private Long dataverseId;
private ExplicitGroup selectedGroup = null;
public String init() {
setDataverse(dataverseService.find(getDataverseId()));
Dataverse editDv = getDataverse();
dvpage.setDataverse(editDv);
if (editDv == null) {
return permissionsWrapper.notFound();
}
Boolean hasPermissions = permissionsWrapper.canIssueCommand(editDv, CreateExplicitGroupCommand.class);
hasPermissions |= permissionsWrapper.canIssueCommand(editDv, DeleteExplicitGroupCommand.class);
hasPermissions |= permissionsWrapper.canIssueCommand(editDv, UpdateExplicitGroupCommand.class);
if (!hasPermissions) {
return permissionsWrapper.notAuthorized();
}
explicitGroups = new LinkedList<>(explicitGroupService.findByOwner(getDataverseId()));
return null;
}
public void setSelectedGroup(ExplicitGroup selectedGroup) {
this.selectedGroup = selectedGroup;
}
public List<ExplicitGroup> getExplicitGroups() {
return explicitGroups;
}
public void setExplicitGroups(List<ExplicitGroup> explicitGroups) {
this.explicitGroups = explicitGroups;
}
public Dataverse getDataverse() {
return dataverse;
}
public void setDataverse(Dataverse dataverse) {
this.dataverse = dataverse;
}
public Long getDataverseId() {
return dataverseId;
}
public void setDataverseId(Long dataverseId) {
this.dataverseId = dataverseId;
}
public Group getSelectedGroup() {
return selectedGroup;
}
public void deleteGroup() {
if (selectedGroup != null) {
explicitGroups.remove(selectedGroup);
try {
engineService.submit(new DeleteExplicitGroupCommand(dvRequestService.getDataverseRequest(), selectedGroup));
JsfHelper.addFlashMessage("The group has been deleted.");
} catch (CommandException ex) {
String failMessage = "The explicit group cannot be deleted.";
JH.addMessage(FacesMessage.SEVERITY_FATAL, failMessage);
}
} else {
logger.info("Selected group is null");
}
}
private List<RoleAssignee> selectedGroupRoleAssignees = new ArrayList<>();
public void setSelectedGroupRoleAssignees(List<RoleAssignee> newSelectedGroupRoleAssignees) {
this.selectedGroupRoleAssignees = newSelectedGroupRoleAssignees;
}
public List<RoleAssignee> getSelectedGroupRoleAssignees() {
return this.selectedGroupRoleAssignees;
}
private List<RoleAssignee> selectedGroupAddRoleAssignees;
public void setSelectedGroupAddRoleAssignees(List<RoleAssignee> ras) {
this.selectedGroupAddRoleAssignees = ras;
}
public List<RoleAssignee> getSelectedGroupAddRoleAssignees() {
return this.selectedGroupAddRoleAssignees;
}
public void viewSelectedGroup(ExplicitGroup selectedGroup) {
this.selectedGroup = selectedGroup;
// initialize member list for autocomplete interface
setSelectedGroupAddRoleAssignees(new LinkedList<>());
setSelectedGroupRoleAssignees(getExplicitGroupMembers(selectedGroup));
}
/**
* Return the set of all role assignees for an explicit group.
* Does not traverse subgroups.
* @param eg The explicit group to check.
* @return The set of role assignees belonging to explicit group.
*/
public List<RoleAssignee> getExplicitGroupMembers(ExplicitGroup eg) {
return (eg != null) ?
new ArrayList(eg.getDirectMembers()) : null;
}
/**
* Return a string describing the type of a role assignee
* TODO reference the bundle for localization
* @param ra The role assignee
* @return A {@code String} representing the role assignee's type.
*/
public String getRoleAssigneeTypeString(RoleAssignee ra) {
if (ra instanceof User) {
return "User";
} else if (ra instanceof Group) {
return "Group";
} else {
return "unknown";
}
}
public String getMembershipString(ExplicitGroup eg) {
long userCount = 0;
long groupCount = 0;
for ( RoleAssignee ra : eg.getDirectMembers() ) {
if ( ra instanceof User ) {
userCount++;
} else {
groupCount++;
}
}
if (userCount == 0 && groupCount == 0) {
return "No members";
}
String memberString = "";
if (userCount == 1) {
memberString = "1 user";
} else if (userCount != 1) {
memberString = Long.toString(userCount) + " users";
}
if (groupCount == 1) {
memberString = memberString + ", 1 group";
} else if (groupCount != 1) {
memberString = memberString + ", " + Long.toString(groupCount) + " groups";
}
return memberString;
}
public void removeMemberFromSelectedGroup(RoleAssignee ra) {
selectedGroup.remove(ra);
}
public List<RoleAssignee> completeRoleAssignee( String query ) {
List<RoleAssignee> alreadyAssignedRoleAssignees = new ArrayList<>();
if (this.getNewExplicitGroupRoleAssignees() != null) {
alreadyAssignedRoleAssignees.addAll(this.getNewExplicitGroupRoleAssignees());
}
if (this.getSelectedGroupRoleAssignees() != null) {
alreadyAssignedRoleAssignees.addAll(this.getSelectedGroupRoleAssignees());
}
if (this.getSelectedGroupAddRoleAssignees() != null) {
alreadyAssignedRoleAssignees.addAll(this.getSelectedGroupAddRoleAssignees());
}
return roleAssigneeService.filterRoleAssignees(query, dataverse, alreadyAssignedRoleAssignees);
}
/*
============================================================================
Explicit Group dialogs
============================================================================
*/
String explicitGroupIdentifier = "";
String explicitGroupName = "";
String newExplicitGroupDescription = "";
UIInput explicitGroupIdentifierField;
List<RoleAssignee> newExplicitGroupRoleAssignees = new LinkedList<>();
public void initExplicitGroupDialog(ActionEvent ae) {
showNoMessages();
setExplicitGroupName("");
setExplicitGroupIdentifier("");
setNewExplicitGroupDescription("");
setNewExplicitGroupRoleAssignees(new LinkedList<>());
FacesContext context = FacesContext.getCurrentInstance();
setSelectedGroupRoleAssignees(null);
}
public void createExplicitGroup(ActionEvent ae) {
ExplicitGroup eg = explicitGroupService.getProvider().makeGroup();
eg.setDisplayName( getExplicitGroupName() );
eg.setGroupAliasInOwner( getExplicitGroupIdentifier() );
eg.setDescription( getNewExplicitGroupDescription() );
if ( getNewExplicitGroupRoleAssignees()!= null ) {
try {
for ( RoleAssignee ra : getNewExplicitGroupRoleAssignees() ) {
eg.add( ra );
}
} catch ( GroupException ge ) {
JsfHelper.JH.addMessage(FacesMessage.SEVERITY_ERROR,
"Group Creation failed.",
ge.getMessage());
return;
}
}
try {
eg = engineService.submit( new CreateExplicitGroupCommand(dvRequestService.getDataverseRequest(), this.dataverse, eg));
explicitGroups.add(eg);
JsfHelper.addSuccessMessage("Succesfully created group " + eg.getDisplayName() + ". Refresh to update your page.");
} catch ( CreateExplicitGroupCommand.GroupAliasExistsException gaee ) {
explicitGroupIdentifierField.setValid( false );
FacesContext.getCurrentInstance().addMessage(explicitGroupIdentifierField.getClientId(),
new FacesMessage( FacesMessage.SEVERITY_ERROR, gaee.getMessage(), null));
} catch (CommandException ex) {
logger.log(Level.WARNING, "Group creation failed", ex);
JsfHelper.JH.addMessage(FacesMessage.SEVERITY_ERROR,
"Group Creation failed.",
ex.getMessage());
} catch (Exception ex) {
JH.addMessage(FacesMessage.SEVERITY_FATAL, "The role was not able to be saved.");
logger.log(Level.SEVERE, "Error saving role: " + ex.getMessage(), ex);
}
showAssignmentMessages();
}
public void saveExplicitGroup(ActionEvent ae) {
ExplicitGroup eg = selectedGroup;
if ( getSelectedGroupAddRoleAssignees() != null ) {
try {
for ( RoleAssignee ra : getSelectedGroupAddRoleAssignees() ) {
eg.add( ra );
}
} catch ( GroupException ge ) {
JsfHelper.JH.addMessage(FacesMessage.SEVERITY_ERROR,
"Group edit failed.",
ge.getMessage());
return;
}
}
try {
eg = engineService.submit( new UpdateExplicitGroupCommand(dvRequestService.getDataverseRequest(), eg));
JsfHelper.addSuccessMessage("Succesfully saved group " + eg.getDisplayName());
} catch (CommandException ex) {
JsfHelper.JH.addMessage(FacesMessage.SEVERITY_ERROR,
"Group Save failed.",
ex.getMessage());
} catch (Exception ex) {
JH.addMessage(FacesMessage.SEVERITY_FATAL, "The role was not able to be saved.");
logger.log(Level.SEVERE, "Error saving role: " + ex.getMessage(), ex);
}
showAssignmentMessages();
}
public void setExplicitGroupName(String explicitGroupFriendlyName) {
this.explicitGroupName = explicitGroupFriendlyName;
}
public String getExplicitGroupName() {
return explicitGroupName;
}
public void setExplicitGroupIdentifier(String explicitGroupName) {
this.explicitGroupIdentifier = explicitGroupName;
}
public String getExplicitGroupIdentifier() {
return explicitGroupIdentifier;
}
public UIInput getExplicitGroupIdentifierField() {
return explicitGroupIdentifierField;
}
public void setExplicitGroupIdentifierField(UIInput explicitGroupIdentifierField) {
this.explicitGroupIdentifierField = explicitGroupIdentifierField;
}
public void validateGroupIdentifier(FacesContext context, UIComponent toValidate, Object rawValue) {
String value = (String) rawValue;
UIInput input = (UIInput) toValidate;
input.setValid(true); // Optimistic approach
if ( context.getExternalContext().getRequestParameterMap().get("DO_GROUP_VALIDATION") != null
&& !StringUtils.isEmpty(value) ) {
// cheap test - regex
if (! Pattern.matches("^[a-zA-Z0-9\\_\\-]+$", value) ) {
input.setValid(false);
context.addMessage(toValidate.getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("dataverse.permissions.explicitGroupEditDialog.groupIdentifier.invalid")));
} else if ( explicitGroupService.findInOwner(dataverse.getId(), value) != null ) {
// Ok, see that the alias is not taken
input.setValid(false);
context.addMessage(toValidate.getClientId(),
new FacesMessage(FacesMessage.SEVERITY_ERROR, "", JH.localize("dataverse.permissions.explicitGroupEditDialog.groupIdentifier.taken")));
}
}
}
public void setNewExplicitGroupRoleAssignees(List<RoleAssignee> newExplicitGroupRoleAssignees) {
this.newExplicitGroupRoleAssignees = newExplicitGroupRoleAssignees;
}
public List<RoleAssignee> getNewExplicitGroupRoleAssignees() {
return newExplicitGroupRoleAssignees;
}
public String getNewExplicitGroupDescription() {
return newExplicitGroupDescription;
}
public void setNewExplicitGroupDescription(String newExplicitGroupDescription) {
this.newExplicitGroupDescription = newExplicitGroupDescription;
}
/*
============================================================================
Internal methods
============================================================================
*/
boolean renderConfigureMessages = false;
boolean renderAssignmentMessages = false;
boolean renderRoleMessages = false;
private void showNoMessages() {
renderConfigureMessages = false;
renderAssignmentMessages = false;
renderRoleMessages = false;
}
private void showAssignmentMessages() {
renderConfigureMessages = false;
renderAssignmentMessages = true;
renderRoleMessages = false;
}
}