Skip to content
Closed
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
14 changes: 1 addition & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -496,17 +496,6 @@
<excludes>
<exclude>**/*IT</exclude>
</excludes>
<!--
Pin tests to UTC so they pass deterministically on non-UTC developer
machines. The application reads SQL DATETIME values via JDBC
getTimestamp() without a Calendar, which interprets them in the JVM's
default timezone. With the DB in UTC and the JVM in a non-UTC zone,
time-based checks (suspendedUntil, startTime, lockTime, endTime) skew
by the JVM's UTC offset. CI runs in UTC so does not see this; local
runs on UTC+N developer machines fail those tests.
Production bug tracked in #841.
-->
<argLine>-Duser.timezone=UTC</argLine>
</configuration>
</plugin>
<plugin>
Expand All @@ -519,7 +508,6 @@
<excludes>
<exclude>**/*Test*</exclude>
</excludes>
<argLine>-Duser.timezone=UTC</argLine>
</configuration>
<executions>
<execution>
Expand Down Expand Up @@ -594,4 +582,4 @@

</plugins>
</build>
</project>
</project>
25 changes: 25 additions & 0 deletions src/it/java/dbProcs/GetterAuthIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import java.io.IOException;
import java.sql.SQLException;
import java.util.TimeZone;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.AfterAll;
Expand Down Expand Up @@ -75,6 +76,30 @@ public void suspendedUserIsRejected() throws SQLException {
"User should be able to authenticate after unsuspension");
}

@Test
public void suspendedUserIsRejectedWhenJvmTimezoneIsNonUtc() throws SQLException {
requireDatabase();
TimeZone originalTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Kolkata"));
try {
String userName = "authSuspendedNonUtcUser";

Setter.userCreate(
applicationRoot, null, userName, userName, "player", userName + "@test.com", false);
String[] user = Getter.authUser(applicationRoot, userName, userName);
assertNotNull(user, "User should be able to authenticate before suspension");

String userId = user[0];

assertTrue(Setter.suspendUser(applicationRoot, userId, 10), "Could not suspend user");
assertNull(
Getter.authUser(applicationRoot, userName, userName),
"Suspended user should not be able to authenticate under a non-UTC JVM timezone");
} finally {
TimeZone.setDefault(originalTimeZone);
}
}

@Test
public void ssoUserIsRejectedFromPasswordLogin() {
requireDatabase();
Expand Down
25 changes: 25 additions & 0 deletions src/it/java/dbProcs/GetterIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

Expand All @@ -14,6 +15,7 @@
import java.util.ArrayList;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.TimeZone;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
Expand Down Expand Up @@ -3194,6 +3196,29 @@ public void testSSOAuthSuspended() {
}
}

@Test
public void testSSOAuthSuspendedWithNonUtcJvmTimeZone() {
TimeZone originalTimeZone = TimeZone.getDefault();
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Kolkata"));
try {
String userName = "SSOSuspendedNonUtcUser Lastname";
String ssoName = "ssosuspendednonutcuser@example.com";

String[] user = Getter.authUserSSO(applicationRoot, null, userName, ssoName, "player");
assertNotNull(user, "Initial SSO auth should succeed");
assertFalse(user[0].isEmpty(), "Initial SSO auth should return a userId");

String userID = user[0];

assertTrue(Setter.suspendUser(applicationRoot, userID, 10), "Could not suspend user");
assertNull(
Getter.authUserSSO(applicationRoot, null, userName, ssoName, "player"),
"Suspended SSO user should not authenticate under a non-UTC JVM timezone");
} finally {
TimeZone.setDefault(originalTimeZone);
}
}

/**
* Exercises the existing-user SSO re-login path: the first call creates the user, the second call
* finds the existing (non-suspended) user. This drives Phase 1 (found) -> skip create -> Phase 3
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/dbProcs/Getter.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.json.JSONObject;
import org.owasp.encoder.Encode;
import servlets.Register;
import utils.DbTime;
import utils.ModulePlan;
import utils.ScoreboardStatus;

Expand Down Expand Up @@ -112,7 +113,7 @@ public static String[] authUser(String ApplicationRoot, String userName, String
badLoginCount = userResult.getInt(5);
tempPassword = userResult.getBoolean(6);
classId = userResult.getString(7);
suspendedUntil = userResult.getTimestamp(8);
suspendedUntil = userResult.getTimestamp(8, DbTime.utcCalendar());
loginType = userResult.getString(9);
tempUsername = userResult.getBoolean(10);
} else {
Expand Down Expand Up @@ -237,7 +238,7 @@ public static String[] authUserSSO(
// User found if a row is in the database
userFound = true;
log.debug("User Found");
suspendedUntil = userResult.getTimestamp(1);
suspendedUntil = userResult.getTimestamp(1, DbTime.utcCalendar());
} else {
userFound = false;
}
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/utils/DbTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package utils;

import java.util.Calendar;
import java.util.TimeZone;

public final class DbTime {

private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

private DbTime() {}

public static Calendar utcCalendar() {
return Calendar.getInstance(UTC);
}
}
23 changes: 23 additions & 0 deletions src/test/java/utils/DbTimeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package utils;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;

import java.util.Calendar;
import org.junit.jupiter.api.Test;

class DbTimeTest {

@Test
void utcCalendarUsesUtc() {
assertEquals("UTC", DbTime.utcCalendar().getTimeZone().getID());
}

@Test
void utcCalendarReturnsIndependentInstances() {
Calendar first = DbTime.utcCalendar();
Calendar second = DbTime.utcCalendar();

assertNotSame(first, second);
}
}