287 lines
11 KiB
Java
287 lines
11 KiB
Java
package jmri.jmrit.permission;
|
|
|
|
import jmri.util.JUnitUtil;
|
|
|
|
import org.junit.jupiter.api.*;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
import java.util.Locale;
|
|
|
|
/**
|
|
* Tests for DefaultPermissionManager session management.
|
|
*
|
|
* @author Ralf Lang
|
|
* @author JMRI Community (C) 2026
|
|
*/
|
|
public class DefaultPermissionManagerTest {
|
|
|
|
private DefaultPermissionManager manager;
|
|
|
|
/**
|
|
* Test successful remote login with valid credentials.
|
|
*/
|
|
@Test
|
|
public void testRemoteLoginSuccess() throws Exception {
|
|
// Add a test user
|
|
manager.addUser("testuser", "testpass");
|
|
|
|
// Attempt remote login
|
|
StringBuilder sessionId = new StringBuilder();
|
|
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
|
|
|
|
assertTrue(result, "Remote login should succeed with valid credentials");
|
|
assertNotNull(sessionId.toString(), "Session ID should not be null");
|
|
assertFalse(sessionId.toString().isBlank(), "Session ID should not be empty or whitespace-only");
|
|
assertEquals(10, sessionId.length(), "Session ID should be 10 characters long");
|
|
}
|
|
|
|
/**
|
|
* Test remote login with invalid password.
|
|
*/
|
|
@Test
|
|
public void testRemoteLoginInvalidPassword() throws Exception {
|
|
// Add a test user
|
|
manager.addUser("testuser", "testpass");
|
|
|
|
// Attempt remote login with wrong password
|
|
StringBuilder sessionId = new StringBuilder();
|
|
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "wrongpass");
|
|
|
|
assertFalse(result, "Remote login should fail with invalid password");
|
|
assertEquals(0, sessionId.length(), "Session ID should be empty on failed login");
|
|
}
|
|
|
|
/**
|
|
* Test remote login with non-existent user.
|
|
*/
|
|
@Test
|
|
public void testRemoteLoginNonExistentUser() {
|
|
// Attempt remote login with non-existent user
|
|
StringBuilder sessionId = new StringBuilder();
|
|
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "nonexistent", "anypass");
|
|
|
|
assertFalse(result, "Remote login should fail for non-existent user");
|
|
assertEquals(0, sessionId.length(), "Session ID should be empty on failed login");
|
|
}
|
|
|
|
/**
|
|
* Test that session ID is stored and can be verified.
|
|
*/
|
|
@Test
|
|
public void testRemoteSessionStorage() throws Exception {
|
|
// Add a test user and login
|
|
manager.addUser("testuser", "testpass");
|
|
StringBuilder sessionId = new StringBuilder();
|
|
manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
|
|
|
|
// Verify the session is stored
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId.toString()),
|
|
"Session should be marked as logged in");
|
|
}
|
|
|
|
/**
|
|
* Test that invalid session ID is not recognized.
|
|
*/
|
|
@Test
|
|
public void testInvalidSessionNotLoggedIn() {
|
|
assertFalse(manager.isRemotelyLoggedIn("invalid-session-id"),
|
|
"Invalid session should not be recognized as logged in");
|
|
assertFalse(manager.isRemotelyLoggedIn(null),
|
|
"Null session should not be recognized as logged in");
|
|
assertFalse(manager.isRemotelyLoggedIn(""),
|
|
"Empty session should not be recognized as logged in");
|
|
assertFalse(manager.isRemotelyLoggedIn(" "),
|
|
"Blank session should not be recognized as logged in");
|
|
}
|
|
|
|
/**
|
|
* Test remote logout removes the session.
|
|
*/
|
|
@Test
|
|
public void testRemoteLogout() throws Exception {
|
|
// Add a test user and login
|
|
manager.addUser("testuser", "testpass");
|
|
StringBuilder sessionId = new StringBuilder();
|
|
manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
|
|
|
|
// Verify session exists
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId.toString()),
|
|
"Session should exist before logout");
|
|
|
|
// Logout
|
|
manager.remoteLogout(sessionId.toString());
|
|
|
|
// Verify session is removed
|
|
assertFalse(manager.isRemotelyLoggedIn(sessionId.toString()),
|
|
"Session should be removed after logout");
|
|
}
|
|
|
|
/**
|
|
* Test remote logout with invalid session IDs (should not throw exception).
|
|
*/
|
|
@Test
|
|
public void testRemoteLogoutInvalidSessions() {
|
|
// These should not throw exceptions
|
|
assertDoesNotThrow(() -> manager.remoteLogout(null),
|
|
"Logout with null session should not throw");
|
|
assertDoesNotThrow(() -> manager.remoteLogout(""),
|
|
"Logout with empty session should not throw");
|
|
assertDoesNotThrow(() -> manager.remoteLogout(" "),
|
|
"Logout with blank session should not throw");
|
|
assertDoesNotThrow(() -> manager.remoteLogout("nonexistent-session"),
|
|
"Logout with non-existent session should not throw");
|
|
}
|
|
|
|
/**
|
|
* Test multiple simultaneous remote sessions for different users.
|
|
*/
|
|
@Test
|
|
public void testMultipleRemoteSessions() throws Exception {
|
|
// Add multiple users
|
|
manager.addUser("user1", "pass1");
|
|
manager.addUser("user2", "pass2");
|
|
|
|
// Login both users
|
|
StringBuilder sessionId1 = new StringBuilder();
|
|
StringBuilder sessionId2 = new StringBuilder();
|
|
manager.remoteLogin(sessionId1, Locale.getDefault(), "user1", "pass1");
|
|
manager.remoteLogin(sessionId2, Locale.getDefault(), "user2", "pass2");
|
|
|
|
// Verify both sessions exist
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId1.toString()),
|
|
"User1 session should exist");
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
|
|
"User2 session should exist");
|
|
|
|
// Sessions should be different
|
|
assertNotEquals(sessionId1.toString(), sessionId2.toString(),
|
|
"Different users should have different session IDs");
|
|
|
|
// Logout user1
|
|
manager.remoteLogout(sessionId1.toString());
|
|
|
|
// Verify user1 session removed but user2 session still exists
|
|
assertFalse(manager.isRemotelyLoggedIn(sessionId1.toString()),
|
|
"User1 session should be removed");
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
|
|
"User2 session should still exist");
|
|
}
|
|
|
|
/**
|
|
* Test that session IDs are generated uniquely.
|
|
* Note: This test verifies uniqueness for multiple logins,
|
|
* but does not test cryptographic randomness.
|
|
*/
|
|
@Test
|
|
public void testSessionIdUniqueness() throws Exception {
|
|
manager.addUser("testuser", "testpass");
|
|
|
|
// Generate multiple session IDs
|
|
StringBuilder sessionId1 = new StringBuilder();
|
|
StringBuilder sessionId2 = new StringBuilder();
|
|
StringBuilder sessionId3 = new StringBuilder();
|
|
|
|
manager.remoteLogin(sessionId1, Locale.getDefault(), "testuser", "testpass");
|
|
manager.remoteLogout(sessionId1.toString());
|
|
|
|
manager.remoteLogin(sessionId2, Locale.getDefault(), "testuser", "testpass");
|
|
manager.remoteLogout(sessionId2.toString());
|
|
|
|
manager.remoteLogin(sessionId3, Locale.getDefault(), "testuser", "testpass");
|
|
|
|
// Verify all session IDs are different
|
|
assertNotEquals(sessionId1.toString(), sessionId2.toString(),
|
|
"Consecutive session IDs should be different");
|
|
assertNotEquals(sessionId2.toString(), sessionId3.toString(),
|
|
"Consecutive session IDs should be different");
|
|
assertNotEquals(sessionId1.toString(), sessionId3.toString(),
|
|
"Consecutive session IDs should be different");
|
|
}
|
|
|
|
/**
|
|
* Test that pre-existing session ID in StringBuilder is used.
|
|
*/
|
|
@Test
|
|
public void testRemoteLoginWithPreExistingSessionId() throws Exception {
|
|
manager.addUser("testuser", "testpass");
|
|
|
|
// Provide a pre-existing session ID
|
|
StringBuilder sessionId = new StringBuilder("my-custom-session-id");
|
|
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "testuser", "testpass");
|
|
|
|
assertTrue(result, "Remote login should succeed");
|
|
assertEquals("my-custom-session-id", sessionId.toString(),
|
|
"Pre-existing session ID should be preserved");
|
|
assertTrue(manager.isRemotelyLoggedIn("my-custom-session-id"),
|
|
"Pre-existing session ID should be registered");
|
|
}
|
|
|
|
/**
|
|
* Test that guest user cannot login remotely.
|
|
* Guest user has null password which should cause login to fail safely.
|
|
*/
|
|
@Test
|
|
public void testGuestUserCannotLoginRemotely() {
|
|
StringBuilder sessionId = new StringBuilder();
|
|
|
|
// Guest user login should fail (guest has null password)
|
|
// This may throw NPE or return false depending on implementation
|
|
// We just verify that no session is created
|
|
try {
|
|
boolean result = manager.remoteLogin(sessionId, Locale.getDefault(), "guest", "anypassword");
|
|
assertFalse(result, "Guest user should not be able to login remotely");
|
|
} catch (NullPointerException e) {
|
|
// Expected - guest user has null password which causes NPE in checkPassword
|
|
// This is acceptable behavior - guest cannot login remotely
|
|
}
|
|
|
|
// Verify no session was created for guest
|
|
assertFalse(manager.isRemotelyLoggedIn(sessionId.toString()),
|
|
"No session should be created for guest user");
|
|
}
|
|
|
|
/**
|
|
* Test same user can have multiple remote sessions simultaneously.
|
|
*/
|
|
@Test
|
|
public void testSameUserMultipleSessions() throws Exception {
|
|
manager.addUser("testuser", "testpass");
|
|
|
|
// Login same user twice with different sessions
|
|
StringBuilder sessionId1 = new StringBuilder();
|
|
StringBuilder sessionId2 = new StringBuilder();
|
|
|
|
manager.remoteLogin(sessionId1, Locale.getDefault(), "testuser", "testpass");
|
|
manager.remoteLogin(sessionId2, Locale.getDefault(), "testuser", "testpass");
|
|
|
|
// Both sessions should be valid
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId1.toString()),
|
|
"First session should be valid");
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
|
|
"Second session should be valid");
|
|
|
|
// Logout one session
|
|
manager.remoteLogout(sessionId1.toString());
|
|
|
|
// First session should be invalid, second should still be valid
|
|
assertFalse(manager.isRemotelyLoggedIn(sessionId1.toString()),
|
|
"First session should be invalidated");
|
|
assertTrue(manager.isRemotelyLoggedIn(sessionId2.toString()),
|
|
"Second session should still be valid");
|
|
}
|
|
|
|
@BeforeEach
|
|
public void setUp() {
|
|
JUnitUtil.setUp();
|
|
JUnitUtil.resetProfileManager();
|
|
manager = new DefaultPermissionManager().init();
|
|
}
|
|
|
|
@AfterEach
|
|
public void tearDown() {
|
|
JUnitUtil.tearDown();
|
|
}
|
|
|
|
}
|