diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5af9ff6..1649db4 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -4,13 +4,18 @@ on: push: branches: - master + - dev pull_request: branches: - master + - dev paths-ignore: - 'documentation/**' + - 'mysql/**' - 'README.adoc' - 'Dockerfile' + - 'docker-compose.yaml' + - '.gitignore' jobs: build: runs-on: ubuntu-latest diff --git a/README.adoc b/README.adoc index 6943690..4ccc5fb 100644 --- a/README.adoc +++ b/README.adoc @@ -1,10 +1,17 @@ = Gruppenbildung -Das System bietet eine zentrale Oberfläche zum erstellen und verwalten von Gruppen. Diese kann von anderen Systemen eingebunden werden, oder von Studierenden direkt aufgerufen werden. Außerdem wird eine API bereitgestellt für die Nutzung in anderen Systemen. Man kann Private und Öffentliche Gruppen erstellen. Private Gruppen kann man nur über einen Beitrittslink beitreten. Öffentliche Gruppen kann man ohne diesen beitreten. Man kann nach Öffentlichen Gruppen über eine Suchfunktion suchen. +Das System bietet eine zentrale Oberfläche zum erstellen und verwalten von Gruppen. +Diese kann von anderen Systemen eingebunden werden, oder von Studierenden direkt aufgerufen werden. +Außerdem wird eine API bereitgestellt für die Nutzung in anderen Systemen. +Man kann Private und Öffentliche Gruppen erstellen. +Private Gruppen kann man nur über einen Beitrittslink beitreten. +Öffentliche Gruppen kann man ohne diesen beitreten. +Man kann nach Öffentlichen Gruppen über eine Suchfunktion suchen. === Problem -Die meisten Teilsysteme von MOPS arbeiten mit Gruppierungen von Studenten: Materialien für Lerngruppen/Veranstaltungen, Gruppenportfolios, Gruppenabstimmungen etc. Jedes System müsste dementsprechend eine Gruppenverwaltung implementieren, was zeitaufwändig ist. +Die meisten Teilsysteme von MOPS arbeiten mit Gruppierungen von Studenten: Materialien für Lerngruppen/Veranstaltungen, Gruppenportfolios, Gruppenabstimmungen etc. +Jedes System müsste dementsprechend eine Gruppenverwaltung implementieren, was zeitaufwändig ist. === Ziele @@ -36,7 +43,8 @@ Die Gruppenverwaltung wird bieten: Über *Mitglied* (interne Rolle): -* Mitglieder haben keine Rechte in der Gruppe. Sie können nur eigenständig aus der Gruppe austreten. +* Mitglieder haben keine Rechte in der Gruppe. +Sie können nur eigenständig aus der Gruppe austreten. Für *Organisatoren* (keycloak Rolle): @@ -62,3 +70,6 @@ Für *Studenten* (keycloak Rolle) : === Verwendung Die Anwendung kann mit `docker-compse up` im Wurzelverzeichnis gestartet werden, eine API-Doku befindet sich im Dokumentation-Ordner (das swagger-zip). + +Der Import über CSV erfolgt nach dem Format `id,givenname,familyname,email` + diff --git a/build.gradle b/build.gradle index f65225b..cd5b93f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,90 +1,103 @@ import com.github.spotbugs.SpotBugsTask plugins { - id 'org.springframework.boot' version '2.2.5.RELEASE' - id 'io.spring.dependency-management' version '1.0.9.RELEASE' - id 'java' + id 'org.springframework.boot' version '2.2.5.RELEASE' + id 'io.spring.dependency-management' version '1.0.9.RELEASE' + id 'java' - id 'com.github.spotbugs' version '3.0.0' - id 'checkstyle' + id 'com.github.spotbugs' version '3.0.0' + id 'checkstyle' + id 'pmd' } group = 'mops' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' -spotbugs{ - ignoreFailures = true - reportLevel = "high" - effort = "max" - toolVersion = '4.0.0-RC1' +spotbugs { + ignoreFailures = false + reportLevel = "high" + effort = "max" + toolVersion = '4.0.0-RC1' } tasks.withType(SpotBugsTask) { - reports { - xml.enabled = false - html.enabled = true - } + reports { + xml.enabled = false + html.enabled = true + } +} + +pmd { + consoleOutput = true + ignoreFailures = true + toolVersion = "6.21.0" + rulePriority = 5 + ruleSets = ["category/java/errorprone.xml", + "category/java/bestpractices.xml", + "category/java/security.xml", + "category/java/performance.xml", + "category/java/design.xml"] } checkstyle { - toolVersion = "8.28" - configFile = file("${rootDir}/config/checkstyle/checkstyle.xml") - ignoreFailures = true + toolVersion = "8.28" + configFile = file("${rootDir}/config/checkstyle/checkstyle.xml") + ignoreFailures = true } configurations { - developmentOnly - runtimeClasspath { - extendsFrom developmentOnly - } - compileOnly { - extendsFrom annotationProcessor - } + developmentOnly + runtimeClasspath { + extendsFrom developmentOnly + } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - maven { - url = 'https://s3.cs.hhu.de/public/mops/' - metadataSources { - artifact() - } - } - mavenCentral() + maven { + url = 'https://s3.cs.hhu.de/public/mops/' + metadataSources { + artifact() + } + } + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' - implementation 'org.springframework.security.oauth:spring-security-oauth2:2.4.0.RELEASE' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + implementation 'org.springframework.security.oauth:spring-security-oauth2:2.4.0.RELEASE' - implementation 'org.keycloak:keycloak-spring-boot-starter:9.0.0' - implementation 'org.keycloak.bom:keycloak-adapter-bom:9.0.0' - implementation 'mops:styleguide:2.1.0' - implementation 'io.springfox:springfox-swagger2:2.9.2' - implementation 'io.springfox:springfox-swagger-ui:2.9.2' - implementation 'com.github.javafaker:javafaker:1.0.2' - implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.10.3' + implementation 'org.keycloak:keycloak-spring-boot-starter:9.0.0' + implementation 'org.keycloak.bom:keycloak-adapter-bom:9.0.0' + implementation 'mops:styleguide:2.1.0' + implementation 'io.springfox:springfox-swagger2:2.9.2' + implementation 'io.springfox:springfox-swagger-ui:2.9.2' + implementation 'com.github.javafaker:javafaker:1.0.2' + implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.10.3' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - runtimeOnly 'com.h2database:h2' - runtimeOnly 'mysql:mysql-connector-java' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'mysql:mysql-connector-java' - testImplementation 'org.assertj:assertj-core:3.15.0' - testImplementation('org.springframework.boot:spring-boot-starter-test') { - exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' - } - testImplementation 'org.springframework.security:spring-security-test' - testImplementation 'com.tngtech.archunit:archunit-junit5:0.13.1' + testImplementation 'org.assertj:assertj-core:3.15.0' + testImplementation('org.springframework.boot:spring-boot-starter-test') { + exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' + } + testImplementation 'org.springframework.security:spring-security-test' + testImplementation 'com.tngtech.archunit:archunit-junit5:0.13.1' } test { - useJUnitPlatform() + useJUnitPlatform() } diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 60ed2b6..8cbd8b6 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -226,7 +226,7 @@ - + events = eventService.getNewEvents(status); + @ApiOperation("Gibt alle Gruppen zurück, in denen sich etwas geändert hat") + public GroupRequestWrapper updateGroups(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long lastEventId) throws EventException { + List events = eventService.getNewEvents(lastEventId); - return APIFormatterService.wrap(eventService.getMaxEvent_id(), groupService.projectEventList(events)); + return APIFormatterService.wrap(eventService.getMaxEventId(), groupService.projectEventList(events)); } - @GetMapping("/getGroupIdsOfUser/{teilnehmer}") + @GetMapping("/getGroupIdsOfUser/{userId}") @Secured("ROLE_api_user") - @ApiOperation("Gibt alle Gruppen zurück in denen sich ein Teilnehmer befindet") - public List getGroupsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String teilnehmer) { - return userService.getUserGroups(teilnehmer).stream() + @ApiOperation("Gibt alle Gruppen zurück, in denen sich ein Teilnehmer befindet") + public List getGroupIdsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String userId) { + return userService.getUserGroups(userId).stream() .map(group -> group.getId().toString()) .collect(Collectors.toList()); } @@ -59,10 +60,14 @@ public class APIController { @GetMapping("/getGroup/{groupId}") @Secured("ROLE_api_user") @ApiOperation("Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück") - public Group getGroupFromId(@ApiParam("GruppenId der gefordeten Gruppe") @PathVariable String groupId) throws EventException { + public Group getGroupById(@ApiParam("GruppenId der gefordeten Gruppe") @PathVariable String groupId) throws EventException { List eventList = eventService.getEventsOfGroup(UUID.fromString(groupId)); List groups = groupService.projectEventList(eventList); + if (groups.isEmpty()) { + return null; + } + return groups.get(0); } diff --git a/src/main/java/mops/gruppen2/controller/GroupCreationController.java b/src/main/java/mops/gruppen2/controller/GroupCreationController.java new file mode 100644 index 0000000..ed7fcbf --- /dev/null +++ b/src/main/java/mops/gruppen2/controller/GroupCreationController.java @@ -0,0 +1,120 @@ +package mops.gruppen2.controller; + +import mops.gruppen2.domain.Account; +import mops.gruppen2.service.ControllerService; +import mops.gruppen2.service.GroupService; +import mops.gruppen2.service.KeyCloakService; +import mops.gruppen2.service.ValidationService; +import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.context.annotation.SessionScope; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.security.RolesAllowed; +import java.util.UUID; + +@Controller +@SessionScope +@RequestMapping("/gruppen2") +public class GroupCreationController { + + private final GroupService groupService; + private final ControllerService controllerService; + private final ValidationService validationService; + + public GroupCreationController(GroupService groupService, ControllerService controllerService, ValidationService validationService) { + this.groupService = groupService; + this.controllerService = controllerService; + this.validationService = validationService; + } + + @RolesAllowed({"ROLE_orga", "ROLE_actuator"}) + @GetMapping("/createOrga") + public String createGroupAsOrga(KeycloakAuthenticationToken token, + Model model) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + + model.addAttribute("account", account); + model.addAttribute("lectures", groupService.getAllLecturesWithVisibilityPublic()); + + return "createOrga"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_actuator"}) + @PostMapping("/createOrga") + @CacheEvict(value = "groups", allEntries = true) + public String postCrateGroupAsOrga(KeycloakAuthenticationToken token, + @RequestParam("title") String title, + @RequestParam("description") String description, + @RequestParam(value = "visibility", required = false) Boolean visibility, + @RequestParam(value = "lecture", required = false) Boolean lecture, + @RequestParam("userMaximum") Long userMaximum, + @RequestParam(value = "maxInfiniteUsers", required = false) Boolean maxInfiniteUsers, + @RequestParam(value = "parent", required = false) String parent, + @RequestParam(value = "file", required = false) MultipartFile file) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + UUID parentUUID = controllerService.getUUID(parent); + + validationService.checkFields(description, title, userMaximum, maxInfiniteUsers); + + controllerService.createGroupAsOrga(account, + title, + description, + visibility, + lecture, + maxInfiniteUsers, + userMaximum, + parentUUID, + file); + return "redirect:/gruppen2"; + } + + @RolesAllowed("ROLE_studentin") + @GetMapping("/createStudent") + public String createGroupAsStudent(KeycloakAuthenticationToken token, + Model model) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + + model.addAttribute("account", account); + model.addAttribute("lectures", groupService.getAllLecturesWithVisibilityPublic()); + + return "createStudent"; + } + + @RolesAllowed("ROLE_studentin") + @PostMapping("/createStudent") + @CacheEvict(value = "groups", allEntries = true) + public String postCreateGroupAsStudent(KeycloakAuthenticationToken token, + @RequestParam("title") String title, + @RequestParam("description") String description, + @RequestParam("userMaximum") Long userMaximum, + @RequestParam(value = "visibility", required = false) Boolean visibility, + @RequestParam(value = "maxInfiniteUsers", required = false) Boolean maxInfiniteUsers, + @RequestParam(value = "parent", required = false) String parent) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + UUID parentUUID = controllerService.getUUID(parent); + + validationService.checkFields(description, title, userMaximum, maxInfiniteUsers); + + controllerService.createGroup(account, + title, + description, + visibility, + null, + maxInfiniteUsers, + userMaximum, + parentUUID); + + return "redirect:/gruppen2"; + } +} diff --git a/src/main/java/mops/gruppen2/controller/GroupDetailsController.java b/src/main/java/mops/gruppen2/controller/GroupDetailsController.java new file mode 100644 index 0000000..008851e --- /dev/null +++ b/src/main/java/mops/gruppen2/controller/GroupDetailsController.java @@ -0,0 +1,281 @@ +package mops.gruppen2.controller; + +import mops.gruppen2.domain.Account; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.Role; +import mops.gruppen2.domain.User; +import mops.gruppen2.domain.Visibility; +import mops.gruppen2.service.ControllerService; +import mops.gruppen2.service.InviteService; +import mops.gruppen2.service.KeyCloakService; +import mops.gruppen2.service.UserService; +import mops.gruppen2.service.ValidationService; +import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.context.annotation.SessionScope; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.security.RolesAllowed; +import javax.servlet.http.HttpServletRequest; +import java.util.UUID; + +@Controller +@SessionScope +@RequestMapping("/gruppen2") +public class GroupDetailsController { + + private final ControllerService controllerService; + private final UserService userService; + private final ValidationService validationService; + private final InviteService inviteService; + + public GroupDetailsController(ControllerService controllerService, UserService userService, ValidationService validationService, InviteService inviteService) { + this.controllerService = controllerService; + this.userService = userService; + this.validationService = validationService; + this.inviteService = inviteService; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/details/{id}") + public String showGroupDetails(KeycloakAuthenticationToken token, + Model model, + HttpServletRequest request, + @PathVariable("id") String groupId) { + + Group group = userService.getGroupById(UUID.fromString(groupId)); + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + UUID parentId = group.getParent(); + String actualURL = request.getRequestURL().toString(); + String serverURL = actualURL.substring(0, actualURL.indexOf("gruppen2/")); + Group parent = controllerService.getParent(parentId); + + validationService.throwIfGroupNotExisting(group.getTitle()); + + model.addAttribute("account", account); + if (!validationService.checkIfUserInGroup(group, user)) { + validationService.throwIfNoAccessToPrivate(group, user); + model.addAttribute("group", group); + model.addAttribute("parentId", parentId); + model.addAttribute("parent", parent); + return "detailsNoMember"; + } + + model.addAttribute("parentId", parentId); + model.addAttribute("parent", parent); + model.addAttribute("group", group); + model.addAttribute("roles", group.getRoles()); + model.addAttribute("user", user); + model.addAttribute("admin", Role.ADMIN); + model.addAttribute("public", Visibility.PUBLIC); + model.addAttribute("private", Visibility.PRIVATE); + + if (validationService.checkIfAdmin(group, user)) { + model.addAttribute("link", serverURL + "gruppen2/acceptinvite/" + inviteService.getLinkByGroupId(group.getId())); + } + + return "detailsMember"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/details/changeMetadata/{id}") + public String changeMetadata(KeycloakAuthenticationToken token, + Model model, + @PathVariable("id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfNoAdmin(group, user); + + model.addAttribute("account", account); + model.addAttribute("title", group.getTitle()); + model.addAttribute("description", group.getDescription()); + model.addAttribute("admin", Role.ADMIN); + model.addAttribute("roles", group.getRoles()); + model.addAttribute("groupId", group.getId()); + model.addAttribute("user", user); + + return "changeMetadata"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/details/changeMetadata") + @CacheEvict(value = "groups", allEntries = true) + public String postChangeMetadata(KeycloakAuthenticationToken token, + @RequestParam("title") String title, + @RequestParam("description") String description, + @RequestParam("groupId") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfNoAdmin(group, user); + validationService.checkFields(title, description); + + controllerService.changeMetaData(account, group, title, description); + + return "redirect:/gruppen2/details/" + groupId; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/details/members/{id}") + public String editMembers(KeycloakAuthenticationToken token, + Model model, + @PathVariable("id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + Group group = userService.getGroupById(UUID.fromString(groupId)); + User user = new User(account); + + validationService.throwIfNoAdmin(group, user); + + model.addAttribute("account", account); + model.addAttribute("members", group.getMembers()); + model.addAttribute("group", group); + model.addAttribute("admin", Role.ADMIN); + + return "editMembers"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/details/members/changeRole") + @CacheEvict(value = "groups", allEntries = true) + public String changeRole(KeycloakAuthenticationToken token, + @RequestParam("group_id") String groupId, + @RequestParam("user_id") String userId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + Group group = userService.getGroupById(UUID.fromString(groupId)); + User principle = new User(account); + User user = new User(userId, "", "", ""); + + validationService.throwIfNoAdmin(group, principle); + + //TODO: checkIfAdmin checkt nicht, dass die rolle geändert wurde. oder die rolle wird nicht geändert + + controllerService.changeRole(account, user, group); + + if (!validationService.checkIfAdmin(group, principle)) { + return "redirect:/gruppen2/details/" + groupId; + } + + return "redirect:/gruppen2/details/members/" + groupId; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/details/members/changeMaximum") + @CacheEvict(value = "groups", allEntries = true) + public String changeMaxSize(KeycloakAuthenticationToken token, + @RequestParam("maximum") Long maximum, + @RequestParam("group_id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfNewMaximumIsValid(maximum, group); + + controllerService.updateMaxUser(account, UUID.fromString(groupId), maximum); + + return "redirect:/gruppen2/details/members/" + groupId; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/details/members/deleteUser") + @CacheEvict(value = "groups", allEntries = true) + public String deleteUser(KeycloakAuthenticationToken token, + @RequestParam("group_id") String groupId, + @RequestParam("user_id") String userId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User principle = new User(account); + User user = new User(userId, "", "", ""); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfNoAdmin(group, principle); + + controllerService.deleteUser(account, user, group); + + if (!validationService.checkIfUserInGroup(group, principle)) { + return "redirect:/gruppen2"; + } + + return "redirect:/gruppen2/details/members/" + groupId; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/detailsBeitreten") + @CacheEvict(value = "groups", allEntries = true) + public String joinGroup(KeycloakAuthenticationToken token, + Model model, + @RequestParam("id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfUserAlreadyInGroup(group, user); + validationService.throwIfGroupFull(group); + + controllerService.addUser(account, UUID.fromString(groupId)); + + model.addAttribute("account", account); + + return "redirect:/gruppen2"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/leaveGroup") + @CacheEvict(value = "groups", allEntries = true) + public String leaveGroup(KeycloakAuthenticationToken token, + @RequestParam("group_id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + controllerService.deleteUser(account, user, group); + + return "redirect:/gruppen2"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/deleteGroup") + @CacheEvict(value = "groups", allEntries = true) + public String deleteGroup(KeycloakAuthenticationToken token, + @RequestParam("group_id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfNoAdmin(group, user); + + controllerService.deleteGroupEvent(user.getId(), UUID.fromString(groupId)); + + return "redirect:/gruppen2"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_actuator"}) + @PostMapping("/details/members/addUsersFromCsv") + @CacheEvict(value = "groups", allEntries = true) + public String addUsersFromCsv(KeycloakAuthenticationToken token, + @RequestParam("group_id") String groupId, + @RequestParam(value = "file", required = false) MultipartFile file) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + controllerService.addUsersFromCsv(account, file, groupId); + + return "redirect:/gruppen2/details/members/" + groupId; + } +} diff --git a/src/main/java/mops/gruppen2/controller/GruppenfindungController.java b/src/main/java/mops/gruppen2/controller/GruppenfindungController.java new file mode 100644 index 0000000..c1e156a --- /dev/null +++ b/src/main/java/mops/gruppen2/controller/GruppenfindungController.java @@ -0,0 +1,56 @@ +package mops.gruppen2.controller; + +import mops.gruppen2.domain.Account; +import mops.gruppen2.domain.User; +import mops.gruppen2.domain.exception.PageNotFoundException; +import mops.gruppen2.service.KeyCloakService; +import mops.gruppen2.service.UserService; +import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +import javax.annotation.security.RolesAllowed; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +@Controller +public class GruppenfindungController { + + private final UserService userService; + + public GruppenfindungController(UserService userService) { + this.userService = userService; + } + + @GetMapping("") + public String redirect() { + return "redirect:/gruppen2"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/gruppen2") + public String index(KeycloakAuthenticationToken token, + Model model) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + + model.addAttribute("account", account); + model.addAttribute("gruppen", userService.getUserGroups(user)); + model.addAttribute("user", user); + + return "index"; + } + + @GetMapping("/logout") + public String logout(HttpServletRequest request) throws ServletException { + request.logout(); + return "redirect:/gruppen2/"; + } + + @GetMapping("/gruppen2/*") + public String defaultLink() throws PageNotFoundException { + throw new PageNotFoundException("\uD83D\uDE41"); + } +} diff --git a/src/main/java/mops/gruppen2/controller/MopsController.java b/src/main/java/mops/gruppen2/controller/MopsController.java deleted file mode 100644 index 534c7e8..0000000 --- a/src/main/java/mops/gruppen2/controller/MopsController.java +++ /dev/null @@ -1,28 +0,0 @@ -package mops.gruppen2.controller; - -import mops.gruppen2.domain.exception.EventException; -import mops.gruppen2.domain.exception.PageNotFoundException; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -import javax.servlet.http.HttpServletRequest; - -@Controller -public class MopsController { - - @GetMapping("") - public String redirect() { - return "redirect:/gruppen2/"; - } - - @GetMapping("/logout") - public String logout(HttpServletRequest request) throws Exception { - request.logout(); - return "redirect:/gruppen2/"; - } - - @GetMapping("*") - public String defaultLink() throws EventException { - throw new PageNotFoundException("\uD83D\uDE41"); - } -} diff --git a/src/main/java/mops/gruppen2/controller/SearchAndInviteController.java b/src/main/java/mops/gruppen2/controller/SearchAndInviteController.java new file mode 100644 index 0000000..ef351cc --- /dev/null +++ b/src/main/java/mops/gruppen2/controller/SearchAndInviteController.java @@ -0,0 +1,123 @@ +package mops.gruppen2.controller; + +import mops.gruppen2.domain.Account; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.User; +import mops.gruppen2.domain.Visibility; +import mops.gruppen2.service.ControllerService; +import mops.gruppen2.service.InviteService; +import mops.gruppen2.service.KeyCloakService; +import mops.gruppen2.service.UserService; +import mops.gruppen2.service.ValidationService; +import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.context.annotation.SessionScope; + +import javax.annotation.security.RolesAllowed; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Controller +@SessionScope +@RequestMapping("/gruppen2") +public class SearchAndInviteController { + + private final ValidationService validationService; + private final InviteService inviteService; + private final UserService userService; + private final ControllerService controllerService; + + public SearchAndInviteController(ValidationService validationService, InviteService inviteService, UserService userService, ControllerService controllerService) { + this.validationService = validationService; + this.inviteService = inviteService; + this.userService = userService; + this.controllerService = controllerService; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/findGroup") + public String findGroup(KeycloakAuthenticationToken token, + Model model, + @RequestParam(value = "suchbegriff", required = false) String search) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + List groups = new ArrayList<>(); + groups = validationService.checkSearch(search, groups, account); + + model.addAttribute("account", account); + model.addAttribute("gruppen", groups); + model.addAttribute("inviteService", inviteService); + + return "search"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/detailsSearch") + public String showGroupDetailsNoMember(KeycloakAuthenticationToken token, + Model model, + @RequestParam("id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + Group group = userService.getGroupById(UUID.fromString(groupId)); + UUID parentId = group.getParent(); + Group parent = controllerService.getParent(parentId); + User user = new User(account); + + model.addAttribute("account", account); + if (validationService.checkIfUserInGroup(group, user)) { + return "redirect:/gruppen2/details/" + groupId; + } + + model.addAttribute("group", group); + model.addAttribute("parentId", parentId); + model.addAttribute("parent", parent); + + return "detailsNoMember"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @GetMapping("/acceptinvite/{link}") + public String acceptInvite(KeycloakAuthenticationToken token, + Model model, + @PathVariable("link") String link) { + + Group group = userService.getGroupById(inviteService.getGroupIdFromLink(link)); + + validationService.throwIfGroupNotExisting(group.getTitle()); + + model.addAttribute("account", KeyCloakService.createAccountFromPrincipal(token)); + model.addAttribute("group", group); + + if (group.getVisibility() == Visibility.PUBLIC) { + return "redirect:/gruppen2/details/" + group.getId(); + } + + return "joinprivate"; + } + + @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) + @PostMapping("/acceptinvite") + @CacheEvict(value = "groups", allEntries = true) + public String postAcceptInvite(KeycloakAuthenticationToken token, + @RequestParam("id") String groupId) { + + Account account = KeyCloakService.createAccountFromPrincipal(token); + User user = new User(account); + Group group = userService.getGroupById(UUID.fromString(groupId)); + + validationService.throwIfUserAlreadyInGroup(group, user); + validationService.throwIfGroupFull(group); + + controllerService.addUser(account, UUID.fromString(groupId)); + + return "redirect:/gruppen2/details/" + groupId; + } +} diff --git a/src/main/java/mops/gruppen2/controller/WebController.java b/src/main/java/mops/gruppen2/controller/WebController.java deleted file mode 100644 index b72db33..0000000 --- a/src/main/java/mops/gruppen2/controller/WebController.java +++ /dev/null @@ -1,429 +0,0 @@ -package mops.gruppen2.controller; - -import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.Role; -import mops.gruppen2.domain.User; -import mops.gruppen2.domain.Visibility; -import mops.gruppen2.domain.exception.EventException; -import mops.gruppen2.domain.exception.PageNotFoundException; -import mops.gruppen2.security.Account; -import mops.gruppen2.service.ControllerService; -import mops.gruppen2.service.GroupService; -import mops.gruppen2.service.InviteService; -import mops.gruppen2.service.KeyCloakService; -import mops.gruppen2.service.UserService; -import mops.gruppen2.service.ValidationService; -import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.context.annotation.SessionScope; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.security.RolesAllowed; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -@Controller -@SessionScope -@RequestMapping("/gruppen2") -public class WebController { - - private final KeyCloakService keyCloakService; - private final GroupService groupService; - private final UserService userService; - private final ControllerService controllerService; - private final ValidationService validationService; - private final InviteService inviteService; - - public WebController(KeyCloakService keyCloakService, GroupService groupService, UserService userService, ControllerService controllerService, ValidationService validationService, InviteService inviteService) { - this.keyCloakService = keyCloakService; - this.groupService = groupService; - this.userService = userService; - this.controllerService = controllerService; - this.validationService = validationService; - this.inviteService = inviteService; - } - - /** - * Zeigt die index.html an. - * - * @param token toller token - * @param model tolles model - * @return index.html - */ - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("") - public String index(KeycloakAuthenticationToken token, Model model) { - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); - - model.addAttribute("account", keyCloakService.createAccountFromPrincipal(token)); - model.addAttribute("gruppen", userService.getUserGroups(user)); - model.addAttribute("user", user); - return "index"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_actuator"}) - @GetMapping("/createOrga") - public String createGroupAsOrga(KeycloakAuthenticationToken token, Model model) { - Account account = keyCloakService.createAccountFromPrincipal(token); - - model.addAttribute("account", account); - model.addAttribute("lectures", groupService.getAllLecturesWithVisibilityPublic()); - return "createOrga"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_actuator"}) - @PostMapping("/createOrga") - @CacheEvict(value = "groups", allEntries = true) - public String postCrateGroupAsOrga(KeycloakAuthenticationToken token, - @RequestParam("title") String title, - @RequestParam("description") String description, - @RequestParam(value = "visibility", required = false) Boolean visibility, - @RequestParam(value = "lecture", required = false) Boolean lecture, - @RequestParam("userMaximum") Long userMaximum, - @RequestParam(value = "maxInfiniteUsers", required = false) Boolean maxInfiniteUsers, - @RequestParam(value = "parent", required = false) String parent, - @RequestParam(value = "file", required = false) MultipartFile file) { - - Account account = keyCloakService.createAccountFromPrincipal(token); - UUID parentUUID = controllerService.getUUID(parent); - - validationService.checkFields(description, title, userMaximum, maxInfiniteUsers); - - controllerService.createGroupAsOrga(account, title, description, visibility, lecture, maxInfiniteUsers, userMaximum, parentUUID, file); - return "redirect:/gruppen2/"; - } - - @RolesAllowed({"ROLE_studentin"}) - @GetMapping("/createStudent") - public String createGroupAsStudent(KeycloakAuthenticationToken token, Model model) { - Account account = keyCloakService.createAccountFromPrincipal(token); - - model.addAttribute("account", account); - model.addAttribute("lectures", groupService.getAllLecturesWithVisibilityPublic()); - return "createStudent"; - } - - @RolesAllowed({"ROLE_studentin"}) - @PostMapping("/createStudent") - @CacheEvict(value = "groups", allEntries = true) - public String postCreateGroupAsStudent(KeycloakAuthenticationToken token, - @RequestParam("title") String title, - @RequestParam("description") String description, - @RequestParam(value = "visibility", required = false) Boolean visibility, - @RequestParam("userMaximum") Long userMaximum, - @RequestParam(value = "maxInfiniteUsers", required = false) Boolean maxInfiniteUsers, - @RequestParam(value = "parent", required = false) String parent) { - - Account account = keyCloakService.createAccountFromPrincipal(token); - UUID parentUUID = controllerService.getUUID(parent); - - validationService.checkFields(description, title, userMaximum, maxInfiniteUsers); - - controllerService.createGroup(account, title, description, visibility, null, maxInfiniteUsers, userMaximum, parentUUID); - return "redirect:/gruppen2/"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_actuator"}) - @PostMapping("/details/members/addUsersFromCsv") - @CacheEvict(value = "groups", allEntries = true) - public String addUsersFromCsv(KeycloakAuthenticationToken token, - @RequestParam("group_id") String groupId, - @RequestParam(value = "file", required = false) MultipartFile file) throws IOException { - Account account = keyCloakService.createAccountFromPrincipal(token); - - controllerService.addUsersFromCsv(account, file, groupId); - return "redirect:/gruppen2/details/members/" + groupId; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("/details/changeMetadata/{id}") - public String changeMetadata(KeycloakAuthenticationToken token, Model model, @PathVariable("id") String groupId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); - Group group = userService.getGroupById(UUID.fromString(groupId)); - UUID parentId = group.getParent(); - Group parent = new Group(); - - validationService.throwIfNoAdmin(group, user); - - model.addAttribute("account", account); - model.addAttribute("title", group.getTitle()); - model.addAttribute("description", group.getDescription()); - model.addAttribute("admin", Role.ADMIN); - model.addAttribute("roles", group.getRoles()); - model.addAttribute("groupId", group.getId()); - model.addAttribute("user", user); - return "changeMetadata"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/details/changeMetadata") - @CacheEvict(value = "groups", allEntries = true) - public String postChangeMetadata(KeycloakAuthenticationToken token, - @RequestParam("title") String title, - @RequestParam("description") String description, - @RequestParam("groupId") String groupId) { - - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), "", "", ""); - Group group = userService.getGroupById(UUID.fromString(groupId)); - - validationService.throwIfNoAdmin(group, user); - validationService.checkFields(title, description); - - controllerService.changeMetaData(account, group, title, description); - return "redirect:/gruppen2/details/" + groupId; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("/findGroup") - public String findGroup(KeycloakAuthenticationToken token, - Model model, - @RequestParam(value = "suchbegriff", required = false) String search) { - Account account = keyCloakService.createAccountFromPrincipal(token); - List groups = new ArrayList<>(); - groups = validationService.checkSearch(search, groups, account); - - model.addAttribute("account", account); - model.addAttribute("gruppen", groups); - model.addAttribute("inviteService", inviteService); - return "search"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("/details/{id}") - public String showGroupDetails(KeycloakAuthenticationToken token, - Model model, - HttpServletRequest request, - @PathVariable("id") String groupId) { - - Group group = userService.getGroupById(UUID.fromString(groupId)); - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); - UUID parentId = group.getParent(); - String actualURL = request.getRequestURL().toString(); - String serverURL = actualURL.substring(0, actualURL.indexOf("gruppen2/")); - Group parent = controllerService.getParent(parentId); - - validationService.throwIfGroupNotExisting(group.getTitle()); - - model.addAttribute("account", account); - if (!validationService.checkIfUserInGroup(group, user)) { - validationService.throwIfNoAccessToPrivate(group, user); - model.addAttribute("group", group); - model.addAttribute("parentId", parentId); - model.addAttribute("parent", parent); - return "detailsNoMember"; - } - - model.addAttribute("parentId", parentId); - model.addAttribute("parent", parent); - model.addAttribute("group", group); - model.addAttribute("roles", group.getRoles()); - model.addAttribute("user", user); - model.addAttribute("admin", Role.ADMIN); - - if (validationService.checkIfAdmin(group, user)) { - model.addAttribute("link", serverURL + "gruppen2/acceptinvite/" + inviteService.getLinkByGroupId(group.getId())); - } - return "detailsMember"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/detailsBeitreten") - @CacheEvict(value = "groups", allEntries = true) - public String joinGroup(KeycloakAuthenticationToken token, - Model model, @RequestParam("id") String groupId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); - Group group = userService.getGroupById(UUID.fromString(groupId)); - - validationService.throwIfUserAlreadyInGroup(group, user); - validationService.throwIfGroupFull(group); - - controllerService.addUser(account, UUID.fromString(groupId)); - - model.addAttribute("account", account); - return "redirect:/gruppen2/"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("/detailsSearch") - public String showGroupDetailsNoMember(KeycloakAuthenticationToken token, - Model model, - @RequestParam("id") String groupId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - Group group = userService.getGroupById(UUID.fromString(groupId)); - UUID parentId = group.getParent(); - Group parent = controllerService.getParent(parentId); - User user = new User(account.getName(), "", "", ""); - - model.addAttribute("account", account); - if (validationService.checkIfUserInGroup(group, user)){ - return "redirect:/gruppen2/details/" + groupId; - } - - model.addAttribute("group", group); - model.addAttribute("parentId", parentId); - model.addAttribute("parent", parent); - - return "detailsNoMember"; - } - - //TODO: Muss post-mapping sein - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("/acceptinvite/{link}") - public String acceptInvite(KeycloakAuthenticationToken token, - Model model, - @PathVariable("link") String link) { - Group group = userService.getGroupById(inviteService.getGroupIdFromLink(link)); - - validationService.throwIfGroupNotExisting(group.getTitle()); - - model.addAttribute("account", keyCloakService.createAccountFromPrincipal(token)); - model.addAttribute("group", group); - - if (group.getVisibility() == Visibility.PUBLIC) { - return "redirect:/gruppen2/details/" + group.getId(); - } - - return "joinprivate"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/acceptinvite") - @CacheEvict(value = "groups", allEntries = true) - public String postAcceptInvite(KeycloakAuthenticationToken token, - @RequestParam("id") String groupId) { - - Account acc = keyCloakService.createAccountFromPrincipal(token); - - User user = new User(acc.getName(), acc.getGivenname(), acc.getFamilyname(), acc.getEmail()); - - if (!validationService.checkIfUserInGroup(userService.getGroupById(UUID.fromString(groupId)), user)) { - controllerService.addUser(keyCloakService.createAccountFromPrincipal(token), UUID.fromString(groupId)); - } - - return "redirect:/gruppen2/"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/leaveGroup") - @CacheEvict(value = "groups", allEntries = true) - public String pLeaveGroup(KeycloakAuthenticationToken token, - @RequestParam("group_id") String groupId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), "", "", ""); - Group group = userService.getGroupById(UUID.fromString(groupId)); - - controllerService.deleteUser(account, user, group); - return "redirect:/gruppen2/"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/deleteGroup") - @CacheEvict(value = "groups", allEntries = true) - public String pDeleteGroup(KeycloakAuthenticationToken token, - @RequestParam("group_id") String groupId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - User user = new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); - Group group = userService.getGroupById(UUID.fromString(groupId)); - - validationService.throwIfNoAdmin(group, user); - - controllerService.deleteGroupEvent(user.getId(), UUID.fromString(groupId)); - return "redirect:/gruppen2/"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @GetMapping("/details/members/{id}") - public String editMembers(Model model, - KeycloakAuthenticationToken token, - @PathVariable("id") String groupId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - Group group = userService.getGroupById(UUID.fromString(groupId)); - User user = new User(account.getName(), "", "", ""); - - validationService.throwIfNoAdmin(group, user); - - model.addAttribute("account", account); - model.addAttribute("members", group.getMembers()); - model.addAttribute("group", group); - model.addAttribute("admin", Role.ADMIN); - return "editMembers"; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/details/members/changeRole") - @CacheEvict(value = "groups", allEntries = true) - public String changeRole(KeycloakAuthenticationToken token, - @RequestParam("group_id") String groupId, - @RequestParam("user_id") String userId) { - Account account = keyCloakService.createAccountFromPrincipal(token); - Group group = userService.getGroupById(UUID.fromString(groupId)); - User principle = new User(account.getName(), "", "", ""); - User user = new User(userId, "", "", ""); - - validationService.throwIfNoAdmin(group, principle); - - controllerService.changeRole(account, user, group); - - group = userService.getGroupById(UUID.fromString(groupId)); - if (!validationService.checkIfAdmin(group, principle)) { - return "redirect:/gruppen2/details/" + groupId; - } - return "redirect:/gruppen2/details/members/" + groupId; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/details/members/changeMaximum") - @CacheEvict(value = "groups", allEntries = true) - public String changeMaxSize(@RequestParam("maximum") Long maximum, - @RequestParam("group_id") String groupId, - KeycloakAuthenticationToken token) { - Account account = keyCloakService.createAccountFromPrincipal(token); - Group group = userService.getGroupById(UUID.fromString(groupId)); - - validationService.throwIfNewMaximumIsValid(maximum, group); - - controllerService.updateMaxUser(account, UUID.fromString(groupId), maximum); - return "redirect:/gruppen2/details/members/" + groupId; - } - - @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) - @PostMapping("/details/members/deleteUser") - @CacheEvict(value = "groups", allEntries = true) - public String deleteUser(@RequestParam("group_id") String groupId, - @RequestParam("user_id") String userId, - KeycloakAuthenticationToken token) { - Account account = keyCloakService.createAccountFromPrincipal(token); - User principle = new User(account.getName(), "", "", ""); - User user = new User(userId, "", "", ""); - Group group = userService.getGroupById(UUID.fromString(groupId)); - - validationService.throwIfNoAdmin(group, principle); - - controllerService.deleteUser(account, user, group); - - if (!validationService.checkIfUserInGroup(group, principle)) { - return "redirect:/gruppen2/"; - } - return "redirect:/gruppen2/details/members/" + groupId; - } - - @GetMapping("*") - public String defaultLink() throws EventException { - throw new PageNotFoundException("\uD83D\uDE41"); - } -} diff --git a/src/main/java/mops/gruppen2/security/Account.java b/src/main/java/mops/gruppen2/domain/Account.java similarity index 86% rename from src/main/java/mops/gruppen2/security/Account.java rename to src/main/java/mops/gruppen2/domain/Account.java index b0466b2..ad24a7a 100644 --- a/src/main/java/mops/gruppen2/security/Account.java +++ b/src/main/java/mops/gruppen2/domain/Account.java @@ -1,4 +1,4 @@ -package mops.gruppen2.security; +package mops.gruppen2.domain; import lombok.Value; diff --git a/src/main/java/mops/gruppen2/domain/Group.java b/src/main/java/mops/gruppen2/domain/Group.java index 0ac93b6..9bfdd9c 100644 --- a/src/main/java/mops/gruppen2/domain/Group.java +++ b/src/main/java/mops/gruppen2/domain/Group.java @@ -16,6 +16,7 @@ import java.util.UUID; @Setter public class Group { + //TODO: List to Hashmap private final List members; private final Map roles; private UUID id; @@ -27,8 +28,8 @@ public class Group { private UUID parent; public Group() { - this.members = new ArrayList<>(); - this.roles = new HashMap<>(); + members = new ArrayList<>(); + roles = new HashMap<>(); } } diff --git a/src/main/java/mops/gruppen2/domain/GroupType.java b/src/main/java/mops/gruppen2/domain/GroupType.java index 30bf9ca..ea45105 100644 --- a/src/main/java/mops/gruppen2/domain/GroupType.java +++ b/src/main/java/mops/gruppen2/domain/GroupType.java @@ -1,5 +1,6 @@ package mops.gruppen2.domain; public enum GroupType { - SIMPLE, LECTURE + SIMPLE, + LECTURE } diff --git a/src/main/java/mops/gruppen2/domain/Role.java b/src/main/java/mops/gruppen2/domain/Role.java index 2806b91..2b58e75 100644 --- a/src/main/java/mops/gruppen2/domain/Role.java +++ b/src/main/java/mops/gruppen2/domain/Role.java @@ -1,5 +1,6 @@ package mops.gruppen2.domain; public enum Role { - ADMIN, MEMBER + ADMIN, + MEMBER } diff --git a/src/main/java/mops/gruppen2/domain/User.java b/src/main/java/mops/gruppen2/domain/User.java index bf6c172..16806b2 100644 --- a/src/main/java/mops/gruppen2/domain/User.java +++ b/src/main/java/mops/gruppen2/domain/User.java @@ -15,4 +15,11 @@ public class User { private String givenname; private String familyname; private String email; + + public User(Account account) { + id = account.getName(); + givenname = account.getGivenname(); + familyname = account.getFamilyname(); + email = account.getEmail(); + } } diff --git a/src/main/java/mops/gruppen2/domain/Visibility.java b/src/main/java/mops/gruppen2/domain/Visibility.java index 18be67b..5f41a61 100644 --- a/src/main/java/mops/gruppen2/domain/Visibility.java +++ b/src/main/java/mops/gruppen2/domain/Visibility.java @@ -1,5 +1,6 @@ package mops.gruppen2.domain; public enum Visibility { - PUBLIC, PRIVATE + PUBLIC, + PRIVATE } diff --git a/src/main/java/mops/gruppen2/domain/event/AddUserEvent.java b/src/main/java/mops/gruppen2/domain/event/AddUserEvent.java index 9020b0c..b2f65be 100644 --- a/src/main/java/mops/gruppen2/domain/event/AddUserEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/AddUserEvent.java @@ -1,6 +1,5 @@ package mops.gruppen2.domain.event; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import mops.gruppen2.domain.Group; @@ -16,7 +15,6 @@ import java.util.UUID; * Fügt einen einzelnen Nutzer einer Gruppe hinzu. */ @Getter -@AllArgsConstructor @NoArgsConstructor // For Jackson public class AddUserEvent extends Event { @@ -33,14 +31,14 @@ public class AddUserEvent extends Event { @Override protected void applyEvent(Group group) throws EventException { - User user = new User(this.userId, this.givenname, this.familyname, this.email); + User user = new User(userId, givenname, familyname, email); if (group.getMembers().contains(user)) { - throw new UserAlreadyExistsException(this.getClass().toString()); + throw new UserAlreadyExistsException(getClass().toString()); } if (group.getMembers().size() >= group.getUserMaximum()) { - throw new GroupFullException(this.getClass().toString()); + throw new GroupFullException(getClass().toString()); } group.getMembers().add(user); diff --git a/src/main/java/mops/gruppen2/domain/event/CreateGroupEvent.java b/src/main/java/mops/gruppen2/domain/event/CreateGroupEvent.java index 5e2b1a1..e75c6e6 100644 --- a/src/main/java/mops/gruppen2/domain/event/CreateGroupEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/CreateGroupEvent.java @@ -1,6 +1,5 @@ package mops.gruppen2.domain.event; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import mops.gruppen2.domain.Group; @@ -10,7 +9,6 @@ import mops.gruppen2.domain.Visibility; import java.util.UUID; @Getter -@AllArgsConstructor @NoArgsConstructor // For Jackson public class CreateGroupEvent extends Event { @@ -21,18 +19,18 @@ public class CreateGroupEvent extends Event { public CreateGroupEvent(UUID groupId, String userId, UUID parent, GroupType type, Visibility visibility, Long userMaximum) { super(groupId, userId); - this.groupParent = parent; - this.groupType = type; - this.groupVisibility = visibility; - this.groupUserMaximum = userMaximum; + groupParent = parent; + groupType = type; + groupVisibility = visibility; + groupUserMaximum = userMaximum; } @Override protected void applyEvent(Group group) { - group.setId(this.groupId); - group.setParent(this.groupParent); - group.setType(this.groupType); - group.setVisibility(this.groupVisibility); - group.setUserMaximum(this.groupUserMaximum); + group.setId(groupId); + group.setParent(groupParent); + group.setType(groupType); + group.setVisibility(groupVisibility); + group.setUserMaximum(groupUserMaximum); } } diff --git a/src/main/java/mops/gruppen2/domain/event/DeleteGroupEvent.java b/src/main/java/mops/gruppen2/domain/event/DeleteGroupEvent.java index 788d300..adc54f5 100644 --- a/src/main/java/mops/gruppen2/domain/event/DeleteGroupEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/DeleteGroupEvent.java @@ -23,5 +23,6 @@ public class DeleteGroupEvent extends Event { group.setVisibility(null); group.setType(null); group.setParent(null); + group.setUserMaximum(0L); } } diff --git a/src/main/java/mops/gruppen2/domain/event/Event.java b/src/main/java/mops/gruppen2/domain/event/Event.java index 167c122..bf1d8f5 100644 --- a/src/main/java/mops/gruppen2/domain/event/Event.java +++ b/src/main/java/mops/gruppen2/domain/event/Event.java @@ -39,13 +39,13 @@ public abstract class Event { applyEvent(group); } - protected abstract void applyEvent(Group group) throws EventException; - private void checkGroupIdMatch(UUID groupId) { if (groupId == null || this.groupId.equals(groupId)) { return; } - throw new GroupIdMismatchException(this.getClass().toString()); + throw new GroupIdMismatchException(getClass().toString()); } + + protected abstract void applyEvent(Group group) throws EventException; } diff --git a/src/main/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEvent.java b/src/main/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEvent.java index 4eae31f..bbd9f6d 100644 --- a/src/main/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEvent.java @@ -1,10 +1,9 @@ package mops.gruppen2.domain.event; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.exception.NoValueException; +import mops.gruppen2.domain.exception.BadParameterException; import java.util.UUID; @@ -12,7 +11,6 @@ import java.util.UUID; * Ändert nur die Gruppenbeschreibung. */ @Getter -@AllArgsConstructor @NoArgsConstructor // For Jackson public class UpdateGroupDescriptionEvent extends Event { @@ -25,10 +23,10 @@ public class UpdateGroupDescriptionEvent extends Event { @Override protected void applyEvent(Group group) { - if (this.newGroupDescription.isEmpty()) { - throw new NoValueException(this.getClass().toString()); + if (newGroupDescription.isEmpty()) { + throw new BadParameterException("Die Beschreibung ist leer."); } - group.setDescription(this.newGroupDescription); + group.setDescription(newGroupDescription); } } diff --git a/src/main/java/mops/gruppen2/domain/event/UpdateGroupTitleEvent.java b/src/main/java/mops/gruppen2/domain/event/UpdateGroupTitleEvent.java index b3a57ba..689e55f 100644 --- a/src/main/java/mops/gruppen2/domain/event/UpdateGroupTitleEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/UpdateGroupTitleEvent.java @@ -1,10 +1,9 @@ package mops.gruppen2.domain.event; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.exception.NoValueException; +import mops.gruppen2.domain.exception.BadParameterException; import java.util.UUID; @@ -12,7 +11,6 @@ import java.util.UUID; * Ändert nur den Gruppentitel. */ @Getter -@AllArgsConstructor @NoArgsConstructor // For Jackson public class UpdateGroupTitleEvent extends Event { @@ -25,11 +23,11 @@ public class UpdateGroupTitleEvent extends Event { @Override protected void applyEvent(Group group) { - if (this.getNewGroupTitle().isEmpty()) { - throw new NoValueException(this.getClass().toString()); + if (newGroupTitle.isEmpty()) { + throw new BadParameterException("Der Titel ist leer."); } - group.setTitle(this.newGroupTitle); + group.setTitle(newGroupTitle); } } diff --git a/src/main/java/mops/gruppen2/domain/event/UpdateRoleEvent.java b/src/main/java/mops/gruppen2/domain/event/UpdateRoleEvent.java index 740eb40..e7703e3 100644 --- a/src/main/java/mops/gruppen2/domain/event/UpdateRoleEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/UpdateRoleEvent.java @@ -1,6 +1,5 @@ package mops.gruppen2.domain.event; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import mops.gruppen2.domain.Group; @@ -13,7 +12,6 @@ import java.util.UUID; * Aktualisiert die Gruppenrolle eines Teilnehmers. */ @Getter -@AllArgsConstructor @NoArgsConstructor // For Jackson public class UpdateRoleEvent extends Event { @@ -26,12 +24,12 @@ public class UpdateRoleEvent extends Event { @Override protected void applyEvent(Group group) throws UserNotFoundException { - if (group.getRoles().containsKey(this.userId)) { - group.getRoles().put(this.userId, this.newRole); + if (group.getRoles().containsKey(userId)) { + group.getRoles().put(userId, newRole); return; } - throw new UserNotFoundException(this.getClass().toString()); + throw new UserNotFoundException(getClass().toString()); } } diff --git a/src/main/java/mops/gruppen2/domain/event/UpdateUserMaxEvent.java b/src/main/java/mops/gruppen2/domain/event/UpdateUserMaxEvent.java index e3f39fd..f9df452 100644 --- a/src/main/java/mops/gruppen2/domain/event/UpdateUserMaxEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/UpdateUserMaxEvent.java @@ -1,19 +1,18 @@ package mops.gruppen2.domain.event; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.exception.BadParameterException; import mops.gruppen2.domain.exception.EventException; import java.util.UUID; @Getter -@AllArgsConstructor @NoArgsConstructor public class UpdateUserMaxEvent extends Event { - private Long userMaximum; + private Long userMaximum; public UpdateUserMaxEvent(UUID groupId, String userId, Long userMaximum) { super(groupId, userId); @@ -22,6 +21,10 @@ public class UpdateUserMaxEvent extends Event { @Override protected void applyEvent(Group group) throws EventException { - group.setUserMaximum(this.userMaximum); + if (userMaximum <= 0 || userMaximum < group.getMembers().size()) { + throw new BadParameterException("Usermaximum zu klein."); + } + + group.setUserMaximum(userMaximum); } } diff --git a/src/main/java/mops/gruppen2/domain/exception/EventException.java b/src/main/java/mops/gruppen2/domain/exception/EventException.java index 3b6c609..38d56d9 100644 --- a/src/main/java/mops/gruppen2/domain/exception/EventException.java +++ b/src/main/java/mops/gruppen2/domain/exception/EventException.java @@ -3,7 +3,7 @@ package mops.gruppen2.domain.exception; import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; -public abstract class EventException extends ResponseStatusException { +public class EventException extends ResponseStatusException { public EventException(HttpStatus status, String msg, String info) { super(status, msg + " (" + info + ")"); diff --git a/src/main/java/mops/gruppen2/domain/exception/NoValueException.java b/src/main/java/mops/gruppen2/domain/exception/NoValueException.java deleted file mode 100644 index 3fd91dd..0000000 --- a/src/main/java/mops/gruppen2/domain/exception/NoValueException.java +++ /dev/null @@ -1,10 +0,0 @@ -package mops.gruppen2.domain.exception; - -import org.springframework.http.HttpStatus; - -public class NoValueException extends EventException { - - public NoValueException(String info) { - super(HttpStatus.BAD_REQUEST, "Eine Information fehlt.", info); - } -} diff --git a/src/main/java/mops/gruppen2/domain/exception/WrongFileException.java b/src/main/java/mops/gruppen2/domain/exception/WrongFileException.java index b2e69f4..665c9da 100644 --- a/src/main/java/mops/gruppen2/domain/exception/WrongFileException.java +++ b/src/main/java/mops/gruppen2/domain/exception/WrongFileException.java @@ -3,6 +3,7 @@ package mops.gruppen2.domain.exception; import org.springframework.http.HttpStatus; public class WrongFileException extends EventException { + public WrongFileException(String info) { super(HttpStatus.BAD_REQUEST, "Die entsprechende Datei ist keine valide CSV-Datei!", info); } diff --git a/src/main/java/mops/gruppen2/repository/EventRepository.java b/src/main/java/mops/gruppen2/repository/EventRepository.java index 579c104..775991f 100644 --- a/src/main/java/mops/gruppen2/repository/EventRepository.java +++ b/src/main/java/mops/gruppen2/repository/EventRepository.java @@ -29,7 +29,7 @@ public interface EventRepository extends CrudRepository { @Query("SELECT * FROM event WHERE event_type = :type") List findAllEventsByType(@Param("type") String type); - @Query("SELECT * FROM event WHERE event_type = :type AND user_id = :userId") + @Query("SELECT * FROM event WHERE event_type = :type AND user_id = :userId") List findEventsByTypeAndUserId(@Param("type") String type, @Param("userId") String userId); @Query("SELECT COUNT(*) FROM event WHERE event_type = :type AND group_id = :groupId") diff --git a/src/main/java/mops/gruppen2/service/APIFormatterService.java b/src/main/java/mops/gruppen2/service/APIFormatterService.java index a279688..2985a4f 100644 --- a/src/main/java/mops/gruppen2/service/APIFormatterService.java +++ b/src/main/java/mops/gruppen2/service/APIFormatterService.java @@ -7,9 +7,11 @@ import org.springframework.stereotype.Service; import java.util.List; @Service -public class APIFormatterService { +public final class APIFormatterService { - public static GroupRequestWrapper wrap(Long status, List groupList) { + private APIFormatterService() {} + + public static GroupRequestWrapper wrap(long status, List groupList) { return new GroupRequestWrapper(status, groupList); } } diff --git a/src/main/java/mops/gruppen2/service/ControllerService.java b/src/main/java/mops/gruppen2/service/ControllerService.java index c0aec6d..0d932d3 100644 --- a/src/main/java/mops/gruppen2/service/ControllerService.java +++ b/src/main/java/mops/gruppen2/service/ControllerService.java @@ -1,5 +1,6 @@ package mops.gruppen2.service; +import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Group; import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.Role; @@ -14,18 +15,17 @@ import mops.gruppen2.domain.event.UpdateGroupTitleEvent; import mops.gruppen2.domain.event.UpdateRoleEvent; import mops.gruppen2.domain.event.UpdateUserMaxEvent; import mops.gruppen2.domain.exception.EventException; -import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.domain.exception.WrongFileException; -import mops.gruppen2.security.Account; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Map; +import java.util.Objects; import java.util.UUID; -import java.util.logging.Logger; import java.util.stream.Collectors; import static mops.gruppen2.domain.Role.ADMIN; @@ -34,30 +34,115 @@ import static mops.gruppen2.domain.Role.ADMIN; @Service public class ControllerService { + private static final Logger LOG = LoggerFactory.getLogger("controllerServiceLogger"); private final EventService eventService; private final UserService userService; private final ValidationService validationService; private final InviteService inviteService; - private final Logger logger; public ControllerService(EventService eventService, UserService userService, ValidationService validationService, InviteService inviteService) { this.eventService = eventService; this.userService = userService; this.validationService = validationService; this.inviteService = inviteService; - this.logger = Logger.getLogger("controllerServiceLogger"); + } + + private static User getVeteranMember(Account account, Group group) { + List members = group.getMembers(); + String newAdminId; + if (members.get(0).getId().equals(account.getName())) { + newAdminId = members.get(1).getId(); + } else { + newAdminId = members.get(0).getId(); + } + return new User(newAdminId, "", "", ""); + } + + /** + * Wie createGroup, nur das hier die Gruppe auch als Veranstaltung gesetzt werden kann und CSV Dateien mit Nutzern + * eingelesen werden können. + * + * @param account Der Nutzer der die Gruppe erstellt + * @param title Parameter für die neue Gruppe + * @param description Parameter für die neue Gruppe + * @param isVisibilityPrivate Parameter für die neue Gruppe + * @param isLecture Parameter für die neue Gruppe + * @param isMaximumInfinite Parameter für die neue Gruppe + * @param userMaximum Parameter für die neue Gruppe + * @param parent Parameter für die neue Gruppe + * @param file Parameter für die neue Gruppe + */ + public void createGroupAsOrga(Account account, + String title, + String description, + Boolean isVisibilityPrivate, + Boolean isLecture, + Boolean isMaximumInfinite, + Long userMaximum, + UUID parent, + MultipartFile file) { + + userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum); + + List newUsers = readCsvFile(file); + + List oldUsers = new ArrayList<>(); + User user = new User(account); + oldUsers.add(user); + + removeOldUsersFromNewUsers(oldUsers, newUsers); + + userMaximum = adjustUserMaximum((long) newUsers.size(), 1L, userMaximum); + + UUID groupId = createGroup(account, + title, + description, + isVisibilityPrivate, + isLecture, + isMaximumInfinite, + userMaximum, parent); + + addUserList(newUsers, groupId); + } + + /** + * Wenn die maximale Useranzahl unendlich ist, wird das Maximum auf 100000 gesetzt. Praktisch gibt es also Maximla 100000 + * Nutzer pro Gruppe. + * + * @param isMaximumInfinite Gibt an ob es unendlich viele User geben soll + * @param userMaximum Das Maximum an Usern, falls es eins gibt + * + * @return Maximum an Usern + */ + private static Long checkInfiniteUsers(Boolean isMaximumInfinite, Long userMaximum) { + isMaximumInfinite = isMaximumInfinite != null; + + if (isMaximumInfinite) { + userMaximum = 100_000L; + } + + return userMaximum; } /** * Erzeugt eine neue Gruppe, fügt den User, der die Gruppe erstellt hat, hinzu und setzt seine Rolle als Admin fest. * Zudem wird der Gruppentitel und die Gruppenbeschreibung erzeugt, welche vorher der Methode übergeben wurden. - * Aus diesen Event Objekten wird eine Liste erzeugt, welche daraufhin mithilfe des EventServices gesichert wird. + * Aus diesen Event-Objekten wird eine Liste erzeugt, welche daraufhin mithilfe des EventServices gesichert wird. * * @param account Keycloak-Account * @param title Gruppentitel * @param description Gruppenbeschreibung */ - public UUID createGroup(Account account, String title, String description, Boolean isVisibilityPrivate, Boolean isLecture, Boolean isMaximumInfinite, Long userMaximum, UUID parent) { + //TODO: remove booleans + public UUID createGroup(Account account, + String title, + String description, + Boolean isVisibilityPrivate, + Boolean isLecture, + Boolean isMaximumInfinite, + Long userMaximum, + UUID parent) { + userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum); Visibility groupVisibility = setGroupVisibility(isVisibilityPrivate); @@ -65,7 +150,12 @@ public class ControllerService { GroupType groupType = setGroupType(isLecture); - CreateGroupEvent createGroupEvent = new CreateGroupEvent(groupId, account.getName(), parent, groupType, groupVisibility, userMaximum); + CreateGroupEvent createGroupEvent = new CreateGroupEvent(groupId, + account.getName(), + parent, + groupType, + groupVisibility, + userMaximum); eventService.saveEvent(createGroupEvent); inviteService.createLink(groupId); @@ -80,38 +170,95 @@ public class ControllerService { return groupId; } - /** - * Wie createGroup, nur das hier die Gruppe auch als Veranstaltung gesetzt werden kann und CSV Dateien mit Nutzern - * eingelesen werden können. - * @param account Der Nutzer der die Gruppe erstellt - * @param title Parameter für die neue Gruppe - * @param description Parameter für die neue Gruppe - * @param isVisibilityPrivate Parameter für die neue Gruppe - * @param isLecture Parameter für die neue Gruppe - * @param isMaximumInfinite Parameter für die neue Gruppe - * @param userMaximum Parameter für die neue Gruppe - * @param parent Parameter für die neue Gruppe - * @param file Parameter für die neue Gruppe - */ - public void createGroupAsOrga(Account account, String title, String description, Boolean isVisibilityPrivate, Boolean isLecture, Boolean isMaximumInfinite, Long userMaximum, UUID parent, MultipartFile file) { - userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum); - - List newUsers = readCsvFile(file); - - List oldUsers = new ArrayList<>(); - User user = new User(account.getName(), "", "", ""); - oldUsers.add(user); - - removeOldUsersFromNewUsers(oldUsers, newUsers); - - userMaximum = adjustUserMaximum((long) newUsers.size(), 1L, userMaximum); - - UUID groupId = createGroup(account, title, description, isVisibilityPrivate, isLecture, isMaximumInfinite, userMaximum, parent); - - addUserList(newUsers, groupId); + private static List readCsvFile(MultipartFile file) throws EventException { + if (file == null) { + return new ArrayList<>(); + } + if (!file.isEmpty()) { + try { + List userList = CsvService.read(file.getInputStream()); + return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list + } catch (IOException ex) { + LOG.warn("File konnte nicht gelesen werden"); + throw new WrongFileException(file.getOriginalFilename()); + } + } + return new ArrayList<>(); } - public void addUsersFromCsv(Account account, MultipartFile file, String groupId) throws IOException{ + private static void removeOldUsersFromNewUsers(List oldUsers, List newUsers) { + for (User oldUser : oldUsers) { + newUsers.remove(oldUser); + } + } + + private static Long adjustUserMaximum(Long newUsers, Long oldUsers, Long maxUsers) { + if (oldUsers + newUsers > maxUsers) { + maxUsers = oldUsers + newUsers; + } + return maxUsers; + } + + private void addUserList(List newUsers, UUID groupId) { + for (User user : newUsers) { + Group group = userService.getGroupById(groupId); + if (group.getMembers().contains(user)) { + LOG.info("Benutzer {} ist bereits in Gruppe", user.getId()); + } else { + AddUserEvent addUserEvent = new AddUserEvent(groupId, user.getId(), user.getGivenname(), user.getFamilyname(), user.getEmail()); + eventService.saveEvent(addUserEvent); + } + } + } + + private static Visibility setGroupVisibility(Boolean isVisibilityPrivate) { + isVisibilityPrivate = isVisibilityPrivate != null; + + if (isVisibilityPrivate) { + return Visibility.PRIVATE; + } else { + return Visibility.PUBLIC; + } + } + + private static GroupType setGroupType(Boolean isLecture) { + isLecture = isLecture != null; + if (isLecture) { + return GroupType.LECTURE; + } else { + return GroupType.SIMPLE; + } + } + + public void addUser(Account account, UUID groupId) { + AddUserEvent addUserEvent = new AddUserEvent(groupId, account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); + eventService.saveEvent(addUserEvent); + } + + private void updateTitle(Account account, UUID groupId, String title) { + UpdateGroupTitleEvent updateGroupTitleEvent = new UpdateGroupTitleEvent(groupId, account.getName(), title); + eventService.saveEvent(updateGroupTitleEvent); + } + + public void updateRole(User user, UUID groupId) throws EventException { + UpdateRoleEvent updateRoleEvent; + Group group = userService.getGroupById(groupId); + validationService.throwIfNotInGroup(group, user); + + if (group.getRoles().get(user.getId()) == ADMIN) { + updateRoleEvent = new UpdateRoleEvent(group.getId(), user.getId(), Role.MEMBER); + } else { + updateRoleEvent = new UpdateRoleEvent(group.getId(), user.getId(), ADMIN); + } + eventService.saveEvent(updateRoleEvent); + } + + private void updateDescription(Account account, UUID groupId, String description) { + UpdateGroupDescriptionEvent updateGroupDescriptionEvent = new UpdateGroupDescriptionEvent(groupId, account.getName(), description); + eventService.saveEvent(updateGroupDescriptionEvent); + } + + public void addUsersFromCsv(Account account, MultipartFile file, String groupId) { Group group = userService.getGroupById(UUID.fromString(groupId)); List newUserList = readCsvFile(file); @@ -120,15 +267,24 @@ public class ControllerService { UUID groupUUID = getUUID(groupId); Long newUserMaximum = adjustUserMaximum((long) newUserList.size(), (long) group.getMembers().size(), group.getUserMaximum()); - if (newUserMaximum > group.getUserMaximum()){ + if (newUserMaximum > group.getUserMaximum()) { updateMaxUser(account, groupUUID, newUserMaximum); } addUserList(newUserList, groupUUID); } + public UUID getUUID(String id) { + return UUID.fromString(Objects.requireNonNullElse(id, "00000000-0000-0000-0000-000000000000")); + } + + public void updateMaxUser(Account account, UUID groupId, Long userMaximum) { + UpdateUserMaxEvent updateUserMaxEvent = new UpdateUserMaxEvent(groupId, account.getName(), userMaximum); + eventService.saveEvent(updateUserMaxEvent); + } + public void changeMetaData(Account account, Group group, String title, String description) { - if (!title.equals(group.getTitle())){ + if (!title.equals(group.getTitle())) { updateTitle(account, group.getId(), title); } @@ -145,114 +301,6 @@ public class ControllerService { return parent; } - private void removeOldUsersFromNewUsers(List oldUsers, List newUsers) { - for (User oldUser : oldUsers) { - newUsers.remove(oldUser); - } - } - - /** - * Wenn die maximale Useranzahl unendlich ist, wird das Maximum auf 100000 gesetzt. Praktisch gibt es also Maximla 100000 - * Nutzer pro Gruppe. - * @param isMaximumInfinite Gibt an ob es unendlich viele User geben soll - * @param userMaximum Das Maximum an Usern, falls es eins gibt - * @return Maximum an Usern - */ - private Long checkInfiniteUsers(Boolean isMaximumInfinite, Long userMaximum) { - isMaximumInfinite = isMaximumInfinite != null; - - if (isMaximumInfinite) { - userMaximum = 100000L; - } - - return userMaximum; - } - - private Visibility setGroupVisibility(Boolean isVisibilityPrivate) { - isVisibilityPrivate = isVisibilityPrivate != null; - - if (isVisibilityPrivate) { - return Visibility.PRIVATE; - } else { - return Visibility.PUBLIC; - } - } - - private GroupType setGroupType(Boolean isLecture) { - isLecture = isLecture != null; - if (isLecture) { - return GroupType.LECTURE; - } else { - return GroupType.SIMPLE; - } - } - - private List readCsvFile(MultipartFile file) throws EventException{ - if(file == null) return new ArrayList<>(); - if (!file.isEmpty()) { - try { - List userList = CsvService.read(file.getInputStream()); - return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list - } catch (IOException ex) { - logger.warning("File konnte nicht gelesen werden"); - throw new WrongFileException(file.getOriginalFilename()); - } - } - return new ArrayList<>(); - } - - private Long adjustUserMaximum(Long newUsers, Long oldUsers, Long maxUsers) { - if (oldUsers + newUsers > maxUsers) { - maxUsers = oldUsers + newUsers; - } - return maxUsers; - } - - public void addUser(Account account, UUID groupId) { - AddUserEvent addUserEvent = new AddUserEvent(groupId, account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()); - eventService.saveEvent(addUserEvent); - } - - public void addUserList(List newUsers, UUID groupId) { - for (User user : newUsers) { - Group group = userService.getGroupById(groupId); - if (group.getMembers().contains(user)) { - logger.info("Benutzer " + user.getId() + " ist bereits in Gruppe"); - } else { - AddUserEvent addUserEvent = new AddUserEvent(groupId, user.getId(), user.getGivenname(), user.getFamilyname(), user.getEmail()); - eventService.saveEvent(addUserEvent); - } - } - } - - public void updateTitle(Account account, UUID groupId, String title) { - UpdateGroupTitleEvent updateGroupTitleEvent = new UpdateGroupTitleEvent(groupId, account.getName(), title); - eventService.saveEvent(updateGroupTitleEvent); - } - - public void updateDescription(Account account, UUID groupId, String description) { - UpdateGroupDescriptionEvent updateGroupDescriptionEvent = new UpdateGroupDescriptionEvent(groupId, account.getName(), description); - eventService.saveEvent(updateGroupDescriptionEvent); - } - - public void updateMaxUser(Account account, UUID groupId, Long userMaximum) { - UpdateUserMaxEvent updateUserMaxEvent = new UpdateUserMaxEvent(groupId, account.getName(), userMaximum); - eventService.saveEvent(updateUserMaxEvent); - } - - public void updateRole(User user, UUID groupId) throws EventException { - UpdateRoleEvent updateRoleEvent; - Group group = userService.getGroupById(groupId); - validationService.throwIfNotInGroup(group, user); - - if (group.getRoles().get(user.getId()) == ADMIN) { - updateRoleEvent = new UpdateRoleEvent(group.getId(), user.getId(), Role.MEMBER); - } else { - updateRoleEvent = new UpdateRoleEvent(group.getId(), user.getId(), ADMIN); - } - eventService.saveEvent(updateRoleEvent); - } - public void deleteUser(Account account, User user, Group group) throws EventException { changeRoleIfLastAdmin(account, group); @@ -265,6 +313,14 @@ public class ControllerService { } } + private static boolean idIsEmpty(UUID id) { + if (id == null) { + return true; + } + + return "00000000-0000-0000-0000-000000000000".equals(id.toString()); + } + private void deleteUserEvent(User user, UUID groupId) { DeleteUserEvent deleteUserEvent = new DeleteUserEvent(groupId, user.getId()); eventService.saveEvent(deleteUserEvent); @@ -276,13 +332,6 @@ public class ControllerService { eventService.saveEvent(deleteGroupEvent); } - public void changeRoleIfLastAdmin(Account account, Group group) { - if (group.getMembers().size() <= 1) { - return; - } - promoteVeteranMember(account, group); - } - private void promoteVeteranMember(Account account, Group group) { if (validationService.checkIfLastAdmin(account, group)) { User newAdmin = getVeteranMember(account, group); @@ -290,6 +339,13 @@ public class ControllerService { } } + public void changeRoleIfLastAdmin(Account account, Group group) { + if (group.getMembers().size() <= 1) { + return; + } + promoteVeteranMember(account, group); + } + public void changeRole(Account account, User user, Group group) { if (user.getId().equals(account.getName())) { if (group.getMembers().size() <= 1) { @@ -300,31 +356,4 @@ public class ControllerService { updateRole(user, group.getId()); } - private User getVeteranMember(Account account, Group group) { - List members = group.getMembers(); - String newAdminId; - if (members.get(0).getId().equals(account.getName())) { - newAdminId = members.get(1).getId(); - } else { - newAdminId = members.get(0).getId(); - } - return new User(newAdminId, "", "", ""); - } - - public UUID getUUID(String id) { - if (id == null) { - return UUID.fromString("00000000-0000-0000-0000-000000000000"); - } else { - return UUID.fromString(id); - } - } - - public boolean idIsEmpty(UUID id) { - if (id == null) { - return true; - } - - return id.toString().equals("00000000-0000-0000-0000-000000000000"); - } - } diff --git a/src/main/java/mops/gruppen2/service/CsvService.java b/src/main/java/mops/gruppen2/service/CsvService.java index a876d04..a476481 100644 --- a/src/main/java/mops/gruppen2/service/CsvService.java +++ b/src/main/java/mops/gruppen2/service/CsvService.java @@ -11,9 +11,11 @@ import java.io.InputStream; import java.util.List; @Service -public class CsvService { +public final class CsvService { - public static List read(InputStream stream) throws IOException { + private CsvService() {} + + static List read(InputStream stream) throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = mapper.schemaFor(User.class).withHeader().withColumnReordering(true); diff --git a/src/main/java/mops/gruppen2/service/EventService.java b/src/main/java/mops/gruppen2/service/EventService.java index 93759c2..5226519 100644 --- a/src/main/java/mops/gruppen2/service/EventService.java +++ b/src/main/java/mops/gruppen2/service/EventService.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import mops.gruppen2.domain.dto.EventDTO; import mops.gruppen2.domain.event.Event; import mops.gruppen2.repository.EventRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -15,11 +17,10 @@ import java.util.stream.Collectors; //TODO: Evtl aufsplitten in EventRepoService und EventService? public class EventService { - private final JsonService jsonService; + private static final Logger LOG = LoggerFactory.getLogger(EventService.class); private final EventRepository eventStore; - public EventService(JsonService jsonService, EventRepository eventStore) { - this.jsonService = jsonService; + public EventService(EventRepository eventStore) { this.eventStore = eventStore; } @@ -38,8 +39,40 @@ public class EventService { } } + /** + * Erzeugt aus einem Event Objekt ein EventDTO Objekt. + * + * @param event Event, welches in DTO übersetzt wird + * + * @return EventDTO (Neues DTO) + */ + public EventDTO getDTOFromEvent(Event event) { + String payload = ""; + try { + payload = JsonService.serializeEvent(event); + } catch (JsonProcessingException e) { + LOG.error("Event ({}) konnte nicht serialisiert werden!", event.getClass()); + } + + return new EventDTO(null, event.getGroupId().toString(), event.getUserId(), getEventType(event), payload); + } + + /** + * Gibt den Eventtyp als String wieder. + * + * @param event Event dessen Typ abgefragt werden soll + * + * @return Der Name des Typs des Events + */ + private static String getEventType(Event event) { + int lastDot = event.getClass().getName().lastIndexOf('.'); + + return event.getClass().getName().substring(lastDot + 1); + } + /** * Speichert alle Events aus der übergebenen Liste in der DB. + * * @param events Liste an Events die gespeichert werden soll */ @SafeVarargs @@ -51,40 +84,12 @@ public class EventService { } } - /** - * Erzeugt aus einem Event Objekt ein EventDTO Objekt. - * Ist die Gruppe öffentlich, dann wird die visibility auf true gesetzt. - * - * @param event Event, welches in DTO übersetzt wird - * @return EventDTO (Neues DTO) - */ - public EventDTO getDTOFromEvent(Event event) { - String payload = ""; - try { - payload = jsonService.serializeEvent(event); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - - return new EventDTO(null, event.getGroupId().toString(), event.getUserId(), getEventType(event), payload); - } - - /** - * Gibt den Eventtyp als String wieder. - * @param event Event dessen Typ abgefragt werden soll - * @return Der Name des Typs des Events - */ - private String getEventType(Event event) { - int lastDot = event.getClass().getName().lastIndexOf('.'); - - return event.getClass().getName().substring(lastDot + 1); - } - /** * Findet alle Events welche ab dem neuen Status hinzugekommen sind. * Sucht alle Events mit event_id > status * * @param status Die Id des zuletzt gespeicherten Events + * * @return Liste von neueren Events */ public List getNewEvents(Long status) { @@ -98,28 +103,39 @@ public class EventService { * Erzeugt aus einer Liste von eventDTOs eine Liste von Events. * * @param eventDTOS Liste von DTOs + * * @return Liste von Events */ - public List getEventsFromDTOs(Iterable eventDTOS) { + List getEventsFromDTOs(Iterable eventDTOS) { List events = new ArrayList<>(); for (EventDTO eventDTO : eventDTOS) { try { - events.add(jsonService.deserializeEvent(eventDTO.getEvent_payload())); + events.add(JsonService.deserializeEvent(eventDTO.getEvent_payload())); } catch (JsonProcessingException e) { - e.printStackTrace(); + LOG.error("Payload\n {}\n konnte nicht deserialisiert werden!", eventDTO.getEvent_payload()); } } return events; } - public Long getMaxEvent_id() { - return eventStore.getHighesEventID(); + public long getMaxEventId() { + long highestEvent = 0; + + try { + highestEvent = eventStore.getHighesEventID(); + } catch (NullPointerException e) { + LOG.debug("Eine maxId von 0 wurde zurückgegeben, da keine Events vorhanden sind."); + } + + return highestEvent; } /** * Gibt eine Liste mit allen Events zurück, die zu der Gruppe gehören. + * * @param groupId Gruppe die betrachtet werden soll + * * @return Liste aus Events */ public List getEventsOfGroup(UUID groupId) { @@ -128,24 +144,25 @@ public class EventService { } /** - * Gibt eine Liste aus GruppenIds zurück in denen sich der User befindet. + * Gibt eine Liste aus GruppenIds zurück, in denen sich der User befindet. + * * @param userId Die Id des Users + * * @return Liste aus GruppenIds */ public List findGroupIdsByUser(String userId) { - return eventStore.findGroupIdsWhereUserId(userId, "AddUserEvent").stream() - .map(UUID::fromString) - .collect(Collectors.toList()); + return eventStore.findGroupIdsWhereUserId(userId, "AddUserEvent").stream().map(UUID::fromString).collect(Collectors.toList()); } /** * Gibt true zurück, falls der User aktuell in der Gruppe ist, sonst false. + * * @param groupId Id der Gruppe - * @param userId Id des zu überprüfenden Users + * @param userId Id des zu überprüfenden Users + * * @return true or false */ - public boolean userInGroup(UUID groupId, String userId) { - return eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "AddUserEvent") - > eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "DeleteUserEvent"); + boolean userInGroup(UUID groupId, String userId) { + return eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "AddUserEvent") > eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "DeleteUserEvent"); } } diff --git a/src/main/java/mops/gruppen2/service/GroupService.java b/src/main/java/mops/gruppen2/service/GroupService.java index 5febc5a..03549ea 100644 --- a/src/main/java/mops/gruppen2/service/GroupService.java +++ b/src/main/java/mops/gruppen2/service/GroupService.java @@ -1,5 +1,6 @@ package mops.gruppen2.service; +import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Group; import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.Visibility; @@ -7,7 +8,6 @@ import mops.gruppen2.domain.dto.EventDTO; import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.repository.EventRepository; -import mops.gruppen2.security.Account; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -34,9 +34,10 @@ public class GroupService { * Wandelt die Zeilen in Events um und gibt davon eine Liste zurück. * * @param groupIds Liste an IDs + * * @return Liste an Events */ - //TODO Das vielleicht in den EventRepoService? + //TODO: Das vielleicht in den EventRepoService? public List getGroupEvents(List groupIds) { List eventDTOS = new ArrayList<>(); for (UUID groupId : groupIds) { @@ -45,65 +46,6 @@ public class GroupService { return eventService.getEventsFromDTOs(eventDTOS); } - /** - * Erzeugt eine neue Map wo Gruppen aus den Events erzeugt und den Gruppen_ids zugeordnet werden. - * Die Gruppen werden als Liste zurückgegeben - * - * @param events Liste an Events - * @return Liste an Projizierten Gruppen - * @throws EventException Projektionsfehler - */ - public List projectEventList(List events) throws EventException { - Map groupMap = new HashMap<>(); - - events.parallelStream() - .forEachOrdered(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId()))); - - return new ArrayList<>(groupMap.values()); - } - - /** - * Gibt die Gruppe mit der richtigen Id aus der übergebenen Map wieder, existiert diese nicht - * wird die Gruppe erstellt und der Map hizugefügt. - * @param groups Map aus GruppenIds und Gruppen - * @param groupId Die Id der Gruppe, die zurückgegeben werden soll - * @return Die gesuchte Gruppe - */ - private Group getOrCreateGroup(Map groups, UUID groupId) { - if (!groups.containsKey(groupId)) { - groups.put(groupId, new Group()); - } - - return groups.get(groupId); - } - - /** - * Wird verwendet bei der Suche nach Gruppen: Titel, Beschreibung werden benötigt. - * Außerdem wird beachtet, ob der eingeloggte User bereits in entsprechenden Gruppen mitglied ist. - * - * @return Liste von projizierten Gruppen - * @throws EventException Projektionsfehler - */ - //TODO Rename - @Cacheable("groups") - public List getAllGroupWithVisibilityPublic(String userId) throws EventException { - List groupEvents = eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("CreateGroupEvent")); - groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupDescriptionEvent"))); - groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupTitleEvent"))); - groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent"))); - groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateUserMaxEvent"))); - - List visibleGroups = projectEventList(groupEvents); - - sortByGroupType(visibleGroups); - - return visibleGroups.stream() - .filter(group -> group.getType() != null) - .filter(group -> !eventService.userInGroup(group.getId(), userId)) - .filter(group -> group.getVisibility() == Visibility.PUBLIC) - .collect(Collectors.toList()); - } - /** * Wird verwendet beim Gruppe erstellen bei der Parent-Auswahl: nur Titel benötigt. * @@ -119,18 +61,55 @@ public class GroupService { List visibleGroups = projectEventList(createEvents); return visibleGroups.stream() - .filter(group -> group.getType() == GroupType.LECTURE) - .filter(group -> group.getVisibility() == Visibility.PUBLIC) - .collect(Collectors.toList()); + .filter(group -> group.getType() == GroupType.LECTURE) + .filter(group -> group.getVisibility() == Visibility.PUBLIC) + .collect(Collectors.toList()); } + /** + * Erzeugt eine neue Map wo Gruppen aus den Events erzeugt und den Gruppen_ids zugeordnet werden. + * Die Gruppen werden als Liste zurückgegeben. + * + * @param events Liste an Events + * + * @return Liste an Projizierten Gruppen + * + * @throws EventException Projektionsfehler + */ + public List projectEventList(List events) throws EventException { + Map groupMap = new HashMap<>(); + + events.parallelStream() + .forEachOrdered(event -> event.apply(getOrCreateGroup(groupMap, event.getGroupId()))); + + return new ArrayList<>(groupMap.values()); + } + + /** + * Gibt die Gruppe mit der richtigen Id aus der übergebenen Map wieder, existiert diese nicht + * wird die Gruppe erstellt und der Map hizugefügt. + * + * @param groups Map aus GruppenIds und Gruppen + * @param groupId Die Id der Gruppe, die zurückgegeben werden soll + * + * @return Die gesuchte Gruppe + */ + private static Group getOrCreateGroup(Map groups, UUID groupId) { + if (!groups.containsKey(groupId)) { + groups.put(groupId, new Group()); + } + + return groups.get(groupId); + } /** * Filtert alle öffentliche Gruppen nach dem Suchbegriff und gibt diese als Liste von Gruppen zurück. * Groß und Kleinschreibung wird nicht beachtet. * * @param search Der Suchstring + * * @return Liste von projizierten Gruppen + * * @throws EventException Projektionsfehler */ //Todo Rename @@ -140,19 +119,44 @@ public class GroupService { return getAllGroupWithVisibilityPublic(account.getName()); } - return getAllGroupWithVisibilityPublic(account.getName()) - .parallelStream() - .filter(group -> group.getTitle().toLowerCase().contains(search.toLowerCase()) - || group.getDescription().toLowerCase().contains(search.toLowerCase())) - .collect(Collectors.toList()); + return getAllGroupWithVisibilityPublic(account.getName()).parallelStream().filter(group -> group.getTitle().toLowerCase().contains(search.toLowerCase()) || group.getDescription().toLowerCase().contains(search.toLowerCase())).collect(Collectors.toList()); + } + + /** + * Wird verwendet bei der Suche nach Gruppen: Titel, Beschreibung werden benötigt. + * Außerdem wird beachtet, ob der eingeloggte User bereits in entsprechenden Gruppen mitglied ist. + * + * @return Liste von projizierten Gruppen + * + * @throws EventException Projektionsfehler + */ + //TODO Rename + @Cacheable("groups") + public List getAllGroupWithVisibilityPublic(String userId) throws EventException { + List groupEvents = eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("CreateGroupEvent")); + groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupDescriptionEvent"))); + groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateGroupTitleEvent"))); + groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("DeleteGroupEvent"))); + groupEvents.addAll(eventService.getEventsFromDTOs(eventRepository.findAllEventsByType("UpdateUserMaxEvent"))); + + List visibleGroups = projectEventList(groupEvents); + + sortByGroupType(visibleGroups); + + return visibleGroups.stream() + .filter(group -> group.getType() != null) + .filter(group -> !eventService.userInGroup(group.getId(), userId)) + .filter(group -> group.getVisibility() == Visibility.PUBLIC) + .collect(Collectors.toList()); } /** * Sortiert die übergebene Liste an Gruppen, sodass Veranstaltungen am Anfang der Liste sind. + * * @param groups Die Liste von Gruppen die sortiert werden soll */ - public void sortByGroupType(List groups) { - groups.sort((g1, g2) -> { + void sortByGroupType(List groups) { + groups.sort((Group g1, Group g2) -> { if (g1.getType() == GroupType.LECTURE) { return -1; } diff --git a/src/main/java/mops/gruppen2/service/InviteService.java b/src/main/java/mops/gruppen2/service/InviteService.java index 69f21e2..962dd81 100644 --- a/src/main/java/mops/gruppen2/service/InviteService.java +++ b/src/main/java/mops/gruppen2/service/InviteService.java @@ -4,6 +4,8 @@ import mops.gruppen2.domain.dto.InviteLinkDTO; import mops.gruppen2.domain.exception.InvalidInviteException; import mops.gruppen2.domain.exception.NoInviteExistException; import mops.gruppen2.repository.InviteRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.UUID; @@ -11,17 +13,18 @@ import java.util.UUID; @Service public class InviteService { + private static final Logger LOG = LoggerFactory.getLogger(InviteService.class); private final InviteRepository inviteRepository; public InviteService(InviteRepository inviteRepository) { this.inviteRepository = inviteRepository; } - public void createLink(UUID groupId) { + void createLink(UUID groupId) { inviteRepository.save(new InviteLinkDTO(null, groupId.toString(), UUID.randomUUID().toString())); } - public void destroyLink(UUID groupId) { + void destroyLink(UUID groupId) { inviteRepository.deleteLinkOfGroup(groupId.toString()); } @@ -29,7 +32,7 @@ public class InviteService { try { return UUID.fromString(inviteRepository.findGroupIdByLink(link)); } catch (Exception e) { - e.printStackTrace(); + LOG.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link); } throw new InvalidInviteException(link); @@ -39,7 +42,7 @@ public class InviteService { try { return inviteRepository.findLinkByGroupId(groupId.toString()); } catch (Exception e) { - e.printStackTrace(); + LOG.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", groupId); } throw new NoInviteExistException(groupId.toString()); diff --git a/src/main/java/mops/gruppen2/service/JsonService.java b/src/main/java/mops/gruppen2/service/JsonService.java index b5c4730..9f3150b 100644 --- a/src/main/java/mops/gruppen2/service/JsonService.java +++ b/src/main/java/mops/gruppen2/service/JsonService.java @@ -9,17 +9,21 @@ import org.springframework.stereotype.Service; * Übersetzt JSON-Event-Payloads zu Java-Event-Repräsentationen und zurück. */ @Service -public class JsonService { +public final class JsonService { + + private JsonService() {} /** * Übersetzt mithilfe der Jackson-Library eine Java-Event-Repräsentation zu einem JSON-Event-Payload. * * @param event Java-Event-Repräsentation + * * @return JSON-Event-Payload als String + * * @throws JsonProcessingException Bei JSON Fehler */ - public String serializeEvent(Event event) throws JsonProcessingException { + static String serializeEvent(Event event) throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); return mapper.writeValueAsString(event); } @@ -28,10 +32,12 @@ public class JsonService { * Übersetzt mithilfe der Jackson-Library einen JSON-Event-Payload zu einer Java-Event-Repräsentation. * * @param json JSON-Event-Payload als String + * * @return Java-Event-Repräsentation + * * @throws JsonProcessingException Bei JSON Fehler */ - public Event deserializeEvent(String json) throws JsonProcessingException { + static Event deserializeEvent(String json) throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(json, Event.class); } diff --git a/src/main/java/mops/gruppen2/service/KeyCloakService.java b/src/main/java/mops/gruppen2/service/KeyCloakService.java index 825d734..3067da1 100644 --- a/src/main/java/mops/gruppen2/service/KeyCloakService.java +++ b/src/main/java/mops/gruppen2/service/KeyCloakService.java @@ -1,20 +1,23 @@ package mops.gruppen2.service; -import mops.gruppen2.security.Account; +import mops.gruppen2.domain.Account; import org.keycloak.KeycloakPrincipal; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.springframework.stereotype.Service; @Service -public class KeyCloakService { +public final class KeyCloakService { + + private KeyCloakService() {} /** * Creates an Account. * * @param token Ein toller token + * * @return Account with current userdata */ - public Account createAccountFromPrincipal(KeycloakAuthenticationToken token) { + public static Account createAccountFromPrincipal(KeycloakAuthenticationToken token) { KeycloakPrincipal principal = (KeycloakPrincipal) token.getPrincipal(); return new Account( principal.getName(), diff --git a/src/main/java/mops/gruppen2/service/SearchService.java b/src/main/java/mops/gruppen2/service/SearchService.java index 7d09958..6e94bdf 100644 --- a/src/main/java/mops/gruppen2/service/SearchService.java +++ b/src/main/java/mops/gruppen2/service/SearchService.java @@ -3,6 +3,4 @@ package mops.gruppen2.service; import org.springframework.stereotype.Service; @Service -public class SearchService { - -} +public class SearchService {} diff --git a/src/main/java/mops/gruppen2/service/UserService.java b/src/main/java/mops/gruppen2/service/UserService.java index f013c26..dd6d65b 100644 --- a/src/main/java/mops/gruppen2/service/UserService.java +++ b/src/main/java/mops/gruppen2/service/UserService.java @@ -23,11 +23,19 @@ public class UserService { this.eventService = eventService; } + @Cacheable("groups") + public List getUserGroups(String userId) throws EventException { + return getUserGroups(new User(userId, "", "", "")); + } + /** * Gibt eine Liste aus Gruppen zurück, in denen sich der übergebene User befindet. + * * @param user Der User + * * @return Liste aus Gruppen */ + //TODO: Nur AddUserEvents + DeleteUserEvents betrachten @Cacheable("groups") public List getUserGroups(User user) { List groupIds = eventService.findGroupIdsByUser(user.getId()); @@ -45,15 +53,13 @@ public class UserService { return newGroups; } - @Cacheable("groups") - public List getUserGroups(String userId) throws EventException { - return getUserGroups(new User(userId, null, null, null)); - } - /** * Gibt die Gruppe zurück, die zu der übergebenen Id passt. + * * @param groupId Die Id der gesuchten Gruppe + * * @return Die gesuchte Gruppe + * * @throws EventException Wenn die Gruppe nicht gefunden wird */ public Group getGroupById(UUID groupId) throws EventException { diff --git a/src/main/java/mops/gruppen2/service/ValidationService.java b/src/main/java/mops/gruppen2/service/ValidationService.java index 745da93..b1defef 100644 --- a/src/main/java/mops/gruppen2/service/ValidationService.java +++ b/src/main/java/mops/gruppen2/service/ValidationService.java @@ -1,11 +1,17 @@ package mops.gruppen2.service; +import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Role; import mops.gruppen2.domain.User; import mops.gruppen2.domain.Visibility; -import mops.gruppen2.domain.exception.*; -import mops.gruppen2.security.Account; +import mops.gruppen2.domain.exception.BadParameterException; +import mops.gruppen2.domain.exception.GroupFullException; +import mops.gruppen2.domain.exception.GroupNotFoundException; +import mops.gruppen2.domain.exception.NoAccessException; +import mops.gruppen2.domain.exception.NoAdminAfterActionException; +import mops.gruppen2.domain.exception.UserAlreadyExistsException; +import mops.gruppen2.domain.exception.UserNotFoundException; import org.springframework.stereotype.Service; import java.util.List; @@ -25,6 +31,7 @@ public class ValidationService { this.groupService = groupService; } + //TODO: make static or change return + assignment public List checkSearch(String search, List groups, Account account) { if (search != null) { groups = groupService.findGroupWith(search, account); @@ -38,82 +45,80 @@ public class ValidationService { } } - public void throwIfNoAccessToPrivate(Group group, User user) { - if (!checkIfUserInGroup(group, user) && group.getVisibility() == Visibility.PRIVATE) { - throw new NoAccessException(""); - } - } - - public boolean checkIfUserInGroup(Group group, User user) { - return group.getMembers().contains(user); - } - public void throwIfUserAlreadyInGroup(Group group, User user) { if (checkIfUserInGroup(group, user)) { throw new UserAlreadyExistsException("@details"); } } - public void throwIfNotInGroup(Group group, User user) { + void throwIfNotInGroup(Group group, User user) { if (!checkIfUserInGroup(group, user)) { - throw new UserNotFoundException(this.getClass().toString()); + throw new UserNotFoundException(getClass().toString()); } } + public boolean checkIfUserInGroup(Group group, User user) { + return group.getMembers().contains(user); + } + public void throwIfGroupFull(Group group) { if (group.getUserMaximum() < group.getMembers().size() + 1) { throw new GroupFullException("Du kannst der Gruppe daher leider nicht beitreten."); } } - public boolean checkIfGroupEmpty(UUID groupId) { + boolean checkIfGroupEmpty(UUID groupId) { return userService.getGroupById(groupId).getMembers().isEmpty(); } public void throwIfNoAdmin(Group group, User user) { throwIfNoAccessToPrivate(group, user); - if (group.getRoles().get(user.getId()) != Role.ADMIN) { + if (group.getRoles().get(user.getId()) != ADMIN) { + throw new NoAccessException(""); + } + } + + public void throwIfNoAccessToPrivate(Group group, User user) { + if (!checkIfUserInGroup(group, user) && group.getVisibility() == Visibility.PRIVATE) { throw new NoAccessException(""); } } public boolean checkIfAdmin(Group group, User user) { if (checkIfUserInGroup(group, user)) { - return group.getRoles().get(user.getId()) == Role.ADMIN; + return group.getRoles().get(user.getId()) == ADMIN; } return false; } - public boolean checkIfLastAdmin(Account account, Group group) { + void throwIfLastAdmin(Account account, Group group) { + if (checkIfLastAdmin(account, group)) { + throw new NoAdminAfterActionException("Du bist letzter Admin!"); + } + } + + boolean checkIfLastAdmin(Account account, Group group) { for (Map.Entry entry : group.getRoles().entrySet()) { - if (entry.getValue() == ADMIN) { - if (!(entry.getKey().equals(account.getName()))) { - return false; - } + if (entry.getValue() == ADMIN && !(entry.getKey().equals(account.getName()))) { + return false; } } return true; } - public void throwIfLastAdmin(Account account, Group group) { - if (checkIfLastAdmin(account, group)) { - throw new NoAdminAfterActionException("Du Otto bist letzter Admin!"); - } - } - /** * Überprüft ob alle Felder richtig gesetzt sind. * * @param description Die Beschreibung der Gruppe - * @param title Der Titel der Gruppe + * @param title Der Titel der Gruppe * @param userMaximum Das user Limit der Gruppe */ public void checkFields(String title, String description, Long userMaximum, Boolean maxInfiniteUsers) { - if (description == null || description.trim().length() == 0) { + if (description == null || description.trim().isEmpty()) { throw new BadParameterException("Die Beschreibung wurde nicht korrekt angegeben"); } - if (title == null || title.trim().length() == 0) { + if (title == null || title.trim().isEmpty()) { throw new BadParameterException("Der Titel wurde nicht korrekt angegeben"); } @@ -121,19 +126,17 @@ public class ValidationService { throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben"); } - if (userMaximum != null) { - if (userMaximum < 1 || userMaximum > 10000L) { - throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben"); - } + if (userMaximum != null && (userMaximum < 1 || userMaximum > 10000L)) { + throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben"); } } public void checkFields(String title, String description) { - if (description == null || description.trim().length() == 0) { + if (description == null || description.trim().isEmpty()) { throw new BadParameterException("Die Beschreibung wurde nicht korrekt angegeben"); } - if (title == null || title.trim().length() == 0) { + if (title == null || title.trim().isEmpty()) { throw new BadParameterException("Der Titel wurde nicht korrekt angegeben"); } } diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql deleted file mode 100644 index 942abad..0000000 --- a/src/main/resources/data.sql +++ /dev/null @@ -1,6 +0,0 @@ -insert into event values -(1,'8c15f614-fe04-4ac4-a2d7-d13e62ba8597','orga','CreateGroupEvent','{"type":"CreateGroupEvent","groupId":"8c15f614-fe04-4ac4-a2d7-d13e62ba8597","userId":"orga","groupVisibility":"PUBLIC","groupParent":null,"groupType":"SIMPLE","groupUserMaximum":2}'), -(2,'8c15f614-fe04-4ac4-a2d7-d13e62ba8597','orga','AddUserEvent','{"type":"AddUserEvent","groupId":"8c15f614-fe04-4ac4-a2d7-d13e62ba8597","userId":"orga","givenname":"orga","familyname":"orga","email":"blorga@orga.org"}'), -(3,'8c15f614-fe04-4ac4-a2d7-d13e62ba8597','orga','UpdateGroupTitleEvent','{"type":"UpdateGroupTitleEvent","groupId":"8c15f614-fe04-4ac4-a2d7-d13e62ba8597","userId":"orga","newGroupTitle":"sdsad"}'), -(4,'8c15f614-fe04-4ac4-a2d7-d13e62ba8597','orga','UpdateGroupDescriptionEvent','{"type":"UpdateGroupDescriptionEvent","groupId":"8c15f614-fe04-4ac4-a2d7-d13e62ba8597","userId":"orga","newGroupDescription":"sadsad"}'), -(5,'8c15f614-fe04-4ac4-a2d7-d13e62ba8597','orga','UpdateRoleEvent','{"type":"UpdateRoleEvent","groupId":"8c15f614-fe04-4ac4-a2d7-d13e62ba8597","userId":"orga","newRole":"ADMIN"}'); diff --git a/src/main/resources/templates/createOrga.html b/src/main/resources/templates/createOrga.html index ca74dae..99a129a 100644 --- a/src/main/resources/templates/createOrga.html +++ b/src/main/resources/templates/createOrga.html @@ -55,7 +55,8 @@
- +
@@ -66,7 +67,7 @@ + Gruppe
@@ -88,7 +90,8 @@ + Mitgliedern + hochladen
diff --git a/src/main/resources/templates/createStudent.html b/src/main/resources/templates/createStudent.html index f466cb0..022c918 100644 --- a/src/main/resources/templates/createStudent.html +++ b/src/main/resources/templates/createStudent.html @@ -54,7 +54,8 @@
- +
@@ -65,12 +66,13 @@ + Gruppe
diff --git a/src/main/resources/templates/detailsMember.html b/src/main/resources/templates/detailsMember.html index 104f8e2..4fea4cc 100644 --- a/src/main/resources/templates/detailsMember.html +++ b/src/main/resources/templates/detailsMember.html @@ -112,7 +112,9 @@
- +


