package cn.qinys.platform.base.security;

import cn.qinys.platform.base.security.filter.AuthenticationTokenFilter;
import cn.qinys.platform.base.security.handler.BaseAccessDeniedHandler;
import cn.qinys.platform.base.security.handler.BaseAuthenticationEntryPoint;
import cn.qinys.platform.base.security.properties.JwtProperties;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * Description: security 配置
 *
 * @author tanlie
 * Date: 2023/12/22 16:41
 */
@Configuration
public class BaseWebSecurityConfiguration {
    // configuration registers SecurityFilterChain bean
    @Resource
    private JwtProperties jwtProperties;
    @Resource
    private AuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Resource
    private BaseAuthenticationEntryPoint authenticationEntryPoint;
    @Resource
    private BaseAccessDeniedHandler accessDeniedHandler;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // Disable CSRF
                .csrf(AbstractHttpConfigurer::disable)
                // Stateless session management
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                // Authorization rules
                .authorizeHttpRequests(authorize -> authorize
                        // Allow preflight OPTIONS requests
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                        // Allow ignore urls from properties
                        .requestMatchers(jwtProperties.getIgnoreUrls().toArray(new String[0])).permitAll()
                        // All other requests require authentication
                        .anyRequest().authenticated()
                )
                // Exception handling
                .exceptionHandling(ex -> ex
                        .authenticationEntryPoint(authenticationEntryPoint)
                        .accessDeniedHandler(accessDeniedHandler)
                )
                // Add JWT filter before UsernamePasswordAuthenticationFilter
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
}
