package com.constellio.app.ui.pages.management.authorizations;
import static com.constellio.app.ui.i18n.i18n.$;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.vaadin.dialogs.ConfirmDialog;
import com.constellio.app.ui.application.ConstellioUI;
import com.constellio.app.ui.entities.AuthorizationVO;
import com.constellio.app.ui.entities.RecordVO;
import com.constellio.app.ui.framework.buttons.ConfirmDialogButton;
import com.constellio.app.ui.framework.buttons.DeleteButton;
import com.constellio.app.ui.framework.buttons.EditButton;
import com.constellio.app.ui.framework.buttons.WindowButton;
import com.constellio.app.ui.framework.components.BaseForm;
import com.constellio.app.ui.framework.components.converters.JodaDateToStringConverter;
import com.constellio.app.ui.framework.components.display.ReferenceDisplay;
import com.constellio.app.ui.framework.components.fields.ListOptionGroup;
import com.constellio.app.ui.framework.components.fields.date.JodaDateField;
import com.constellio.app.ui.framework.components.fields.list.ListAddRemoveRecordLookupField;
import com.constellio.app.ui.framework.containers.ButtonsContainer;
import com.constellio.app.ui.framework.containers.ButtonsContainer.ContainerButton;
import com.constellio.app.ui.pages.base.BaseViewImpl;
import com.constellio.model.entities.records.wrappers.Group;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.security.Role;
import com.constellio.model.frameworks.validation.ValidationException;
import com.vaadin.data.Container;
import com.vaadin.data.fieldgroup.PropertyId;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnGenerator;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
public abstract class ListAuthorizationsViewImpl extends BaseViewImpl implements ListAuthorizationsView {
public static final String INHERITED_AUTHORIZATIONS = "authorizations-inherited";
public static final String AUTHORIZATIONS = "authorizations";
public enum AuthorizationSource {
INHERITED, OWN
}
public enum DisplayMode {
CONTENT, PRINCIPALS
}
protected ListAuthorizationsPresenter presenter;
protected RecordVO record;
private VerticalLayout layout;
private Table authorizations;
private Button detach;
@Override
protected void initBeforeCreateComponents(ViewChangeEvent event) {
record = presenter.forRequestParams(event.getParameters()).getRecordVO();
}
@Override
protected List<Button> buildActionMenuButtons(ViewChangeEvent event) {
List<Button> result = super.buildActionMenuButtons(event);
result.add(buildDetachButton());
result.add(buildAddButton());
if (this instanceof ListPrincipalAccessAuthorizationsView) {
result.add(buildAddAccessButton());
}
return result;
}
protected abstract Button buildAddButton();
protected Button buildAddAccessButton() {
return null;
}
private Button buildDetachButton() {
if (presenter.seeAccessField()) {
detach = new ConfirmDialogButton($("ListContentAccessAuthorizationsView.detach")) {
@Override
protected String getConfirmDialogMessage() {
return $("ListContentAccessAuthorizationsView.comfirmDetach");
}
@Override
protected void confirmButtonClick(ConfirmDialog dialog) {
presenter.detachRequested();
}
};
}
if (presenter.seeRolesField()) {
detach = new ConfirmDialogButton($("ListContentRoleAuthorizationsView.detach")) {
@Override
protected String getConfirmDialogMessage() {
return $("ListContentRoleAuthorizationsView.comfirmDetach");
}
@Override
protected void confirmButtonClick(ConfirmDialog dialog) {
presenter.detachRequested();
}
};
}
detach.setVisible(presenter.isDetacheable());
detach.setEnabled(presenter.isAttached());
return detach;
}
@Override
protected ClickListener getBackButtonClickListener() {
return new ClickListener() {
@Override
public void buttonClick(ClickEvent event) {
presenter.backButtonClicked(record.getSchema().getCode());
}
};
}
@Override
protected Component buildMainComponent(ViewChangeEvent event) {
layout = new VerticalLayout();
layout.setSpacing(true);
layout.setWidth("100%");
buildGlobalAccess(layout);
buildInheritedAuthorizations(layout);
buildOwnAuthorizations(layout);
return layout;
}
protected void buildGlobalAccess(VerticalLayout layout) {
}
@Override
public void refresh() {
layout.removeAllComponents();
buildGlobalAccess(layout);
buildInheritedAuthorizations(layout);
buildOwnAuthorizations(layout);
detach.setEnabled(presenter.isAttached());
}
@Override
public void addAuthorization(AuthorizationVO authorizationVO) {
authorizations.addItem(authorizationVO);
updateAuthorizationsTable();
}
@Override
public void removeAuthorization(AuthorizationVO authorization) {
refresh();
}
protected abstract DisplayMode getDisplayMode();
private void buildOwnAuthorizations(VerticalLayout layout) {
Label label = new Label();
if (presenter.seeAccessField()) {
label.setValue($("ListAccessAuthorizationsView.ownAuthorizations"));
} else if (presenter.seeRolesField()) {
label.setValue($("ListRoleAuthorizationsView.ownAuthorizations"));
}
label.addStyleName(ValoTheme.LABEL_H2);
authorizations = buildAuthorizationTable(presenter.getOwnAuthorizations(), AuthorizationSource.OWN);
layout.addComponents(label, authorizations);
}
private void buildInheritedAuthorizations(VerticalLayout layout) {
List<AuthorizationVO> authorizationVOs = presenter.getInheritedAuthorizations();
Label label = new Label();
if (presenter.seeAccessField()) {
label.setValue($("ListAccessAuthorizationsView.inheritedAuthorizations"));
} else if (presenter.seeRolesField()) {
label.setValue($("ListRoleAuthorizationsView.inheritedAuthorizations"));
}
label.addStyleName(ValoTheme.LABEL_H2);
authorizations = buildAuthorizationTable(authorizationVOs, AuthorizationSource.INHERITED);
layout.addComponents(label, authorizations);
}
private Table buildAuthorizationTable(List<AuthorizationVO> authorizationVOs, AuthorizationSource source) {
Container container = buildAuthorizationContainer(authorizationVOs, source);
String tableCaption = "";
if (presenter.seeAccessField()) {
tableCaption = $("ListAccessAuthorizationsView.authorizations", container.size());
} else if (presenter.seeRolesField()) {
tableCaption = $("ListRoleAuthorizationsView.authorizations", container.size());
}
Table table = new Table(tableCaption, container);
table.setPageLength(container.size());
table.addStyleName(source == AuthorizationSource.OWN ? AUTHORIZATIONS : INHERITED_AUTHORIZATIONS);
new Authorizations(source, getDisplayMode(), presenter.seeRolesField(), presenter.seeAccessField()).attachTo(table);
return table;
}
private Container buildAuthorizationContainer(List<AuthorizationVO> authorizationVOs, AuthorizationSource source) {
BeanItemContainer<AuthorizationVO> authorizations = new BeanItemContainer<>(AuthorizationVO.class, authorizationVOs);
return source == AuthorizationSource.OWN ?
addButtons(authorizations, source == AuthorizationSource.INHERITED) :
authorizations;
}
private Container addButtons(BeanItemContainer<AuthorizationVO> authorizations, final boolean inherited) {
ButtonsContainer container = new ButtonsContainer<>(authorizations, Authorizations.BUTTONS);
container.addButton(new ContainerButton() {
@Override
protected Button newButtonInstance(Object itemId, ButtonsContainer<?> container) {
AuthorizationVO authorization = (AuthorizationVO) itemId;
EditAuthorizationButton button = new EditAuthorizationButton(authorization);
button.setVisible(inherited || !authorization.isSynched());
return button;
}
});
container.addButton(new ContainerButton() {
@Override
protected Button newButtonInstance(final Object itemId, ButtonsContainer<?> container) {
final AuthorizationVO authorization = (AuthorizationVO) itemId;
DeleteButton deleteButton = new DeleteButton() {
@Override
protected void confirmButtonClick(ConfirmDialog dialog) {
presenter.deleteButtonClicked(authorization);
}
};
deleteButton.setVisible(inherited || !authorization.isSynched());
return deleteButton;
}
});
return container;
}
private void updateAuthorizationsTable() {
String tableCaption = "";
if (presenter.seeAccessField()) {
tableCaption = $("ListAccessAuthorizationsView.authorizations", authorizations.size());
} else if (presenter.seeRolesField()) {
tableCaption = $("ListRoleAuthorizationsView.authorizations", authorizations.size());
}
authorizations.setCaption(tableCaption);
authorizations.setPageLength(authorizations.size());
}
public abstract class AddAuthorizationButton extends WindowButton {
@PropertyId("accessRoles") protected ListOptionGroup accessRoles;
@PropertyId("userRoles") protected ListOptionGroup userRoles;
@PropertyId("startDate") protected JodaDateField startDate;
@PropertyId("endDate") protected JodaDateField endDate;
public AddAuthorizationButton() {
super("", "", WindowConfiguration.modalDialog("40%", "65%"));
String caption = "";
if (presenter.seeAccessField()) {
caption = $("ListAccessAuthorizationsView.add");
} else if (presenter.seeRolesField()) {
caption = $("ListRoleAuthorizationsView.add");
}
super.setCaption(caption);
super.setWindowCaption(caption);
}
protected void buildAccessField() {
accessRoles = new ListOptionGroup($("AuthorizationsView.access"));
for (String accessCode : presenter.getAllowedAccesses()) {
accessRoles.addItem(accessCode);
accessRoles.setItemCaption(accessCode, $("AuthorizationsView." + accessCode));
}
accessRoles.setEnabled(presenter.seeAccessField());
accessRoles.setVisible(presenter.seeAccessField());
accessRoles.setRequired(presenter.seeAccessField());
accessRoles.setMultiSelect(true);
accessRoles.setId("accessRoles");
}
protected void buildRolesField() {
userRoles = new ListOptionGroup($("AuthorizationsView.userRoles"));
for (String roleCode : presenter.getAllowedRoles()) {
userRoles.addItem(roleCode);
userRoles.setItemCaption(roleCode, presenter.getRoleTitle(roleCode));
}
userRoles.setEnabled(presenter.seeRolesField());
userRoles.setVisible(presenter.seeRolesField());
userRoles.setRequired(presenter.seeRolesField());
userRoles.setMultiSelect(true);
userRoles.setId("userRoles");
}
protected void buildDateFields() {
startDate = new JodaDateField();
startDate.setCaption($("AuthorizationsView.startDate"));
startDate.setId("startDate");
endDate = new JodaDateField();
endDate.setCaption($("AuthorizationsView.endDate"));
endDate.setId("endDate");
}
}
public class EditAuthorizationButton extends WindowButton {
private final AuthorizationVO authorization;
@PropertyId("users") private ListAddRemoveRecordLookupField users;
@PropertyId("groups") private ListAddRemoveRecordLookupField groups;
public EditAuthorizationButton(AuthorizationVO authorization) {
super(EditButton.ICON_RESOURCE, $("ListAuthorizationsView.edit"), true,
WindowConfiguration.modalDialog("50%", "50%"));
this.authorization = authorization;
}
@Override
protected Component buildWindowContent() {
buildUsersAndGroupsField();
return new BaseForm<AuthorizationVO>(authorization, this, users, groups) {
@Override
protected void saveButtonClick(AuthorizationVO viewObject)
throws ValidationException {
getWindow().close();
presenter.authorizationModificationRequested(authorization);
}
@Override
protected void cancelButtonClick(AuthorizationVO viewObject) {
getWindow().close();
}
};
}
private void buildUsersAndGroupsField() {
users = new ListAddRemoveRecordLookupField(User.SCHEMA_TYPE);
users.setValue(authorization.getUsers());
users.setVisible(!authorization.getUsers().isEmpty());
users.setCaption($("AuthorizationsView.users"));
users.setId("users");
groups = new ListAddRemoveRecordLookupField(Group.SCHEMA_TYPE);
groups.setValue(authorization.getGroups());
groups.setVisible(!authorization.getGroups().isEmpty());
groups.setCaption($("AuthorizationsView.groups"));
groups.setId("groups");
}
}
public static class Authorizations implements ColumnGenerator {
public static final String PRINCIPALS = "principal";
public static final String CONTENT = "content";
public static final String ACCESS = "access";
public static final String USER_ROLES = "userRoles";
public static final String START_DATE = "startDate";
public static final String END_DATE = "endDate";
public static final String BUTTONS = "buttons";
private final AuthorizationSource source;
private final DisplayMode mode;
private boolean seeRolesField;
private boolean seeAccessField;
private final JodaDateToStringConverter converter;
public Authorizations(AuthorizationSource source, DisplayMode mode, boolean seeRolesField, boolean seeAccessField) {
this.source = source;
this.mode = mode;
this.seeRolesField = seeRolesField;
this.seeAccessField = seeAccessField;
converter = new JodaDateToStringConverter();
}
public void attachTo(Table table) {
String primary;
if (mode == DisplayMode.CONTENT) {
table.addGeneratedColumn(CONTENT, this);
table.setColumnHeader(CONTENT, $("AuthorizationsView.content"));
primary = CONTENT;
} else {
table.addGeneratedColumn(PRINCIPALS, this);
table.setColumnHeader(PRINCIPALS, $("AuthorizationsView.principals"));
primary = PRINCIPALS;
}
table.setColumnExpandRatio(primary, 1);
if (seeAccessField) {
table.addGeneratedColumn(ACCESS, this);
table.setColumnHeader(ACCESS, $("AuthorizationsView.access"));
}
if (seeRolesField) {
table.addGeneratedColumn(USER_ROLES, this);
table.setColumnHeader(USER_ROLES, $("AuthorizationsView.userRoles"));
}
table.addGeneratedColumn(START_DATE, this);
table.setColumnHeader(START_DATE, $("AuthorizationsView.startDate"));
table.addGeneratedColumn(END_DATE, this);
table.setColumnHeader(END_DATE, $("AuthorizationsView.endDate"));
if (source == AuthorizationSource.OWN) {
table.setColumnHeader(BUTTONS, "");
table.setColumnWidth(BUTTONS, 80);
if (seeRolesField && seeAccessField) {
table.setVisibleColumns(primary, ACCESS, USER_ROLES, START_DATE, END_DATE, BUTTONS);
} else if (!seeRolesField && seeAccessField) {
table.setVisibleColumns(primary, ACCESS, START_DATE, END_DATE, BUTTONS);
} else if (seeRolesField && !seeAccessField) {
table.setVisibleColumns(primary, USER_ROLES, START_DATE, END_DATE, BUTTONS);
}
} else {
if (seeRolesField && seeAccessField) {
table.setVisibleColumns(primary, ACCESS, USER_ROLES, START_DATE, END_DATE);
} else if (!seeRolesField && seeAccessField) {
table.setVisibleColumns(primary, ACCESS, START_DATE, END_DATE);
} else if (seeRolesField && !seeAccessField) {
table.setVisibleColumns(primary, USER_ROLES, START_DATE, END_DATE);
}
}
table.setWidth("100%");
}
@Override
public Object generateCell(Table source, Object itemId, Object columnId) {
AuthorizationVO authorization = (AuthorizationVO) itemId;
switch ((String) columnId) {
case CONTENT:
return new ReferenceDisplay(authorization.getRecord());
case PRINCIPALS:
return buildPrincipalColumn(authorization.getGroups(), authorization.getUsers());
case ACCESS:
return buildAccessColumn(authorization.getAccessRoles());
case USER_ROLES:
return buildUserRolesColumn(authorization.getUserRoles(), authorization.getUserRolesTitles());
default:
LocalDate date = (LocalDate) source.getItem(itemId).getItemProperty(columnId).getValue();
return converter.convertToPresentation(
date, String.class, ConstellioUI.getCurrentSessionContext().getCurrentLocale());
}
}
private Object buildPrincipalColumn(List<String> groups, List<String> users) {
List<ReferenceDisplay> results = new ArrayList<>();
for (String groupId : groups) {
results.add(new ReferenceDisplay(groupId));
}
for (String userId : users) {
results.add(new ReferenceDisplay(userId));
}
return new VerticalLayout(results.toArray(new Component[results.size()]));
}
private Component buildAccessColumn(List<String> roles) {
List<String> accesses = new ArrayList<>(3);
List<String> shortened = new ArrayList<>(3);
if (roles.contains(Role.READ)) {
accesses.add($("AuthorizationsView.READ"));
shortened.add($("AuthorizationsView.short.READ"));
}
if (roles.contains(Role.WRITE)) {
accesses.add($("AuthorizationsView.WRITE"));
shortened.add($("AuthorizationsView.short.WRITE"));
}
if (roles.contains(Role.DELETE)) {
accesses.add($("AuthorizationsView.DELETE"));
shortened.add($("AuthorizationsView.short.DELETE"));
}
Label label = new Label(StringUtils.join(shortened, "/"));
label.setDescription(StringUtils.join(accesses, ", "));
return label;
}
private Component buildUserRolesColumn(List<String> roleCodes, List<String> roleTitles) {
Label label = new Label(StringUtils.join(roleCodes, "/"));
label.setDescription(StringUtils.join(roleTitles, ", "));
return label;
}
}
}