package com.daedafusion.security.authorization.impl;

import com.daedafusion.sf.AbstractService;
import com.daedafusion.security.authentication.Subject;
import com.daedafusion.security.authorization.Authorization;
import com.daedafusion.security.authorization.providers.AuthorizationProvider;
import com.daedafusion.security.common.Context;
import com.daedafusion.security.common.impl.DefaultContext;
import com.daedafusion.security.decision.Decision;
import com.daedafusion.security.decision.impl.UnanimousResultCombiner;
import com.daedafusion.security.obligation.Obligation;
import com.daedafusion.security.obligation.ObligationHandler;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

/**
 * Created by mphilpot on 7/14/14.
 */
public class UnanimousResultAuthorizationImpl extends AbstractService<AuthorizationProvider> implements Authorization
{
    private static final Logger log = Logger.getLogger(UnanimousResultAuthorizationImpl.class);

    @Override
    public boolean isAuthorized(Subject subject, URI resource, String action, Context context)
    {
        List<Decision> decisions = new ArrayList<>();

        for(AuthorizationProvider provider : getProviders())
        {
            decisions.add(provider.getAccessDecision(subject, resource, action, context));
        }

        UnanimousResultCombiner combiner = new UnanimousResultCombiner();
        Decision combinedResult = combiner.getCombinedResult(decisions);

        ObligationHandler handler = getServiceRegistry().getService(ObligationHandler.class);


        DefaultContext.Builder builder = DefaultContext.builder()
                .addContext("auth:resource", resource.toString())
                .addContext("auth:action", action);

        context.getKeys().forEach(key -> builder.setContext(key, context.getContext(key)));
        Context obligationContext = builder.build();

        if(combinedResult.getResult().equals(Decision.Result.PERMIT))
        {
            combinedResult.getObligations().stream().filter(ob -> ob.getFulfillment().equals(Obligation.Fulfillment.ON_PERMIT))
                    .forEach(ob -> handler.handle(ob, obligationContext));

            return true;
        }
        else
        {
            combinedResult.getObligations().stream().filter(ob -> ob.getFulfillment().equals(Obligation.Fulfillment.ON_DENY))
                    .forEach(ob -> handler.handle(ob, obligationContext));

            return false;
        }
    }

    @Override
    public boolean isAuthorized(Subject subject, HttpServletRequest request, Context context)
    {
        URI uri = URI.create(request.getRequestURI());
        String action = request.getMethod();

        DefaultContext.Builder builder = DefaultContext.builder();
        context.getKeys().forEach(key -> context.getContext(key).forEach(value -> builder.addContext(key, value)));
        Collections.list((Enumeration<String>)request.getHeaderNames()).forEach(key -> builder.addContext(key, request.getHeader(key)));

        Context updatedContext = builder.build();

        return isAuthorized(subject, uri, action, updatedContext);
    }

    @Override
    public Class getProviderInterface()
    {
        return AuthorizationProvider.class;
    }
}

@@ -47,16 +47,68 @@
 .impl;%0A%0A
+import com.daedafusion.configuration.Configuration;%0A
 import c
@@ -142,16 +142,16 @@
 ervice;%0A
-
 import c
@@ -681,24 +681,69 @@
 ionHandler;%0A
+import com.daedafusion.sf.LifecycleListener;%0A
 import org.a
@@ -847,25 +847,17 @@
 va.util.
-ArrayList
+*
 ;%0Aimport
@@ -871,72 +871,25 @@
 til.
-Collections;%0Aimport java.util.Enumeration;%0Aimport java.util.List
+stream.Collectors
 ;%0A%0A/
@@ -1143,24 +1143,786 @@
 pl.class);%0A%0A
+    private Set%3CAuthorizationProvider%3E enabledProviders;%0A%0A    public UnanimousResultAuthorizationImpl()%0A    %7B%0A        addLifecycleListener(new LifecycleListener()%0A        %7B%0A            @Override%0A            public void postStart()%0A            %7B%0A                Set%3CString%3E disabledProviders = Arrays.stream(%0A                        Configuration.getInstance().getString(%22security.disabledAuthorizationProviders%22, %22%22).split(%22,%22))%0A                        .map(String::trim)%0A                        .collect(Collectors.toSet());%0A                enabledProviders = getProviders().stream()%0A                        .filter(p -%3E !disabledProviders.contains(p.getClass().getName()))%0A                        .collect(Collectors.toSet());%0A            %7D%0A        %7D);%0A    %7D%0A%0A
     @Overrid
@@ -2124,19 +2124,23 @@
 vider : 
-get
+enabled
 Provider
@@ -2140,18 +2140,16 @@
 roviders
-()
 )%0A      

Allow env disabling of auth providers