content: package com.back2reality.security;
  
  import com.back2reality.storage.repository.UserRepository;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.security.authentication.AuthenticationManager;
  import org.springframework.security.authentication.AuthenticationProvider;
  import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
  import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
  import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
  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.configurers.AbstractHttpConfigurer;
  import org.springframework.security.config.http.SessionCreationPolicy;
  import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  import org.springframework.security.crypto.password.PasswordEncoder;
  import org.springframework.security.web.SecurityFilterChain;
  import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  import org.springframework.web.cors.CorsConfiguration;
  
  import java.util.List;
  
  /**
   * @author FLIGHT
   */
  @Configuration
  @EnableWebSecurity
  @EnableMethodSecurity
  public class SecurityContextConfiguration {
  
    @Bean
    public JwtService jwtService() {
      return new JwtService();
    }
  
    @Bean
    public UserService userService(UserRepository userRepository) {
      return new UserService(userRepository);
    }
  
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter(UserService userService, JwtService jwtService) {
      return new JwtAuthenticationFilter(jwtService, userService);
    }
  
    @Bean
    public SecurityFilterChain securityFilterChain(
      HttpSecurity http,
      JwtAuthenticationFilter jwtAuthenticationFilter,
      UserService userService) throws Exception
    {
      http.csrf(AbstractHttpConfigurer::disable)
        .cors(cors -> cors.configurationSource(request -> {
          var corsConfiguration = new CorsConfiguration();
          corsConfiguration.setAllowedOriginPatterns(List.of("*"));
          corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
          corsConfiguration.setAllowedHeaders(List.of("*"));
          corsConfiguration.setAllowCredentials(true);
          return corsConfiguration;
        }))
        .authorizeHttpRequests(request -> request
          .requestMatchers("/auth/**").permitAll()
          .requestMatchers("/security/**").permitAll()
          .requestMatchers("/event/**").permitAll()
          .requestMatchers("/admin/**").hasAnyRole("ADMIN", "OWNER")
          .anyRequest().authenticated())
        .sessionManagement(manager -> manager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .authenticationProvider(authenticationProvider(userService))
        .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
      return http.build();
    }
  
    @Bean
    public PasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
    }
  
    @Bean
    public AuthenticationProvider authenticationProvider(UserService userService) {
      DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
      authProvider.setUserDetailsService(userService.userDetailsService());
      authProvider.setPasswordEncoder(passwordEncoder());
      return authProvider;
    }
  
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
      return config.getAuthenticationManager();
    }
  
    @Bean
    public AuthenticationService authenticationService(
      UserService userService,
      JwtService jwtService,
      PasswordEncoder passwordEncoder,
      AuthenticationManager authenticationManager)
    {
      return new AuthenticationService(
        userService,
        jwtService,
        passwordEncoder,
        authenticationManager
      );
    }
  }
  