package com.cmeeting.ad.config;

import cn.hutool.core.util.ArrayUtil;
import com.cmeeting.ad.filter.RobotJwtAuthenticationTokenFilter;
import com.cmeeting.ad.handler.RobotAccessDeniedHandler;
import com.cmeeting.ad.handler.RobotAuthenticationEntryPointImpl;
import com.cmeeting.ad.service.CustomUserDetailsService;
import com.cmeeting.ad.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Classname WebSecurityConfig
 * @Description Security配置类
 * @Author robot
 * @Date 2019-05-07 09:10
 * @Version 1.0
 */
@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class RobotWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RobotJwtAuthenticationTokenFilter robotJwtAuthenticationTokenFilter;
    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    /**
     * 解决 无法直接注入 AuthenticationManager
     *
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();

    }

    @Bean(name = "customAuthenticationProvider")
    public AuthenticationProvider customAuthenticationProvider() {
        CustomAuthenticationProvider customAuthenticationProvider = new CustomAuthenticationProvider();
        customAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
        customAuthenticationProvider.setHideUserNotFoundExceptions(false);
        customAuthenticationProvider.setCustomUserDetailsService(customUserDetailsService);
        return customAuthenticationProvider;
    }

    @Bean(name = "bCryptPasswordEncoder")
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        return bCryptPasswordEncoder;
    }

    /**
     * 配置策略
     *
     * @param httpSecurity
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 由于使用的是JWT，我们这里不需要csrf
                .csrf().disable()
                // 基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                // 过滤请求
                .authorizeRequests()
                // 对于登录login 图标 要允许匿名访问
//                .antMatchers(customApi).access("@robotJwtCustomTokenFilter.checkToken(request)")
                .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css",
        "/**/*.js", "/**/*.map")
                .permitAll()
                .antMatchers("/error").anonymous()
                .antMatchers("/agent/auth/**").anonymous()
                .antMatchers("/user/login").anonymous()
                .antMatchers("/user/userAuth").anonymous()
                .antMatchers("/user/tokenAuth").anonymous()
                .antMatchers("/user/emailAuth").anonymous()
                .antMatchers("/web/**").anonymous()
                .antMatchers("/file/**")
                .permitAll()
                // 访问/user 需要拥有admin权限
                //  .antMatchers("/user").hasAuthority("ROLE_ADMIN")
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated()
                .and()
                .headers().frameOptions().disable();


        // 添加自定义异常入口
        httpSecurity
                .exceptionHandling()
                .authenticationEntryPoint(new RobotAuthenticationEntryPointImpl())
                .accessDeniedHandler(new RobotAccessDeniedHandler());

        // 添加JWT filter 用户名登录
        httpSecurity
                // 添加JWT验证过滤器
                .addFilterBefore(robotJwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider());
    }

}

