package amu.zhcet.security;

import amu.zhcet.auth.UserDetailService;
import amu.zhcet.auth.login.persistent.PersistentTokenService;
import amu.zhcet.data.user.Role;
import amu.zhcet.firebase.auth.FirebaseAuthenticationProvider;
import amu.zhcet.firebase.auth.FirebaseAutheticationFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationEventPublisher;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.session.SessionRegistry;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Configuration
@EnableWebSecurity
class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final PersistentTokenService persistentTokenService;
    private final AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource;
    private final DefaultWebSecurityExpressionHandler securityExpressionHandler;
    private final SessionRegistry sessionRegistry;
    private final AuthenticationFailureHandler authenticationFailureHandler;
    private final FirebaseAutheticationFilter firebaseAutheticationFilter;

    @Autowired
    public SecurityConfiguration(
            PersistentTokenService persistentTokenService,
            AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource,
            DefaultWebSecurityExpressionHandler securityExpressionHandler,
            SessionRegistry sessionRegistry,
            AuthenticationFailureHandler authenticationFailureHandler,
            FirebaseAutheticationFilter firebaseAutheticationFilter) {
        this.persistentTokenService = persistentTokenService;
        this.authenticationDetailsSource = authenticationDetailsSource;
        this.securityExpressionHandler = securityExpressionHandler;
        this.sessionRegistry = sessionRegistry;
        this.authenticationFailureHandler = authenticationFailureHandler;
        this.firebaseAutheticationFilter = firebaseAutheticationFilter;
    }

    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authBuilder, UserDetailService userDetailsService, PasswordEncoder passwordEncoder) throws Exception {
        authBuilder
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder);
    }

    @Autowired
    public void configureFirebaseAuthentication(AuthenticationManagerBuilder authBuilder, FirebaseAuthenticationProvider firebaseAuthenticationProvider) {
        authBuilder.authenticationProvider(firebaseAuthenticationProvider);
    }

    @Autowired
    public void configureEventPublisher(AuthenticationManagerBuilder authBuilder, AuthenticationEventPublisher authenticationEventPublisher) {
        authBuilder.authenticationEventPublisher(authenticationEventPublisher);
    }

    @Override
    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .addFilterBefore(firebaseAutheticationFilter, UsernamePasswordAuthenticationFilter.class)

                .authorizeRequests()
                .expressionHandler(securityExpressionHandler)

                .requestMatchers(EndpointRequest.toAnyEndpoint())
                .hasRole(Role.DEVELOPMENT_ADMIN.name())

                .antMatchers("/").permitAll()

                .antMatchers("/profile/**").authenticated()

                .antMatchers("/dashboard/**").authenticated()

                .antMatchers("/dashboard/student/**")
                .hasAuthority(Role.STUDENT.toString())

                .antMatchers("/notifications/{id}/**")
                .access("@permissionManager.checkNotificationRecipient(authentication, #id)")
                .antMatchers("/notifications/**")
                .authenticated()

                .antMatchers("/management/notifications/{id}/**")
                .access("@permissionManager.checkNotificationCreator(authentication, #id)")
                .antMatchers("/management/**")
                .hasAuthority(Role.TEACHING_STAFF.toString())

                .antMatchers("/admin/dean/**")
                .hasAuthority(Role.DEAN_ADMIN.toString())

                .antMatchers("/admin/department/courses/{course}/**",
                        "/admin/department/floated/{course}/**",
                        "/admin/department/float/{course}/**")
                .access("@permissionManager.checkCourse(authentication, #course)")

                .antMatchers("/admin/department/{department}/**")
                .access("@permissionManager.checkDepartment(authentication, #department)")
                .antMatchers("/admin/department/**")
                .hasAuthority(Role.DEPARTMENT_ADMIN.toString())

                .antMatchers("/admin/faculty/**")
                .hasAuthority(Role.FACULTY.toString())

                .and()
                .formLogin()
                .authenticationDetailsSource(authenticationDetailsSource)
                .loginPage("/login").permitAll()
                .failureHandler(authenticationFailureHandler)
                .usernameParameter("username")
                .passwordParameter("password")

                .and()
                .logout().logoutSuccessUrl("/login?logout").permitAll()

                .and()
                .rememberMe()
                .rememberMeCookieName("zhcet-remember-me")
                .tokenValiditySeconds(24 * 60 * 60)
                .tokenRepository(persistentTokenService)

                .and()
                .sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry);
    }
}

@@ -1388,103 +1388,8 @@
 er;%0A
-import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;%0A
 impo
@@ -1990,89 +1990,8 @@
 ce;%0A
-    private final DefaultWebSecurityExpressionHandler securityExpressionHandler;%0A
     
@@ -2417,83 +2417,8 @@
 ce,%0A
-            DefaultWebSecurityExpressionHandler securityExpressionHandler,%0A
     
@@ -2738,76 +2738,8 @@
 ce;%0A
-        this.securityExpressionHandler = securityExpressionHandler;%0A
     
@@ -4211,70 +4211,8 @@
 ts()
-%0A                .expressionHandler(securityExpressionHandler)
 %0A%0A  
@@ -5935,16 +5935,65 @@
 Login()%0A
+                .loginPage(%22/login%22).permitAll()%0A
         
@@ -6062,57 +6062,8 @@
 ce)%0A
-                .loginPage(%22/login%22).permitAll()%0A
     
@@ -6120,16 +6120,17 @@
 andler)%0A
+%0A
         
@@ -6142,106 +6142,49 @@
    .
-usernameParameter(%22username%22)%0A                .passwordParameter(%22password%22)%0A%0A                .and
+and()%0A                .logout().permitAll
 ()%0A 
@@ -6198,25 +6198,16 @@
         
-.logout()
 .logoutS
@@ -6232,28 +6232,16 @@
 logout%22)
-.permitAll()
 %0A%0A      
@@ -6515,16 +6515,33 @@
 gement()
+%0A                
 .maximum
@@ -6551,16 +6551,33 @@
 sions(1)
+%0A                
 .session
@@ -6601,16 +6601,62 @@
 egistry)
+%0A                .expiredUrl(%22/login?expired%22)
 ;%0A    %7D%0A

Straighten out web security config