Skip to content

Commit

Permalink
merge: merge v1.0.0 into feat/wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucy Ciara Herud-Thomassen authored and Lucy Ciara Herud-Thomassen committed Mar 3, 2026
2 parents 59be68d + 967fb50 commit da95605
Show file tree
Hide file tree
Showing 12 changed files with 545 additions and 5 deletions.
8 changes: 6 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
<artifactId>spring-security-crypto</artifactId>
<version>7.0.2</version>
</dependency>

<!-- Source: https://mvnrepository.com/artifact/tools.jackson.core/jackson-databind -->
<dependency>
<groupId>tools.jackson.core</groupId>
Expand All @@ -47,7 +46,12 @@
<scope>compile</scope>
</dependency>

</dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.3.5</version>
</dependency>
</dependencies>

<build>
<plugins>
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/edu/group5/app/model/Repository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package edu.group5.app.model;

import java.util.Map;

/**
* Represents a repository
*/
public abstract class Repository<K, V> {
protected final Map<K, V> content;

public Repository(Map<K, V> content) {
this.content = content;
}

/**
* Gets the content of the repo
* @return content of the repo
*/
public Map<K, V> getContent() {
return content;
}
}
60 changes: 58 additions & 2 deletions src/main/java/edu/group5/app/model/organization/Organization.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,61 @@
package edu.group5.app.model.organization;

public class Organization {

import java.util.Objects;

/**
* Represents an organization.
*
* <p>
* An organization is identified by an organization number, a name,
* trust status, website URL, pre-approval status, and a textual description.
*
* <p>
* Instances are validated on creation:
* <ul>
* <li>orgNumber must be non-negative</li>
* <li>name and websiteURL must not be null or blank</li>
* <li>description must not be null</li>
* </ul>
*/
public record Organization(
int orgNumber,
String name,
boolean trusted,
String websiteURL,
boolean isPreApproved,
String description) {
/**
* Creates a new organization.
*
* @param orgNumber the organization number; must be non-negative
* @param name the organization name; must not be null or blank
* @param trusted whether the organization is trusted
* @param websiteURL the organization's website URL; must not be null or
* blank
* @param isPreApproved whether the organization is pre-approved
* @param description a textual description of the organization; must not be
* null
* @throws NullPointerException if name, websiteURL or description is null
* @throws IllegalArgumentException if orgNumber is negative, or if name or
* websiteURL is blank
*/
public Organization(int orgNumber, String name, boolean trusted, String websiteURL, boolean isPreApproved,
String description) {
if (orgNumber < 0) {
throw new IllegalArgumentException("orgNumber cannot be negative");
}
this.orgNumber = orgNumber;
this.name = Objects.requireNonNull(name, "name cannot be null");
this.trusted = trusted;
this.websiteURL = Objects.requireNonNull(websiteURL, "websiteURL cannot be null");
this.isPreApproved = isPreApproved;
this.description = Objects.requireNonNull(description, "description cannot be null");

if (name.isBlank()) {
throw new IllegalArgumentException("name cannot be blank");
}
if (websiteURL.isBlank()) {
throw new IllegalArgumentException("websiteURL cannot be blank");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package edu.group5.app.model.organization;

import edu.group5.app.model.Repository;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
* Handles the business logic associated with organizations
*/
public class OrganizationRepository extends Repository<Integer, Organization> {
/**
* Creates a new Organization Repository
*
* @param content holds all current organizations in the repository; must not be null
* @throws NullPointerException if content is null
*/
public OrganizationRepository(Map<Integer, Organization> content) {
super(Objects.requireNonNull(content, "content cannot be null"));
}

/**
* Gets all trusted organizations in the repository
* @return all organizations with trusted = true
*/
public Map<Integer, Organization> getTrustedOrganizations() {
Map<Integer, Organization> trustedOrganizations = new HashMap<>();

content.forEach((orgNr, org) -> {
if (org.trusted()) {
trustedOrganizations.put(orgNr, org);
}
});

return trustedOrganizations;
}
}
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,48 @@
package edu.group5.app.model.organization;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

class OrganizationRepositoryTest {

private OrganizationRepository repository;

@BeforeEach
void setUp() {
Map<Integer, Organization> content = new HashMap<>();

Organization trustedOrganization1 = new Organization(1, "Trusted Org1", true, "org.com", true, "description");
Organization trustedOrganization2 = new Organization(2, "Trusted Org2", true, "org.com", true, "description");
Organization untrustedOrganization1 = new Organization(3, "Untrusted Org1", false, "org.com", true, "description");
Organization untrustedOrganization2 = new Organization(4, "Untrusted Org2", false, "org.com", true, "description");

content.put(1, trustedOrganization1);
content.put(2, trustedOrganization2);
content.put(3, untrustedOrganization1);
content.put(4, untrustedOrganization2);

repository = new OrganizationRepository(content);
}

@Test
void constructor_ThrowsWhenContentIsNull() {
assertThrows(NullPointerException.class, () -> new OrganizationRepository(null));
}

@Test
void getTrustedOrganizations_OnlyReturnsTrustedOrganizations() {
Map<Integer, Organization> trusted = repository.getTrustedOrganizations();

assertEquals(2, trusted.size());
assertTrue(trusted.containsKey(1));
assertTrue(trusted.containsKey(2));
assertFalse(trusted.containsKey(3));
assertFalse(trusted.containsKey(4));
assertTrue(trusted.values().stream().allMatch(Organization::trusted));
}
}
Loading

0 comments on commit da95605

Please sign in to comment.