Fix backend user contract and add User-Employee-Customer linkage

- Add active field to User entity and users table
- Add userId linkage to Employee and Customer entities with unique constraints and FKs
- Add repository methods findByUserId and findAllByEmail
- Create UserBusinessLinkageService for shared employee/customer creation logic
- Create AuthenticationHelper utility for resolving authenticated users
- Update UserService to persist all user fields and create linked business entities
- Update AuthController register to set active and create linked customer
- Update DataInitializer to be idempotent and use shared linkage service
- Update Postman collection user endpoints with fullName, email, and active
This commit is contained in:
2026-03-08 21:56:04 -06:00
parent d86652b462
commit a0d14e493f
12 changed files with 363 additions and 19 deletions

View File

@@ -1435,7 +1435,7 @@
], ],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\n \"username\": \"newuser\",\n \"password\": \"password123\",\n \"role\": \"STAFF\"\n}" "raw": "{\n \"username\": \"newuser\",\n \"password\": \"password123\",\n \"fullName\": \"New User\",\n \"email\": \"newuser@petshop.com\",\n \"role\": \"STAFF\",\n \"active\": true\n}"
} }
} }
}, },
@@ -1457,7 +1457,7 @@
], ],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\n \"username\": \"user1\",\n \"role\": \"STAFF\"\n}" "raw": "{\n \"username\": \"user1\",\n \"password\": \"newpassword123\",\n \"fullName\": \"Updated User\",\n \"email\": \"user1@petshop.com\",\n \"role\": \"STAFF\",\n \"active\": true\n}"
} }
} }
}, },

View File

