Package org.jboss.as.console.client.rbac

Source Code of org.jboss.as.console.client.rbac.SecurityServiceImpl

package org.jboss.as.console.client.rbac;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.jboss.as.console.client.domain.model.SimpleCallback;
import org.jboss.as.console.client.plugins.AccessControlRegistry;
import org.jboss.as.console.mbui.behaviour.CoreGUIContext;
import org.jboss.as.console.mbui.model.mapping.AddressMapping;
import org.jboss.ballroom.client.rbac.Constraints;
import org.jboss.ballroom.client.rbac.Facet;
import org.jboss.ballroom.client.rbac.SecurityContext;
import org.jboss.ballroom.client.rbac.SecurityService;
import org.jboss.dmr.client.ModelNode;
import org.jboss.dmr.client.ModelType;
import org.jboss.dmr.client.Property;
import org.jboss.dmr.client.dispatch.DispatchAsync;
import org.jboss.dmr.client.dispatch.impl.DMRAction;
import org.jboss.dmr.client.dispatch.impl.DMRResponse;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.jboss.dmr.client.ModelDescriptionConstants.*;

/**
* The secuirty service creates and provides a {@link SecurityContext} per place
*
* @see com.gwtplatform.mvp.client.proxy.PlaceManager
*
* @author Heiko Braun
* @date 7/3/13
*/
public class SecurityServiceImpl implements SecurityService {


    private static final String MODEL_DESCRIPTION = "model-description";
    private static final String DEFAULT = "default";
    private static final String ACCESS_CONTROL = "access-control";
    private static final String ATTRIBUTES = "attributes";
    private static final String READ_CONFIG = "read-config";
    private static final String WRITE_CONFIG = "write-config";
    private static final String READ_RUNTIME = "read-runtime";
    private static final String WRITE_RUNTIME = "write-runtime";
    private static final String ADDRESS = "address";

    private final AccessControlRegistry accessControlReg;
    private final DispatchAsync dispatcher;
    private final CoreGUIContext statementContext;

    private Map<String, SecurityContext> contextMapping = new HashMap<String, SecurityContext>();

    @Inject
    public SecurityServiceImpl(AccessControlRegistry accessControlReg, DispatchAsync dispatcher, CoreGUIContext statementContext) {
        this.accessControlReg = accessControlReg;
        this.dispatcher = dispatcher;
        this.statementContext = statementContext;
    }

    @Override
    public boolean hasContext(String nameToken) {
        return contextMapping.containsKey(nameToken);
    }

    @Override
    public SecurityContext getSecurityContext(String nameToken) {

        SecurityContext securityContext = contextMapping.get(nameToken);
        if(null==securityContext)
            throw new IllegalStateException("Security context should have been created upfront");

        return securityContext;
    }

    public void createSecurityContext(final String nameToken, final AsyncCallback<SecurityContext> callback) {

        final ModelNode operation = new ModelNode();
        operation.get(OP).set(COMPOSITE);
        operation.get(ADDRESS).setEmptyList();

        final List<ModelNode> steps = new LinkedList<ModelNode>();

        final Set<String> requiredResources = accessControlReg.getResources(nameToken);
        final Map<String, String> step2address = new HashMap<String,String>();

        for(String resource : requiredResources)
        {

            ModelNode step = AddressMapping.fromString(resource).asResource(statementContext);
            step2address.put("step-" + (steps.size() + 1), resource);   // we need this for later retrieval

            step.get(OP).set(READ_RESOURCE_DESCRIPTION_OPERATION);
            //step.get(RECURSIVE).set();

            if(accessControlReg.isRecursive(nameToken))
                step.get("recursive-depth").set(2); // Workaround for Beta2 : some browsers choke on two big payload size

            step.get("access-control").set(true);
            step.get(ATTRIBUTES).set(false);    // reduces the overall payload size
            steps.add(step);

        }

        operation.get(STEPS).set(steps);

        //System.out.println(operation);

        final long start = System.currentTimeMillis();

        dispatcher.execute(new DMRAction(operation), new SimpleCallback<DMRResponse>() {

            @Override
            public void onFailure(Throwable caught) {

                callback.onFailure(new RuntimeException("Failed to create security context for "+nameToken, caught));
            }

            @Override
            public void onSuccess(DMRResponse dmrResponse) {

                ModelNode response = dmrResponse.get();
                ModelNode overalResult = response.get(RESULT);

                SecurityContext context = new SecurityContext(nameToken, requiredResources);
                context.setFacet(Facet.valueOf(accessControlReg.getFacet(nameToken).toUpperCase()));

                try {

                    // retrieve access constraints for each required resource and update the security context
                    for(int i=1; i<=steps.size();i++)
                    {
                        String step = "step-"+i;
                        if(overalResult.hasDefined(step))
                        {
                            String resourceAddress = step2address.get(step);
                            ModelNode modelNode = overalResult.get(step).get(RESULT);

                            ModelNode payload = null;
                            if(modelNode.getType() == ModelType.LIST)
                                payload = modelNode.asList().get(0);
                            else
                                payload = modelNode;

                            // break down into root resource and children
                            parseAccessControlChildren(resourceAddress, requiredResources, context, payload);
                        }
                    }

                    context.seal(); // makes it immutable

                    contextMapping.put(nameToken, context);

                    Log.info("Context creation time (" + nameToken + "): " + (System.currentTimeMillis() - start) + "ms");

                    callback.onSuccess(context);

                } catch (Throwable e) {
                    Log.error("Failed to parse access control meta data", e);
                    callback.onFailure(new RuntimeException("Failed to parse access control meta data", e));
                }

            }
        });


    }

