content: package com.example.identityservice.auth;
  
  import com.example.identityservice.token.JwtService;
  import com.example.identityservice.token.Token;
  import com.example.identityservice.token.TokenRepository;
  import com.example.identityservice.token.TokenType;
  import com.example.identityservice.user.Role;
  import com.example.identityservice.user.User;
  import com.example.identityservice.user.UserRepository;
  import lombok.RequiredArgsConstructor;
  import org.springframework.security.authentication.AuthenticationManager;
  import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  import org.springframework.security.crypto.password.PasswordEncoder;
  import org.springframework.stereotype.Service;
  
  @Service
  @RequiredArgsConstructor
  public class AuthenticationService {
  
      private final UserRepository repository;
      private final TokenRepository tokenRepository;
      private final PasswordEncoder passwordEncoder;
      private final JwtService jwtService;
      private final AuthenticationManager authManager;
  
      public AuthenticationResponse register(RegisterRequest request) {
          var user = User.builder()
                  .firstname(request.getFirstname())
                  .lastname(request.getLastname())
                  .email(request.getEmail())
                  .password(passwordEncoder.encode(request.getPassword()))
                  .role(Role.USER)
                  .build();
  
          if (repository.findByEmail(request.getEmail()).isPresent()) {
              throw new IllegalArgumentException("Username already exists.");
          }
  
          var savedUser = repository.save(user);
          var jwtToken = jwtService.generateToken(user);
          saveUserToken(savedUser, jwtToken);
  
          return AuthenticationResponse.builder()
                  .token(jwtToken)
                  .build();
      }
  
      public AuthenticationResponse authenticate(AuthenticationRequest request) {
          authManager.authenticate(
  
                  new UsernamePasswordAuthenticationToken(
                          request.getEmail(),
                          request.getPassword()
                  )
          );
  
          var user = repository.findByEmail(request.getEmail()).orElseThrow();
  
          var jwtToken = jwtService.generateToken(user);
          revokeAllUserTokens(user);
          saveUserToken(user, jwtToken);
  
          return AuthenticationResponse.builder()
                  .token(jwtToken)
                  .build();
      }
  
      private void revokeAllUserTokens(User user) {
          var validUserTokens = tokenRepository.findAllValidTokensByUser(user.getId());
  
          if (validUserTokens.isEmpty()) return;
  
          validUserTokens.forEach(t -> {
              t.setExpired(true);
              t.setRevoked(true);
          });
  
          tokenRepository.saveAll(validUserTokens);
      }
  
      private void saveUserToken(User user, String jwtToken) {
          var token = Token.builder()
                  .user(user)
                  .token(jwtToken)
                  .tokenType(TokenType.BEARER)
                  .revoked(false)
                  .expired(false)
                  .build();
  
          tokenRepository.save(token);
      }
  }
  