@@ -2,6 +2,7 @@ package com.petshop.backend.config;
import com.petshop.backend.entity.User; import com.petshop.backend.entity.User;
import com.petshop.backend.repository.UserRepository; import com.petshop.backend.repository.UserRepository;
import com.petshop.backend.service.UserBusinessLinkageService;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -11,57 +12,137 @@ public class DataInitializer implements CommandLineRunner {
private final UserRepository userRepository; private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final UserBusinessLinkageService userBusinessLinkageService;
public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder) { public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
this.userRepository = userRepository; this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.userBusinessLinkageService = userBusinessLinkageService;
} }
@Override @Override
public void run(String... args) { public void run(String... args) {
System.out.println("==== DataInitializer: Starting user creation ===="); System.out.println("==== DataInitializer: Starting user creation ====");
if (userRepository.findByUsername("admin").isEmpty()) { User admin = userRepository.findByUsername("admin").orElse(null);
if (admin == null) {
System.out.println("Creating admin user..."); System.out.println("Creating admin user...");
User admin = new User(); admin = new User();
admin.setUsername("admin"); admin.setUsername("admin");
admin.setPassword(passwordEncoder.encode("admin123")); admin.setPassword(passwordEncoder.encode("admin123"));
admin.setEmail("admin@petshop.com"); admin.setEmail("admin@petshop.com");
admin.setFullName("Admin User"); admin.setFullName("Admin User");
admin.setRole(User.Role.ADMIN); admin.setRole(User.Role.ADMIN);
userRepository.save(admin); admin.setActive(true);
admin = userRepository.save(admin);
System.out.println("Admin user created successfully"); System.out.println("Admin user created successfully");
} else { } else {
System.out.println("Admin user already exists"); System.out.println("Admin user already exists");
// Normalize missing fields if needed
boolean updated = false;
if (admin.getFullName() == null || admin.getFullName().isEmpty()) {
admin.setFullName("Admin User");
updated = true;
} }
if (admin.getEmail() == null || admin.getEmail().isEmpty()) {
admin.setEmail("admin@petshop.com");
updated = true;
}
if (admin.getActive() == null) {
admin.setActive(true);
updated = true;
}
if (admin.getRole() == null) {
admin.setRole(User.Role.ADMIN);
updated = true;
}
if (updated) {
admin = userRepository.save(admin);
System.out.println("Admin user normalized");
}
}
// Ensure linked employee
userBusinessLinkageService.ensureLinkedEmployee(admin);
if (userRepository.findByUsername("staff").isEmpty()) { User staff = userRepository.findByUsername("staff").orElse(null);
if (staff == null) {
System.out.println("Creating staff user..."); System.out.println("Creating staff user...");
User staff = new User(); staff = new User();
staff.setUsername("staff"); staff.setUsername("staff");
staff.setPassword(passwordEncoder.encode("staff123")); staff.setPassword(passwordEncoder.encode("staff123"));
staff.setEmail("staff@petshop.com"); staff.setEmail("staff@petshop.com");
staff.setFullName("Staff User"); staff.setFullName("Staff User");
staff.setRole(User.Role.STAFF); staff.setRole(User.Role.STAFF);
userRepository.save(staff); staff.setActive(true);
staff = userRepository.save(staff);
System.out.println("Staff user created successfully"); System.out.println("Staff user created successfully");
} else { } else {
System.out.println("Staff user already exists"); System.out.println("Staff user already exists");
// Normalize missing fields if needed
boolean updated = false;
if (staff.getFullName() == null || staff.getFullName().isEmpty()) {
staff.setFullName("Staff User");
updated = true;
} }
if (staff.getEmail() == null || staff.getEmail().isEmpty()) {
staff.setEmail("staff@petshop.com");
updated = true;
}
if (staff.getActive() == null) {
staff.setActive(true);
updated = true;
}
if (staff.getRole() == null) {
staff.setRole(User.Role.STAFF);
updated = true;
}
if (updated) {
staff = userRepository.save(staff);
System.out.println("Staff user normalized");
}
}
// Ensure linked employee
userBusinessLinkageService.ensureLinkedEmployee(staff);
if (userRepository.findByUsername("customer").isEmpty()) { User customer = userRepository.findByUsername("customer").orElse(null);
if (customer == null) {
System.out.println("Creating customer user..."); System.out.println("Creating customer user...");
User customer = new User(); customer = new User();
customer.setUsername("customer"); customer.setUsername("customer");
customer.setPassword(passwordEncoder.encode("customer123")); customer.setPassword(passwordEncoder.encode("customer123"));
customer.setEmail("customer@petshop.com"); customer.setEmail("customer@petshop.com");
customer.setFullName("Test Customer"); customer.setFullName("Test Customer");
customer.setRole(User.Role.CUSTOMER); customer.setRole(User.Role.CUSTOMER);
userRepository.save(customer); customer.setActive(true);
customer = userRepository.save(customer);
System.out.println("Customer user created successfully"); System.out.println("Customer user created successfully");
} else { } else {
System.out.println("Customer user already exists"); System.out.println("Customer user already exists");
// Normalize missing fields if needed
boolean updated = false;
if (customer.getFullName() == null || customer.getFullName().isEmpty()) {
customer.setFullName("Test Customer");
updated = true;
} }
if (customer.getEmail() == null || customer.getEmail().isEmpty()) {
customer.setEmail("customer@petshop.com");
updated = true;
}
if (customer.getActive() == null) {
customer.setActive(true);
updated = true;
}
if (customer.getRole() == null) {
customer.setRole(User.Role.CUSTOMER);
updated = true;
}
if (updated) {
customer = userRepository.save(customer);
System.out.println("Customer user normalized");
}
}
// Ensure linked customer
userBusinessLinkageService.ensureLinkedCustomer(customer);
System.out.println("==== DataInitializer: Completed ===="); System.out.println("==== DataInitializer: Completed ====");
} }

View File

