package org.codiki.core.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;


@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.BASIC_AUTH_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
	
	private static final String XSRF_REPOSITORY_HEADER_NAME = "X-XSRF-TOKEN";

	@Autowired
	private CustomAuthenticationProvider authenticationProvider;
	@Autowired
	private RestAuthenticationEntryPoint authenticationEntryPoint;
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.authenticationProvider(authenticationProvider);
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.antMatchers(
				"/api/account/login",
				"/api/account/logout",
				"/api/account/signin"
			).permitAll()
			.antMatchers(
				"/api/images/uploadAvatar",
				"/api/images/myImages",
				"/api/posts/myPosts"
			).authenticated()
			.antMatchers(
					HttpMethod.GET,
					"/api/categories",
					"/api/images",
					"/api/posts",
					"/api/categories/**",
					"/api/images/**",
					"/api/posts/**"
			).permitAll()
			.anyRequest().authenticated()
			.and()
			// Allow to avoid login form at authentication failure from Angular app
			.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
			.and()
			.addFilterAfter(new XSRFTokenFilter(), CsrfFilter.class)
			.csrf()
			.csrfTokenRepository(xsrfTokenRepository());
		http.httpBasic();
		http.csrf().disable();
	}
	
	private CsrfTokenRepository xsrfTokenRepository() {
		HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
		repository.setHeaderName(XSRF_REPOSITORY_HEADER_NAME);
		return repository;
	}
}