package jp.sourceforge.shovel.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;


import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.aop.interceptors.AbstractInterceptor;
import org.seasar.framework.container.ContainerConstants;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.annotation.tiger.Binding;
import org.seasar.framework.container.annotation.tiger.BindingType;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

import jp.sourceforge.shovel.annotation.Perform;
import jp.sourceforge.shovel.entity.IUser;
import jp.sourceforge.shovel.entity.TokenProcessorWrapper;
import jp.sourceforge.shovel.exception.ApplicationRuntimeException;

import static jp.sourceforge.shovel.ErrorConst.*;
import static jp.sourceforge.shovel.SessionConst.*;

public class CsrfInterceptor extends AbstractInterceptor {
    private static final long serialVersionUID = 1L;

    public Object invoke(MethodInvocation invocation) throws Throwable {
        if (isCsrf(invocation)) {
            checkCSRF();
        }
        return invocation.proceed();
    }
    boolean isCsrf(MethodInvocation invocation) {
        Perform annotation = invocation.getMethod().getAnnotation(Perform.class);
        return annotation == null ? true : annotation.CSRF();
    }
    void checkCSRF() {
        String token1 = getRequest().getParameter( S_CSRF_TICKET );
        if( token1 == null )
        {
            throw new ApplicationRuntimeException( E_COMMON_CSRF_NO_TICKET );
        }
        String token2 = (String)getSession().getAttribute( S_CSRF_TICKET );
        if( !token1.equals( token2 ) )
        {
            throw new ApplicationRuntimeException( E_COMMON_CSRF_INVALID_TICKET );
        }
    }
    @Binding(bindingType=BindingType.NONE)
    public static void setCsrfTicket(IUser user) {
        String userId = String.valueOf(user.getUserId());
        String ticket = getTokenProcessor().generateToken(userId);
        getSession().setAttribute(S_CSRF_TICKET, ticket);
    }
    
    static S2Container getContainer() {
        return SingletonS2ContainerFactory.getContainer();
    }
    static HttpServletRequest getRequest() {
        return (HttpServletRequest)getContainer().getComponent(ContainerConstants.REQUEST_NAME);
    }
    static HttpSession getSession() {
        return getRequest().getSession(true);
    }
    static TokenProcessorWrapper getTokenProcessor() {
        return new TokenProcessorWrapper();
    }
}
