package com.style24.front.support.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import com.style24.front.support.security.TsfAuthenticationProvider;
import com.style24.front.support.security.filter.TsfAuthenticationFilter;
import com.style24.front.support.security.handler.TsfLoginFailureHandler;
import com.style24.front.support.security.handler.TsfLoginSuccessHandler;
import com.style24.front.support.security.handler.TsfLogoutSuccessHandler;

import com.gagaframework.web.security.GagaCsrfSecurityRequestMatcher;

/**
 * Java Security를 이용한 Login 처리
 * 
 * @author gagamel
 * @since 2020. 9. 11
 */
@Configuration
@EnableWebSecurity
public class TsfSecurityConfig extends WebSecurityConfigurerAdapter {

	private static final String[] UNAUTHORIZED_RESOURCE_LIST = new String[] {"/*", "/index", "/signin/**"};

	private static final String[] UNSECURED_RESOURCE_LIST = new String[] {"/images/**", "/ux/**", "/data/**"};

	@Autowired
	private TsfAuthenticationProvider authenticationProvider;

	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		// static resources
		httpSecurity
			.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
			.authorizeRequests()
			.antMatchers(UNAUTHORIZED_RESOURCE_LIST).permitAll()
			.and()
			.formLogin()
			.usernameParameter("loginId")
			.passwordParameter("passwd")
			.loginPage("/signin")
			.loginProcessingUrl("/login")
//			.successHandler(loginSuccessHandler) // authenticationFilter() 안에 설정
//			.failureHandler(loginFailureHandler) // authenticationFilter() 안에 설정
//			.failureUrl("/signin?error=true")
			.and()
			.logout()
			.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
			.logoutSuccessHandler(logoutSuccessHandler())
			.and()
//			.csrf().disable() // CSRF(Cross Site Request Forgery) 해제
			.csrf().requireCsrfProtectionMatcher(requireCsrfProtectionMatcher())
			.and()
			.exceptionHandling()
			.accessDeniedPage("/403")
			.and()
			.headers().frameOptions().disable() // iframe deny 설정 제거(네이버스마트에디터 사용 때문에 추가)
		;
	}

	@Override
	public void configure(WebSecurity webSecurity) throws Exception {
		webSecurity
			.ignoring()
			.antMatchers(UNSECURED_RESOURCE_LIST);
	}

	@Bean
	public RequestMatcher requireCsrfProtectionMatcher() {
		GagaCsrfSecurityRequestMatcher bean = new GagaCsrfSecurityRequestMatcher();

		bean.setDisableUrls(new String[] {
			"/",
			"/index"
		});

		return bean;
	}

	/**
	 * Register the Authentication Provider
	 */
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(authenticationProvider);
	}

	@Bean
	public TsfLoginSuccessHandler loginSuccessHandler() {
		return new TsfLoginSuccessHandler();
	}

	@Bean
	public TsfLoginFailureHandler loginFailureHandler() {
		return new TsfLoginFailureHandler();
	}

	@Bean
	public TsfLogoutSuccessHandler logoutSuccessHandler() {
		return new TsfLogoutSuccessHandler();
	}

	/**
	 * Authentication Filter
	 * @return
	 * @throws Exception
	 * @author gagamel
	 * @since 2020. 2. 20
	 */
	public TsfAuthenticationFilter authenticationFilter() throws Exception {
		TsfAuthenticationFilter filter = new TsfAuthenticationFilter();
		filter.setAuthenticationManager(authenticationManagerBean());
		filter.setAuthenticationSuccessHandler(loginSuccessHandler());
		filter.setAuthenticationFailureHandler(loginFailureHandler());
		return filter;
	}

}
