fix add-on expiry, add tests
This commit is contained in:
@@ -104,5 +104,12 @@
|
||||
<artifactId>commons-csv</artifactId>
|
||||
<version>${commons-csv.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -416,11 +416,7 @@ public class PermissionManager implements UserDataProvider {
|
||||
List<Permission> existingPermissions = get(target, name);
|
||||
|
||||
for (Permission existingPermission : existingPermissions) {
|
||||
if (additional && (starts == null && (existingPermission.getStarts() == null
|
||||
|| existingPermission.getStarts().isBefore(Instant.now()))
|
||||
|| starts != null && (starts.isBefore(existingPermission.getExpires())
|
||||
|| existingPermission.getStarts() != null
|
||||
&& starts.isAfter(existingPermission.getStarts())))) {
|
||||
if (additional) {
|
||||
if (permission == null) {
|
||||
permission = existingPermission;
|
||||
} else if (existingPermission.getExpires().isAfter(permission.getExpires())) {
|
||||
@@ -437,13 +433,23 @@ public class PermissionManager implements UserDataProvider {
|
||||
permission.setStarts(permissionStarts);
|
||||
permission.setExpires(permissionsExpires);
|
||||
} else {
|
||||
// For expired permissions, calculate the appropriate future expiry date
|
||||
if (permission.getExpires() == null || permission.getExpires().isBefore(Instant.now())) {
|
||||
permission.setExpires(Instant.now());
|
||||
}
|
||||
Instant baseExpiry = permission.getExpires() != null ? permission.getExpires() : Instant.now();
|
||||
Instant newExpiry = baseExpiry;
|
||||
|
||||
// Keep adding lifetime periods until we get a date in the future
|
||||
while (newExpiry.isBefore(Instant.now()) || newExpiry.equals(Instant.now())) {
|
||||
newExpiry = InstantHelper.plus(newExpiry, permissionMapping.getLifetime(),
|
||||
permissionMapping.getLifetimeUnit());
|
||||
}
|
||||
permission.setExpires(newExpiry);
|
||||
} else {
|
||||
// For valid permissions, extend from current expiry
|
||||
permission.setExpires(InstantHelper.plus(permission.getExpires(), permissionMapping.getLifetime(),
|
||||
permissionMapping.getLifetimeUnit()));
|
||||
}
|
||||
}
|
||||
|
||||
if (permission.getStarts() != null && permission.getStarts().isBefore(Instant.now())) {
|
||||
permission.setStarts(null);
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
package de.bstly.we.businesslogic;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
||||
import de.bstly.we.model.Permission;
|
||||
import de.bstly.we.model.PermissionMapping;
|
||||
import de.bstly.we.model.QPermission;
|
||||
import de.bstly.we.repository.PermissionRepository;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PermissionManagerTest {
|
||||
|
||||
@Mock
|
||||
private PermissionRepository permissionRepository;
|
||||
|
||||
@Mock
|
||||
private PermissionMappingManager permissionMappingManager;
|
||||
|
||||
@InjectMocks
|
||||
private PermissionManager permissionManager;
|
||||
|
||||
private static final Long TARGET_USER_ID = 1L;
|
||||
private static final Integer TEST_ITEM_ID = 1;
|
||||
private static final String ROLE_MEMBER = "ROLE_MEMBER";
|
||||
|
||||
@Test
|
||||
void testGetForItem_NewAddonPermission_CreatesNewWhenNoExisting() {
|
||||
// Given
|
||||
Instant currentTime = Instant.parse("2025-03-15T10:00:00Z");
|
||||
PermissionMapping addonMapping = createAddonPermissionMapping(ROLE_MEMBER, 1L, ChronoUnit.YEARS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(addonMapping));
|
||||
|
||||
// No existing permissions
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList());
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission permission = result.get(0);
|
||||
assertEquals(TARGET_USER_ID, permission.getTarget());
|
||||
assertEquals(ROLE_MEMBER, permission.getName());
|
||||
assertTrue(permission.isAddon()); // Should be addon since no existing permission found
|
||||
|
||||
// Should create new permission with 1 year from current time: March 15, 2025 + 1 year = March 15, 2026
|
||||
Instant expectedExpiry = Instant.parse("2026-03-15T10:00:00Z");
|
||||
assertEquals(expectedExpiry, permission.getExpires());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetForItem_AddonExtendsValidPermission_Simple() {
|
||||
// Given - existing valid permission that expires on June 15, 2025
|
||||
Instant currentTime = Instant.parse("2025-03-15T10:00:00Z");
|
||||
Instant existingExpiry = Instant.parse("2025-06-15T10:00:00Z"); // 3 months in the future
|
||||
Permission existingPermission = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, existingExpiry);
|
||||
|
||||
PermissionMapping addonMapping = createAddonPermissionMapping(ROLE_MEMBER, 1L, ChronoUnit.YEARS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(addonMapping));
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList(existingPermission));
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission extendedPermission = result.get(0);
|
||||
assertEquals(existingPermission, extendedPermission); // Should be the same object (extended)
|
||||
|
||||
// Should extend by exactly 1 year from current expiry: June 15, 2025 + 1 year = June 15, 2026
|
||||
Instant expectedExpiry = Instant.parse("2026-06-15T10:00:00Z");
|
||||
assertEquals(expectedExpiry, extendedPermission.getExpires());
|
||||
assertEquals(TARGET_USER_ID, extendedPermission.getTarget());
|
||||
assertEquals(ROLE_MEMBER, extendedPermission.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetForItem_AddonExtendsExpiredPermission_SimpleCase() {
|
||||
// Given - existing permission that expired on February 15, 2025 (1 month ago from March 15)
|
||||
Instant currentTime = Instant.parse("2025-03-15T10:00:00Z");
|
||||
Instant expiredDate = Instant.parse("2025-02-15T10:00:00Z"); // Expired exactly 1 month ago
|
||||
Permission expiredPermission = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, expiredDate);
|
||||
|
||||
PermissionMapping addonMapping = createAddonPermissionMapping(ROLE_MEMBER, 1L, ChronoUnit.YEARS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(addonMapping));
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList(expiredPermission));
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission extendedPermission = result.get(0);
|
||||
assertEquals(expiredPermission, extendedPermission); // Should be the same object (extended)
|
||||
|
||||
// Should extend by exactly 1 year from original expiry: Feb 15, 2025 + 1 year = Feb 15, 2026
|
||||
Instant expectedExpiry = Instant.parse("2026-02-15T10:00:00Z");
|
||||
assertEquals(expectedExpiry, extendedPermission.getExpires());
|
||||
assertTrue(extendedPermission.getExpires().isAfter(currentTime)); // Should be in the future
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetForItem_AddonExtendsLongExpiredPermission_CatchesUp() {
|
||||
// Given - permission that expired 2 years ago (Dec 31, 2023, applied in Nov 2025)
|
||||
Instant currentTime = Instant.parse("2025-02-09T10:00:00Z");
|
||||
Instant longExpiredDate = Instant.parse("2023-12-31T23:59:59Z");
|
||||
Permission longExpiredPermission = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, longExpiredDate);
|
||||
|
||||
PermissionMapping addonMapping = createAddonPermissionMapping(ROLE_MEMBER, 1L, ChronoUnit.YEARS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(addonMapping));
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList(longExpiredPermission));
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission extendedPermission = result.get(0);
|
||||
assertEquals(longExpiredPermission, extendedPermission); // Should be the same object (extended)
|
||||
|
||||
// Should "catch up" to future: 2023-12-31 -> 2024-12-31 -> 2025-12-31 (first future date)
|
||||
Instant expectedExpiry = Instant.parse("2025-12-31T23:59:59Z");
|
||||
assertEquals(expectedExpiry, extendedPermission.getExpires());
|
||||
assertTrue(extendedPermission.getExpires().isAfter(currentTime)); // Should be in the future
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testGetForItem_AddonExtendsNonExpiredPermission_CatchesUp() {
|
||||
// Given - permission that expired 2 years ago (Dec 31, 2023, applied in Nov 2025)
|
||||
Instant currentTime = Instant.parse("2025-02-09T10:00:00Z");
|
||||
Instant expiredDate = Instant.parse("2025-12-31T23:59:59Z");
|
||||
Permission existingPermission = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, expiredDate);
|
||||
|
||||
PermissionMapping addonMapping = createAddonPermissionMapping(ROLE_MEMBER, 1L, ChronoUnit.YEARS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(addonMapping));
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList(existingPermission));
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission extendedPermission = result.get(0);
|
||||
assertEquals(existingPermission, extendedPermission); // Should be the same object (extended)
|
||||
|
||||
// Should "catch up" to future: 2025-12-31 -> 2026-12-31 (first future date)
|
||||
Instant expectedExpiry = Instant.parse("2026-12-31T23:59:59Z");
|
||||
assertEquals(expectedExpiry, extendedPermission.getExpires());
|
||||
assertTrue(extendedPermission.getExpires().isAfter(currentTime)); // Should be in the future
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetForItem_AddonSelectsLatestExpiringPermission() {
|
||||
// Given - multiple existing permissions with different expiry dates
|
||||
Instant currentTime = Instant.parse("2025-03-15T10:00:00Z");
|
||||
Permission permission1 = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, Instant.parse("2025-06-23T10:00:00Z")); // 100 days
|
||||
Permission permission2 = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, Instant.parse("2025-10-01T10:00:00Z")); // 200 days (latest)
|
||||
Permission permission3 = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, Instant.parse("2025-05-04T10:00:00Z")); // 50 days
|
||||
|
||||
PermissionMapping addonMapping = createAddonPermissionMapping(ROLE_MEMBER, 6L, ChronoUnit.MONTHS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(addonMapping));
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList(permission1, permission2, permission3));
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission selectedPermission = result.get(0);
|
||||
assertEquals(permission2, selectedPermission); // Should select the one with latest expiry (Oct 1, 2025)
|
||||
|
||||
// Should extend by 6 months from latest expiry: Oct 1, 2025 + 6 months = April 1, 2026
|
||||
Instant expectedExpiry = Instant.parse("2026-04-01T10:00:00Z");
|
||||
assertEquals(expectedExpiry, selectedPermission.getExpires());
|
||||
assertEquals(TARGET_USER_ID, selectedPermission.getTarget());
|
||||
assertEquals(ROLE_MEMBER, selectedPermission.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetForItem_NonAddonCreatesNewPermission() {
|
||||
// Given
|
||||
Instant currentTime = Instant.parse("2025-03-15T10:00:00Z");
|
||||
PermissionMapping nonAddonMapping = createAddonPermissionMapping(ROLE_MEMBER, 1L, ChronoUnit.YEARS, false); // Not addon
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(nonAddonMapping));
|
||||
|
||||
// Existing permission exists but should be ignored since this is not an addon
|
||||
Permission existingPermission = createPermission(TARGET_USER_ID, ROLE_MEMBER, false, null, Instant.parse("2025-06-23T10:00:00Z"));
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList(existingPermission));
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(1, result.size());
|
||||
Permission newPermission = result.get(0);
|
||||
assertNotEquals(existingPermission, newPermission); // Should be a new permission object
|
||||
assertEquals(TARGET_USER_ID, newPermission.getTarget());
|
||||
assertEquals(ROLE_MEMBER, newPermission.getName());
|
||||
assertFalse(newPermission.isAddon()); // Should not be addon
|
||||
|
||||
// Should create new permission with 1 year from current time: March 15, 2025 + 1 year = March 15, 2026
|
||||
Instant expectedExpiry = Instant.parse("2026-03-15T10:00:00Z");
|
||||
assertEquals(expectedExpiry, newPermission.getExpires());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetForItem_MultiplePermissionNames() {
|
||||
// Given - mapping with multiple permission names
|
||||
Instant currentTime = Instant.parse("2025-03-15T10:00:00Z");
|
||||
Set<String> permissionNames = new HashSet<>(Arrays.asList("ROLE_MEMBER", "ROLE_SPECIAL"));
|
||||
PermissionMapping multiMapping = createPermissionMapping(permissionNames, 1L, ChronoUnit.YEARS, true);
|
||||
when(permissionMappingManager.getAllByItem(TEST_ITEM_ID)).thenReturn(Arrays.asList(multiMapping));
|
||||
|
||||
when(permissionRepository.findAll(any(com.querydsl.core.types.Predicate.class), any(Sort.class)))
|
||||
.thenReturn(Arrays.asList()); // No existing permissions
|
||||
|
||||
// When
|
||||
List<Permission> result = permissionManager.getForItem(TARGET_USER_ID, TEST_ITEM_ID, new JsonArray(),
|
||||
currentTime, null);
|
||||
|
||||
// Then
|
||||
assertEquals(2, result.size());
|
||||
|
||||
// Should have both permission names
|
||||
Set<String> resultNames = new HashSet<>();
|
||||
for (Permission p : result) {
|
||||
resultNames.add(p.getName());
|
||||
assertEquals(TARGET_USER_ID, p.getTarget());
|
||||
assertTrue(p.isAddon());
|
||||
}
|
||||
assertEquals(permissionNames, resultNames);
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private Permission createPermission(Long target, String name, boolean addon, Instant starts, Instant expires) {
|
||||
Permission permission = new Permission();
|
||||
permission.setTarget(target);
|
||||
permission.setName(name);
|
||||
permission.setAddon(addon);
|
||||
permission.setStarts(starts);
|
||||
permission.setExpires(expires);
|
||||
return permission;
|
||||
}
|
||||
|
||||
private PermissionMapping createAddonPermissionMapping(String permissionName, Long lifetime, ChronoUnit unit, boolean isAddon) {
|
||||
Set<String> names = new HashSet<>();
|
||||
names.add(permissionName);
|
||||
return createPermissionMapping(names, lifetime, unit, isAddon);
|
||||
}
|
||||
|
||||
private PermissionMapping createPermissionMapping(Set<String> names, Long lifetime, ChronoUnit unit, boolean isAddon) {
|
||||
PermissionMapping mapping = new PermissionMapping();
|
||||
mapping.setItem(TEST_ITEM_ID);
|
||||
mapping.setNames(names);
|
||||
mapping.setLifetime(lifetime);
|
||||
mapping.setLifetimeUnit(unit);
|
||||
mapping.setAddon(isAddon);
|
||||
mapping.setLifetimeRound(false);
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user