sakthivikram/geo-location
0
1package com.georeport.service;2 3import com.georeport.dto.AuthResponse;4import com.georeport.dto.LoginRequest;5import com.georeport.dto.RegisterRequest;6import com.georeport.dto.GoogleLoginRequest;7import com.georeport.entity.Role;8import com.georeport.entity.RoleType;9import com.georeport.entity.User;10import com.georeport.exception.BadRequestException;11import com.georeport.exception.ResourceNotFoundException;12import com.georeport.repository.RoleRepository;13import com.georeport.repository.UserRepository;14import com.georeport.security.JwtTokenProvider;15import org.springframework.beans.factory.annotation.Autowired;16import org.springframework.security.authentication.AuthenticationManager;17import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;18import org.springframework.security.core.Authentication;19import org.springframework.security.core.context.SecurityContextHolder;20import org.springframework.security.crypto.password.PasswordEncoder;21import org.springframework.stereotype.Service;22import org.springframework.transaction.annotation.Isolation;23import org.springframework.transaction.annotation.Transactional;24 25import java.time.LocalDateTime;26import java.util.stream.Collectors;27 28/**29 * Service for authentication operations.30 * Handles user registration, login, and token management.31 */32@Service33public class AuthService {34 35 @Autowired36 private UserRepository userRepository;37 38 @Autowired39 private RoleRepository roleRepository;40 41 @Autowired42 private PasswordEncoder passwordEncoder;43 44 @Autowired45 private AuthenticationManager authenticationManager;46 47 @Autowired48 private JwtTokenProvider tokenProvider;49 50 /**51 * Register a new user.52 * The first registered user automatically becomes an admin.53 * All subsequent users are registered as citizens.54 * Uses SERIALIZABLE isolation to prevent race condition for first user admin55 * assignment.56 */57 @Transactional(isolation = Isolation.SERIALIZABLE)58 public AuthResponse register(RegisterRequest request) {59 // Check if email already exists60 if (userRepository.existsByEmail(request.getEmail())) {61 throw new BadRequestException("Email is already registered");62 }63 64 // Get citizen role (all users get this)65 Role citizenRole = roleRepository.findByName(RoleType.ROLE_CITIZEN)66 .orElseThrow(() -> new ResourceNotFoundException("Role", "name", "ROLE_CITIZEN"));67 68 // Create new user69 User user = User.builder()70 .email(request.getEmail())71 .password(passwordEncoder.encode(request.getPassword()))72 .fullName(request.getFullName())73 .phone(request.getPhone())74 .address(request.getAddress())75 .ward(request.getWard())76 .isActive(true)77 .emailVerified(true)78 .build();79 80 // Add citizen role to all users81 user.getRoles().add(citizenRole);82 83 // If this is the first user, also make them admin84 if (userRepository.count() == 0) {85 Role adminRole = roleRepository.findByName(RoleType.ROLE_ADMIN)86 .orElseThrow(() -> new ResourceNotFoundException("Role", "name", "ROLE_ADMIN"));87 user.getRoles().add(adminRole);88 System.out.println("==============================================");89 System.out.println(" First user registered as ADMIN: " + request.getEmail());90 System.out.println("==============================================");91 }92 93 user = userRepository.save(user);94 95 // Generate token96 String token = tokenProvider.generateToken(user.getEmail());97 98 return AuthResponse.of(99 token,100 user.getId(),101 user.getEmail(),102 user.getFullName(),103 user.getRoles().stream().map(r -> r.getName().name()).collect(Collectors.toList()),104 tokenProvider.getExpirationMs());105 }106 107 /**108 * Authenticate user and return JWT token109 */110 @Transactional111 public AuthResponse login(LoginRequest request) {112 // Authenticate113 Authentication authentication = authenticationManager.authenticate(114 new UsernamePasswordAuthenticationToken(115 request.getEmail(),116 request.getPassword()));117 118 SecurityContextHolder.getContext().setAuthentication(authentication);119 120 // Get user121 User user = userRepository.findByEmail(request.getEmail())122 .orElseThrow(() -> new ResourceNotFoundException("User", "email", request.getEmail()));123 124 // Update last login125 user.setLastLogin(LocalDateTime.now());126 userRepository.save(user);127 128 // Generate token129 String token = tokenProvider.generateToken(authentication);130 131 return AuthResponse.of(132 token,133 user.getId(),134 user.getEmail(),135 user.getFullName(),136 user.getRoles().stream().map(r -> r.getName().name()).collect(Collectors.toList()),137 tokenProvider.getExpirationMs());138 }139 140 /**141 * Authenticate user via Google and return JWT token.142 * Auto-registers the user if they don't exist yet.143 */144 @Transactional145 public AuthResponse googleLogin(GoogleLoginRequest request) {146 // Find user by email or create new147 User user = userRepository.findByEmail(request.getEmail())148 .orElseGet(() -> {149 // Auto-register new Google user150 Role citizenRole = roleRepository.findByName(RoleType.ROLE_CITIZEN)151 .orElseThrow(() -> new ResourceNotFoundException("Role", "name", "ROLE_CITIZEN"));152 153 User newUser = User.builder()154 .email(request.getEmail())155 .password(passwordEncoder.encode(java.util.UUID.randomUUID().toString())) // Random password156 .fullName(request.getFullName())157 .isActive(true)158 .emailVerified(true)159 .build();160 161 newUser.getRoles().add(citizenRole);162 return userRepository.save(newUser);163 });164 165 // Update last login166 user.setLastLogin(LocalDateTime.now());167 userRepository.save(user);168 169 // Generate token directly for the user's email170 String token = tokenProvider.generateToken(user.getEmail());171 172 return AuthResponse.of(173 token,174 user.getId(),175 user.getEmail(),176 user.getFullName(),177 user.getRoles().stream().map(r -> r.getName().name()).collect(Collectors.toList()),178 tokenProvider.getExpirationMs());179 }180 181 /**182 * Get current authenticated user183 */184 public User getCurrentUser() {185 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();186 String email = authentication.getName();187 return userRepository.findByEmail(email)188 .orElseThrow(() -> new ResourceNotFoundException("User", "email", email));189 }190}191 