Package org.geoserver.security.web.user

Source Code of org.geoserver.security.web.user.AbstractUserPage$CalculatedRoleModel

/* (c) 2014 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.security.web.user;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
import java.util.logging.Level;

import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.AbstractFormValidator;
import org.apache.wicket.markup.html.form.validation.EqualInputValidator;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.validation.IValidator;
import org.geoserver.security.GeoServerRoleService;
import org.geoserver.security.GeoServerUserGroupService;
import org.geoserver.security.impl.GeoServerRole;
import org.geoserver.security.impl.GeoServerUser;
import org.geoserver.security.impl.GeoServerUserGroup;
import org.geoserver.security.impl.GroupAdminProperty;
import org.geoserver.security.impl.RoleCalculator;
import org.geoserver.security.password.GeoServerEmptyPasswordEncoder;
import org.geoserver.security.validation.AbstractSecurityException;
import org.geoserver.security.validation.PasswordPolicyException;
import org.geoserver.security.web.AbstractSecurityPage;
import org.geoserver.security.web.role.EditRolePage;
import org.geoserver.security.web.role.RoleListProvider;
import org.geoserver.security.web.role.RolePaletteFormComponent;
import org.geoserver.web.wicket.ParamResourceModel;
import org.geoserver.web.wicket.SimpleAjaxLink;
import org.geoserver.web.wicket.property.PropertyEditorFormComponent;
import org.geotools.resources.UnmodifiableArrayList;

/**
* Allows creation of a new user in users.properties
*/
public abstract class AbstractUserPage extends AbstractSecurityPage {

    protected RolePaletteFormComponent rolePalette;
    protected UserGroupPaletteFormComponent userGroupPalette;
    protected UserGroupListMultipleChoice adminGroupChoice;
    protected ListView<GeoServerRole> calculatedRoles;

    protected String ugServiceName;