    private static void parseAccessControlChildren(final String resourceAddress, Set<String> requiredResources, SecurityContext context, ModelNode payload) {

        ModelNode actualPayload = payload.hasDefined(RESULT) ? payload.get(RESULT) : payload;

        // parse the root resource itself
        parseAccessControlMetaData(resourceAddress, context, actualPayload);

        // parse the child resources
        if(actualPayload.hasDefined(CHILDREN))
        {
            //List<Property> children = actualPayload.get(CHILDREN).asPropertyList();
            ModelNode childNodes = actualPayload.get(CHILDREN);
            Set<String> children = childNodes.keys();
            for(String child : children)
            {
                String childAddress = resourceAddress+"/"+child+"=*";
                if(!requiredResources.contains(childAddress)) // might be parsed already
                {
                    ModelNode childModel = childNodes.get(child);
                    if(childModel.hasDefined(MODEL_DESCRIPTION)) // depends on 'recursive' true/false
                    {
                        ModelNode childPayload = childModel.get(MODEL_DESCRIPTION).asPropertyList().get(0).getValue();
                        requiredResources.add(childAddress); /// dynamically update the list of required resources
                        parseAccessControlChildren(childAddress, requiredResources, context, childPayload);
                    }
                }
            }
        }
    }

    private static void parseAccessControlMetaData(final String resourceAddress, SecurityContext context, ModelNode payload) {

        ModelNode accessControl = payload.get(ACCESS_CONTROL);

        if(accessControl.isDefined() && accessControl.hasDefined(DEFAULT)) // TODO: overrides ...
        {
            ModelNode model = accessControl.get(DEFAULT);

            Constraints c = new Constraints();

            if(model.hasDefined(ADDRESS)
                    && model.get(ADDRESS).asBoolean()==false)
            {
                c.setAddress(false);
            }
            else
            {

                c.setReadConfig(model.get(READ_CONFIG).asBoolean());
                c.setWriteConfig(model.get(WRITE_CONFIG).asBoolean());
                c.setReadRuntime(model.get(READ_RUNTIME).asBoolean());
                c.setWriteRuntime(model.get(WRITE_RUNTIME).asBoolean());

            }

            // attribute constraints

            if(model.hasDefined(ATTRIBUTES))
            {
                List<Property> attributes = model.get(ATTRIBUTES).asPropertyList();

                for(Property att : attributes)
                {
                    ModelNode attConstraintModel = att.getValue();
                    // config access
                    if(attConstraintModel.hasDefined(READ_CONFIG))
                    {
                        c.setAttributeRead(att.getName(), attConstraintModel.get(READ_CONFIG).asBoolean());
                        c.setAttributeWrite(att.getName(), attConstraintModel.get(WRITE_CONFIG).asBoolean());
                    }

                    // runtime access
                    else
                    {
                        c.setAttributeRead(att.getName(), attConstraintModel.get(READ_RUNTIME).asBoolean());
                        c.setAttributeWrite(att.getName(), attConstraintModel.get(WRITE_RUNTIME).asBoolean());
                    }
                }
            }

            context.updateResourceConstraints(resourceAddress, c);
        }
    }

    @Override
    public void flushContext(String nameToken) {
        contextMapping.remove(nameToken);
    }
}
TOP

Related Classes of org.jboss.as.console.client.rbac.SecurityServiceImpl

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.