@@ -10,6 +10,7 @@ import com.petshop.backend.dto.auth.UserInfoResponse;
import com.petshop.backend.entity.User; import com.petshop.backend.entity.User;
import com.petshop.backend.repository.UserRepository; import com.petshop.backend.repository.UserRepository;
import com.petshop.backend.security.JwtUtil; import com.petshop.backend.security.JwtUtil;
import com.petshop.backend.service.UserBusinessLinkageService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -42,12 +43,14 @@ public class AuthController {
private final UserRepository userRepository; private final UserRepository userRepository;
private final JwtUtil jwtUtil; private final JwtUtil jwtUtil;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final UserBusinessLinkageService userBusinessLinkageService;
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder) { public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
this.authenticationManager = authenticationManager; this.authenticationManager = authenticationManager;
this.userRepository = userRepository; this.userRepository = userRepository;
this.jwtUtil = jwtUtil; this.jwtUtil = jwtUtil;
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.userBusinessLinkageService = userBusinessLinkageService;
} }
@PostMapping("/register") @PostMapping("/register")
@@ -70,9 +73,13 @@ public class AuthController {
user.setEmail(request.getEmail()); user.setEmail(request.getEmail());
user.setFullName(request.getFullName()); user.setFullName(request.getFullName());
user.setRole(User.Role.CUSTOMER); user.setRole(User.Role.CUSTOMER);
user.setActive(true);
User savedUser = userRepository.save(user); User savedUser = userRepository.save(user);
// Create or link customer record
userBusinessLinkageService.ensureLinkedCustomer(savedUser);
UserDetails userDetails = new org.springframework.security.core.userdetails.User( UserDetails userDetails = new org.springframework.security.core.userdetails.User(
savedUser.getUsername(), savedUser.getUsername(),
savedUser.getPassword(), savedUser.getPassword(),

View File

@@ -15,6 +15,9 @@ public class Customer {
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long customerId; private Long customerId;
@Column(name = "user_id")
private Long userId;
@Column(nullable = false, length = 50) @Column(nullable = false, length = 50)
private String firstName; private String firstName;
@@ -38,8 +41,9 @@ public class Customer {
public Customer() { public Customer() {
} }
public Customer(Long customerId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) { public Customer(Long customerId, Long userId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.customerId = customerId; this.customerId = customerId;
this.userId = userId;
this.firstName = firstName; this.firstName = firstName;
this.lastName = lastName; this.lastName = lastName;
this.email = email; this.email = email;
@@ -56,6 +60,14 @@ public class Customer {
this.customerId = customerId; this.customerId = customerId;
} }
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getFirstName() { public String getFirstName() {
return firstName; return firstName;
} }
@@ -121,6 +133,7 @@ public class Customer {
public String toString() { public String toString() {
return "Customer{" + return "Customer{" +
"customerId=" + customerId + "customerId=" + customerId +
", userId=" + userId +
", firstName='" + firstName + '\'' + ", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' + ", lastName='" + lastName + '\'' +
", email='" + email + '\'' + ", email='" + email + '\'' +

View File

@@ -15,6 +15,9 @@ public class Employee {
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long employeeId; private Long employeeId;
@Column(name = "user_id")
private Long userId;
@Column(nullable = false, length = 50) @Column(nullable = false, length = 50)
private String firstName; private String firstName;
@@ -44,8 +47,9 @@ public class Employee {
public Employee() { public Employee() {
} }
public Employee(Long employeeId, String firstName, String lastName, String email, String phone, String role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) { public Employee(Long employeeId, Long userId, String firstName, String lastName, String email, String phone, String role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.employeeId = employeeId; this.employeeId = employeeId;
this.userId = userId;
this.firstName = firstName; this.firstName = firstName;
this.lastName = lastName; this.lastName = lastName;
this.email = email; this.email = email;
@@ -64,6 +68,14 @@ public class Employee {
this.employeeId = employeeId; this.employeeId = employeeId;
} }
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getFirstName() { public String getFirstName() {
return firstName; return firstName;
} }
@@ -145,6 +157,7 @@ public class Employee {
public String toString() { public String toString() {
return "Employee{" + return "Employee{" +
"employeeId=" + employeeId + "employeeId=" + employeeId +
", userId=" + userId +
", firstName='" + firstName + '\'' + ", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' + ", lastName='" + lastName + '\'' +
", email='" + email + '\'' + ", email='" + email + '\'' +

View File

@@ -34,6 +34,9 @@ public class User {
@Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)") @Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)")
private Role role; private Role role;
@Column(nullable = false)
private Boolean active = true;
@CreationTimestamp @CreationTimestamp
@Column(name = "created_at", updatable = false) @Column(name = "created_at", updatable = false)
private LocalDateTime createdAt; private LocalDateTime createdAt;
@@ -49,7 +52,7 @@ public class User {
public User() { public User() {
} }
public User(Long id, String username, String password, String email, String fullName, String avatarUrl, Role role, LocalDateTime createdAt, LocalDateTime updatedAt) { public User(Long id, String username, String password, String email, String fullName, String avatarUrl, Role role, Boolean active, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.id = id; this.id = id;
this.username = username; this.username = username;
this.password = password; this.password = password;
@@ -57,6 +60,7 @@ public class User {
this.fullName = fullName; this.fullName = fullName;
this.avatarUrl = avatarUrl; this.avatarUrl = avatarUrl;
this.role = role; this.role = role;
this.active = active;
this.createdAt = createdAt; this.createdAt = createdAt;
this.updatedAt = updatedAt; this.updatedAt = updatedAt;
} }
@@ -117,6 +121,14 @@ public class User {
this.role = role; this.role = role;
} }
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public LocalDateTime getCreatedAt() { public LocalDateTime getCreatedAt() {
return createdAt; return createdAt;
} }
@@ -156,6 +168,7 @@ public class User {
", fullName='" + fullName + '\'' + ", fullName='" + fullName + '\'' +
", avatarUrl='" + avatarUrl + '\'' + ", avatarUrl='" + avatarUrl + '\'' +
", role=" + role + ", role=" + role +
", active=" + active +
", createdAt=" + createdAt + ", createdAt=" + createdAt +
", updatedAt=" + updatedAt + ", updatedAt=" + updatedAt +
'}'; '}';

View File

@@ -8,9 +8,15 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository @Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> { public interface CustomerRepository extends JpaRepository<Customer, Long> {
Optional<Customer> findByUserId(Long userId);
List<Customer> findAllByEmail(String email);
@Query("SELECT c FROM Customer c WHERE " + @Query("SELECT c FROM Customer c WHERE " +
"LOWER(c.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + "LOWER(c.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
"LOWER(c.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + "LOWER(c.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +

View File

@@ -4,6 +4,11 @@ import com.petshop.backend.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository @Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> { public interface EmployeeRepository extends JpaRepository<Employee, Long> {
Optional<Employee> findByUserId(Long userId);
List<Employee> findAllByEmail(String email);
} }

View File

@@ -0,0 +1,138 @@
package com.petshop.backend.service;
import com.petshop.backend.entity.Customer;
import com.petshop.backend.entity.Employee;
import com.petshop.backend.entity.User;
import com.petshop.backend.repository.CustomerRepository;
import com.petshop.backend.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserBusinessLinkageService {
private final EmployeeRepository employeeRepository;
private final CustomerRepository customerRepository;
@Autowired
public UserBusinessLinkageService(EmployeeRepository employeeRepository, CustomerRepository customerRepository) {
this.employeeRepository = employeeRepository;
this.customerRepository = customerRepository;
}
@Transactional
public Employee ensureLinkedEmployee(User user) {
// Check if already linked
if (user.getId() != null) {
var existing = employeeRepository.findByUserId(user.getId());
if (existing.isPresent()) {
return existing.get();
}
}
// Check for email matches
List<Employee> emailMatches = employeeRepository.findAllByEmail(user.getEmail());
// If exactly one match exists and has no userId, link it
if (emailMatches.size() == 1) {
Employee employee = emailMatches.get(0);
if (employee.getUserId() == null) {
employee.setUserId(user.getId());
return employeeRepository.save(employee);
}
}
// Otherwise create a new linked Employee
Employee newEmployee = new Employee();
newEmployee.setUserId(user.getId());
newEmployee.setEmail(user.getEmail());
// Split fullName into firstName and lastName
String[] nameParts = splitFullName(user.getFullName());
newEmployee.setFirstName(nameParts[0]);
newEmployee.setLastName(nameParts[1]);
// Set required fields with deterministic values
newEmployee.setPhone("000-000-0000");
newEmployee.setIsActive(true);
// Map role based on user role
if (user.getRole() == User.Role.ADMIN) {
newEmployee.setRole("Manager");
} else if (user.getRole() == User.Role.STAFF) {
newEmployee.setRole("Staff");
} else {
newEmployee.setRole("Staff"); // fallback
}
return employeeRepository.save(newEmployee);
}
@Transactional
public Customer ensureLinkedCustomer(User user) {
// Check if already linked
if (user.getId() != null) {
var existing = customerRepository.findByUserId(user.getId());
if (existing.isPresent()) {
return existing.get();
}
}
// Check for email matches
List<Customer> emailMatches = customerRepository.findAllByEmail(user.getEmail());
// If exactly one match exists and has no userId, link it
if (emailMatches.size() == 1) {
Customer customer = emailMatches.get(0);
if (customer.getUserId() == null) {
customer.setUserId(user.getId());
return customerRepository.save(customer);
}
}
// Otherwise create a new linked Customer
Customer newCustomer = new Customer();
newCustomer.setUserId(user.getId());
newCustomer.setEmail(user.getEmail());
// Split fullName into firstName and lastName
String[] nameParts = splitFullName(user.getFullName());
newCustomer.setFirstName(nameParts[0]);
newCustomer.setLastName(nameParts[1]);
// Set required fields with deterministic values
newCustomer.setPhone("000-000-0001");
return customerRepository.save(newCustomer);
}
private String[] splitFullName(String fullName) {
if (fullName == null || fullName.trim().isEmpty()) {
return new String[]{"System", "User"};
}
String trimmed = fullName.trim();
int spaceIndex = trimmed.indexOf(' ');
if (spaceIndex == -1) {
// Single token
return new String[]{trimmed, "User"};
}
// Multiple tokens
String firstName = trimmed.substring(0, spaceIndex).trim();
String lastName = trimmed.substring(spaceIndex + 1).trim();
if (firstName.isEmpty()) {
firstName = "System";
}
if (lastName.isEmpty()) {
lastName = "User";
}
return new String[]{firstName, lastName};
}
}

View File

@@ -17,10 +17,12 @@ public class UserService {
private final UserRepository userRepository; private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final UserBusinessLinkageService userBusinessLinkageService;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) { public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
this.userRepository = userRepository; this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.userBusinessLinkageService = userBusinessLinkageService;
} }
public Page<UserResponse> getAllUsers(String query, Pageable pageable) { public Page<UserResponse> getAllUsers(String query, Pageable pageable) {
@@ -44,9 +46,20 @@ public class UserService {
User user = new User(); User user = new User();
user.setUsername(request.getUsername()); user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword())); user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setFullName(request.getFullName());
user.setEmail(request.getEmail());
user.setRole(request.getRole()); user.setRole(request.getRole());
user.setActive(request.getActive() != null ? request.getActive() : true);
user = userRepository.save(user); user = userRepository.save(user);
// Create or link business entity based on role
if (user.getRole() == User.Role.STAFF || user.getRole() == User.Role.ADMIN) {
userBusinessLinkageService.ensureLinkedEmployee(user);
} else if (user.getRole() == User.Role.CUSTOMER) {
userBusinessLinkageService.ensureLinkedCustomer(user);
}
return mapToResponse(user); return mapToResponse(user);
} }
@@ -59,7 +72,10 @@ public class UserService {
if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) { if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
user.setPassword(passwordEncoder.encode(request.getPassword())); user.setPassword(passwordEncoder.encode(request.getPassword()));
} }
user.setFullName(request.getFullName());
user.setEmail(request.getEmail());
user.setRole(request.getRole()); user.setRole(request.getRole());
user.setActive(request.getActive() != null ? request.getActive() : true);
user = userRepository.save(user); user = userRepository.save(user);
return mapToResponse(user); return mapToResponse(user);
@@ -82,7 +98,12 @@ public class UserService {
UserResponse response = new UserResponse(); UserResponse response = new UserResponse();
response.setId(user.getId()); response.setId(user.getId());
response.setUsername(user.getUsername()); response.setUsername(user.getUsername());
response.setFullName(user.getFullName());
response.setEmail(user.getEmail());
response.setRole(user.getRole().toString()); response.setRole(user.getRole().toString());
response.setActive(user.getActive());
response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt());
return response; return response;
} }
} }

View File

@@ -0,0 +1,38 @@
package com.petshop.backend.util;
import com.petshop.backend.entity.Customer;
import com.petshop.backend.entity.Employee;
import com.petshop.backend.entity.User;
import com.petshop.backend.repository.CustomerRepository;
import com.petshop.backend.repository.EmployeeRepository;
import com.petshop.backend.repository.UserRepository;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Component
public class AuthenticationHelper {
public static User getAuthenticatedUser(UserRepository userRepository) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
throw new RuntimeException("No authenticated user found");
}
String username = authentication.getName();
return userRepository.findByUsername(username)
.orElseThrow(() -> new RuntimeException("User not found: " + username));
}
public static Employee getAuthenticatedEmployee(UserRepository userRepository, EmployeeRepository employeeRepository) {
User user = getAuthenticatedUser(userRepository);
return employeeRepository.findByUserId(user.getId())
.orElseThrow(() -> new RuntimeException("Employee record not found for user: " + user.getUsername()));
}
public static Customer getAuthenticatedCustomer(UserRepository userRepository, CustomerRepository customerRepository) {
User user = getAuthenticatedUser(userRepository);
return customerRepository.findByUserId(user.getId())
.orElseThrow(() -> new RuntimeException("Customer record not found for user: " + user.getUsername()));
}
}

View File

@@ -12,6 +12,7 @@ CREATE TABLE IF NOT EXISTS storeLocation (
CREATE TABLE IF NOT EXISTS employee ( CREATE TABLE IF NOT EXISTS employee (
employeeId BIGINT AUTO_INCREMENT PRIMARY KEY, employeeId BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NULL,
firstName VARCHAR(50) NOT NULL, firstName VARCHAR(50) NOT NULL,
lastName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL,
@@ -19,7 +20,8 @@ CREATE TABLE IF NOT EXISTS employee (
role VARCHAR(50) NOT NULL, role VARCHAR(50) NOT NULL,
isActive BOOLEAN DEFAULT TRUE NOT NULL, isActive BOOLEAN DEFAULT TRUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT uk_employee_user_id UNIQUE (user_id)
); );
CREATE TABLE IF NOT EXISTS employeeStore ( CREATE TABLE IF NOT EXISTS employeeStore (
@@ -32,12 +34,14 @@ CREATE TABLE IF NOT EXISTS employeeStore (
CREATE TABLE IF NOT EXISTS customer ( CREATE TABLE IF NOT EXISTS customer (
customerId BIGINT AUTO_INCREMENT PRIMARY KEY, customerId BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NULL,
firstName VARCHAR(50) NOT NULL, firstName VARCHAR(50) NOT NULL,
lastName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL,
phone VARCHAR(20) NOT NULL, phone VARCHAR(20) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT uk_customer_user_id UNIQUE (user_id)
); );
CREATE TABLE IF NOT EXISTS pet ( CREATE TABLE IF NOT EXISTS pet (
@@ -201,6 +205,7 @@ CREATE TABLE IF NOT EXISTS users (
fullName VARCHAR(100), fullName VARCHAR(100),
avatarUrl VARCHAR(255), avatarUrl VARCHAR(255),
role VARCHAR(20) NOT NULL, role VARCHAR(20) NOT NULL,
active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
); );
@@ -239,3 +244,7 @@ CREATE TABLE IF NOT EXISTS message (
FOREIGN KEY (conversationId) REFERENCES conversation(id), FOREIGN KEY (conversationId) REFERENCES conversation(id),
FOREIGN KEY (senderId) REFERENCES users(id) FOREIGN KEY (senderId) REFERENCES users(id)
); );
-- Add foreign keys for user_id linkage
ALTER TABLE employee ADD CONSTRAINT fk_employee_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE customer ADD CONSTRAINT fk_customer_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;