Initial commit
This commit is contained in:
102
backend/src/main/java/com/smartoffice/auth/AuthService.java
Normal file
102
backend/src/main/java/com/smartoffice/auth/AuthService.java
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.smartoffice.auth;
|
||||
|
||||
import com.smartoffice.common.ApiException;
|
||||
import com.smartoffice.user.Role;
|
||||
import com.smartoffice.user.User;
|
||||
import com.smartoffice.user.UserDto;
|
||||
import com.smartoffice.user.UserRepository;
|
||||
import com.smartoffice.user.UserStatus;
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Service
|
||||
public class AuthService {
|
||||
private final UserRepository userRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final JwtService jwtService;
|
||||
private final int maxAttempts;
|
||||
private final int lockMinutes;
|
||||
|
||||
public AuthService(UserRepository userRepository,
|
||||
PasswordEncoder passwordEncoder,
|
||||
AuthenticationManager authenticationManager,
|
||||
JwtService jwtService,
|
||||
@Value("${app.security.lockout.max-attempts}") int maxAttempts,
|
||||
@Value("${app.security.lockout.lock-minutes}") int lockMinutes) {
|
||||
this.userRepository = userRepository;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.jwtService = jwtService;
|
||||
this.maxAttempts = maxAttempts;
|
||||
this.lockMinutes = lockMinutes;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AuthResponse login(LoginRequest request) {
|
||||
User user = userRepository.findByUsername(request.getUsername())
|
||||
.orElseThrow(() -> new ApiException(401, "Invalid credentials"));
|
||||
|
||||
if (user.getStatus() == UserStatus.DISABLED) {
|
||||
throw new ApiException(403, "Account disabled");
|
||||
}
|
||||
if (user.getLockedUntil() != null && user.getLockedUntil().isAfter(Instant.now())) {
|
||||
throw new ApiException(423, "Account locked until " + user.getLockedUntil());
|
||||
}
|
||||
if (user.getStatus() == UserStatus.LOCKED && user.getLockedUntil() == null) {
|
||||
throw new ApiException(423, "Account locked");
|
||||
}
|
||||
if (user.getLockedUntil() != null && user.getLockedUntil().isBefore(Instant.now())) {
|
||||
user.setLockedUntil(null);
|
||||
user.setStatus(UserStatus.ACTIVE);
|
||||
user.setFailedLoginAttempts(0);
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
try {
|
||||
Authentication authentication = authenticationManager.authenticate(
|
||||
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
|
||||
UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
|
||||
user.setFailedLoginAttempts(0);
|
||||
user.setLockedUntil(null);
|
||||
user.setLastLoginAt(Instant.now());
|
||||
user.setStatus(UserStatus.ACTIVE);
|
||||
userRepository.save(user);
|
||||
String token = jwtService.generateToken(principal);
|
||||
return new AuthResponse(token, UserDto.from(user));
|
||||
} catch (Exception ex) {
|
||||
int attempts = user.getFailedLoginAttempts() + 1;
|
||||
user.setFailedLoginAttempts(attempts);
|
||||
if (attempts >= maxAttempts) {
|
||||
user.setLockedUntil(Instant.now().plusSeconds(lockMinutes * 60L));
|
||||
user.setStatus(UserStatus.LOCKED);
|
||||
}
|
||||
userRepository.save(user);
|
||||
throw new ApiException(401, "Invalid credentials");
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public UserDto register(RegisterRequest request) {
|
||||
if (userRepository.existsByUsername(request.getUsername())) {
|
||||
throw new ApiException(409, "Username already exists");
|
||||
}
|
||||
User user = new User();
|
||||
user.setUsername(request.getUsername());
|
||||
user.setPasswordHash(passwordEncoder.encode(request.getPassword()));
|
||||
user.setFullName(request.getFullName());
|
||||
user.setEmail(request.getEmail());
|
||||
user.setPhone(request.getPhone());
|
||||
user.setRole(Role.EMPLOYEE);
|
||||
user.setStatus(UserStatus.ACTIVE);
|
||||
userRepository.save(user);
|
||||
return UserDto.from(user);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user