package org.activityinfo.ui.client.page.config; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.extjs.gxt.ui.client.core.El; import com.extjs.gxt.ui.client.data.*; import com.extjs.gxt.ui.client.event.GridEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.SelectionChangedEvent; import com.extjs.gxt.ui.client.event.SelectionChangedListener; import com.extjs.gxt.ui.client.store.ListStore; import com.extjs.gxt.ui.client.store.Record; import com.extjs.gxt.ui.client.store.Store; import com.extjs.gxt.ui.client.store.StoreEvent; import com.extjs.gxt.ui.client.widget.ContentPanel; import com.extjs.gxt.ui.client.widget.grid.*; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.inject.Inject; import org.activityinfo.i18n.shared.I18N; import org.activityinfo.legacy.client.Dispatcher; import org.activityinfo.legacy.client.monitor.MaskingAsyncMonitor; import org.activityinfo.legacy.client.state.StateProvider; import org.activityinfo.legacy.shared.command.BatchCommand; import org.activityinfo.legacy.shared.command.GetUsers; import org.activityinfo.legacy.shared.command.UpdateUserPermissions; import org.activityinfo.legacy.shared.command.result.BatchResult; import org.activityinfo.legacy.shared.command.result.UserResult; import org.activityinfo.legacy.shared.command.result.VoidResult; import org.activityinfo.legacy.shared.model.PartnerDTO; import org.activityinfo.legacy.shared.model.UserDatabaseDTO; import org.activityinfo.legacy.shared.model.UserPermissionDTO; import org.activityinfo.ui.client.EventBus; import org.activityinfo.ui.client.page.NavigationCallback; import org.activityinfo.ui.client.page.PageId; import org.activityinfo.ui.client.page.PageState; import org.activityinfo.ui.client.page.common.dialog.FormDialogCallback; import org.activityinfo.ui.client.page.common.dialog.FormDialogImpl; import org.activityinfo.ui.client.page.common.toolbar.ActionListener; import org.activityinfo.ui.client.page.common.toolbar.ActionToolBar; import org.activityinfo.ui.client.page.common.toolbar.UIActions; import org.activityinfo.ui.client.page.config.form.UserForm; import org.activityinfo.ui.client.style.legacy.icon.IconImageBundle; import java.util.ArrayList; import java.util.List; public class DbUserEditor extends ContentPanel implements DbPage, ActionListener { public static final PageId PAGE_ID = new PageId("dbusers"); private final EventBus eventBus; private final Dispatcher dispatcher; private PagingLoader<UserResult> loader; private ListStore<UserPermissionDTO> store; private Grid<UserPermissionDTO> grid; private UserDatabaseDTO db; private ActionToolBar toolBar; @Inject public DbUserEditor(EventBus eventBus, Dispatcher service, StateProvider stateMgr) { this.eventBus = eventBus; this.dispatcher = service; setHeadingText(I18N.CONSTANTS.users()); setLayout(new FitLayout()); createToolBar(); createGrid(); createPagingToolBar(); } @Override public void go(UserDatabaseDTO db) { this.db = db; store.removeAll(); toolBar.setActionEnabled(UIActions.SAVE, false); toolBar.setActionEnabled(UIActions.ADD, db.isManageUsersAllowed()); toolBar.setActionEnabled(UIActions.DELETE, false); grid.getColumnModel().getColumnById("allowViewAll").setHidden(!db.isManageUsersAllowed()); grid.getColumnModel().getColumnById("allowEditAll").setHidden(!db.isManageUsersAllowed()); grid.getColumnModel().getColumnById("allowManageUsers").setHidden(!db.isManageAllUsersAllowed()); grid.getColumnModel().getColumnById("allowManageAllUsers").setHidden(!db.isManageAllUsersAllowed()); grid.getColumnModel().getColumnById("allowDesign").setHidden(!db.isDesignAllowed()); loader.load(); } private void createToolBar() { toolBar = new ActionToolBar(this); toolBar.addSaveSplitButton(); toolBar.addButton(UIActions.ADD, I18N.CONSTANTS.addUser(), IconImageBundle.ICONS.addUser()); toolBar.addButton(UIActions.DELETE, I18N.CONSTANTS.delete(), IconImageBundle.ICONS.deleteUser()); toolBar.addButton(UIActions.EXPORT, I18N.CONSTANTS.export(), IconImageBundle.ICONS.excel()); toolBar.addButton(UIActions.MAILING_LIST, I18N.CONSTANTS.CopyAddressToClipBoard(), IconImageBundle.ICONS.dataEntry()); setTopComponent(toolBar); } private void createGrid() { loader = new BasePagingLoader<UserResult>(new UserProxy()); store = new ListStore<UserPermissionDTO>(loader); store.setKeyProvider(new ModelKeyProvider<UserPermissionDTO>() { @Override public String getKey(UserPermissionDTO model) { return model.getEmail(); } }); store.addListener(Store.Update, new Listener<StoreEvent<UserPermissionDTO>>() { @Override public void handleEvent(StoreEvent<UserPermissionDTO> event) { toolBar.setDirty(!store.getModifiedRecords().isEmpty()); } }); final List<ColumnConfig> columns = new ArrayList<ColumnConfig>(); columns.add(new ColumnConfig("name", I18N.CONSTANTS.name(), 100)); columns.add(new ColumnConfig("email", I18N.CONSTANTS.email(), 150)); columns.add(new ColumnConfig("partner", I18N.CONSTANTS.partner(), 150)); PermissionCheckConfig allowView = new PermissionCheckConfig("allowViewSimple", I18N.CONSTANTS.allowView(), 75); allowView.setDataIndex("allowView"); allowView.setToolTip(I18N.CONSTANTS.allowViewLong()); columns.add(allowView); PermissionCheckConfig allowEdit = new PermissionCheckConfig("allowEditSimple", I18N.CONSTANTS.allowEdit(), 75); allowEdit.setDataIndex("allowEdit"); allowEdit.setToolTip(I18N.CONSTANTS.allowEditLong()); columns.add(allowEdit); PermissionCheckConfig allowViewAll = new PermissionCheckConfig("allowViewAll", I18N.CONSTANTS.allowViewAll(), 75); allowViewAll.setToolTip(I18N.CONSTANTS.allowViewAllLong()); columns.add(allowViewAll); PermissionCheckConfig allowEditAll = new PermissionCheckConfig("allowEditAll", I18N.CONSTANTS.allowEditAll(), 75); allowEditAll.setToolTip(I18N.CONSTANTS.allowEditAllLong()); columns.add(allowEditAll); PermissionCheckConfig allowManageUsers = null; allowManageUsers = new PermissionCheckConfig("allowManageUsers", I18N.CONSTANTS.allowManageUsers(), 150); columns.add(allowManageUsers); PermissionCheckConfig allowManageAllUsers = new PermissionCheckConfig("allowManageAllUsers", I18N.CONSTANTS.manageAllUsers(), 150); columns.add(allowManageAllUsers); // only users with the right to design them selves can change the design // attribute PermissionCheckConfig allowDesign = new PermissionCheckConfig("allowDesign", I18N.CONSTANTS.allowDesign(), 75); allowDesign.setToolTip(I18N.CONSTANTS.allowDesignLong()); columns.add(allowDesign); grid = new Grid<UserPermissionDTO>(store, new ColumnModel(columns)); grid.setLoadMask(true); grid.setSelectionModel(new GridSelectionModel<UserPermissionDTO>()); grid.getSelectionModel().addSelectionChangedListener(new SelectionChangedListener<UserPermissionDTO>() { @Override public void selectionChanged(SelectionChangedEvent<UserPermissionDTO> se) { onSelectionChanged(se.getSelectedItem()); } }); grid.addPlugin(allowEdit); grid.addPlugin(allowViewAll); grid.addPlugin(allowEditAll); grid.addPlugin(allowManageUsers); grid.addPlugin(allowManageAllUsers); grid.addPlugin(allowDesign); add(grid); } private void createPagingToolBar() { PagingToolBar pagingToolBar = new PagingToolBar(100); pagingToolBar.bind(loader); setBottomComponent(pagingToolBar); } @Override public void shutdown() { } @Override public boolean navigate(PageState place) { return false; } private boolean validateChange(UserPermissionDTO user, String property) { // If the user doesn't have the manageUser permission, then it's // definitely // a no. if (!db.isManageUsersAllowed()) { return false; } // if the user is only allowed to manager their own partners, then make // sure they're changing someone from their own organisation if (!db.isManageAllUsersAllowed() && db.getMyPartner().getId() != user.getPartner().getId()) { return false; } // do not allow users to set rights they themselves do not have if ("allowViewAll".equals(property) && !db.isViewAllAllowed()) { return false; } if ("allowEdit".equals(property) && !db.isEditAllowed()) { return false; } if ("allowEditAll".equals(property) && !db.isEditAllAllowed()) { return false; } if ("allowDesign".equals(property) && !db.isDesignAllowed()) { return false; } if ("allowManageUsers".equals(property) && !db.isManageUsersAllowed()) { return false; } if ("allowManageAllUsers".equals(property) && !db.isManageAllUsersAllowed()) { return false; } return true; } @Override public PageId getPageId() { return PAGE_ID; } @Override public Object getWidget() { return this; } @Override public String beforeWindowCloses() { return null; } private void onRowEdit(String property, boolean value, Record record) { record.beginEdit(); if (!value) { // Cascade remove permissions if ("allowViewAll".equals(property)) { record.set("allowEditAll", false); } } else { // cascade add permissions if ("allowEditAll".equals(property)) { record.set("allowEdit", true); record.set("allowViewAll", true); } else if ("allowManageAllUsers".equals(property)) { record.set("allowManageUsers", true); } } record.endEdit(); toolBar.setDirty(store.getModifiedRecords().size() != 0); } private void onSelectionChanged(UserPermissionDTO selectedItem) { if (selectedItem != null) { PartnerDTO selectedPartner = selectedItem.getPartner(); toolBar.setActionEnabled(UIActions.DELETE, db.isManageAllUsersAllowed() || (db.isManageUsersAllowed() && db.getMyPartnerId() == selectedPartner.getId())); } toolBar.setActionEnabled(UIActions.DELETE, selectedItem != null); } @Override public void onUIAction(String actionId) { if (actionId.equals(UIActions.SAVE)) { save(); } else if (actionId.equals(UIActions.ADD)) { add(); } else if (actionId.equals(UIActions.DELETE)) { delete(); } else if (actionId.equals(UIActions.EXPORT)) { export(); } else if (UIActions.MAILING_LIST.equals(actionId)) { createMailingListPopup(); } } private void save() { BatchCommand batch = new BatchCommand(); for (Record record : store.getModifiedRecords()) { batch.add(new UpdateUserPermissions(db.getId(), (UserPermissionDTO) record.getModel())); } dispatcher.execute(batch, new MaskingAsyncMonitor(this, I18N.CONSTANTS.saving()), new AsyncCallback<BatchResult>() { @Override public void onFailure(Throwable caught) { // handled by monitor } @Override public void onSuccess(BatchResult result) { store.commitChanges(); } }); } private void createMailingListPopup() { new MailingListDialog(dispatcher, db.getId()); } private void add() { final UserForm form = new UserForm(db); final FormDialogImpl dlg = new FormDialogImpl(form); dlg.setHeadingText(I18N.CONSTANTS.newUser()); dlg.setWidth(400); dlg.setHeight(300); final String host = Window.Location.getHostName(); dlg.show(new FormDialogCallback() { @Override public void onValidated() { dispatcher.execute(new UpdateUserPermissions(db, form.getUser(), host), dlg, new AsyncCallback<VoidResult>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(VoidResult result) { loader.load(); dlg.hide(); } }); } }); } private void delete() { final UserPermissionDTO model = grid.getSelectionModel().getSelectedItem(); model.setAllowView(false); model.setAllowViewAll(false); model.setAllowEdit(false); model.setAllowEditAll(false); model.setAllowDesign(false); model.setAllowManageAllUsers(false); model.setAllowManageUsers(false); dispatcher.execute(new UpdateUserPermissions(db.getId(), model), new MaskingAsyncMonitor(this, I18N.CONSTANTS.deleting()), new AsyncCallback<VoidResult>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(VoidResult result) { store.remove(model); } }); } private void export() { Window.open(GWT.getModuleBaseURL() + "export/users?dbUsers=" + db.getId(), "_blank", null); } @Override public void requestToNavigateAway(PageState place, NavigationCallback callback) { callback.onDecided(true); } private class PermissionCheckConfig extends CheckColumnConfig { public PermissionCheckConfig(String id, String name, int width) { super(id, name, width); } @Override protected void onMouseDown(GridEvent<ModelData> ge) { El el = ge.getTargetEl(); if (el != null && el.hasStyleName("x-grid3-cc-" + getId()) && !el.hasStyleName("x-grid3-check-col-disabled")) { ge.stopEvent(); UserPermissionDTO m = (UserPermissionDTO) ge.getModel(); String property = grid.getColumnModel().getColumnId(ge.getColIndex()); Record r = store.getRecord(m); Boolean b = (Boolean) m.get(getDataIndex()); if (validateChange(m, property)) { boolean newValue = b == null ? true : !b; r.set(getDataIndex(), newValue); onRowEdit(property, newValue, r); } } } } private class UserProxy extends RpcProxy<UserResult> { @Override protected void load(Object loadConfig, final AsyncCallback<UserResult> callback) { PagingLoadConfig config = (PagingLoadConfig) loadConfig; GetUsers command = new GetUsers(db.getId()); command.setOffset(config.getOffset()); command.setLimit(config.getLimit()); command.setSortInfo(config.getSortInfo()); dispatcher.execute(command, callback); } } }