/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wps.web; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteBehavior; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings; import org.apache.wicket.extensions.ajax.markup.html.autocomplete.IAutoCompleteRenderer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.Button; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.ChoiceRenderer; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.RadioChoice; import org.apache.wicket.markup.html.form.SubmitLink; import org.apache.wicket.markup.html.form.TextArea; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.validation.validator.RangeValidator; import org.geoserver.security.CatalogMode; import org.geoserver.security.GeoServerRoleService; import org.geoserver.security.impl.GeoServerRole; import org.geoserver.security.web.AbstractSecurityPage; import org.geoserver.web.wicket.GeoServerDataProvider.Property; import org.geoserver.web.wicket.GeoServerTablePanel; import org.geoserver.web.wicket.ParamResourceModel; import org.geoserver.wps.ProcessGroupInfo; import org.geoserver.wps.WPSInfo; /** * A page listing all WPS groups, * allowing enable/disable single groups and add/remove roles to grant access to all its processes * This page links to WPS service security configuration page to works on single processes. * * @see ProcessSelectionPage */ @SuppressWarnings("serial") public class WPSAccessRulePage extends AbstractSecurityPage { static final List<CatalogMode> CATALOG_MODES = Arrays.asList(CatalogMode.HIDE, CatalogMode.MIXED, CatalogMode.CHALLENGE); private List<ProcessGroupInfo> processFactories; private WPSInfo wpsInfo; private RadioChoice catalogModeChoice; private List<String> availableRoles = new ArrayList<String>(); public WPSAccessRulePage() { wpsInfo = getGeoServer().getService( WPSInfo.class ); Form form = new Form("form", new CompoundPropertyModel(wpsInfo)); processFactories = cloneFactoryInfos(wpsInfo.getProcessGroups()); ProcessFactoryInfoProvider provider = new ProcessFactoryInfoProvider(processFactories, getLocale()); GeoServerRoleService roleService = getSecurityManager().getActiveRoleService(); try { for(GeoServerRole r : roleService.getRoles()){ availableRoles.add(r.getAuthority()); } } catch (IOException e1) { LOGGER.log(Level.FINER, e1.getMessage(), e1); } TextField<Integer> maxComplexInputSize = new TextField<Integer>("maxComplexInputSize", Integer.class); maxComplexInputSize.add(RangeValidator.minimum(0)); form.add(maxComplexInputSize); final AutoCompleteSettings settings = new AutoCompleteSettings(); settings.setShowCompleteListOnFocusGain(false); settings.setShowListOnEmptyInput(true); settings.setShowListOnFocusGain(true); settings.setMaxHeightInPx(100); GeoServerTablePanel<ProcessGroupInfo> processFilterEditor = new GeoServerTablePanel<ProcessGroupInfo>("processFilterTable", provider) { @Override protected Component getComponentForProperty(String id, final IModel<ProcessGroupInfo> itemModel, Property<ProcessGroupInfo> property) { if(property.getName().equals("enabled")) { Fragment fragment = new Fragment(id, "enabledFragment", WPSAccessRulePage.this); CheckBox enabled = new CheckBox("enabled", (IModel<Boolean>) property.getModel(itemModel)); enabled.setOutputMarkupId(true); fragment.add(enabled); return fragment; } else if(property.getName().equals("prefix")) { return new Label(id, property.getModel(itemModel)); } else if(property.getName().equals("title")) { return new Label(id, property.getModel(itemModel)); } else if(property.getName().equals("summary")) { return new Label(id, property.getModel(itemModel)); } else if(property.getName().equals("roles")) { Fragment fragment = new Fragment(id, "rolesFragment", WPSAccessRulePage.this); TextArea<String> roles = new TextArea<String>("roles", (IModel<String>) property.getModel(itemModel)) { public <C extends Object> org.apache.wicket.util.convert.IConverter<C> getConverter(java.lang.Class<C> type) { return new RolesConverter(availableRoles); }; }; StringBuilder selectedRoles = new StringBuilder (); IAutoCompleteRenderer<String> roleRenderer = new RolesRenderer(selectedRoles); AutoCompleteBehavior<String> b = new RolesAutoCompleteBehavior(roleRenderer,settings,selectedRoles,availableRoles); roles.setOutputMarkupId(true); roles.add(b); fragment.add(roles); return fragment; } else if(property.getName().equals("edit")) { Fragment fragment = new Fragment(id, "linkFragment", WPSAccessRulePage.this); // we use a submit link to avoid losing the other edits in the form Link link = new Link("link") { @Override public void onClick() { ProcessGroupInfo pfi = (ProcessGroupInfo) itemModel.getObject(); setResponsePage(new ProcessSelectionPage(WPSAccessRulePage.this, pfi)); } }; fragment.add(link); return fragment; } return null; } }; processFilterEditor.setFilterable(false); processFilterEditor.setPageable(false); processFilterEditor.setOutputMarkupId( true ); form.add(processFilterEditor); form.add(new AjaxLink("processAccessModeHelp") { @Override public void onClick(AjaxRequestTarget target) { dialog.showInfo(target, new StringResourceModel("processAccessModeHelp.title",getPage(), null), new StringResourceModel("processAccessModeHelp.message",getPage(), null)); } }); catalogModeChoice = new RadioChoice("processAccessMode", new PropertyModel<CatalogMode>(wpsInfo, "catalogMode"), CATALOG_MODES, new CatalogModeRenderer()); catalogModeChoice.setSuffix(" "); form.add(catalogModeChoice); SubmitLink submit = new SubmitLink("submit",new StringResourceModel( "save", (Component)null, null) ) { @Override public void onSubmit() { try { // overwrite the process factories that we did clone to achieve isolation List<ProcessGroupInfo> factories = wpsInfo.getProcessGroups(); factories.clear(); factories.addAll(processFactories); getGeoServer().save(wpsInfo); doReturn(); }catch(Exception e) { error(e); } } }; form.add(submit); Button cancel = new Button( "cancel" ) { public void onSubmit() { doReturn(); } }; form.add( cancel ); add(form); } private List<ProcessGroupInfo> cloneFactoryInfos(List<ProcessGroupInfo> processFactories) { List<ProcessGroupInfo> result = new ArrayList<ProcessGroupInfo>(); for (ProcessGroupInfo pfi : processFactories) { result.add(pfi.clone()); } return result; } class CatalogModeRenderer extends ChoiceRenderer { public Object getDisplayValue(Object object) { return new ParamResourceModel(((CatalogMode) object).name(), getPage()) .getObject(); } public String getIdValue(Object object, int index) { return ((CatalogMode) object).name(); } } }