/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.wui.client.browse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.roda.core.data.common.RodaConstants;
import org.roda.core.data.v2.index.filter.Filter;
import org.roda.core.data.v2.index.filter.NotSimpleFilterParameter;
import org.roda.core.data.v2.index.select.SelectedItems;
import org.roda.core.data.v2.ip.HasPermissions;
import org.roda.core.data.v2.ip.IndexedAIP;
import org.roda.core.data.v2.ip.IndexedDIP;
import org.roda.core.data.v2.ip.Permissions;
import org.roda.core.data.v2.ip.Permissions.PermissionType;
import org.roda.core.data.v2.user.RODAMember;
import org.roda.wui.client.common.LastSelectedItemsSingleton;
import org.roda.wui.client.common.LoadingAsyncCallback;
import org.roda.wui.client.common.UserLogin;
import org.roda.wui.client.common.dialogs.Dialogs;
import org.roda.wui.client.common.dialogs.MemberSelectDialog;
import org.roda.wui.client.common.lists.utils.ClientSelectedItemsUtils;
import org.roda.wui.client.common.utils.JavascriptUtils;
import org.roda.wui.common.client.HistoryResolver;
import org.roda.wui.common.client.tools.HistoryUtils;
import org.roda.wui.common.client.tools.ListUtils;
import org.roda.wui.common.client.widgets.HTMLWidgetWrapper;
import org.roda.wui.common.client.widgets.Toast;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import config.i18n.client.ClientMessages;
public class EditPermissions extends Composite {
public static final HistoryResolver AIP_RESOLVER = new HistoryResolver() {
@Override
public void resolve(List<String> historyTokens, final AsyncCallback<Widget> callback) {
if (historyTokens.size() == 1) {
final String aipId = historyTokens.get(0);
BrowserService.Util.getInstance().retrieve(IndexedAIP.class.getName(), aipId,
RodaConstants.AIP_PERMISSIONS_FIELDS_TO_RETURN, new AsyncCallback<IndexedAIP>() {
@Override
public void onFailure(Throwable caught) {
HistoryUtils.newHistory(BrowseAIP.RESOLVER);
callback.onSuccess(null);
}
@Override
public void onSuccess(IndexedAIP aip) {
EditPermissions edit = new EditPermissions(IndexedAIP.class.getName(), aip);
callback.onSuccess(edit);
}
});
} else if (historyTokens.isEmpty()) {
LastSelectedItemsSingleton selectedItems = LastSelectedItemsSingleton.getInstance();
final SelectedItems<IndexedAIP> selected = (SelectedItems<IndexedAIP>) selectedItems.getSelectedItems();
if (!ClientSelectedItemsUtils.isEmpty(selected)) {
BrowserService.Util.getInstance().retrieve(IndexedAIP.class.getName(), selected,
RodaConstants.AIP_PERMISSIONS_FIELDS_TO_RETURN, new AsyncCallback<List<IndexedAIP>>() {
@Override
public void onFailure(Throwable caught) {
HistoryUtils.newHistory(BrowseAIP.RESOLVER);
callback.onSuccess(null);
}
@Override
public void onSuccess(List<IndexedAIP> aips) {
List<? extends HasPermissions> hasPermissionsObjects = aips;
EditPermissions edit = new EditPermissions(IndexedAIP.class.getName(), hasPermissionsObjects);
callback.onSuccess(edit);
}
});
}
} else {
HistoryUtils.newHistory(BrowseAIP.RESOLVER);
callback.onSuccess(null);
}
}
@Override
public void isCurrentUserPermitted(AsyncCallback<Boolean> callback) {
UserLogin.getInstance().checkRoles(new HistoryResolver[] {EditPermissions.AIP_RESOLVER}, false, callback);
}
@Override
public List<String> getHistoryPath() {
return ListUtils.concat(BrowseAIP.RESOLVER.getHistoryPath(), getHistoryToken());
}
@Override
public String getHistoryToken() {
return "edit_permissions";
}
};
public static final HistoryResolver DIP_RESOLVER = new HistoryResolver() {
@Override
public void resolve(List<String> historyTokens, final AsyncCallback<Widget> callback) {
if (historyTokens.size() == 1) {
final String dipId = historyTokens.get(0);
BrowserService.Util.getInstance().retrieve(IndexedDIP.class.getName(), dipId,
RodaConstants.DIP_PERMISSIONS_FIELDS_TO_RETURN, new AsyncCallback<IndexedDIP>() {
@Override
public void onFailure(Throwable caught) {
HistoryUtils.newHistory(BrowseDIP.RESOLVER, dipId);
callback.onSuccess(null);
}
@Override
public void onSuccess(IndexedDIP dip) {
EditPermissions edit = new EditPermissions(IndexedDIP.class.getName(), dip);
callback.onSuccess(edit);
}
});
} else if (historyTokens.isEmpty()) {
LastSelectedItemsSingleton selectedItems = LastSelectedItemsSingleton.getInstance();
final SelectedItems<IndexedDIP> selected = (SelectedItems<IndexedDIP>) selectedItems.getSelectedItems();
if (!ClientSelectedItemsUtils.isEmpty(selected)) {
BrowserService.Util.getInstance().retrieve(IndexedDIP.class.getName(), selected,
RodaConstants.DIP_PERMISSIONS_FIELDS_TO_RETURN, new AsyncCallback<List<IndexedDIP>>() {
@Override
public void onFailure(Throwable caught) {
HistoryUtils.newHistory(BrowseAIP.RESOLVER);
callback.onSuccess(null);
}
@Override
public void onSuccess(List<IndexedDIP> dips) {
List<? extends HasPermissions> hasPermissionsObjects = dips;
EditPermissions edit = new EditPermissions(IndexedDIP.class.getName(), hasPermissionsObjects);
callback.onSuccess(edit);
}
});
}
} else {
HistoryUtils.newHistory(BrowseAIP.RESOLVER);
callback.onSuccess(null);
}
}
@Override
public void isCurrentUserPermitted(AsyncCallback<Boolean> callback) {
UserLogin.getInstance().checkRoles(new HistoryResolver[] {EditPermissions.DIP_RESOLVER}, false, callback);
}
@Override
public List<String> getHistoryPath() {
return ListUtils.concat(BrowseAIP.RESOLVER.getHistoryPath(), getHistoryToken());
}
@Override
public String getHistoryToken() {
return "edit_dip_permissions";
}
};
interface MyUiBinder extends UiBinder<Widget, EditPermissions> {
}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private static ClientMessages messages = GWT.create(ClientMessages.class);
@UiField
FlowPanel editPermissionsDescription;
@UiField
Label userPermissionsEmpty, groupPermissionsEmpty;
@UiField
FlowPanel userPermissionsPanel, groupPermissionsPanel;
@UiField
Button buttonApplyToAll;
private List<HasPermissions> objects = new ArrayList<>();
private String objectClass = null;
public EditPermissions(String objectClass, HasPermissions object) {
this.objects.add(object);
this.objectClass = objectClass;
initWidget(uiBinder.createAndBindUi(this));
buttonApplyToAll.setVisible(IndexedAIP.class.getName().equals(objectClass));
createPermissionPanel();
}
public EditPermissions(String objectClass, List<? extends HasPermissions> list) {
this.objects.addAll(list);
this.objectClass = objectClass;
initWidget(uiBinder.createAndBindUi(this));
buttonApplyToAll.setVisible(IndexedAIP.class.getName().equals(objectClass));
editPermissionsDescription.add(new HTMLWidgetWrapper("EditPermissionsDescription.html"));
createPermissionPanelList();
}
@Override
protected void onLoad() {
super.onLoad();
JavascriptUtils.stickSidebar();
}
private void createPermissionPanelList() {
Map<String, Set<PermissionType>> userPermissionsToShow = new HashMap<>();
Map<String, Set<PermissionType>> groupPermissionsToShow = new HashMap<>();
if (!objects.isEmpty()) {
Permissions firstAIPPermissions = objects.get(0).getPermissions();
for (String userName : firstAIPPermissions.getUsernames()) {
userPermissionsToShow.put(userName, firstAIPPermissions.getUserPermissions(userName));
}
for (String groupName : firstAIPPermissions.getGroupnames()) {
groupPermissionsToShow.put(groupName, firstAIPPermissions.getGroupPermissions(groupName));
}
for (int i = 1; i < objects.size(); i++) {
Permissions permissions = objects.get(i).getPermissions();
for (Iterator<Entry<String, Set<PermissionType>>> userIterator = userPermissionsToShow.entrySet()
.iterator(); userIterator.hasNext();) {
Entry<String, Set<PermissionType>> entry = userIterator.next();
if (permissions.getUsernames().contains(entry.getKey())) {
Set<PermissionType> userPermissionType = entry.getValue();
for (Iterator<PermissionType> permissionTypeIterator = userPermissionType.iterator(); permissionTypeIterator
.hasNext();) {
PermissionType permissionType = permissionTypeIterator.next();
if (!permissions.getUserPermissions(entry.getKey()).contains(permissionType)) {
permissionTypeIterator.remove();
}
}
} else {
userIterator.remove();
}
}
for (Iterator<Entry<String, Set<PermissionType>>> groupIterator = groupPermissionsToShow.entrySet()
.iterator(); groupIterator.hasNext();) {
Entry<String, Set<PermissionType>> entry = groupIterator.next();
if (permissions.getGroupnames().contains(entry.getKey())) {
Set<PermissionType> groupPermissionType = entry.getValue();
for (Iterator<PermissionType> permissionTypeIterator = groupPermissionType
.iterator(); permissionTypeIterator.hasNext();) {
PermissionType permissionType = permissionTypeIterator.next();
if (!permissions.getGroupPermissions(entry.getKey()).contains(permissionType)) {
permissionTypeIterator.remove();
}
}
} else {
groupIterator.remove();
}
}
}
}
userPermissionsEmpty.setVisible(userPermissionsToShow.isEmpty());
groupPermissionsEmpty.setVisible(groupPermissionsToShow.isEmpty());
for (Entry<String, Set<PermissionType>> entry : userPermissionsToShow.entrySet()) {
PermissionPanel permissionPanel = new PermissionPanel(entry.getKey(), true, entry.getValue());
userPermissionsPanel.add(permissionPanel);
bindUpdateEmptyVisibility(permissionPanel);
}
for (Entry<String, Set<PermissionType>> entry : groupPermissionsToShow.entrySet()) {
PermissionPanel permissionPanel = new PermissionPanel(entry.getKey(), false, entry.getValue());
groupPermissionsPanel.add(permissionPanel);
bindUpdateEmptyVisibility(permissionPanel);
}
}
private void createPermissionPanel() {
Permissions permissions = objects.get(0).getPermissions();
userPermissionsEmpty.setVisible(permissions.getUsernames().isEmpty());
groupPermissionsEmpty.setVisible(permissions.getGroupnames().isEmpty());
for (String username : permissions.getUsernames()) {
PermissionPanel permissionPanel = new PermissionPanel(username, true, permissions.getUserPermissions(username));
bindUpdateEmptyVisibility(permissionPanel);
userPermissionsPanel.add(permissionPanel);
}
for (String groupname : permissions.getGroupnames()) {
PermissionPanel permissionPanel = new PermissionPanel(groupname, false,
permissions.getGroupPermissions(groupname));
bindUpdateEmptyVisibility(permissionPanel);
groupPermissionsPanel.add(permissionPanel);
}
}
public void addPermissionPanel(RODAMember member) {
PermissionPanel permissionPanel = new PermissionPanel(member);
if (member.isUser()) {
bindUpdateEmptyVisibility(permissionPanel);
userPermissionsPanel.insert(permissionPanel, 0);
} else {
bindUpdateEmptyVisibility(permissionPanel);
groupPermissionsPanel.insert(permissionPanel, 0);
}
}
private void bindUpdateEmptyVisibility(PermissionPanel permissionPanel) {
permissionPanel.addAttachHandler(new Handler() {
@Override
public void onAttachOrDetach(AttachEvent event) {
// running later to let attach/detach take effect
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
userPermissionsEmpty.setVisible(userPermissionsPanel.getWidgetCount() == 0);
groupPermissionsEmpty.setVisible(groupPermissionsPanel.getWidgetCount() == 0);
}
});
}
});
}
@UiHandler("buttonAdd")
void buttonAddHandler(ClickEvent e) {
Filter filter = new Filter();
for (String username : getAssignedUserNames()) {
filter.add(new NotSimpleFilterParameter(RodaConstants.MEMBERS_ID, username));
}
for (String groupname : getAssignedGroupNames()) {
filter.add(new NotSimpleFilterParameter(RodaConstants.MEMBERS_ID, groupname));
}
MemberSelectDialog selectDialog = new MemberSelectDialog(messages.selectUserOrGroupToAdd(), filter);
selectDialog.showAndCenter();
selectDialog.addValueChangeHandler(new ValueChangeHandler<RODAMember>() {
@Override
public void onValueChange(ValueChangeEvent<RODAMember> event) {
RODAMember selected = event.getValue();
if (selected != null) {
addPermissionPanel(selected);
}
}
});
}
public List<String> getAssignedUserNames() {
List<String> ret = new ArrayList<>();
for (int i = 0; i < userPermissionsPanel.getWidgetCount(); i++) {
PermissionPanel permissionPanel = (PermissionPanel) userPermissionsPanel.getWidget(i);
if (permissionPanel.isUser()) {
ret.add(permissionPanel.getName());
}
}
return ret;
}
public List<String> getAssignedGroupNames() {
List<String> ret = new ArrayList<>();
for (int i = 0; i < groupPermissionsPanel.getWidgetCount(); i++) {
PermissionPanel permissionPanel = (PermissionPanel) groupPermissionsPanel.getWidget(i);
if (!permissionPanel.isUser()) {
ret.add(permissionPanel.getName());
}
}
return ret;
}
public Permissions getPermissions() {
Permissions permissions = new Permissions();
for (int i = 0; i < userPermissionsPanel.getWidgetCount(); i++) {
PermissionPanel permissionPanel = (PermissionPanel) userPermissionsPanel.getWidget(i);
if (permissionPanel.isUser()) {
permissions.setUserPermissions(permissionPanel.getName(), permissionPanel.getPermissions());
} else {
permissions.setGroupPermissions(permissionPanel.getName(), permissionPanel.getPermissions());
}
}
for (int i = 0; i < groupPermissionsPanel.getWidgetCount(); i++) {
PermissionPanel permissionPanel = (PermissionPanel) groupPermissionsPanel.getWidget(i);
if (permissionPanel.isUser()) {
permissions.setUserPermissions(permissionPanel.getName(), permissionPanel.getPermissions());
} else {
permissions.setGroupPermissions(permissionPanel.getName(), permissionPanel.getPermissions());
}
}
return permissions;
}
private void apply(final boolean recursive) {
final Permissions permissions = getPermissions();
Dialogs.showPromptDialog(messages.outcomeDetailTitle(), null, null, messages.outcomeDetailPlaceholder(),
RegExp.compile(".*"), messages.cancelButton(), messages.confirmButton(), false, new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
// do nothing
}
@Override
public void onSuccess(String details) {
if (IndexedAIP.class.getName().equals(objectClass)) {
List<IndexedAIP> aips = (List<IndexedAIP>) (Object) objects;
BrowserService.Util.getInstance().updateAIPPermissions(aips, permissions, details, recursive,
new LoadingAsyncCallback<Void>() {
@Override
public void onSuccessImpl(Void result) {
if (recursive) {
Toast.showInfo(messages.dialogSuccess(), messages.permissionsWillBeChanged());
} else {
Toast.showInfo(messages.dialogSuccess(), messages.permissionsChanged());
}
}
});
} else if (IndexedDIP.class.getName().equals(objectClass)) {
List<IndexedDIP> dips = (List<IndexedDIP>) (Object) objects;
BrowserService.Util.getInstance().updateDIPPermissions(dips, permissions, details,
new LoadingAsyncCallback<Void>() {
@Override
public void onSuccessImpl(Void result) {
Toast.showInfo(messages.dialogSuccess(), messages.permissionsChanged());
}
});
}
}
});
}
@UiHandler("buttonApply")
void buttonApplyHandler(ClickEvent e) {
apply(false);
}
@UiHandler("buttonApplyToAll")
void buttonApplyToAllHandler(ClickEvent e) {
apply(true);
}
@UiHandler("buttonClose")
void buttonCancelHandler(ClickEvent e) {
close();
}
public void close() {
LastSelectedItemsSingleton selectedItems = LastSelectedItemsSingleton.getInstance();
HistoryUtils.newHistory(selectedItems.getLastHistory());
}
public class PermissionPanel extends Composite {
private FlowPanel panel;
private FlowPanel panelBody;
private FlowPanel rightPanel;
private HTML type;
private Label nameLabel;
private FlowPanel editPermissionsPanel;
private Button removePanel;
private Button selectAllPanel;
private String name;
private boolean isUser;
public PermissionPanel(RODAMember member) {
this(member.getName(), member.isUser(), new HashSet<PermissionType>());
}
public PermissionPanel(String name, boolean isUser, Set<PermissionType> permissions) {
this.name = name;
this.isUser = isUser;
panel = new FlowPanel();
panelBody = new FlowPanel();
type = new HTML(
SafeHtmlUtils.fromSafeConstant(isUser ? "<i class='fa fa-user'></i>" : "<i class='fa fa-users'></i>"));
nameLabel = new Label(name);
rightPanel = new FlowPanel();
editPermissionsPanel = new FlowPanel();
boolean allSelected = true;
for (PermissionType permissionType : Permissions.PermissionType.values()) {
ValueCheckBox valueCheckBox = new ValueCheckBox(permissionType);
if (permissions.contains(permissionType)) {
valueCheckBox.setValue(true);
} else {
allSelected = false;
}
editPermissionsPanel.add(valueCheckBox);
valueCheckBox.addStyleName("permission-edit-checkbox");
}
removePanel = new Button(messages.removeButton());
if (!allSelected) {
selectAllPanel = new Button(messages.selectAllButton());
} else {
selectAllPanel = new Button(messages.clearButton());
}
panelBody.add(type);
panelBody.add(nameLabel);
panelBody.add(rightPanel);
rightPanel.add(editPermissionsPanel);
rightPanel.add(selectAllPanel);
rightPanel.add(removePanel);
panel.add(panelBody);
initWidget(panel);
panel.addStyleName("panel permission");
panel.addStyleName(isUser ? "permission-user" : "permission-group");
panelBody.addStyleName("panel-body");
type.addStyleName("permission-type");
nameLabel.addStyleName("permission-name");
rightPanel.addStyleName("pull-right");
editPermissionsPanel.addStyleName("permission-edit");
removePanel.addStyleName("permission-remove btn btn-danger btn-ban");
selectAllPanel.addStyleName("permission-remove permission-clear btn btn-check");
removePanel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
PermissionPanel.this.removeFromParent();
}
});
selectAllPanel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
boolean selectAll = selectAllPanel.getText().equals(messages.selectAllButton());
for (int i = 0; i < editPermissionsPanel.getWidgetCount(); i++) {
ValueCheckBox valueCheckBox = (ValueCheckBox) editPermissionsPanel.getWidget(i);
valueCheckBox.setValue(selectAll);
}
if (!selectAll) {
selectAllPanel.setText(messages.selectAllButton());
} else {
selectAllPanel.setText(messages.clearButton());
}
}
});
}
public Set<PermissionType> getPermissions() {
HashSet<PermissionType> permissions = new HashSet<>();
for (int i = 0; i < editPermissionsPanel.getWidgetCount(); i++) {
ValueCheckBox valueCheckBox = (ValueCheckBox) editPermissionsPanel.getWidget(i);
if (valueCheckBox.getValue()) {
permissions.add(valueCheckBox.getPermissionType());
}
}
return permissions;
}
public String getName() {
return name;
}
public boolean isUser() {
return isUser;
}
public class ValueCheckBox extends CheckBox {
private PermissionType permissionType;
public ValueCheckBox(PermissionType permissionType) {
super(messages.objectPermission(permissionType));
setTitle(messages.objectPermissionDescription(permissionType));
this.permissionType = permissionType;
}
public PermissionType getPermissionType() {
return permissionType;
}
}
}
}