diff --git a/src/main/java/de/filefighter/rest/configuration/PrepareDataBase.java b/src/main/java/de/filefighter/rest/configuration/PrepareDataBase.java index d1b83ee3..645cfa8d 100644 --- a/src/main/java/de/filefighter/rest/configuration/PrepareDataBase.java +++ b/src/main/java/de/filefighter/rest/configuration/PrepareDataBase.java @@ -2,7 +2,6 @@ import de.filefighter.rest.domain.filesystem.data.persistence.FileSystemEntity; import de.filefighter.rest.domain.filesystem.data.persistence.FileSystemRepository; -import de.filefighter.rest.domain.filesystem.type.FileSystemType; import de.filefighter.rest.domain.token.business.AccessTokenBusinessService; import de.filefighter.rest.domain.token.data.persistence.AccessTokenEntity; import de.filefighter.rest.domain.token.data.persistence.AccessTokenRepository; @@ -17,6 +16,10 @@ import java.time.Instant; +import static de.filefighter.rest.domain.filesystem.type.FileSystemType.FOLDER; +import static de.filefighter.rest.domain.filesystem.type.FileSystemType.TEXT; +import static de.filefighter.rest.domain.user.group.Groups.*; + @Log4j2 @Configuration public class PrepareDataBase { @@ -70,18 +73,31 @@ CommandLineRunner cleanDataBase(UserRepository userRepository, FileSystemReposit }; } + @Bean + CommandLineRunner createRuntimeUser(UserRepository userRepository) { + return args -> log.info("Preloading system runtime user. {}", userRepository.save(UserEntity + .builder() + .userId(0L) + .username("FileFighter") + .lowercaseUsername("filefighter") + .password(null) + .refreshToken(null) + .groupIds(new long[]{SYSTEM.getGroupId()}) + .build())); + } + @Bean @Profile("prod") CommandLineRunner initDataBaseProd(UserRepository userRepository, FileSystemRepository fileSystemRepository) { return args -> { log.info("Preloading default admin user: {}.", userRepository.save(UserEntity .builder() - .userId(0L) + .userId(1L) .username("Admin") .lowercaseUsername("admin") .password("admin") .refreshToken("refreshToken1234") - .groupIds(new long[]{0, 1}) + .groupIds(new long[]{FAMILY.getGroupId(), ADMIN.getGroupId()}) .build())); log.info("Preloading default fsStructure: {} {}.", fileSystemRepository.save(FileSystemEntity @@ -92,22 +108,22 @@ CommandLineRunner initDataBaseProd(UserRepository userRepository, FileSystemRepo .path("/") .itemIds(new long[0]) .lastUpdated(Instant.now().getEpochSecond()) - .name("root") + .name("HOME_Admin") .size(0) - .typeId(FileSystemType.FOLDER.getId()) - .visibleForGroupIds(new long[]{-1, 0, 1}) + .typeId(FOLDER.getId()) + .visibleForGroupIds(new long[]{UNDEFINED.getGroupId(), FAMILY.getGroupId(), ADMIN.getGroupId()}) .itemIds(new long[]{1}) .build()), fileSystemRepository.save(FileSystemEntity.builder() - .createdByUserId(0) + .createdByUserId(1) .fileSystemId(1) .isFile(true) .lastUpdated(Instant.now().getEpochSecond()) .name("dummyFile.txt") .size(420) - .typeId(FileSystemType.TEXT.getId()) - .editableFoGroupIds(new long[]{0}) - .visibleForGroupIds(new long[]{0}) + .typeId(TEXT.getId()) + .editableFoGroupIds(new long[]{FAMILY.getGroupId()}) + .visibleForGroupIds(new long[]{FAMILY.getGroupId()}) .build())); log.info("Inserting Users {}", (userRepository.findAll().size() == 1 ? MESSAGE_ON_SUCCESS : MESSAGE_ON_FAILURE)); @@ -122,33 +138,33 @@ CommandLineRunner initDataBaseDev(UserRepository userRepository, AccessTokenRepo log.info("Preloading default users: {} {}.", userRepository.save(UserEntity .builder() - .userId(0) + .userId(1) .username("user") .lowercaseUsername("user") .password("1234") .refreshToken("rft1234") - .groupIds(new long[]{1}) + .groupIds(new long[]{ADMIN.getGroupId()}) .build()), userRepository.save(UserEntity .builder() - .userId(1) + .userId(2) .username("user1") .lowercaseUsername("user1") .password("12345") .refreshToken("rft") - .groupIds(new long[]{0}) + .groupIds(new long[]{FAMILY.getGroupId()}) .build())); log.info("Preloading default tokens: {} {}", accessTokenRepository.save(AccessTokenEntity .builder() - .userId(0) + .userId(1) .value("token") .validUntil(Instant.now().getEpochSecond() + AccessTokenBusinessService.ACCESS_TOKEN_DURATION_IN_SECONDS) .build()), accessTokenRepository.save(AccessTokenEntity .builder() - .userId(1) + .userId(2) .value("token1234") .validUntil(Instant.now().getEpochSecond() + AccessTokenBusinessService.ACCESS_TOKEN_DURATION_IN_SECONDS) .build())); @@ -163,30 +179,30 @@ CommandLineRunner initDataBaseDev(UserRepository userRepository, AccessTokenRepo .lastUpdated(Instant.now().getEpochSecond()) .name("HOME_User") .size(420) - .typeId(FileSystemType.FOLDER.getId()) - .visibleForGroupIds(new long[]{0, 1}) + .typeId(FOLDER.getId()) + .visibleForGroupIds(new long[]{FAMILY.getGroupId(), ADMIN.getGroupId()}) .build()), fileSystemRepository.save(FileSystemEntity.builder() - .createdByUserId(1) + .createdByUserId(0) .fileSystemId(1) .isFile(false) .path("/") .lastUpdated(Instant.now().getEpochSecond()) .name("HOME_User1") .size(420) - .typeId(FileSystemType.FOLDER.getId()) - .visibleForGroupIds(new long[]{-1, 0, 1}) + .typeId(FOLDER.getId()) + .visibleForGroupIds(new long[]{UNDEFINED.getGroupId(), FAMILY.getGroupId(), ADMIN.getGroupId()}) .build()), fileSystemRepository.save(FileSystemEntity.builder() - .createdByUserId(0) + .createdByUserId(1) .fileSystemId(2) .isFile(true) .lastUpdated(Instant.now().getEpochSecond()) .name("dummyFile.txt") .size(420) - .typeId(FileSystemType.TEXT.getId()) - .editableFoGroupIds(new long[]{0}) - .visibleForGroupIds(new long[]{0}) + .typeId(TEXT.getId()) + .editableFoGroupIds(new long[]{FAMILY.getGroupId()}) + .visibleForGroupIds(new long[]{FAMILY.getGroupId()}) .build())); log.info("Inserting FileSystemItems {}", (fileSystemRepository.findAll().size() == 3 ? MESSAGE_ON_SUCCESS : MESSAGE_ON_FAILURE)); diff --git a/src/main/java/de/filefighter/rest/domain/user/business/UserBusinessService.java b/src/main/java/de/filefighter/rest/domain/user/business/UserBusinessService.java index 73155222..6f3cd967 100644 --- a/src/main/java/de/filefighter/rest/domain/user/business/UserBusinessService.java +++ b/src/main/java/de/filefighter/rest/domain/user/business/UserBusinessService.java @@ -114,6 +114,9 @@ public UserEntity registerNewUser(UserRegisterForm newUser) { for (long id : userGroups) { try { + if (id == Groups.SYSTEM.getGroupId()) + throw new UserNotRegisteredException("New users cannot be in group '" + Groups.SYSTEM.getDisplayName() + "'."); + groupRepository.getGroupById(id); } catch (IllegalArgumentException exception) { throw new UserNotRegisteredException("One or more groups do not exist."); @@ -162,10 +165,12 @@ public void updateUser(long userId, UserRegisterForm userToUpdate, User authenti if (null == userEntityToUpdate) throw new UserNotUpdatedException("User does not exist, use register endpoint."); + if (Arrays.stream(userEntityToUpdate.getGroupIds()).asDoubleStream().anyMatch(id -> id == Groups.SYSTEM.getGroupId())) + throw new UserNotUpdatedException("Runtime users cannot be modified."); + Update newUpdate = new Update(); boolean changesWereMade = updateUserName(newUpdate, userToUpdate.getUsername()); - boolean usernameIsValid = stringIsValid(userToUpdate.getUsername()); String lowerCaseUsername = usernameIsValid ? userToUpdate.getUsername().toLowerCase() : userEntityToUpdate.getLowercaseUsername(); boolean passwordWasUpdated = updatePassword(newUpdate, userToUpdate.getPassword(), userToUpdate.getConfirmationPassword(), lowerCaseUsername); @@ -186,6 +191,8 @@ private boolean updateGroups(Update newUpdate, long[] groupIds, boolean authenti if (null != groupIds && groupIds.length != 0) { try { for (Groups group : groupRepository.getGroupsByIds(groupIds)) { + if (group == Groups.SYSTEM) + throw new UserNotUpdatedException("Users cannot be added to the '" + Groups.SYSTEM.getDisplayName() + "' Group"); if (group == Groups.ADMIN && !authenticatedUserIsAdmin) throw new UserNotUpdatedException("Only admins can add users to group " + Groups.ADMIN.getDisplayName() + "."); } diff --git a/src/main/java/de/filefighter/rest/domain/user/group/Groups.java b/src/main/java/de/filefighter/rest/domain/user/group/Groups.java index f9711921..a328b60f 100644 --- a/src/main/java/de/filefighter/rest/domain/user/group/Groups.java +++ b/src/main/java/de/filefighter/rest/domain/user/group/Groups.java @@ -3,7 +3,8 @@ public enum Groups { UNDEFINED(-1, "No group"), FAMILY(0, "Family"), - ADMIN(1, "Admin"); + ADMIN(1, "Admin"), + SYSTEM(999, "FileFighter System Users"); private final long groupId; private final String displayName; diff --git a/src/test/java/de/filefighter/rest/domain/user/business/UserBusinessServiceUnitTest.java b/src/test/java/de/filefighter/rest/domain/user/business/UserBusinessServiceUnitTest.java index 414a8f94..067d6662 100644 --- a/src/test/java/de/filefighter/rest/domain/user/business/UserBusinessServiceUnitTest.java +++ b/src/test/java/de/filefighter/rest/domain/user/business/UserBusinessServiceUnitTest.java @@ -250,6 +250,11 @@ void registerNewUserThrows() { ex = assertThrows(UserNotRegisteredException.class, () -> userBusinessService.registerNewUser(userRegisterForm)); assertEquals("User could not be registered. One or more groups do not exist.", ex.getMessage()); + + userRegisterForm.setGroupIds(new long[]{Groups.SYSTEM.getGroupId()}); + ex = assertThrows(UserNotRegisteredException.class, () -> + userBusinessService.registerNewUser(userRegisterForm)); + assertEquals("User could not be registered. New users cannot be in group '" + Groups.SYSTEM.getDisplayName() + "'.", ex.getMessage()); } @Test @@ -299,6 +304,11 @@ void updateUserThrows() { userBusinessService.updateUser(userId, userRegisterForm1, authenticatedUser)); assertEquals("User could not get updated. User does not exist, use register endpoint.", ex.getMessage()); + when(userRepositoryMock.findByUserId(userId)).thenReturn(UserEntity.builder().groupIds(new long[]{Groups.SYSTEM.getGroupId()}).build()); + ex = assertThrows(UserNotUpdatedException.class, () -> + userBusinessService.updateUser(userId, userRegisterForm1, authenticatedUser)); + assertEquals("User could not get updated. Runtime users cannot be modified.", ex.getMessage()); + when(userRepositoryMock.findByUserId(userId)).thenReturn(userEntityMock); ex = assertThrows(UserNotUpdatedException.class, () -> userBusinessService.updateUser(userId, userRegisterForm1, authenticatedUser)); @@ -414,6 +424,13 @@ void updateGroupsThrows() { ex = assertThrows(UserNotUpdatedException.class, () -> userBusinessService.updateUser(userId, userRegisterForm, authenticatedUser)); assertEquals("User could not get updated. One or more groups do not exist.", ex.getMessage()); + + long[] systemUser = new long[]{Groups.SYSTEM.getGroupId()}; + userRegisterForm.setGroupIds(systemUser); + when(groupRepositoryMock.getGroupsByIds(systemUser)).thenReturn(new Groups[]{Groups.SYSTEM}); + ex = assertThrows(UserNotUpdatedException.class, () -> + userBusinessService.updateUser(userId, userRegisterForm, authenticatedUser)); + assertEquals("User could not get updated. Users cannot be added to the '" + Groups.SYSTEM.getDisplayName() + "' Group", ex.getMessage()); } @Test