    protected AbstractUserPage(String ugServiceName, final GeoServerUser user) {
        this.ugServiceName=ugServiceName;

        GeoServerUserGroupService ugService = getUserGroupService(ugServiceName);
        boolean emptyPasswd = getSecurityManager().loadPasswordEncoder(ugService.getPasswordEncoderName())
            instanceof GeoServerEmptyPasswordEncoder;
        boolean hasUserGroupStore = ugService.canCreateStore();
        boolean hasRoleStore = hasRoleStore(getSecurityManager().getActiveRoleService().getName());

        // build the form
        Form form = new Form<Serializable>("form", new CompoundPropertyModel(user));
        add(form);

        form.add(new TextField("username").setEnabled(hasUserGroupStore));
        form.add(new CheckBox("enabled").setEnabled(hasUserGroupStore));

        PasswordTextField pw1 = new PasswordTextField("password") {
            @Override
            public boolean isRequired() {
                return isFinalSubmit(this);
            }
        };
        form.add(pw1);
        pw1.setResetPassword(false);
        pw1.setEnabled(hasUserGroupStore && !emptyPasswd);

        PasswordTextField pw2 = new PasswordTextField("confirmPassword",
            new Model(user.getPassword())) {
            @Override
            public boolean isRequired() {
                return isFinalSubmit(this);
            }
        };
        form.add(pw2);
        pw2.setResetPassword(false);               
        pw2.setEnabled(hasUserGroupStore && !emptyPasswd);

        form.add(new PropertyEditorFormComponent("properties").setEnabled(hasUserGroupStore));

        form.add(userGroupPalette = new UserGroupPaletteFormComponent("groups", ugServiceName, user));
        userGroupPalette.add(new AjaxFormComponentUpdatingBehavior("onchange") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                updateCalculatedRoles(target);
            }
        });
        userGroupPalette.setEnabled(hasUserGroupStore);

        List<GeoServerRole> roles;
        try {
            roles = new ArrayList(
                getSecurityManager().getActiveRoleService().getRolesForUser(user.getUsername()));
        } catch (IOException e) {
            throw new WicketRuntimeException(e);
        }
       
        form.add(rolePalette = new RolePaletteFormComponent("roles", new ListModel(roles)));
        rolePalette.add(new AjaxFormComponentUpdatingBehavior("onchange") {
           @Override
           protected void onUpdate(AjaxRequestTarget target) {
               updateCalculatedRoles(target);
               updateGroupAdminList(target);
           }
        });
        rolePalette.setOutputMarkupId(true);
        rolePalette.setEnabled(hasRoleStore);

        boolean isGroupAdmin = roles.contains(GeoServerRole.GROUP_ADMIN_ROLE);
        List<GeoServerUserGroup> adminGroups = new ArrayList();
        if (isGroupAdmin) {
            for (String groupName : GroupAdminProperty.get(user.getProperties())) {
                try {
                    adminGroups.add(ugService.getGroupByGroupname(groupName));
                } catch (IOException e) {
                    throw new WicketRuntimeException(e);
                }
            }
        }

        form.add(adminGroupChoice = new UserGroupListMultipleChoice("adminGroups",
            new ListModel(adminGroups), new GroupsModel(ugServiceName)));
        adminGroupChoice.setOutputMarkupId(true);
        adminGroupChoice.setEnabled(hasUserGroupStore && isGroupAdmin);

        WebMarkupContainer container = new WebMarkupContainer("calculatedRolesContainer");
        form.add(container);
        container.setOutputMarkupId(true);

        container.add(calculatedRoles =
            new ListView<GeoServerRole>("calculatedRoles", new CalculatedRoleModel(user)) {
            @Override
            @SuppressWarnings("unchecked")
            protected void populateItem(ListItem<GeoServerRole> item) {
                IModel<GeoServerRole> model = item.getModel();
                item.add(new SimpleAjaxLink("role", model, RoleListProvider.ROLENAME.getModel(model)) {
                    @Override
                    protected void onClick(AjaxRequestTarget target) {
                        setResponsePage(
                            new EditRolePage(getSecurityManager().getActiveRoleService().getName(),
                                (GeoServerRole) getDefaultModelObject()).setReturnPage(this.getPage()));
                    }
                });
            }
        });
        calculatedRoles.setOutputMarkupId(true);

        form.add(new SubmitLink("save") {
            @Override
            public void onSubmit() {
                try {
                    //update the user property listing the group names the user is admin for
                    if (adminGroupChoice.isEnabled()) {
                        Collection<GeoServerUserGroup> groups = adminGroupChoice.getModelObject();
                        String[] groupNames = new String[groups.size()];
                        int i = 0;
                        for (GeoServerUserGroup group : groups) {
                            groupNames[i++] = group.getGroupname();
                        }

                        GroupAdminProperty.set(user.getProperties(), groupNames);
                    }
                    else {
                        GroupAdminProperty.del(user.getProperties());
                    }

                    onFormSubmit(user);
                    setReturnPageDirtyAndReturn(true);
                }
                catch(Exception e) {
                    handleSubmitError(e);
                }
            }
        }.setEnabled(hasUserGroupStore || hasRoleStore(getSecurityManager().getActiveRoleService().getName())));
        form.add(getCancelLink());

        // add the validators
        form.add(new EqualInputValidator(pw1, pw2) {
            private static final long serialVersionUID = 1L;
           
            @Override
            public void validate(Form<?> form) {
                if (isFinalSubmit(form)) {
                    super.validate(form);
                }
            }
            @Override
            protected String resourceKey() {
                return "AbstractUserPage.passwordMismatch";
            }
        });
        form.add(new GroupAdminValidator());
    }

    boolean isFinalSubmit(FormComponent component) {
        return isFinalSubmit(Form.findForm(component));
    }

    boolean isFinalSubmit(Form form) {
        if (form == null) {
            return false;
        }
        return form.findSubmittingButton() == form.get("save");
    }

    void updateCalculatedRoles(AjaxRequestTarget target) {
        calculatedRoles.modelChanged();
        target.addComponent(calculatedRoles.getParent());
    }

    void updateGroupAdminList(AjaxRequestTarget target) {
        adminGroupChoice.setEnabled(
            rolePalette.getSelectedRoles().contains(GeoServerRole.GROUP_ADMIN_ROLE));
        target.addComponent(adminGroupChoice);
    }

    void handleSubmitError(Exception e) {
        LOGGER.log(Level.SEVERE, "Error occurred while saving user", e);
       
        if (e instanceof RuntimeException && e.getCause() instanceof Exception) {
            e = (Exception) e.getCause();
        }
       
        if (e instanceof IOException && e.getCause() instanceof AbstractSecurityException) {
            e = (Exception) e.getCause();
        }

        if (e instanceof AbstractSecurityException) {
            error(e);
        }
        else {
            error(new ParamResourceModel("saveError", getPage(), e.getMessage()).getObject());
        }
    }

    /**
     * List model that calculates derived roles for the user, those assigned directly and through
     * group membership.
     */
    class CalculatedRoleModel extends LoadableDetachableModel<List<GeoServerRole>> {

        GeoServerUser user;

        CalculatedRoleModel(GeoServerUser user) {
            this.user = user;
        }

        @Override
        protected List<GeoServerRole> load() {
            List<GeoServerRole> tmp = new ArrayList<GeoServerRole>();
            List<GeoServerRole> result = new ArrayList<GeoServerRole>();
            try {
                GeoServerUserGroupService ugService = getSecurityManager()
                        .loadUserGroupService(ugServiceName);
                GeoServerRoleService gaService = getSecurityManager()
                        .getActiveRoleService();

                RoleCalculator calc = new RoleCalculator(ugService, gaService);
                tmp.addAll(rolePalette.getSelectedRoles());
                calc.addInheritedRoles(tmp);

                for (GeoServerUserGroup group : userGroupPalette.getSelectedGroups()) {
                    if (group.isEnabled()) {
                        tmp.addAll(calc.calculateRoles(group));
                    }
                }
                result.addAll(calc.personalizeRoles(user, tmp));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
       
            Collections.sort(result);
            return result;
        }
    }

    /**
     * Validator that ensures when a user is assigned to be a group admin that at least one group
     * is selected.
     */
    class GroupAdminValidator extends AbstractFormValidator {

        @Override
        public FormComponent<?>[] getDependentFormComponents() {
            return new FormComponent[] {adminGroupChoice};
        }

        @Override
        public void validate(Form<?> form) {
            if (adminGroupChoice.isEnabled()) {
                adminGroupChoice.updateModel();
                if (adminGroupChoice.getModelObject().isEmpty()) {
                    form.error(new StringResourceModel("noAdminGroups", getPage(), null).getString());
                }
            }
        }
    }

    /**
     * Implements the actual save action.
     */
    protected abstract void onFormSubmit(GeoServerUser user)
        throws IOException, PasswordPolicyException;

}
TOP

Related Classes of org.geoserver.security.web.user.AbstractUserPage$CalculatedRoleModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.