From 5064cf90b672cc26b8fbb0afd90cb99af92b03d3 Mon Sep 17 00:00:00 2001 From: ALEEF02 Date: Sat, 23 Nov 2024 15:33:26 -0500 Subject: [PATCH 1/9] Add Authenticator unit tests Refactor CUser to allow unit testing --- MavenBack/src/main/java/ppp/api/GetGames.java | 11 ++-- MavenBack/src/main/java/ppp/api/GetUsers.java | 5 +- .../src/main/java/ppp/auth/AuthServlet.java | 7 +- .../src/main/java/ppp/auth/Authenticator.java | 12 +++- .../src/main/java/ppp/db/UserRepository.java | 8 +++ .../ppp/db/controllers/CUserRepository.java | 17 +++++ .../main/java/ppp/staticServe/DashServe.java | 10 ++- .../main/java/ppp/staticServe/GamesServe.java | 5 +- .../main/java/ppp/staticServe/LoginServe.java | 5 +- .../test/java/ppp/auth/AuthenticatorTest.java | 65 +++++++++++++++++++ 10 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 MavenBack/src/main/java/ppp/db/UserRepository.java create mode 100644 MavenBack/src/main/java/ppp/db/controllers/CUserRepository.java create mode 100644 MavenBack/src/test/java/ppp/auth/AuthenticatorTest.java diff --git a/MavenBack/src/main/java/ppp/api/GetGames.java b/MavenBack/src/main/java/ppp/api/GetGames.java index fc00a88..4c2e2bb 100644 --- a/MavenBack/src/main/java/ppp/api/GetGames.java +++ b/MavenBack/src/main/java/ppp/api/GetGames.java @@ -12,8 +12,10 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import ppp.auth.Authenticator; +import ppp.db.UserRepository; import ppp.db.controllers.CGames; import ppp.db.controllers.CUser; +import ppp.db.controllers.CUserRepository; import ppp.db.model.OGame; import ppp.db.model.OUser; import ppp.meta.GlickoTwo; @@ -37,14 +39,16 @@ @WebServlet("/api/games") public class GetGames extends HttpServlet { + UserRepository repository = new CUserRepository(); + Authenticator auth = new Authenticator(repository); + @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { Map parameters = request.getParameterMap(); List games = null; // Our list of games to be returned StatusEnum.Status status = Status.ANY; int limit = 20; // Return a maximum of 20 games by default - - Authenticator auth = new Authenticator(); + boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; // Check with the Authenticator to see if the request is authorized try { @@ -188,8 +192,7 @@ public void doPost(HttpServletRequest request, HttpServletResponse response) thr Map parameters = request.getParameterMap(); StatusEnum.Status status = Status.ANY; - - Authenticator auth = new Authenticator(); + boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; if (!loggedIn) { // Every request to modify games must be authenticated. response.setStatus(401); diff --git a/MavenBack/src/main/java/ppp/api/GetUsers.java b/MavenBack/src/main/java/ppp/api/GetUsers.java index 09bfc33..4b74799 100644 --- a/MavenBack/src/main/java/ppp/api/GetUsers.java +++ b/MavenBack/src/main/java/ppp/api/GetUsers.java @@ -11,7 +11,9 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import ppp.auth.Authenticator; +import ppp.db.UserRepository; import ppp.db.controllers.CUser; +import ppp.db.controllers.CUserRepository; import ppp.db.model.OUser; import ppp.meta.LoginEnum; @@ -40,7 +42,8 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro Map parameters = request.getParameterMap(); List users = null; - Authenticator auth = new Authenticator(); + UserRepository repository = new CUserRepository(); + Authenticator auth = new Authenticator(repository); boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; int limit = 10; // Return maximum 10 users by default boolean withHistory = parameters.containsKey("withHistory"); diff --git a/MavenBack/src/main/java/ppp/auth/AuthServlet.java b/MavenBack/src/main/java/ppp/auth/AuthServlet.java index 3224994..0be6005 100644 --- a/MavenBack/src/main/java/ppp/auth/AuthServlet.java +++ b/MavenBack/src/main/java/ppp/auth/AuthServlet.java @@ -13,8 +13,10 @@ import jakarta.servlet.http.HttpServletResponse; import ppp.ServerConfig; import ppp.api.GetGames; +import ppp.db.UserRepository; import ppp.db.controllers.CGlicko; import ppp.db.controllers.CUser; +import ppp.db.controllers.CUserRepository; import ppp.db.model.OGlicko; import ppp.db.model.OUser; import ppp.meta.LoginEnum; @@ -22,8 +24,9 @@ @WebServlet("/api/auth") public class AuthServlet extends HttpServlet { - - Authenticator emailer = new Authenticator(); + + UserRepository repository = new CUserRepository(); + Authenticator emailer = new Authenticator(repository); /** * Creates a new 24-bit, Base64 Token diff --git a/MavenBack/src/main/java/ppp/auth/Authenticator.java b/MavenBack/src/main/java/ppp/auth/Authenticator.java index 43ace97..70d6944 100644 --- a/MavenBack/src/main/java/ppp/auth/Authenticator.java +++ b/MavenBack/src/main/java/ppp/auth/Authenticator.java @@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpServletRequest; import ppp.ServerConfig; +import ppp.db.UserRepository; import ppp.db.controllers.CUser; import ppp.db.model.OUser; import ppp.meta.LoginEnum; @@ -25,6 +26,13 @@ public class Authenticator { */ private static Map emailsSent = new HashMap(); + // Access to CUser that can be unit tested + private final UserRepository userRepository; + + public Authenticator(UserRepository userRepository) { + this.userRepository = userRepository; + } + /** * Checks the input authentication code to the one sent * @@ -80,7 +88,7 @@ public LoginEnum.Status login(HttpServletRequest request) { */ public LoginEnum.Status login(String email, String token) { email = email.toLowerCase(); - OUser user = CUser.findByEmail(email, true); + OUser user = userRepository.findByEmail(email, true); if (user.id == 0) return LoginEnum.Status.USER_INVALID; if (user.email == "") return LoginEnum.Status.EMAIL_INVALID; if (user.token == "" || user.tokenExpiryDate.before(new Date()) || user.token.length() < 2) return LoginEnum.Status.TOKEN_EXPIRED; @@ -89,7 +97,7 @@ public LoginEnum.Status login(String email, String token) { // Successful login. Timestamp & log it. user.lastSignIn = new Timestamp(new Date().getTime()); // Should we use new Timestamp(System.currentTimeMillis()); instead? - CUser.update(user); + userRepository.update(user); return LoginEnum.Status.SUCCESS; } diff --git a/MavenBack/src/main/java/ppp/db/UserRepository.java b/MavenBack/src/main/java/ppp/db/UserRepository.java new file mode 100644 index 0000000..684db24 --- /dev/null +++ b/MavenBack/src/main/java/ppp/db/UserRepository.java @@ -0,0 +1,8 @@ +package ppp.db; + +import ppp.db.model.OUser; + +public interface UserRepository { + OUser findByEmail(String email, boolean withToken); + void update(OUser user); +} diff --git a/MavenBack/src/main/java/ppp/db/controllers/CUserRepository.java b/MavenBack/src/main/java/ppp/db/controllers/CUserRepository.java new file mode 100644 index 0000000..4c18321 --- /dev/null +++ b/MavenBack/src/main/java/ppp/db/controllers/CUserRepository.java @@ -0,0 +1,17 @@ +package ppp.db.controllers; + +import ppp.db.UserRepository; +import ppp.db.model.OUser; + +public class CUserRepository implements UserRepository { + + @Override + public OUser findByEmail(String email, boolean withToken) { + return CUser.findByEmail(email, withToken); + } + + @Override + public void update(OUser user) { + CUser.update(user); + } +} diff --git a/MavenBack/src/main/java/ppp/staticServe/DashServe.java b/MavenBack/src/main/java/ppp/staticServe/DashServe.java index 0975e06..4706d0f 100644 --- a/MavenBack/src/main/java/ppp/staticServe/DashServe.java +++ b/MavenBack/src/main/java/ppp/staticServe/DashServe.java @@ -12,8 +12,10 @@ import jakarta.servlet.http.HttpServletResponse; import ppp.api.GetGames; import ppp.auth.Authenticator; +import ppp.db.UserRepository; import ppp.db.controllers.CGames; import ppp.db.controllers.CUser; +import ppp.db.controllers.CUserRepository; import ppp.db.model.OUser; import ppp.meta.GlickoTwo; import ppp.meta.LoginEnum; @@ -27,7 +29,8 @@ public class DashServe extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - Authenticator auth = new Authenticator(); + UserRepository repository = new CUserRepository(); + Authenticator auth = new Authenticator(repository); boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; OUser user = new OUser(); if (loggedIn) user = CUser.findByEmail((String)request.getSession().getAttribute("email")); @@ -56,8 +59,9 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { Map parameters = request.getParameterMap(); - - Authenticator auth = new Authenticator(); + + UserRepository repository = new CUserRepository(); + Authenticator auth = new Authenticator(repository); boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; if (!loggedIn) { response.setStatus(401); diff --git a/MavenBack/src/main/java/ppp/staticServe/GamesServe.java b/MavenBack/src/main/java/ppp/staticServe/GamesServe.java index 65e3fba..0d39e8e 100644 --- a/MavenBack/src/main/java/ppp/staticServe/GamesServe.java +++ b/MavenBack/src/main/java/ppp/staticServe/GamesServe.java @@ -10,6 +10,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import ppp.auth.Authenticator; +import ppp.db.UserRepository; +import ppp.db.controllers.CUserRepository; import ppp.meta.LoginEnum; @WebServlet("/games") @@ -24,7 +26,8 @@ public class GamesServe extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - Authenticator auth = new Authenticator(); + UserRepository repository = new CUserRepository(); + Authenticator auth = new Authenticator(repository); boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; try { diff --git a/MavenBack/src/main/java/ppp/staticServe/LoginServe.java b/MavenBack/src/main/java/ppp/staticServe/LoginServe.java index 985ae10..05e8762 100644 --- a/MavenBack/src/main/java/ppp/staticServe/LoginServe.java +++ b/MavenBack/src/main/java/ppp/staticServe/LoginServe.java @@ -10,6 +10,8 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import ppp.auth.Authenticator; +import ppp.db.UserRepository; +import ppp.db.controllers.CUserRepository; import ppp.meta.LoginEnum; @WebServlet("/login") @@ -18,7 +20,8 @@ public class LoginServe extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - Authenticator auth = new Authenticator(); + UserRepository repository = new CUserRepository(); + Authenticator auth = new Authenticator(repository); boolean loggedIn = auth.login(request) == LoginEnum.Status.SUCCESS; try { diff --git a/MavenBack/src/test/java/ppp/auth/AuthenticatorTest.java b/MavenBack/src/test/java/ppp/auth/AuthenticatorTest.java new file mode 100644 index 0000000..847d14e --- /dev/null +++ b/MavenBack/src/test/java/ppp/auth/AuthenticatorTest.java @@ -0,0 +1,65 @@ +package ppp.auth; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.Timestamp; + +import ppp.db.UserRepository; +import ppp.db.model.OUser; +import ppp.meta.LoginEnum; + +class AuthenticatorTest { + + private UserRepository userRepositoryMock; + private Authenticator authenticator; + + @BeforeEach + void setUp() { + userRepositoryMock = mock(UserRepository.class); + authenticator = new Authenticator(userRepositoryMock); + } + + @Test + void testLoginSuccess() { + OUser mockUser = new OUser(); + mockUser.id = 1; + mockUser.email = "user@example.com"; + mockUser.token = "validToken"; + mockUser.tokenExpiryDate = new Timestamp(System.currentTimeMillis() + 10000); + mockUser.banned = false; + + when(userRepositoryMock.findByEmail("user@example.com", true)).thenReturn(mockUser); + + LoginEnum.Status status = authenticator.login("user@example.com", "validToken"); + assertEquals(LoginEnum.Status.SUCCESS, status); + + verify(userRepositoryMock).update(any(OUser.class)); + } + + @Test + void testLoginUserInvalid() { + when(userRepositoryMock.findByEmail("invalid@example.com", true)).thenReturn(new OUser()); + + LoginEnum.Status status = authenticator.login("invalid@example.com", "anyToken"); + assertEquals(LoginEnum.Status.USER_INVALID, status); + } + + @Test + void testLoginTokenExpired() { + OUser mockUser = new OUser(); + mockUser.id = 1; + mockUser.email = "user@example.com"; + mockUser.token = "expiredToken"; + mockUser.tokenExpiryDate = new Timestamp(System.currentTimeMillis() - 10000); + mockUser.banned = false; + + when(userRepositoryMock.findByEmail("user@example.com", true)).thenReturn(mockUser); + + LoginEnum.Status status = authenticator.login("user@example.com", "expiredToken"); + assertEquals(LoginEnum.Status.TOKEN_EXPIRED, status); + } +} From b5d869ec6201d751160615b9bef67708fa7d9208 Mon Sep 17 00:00:00 2001 From: ALEEF02 Date: Sat, 23 Nov 2024 15:40:36 -0500 Subject: [PATCH 2/9] Unit testing workflow --- .github/workflows/unit_tests.yml | 38 ++++++++++++++++++++++++++++++++ MavenBack/pom.xml | 9 ++++++++ 2 files changed, 47 insertions(+) create mode 100644 .github/workflows/unit_tests.yml diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 0000000..06416ec --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,38 @@ +name: Java Unit Testing + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # Step 1: Check out the repository + - name: Checkout repository + uses: actions/checkout@v3 + + # Step 2: Set up JDK + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' # You can change this to your desired distribution (e.g., 'zulu', 'adopt') + + # Step 3: Cache Maven dependencies + - name: Cache Maven dependencies + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-m2 + + # Step 4: Build and test with Maven + - name: Build and run tests + run: mvn clean test diff --git a/MavenBack/pom.xml b/MavenBack/pom.xml index f0e6033..e010926 100644 --- a/MavenBack/pom.xml +++ b/MavenBack/pom.xml @@ -13,6 +13,7 @@ 11 UTF-8 11.0.12 + 2.0.9 ppp.ServerMain @@ -65,6 +66,14 @@ 7.5.0 + + + org.mockito + mockito-junit-jupiter + 5.14.2 + compile + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.5.2 + From 4634f68278cc960c7f044f2cec86f9c151ba4853 Mon Sep 17 00:00:00 2001 From: ALEEF02 Date: Wed, 4 Dec 2024 13:43:40 -0500 Subject: [PATCH 8/9] Additional Unit Tests --- .../src/main/java/ppp/auth/Authenticator.java | 3 +- .../AuthenticatorCompareAuthCodeTest.java | 60 +++++++++++++ .../auth/AuthenticatorLoginRequestTest.java | 90 +++++++++++++++++++ .../auth/AuthenticatorSendAuthEmailTest.java | 61 +++++++++++++ 4 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 MavenBack/src/test/java/ppp/auth/AuthenticatorCompareAuthCodeTest.java create mode 100644 MavenBack/src/test/java/ppp/auth/AuthenticatorLoginRequestTest.java create mode 100644 MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java diff --git a/MavenBack/src/main/java/ppp/auth/Authenticator.java b/MavenBack/src/main/java/ppp/auth/Authenticator.java index 70d6944..fa12e32 100644 --- a/MavenBack/src/main/java/ppp/auth/Authenticator.java +++ b/MavenBack/src/main/java/ppp/auth/Authenticator.java @@ -11,7 +11,6 @@ import jakarta.servlet.http.HttpServletRequest; import ppp.ServerConfig; import ppp.db.UserRepository; -import ppp.db.controllers.CUser; import ppp.db.model.OUser; import ppp.meta.LoginEnum; @@ -24,7 +23,7 @@ public class Authenticator { * index 1: AuthCode
* index 2: Attempts */ - private static Map emailsSent = new HashMap(); + protected static Map emailsSent = new HashMap(); // Access to CUser that can be unit tested private final UserRepository userRepository; diff --git a/MavenBack/src/test/java/ppp/auth/AuthenticatorCompareAuthCodeTest.java b/MavenBack/src/test/java/ppp/auth/AuthenticatorCompareAuthCodeTest.java new file mode 100644 index 0000000..28626b6 --- /dev/null +++ b/MavenBack/src/test/java/ppp/auth/AuthenticatorCompareAuthCodeTest.java @@ -0,0 +1,60 @@ +package ppp.auth; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.sql.Timestamp; + +import ppp.db.UserRepository; +import ppp.db.model.OUser; +import ppp.meta.LoginEnum; + +class AuthenticatorCompareAuthCodeTest { + + @Test + void testCompareAuthCodeSuccess() { + Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000), 12345, 0}); + Authenticator authenticator = new Authenticator(null); // No UserRepository needed for this test. + + LoginEnum.Status status = authenticator.compareAuthCode("user@example.com", 12345); + assertEquals(LoginEnum.Status.SUCCESS, status); + } + + @Test + void testCompareAuthCodeEmailInvalid() { + Authenticator authenticator = new Authenticator(null); + + LoginEnum.Status status = authenticator.compareAuthCode("nonexistent@example.com", 12345); + assertEquals(LoginEnum.Status.EMAIL_INVALID, status); + } + + @Test + void testCompareAuthCodeTooLate() { + Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000 - 3600), 12345, 0}); + Authenticator authenticator = new Authenticator(null); + + LoginEnum.Status status = authenticator.compareAuthCode("user@example.com", 12345); + assertEquals(LoginEnum.Status.AUTH_TOO_LATE, status); + } + + @Test + void testCompareAuthCodeTooManyAttempts() { + Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000), 12345, 3}); + Authenticator authenticator = new Authenticator(null); + + LoginEnum.Status status = authenticator.compareAuthCode("user@example.com", 12345); + assertEquals(LoginEnum.Status.TOO_MANY_ATTEMPTS, status); + } + + @Test + void testCompareAuthCodeInvalid() { + Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000), 12345, 0}); + Authenticator authenticator = new Authenticator(null); + + LoginEnum.Status status = authenticator.compareAuthCode("user@example.com", 54321); + assertEquals(LoginEnum.Status.AUTH_INVALID, status); + } +} diff --git a/MavenBack/src/test/java/ppp/auth/AuthenticatorLoginRequestTest.java b/MavenBack/src/test/java/ppp/auth/AuthenticatorLoginRequestTest.java new file mode 100644 index 0000000..622e1f6 --- /dev/null +++ b/MavenBack/src/test/java/ppp/auth/AuthenticatorLoginRequestTest.java @@ -0,0 +1,90 @@ +package ppp.auth; + +import static org.mockito.Mockito.*; + +import java.sql.Timestamp; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; +import ppp.db.UserRepository; +import ppp.db.model.OUser; +import ppp.meta.LoginEnum; + +class AuthenticatorLoginRequestTest { + + HttpServletRequest request = mock(HttpServletRequest.class); + HttpSession session = mock(HttpSession.class); + + @BeforeEach + void setUp() { + request = mock(HttpServletRequest.class); + session = mock(HttpSession.class); + when(request.getSession()).thenReturn(session); // Return mocked session + } + + @Test + void testLoginRequestSuccess() { + when(request.getSession().getAttribute("email")).thenReturn("user@stevens.edu"); + when(request.getSession().getAttribute("token")).thenReturn("validToken"); + + UserRepository userRepository = mock(UserRepository.class); + OUser mockUser = new OUser(); + mockUser.id = 1; + mockUser.email = "user@stevens.edu"; + mockUser.token = "validToken"; + mockUser.tokenExpiryDate = new Timestamp(new Date(System.currentTimeMillis() + 10000).getTime()); + when(userRepository.findByEmail("user@stevens.edu", true)).thenReturn(mockUser); + + Authenticator authenticator = new Authenticator(userRepository); + LoginEnum.Status status = authenticator.login(request); + + assertEquals(LoginEnum.Status.SUCCESS, status); + } + + @Test + void testLoginRequestEmailInvalid() { + when(request.getSession().getAttribute("email")).thenReturn("user@gmail.com"); + + Authenticator authenticator = new Authenticator(null); // No repository needed for this test. + LoginEnum.Status status = authenticator.login(request); + + assertEquals(LoginEnum.Status.EMAIL_INVALID, status); + } + + @Test + void testLoginRequestTokenInvalid() { + when(request.getSession().getAttribute("email")).thenReturn("user@stevens.edu"); + when(request.getSession().getAttribute("token")).thenReturn(""); + + Authenticator authenticator = new Authenticator(null); // No repository needed for this test. + LoginEnum.Status status = authenticator.login(request); + + assertEquals(LoginEnum.Status.TOKEN_INVALID, status); + } + + @Test + void testLoginRequestNullEmail() { + when(request.getSession().getAttribute("email")).thenReturn(null); + + Authenticator authenticator = new Authenticator(null); // No repository needed for this test. + LoginEnum.Status status = authenticator.login(request); + + assertEquals(LoginEnum.Status.EMAIL_INVALID, status); + } + + @Test + void testLoginRequestNullToken() { + when(request.getSession().getAttribute("email")).thenReturn("user@stevens.edu"); + when(request.getSession().getAttribute("token")).thenReturn(null); + + Authenticator authenticator = new Authenticator(null); // No repository needed for this test. + LoginEnum.Status status = authenticator.login(request); + + assertEquals(LoginEnum.Status.TOKEN_INVALID, status); + } +} \ No newline at end of file diff --git a/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java b/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java new file mode 100644 index 0000000..f8d970f --- /dev/null +++ b/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java @@ -0,0 +1,61 @@ +package ppp.auth; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import ppp.meta.LoginEnum; + +class AuthenticatorSendAuthEmailTest { + + @Test + void testSendAuthEmailSuccess() { + Authenticator authenticator = new Authenticator(null); + LoginEnum.Status status = authenticator.sendAuthEmail("user@example.com"); + assertEquals(LoginEnum.Status.EMAIL_SENT, status); + } + + @Test + void testSendAuthEmailAlreadySent() { + Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000), 12345, 0}); + Authenticator authenticator = new Authenticator(null); + + LoginEnum.Status status = authenticator.sendAuthEmail("user@example.com"); + assertEquals(LoginEnum.Status.AUTH_ALREADY_SENT, status); + } + + @Test + void testSendAuthEmailInvalidAddress() { + Authenticator authenticator = new Authenticator(null); + LoginEnum.Status status = authenticator.sendAuthEmail("invalid_email"); + assertNotEquals(LoginEnum.Status.EMAIL_SENT, status); // Email sanitization TODO + } + + @Test + void testSendAuthEmailRateLimit() { + Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000 - 500), 12345, 0}); + Authenticator authenticator = new Authenticator(null); + + LoginEnum.Status status = authenticator.sendAuthEmail("user@example.com"); + assertEquals(LoginEnum.Status.AUTH_ALREADY_SENT, status); + } + + @Test + void testSendAuthEmailRandomCode() { + Authenticator authenticator = new Authenticator(null); + authenticator.sendAuthEmail("user@example.com"); + + Integer[] emailData = Authenticator.emailsSent.get("user@example.com"); + assertNotNull(emailData); + assertTrue(emailData[1] > 0); // Random code was generated + } + + @AfterEach + void cleanUp() { + // Clean-up + Authenticator.emailsSent.clear(); + } +} + From 8df2f0893b1e3e08c14bf23254d0bbfe3465a35b Mon Sep 17 00:00:00 2001 From: ALEEF02 Date: Wed, 4 Dec 2024 14:42:22 -0500 Subject: [PATCH 9/9] Add Unit Tests --- MavenBack/src/main/java/ppp/ServerMain.java | 5 +++++ .../src/main/java/ppp/auth/Authenticator.java | 19 ++++++++++++------- .../src/main/java/ppp/meta/LoginEnum.java | 1 + .../auth/AuthenticatorSendAuthEmailTest.java | 17 ----------------- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/MavenBack/src/main/java/ppp/ServerMain.java b/MavenBack/src/main/java/ppp/ServerMain.java index 5d936e7..081cf2a 100644 --- a/MavenBack/src/main/java/ppp/ServerMain.java +++ b/MavenBack/src/main/java/ppp/ServerMain.java @@ -52,6 +52,11 @@ public static void main(String[] args) throws Exception { // Load the env variables from the config. This will also build a new cfg file if none exists. new ConfigurationBuilder(ServerConfig.class, new File("application.cfg")).build(true); + if (ServerConfig.EMAIL_USER.isBlank()) { + logger.error("No EMAIL_USER provided!"); + System.exit(-1); + } + // Connect to the DB logger.info("DB connecting..."); WebDb.init(); diff --git a/MavenBack/src/main/java/ppp/auth/Authenticator.java b/MavenBack/src/main/java/ppp/auth/Authenticator.java index fa12e32..b07f4d3 100644 --- a/MavenBack/src/main/java/ppp/auth/Authenticator.java +++ b/MavenBack/src/main/java/ppp/auth/Authenticator.java @@ -120,14 +120,19 @@ public LoginEnum.Status sendAuthEmail(String toEmailAddress) { final int authCode = (int)(Math.random() * Math.pow(10, ServerConfig.AUTH_NUM_DIGITS)); // TODO: This can produce numbers LESS than the number of digits with the current implementation. // Everything looks in order. Create, send, and store the email - Email email = EmailBuilder.startingBlank() - .from("PingPongPage", ServerConfig.EMAIL_USER) - .to(toEmailAddress) - .withSubject("One-Time Password") - .withPlainText("Hi! Your one-time password is: " + authCode + ". It'll expire in " + ServerConfig.AUTH_CODE_VALIDITY_PERIOD + " minutes.\nThanks for using our service\n\t- Backend Software Engineer, Anthony Ford") - .buildEmail(); + try { + Email email = EmailBuilder.startingBlank() + .from("PingPongPage", ServerConfig.EMAIL_USER) + .to(toEmailAddress) + .withSubject("One-Time Password") + .withPlainText("Hi! Your one-time password is: " + authCode + ". It'll expire in " + ServerConfig.AUTH_CODE_VALIDITY_PERIOD + " minutes.\nThanks for using our service\n\t- Backend Software Engineer, Anthony Ford") + .buildEmail(); + + Emailer.getMailer(true).sendMail(email); + } catch (Exception e) { + return LoginEnum.Status.EMAILING_ERROR; + } - Emailer.getMailer(true).sendMail(email); Integer mapVal[] = {Integer.valueOf((int)now), Integer.valueOf(authCode), 0}; emailsSent.put(toEmailAddress, mapVal); return LoginEnum.Status.EMAIL_SENT; diff --git a/MavenBack/src/main/java/ppp/meta/LoginEnum.java b/MavenBack/src/main/java/ppp/meta/LoginEnum.java index 91c3732..134cbf2 100644 --- a/MavenBack/src/main/java/ppp/meta/LoginEnum.java +++ b/MavenBack/src/main/java/ppp/meta/LoginEnum.java @@ -22,6 +22,7 @@ public static enum Status { BANNED(401, "omegalol"), UNKNOWN_ERROR(500), + EMAILING_ERROR(503, "The emailer is having issues. Please contact PPP administrators."), EMAIL_SENT(200), SUCCESS(200); diff --git a/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java b/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java index f8d970f..c16a373 100644 --- a/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java +++ b/MavenBack/src/test/java/ppp/auth/AuthenticatorSendAuthEmailTest.java @@ -10,13 +10,6 @@ class AuthenticatorSendAuthEmailTest { - @Test - void testSendAuthEmailSuccess() { - Authenticator authenticator = new Authenticator(null); - LoginEnum.Status status = authenticator.sendAuthEmail("user@example.com"); - assertEquals(LoginEnum.Status.EMAIL_SENT, status); - } - @Test void testSendAuthEmailAlreadySent() { Authenticator.emailsSent.put("user@example.com", new Integer[]{(int)(System.currentTimeMillis() / 1000), 12345, 0}); @@ -41,16 +34,6 @@ void testSendAuthEmailRateLimit() { LoginEnum.Status status = authenticator.sendAuthEmail("user@example.com"); assertEquals(LoginEnum.Status.AUTH_ALREADY_SENT, status); } - - @Test - void testSendAuthEmailRandomCode() { - Authenticator authenticator = new Authenticator(null); - authenticator.sendAuthEmail("user@example.com"); - - Integer[] emailData = Authenticator.emailsSent.get("user@example.com"); - assertNotNull(emailData); - assertTrue(emailData[1] > 0); // Random code was generated - } @AfterEach void cleanUp() {