@@ -122,7 +124,8 @@
  • - + + admin
  • diff --git a/src/main/resources/templates/editMembers.html b/src/main/resources/templates/editMembers.html index 7eadaf0..afc7c77 100644 --- a/src/main/resources/templates/editMembers.html +++ b/src/main/resources/templates/editMembers.html @@ -56,7 +56,8 @@ + Mitgliedern + hochladen
- +
diff --git a/src/main/resources/templates/search.html b/src/main/resources/templates/search.html index f98ef29..e90a8dd 100644 --- a/src/main/resources/templates/search.html +++ b/src/main/resources/templates/search.html @@ -35,23 +35,24 @@

Gruppensuche

-
-
- - -
- - -
+
+
+ + +
+ + +

diff --git a/src/test/java/mops/gruppen2/TestBuilder.java b/src/test/java/mops/gruppen2/TestBuilder.java index 903bd93..d79f850 100644 --- a/src/test/java/mops/gruppen2/TestBuilder.java +++ b/src/test/java/mops/gruppen2/TestBuilder.java @@ -1,6 +1,7 @@ package mops.gruppen2; import com.github.javafaker.Faker; +import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Group; import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.Role; @@ -13,7 +14,6 @@ import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.UpdateGroupDescriptionEvent; import mops.gruppen2.domain.event.UpdateGroupTitleEvent; import mops.gruppen2.domain.event.UpdateRoleEvent; -import mops.gruppen2.security.Account; import java.util.ArrayList; import java.util.Collection; @@ -29,11 +29,11 @@ public class TestBuilder { public static Account account(String name) { return new Account(name, - "", - "", - "", - "", - null); + "", + "", + "", + "", + null); } public static Group apply(Group group, Event... events) { @@ -52,12 +52,14 @@ public class TestBuilder { * Baut eine UUID. * * @param id Integer id + * * @return UUID */ - public static UUID uuidFromInt(int id) { + public static UUID uuidMock(int id) { + String idString = String.valueOf(Math.abs(id + 1)); return UUID.fromString("00000000-0000-0000-0000-" - + "0".repeat(11 - String.valueOf(id).length()) - + id); + + "0".repeat(11 - idString.length()) + + idString); } /** @@ -65,22 +67,23 @@ public class TestBuilder { * * @param count Gruppenanzahl * @param membercount Mitgliederanzahl pro Gruppe + * * @return Eventliste */ public static List completePublicGroups(int count, int membercount) { return IntStream.range(0, count) - .parallel() - .mapToObj(i -> completePublicGroup(membercount)) - .flatMap(Collection::stream) - .collect(Collectors.toList()); + .parallel() + .mapToObj(i -> completePublicGroup(membercount)) + .flatMap(Collection::stream) + .collect(Collectors.toList()); } public static List completePrivateGroups(int count, int membercount) { return IntStream.range(0, count) - .parallel() - .mapToObj(i -> completePrivateGroup(membercount)) - .flatMap(Collection::stream) - .collect(Collectors.toList()); + .parallel() + .mapToObj(i -> completePrivateGroup(membercount)) + .flatMap(Collection::stream) + .collect(Collectors.toList()); } public static List completePublicGroup(int membercount) { @@ -119,29 +122,30 @@ public class TestBuilder { * Generiert mehrere CreateGroupEvents, 1 <= groupId <= count. * * @param count Anzahl der verschiedenen Gruppen + * * @return Eventliste */ public static List createPublicGroupEvents(int count) { return IntStream.range(0, count) - .parallel() - .mapToObj(i -> createPublicGroupEvent()) - .collect(Collectors.toList()); + .parallel() + .mapToObj(i -> createPublicGroupEvent()) + .collect(Collectors.toList()); } public static List createPrivateGroupEvents(int count) { return IntStream.range(0, count) - .parallel() - .mapToObj(i -> createPublicGroupEvent()) - .collect(Collectors.toList()); + .parallel() + .mapToObj(i -> createPublicGroupEvent()) + .collect(Collectors.toList()); } public static List createMixedGroupEvents(int count) { return IntStream.range(0, count) - .parallel() - .mapToObj(i -> faker.random().nextInt(0, 1) > 0.5 - ? createPublicGroupEvent() - : createPrivateGroupEvent()) - .collect(Collectors.toList()); + .parallel() + .mapToObj(i -> faker.random().nextInt(0, 1) > 0.5 + ? createPublicGroupEvent() + : createPrivateGroupEvent()) + .collect(Collectors.toList()); } public static Event createPrivateGroupEvent(UUID groupId) { @@ -191,13 +195,14 @@ public class TestBuilder { * * @param count Anzahl der Mitglieder * @param groupId Gruppe, zu welcher geaddet wird + * * @return Eventliste */ public static List addUserEvents(int count, UUID groupId) { return IntStream.range(0, count) - .parallel() - .mapToObj(i -> addUserEvent(groupId, String.valueOf(i))) - .collect(Collectors.toList()); + .parallel() + .mapToObj(i -> addUserEvent(groupId, String.valueOf(i))) + .collect(Collectors.toList()); } public static Event addUserEvent(UUID groupId, String userId) { @@ -221,8 +226,8 @@ public class TestBuilder { public static List deleteUserEvents(int count, List eventList) { List removeEvents = new ArrayList<>(); List shuffle = eventList.parallelStream() - .filter(event -> event instanceof AddUserEvent) - .collect(Collectors.toList()); + .filter(event -> event instanceof AddUserEvent) + .collect(Collectors.toList()); Collections.shuffle(shuffle); @@ -241,12 +246,13 @@ public class TestBuilder { * Erzeugt mehrere DeleteUserEvents, sodass eine Gruppe komplett geleert wird. * * @param group Gruppe welche geleert wird + * * @return Eventliste */ public static List deleteUserEvents(Group group) { return group.getMembers().parallelStream() - .map(user -> deleteUserEvent(group.getId(), user.getId())) - .collect(Collectors.toList()); + .map(user -> deleteUserEvent(group.getId(), user.getId())) + .collect(Collectors.toList()); } public static Event deleteUserEvent(UUID groupId, String userId) { diff --git a/src/test/java/mops/gruppen2/architecture/LayeredArchitectureTest.java b/src/test/java/mops/gruppen2/architecture/LayeredArchitectureTest.java index fca3740..2596a1d 100644 --- a/src/test/java/mops/gruppen2/architecture/LayeredArchitectureTest.java +++ b/src/test/java/mops/gruppen2/architecture/LayeredArchitectureTest.java @@ -14,18 +14,17 @@ public class LayeredArchitectureTest { .layer("Domain").definedBy("..domain..") .layer("Service").definedBy("..service") .layer("Controller").definedBy("..controller..") - .layer("Repository").definedBy("..repository..") - .layer("Config").definedBy("..config.."); + .layer("Repository").definedBy("..repository.."); @ArchTest public static final ArchRule domainLayerShouldOnlyBeAccessedByServiceAndControllerLayer = layeredArchitecture .whereLayer("Domain") - .mayOnlyBeAccessedByLayers("Service", "Controller", "Config"); + .mayOnlyBeAccessedByLayers("Service", "Controller"); @ArchTest public static final ArchRule serviceLayerShouldOnlyBeAccessedByControllerLayer = layeredArchitecture .whereLayer("Service") - .mayOnlyBeAccessedByLayers("Controller", "Config"); + .mayOnlyBeAccessedByLayers("Controller"); @ArchTest public static final ArchRule repositoryLayerShouldOnlyBeAccessedByServiceLayer = layeredArchitecture diff --git a/src/test/java/mops/gruppen2/controller/APIControllerTest.java b/src/test/java/mops/gruppen2/controller/APIControllerTest.java new file mode 100644 index 0000000..a04386b --- /dev/null +++ b/src/test/java/mops/gruppen2/controller/APIControllerTest.java @@ -0,0 +1,167 @@ +package mops.gruppen2.controller; + +import mops.gruppen2.Gruppen2Application; +import mops.gruppen2.repository.EventRepository; +import mops.gruppen2.service.EventService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.transaction.annotation.Transactional; + +import static mops.gruppen2.TestBuilder.addUserEvent; +import static mops.gruppen2.TestBuilder.createPrivateGroupEvent; +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.deleteGroupEvent; +import static mops.gruppen2.TestBuilder.deleteUserEvent; +import static mops.gruppen2.TestBuilder.updateGroupTitleEvent; +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = Gruppen2Application.class) +@Transactional +@Rollback +class APIControllerTest { + + @Autowired + private EventRepository eventRepository; + @Autowired + private APIController apiController; + private EventService eventService; + @Autowired + private JdbcTemplate template; + + @BeforeEach + void setUp() { + eventService = new EventService(eventRepository); + eventRepository.deleteAll(); + //noinspection SqlResolve + template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1"); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void updateGroup_noGroup() { + assertThat(apiController.updateGroups(0L).getGroupList()).hasSize(0); + assertThat(apiController.updateGroups(4L).getGroupList()).hasSize(0); + assertThat(apiController.updateGroups(10L).getGroupList()).hasSize(0); + assertThat(apiController.updateGroups(0L).getStatus()).isEqualTo(0); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void updateGroup_singleGroup() { + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + addUserEvent(uuidMock(0)), + addUserEvent(uuidMock(0)), + addUserEvent(uuidMock(0)), + addUserEvent(uuidMock(0))); + + assertThat(apiController.updateGroups(0L).getGroupList()).hasSize(1); + assertThat(apiController.updateGroups(4L).getGroupList()).hasSize(1); + assertThat(apiController.updateGroups(10L).getGroupList()).hasSize(0); + assertThat(apiController.updateGroups(0L).getStatus()).isEqualTo(5); + } + + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void updateGroup_multipleGroups() { + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + addUserEvent(uuidMock(0)), + addUserEvent(uuidMock(0)), + createPrivateGroupEvent(uuidMock(1)), + addUserEvent(uuidMock(1)), + addUserEvent(uuidMock(1)), + addUserEvent(uuidMock(1))); + + assertThat(apiController.updateGroups(0L).getGroupList()).hasSize(2); + assertThat(apiController.updateGroups(4L).getGroupList()).hasSize(1); + assertThat(apiController.updateGroups(6L).getGroupList()).hasSize(1); + assertThat(apiController.updateGroups(7L).getGroupList()).hasSize(0); + assertThat(apiController.updateGroups(0L).getStatus()).isEqualTo(7); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupsOfUser_noGroup() { + assertThat(apiController.getGroupIdsOfUser("A")).isEmpty(); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupsOfUser_singleGroup() { + eventService.saveAll(createPrivateGroupEvent(uuidMock(0)), + createPrivateGroupEvent(uuidMock(1)), + createPrivateGroupEvent(uuidMock(2)), + addUserEvent(uuidMock(0), "A")); + + assertThat(apiController.getGroupIdsOfUser("A")).hasSize(1); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupsOfUser_singleGroupDeletedUser() { + eventService.saveAll(createPrivateGroupEvent(uuidMock(0)), + addUserEvent(uuidMock(0), "A"), + deleteUserEvent(uuidMock(0), "A")); + + assertThat(apiController.getGroupIdsOfUser("A")).isEmpty(); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupsOfUser_singleDeletedGroup() { + eventService.saveAll(createPrivateGroupEvent(uuidMock(0)), + addUserEvent(uuidMock(0), "A"), + deleteGroupEvent(uuidMock(0))); + + assertThat(apiController.getGroupIdsOfUser("A")).isEmpty(); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupsOfUser_multipleGroups() { + eventService.saveAll(createPrivateGroupEvent(uuidMock(0)), + createPrivateGroupEvent(uuidMock(1)), + createPrivateGroupEvent(uuidMock(2)), + addUserEvent(uuidMock(0), "A"), + addUserEvent(uuidMock(0), "B"), + addUserEvent(uuidMock(1), "A"), + addUserEvent(uuidMock(2), "A"), + addUserEvent(uuidMock(2), "B")); + + assertThat(apiController.getGroupIdsOfUser("A")).hasSize(3); + assertThat(apiController.getGroupIdsOfUser("B")).hasSize(2); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupFromId_noGroup() { + assertThat(apiController.getGroupById(uuidMock(0).toString())).isEqualTo(null); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupFromId_singleGroup() { + eventService.saveAll(createPrivateGroupEvent(uuidMock(0))); + + assertThat(apiController.getGroupById(uuidMock(0).toString()).getId()).isEqualTo(uuidMock(0)); + } + + @Test + @WithMockUser(username = "api_user", roles = "api_user") + void getGroupFromId_deletedGroup() { + eventService.saveAll(createPrivateGroupEvent(uuidMock(0)), + updateGroupTitleEvent(uuidMock(0)), + deleteGroupEvent(uuidMock(0))); + + assertThat(apiController.getGroupById(uuidMock(0).toString()).getTitle()).isEqualTo(null); + } +} diff --git a/src/test/java/mops/gruppen2/domain/event/AddUserEventTest.java b/src/test/java/mops/gruppen2/domain/event/AddUserEventTest.java index 81472a6..050c1ff 100644 --- a/src/test/java/mops/gruppen2/domain/event/AddUserEventTest.java +++ b/src/test/java/mops/gruppen2/domain/event/AddUserEventTest.java @@ -1,35 +1,57 @@ package mops.gruppen2.domain.event; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.User; -import mops.gruppen2.domain.exception.EventException; +import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.UserAlreadyExistsException; import org.junit.jupiter.api.Test; -import java.util.UUID; - +import static mops.gruppen2.TestBuilder.addUserEvent; +import static mops.gruppen2.TestBuilder.apply; +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; class AddUserEventTest { @Test - void userAlreadyExistExeption() throws EventException { - Group group = new Group(); - User user = new User("user1", "Stein", "Speck", "@sdasd"); - group.getMembers().add(user); - group.setUserMaximum(10L); - UUID id = UUID.randomUUID(); - Event event1 = new AddUserEvent(id, "user2", "Rock", "Roll", "and"); - event1.apply(group); + void applyEvent() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEvent = new AddUserEvent(uuidMock(0), "A", "Thomas", "Tom", "tho@mail.de"); - Event event2 = new AddUserEvent(id, "user1", "Rock", "Roll", "and"); + Group group = apply(createEvent, addEvent); - assertThrows(UserAlreadyExistsException.class, () -> - event2.apply(group) - ); - assertThat(group.getMembers().size()).isEqualTo(2); + assertThat(group.getMembers()).hasSize(1); + assertThat(group.getMembers().get(0).getGivenname()).isEqualTo("Thomas"); + assertThat(group.getMembers().get(0).getFamilyname()).isEqualTo("Tom"); + assertThat(group.getMembers().get(0).getEmail()).isEqualTo("tho@mail.de"); } + @Test + void applyEvent_userAlreadyExists() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEventA = addUserEvent(uuidMock(0), "A"); + Event addEventB = addUserEvent(uuidMock(0), "B"); + Event addEventC = addUserEvent(uuidMock(0), "A"); + Group group = apply(createEvent, addEventA, addEventB); + + assertThrows(UserAlreadyExistsException.class, () -> addEventA.apply(group)); + assertThrows(UserAlreadyExistsException.class, () -> addEventC.apply(group)); + assertThat(group.getMembers()).hasSize(2); + } + + @Test + void applyEvent_groupFull() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event maxSizeEvent = new UpdateUserMaxEvent(uuidMock(0), "A", 2L); + Event addEventA = addUserEvent(uuidMock(0), "A"); + Event addEventB = addUserEvent(uuidMock(0), "B"); + Event addEventC = addUserEvent(uuidMock(0), "C"); + + Group group = apply(createEvent, maxSizeEvent, addEventA, addEventB); + + assertThrows(GroupFullException.class, () -> addEventC.apply(group)); + assertThat(group.getMembers()).hasSize(2); + } } diff --git a/src/test/java/mops/gruppen2/domain/event/CreateGroupEventTest.java b/src/test/java/mops/gruppen2/domain/event/CreateGroupEventTest.java new file mode 100644 index 0000000..cdbbeea --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/CreateGroupEventTest.java @@ -0,0 +1,32 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.TestBuilder; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.GroupType; +import mops.gruppen2.domain.Visibility; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; + +class CreateGroupEventTest { + + @Test + void applyEvent() { + Event createEvent = new CreateGroupEvent(uuidMock(0), + "A", + uuidMock(1), + GroupType.SIMPLE, + Visibility.PUBLIC, + 100L); + + Group group = TestBuilder.apply(createEvent); + + assertThat(group.getMembers()).hasSize(0); + assertThat(group.getType()).isEqualTo(GroupType.SIMPLE); + assertThat(group.getVisibility()).isEqualTo(Visibility.PUBLIC); + assertThat(group.getUserMaximum()).isEqualTo(100); + assertThat(group.getId()).isEqualTo(uuidMock(0)); + assertThat(group.getParent()).isEqualTo(uuidMock(1)); + } +} diff --git a/src/test/java/mops/gruppen2/domain/event/DeleteGroupEventTest.java b/src/test/java/mops/gruppen2/domain/event/DeleteGroupEventTest.java new file mode 100644 index 0000000..67090f2 --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/DeleteGroupEventTest.java @@ -0,0 +1,33 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.TestBuilder; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.GroupType; +import mops.gruppen2.domain.Visibility; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; + +class DeleteGroupEventTest { + + @Test + void applyEvent() { + Event createEvent = new CreateGroupEvent(uuidMock(0), + "A", + uuidMock(1), + GroupType.SIMPLE, + Visibility.PUBLIC, + 100L); + Event deleteEvent = new DeleteGroupEvent(uuidMock(0), "A"); + + Group group = TestBuilder.apply(createEvent, deleteEvent); + + assertThat(group.getMembers()).isEmpty(); + assertThat(group.getType()).isEqualTo(null); + assertThat(group.getVisibility()).isEqualTo(null); + assertThat(group.getUserMaximum()).isEqualTo(0); + assertThat(group.getId()).isEqualTo(uuidMock(0)); + assertThat(group.getParent()).isEqualTo(null); + } +} diff --git a/src/test/java/mops/gruppen2/domain/event/DeleteUserEventTest.java b/src/test/java/mops/gruppen2/domain/event/DeleteUserEventTest.java index dad27f5..ecee94a 100644 --- a/src/test/java/mops/gruppen2/domain/event/DeleteUserEventTest.java +++ b/src/test/java/mops/gruppen2/domain/event/DeleteUserEventTest.java @@ -1,48 +1,38 @@ package mops.gruppen2.domain.event; +import mops.gruppen2.TestBuilder; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.User; -import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.UserNotFoundException; import org.junit.jupiter.api.Test; -import java.util.UUID; - -import static mops.gruppen2.domain.Role.MEMBER; +import static mops.gruppen2.TestBuilder.addUserEvent; +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; class DeleteUserEventTest { @Test - void applyDeleteUser() throws EventException { - Group group = new Group(); - User user = new User("user1", "Stein", "Speck", "@sdasd"); - group.getMembers().add(user); - group.getRoles().put("user1", MEMBER); - User user2 = new User("user2", "Rock", "Roll", "and"); - group.getMembers().add(user2); - group.getRoles().put("user2", MEMBER); + void applyEvent() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEvent = addUserEvent(uuidMock(0), "A"); + Event deleteEvent = new DeleteUserEvent(uuidMock(0), "A"); - Event event = new DeleteUserEvent(UUID.randomUUID(), "user1"); - event.apply(group); - - assertThat(group.getMembers().size()).isEqualTo(1); - assertThat(group.getRoles().size()).isEqualTo(1); + Group group = TestBuilder.apply(createEvent, addEvent, deleteEvent); + assertThat(group.getMembers()).hasSize(0); } @Test - void userDoesNotExistExeption() { - Group group = new Group(); - User user = new User("user1", "Stein", "Speck", "@sdasd"); - group.getMembers().add(user); - group.getRoles().put("user1", MEMBER); + void applyEvent_userNotFound() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEvent = addUserEvent(uuidMock(0), "A"); + Event deleteEvent = new DeleteUserEvent(uuidMock(0), "B"); - Event event = new DeleteUserEvent(UUID.randomUUID(), "user5"); - assertThrows(UserNotFoundException.class, () -> - event.apply(group) - ); - assertThat(group.getMembers().size()).isEqualTo(1); + Group group = TestBuilder.apply(createEvent, addEvent); + + assertThrows(UserNotFoundException.class, () -> deleteEvent.apply(group)); + assertThat(group.getMembers()).hasSize(1); } } diff --git a/src/test/java/mops/gruppen2/domain/event/EventTest.java b/src/test/java/mops/gruppen2/domain/event/EventTest.java new file mode 100644 index 0000000..dd906fb --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/EventTest.java @@ -0,0 +1,24 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.TestBuilder; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.exception.GroupIdMismatchException; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class EventTest { + + @Test + void apply() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEvent = TestBuilder.addUserEvent(uuidMock(1)); + + Group group = TestBuilder.apply(createEvent); + + assertThrows(GroupIdMismatchException.class, () -> addEvent.apply(group)); + } + +} diff --git a/src/test/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEventTest.java b/src/test/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEventTest.java new file mode 100644 index 0000000..8a8d53b --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/UpdateGroupDescriptionEventTest.java @@ -0,0 +1,36 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.TestBuilder; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.exception.BadParameterException; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UpdateGroupDescriptionEventTest { + + @Test + void applyEvent() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEvent = new UpdateGroupDescriptionEvent(uuidMock(0), "A", "desc."); + + Group group = TestBuilder.apply(createEvent, updateEvent); + + assertThat(group.getDescription()).isEqualTo("desc."); + } + + @Test + void applyEvent_badDescription() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEventA = new UpdateGroupDescriptionEvent(uuidMock(0), "A", ""); + Event updateEventB = new UpdateGroupDescriptionEvent(uuidMock(0), "A", " "); + + Group group = TestBuilder.apply(createEvent); + + assertThrows(BadParameterException.class, () -> updateEventA.apply(group)); + assertThrows(BadParameterException.class, () -> updateEventB.apply(group)); + } +} diff --git a/src/test/java/mops/gruppen2/domain/event/UpdateGroupTitleEventTest.java b/src/test/java/mops/gruppen2/domain/event/UpdateGroupTitleEventTest.java new file mode 100644 index 0000000..318d4dd --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/UpdateGroupTitleEventTest.java @@ -0,0 +1,36 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.TestBuilder; +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.exception.BadParameterException; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UpdateGroupTitleEventTest { + + @Test + void applyEvent() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEvent = new UpdateGroupTitleEvent(uuidMock(0), "A", "title."); + + Group group = TestBuilder.apply(createEvent, updateEvent); + + assertThat(group.getTitle()).isEqualTo("title."); + } + + @Test + void applyEvent_badDescription() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEventA = new UpdateGroupTitleEvent(uuidMock(0), "A", ""); + Event updateEventB = new UpdateGroupTitleEvent(uuidMock(0), "A", " "); + + Group group = TestBuilder.apply(createEvent); + + assertThrows(BadParameterException.class, () -> updateEventA.apply(group)); + assertThrows(BadParameterException.class, () -> updateEventB.apply(group)); + } +} diff --git a/src/test/java/mops/gruppen2/domain/event/UpdateRoleEventTest.java b/src/test/java/mops/gruppen2/domain/event/UpdateRoleEventTest.java new file mode 100644 index 0000000..3b3b5d0 --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/UpdateRoleEventTest.java @@ -0,0 +1,39 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.Role; +import mops.gruppen2.domain.exception.UserNotFoundException; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.addUserEvent; +import static mops.gruppen2.TestBuilder.apply; +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UpdateRoleEventTest { + + @Test + void applyEvent() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEvent = addUserEvent(uuidMock(0), "A"); + Event updateEvent = new UpdateRoleEvent(uuidMock(0), "A", Role.ADMIN); + + Group group = apply(createEvent, addEvent, updateEvent); + + assertThat(group.getRoles().get("A")).isEqualTo(Role.ADMIN); + } + + @Test + void applyEvent_userNotFound() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event addEvent = addUserEvent(uuidMock(0), "A"); + Event updateEvent = new UpdateRoleEvent(uuidMock(0), "B", Role.ADMIN); + + Group group = apply(createEvent, addEvent); + + assertThrows(UserNotFoundException.class, () -> updateEvent.apply(group)); + assertThat(group.getRoles().get("A")).isEqualTo(Role.MEMBER); + } +} diff --git a/src/test/java/mops/gruppen2/domain/event/UpdateUserMaxEventTest.java b/src/test/java/mops/gruppen2/domain/event/UpdateUserMaxEventTest.java new file mode 100644 index 0000000..b9e741f --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/UpdateUserMaxEventTest.java @@ -0,0 +1,49 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.domain.Group; +import mops.gruppen2.domain.exception.BadParameterException; +import org.junit.jupiter.api.Test; + +import static mops.gruppen2.TestBuilder.addUserEvent; +import static mops.gruppen2.TestBuilder.apply; +import static mops.gruppen2.TestBuilder.createPublicGroupEvent; +import static mops.gruppen2.TestBuilder.uuidMock; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UpdateUserMaxEventTest { + + @Test + void applyEvent() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEvent = new UpdateUserMaxEvent(uuidMock(0), "A", 5L); + + Group group = apply(createEvent, updateEvent); + + assertThat(group.getUserMaximum()).isEqualTo(5); + } + + @Test + void applyEvent_badParameter_negative() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEvent = new UpdateUserMaxEvent(uuidMock(0), "A", -5L); + + Group group = apply(createEvent); + + assertThrows(BadParameterException.class, () -> updateEvent.apply(group)); + } + + @Test + void applyEvent_badParameter_tooSmall() { + Event createEvent = createPublicGroupEvent(uuidMock(0)); + Event updateEventA = new UpdateUserMaxEvent(uuidMock(0), "A", 5L); + Event addEventA = addUserEvent(uuidMock(0)); + Event addEventB = addUserEvent(uuidMock(0)); + Event addEventC = addUserEvent(uuidMock(0)); + Event updateEventB = new UpdateUserMaxEvent(uuidMock(0), "A", 2L); + + Group group = apply(createEvent, updateEventA, addEventA, addEventB, addEventC); + + assertThrows(BadParameterException.class, () -> updateEventB.apply(group)); + } +} diff --git a/src/test/java/mops/gruppen2/service/ControllerServiceTest.java b/src/test/java/mops/gruppen2/service/ControllerServiceTest.java index 75200e6..9cfc762 100644 --- a/src/test/java/mops/gruppen2/service/ControllerServiceTest.java +++ b/src/test/java/mops/gruppen2/service/ControllerServiceTest.java @@ -1,14 +1,14 @@ package mops.gruppen2.service; import mops.gruppen2.Gruppen2Application; -import mops.gruppen2.domain.User; +import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Group; -import mops.gruppen2.domain.Role; -import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.GroupType; +import mops.gruppen2.domain.Role; +import mops.gruppen2.domain.User; +import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.repository.EventRepository; -import mops.gruppen2.security.Account; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -33,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Transactional @Rollback class ControllerServiceTest { + Account account; Account account2; Account account3; @@ -44,13 +45,11 @@ class ControllerServiceTest { EventRepository eventRepository; GroupService groupService; @Autowired - JsonService jsonService; - @Autowired InviteService inviteService; @BeforeEach void setUp() { - eventService = new EventService(jsonService, eventRepository); + eventService = new EventService(eventRepository); groupService = new GroupService(eventService, eventRepository); userService = new UserService(groupService, eventService); validationService = new ValidationService(userService, groupService); @@ -136,7 +135,7 @@ class ControllerServiceTest { void createPublicGroupWithParentAndUnlimitedNumberTest() throws IOException { controllerService.createGroupAsOrga(account2, "test", "hi", null, null, true, null, null, null); List groups1 = userService.getUserGroups(new User(account2.getName(), account2.getGivenname(), account2.getFamilyname(), account2.getEmail())); - controllerService.createGroup(account, "test", "hi", null, true, true, null,groups1.get(0).getId()); + controllerService.createGroup(account, "test", "hi", null, true, true, null, groups1.get(0).getId()); List groups = userService.getUserGroups(new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail())); testTitleAndDescription(groups.get(0).getTitle(), groups.get(0).getDescription()); assertEquals(Visibility.PUBLIC, groups.get(0).getVisibility()); diff --git a/src/test/java/mops/gruppen2/service/EventServiceTest.java b/src/test/java/mops/gruppen2/service/EventServiceTest.java index 540e854..43e105c 100644 --- a/src/test/java/mops/gruppen2/service/EventServiceTest.java +++ b/src/test/java/mops/gruppen2/service/EventServiceTest.java @@ -5,26 +5,23 @@ import mops.gruppen2.domain.dto.EventDTO; import mops.gruppen2.domain.event.Event; import mops.gruppen2.repository.EventRepository; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; import static mops.gruppen2.TestBuilder.addUserEvent; import static mops.gruppen2.TestBuilder.addUserEvents; -import static mops.gruppen2.TestBuilder.createPrivateGroupEvent; import static mops.gruppen2.TestBuilder.createPrivateGroupEvents; import static mops.gruppen2.TestBuilder.createPublicGroupEvent; import static mops.gruppen2.TestBuilder.createPublicGroupEvents; -import static mops.gruppen2.TestBuilder.updateGroupDescriptionEvent; -import static mops.gruppen2.TestBuilder.uuidFromInt; +import static mops.gruppen2.TestBuilder.uuidMock; import static org.assertj.core.api.Assertions.assertThat; -//TODO: Der ID autocounter wird nicht resettet -> Tests schlagen fehl beim nacheinanderausführen @ExtendWith(SpringExtension.class) @SpringBootTest(classes = Gruppen2Application.class) @Transactional @@ -33,14 +30,16 @@ class EventServiceTest { @Autowired private EventRepository eventRepository; - @Autowired - private JsonService jsonService; private EventService eventService; + @Autowired + private JdbcTemplate template; @BeforeEach void setUp() { - eventService = new EventService(jsonService, eventRepository); + eventService = new EventService(eventRepository); eventRepository.deleteAll(); + //noinspection SqlResolve + template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1"); } @Test @@ -79,20 +78,20 @@ class EventServiceTest { @Test void getEventsOfGroup() { - eventService.saveAll(addUserEvents(10, uuidFromInt(0)), - addUserEvents(5, uuidFromInt(1))); + eventService.saveAll(addUserEvents(10, uuidMock(0)), + addUserEvents(5, uuidMock(1))); - assertThat(eventService.getEventsOfGroup(uuidFromInt(0))).hasSize(10); - assertThat(eventService.getEventsOfGroup(uuidFromInt(1))).hasSize(5); + assertThat(eventService.getEventsOfGroup(uuidMock(0))).hasSize(10); + assertThat(eventService.getEventsOfGroup(uuidMock(1))).hasSize(5); } @Test void findGroupIdsByUser() { - eventService.saveAll(addUserEvent(uuidFromInt(0), "A"), - addUserEvent(uuidFromInt(1), "A"), - addUserEvent(uuidFromInt(2), "A"), - addUserEvent(uuidFromInt(3), "A"), - addUserEvent(uuidFromInt(3), "B")); + eventService.saveAll(addUserEvent(uuidMock(0), "A"), + addUserEvent(uuidMock(1), "A"), + addUserEvent(uuidMock(2), "A"), + addUserEvent(uuidMock(3), "A"), + addUserEvent(uuidMock(3), "B")); assertThat(eventService.findGroupIdsByUser("A")).hasSize(4); assertThat(eventService.findGroupIdsByUser("B")).hasSize(1); diff --git a/src/test/java/mops/gruppen2/service/GroupServiceTest.java b/src/test/java/mops/gruppen2/service/GroupServiceTest.java index 3101bf0..488a22b 100644 --- a/src/test/java/mops/gruppen2/service/GroupServiceTest.java +++ b/src/test/java/mops/gruppen2/service/GroupServiceTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.transaction.annotation.Transactional; @@ -30,7 +31,7 @@ import static mops.gruppen2.TestBuilder.createPublicGroupEvent; import static mops.gruppen2.TestBuilder.deleteGroupEvent; import static mops.gruppen2.TestBuilder.updateGroupDescriptionEvent; import static mops.gruppen2.TestBuilder.updateGroupTitleEvent; -import static mops.gruppen2.TestBuilder.uuidFromInt; +import static mops.gruppen2.TestBuilder.uuidMock; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(SpringExtension.class) @@ -44,20 +45,20 @@ class GroupServiceTest { @Autowired private EventService eventService; private GroupService groupService; + @Autowired + private JdbcTemplate template; @BeforeEach void setUp() { groupService = new GroupService(eventService, eventRepository); eventRepository.deleteAll(); + //noinspection SqlResolve + template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1"); } //TODO: Wofür ist dieser Test? @Test void rightClassForSuccessfulGroup() { - /*List eventList = new ArrayList<>(); - UUID id = UUID.randomUUID(); - eventList.add(new CreateGroupEvent(id, "Prof", null, GroupType.LECTURE, Visibility.PRIVATE, 1000L)); - eventList.add(new AddUserEvent(id, "Ulli", "Ulli", "Honnis", "FC@B.de"));*/ List eventList = completePrivateGroup(1); List groups = groupService.projectEventList(eventList); @@ -88,30 +89,21 @@ class GroupServiceTest { @Test void getGroupEvents() { - //CreateGroupEvent test1 = new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L); - //CreateGroupEvent test2 = new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.SIMPLE, Visibility.PUBLIC, 10L); + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + createPublicGroupEvent(uuidMock(1)), + createPrivateGroupEvent(uuidMock(2))); - eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), - createPublicGroupEvent(uuidFromInt(1)), - createPrivateGroupEvent(uuidFromInt(2))); - - List groupIds = Arrays.asList(uuidFromInt(0), uuidFromInt(1)); + List groupIds = Arrays.asList(uuidMock(0), uuidMock(1)); assertThat(groupService.getGroupEvents(groupIds)).hasSize(2); - assertThat(groupService.getGroupEvents(groupIds).get(0).getGroupId()).isEqualTo(uuidFromInt(0)); - assertThat(groupService.getGroupEvents(groupIds).get(1).getGroupId()).isEqualTo(uuidFromInt(1)); + assertThat(groupService.getGroupEvents(groupIds).get(0).getGroupId()).isEqualTo(uuidMock(0)); + assertThat(groupService.getGroupEvents(groupIds).get(1).getGroupId()).isEqualTo(uuidMock(1)); } @Test void getAllGroupWithVisibilityPublicTestCreateAndDeleteSameGroup() { - //CreateGroupEvent test1 = new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L); - //DeleteGroupEvent test2 = new DeleteGroupEvent(uuidFromInt(0), "test1"); - Event test1 = createPublicGroupEvent(uuidFromInt(0)); - Event test2 = deleteGroupEvent(uuidFromInt(0)); - - //Group group = new Group(); - //test1.apply(group); - //test2.apply(group); + Event test1 = createPublicGroupEvent(uuidMock(0)); + Event test2 = deleteGroupEvent(uuidMock(0)); //TODO: Hier projectEventlist()? Group group = TestBuilder.apply(test1, test2); @@ -122,50 +114,31 @@ class GroupServiceTest { @Test void getAllGroupWithVisibilityPublicTestGroupPublic() { - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); - //eventService.saveEvent(new DeleteGroupEvent(uuidFromInt(0), "test1")); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(1), "test2", Role.MEMBER)); //Wofür ist das - - eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), - deleteGroupEvent(uuidFromInt(0)), - createPublicGroupEvent()); + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + deleteGroupEvent(uuidMock(0)), + createPublicGroupEvent()); assertThat(groupService.getAllGroupWithVisibilityPublic("test1").size()).isEqualTo(1); } @Test void getAllGroupWithVisibilityPublicTestAddSomeEvents() { - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); - //eventService.saveEvent(new DeleteGroupEvent(uuidFromInt(0), "test1")); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(1), "test2", Role.MEMBER)); // Wofür? - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(2), "test3", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(3), "test4", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(4), "test5", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - - eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), - deleteGroupEvent(uuidFromInt(0)), - createPublicGroupEvent(), - createPublicGroupEvent(), - createPublicGroupEvent(), - createPrivateGroupEvent()); + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + deleteGroupEvent(uuidMock(0)), + createPublicGroupEvent(), + createPublicGroupEvent(), + createPublicGroupEvent(), + createPrivateGroupEvent()); assertThat(groupService.getAllGroupWithVisibilityPublic("test1").size()).isEqualTo(3); } @Test void getAllGroupWithVisibilityPublic_UserInGroup() { - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); - //eventService.saveEvent(new AddUserEvent(uuidFromInt(0), "test1", "test", "test", "test@test")); - - eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), - addUserEvent(uuidFromInt(0), "kobold"), - createPrivateGroupEvent(), - createPublicGroupEvent()); - - //Das kommt glaube ich eher in einen Test für die Projektion - //assertThat(groupService.getAllGroupWithVisibilityPublic("test2").get(0).getMembers().size()).isEqualTo(1); + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + addUserEvent(uuidMock(0), "kobold"), + createPrivateGroupEvent(), + createPublicGroupEvent()); assertThat(groupService.getAllGroupWithVisibilityPublic("kobold")).hasSize(1); assertThat(groupService.getAllGroupWithVisibilityPublic("peter")).hasSize(2); @@ -173,56 +146,42 @@ class GroupServiceTest { @Test void getAllLecturesWithVisibilityPublic() { - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(1), "test2", Role.MEMBER)); // Hä - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(2), "test3", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(3), "test4", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(4), "test5", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); - eventService.saveAll(createLectureEvent(), - createPublicGroupEvent(), - createLectureEvent(), - createLectureEvent(), - createLectureEvent()); + createPublicGroupEvent(), + createLectureEvent(), + createLectureEvent(), + createLectureEvent()); assertThat(groupService.getAllLecturesWithVisibilityPublic().size()).isEqualTo(4); } @Test void findGroupWith_UserMember_AllGroups() { - //eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); - //eventService.saveEvent(new AddUserEvent(uuidFromInt(0), "test1", "test", "test", "test@test")); - //eventService.saveEvent(new UpdateGroupTitleEvent(uuidFromInt(0), "test1", "TestGroup")); - //eventService.saveEvent(new UpdateGroupDescriptionEvent(uuidFromInt(0), "test1", "TestDescription")); - //eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(0), "test1", Role.MEMBER)); + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + addUserEvent(uuidMock(0), "jens"), + updateGroupTitleEvent(uuidMock(0)), + updateGroupDescriptionEvent(uuidMock(0))); - eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), - addUserEvent(uuidFromInt(0), "jens"), - updateGroupTitleEvent(uuidFromInt(0)), - updateGroupDescriptionEvent(uuidFromInt(0))); - - //assertThat(groupService.findGroupWith("T", new Account("jens", "a@A", "test", "peter", "mueller", null)).size()).isEqualTo(1); assertThat(groupService.findGroupWith("", account("jens"))).isEmpty(); } @Test void findGroupWith_UserNoMember_AllGroups() { eventService.saveAll(completePublicGroups(10, 0), - completePrivateGroups(10, 0)); + completePrivateGroups(10, 0)); assertThat(groupService.findGroupWith("", account("jens"))).hasSize(10); } @Test void findGroupWith_FilterGroups() { - eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), - updateGroupTitleEvent(uuidFromInt(0), "KK"), - updateGroupDescriptionEvent(uuidFromInt(0), "ABCDE"), - createPublicGroupEvent(uuidFromInt(1)), - updateGroupTitleEvent(uuidFromInt(1), "ABCDEFG"), - updateGroupDescriptionEvent(uuidFromInt(1), "KK"), - createPrivateGroupEvent()); + eventService.saveAll(createPublicGroupEvent(uuidMock(0)), + updateGroupTitleEvent(uuidMock(0), "KK"), + updateGroupDescriptionEvent(uuidMock(0), "ABCDE"), + createPublicGroupEvent(uuidMock(1)), + updateGroupTitleEvent(uuidMock(1), "ABCDEFG"), + updateGroupDescriptionEvent(uuidMock(1), "KK"), + createPrivateGroupEvent()); assertThat(groupService.findGroupWith("A", account("jesus"))).hasSize(2); assertThat(groupService.findGroupWith("F", account("jesus"))).hasSize(1);