package com.daedafusion.security.bindings;

import com.daedafusion.configuration.Configuration;
import com.daedafusion.sf.ServiceFramework;
import com.daedafusion.sf.ServiceFrameworkException;
import com.daedafusion.sf.ServiceFrameworkFactory;
import com.daedafusion.security.authentication.Subject;
import com.daedafusion.security.authentication.Token;
import com.daedafusion.security.authentication.TokenExchange;
import com.daedafusion.security.exceptions.InvalidTokenException;
import org.apache.log4j.Logger;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.regex.Pattern;

/**
 * Created by mphilpot on 7/11/14.
 */
public class AuthorizationTokenFilter implements Filter
{
    private static final Logger log = Logger.getLogger(AuthorizationTokenFilter.class);

    private ServiceFramework framework;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        framework = ServiceFrameworkFactory.getInstance().getFramework(); // assume framework is already started
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        // Handle excludes
        String authorizationExcludes = Configuration.getInstance().getString("authorizationFilter.pathExclude", null);

        if(authorizationExcludes != null)
        {
            String[] paths = authorizationExcludes.split(":");

            String path = httpServletRequest.getRequestURI();

            for (String p : paths)
            {
                if (path.startsWith(p))
                {
                    log.info(String.format("Request %s excluded from authorization", path));
                    chain.doFilter(request, response);
                    return;
                }
            }
        }

        String authorizationToken = httpServletRequest.getHeader("Authorization");

        try
        {
            TokenExchange tokenExchange = framework.getService(TokenExchange.class);

            // Strip "Bearer " if present
            authorizationToken = authorizationToken.replaceAll("(?i)"+ Pattern.quote("Bearer "), "");

            Token token = tokenExchange.getToken(authorizationToken);
            Subject subject = tokenExchange.exchange(token);

            if(subject == null)
            {
                throw new ServletException(String.format("Token (%s) did not map to subject", authorizationToken));
            }

            LocalSubjectStorage.set(subject);
        }
        catch (ServiceFrameworkException e)
        {
            log.error("Framework error", e);
            // TODO return 500 error
            throw new ServletException("Framework error");
        }
        catch (InvalidTokenException e)
        {
            log.error("Invalid Token", e);
            throw new ServletException("Invalid token");
        }

        chain.doFilter(request, response);
    }

    @Override
    public void destroy()
    {

    }
}

@@ -85,24 +85,90 @@
 figuration;%0A
+import com.daedafusion.security.exceptions.UnauthorizedException;%0A
 import com.d
@@ -644,16 +644,63 @@
 equest;%0A
+import javax.servlet.http.HttpServletResponse;%0A
 import j
@@ -1423,16 +1423,98 @@
 request;
+%0A        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
 %0A%0A      
@@ -2239,24 +2239,181 @@
 ization%22);%0A%0A
+        if(authorizationToken == null)%0A        %7B%0A            httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN);%0A            return;%0A        %7D%0A%0A
         try%0A
@@ -2851,166 +2851,254 @@
     
-throw new ServletException(String.format(%22Token (%25s) did not map to subject%22, authorizationToken));%0A            %7D%0A%0A            LocalSubjectStorage.set(subject
+httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);%0A                return;%0A            %7D%0A%0A            LocalSubjectStorage.set(subject);%0A%0A            // Valid Subject -- execute request%0A            chain.doFilter(request, response
 );%0A 
@@ -3221,89 +3221,82 @@
     
-// TODO return 500 error%0A            throw new ServletException(%22Framework error%22
+httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR
 );%0A 
@@ -3413,35 +3413,75 @@
     
-throw new ServletException(
+httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, 
 %22Inv
@@ -3485,17 +3485,17 @@
 Invalid 
-t
+T
 oken%22);%0A
@@ -3507,52 +3507,8 @@
    %7D
-%0A%0A        chain.doFilter(request, response);
 %0A   

Clean up error handling in Token Filter