package org.xcolab.view.auth.handlers;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication
        .SavedRequestAwareAuthenticationSuccessHandler;

import org.xcolab.client.admin.attributes.platform.PlatformAttributeKey;
import org.xcolab.client.members.MembersClient;
import org.xcolab.client.members.PermissionsClient;
import org.xcolab.client.members.pojo.Member;
import org.xcolab.commons.exceptions.InternalException;
import org.xcolab.entity.utils.LinkUtils;
import org.xcolab.view.auth.AuthenticationService;
import org.xcolab.view.pages.redballoon.utils.BalloonService;

import java.io.IOException;

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

import static org.xcolab.view.config.spring.beans.SsoClientConfig.SsoFilter
        .SSO_SAVED_REFERER_SESSION_ATTRIBUTE;

public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    private static final Logger log = LoggerFactory.getLogger(AuthenticationSuccessHandler.class);

    private static final String COLAB_URL = PlatformAttributeKey.COLAB_URL.get();

    private final AuthenticationService authenticationService;
    private final BalloonService balloonService;
    private final boolean allowLogin;

    public AuthenticationSuccessHandler(AuthenticationService authenticationService,
            BalloonService balloonService, boolean allowLogin) {
        this.authenticationService = authenticationService;
        this.balloonService = balloonService;
        this.allowLogin = allowLogin;
        setDefaultTargetUrl("/");

        //TODO COLAB-2362: Rethink circular dependency
        authenticationService.setAuthenticationSuccessHandler(this);
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException {
        onAuthenticationSuccess(request, response, authentication, true);
    }

    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication, boolean redirectOnSuccess) throws IOException {
        final Member member = authenticationService.getRealMemberOrNull();
        if (member == null) {
            // This can currently happen when there's an error during SSO
            // In that case, the CustomPrincipalExtractor returns null
            // An error message will already be saved in an AlertMessage
            log.warn("Member was null after authentication: {}", authentication.toString());
            getRedirectStrategy().sendRedirect(request, response, "/");
            return;
        }

        if (!allowLogin && !PermissionsClient.canAdminAll(member)) {
            authenticationService.logout(request, response);
            getRedirectStrategy().sendRedirect(request, response, "/loginDisabled");
            return;
        }

        balloonService.associateBalloonTrackingWithUser(request, member);

        final HttpSession session = request.getSession();
        String refererHeader;
        if (session.getAttribute(SSO_SAVED_REFERER_SESSION_ATTRIBUTE) != null) {
            refererHeader = (String) session.getAttribute(SSO_SAVED_REFERER_SESSION_ATTRIBUTE);
            session.removeAttribute(SSO_SAVED_REFERER_SESSION_ATTRIBUTE);
        } else {
            refererHeader = request.getHeader(HttpHeaders.REFERER);
        }
        MembersClient.createLoginLog(member.getId_(), request.getRemoteAddr(), refererHeader);

        if (redirectOnSuccess) {
            try {
                //Make URI relative to prevent injection of external redirect URIs
                final String redirect = LinkUtils.getRelativeUri(refererHeader);
                if (StringUtils.isNotBlank(redirect) && isLocalReferer(refererHeader)
                        && !isFromLoginPage(redirect)) {
                    getRedirectStrategy().sendRedirect(request, response, redirect);
                } else {
                    super.onAuthenticationSuccess(request, response, authentication);
                }
            } catch (ServletException e) {
                // Not reachable - no ServletException is thrown by the implementations
                throw new InternalException(e);
            }
        }
    }

    private boolean isLocalReferer(String refererHeader) {
        return refererHeader.startsWith(COLAB_URL);
    }

    private boolean isFromLoginPage(String refererHeader) {
        return refererHeader.endsWith("/login");
    }
}

@@ -291,25 +291,16 @@
 tication
-%0A        
 .SavedRe
@@ -344,81 +344,8 @@
 r;%0A%0A
-import org.xcolab.client.admin.attributes.platform.PlatformAttributeKey;%0A
 impo
@@ -974,25 +974,16 @@
 soFilter
-%0A        
 .SSO_SAV
@@ -1216,91 +1216,8 @@
 );%0A%0A
-    private static final String COLAB_URL = PlatformAttributeKey.COLAB_URL.get();%0A%0A
     
@@ -3690,16 +3690,116 @@
   try %7B%0A
+                if (StringUtils.isNotBlank(refererHeader) && !isFromLoginPage(refererHeader)) %7B%0A    
         
@@ -3885,24 +3885,28 @@
             
+    
 final String
@@ -3934,178 +3934,32 @@
 .get
-RelativeUri(refererHeader);%0A                if (StringUtils.isNotBlank(redirect) && isLocalReferer(refererHeader)%0A                        && !isFromLoginPage(redirect)) %7B
+LocalUrl(refererHeader);
 %0A   
@@ -4383,126 +4383,8 @@
  %7D%0A%0A
-    private boolean isLocalReferer(String refererHeader) %7B%0A        return refererHeader.startsWith(COLAB_URL);%0A    %7D%0A%0A
     

Use new LinkUtils methods