Skip to content

Merge Feat/user into release/v1.0.0 #37

Merged
merged 7 commits into from
Feb 26, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
<artifactId>spring-security-crypto</artifactId>
<version>7.0.2</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.3.5</version>
</dependency>
</dependencies>

<build>
Expand Down
117 changes: 116 additions & 1 deletion src/main/java/edu/group5/app/model/user/User.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,120 @@
package edu.group5.app.model.user;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* User class represents a user in the system. It is an abstract class that will be extended by specific user types such as Donor, Recipient, and Admin.
* Each user has a unique userId, a role that defines their permissions in the system, and personal information such as first name, last name, email, and password hash.
* The constructor validates that all required fields are provided and throws an IllegalArgumentException if any of the fields are null or empty.
* This ensures that the User objects are always in a valid state when created.
* The class also includes a method to verify the user's password
* by comparing the provided plaintext password with the stored hashed password using BCrypt.
*
*/
public class User {
private int userId;
private String role;
private String firstName;
private String lastName;
private String email;
private String passwordHash;

/**
* Constructor for User class. Validates that all required fields
* are provided and throws an IllegalArgumentException if any of the fields are null or empty.
* @param userId the unique identifier for the user, must be a positive integer
* @param role the role of the user (e.g., "Donor", "Recipient", "Admin")
* @param firstName the first name of the user
* @param lastName the last name of the user
* @param email the email address of the user
* @param passwordHash the hashed password of the user, used for authentication purposes
*/
public User(int userId, String role, String firstName,
String lastName, String email, String passwordHash) {
if (userId <= 0) {
throw new IllegalArgumentException("User ID must be positive");
}
if (role == null || role.trim().isEmpty()) {
throw new IllegalArgumentException("Role cannot be null or empty");
}
if (firstName == null || firstName.trim().isEmpty()) {
throw new IllegalArgumentException("First name cannot be null or empty");
}
if (lastName == null || lastName.trim().isEmpty()) {
throw new IllegalArgumentException("Last name cannot be null or empty");
}
if (email == null || email.trim().isEmpty()) {
throw new IllegalArgumentException("Email cannot be null or empty");
}
if (passwordHash == null || passwordHash.trim().isEmpty()) {
throw new IllegalArgumentException("Password hash cannot be null or empty");
}
this.userId = userId;
this.role = role.trim();
this.firstName = firstName.trim();
this.lastName = lastName.trim();
this.email = email.trim();
this.passwordHash = passwordHash;
}

/**
* Gets the unique identifier for the user.
* @return the userId of the user
*/
public int getUserId() {
return userId;
}

/**
* Gets the role of the user, which defines their permissions in the system.
* @return the role of the user
*/
public String getRole() {
return role;
}

/**
* Gets the first name of the user.
* @return the first name of the user
*/
public String getFirstName() {
return firstName;
}

/**
* Gets the last name of the user.
* @return the last name of the user
*/
public String getLastName() {
return lastName;
}

/**
* Gets the email address of the user.
* @return the email of the user
*/
public String getEmail() {
return email;
}

/**
* Gets the hashed password of the user.
* This is used for authentication purposes and should not be exposed in plaintext.
* @return the password hash of the user
*/
public String getPasswordHash() {
return passwordHash;
}

/**
* Verifies if the provided password matches the stored password hash.
* This method uses BCrypt to compare the plaintext password with the hashed password.
* @param password the plaintext password to verify
* @return true if the password is correct, false otherwise
*/
public boolean verifyPassword(String password) {
if (password == null || password.isEmpty()) {
return false;
}
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder.matches(password, this.passwordHash);
}
}
5 changes: 5 additions & 0 deletions src/test/java/edu/group5/app/control/WrapperTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.group5.app.control;

public class WrapperTest {

}
5 changes: 5 additions & 0 deletions src/test/java/edu/group5/app/model/donation/DonationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.group5.app.model.donation;

public class DonationTest {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.group5.app.model.organization;

public class OrganizationTest {

}
136 changes: 136 additions & 0 deletions src/test/java/edu/group5/app/model/user/UserTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package edu.group5.app.model.user;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class UserTest {
private static final int TEST_USER_ID = 1;
private static final String TEST_ROLE = "Donor";
private static final String TEST_FIRST_NAME = "John";
private static final String TEST_LAST_NAME = "Doe";
private static final String TEST_EMAIL = "john.doe@example.com";
private static final String TEST_PASSWORD = "password123";
private static final String TEST_PASSWORD_HASH = new BCryptPasswordEncoder().encode(TEST_PASSWORD);

private static final int WRONG_USER_ID = -5;
private static final String WRONG_ROLE = "";
private static final String WRONG_FIRST_NAME = "";
private static final String WRONG_LAST_NAME = "";
private static final String WRONG_EMAIL = "";
private static final String WRONG_PASSWORD_HASH = "";

private void constructorTest(int userId, String role, String firstName, String lastName, String email, String passwordHash, boolean negativeTest) {
boolean exceptionThrown = negativeTest;
try {
new User(userId, role, firstName, lastName, email, passwordHash);
} catch (Exception e) {
exceptionThrown = !negativeTest;
} finally {
assertFalse(exceptionThrown);
}
}

@Test
public void constructorThrowsNoException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, false);
}

@Test
public void constructorWithNegativeUserIdThrowsException() {
constructorTest(WRONG_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithEmptyRoleThrowsException() {
constructorTest(TEST_USER_ID, WRONG_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithEmptyFirstNameThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, WRONG_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithEmptyLastNameThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, WRONG_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithEmptyEmailThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, WRONG_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithEmptyPasswordHashThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, WRONG_PASSWORD_HASH, true);
}

private void getMethodComparer(User user, boolean negativeTest) {
if (user.getUserId() == TEST_USER_ID &&
user.getRole().equals(TEST_ROLE) &&
user.getFirstName().equals(TEST_FIRST_NAME) &&
user.getLastName().equals(TEST_LAST_NAME) &&
user.getEmail().equals(TEST_EMAIL) &&
user.getPasswordHash() != null) {
assertFalse(negativeTest);
}
}

@Test
public void getMethodsReturnCorrectInformation() {
User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH);
getMethodComparer(testUser, false);
}

@Test
public void verifyPasswordReturnsTrueForCorrectPassword() {
User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH);
assertTrue(testUser.verifyPassword(TEST_PASSWORD));
}

@Test
public void verifyPasswordReturnsFalseForIncorrectPassword() {
User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH);
assertFalse(testUser.verifyPassword("wrongPassword"));
}

@Test
public void verifyPasswordReturnsFalseForNullPassword() {
User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH);
assertFalse(testUser.verifyPassword(null));
}

@Test
public void verifyPasswordReturnsFalseForEmptyPassword() {
User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH);
assertFalse(testUser.verifyPassword(""));
}

@Test
public void constructorWithNullRoleThrowsException() {
constructorTest(TEST_USER_ID, null, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithNullFirstNameThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, null, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithNullLastNameThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, null, TEST_EMAIL, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithNullEmailThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, null, TEST_PASSWORD_HASH, true);
}

@Test
public void constructorWithNullPasswordHashThrowsException() {
constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, null, true);
}
}
5 changes: 5 additions & 0 deletions src/test/java/edu/group5/app/utils/UtilitiesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.group5.app.utils;

public class UtilitiesTest {

}
5 changes: 5 additions & 0 deletions src/test/java/edu/group5/app/view/ViewTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.group5.app.view;

public class ViewTest {

}