content: package com.activecourses.upwork.config.security;
  
  import com.activecourses.upwork.config.security.jwt.AuthEntryPointJwt;
  import com.activecourses.upwork.config.security.jwt.AuthTokenFilter;
  import lombok.RequiredArgsConstructor;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.security.authentication.AuthenticationManager;
  import org.springframework.security.config.Customizer;
  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;
  
  @Configuration
  @EnableWebSecurity
  @RequiredArgsConstructor
  @EnableMethodSecurity(securedEnabled = true, prePostEnabled = true)
  public class SecurityConfig {
  
      private static final String[] AUTH_WHITELIST = {
              "/api/auth/**",
              "/v2/api-docs",
              "/v3/api-docs",
              "/v3/api-docs/**",
              "/api-docs/**",
              "/api-doc/**",
              "/swagger-resources",
              "/swagger-resources/**",
              "/configuration/ui",
              "/configuration/security",
              "/swagger-ui/**",
              "/webjars/**",
              "/swagger-ui/index.html",
              "/swagger-ui.html",
              "/api/test/all"
      };
  
      private static final String[] AUTH_ADMIN = {
              "/api/admin/**"
      };
  
      private static final String[] AUTH_FREELANCER = {
              "/api/freelancer/**"
      };
  
      private static final String[] AUTH_CLIENT = {
              "/api/client/**"
      };
  
      private final AuthEntryPointJwt unauthorizedHandler;
  
      @Bean
      public AuthTokenFilter authenticationJwtTokenFilter() {
          return new AuthTokenFilter();
      }
  
      @Bean
      public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
          return config.getAuthenticationManager();
      }
  
      @Bean
      public PasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder(10);
      }
  
      @Bean
      public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
          http.csrf(AbstractHttpConfigurer::disable)
                  .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
                  .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                  .authorizeHttpRequests(configurer -> configurer
                          .requestMatchers(AUTH_WHITELIST).permitAll()
                          .requestMatchers(AUTH_ADMIN).hasRole("ADMIN")  // Only admins can access admin routes
                          .requestMatchers(AUTH_FREELANCER).hasRole("FREELANCER")  // Freelancer access
                          .requestMatchers(AUTH_CLIENT).hasRole("CLIENT")  // Client access
                          .anyRequest().authenticated()
                  );
  
          http.httpBasic(Customizer.withDefaults());
          http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
  
          return http.build();
      }
  }
  