1

Merge pull request #1 from hhu-propra2/master

update
This commit is contained in:
Christoph
2020-04-05 22:10:50 +02:00
committed by GitHub
64 changed files with 1814 additions and 1213 deletions

View File

@ -4,13 +4,18 @@ on:
push: push:
branches: branches:
- master - master
- dev
pull_request: pull_request:
branches: branches:
- master - master
- dev
paths-ignore: paths-ignore:
- 'documentation/**' - 'documentation/**'
- 'mysql/**'
- 'README.adoc' - 'README.adoc'
- 'Dockerfile' - 'Dockerfile'
- 'docker-compose.yaml'
- '.gitignore'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -1,10 +1,17 @@
= Gruppenbildung = 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 === 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 === Ziele
@ -36,7 +43,8 @@ Die Gruppenverwaltung wird bieten:
Über *Mitglied* (interne Rolle): Ü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): Für *Organisatoren* (keycloak Rolle):
@ -62,3 +70,6 @@ Für *Studenten* (keycloak Rolle) :
=== Verwendung === Verwendung
Die Anwendung kann mit `docker-compse up` im Wurzelverzeichnis gestartet werden, eine API-Doku befindet sich im Dokumentation-Ordner (das swagger-zip). 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`

View File

@ -1,90 +1,103 @@
import com.github.spotbugs.SpotBugsTask import com.github.spotbugs.SpotBugsTask
plugins { plugins {
id 'org.springframework.boot' version '2.2.5.RELEASE' id 'org.springframework.boot' version '2.2.5.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE' id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java' id 'java'
id 'com.github.spotbugs' version '3.0.0' id 'com.github.spotbugs' version '3.0.0'
id 'checkstyle' id 'checkstyle'
id 'pmd'
} }
group = 'mops' group = 'mops'
version = '0.0.1-SNAPSHOT' version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11' sourceCompatibility = '11'
spotbugs{ spotbugs {
ignoreFailures = true ignoreFailures = false
reportLevel = "high" reportLevel = "high"
effort = "max" effort = "max"
toolVersion = '4.0.0-RC1' toolVersion = '4.0.0-RC1'
} }
tasks.withType(SpotBugsTask) { tasks.withType(SpotBugsTask) {
reports { reports {
xml.enabled = false xml.enabled = false
html.enabled = true 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 { checkstyle {
toolVersion = "8.28" toolVersion = "8.28"
configFile = file("${rootDir}/config/checkstyle/checkstyle.xml") configFile = file("${rootDir}/config/checkstyle/checkstyle.xml")
ignoreFailures = true ignoreFailures = true
} }
configurations { configurations {
developmentOnly developmentOnly
runtimeClasspath { runtimeClasspath {
extendsFrom developmentOnly extendsFrom developmentOnly
} }
compileOnly { compileOnly {
extendsFrom annotationProcessor extendsFrom annotationProcessor
} }
} }
repositories { repositories {
maven { maven {
url = 'https://s3.cs.hhu.de/public/mops/' url = 'https://s3.cs.hhu.de/public/mops/'
metadataSources { metadataSources {
artifact() artifact()
} }
} }
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.security.oauth:spring-security-oauth2:2.4.0.RELEASE' 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:keycloak-spring-boot-starter:9.0.0'
implementation 'org.keycloak.bom:keycloak-adapter-bom:9.0.0' implementation 'org.keycloak.bom:keycloak-adapter-bom:9.0.0'
implementation 'mops:styleguide:2.1.0' implementation 'mops:styleguide:2.1.0'
implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger2:2.9.2'
implementation 'io.springfox:springfox-swagger-ui:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2'
implementation 'com.github.javafaker:javafaker:1.0.2' implementation 'com.github.javafaker:javafaker:1.0.2'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.10.3' implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.10.3'
compileOnly 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools' developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2' runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java' runtimeOnly 'mysql:mysql-connector-java'
testImplementation 'org.assertj:assertj-core:3.15.0' testImplementation 'org.assertj:assertj-core:3.15.0'
testImplementation('org.springframework.boot:spring-boot-starter-test') { testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
} }
testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'com.tngtech.archunit:archunit-junit5:0.13.1' testImplementation 'com.tngtech.archunit:archunit-junit5:0.13.1'
} }
test { test {
useJUnitPlatform() useJUnitPlatform()
} }

View File

@ -226,7 +226,7 @@
<property name="lineWrappingIndentation" value="8"/> <property name="lineWrappingIndentation" value="8"/>
<property name="arrayInitIndent" value="4"/> <property name="arrayInitIndent" value="4"/>
</module> </module>
<module name="VariableDeclarationUsageDistance"/> <!-- <module name="VariableDeclarationUsageDistance"/>-->
<module name="MethodParamPad"> <module name="MethodParamPad">
<property name="tokens" <property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF, value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,

View File

@ -1,17 +0,0 @@
package mops.gruppen2.config;
import mops.gruppen2.service.EventService;
import mops.gruppen2.service.GroupService;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Gruppen2Config {
final GroupService groupService;
final EventService eventService;
public Gruppen2Config(GroupService groupService, EventService eventService) {
this.groupService = groupService;
this.eventService = eventService;
}
}

View File

@ -1,4 +1,4 @@
package mops.gruppen2.security; package mops.gruppen2.config;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
@ -42,4 +42,4 @@ public class KeycloakConfig {
return new OAuth2RestTemplate(resourceDetails); return new OAuth2RestTemplate(resourceDetails);
} }
} }

View File

@ -1,4 +1,4 @@
package mops.gruppen2.security; package mops.gruppen2.config;
import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents; import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
@ -33,8 +33,7 @@ class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) { public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
= keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider); auth.authenticationProvider(keycloakAuthenticationProvider);
} }
@ -42,28 +41,26 @@ class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Bean @Bean
@Override @Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy( return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
new SessionRegistryImpl());
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken getAccessToken() {
HttpServletRequest request =
((ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes()).getRequest();
return ((KeycloakPrincipal) request.getUserPrincipal())
.getKeycloakSecurityContext().getToken();
} }
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
super.configure(http); super.configure(http);
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/actuator/**") .antMatchers("/actuator/**")
.hasRole("monitoring") .hasRole("monitoring")
.anyRequest() .anyRequest()
.permitAll(); .permitAll();
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken getAccessToken() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes()).getRequest();
return ((KeycloakPrincipal) request.getUserPrincipal())
.getKeycloakSecurityContext().getToken();
} }
/** /**

View File

@ -22,8 +22,9 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
* Ein Beispiel für eine API mit Swagger. * Api zum Datenabgleich mit Gruppenfindung.
*/ */
//TODO: API-Service?
@RestController @RestController
@RequestMapping("/gruppen2/api") @RequestMapping("/gruppen2/api")
public class APIController { public class APIController {
@ -38,20 +39,20 @@ public class APIController {
this.userService = userService; this.userService = userService;
} }
@GetMapping("/updateGroups/{status}") @GetMapping("/updateGroups/{lastEventId}")
@Secured("ROLE_api_user") @Secured("ROLE_api_user")
@ApiOperation("Gibt alle Gruppen zurück in denen sich etwas geändert hat") @ApiOperation("Gibt alle Gruppen zurück, in denen sich etwas geändert hat")
public GroupRequestWrapper updateGroup(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long status) throws EventException { public GroupRequestWrapper updateGroups(@ApiParam("Letzter Status des Anfragestellers") @PathVariable Long lastEventId) throws EventException {
List<Event> events = eventService.getNewEvents(status); List<Event> 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") @Secured("ROLE_api_user")
@ApiOperation("Gibt alle Gruppen zurück in denen sich ein Teilnehmer befindet") @ApiOperation("Gibt alle Gruppen zurück, in denen sich ein Teilnehmer befindet")
public List<String> getGroupsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String teilnehmer) { public List<String> getGroupIdsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") @PathVariable String userId) {
return userService.getUserGroups(teilnehmer).stream() return userService.getUserGroups(userId).stream()
.map(group -> group.getId().toString()) .map(group -> group.getId().toString())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@ -59,10 +60,14 @@ public class APIController {
@GetMapping("/getGroup/{groupId}") @GetMapping("/getGroup/{groupId}")
@Secured("ROLE_api_user") @Secured("ROLE_api_user")
@ApiOperation("Gibt die Gruppe mit der als Parameter mitgegebenden groupId zurück") @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<Event> eventList = eventService.getEventsOfGroup(UUID.fromString(groupId)); List<Event> eventList = eventService.getEventsOfGroup(UUID.fromString(groupId));
List<Group> groups = groupService.projectEventList(eventList); List<Group> groups = groupService.projectEventList(eventList);
if (groups.isEmpty()) {
return null;
}
return groups.get(0); return groups.get(0);
} }

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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<Group> 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;
}
}

View File

@ -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<Group> 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");
}
}

View File

@ -1,4 +1,4 @@
package mops.gruppen2.security; package mops.gruppen2.domain;
import lombok.Value; import lombok.Value;

View File

@ -16,6 +16,7 @@ import java.util.UUID;
@Setter @Setter
public class Group { public class Group {
//TODO: List to Hashmap
private final List<User> members; private final List<User> members;
private final Map<String, Role> roles; private final Map<String, Role> roles;
private UUID id; private UUID id;
@ -27,8 +28,8 @@ public class Group {
private UUID parent; private UUID parent;
public Group() { public Group() {
this.members = new ArrayList<>(); members = new ArrayList<>();
this.roles = new HashMap<>(); roles = new HashMap<>();
} }
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.domain; package mops.gruppen2.domain;
public enum GroupType { public enum GroupType {
SIMPLE, LECTURE SIMPLE,
LECTURE
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.domain; package mops.gruppen2.domain;
public enum Role { public enum Role {
ADMIN, MEMBER ADMIN,
MEMBER
} }

View File

@ -15,4 +15,11 @@ public class User {
private String givenname; private String givenname;
private String familyname; private String familyname;
private String email; private String email;
public User(Account account) {
id = account.getName();
givenname = account.getGivenname();
familyname = account.getFamilyname();
email = account.getEmail();
}
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.domain; package mops.gruppen2.domain;
public enum Visibility { public enum Visibility {
PUBLIC, PRIVATE PUBLIC,
PRIVATE
} }

View File

@ -1,6 +1,5 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
@ -16,7 +15,6 @@ import java.util.UUID;
* Fügt einen einzelnen Nutzer einer Gruppe hinzu. * Fügt einen einzelnen Nutzer einer Gruppe hinzu.
*/ */
@Getter @Getter
@AllArgsConstructor
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
public class AddUserEvent extends Event { public class AddUserEvent extends Event {
@ -33,14 +31,14 @@ public class AddUserEvent extends Event {
@Override @Override
protected void applyEvent(Group group) throws EventException { 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)) { if (group.getMembers().contains(user)) {
throw new UserAlreadyExistsException(this.getClass().toString()); throw new UserAlreadyExistsException(getClass().toString());
} }
if (group.getMembers().size() >= group.getUserMaximum()) { if (group.getMembers().size() >= group.getUserMaximum()) {
throw new GroupFullException(this.getClass().toString()); throw new GroupFullException(getClass().toString());
} }
group.getMembers().add(user); group.getMembers().add(user);

View File

@ -1,6 +1,5 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
@ -10,7 +9,6 @@ import mops.gruppen2.domain.Visibility;
import java.util.UUID; import java.util.UUID;
@Getter @Getter
@AllArgsConstructor
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
public class CreateGroupEvent extends Event { 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) { public CreateGroupEvent(UUID groupId, String userId, UUID parent, GroupType type, Visibility visibility, Long userMaximum) {
super(groupId, userId); super(groupId, userId);
this.groupParent = parent; groupParent = parent;
this.groupType = type; groupType = type;
this.groupVisibility = visibility; groupVisibility = visibility;
this.groupUserMaximum = userMaximum; groupUserMaximum = userMaximum;
} }
@Override @Override
protected void applyEvent(Group group) { protected void applyEvent(Group group) {
group.setId(this.groupId); group.setId(groupId);
group.setParent(this.groupParent); group.setParent(groupParent);
group.setType(this.groupType); group.setType(groupType);
group.setVisibility(this.groupVisibility); group.setVisibility(groupVisibility);
group.setUserMaximum(this.groupUserMaximum); group.setUserMaximum(groupUserMaximum);
} }
} }

View File

@ -23,5 +23,6 @@ public class DeleteGroupEvent extends Event {
group.setVisibility(null); group.setVisibility(null);
group.setType(null); group.setType(null);
group.setParent(null); group.setParent(null);
group.setUserMaximum(0L);
} }
} }

View File

@ -39,13 +39,13 @@ public abstract class Event {
applyEvent(group); applyEvent(group);
} }
protected abstract void applyEvent(Group group) throws EventException;
private void checkGroupIdMatch(UUID groupId) { private void checkGroupIdMatch(UUID groupId) {
if (groupId == null || this.groupId.equals(groupId)) { if (groupId == null || this.groupId.equals(groupId)) {
return; return;
} }
throw new GroupIdMismatchException(this.getClass().toString()); throw new GroupIdMismatchException(getClass().toString());
} }
protected abstract void applyEvent(Group group) throws EventException;
} }

View File

@ -1,10 +1,9 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.exception.NoValueException; import mops.gruppen2.domain.exception.BadParameterException;
import java.util.UUID; import java.util.UUID;
@ -12,7 +11,6 @@ import java.util.UUID;
* Ändert nur die Gruppenbeschreibung. * Ändert nur die Gruppenbeschreibung.
*/ */
@Getter @Getter
@AllArgsConstructor
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
public class UpdateGroupDescriptionEvent extends Event { public class UpdateGroupDescriptionEvent extends Event {
@ -25,10 +23,10 @@ public class UpdateGroupDescriptionEvent extends Event {
@Override @Override
protected void applyEvent(Group group) { protected void applyEvent(Group group) {
if (this.newGroupDescription.isEmpty()) { if (newGroupDescription.isEmpty()) {
throw new NoValueException(this.getClass().toString()); throw new BadParameterException("Die Beschreibung ist leer.");
} }
group.setDescription(this.newGroupDescription); group.setDescription(newGroupDescription);
} }
} }

View File

@ -1,10 +1,9 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.exception.NoValueException; import mops.gruppen2.domain.exception.BadParameterException;
import java.util.UUID; import java.util.UUID;
@ -12,7 +11,6 @@ import java.util.UUID;
* Ändert nur den Gruppentitel. * Ändert nur den Gruppentitel.
*/ */
@Getter @Getter
@AllArgsConstructor
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
public class UpdateGroupTitleEvent extends Event { public class UpdateGroupTitleEvent extends Event {
@ -25,11 +23,11 @@ public class UpdateGroupTitleEvent extends Event {
@Override @Override
protected void applyEvent(Group group) { protected void applyEvent(Group group) {
if (this.getNewGroupTitle().isEmpty()) { if (newGroupTitle.isEmpty()) {
throw new NoValueException(this.getClass().toString()); throw new BadParameterException("Der Titel ist leer.");
} }
group.setTitle(this.newGroupTitle); group.setTitle(newGroupTitle);
} }
} }

View File

@ -1,6 +1,5 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
@ -13,7 +12,6 @@ import java.util.UUID;
* Aktualisiert die Gruppenrolle eines Teilnehmers. * Aktualisiert die Gruppenrolle eines Teilnehmers.
*/ */
@Getter @Getter
@AllArgsConstructor
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
public class UpdateRoleEvent extends Event { public class UpdateRoleEvent extends Event {
@ -26,12 +24,12 @@ public class UpdateRoleEvent extends Event {
@Override @Override
protected void applyEvent(Group group) throws UserNotFoundException { protected void applyEvent(Group group) throws UserNotFoundException {
if (group.getRoles().containsKey(this.userId)) { if (group.getRoles().containsKey(userId)) {
group.getRoles().put(this.userId, this.newRole); group.getRoles().put(userId, newRole);
return; return;
} }
throw new UserNotFoundException(this.getClass().toString()); throw new UserNotFoundException(getClass().toString());
} }
} }

View File

@ -1,19 +1,18 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.exception.BadParameterException;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import java.util.UUID; import java.util.UUID;
@Getter @Getter
@AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class UpdateUserMaxEvent extends Event { public class UpdateUserMaxEvent extends Event {
private Long userMaximum; private Long userMaximum;
public UpdateUserMaxEvent(UUID groupId, String userId, Long userMaximum) { public UpdateUserMaxEvent(UUID groupId, String userId, Long userMaximum) {
super(groupId, userId); super(groupId, userId);
@ -22,6 +21,10 @@ public class UpdateUserMaxEvent extends Event {
@Override @Override
protected void applyEvent(Group group) throws EventException { 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);
} }
} }

View File

@ -3,7 +3,7 @@ package mops.gruppen2.domain.exception;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException; 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) { public EventException(HttpStatus status, String msg, String info) {
super(status, msg + " (" + info + ")"); super(status, msg + " (" + info + ")");

View File

@ -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);
}
}

View File

@ -3,6 +3,7 @@ package mops.gruppen2.domain.exception;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
public class WrongFileException extends EventException { public class WrongFileException extends EventException {
public WrongFileException(String info) { public WrongFileException(String info) {
super(HttpStatus.BAD_REQUEST, "Die entsprechende Datei ist keine valide CSV-Datei!", info); super(HttpStatus.BAD_REQUEST, "Die entsprechende Datei ist keine valide CSV-Datei!", info);
} }

View File

@ -29,7 +29,7 @@ public interface EventRepository extends CrudRepository<EventDTO, Long> {
@Query("SELECT * FROM event WHERE event_type = :type") @Query("SELECT * FROM event WHERE event_type = :type")
List<EventDTO> findAllEventsByType(@Param("type") String type); List<EventDTO> 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<EventDTO> findEventsByTypeAndUserId(@Param("type") String type, @Param("userId") String userId); List<EventDTO> findEventsByTypeAndUserId(@Param("type") String type, @Param("userId") String userId);
@Query("SELECT COUNT(*) FROM event WHERE event_type = :type AND group_id = :groupId") @Query("SELECT COUNT(*) FROM event WHERE event_type = :type AND group_id = :groupId")

View File

@ -7,9 +7,11 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@Service @Service
public class APIFormatterService { public final class APIFormatterService {
public static GroupRequestWrapper wrap(Long status, List<Group> groupList) { private APIFormatterService() {}
public static GroupRequestWrapper wrap(long status, List<Group> groupList) {
return new GroupRequestWrapper(status, groupList); return new GroupRequestWrapper(status, groupList);
} }
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.Role; 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.UpdateRoleEvent;
import mops.gruppen2.domain.event.UpdateUserMaxEvent; import mops.gruppen2.domain.event.UpdateUserMaxEvent;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.UserNotFoundException;
import mops.gruppen2.domain.exception.WrongFileException; 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.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static mops.gruppen2.domain.Role.ADMIN; import static mops.gruppen2.domain.Role.ADMIN;
@ -34,30 +34,115 @@ import static mops.gruppen2.domain.Role.ADMIN;
@Service @Service
public class ControllerService { public class ControllerService {
private static final Logger LOG = LoggerFactory.getLogger("controllerServiceLogger");
private final EventService eventService; private final EventService eventService;
private final UserService userService; private final UserService userService;
private final ValidationService validationService; private final ValidationService validationService;
private final InviteService inviteService; private final InviteService inviteService;
private final Logger logger;
public ControllerService(EventService eventService, UserService userService, ValidationService validationService, InviteService inviteService) { public ControllerService(EventService eventService, UserService userService, ValidationService validationService, InviteService inviteService) {
this.eventService = eventService; this.eventService = eventService;
this.userService = userService; this.userService = userService;
this.validationService = validationService; this.validationService = validationService;
this.inviteService = inviteService; this.inviteService = inviteService;
this.logger = Logger.getLogger("controllerServiceLogger"); }
private static User getVeteranMember(Account account, Group group) {
List<User> 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<User> newUsers = readCsvFile(file);
List<User> 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. * 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. * 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 account Keycloak-Account
* @param title Gruppentitel * @param title Gruppentitel
* @param description Gruppenbeschreibung * @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); userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum);
Visibility groupVisibility = setGroupVisibility(isVisibilityPrivate); Visibility groupVisibility = setGroupVisibility(isVisibilityPrivate);
@ -65,7 +150,12 @@ public class ControllerService {
GroupType groupType = setGroupType(isLecture); 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); eventService.saveEvent(createGroupEvent);
inviteService.createLink(groupId); inviteService.createLink(groupId);
@ -80,38 +170,95 @@ public class ControllerService {
return groupId; return groupId;
} }
/** private static List<User> readCsvFile(MultipartFile file) throws EventException {
* Wie createGroup, nur das hier die Gruppe auch als Veranstaltung gesetzt werden kann und CSV Dateien mit Nutzern if (file == null) {
* eingelesen werden können. return new ArrayList<>();
* @param account Der Nutzer der die Gruppe erstellt }
* @param title Parameter für die neue Gruppe if (!file.isEmpty()) {
* @param description Parameter für die neue Gruppe try {
* @param isVisibilityPrivate Parameter für die neue Gruppe List<User> userList = CsvService.read(file.getInputStream());
* @param isLecture Parameter für die neue Gruppe return userList.stream().distinct().collect(Collectors.toList()); //filters duplicates from list
* @param isMaximumInfinite Parameter für die neue Gruppe } catch (IOException ex) {
* @param userMaximum Parameter für die neue Gruppe LOG.warn("File konnte nicht gelesen werden");
* @param parent Parameter für die neue Gruppe throw new WrongFileException(file.getOriginalFilename());
* @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) { return new ArrayList<>();
userMaximum = checkInfiniteUsers(isMaximumInfinite, userMaximum);
List<User> newUsers = readCsvFile(file);
List<User> 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);
} }
public void addUsersFromCsv(Account account, MultipartFile file, String groupId) throws IOException{ private static void removeOldUsersFromNewUsers(List<User> oldUsers, List<User> 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<User> 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)); Group group = userService.getGroupById(UUID.fromString(groupId));
List<User> newUserList = readCsvFile(file); List<User> newUserList = readCsvFile(file);
@ -120,15 +267,24 @@ public class ControllerService {
UUID groupUUID = getUUID(groupId); UUID groupUUID = getUUID(groupId);
Long newUserMaximum = adjustUserMaximum((long) newUserList.size(), (long) group.getMembers().size(), group.getUserMaximum()); Long newUserMaximum = adjustUserMaximum((long) newUserList.size(), (long) group.getMembers().size(), group.getUserMaximum());
if (newUserMaximum > group.getUserMaximum()){ if (newUserMaximum > group.getUserMaximum()) {
updateMaxUser(account, groupUUID, newUserMaximum); updateMaxUser(account, groupUUID, newUserMaximum);
} }
addUserList(newUserList, groupUUID); 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) { 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); updateTitle(account, group.getId(), title);
} }
@ -145,114 +301,6 @@ public class ControllerService {
return parent; return parent;
} }
private void removeOldUsersFromNewUsers(List<User> oldUsers, List<User> 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<User> readCsvFile(MultipartFile file) throws EventException{
if(file == null) return new ArrayList<>();
if (!file.isEmpty()) {
try {
List<User> 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<User> 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 { public void deleteUser(Account account, User user, Group group) throws EventException {
changeRoleIfLastAdmin(account, group); 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) { private void deleteUserEvent(User user, UUID groupId) {
DeleteUserEvent deleteUserEvent = new DeleteUserEvent(groupId, user.getId()); DeleteUserEvent deleteUserEvent = new DeleteUserEvent(groupId, user.getId());
eventService.saveEvent(deleteUserEvent); eventService.saveEvent(deleteUserEvent);
@ -276,13 +332,6 @@ public class ControllerService {
eventService.saveEvent(deleteGroupEvent); 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) { private void promoteVeteranMember(Account account, Group group) {
if (validationService.checkIfLastAdmin(account, group)) { if (validationService.checkIfLastAdmin(account, group)) {
User newAdmin = getVeteranMember(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) { public void changeRole(Account account, User user, Group group) {
if (user.getId().equals(account.getName())) { if (user.getId().equals(account.getName())) {
if (group.getMembers().size() <= 1) { if (group.getMembers().size() <= 1) {
@ -300,31 +356,4 @@ public class ControllerService {
updateRole(user, group.getId()); updateRole(user, group.getId());
} }
private User getVeteranMember(Account account, Group group) {
List<User> 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");
}
} }

View File

@ -11,9 +11,11 @@ import java.io.InputStream;
import java.util.List; import java.util.List;
@Service @Service
public class CsvService { public final class CsvService {
public static List<User> read(InputStream stream) throws IOException { private CsvService() {}
static List<User> read(InputStream stream) throws IOException {
CsvMapper mapper = new CsvMapper(); CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(User.class).withHeader().withColumnReordering(true); CsvSchema schema = mapper.schemaFor(User.class).withHeader().withColumnReordering(true);

View File

@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import mops.gruppen2.domain.dto.EventDTO; import mops.gruppen2.domain.dto.EventDTO;
import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.Event;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
@ -15,11 +17,10 @@ import java.util.stream.Collectors;
//TODO: Evtl aufsplitten in EventRepoService und EventService? //TODO: Evtl aufsplitten in EventRepoService und EventService?
public class EventService { public class EventService {
private final JsonService jsonService; private static final Logger LOG = LoggerFactory.getLogger(EventService.class);
private final EventRepository eventStore; private final EventRepository eventStore;
public EventService(JsonService jsonService, EventRepository eventStore) { public EventService(EventRepository eventStore) {
this.jsonService = jsonService;
this.eventStore = 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. * Speichert alle Events aus der übergebenen Liste in der DB.
*
* @param events Liste an Events die gespeichert werden soll * @param events Liste an Events die gespeichert werden soll
*/ */
@SafeVarargs @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. * Findet alle Events welche ab dem neuen Status hinzugekommen sind.
* Sucht alle Events mit event_id > status * Sucht alle Events mit event_id > status
* *
* @param status Die Id des zuletzt gespeicherten Events * @param status Die Id des zuletzt gespeicherten Events
*
* @return Liste von neueren Events * @return Liste von neueren Events
*/ */
public List<Event> getNewEvents(Long status) { public List<Event> getNewEvents(Long status) {
@ -98,28 +103,39 @@ public class EventService {
* Erzeugt aus einer Liste von eventDTOs eine Liste von Events. * Erzeugt aus einer Liste von eventDTOs eine Liste von Events.
* *
* @param eventDTOS Liste von DTOs * @param eventDTOS Liste von DTOs
*
* @return Liste von Events * @return Liste von Events
*/ */
public List<Event> getEventsFromDTOs(Iterable<EventDTO> eventDTOS) { List<Event> getEventsFromDTOs(Iterable<EventDTO> eventDTOS) {
List<Event> events = new ArrayList<>(); List<Event> events = new ArrayList<>();
for (EventDTO eventDTO : eventDTOS) { for (EventDTO eventDTO : eventDTOS) {
try { try {
events.add(jsonService.deserializeEvent(eventDTO.getEvent_payload())); events.add(JsonService.deserializeEvent(eventDTO.getEvent_payload()));
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
e.printStackTrace(); LOG.error("Payload\n {}\n konnte nicht deserialisiert werden!", eventDTO.getEvent_payload());
} }
} }
return events; return events;
} }
public Long getMaxEvent_id() { public long getMaxEventId() {
return eventStore.getHighesEventID(); 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. * Gibt eine Liste mit allen Events zurück, die zu der Gruppe gehören.
*
* @param groupId Gruppe die betrachtet werden soll * @param groupId Gruppe die betrachtet werden soll
*
* @return Liste aus Events * @return Liste aus Events
*/ */
public List<Event> getEventsOfGroup(UUID groupId) { public List<Event> 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 * @param userId Die Id des Users
*
* @return Liste aus GruppenIds * @return Liste aus GruppenIds
*/ */
public List<UUID> findGroupIdsByUser(String userId) { public List<UUID> findGroupIdsByUser(String userId) {
return eventStore.findGroupIdsWhereUserId(userId, "AddUserEvent").stream() return eventStore.findGroupIdsWhereUserId(userId, "AddUserEvent").stream().map(UUID::fromString).collect(Collectors.toList());
.map(UUID::fromString)
.collect(Collectors.toList());
} }
/** /**
* Gibt true zurück, falls der User aktuell in der Gruppe ist, sonst false. * Gibt true zurück, falls der User aktuell in der Gruppe ist, sonst false.
*
* @param groupId Id der Gruppe * @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 * @return true or false
*/ */
public boolean userInGroup(UUID groupId, String userId) { boolean userInGroup(UUID groupId, String userId) {
return eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "AddUserEvent") return eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "AddUserEvent") > eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "DeleteUserEvent");
> eventStore.countEventsByGroupIdAndUserIdAndEventType(groupId.toString(), userId, "DeleteUserEvent");
} }
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.Visibility; 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.event.Event;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
import mops.gruppen2.security.Account;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; 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. * Wandelt die Zeilen in Events um und gibt davon eine Liste zurück.
* *
* @param groupIds Liste an IDs * @param groupIds Liste an IDs
*
* @return Liste an Events * @return Liste an Events
*/ */
//TODO Das vielleicht in den EventRepoService? //TODO: Das vielleicht in den EventRepoService?
public List<Event> getGroupEvents(List<UUID> groupIds) { public List<Event> getGroupEvents(List<UUID> groupIds) {
List<EventDTO> eventDTOS = new ArrayList<>(); List<EventDTO> eventDTOS = new ArrayList<>();
for (UUID groupId : groupIds) { for (UUID groupId : groupIds) {
@ -45,65 +46,6 @@ public class GroupService {
return eventService.getEventsFromDTOs(eventDTOS); 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<Group> projectEventList(List<Event> events) throws EventException {
Map<UUID, Group> 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<UUID, Group> 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<Group> getAllGroupWithVisibilityPublic(String userId) throws EventException {
List<Event> 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<Group> 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. * Wird verwendet beim Gruppe erstellen bei der Parent-Auswahl: nur Titel benötigt.
* *
@ -119,18 +61,55 @@ public class GroupService {
List<Group> visibleGroups = projectEventList(createEvents); List<Group> visibleGroups = projectEventList(createEvents);
return visibleGroups.stream() return visibleGroups.stream()
.filter(group -> group.getType() == GroupType.LECTURE) .filter(group -> group.getType() == GroupType.LECTURE)
.filter(group -> group.getVisibility() == Visibility.PUBLIC) .filter(group -> group.getVisibility() == Visibility.PUBLIC)
.collect(Collectors.toList()); .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<Group> projectEventList(List<Event> events) throws EventException {
Map<UUID, Group> 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<UUID, Group> 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. * Filtert alle öffentliche Gruppen nach dem Suchbegriff und gibt diese als Liste von Gruppen zurück.
* Groß und Kleinschreibung wird nicht beachtet. * Groß und Kleinschreibung wird nicht beachtet.
* *
* @param search Der Suchstring * @param search Der Suchstring
*
* @return Liste von projizierten Gruppen * @return Liste von projizierten Gruppen
*
* @throws EventException Projektionsfehler * @throws EventException Projektionsfehler
*/ */
//Todo Rename //Todo Rename
@ -140,19 +119,44 @@ public class GroupService {
return getAllGroupWithVisibilityPublic(account.getName()); return getAllGroupWithVisibilityPublic(account.getName());
} }
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());
.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<Group> getAllGroupWithVisibilityPublic(String userId) throws EventException {
List<Event> 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<Group> 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. * Sortiert die übergebene Liste an Gruppen, sodass Veranstaltungen am Anfang der Liste sind.
*
* @param groups Die Liste von Gruppen die sortiert werden soll * @param groups Die Liste von Gruppen die sortiert werden soll
*/ */
public void sortByGroupType(List<Group> groups) { void sortByGroupType(List<Group> groups) {
groups.sort((g1, g2) -> { groups.sort((Group g1, Group g2) -> {
if (g1.getType() == GroupType.LECTURE) { if (g1.getType() == GroupType.LECTURE) {
return -1; return -1;
} }

View File

@ -4,6 +4,8 @@ import mops.gruppen2.domain.dto.InviteLinkDTO;
import mops.gruppen2.domain.exception.InvalidInviteException; import mops.gruppen2.domain.exception.InvalidInviteException;
import mops.gruppen2.domain.exception.NoInviteExistException; import mops.gruppen2.domain.exception.NoInviteExistException;
import mops.gruppen2.repository.InviteRepository; import mops.gruppen2.repository.InviteRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.UUID; import java.util.UUID;
@ -11,17 +13,18 @@ import java.util.UUID;
@Service @Service
public class InviteService { public class InviteService {
private static final Logger LOG = LoggerFactory.getLogger(InviteService.class);
private final InviteRepository inviteRepository; private final InviteRepository inviteRepository;
public InviteService(InviteRepository inviteRepository) { public InviteService(InviteRepository inviteRepository) {
this.inviteRepository = inviteRepository; this.inviteRepository = inviteRepository;
} }
public void createLink(UUID groupId) { void createLink(UUID groupId) {
inviteRepository.save(new InviteLinkDTO(null, groupId.toString(), UUID.randomUUID().toString())); inviteRepository.save(new InviteLinkDTO(null, groupId.toString(), UUID.randomUUID().toString()));
} }
public void destroyLink(UUID groupId) { void destroyLink(UUID groupId) {
inviteRepository.deleteLinkOfGroup(groupId.toString()); inviteRepository.deleteLinkOfGroup(groupId.toString());
} }
@ -29,7 +32,7 @@ public class InviteService {
try { try {
return UUID.fromString(inviteRepository.findGroupIdByLink(link)); return UUID.fromString(inviteRepository.findGroupIdByLink(link));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOG.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link);
} }
throw new InvalidInviteException(link); throw new InvalidInviteException(link);
@ -39,7 +42,7 @@ public class InviteService {
try { try {
return inviteRepository.findLinkByGroupId(groupId.toString()); return inviteRepository.findLinkByGroupId(groupId.toString());
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); LOG.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", groupId);
} }
throw new NoInviteExistException(groupId.toString()); throw new NoInviteExistException(groupId.toString());

View File

@ -9,17 +9,21 @@ import org.springframework.stereotype.Service;
* Übersetzt JSON-Event-Payloads zu Java-Event-Repräsentationen und zurück. * Übersetzt JSON-Event-Payloads zu Java-Event-Repräsentationen und zurück.
*/ */
@Service @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. * Übersetzt mithilfe der Jackson-Library eine Java-Event-Repräsentation zu einem JSON-Event-Payload.
* *
* @param event Java-Event-Repräsentation * @param event Java-Event-Repräsentation
*
* @return JSON-Event-Payload als String * @return JSON-Event-Payload als String
*
* @throws JsonProcessingException Bei JSON Fehler * @throws JsonProcessingException Bei JSON Fehler
*/ */
public String serializeEvent(Event event) throws JsonProcessingException { static String serializeEvent(Event event) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(event); 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. * Übersetzt mithilfe der Jackson-Library einen JSON-Event-Payload zu einer Java-Event-Repräsentation.
* *
* @param json JSON-Event-Payload als String * @param json JSON-Event-Payload als String
*
* @return Java-Event-Repräsentation * @return Java-Event-Repräsentation
*
* @throws JsonProcessingException Bei JSON Fehler * @throws JsonProcessingException Bei JSON Fehler
*/ */
public Event deserializeEvent(String json) throws JsonProcessingException { static Event deserializeEvent(String json) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, Event.class); return mapper.readValue(json, Event.class);
} }

View File

@ -1,20 +1,23 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import mops.gruppen2.security.Account; import mops.gruppen2.domain.Account;
import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class KeyCloakService { public final class KeyCloakService {
private KeyCloakService() {}
/** /**
* Creates an Account. * Creates an Account.
* *
* @param token Ein toller token * @param token Ein toller token
*
* @return Account with current userdata * @return Account with current userdata
*/ */
public Account createAccountFromPrincipal(KeycloakAuthenticationToken token) { public static Account createAccountFromPrincipal(KeycloakAuthenticationToken token) {
KeycloakPrincipal principal = (KeycloakPrincipal) token.getPrincipal(); KeycloakPrincipal principal = (KeycloakPrincipal) token.getPrincipal();
return new Account( return new Account(
principal.getName(), principal.getName(),

View File

@ -3,6 +3,4 @@ package mops.gruppen2.service;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class SearchService { public class SearchService {}
}

View File

@ -23,11 +23,19 @@ public class UserService {
this.eventService = eventService; this.eventService = eventService;
} }
@Cacheable("groups")
public List<Group> getUserGroups(String userId) throws EventException {
return getUserGroups(new User(userId, "", "", ""));
}
/** /**
* Gibt eine Liste aus Gruppen zurück, in denen sich der übergebene User befindet. * Gibt eine Liste aus Gruppen zurück, in denen sich der übergebene User befindet.
*
* @param user Der User * @param user Der User
*
* @return Liste aus Gruppen * @return Liste aus Gruppen
*/ */
//TODO: Nur AddUserEvents + DeleteUserEvents betrachten
@Cacheable("groups") @Cacheable("groups")
public List<Group> getUserGroups(User user) { public List<Group> getUserGroups(User user) {
List<UUID> groupIds = eventService.findGroupIdsByUser(user.getId()); List<UUID> groupIds = eventService.findGroupIdsByUser(user.getId());
@ -45,15 +53,13 @@ public class UserService {
return newGroups; return newGroups;
} }
@Cacheable("groups")
public List<Group> getUserGroups(String userId) throws EventException {
return getUserGroups(new User(userId, null, null, null));
}
/** /**
* Gibt die Gruppe zurück, die zu der übergebenen Id passt. * Gibt die Gruppe zurück, die zu der übergebenen Id passt.
*
* @param groupId Die Id der gesuchten Gruppe * @param groupId Die Id der gesuchten Gruppe
*
* @return Die gesuchte Gruppe * @return Die gesuchte Gruppe
*
* @throws EventException Wenn die Gruppe nicht gefunden wird * @throws EventException Wenn die Gruppe nicht gefunden wird
*/ */
public Group getGroupById(UUID groupId) throws EventException { public Group getGroupById(UUID groupId) throws EventException {

View File

@ -1,11 +1,17 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.Role; import mops.gruppen2.domain.Role;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.exception.*; import mops.gruppen2.domain.exception.BadParameterException;
import mops.gruppen2.security.Account; 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 org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@ -25,6 +31,7 @@ public class ValidationService {
this.groupService = groupService; this.groupService = groupService;
} }
//TODO: make static or change return + assignment
public List<Group> checkSearch(String search, List<Group> groups, Account account) { public List<Group> checkSearch(String search, List<Group> groups, Account account) {
if (search != null) { if (search != null) {
groups = groupService.findGroupWith(search, account); 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) { public void throwIfUserAlreadyInGroup(Group group, User user) {
if (checkIfUserInGroup(group, user)) { if (checkIfUserInGroup(group, user)) {
throw new UserAlreadyExistsException("@details"); throw new UserAlreadyExistsException("@details");
} }
} }
public void throwIfNotInGroup(Group group, User user) { void throwIfNotInGroup(Group group, User user) {
if (!checkIfUserInGroup(group, 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) { public void throwIfGroupFull(Group group) {
if (group.getUserMaximum() < group.getMembers().size() + 1) { if (group.getUserMaximum() < group.getMembers().size() + 1) {
throw new GroupFullException("Du kannst der Gruppe daher leider nicht beitreten."); 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(); return userService.getGroupById(groupId).getMembers().isEmpty();
} }
public void throwIfNoAdmin(Group group, User user) { public void throwIfNoAdmin(Group group, User user) {
throwIfNoAccessToPrivate(group, 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(""); throw new NoAccessException("");
} }
} }
public boolean checkIfAdmin(Group group, User user) { public boolean checkIfAdmin(Group group, User user) {
if (checkIfUserInGroup(group, user)) { if (checkIfUserInGroup(group, user)) {
return group.getRoles().get(user.getId()) == Role.ADMIN; return group.getRoles().get(user.getId()) == ADMIN;
} }
return false; 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<String, Role> entry : group.getRoles().entrySet()) { for (Map.Entry<String, Role> entry : group.getRoles().entrySet()) {
if (entry.getValue() == ADMIN) { if (entry.getValue() == ADMIN && !(entry.getKey().equals(account.getName()))) {
if (!(entry.getKey().equals(account.getName()))) { return false;
return false;
}
} }
} }
return true; 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. * Überprüft ob alle Felder richtig gesetzt sind.
* *
* @param description Die Beschreibung der Gruppe * @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 * @param userMaximum Das user Limit der Gruppe
*/ */
public void checkFields(String title, String description, Long userMaximum, Boolean maxInfiniteUsers) { 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"); 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"); throw new BadParameterException("Der Titel wurde nicht korrekt angegeben");
} }
@ -121,19 +126,17 @@ public class ValidationService {
throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben"); throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben");
} }
if (userMaximum != null) { if (userMaximum != null && (userMaximum < 1 || userMaximum > 10000L)) {
if (userMaximum < 1 || userMaximum > 10000L) { throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben");
throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben");
}
} }
} }
public void checkFields(String title, String description) { 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"); 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"); throw new BadParameterException("Der Titel wurde nicht korrekt angegeben");
} }
} }

View File

@ -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"}');

View File

@ -55,7 +55,8 @@
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input class="custom-control-input" id="maxInfiniteUsers" th:name="maxInfiniteUsers" <input class="custom-control-input" id="maxInfiniteUsers" th:name="maxInfiniteUsers"
type="checkbox"> type="checkbox">
<label class="custom-control-label" for="maxInfiniteUsers">Anzahl unbegrenzt</label> <label class="custom-control-label" for="maxInfiniteUsers">Anzahl
unbegrenzt</label>
</div> </div>
<div class="form-group mt-3" id="userMaximum"> <div class="form-group mt-3" id="userMaximum">
<label for="userMaximum">Teilnehmeranzahl</label> <label for="userMaximum">Teilnehmeranzahl</label>
@ -66,7 +67,7 @@
<input class="custom-control-input" id="visibility" th:name="visibility" <input class="custom-control-input" id="visibility" th:name="visibility"
type="checkbox"> type="checkbox">
<label class="custom-control-label" for="visibility">Private <label class="custom-control-label" for="visibility">Private
Gruppe</label> Gruppe</label>
</div> </div>
<div class="custom-control custom-checkbox" id="lectureCheckbox"> <div class="custom-control custom-checkbox" id="lectureCheckbox">
<input class="custom-control-input" id="lecture" th:name="lecture" <input class="custom-control-input" id="lecture" th:name="lecture"
@ -76,7 +77,8 @@
<div class="form-group" id="lectureParent"> <div class="form-group" id="lectureParent">
<label for="parent"></label> <label for="parent"></label>
<select class="form-control" id="parent" name="parent"> <select class="form-control" id="parent" name="parent">
<option disabled selected="true">--Bitte Veranstaltung auswählen--</option> <option disabled selected="true">--Bitte Veranstaltung auswählen--
</option>
<option th:each="lecture : ${lectures}" th:name="parent" th:value="${lecture.getId()}" th:text="${lecture.getTitle()}"> <option th:each="lecture : ${lectures}" th:name="parent" th:value="${lecture.getId()}" th:text="${lecture.getTitle()}">
</option> </option>
</select> </select>
@ -88,7 +90,8 @@
<input class="custom-file-input" id="file" th:name="file" <input class="custom-file-input" id="file" th:name="file"
type="file"> type="file">
<label class="custom-file-label" for="file">CSV Datei von <label class="custom-file-label" for="file">CSV Datei von
Mitgliedern hochladen</label> Mitgliedern
hochladen</label>
</div> </div>
</div> </div>
</div> </div>

View File

@ -54,7 +54,8 @@
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input class="custom-control-input" id="maxInfiniteUsers" th:name="maxInfiniteUsers" <input class="custom-control-input" id="maxInfiniteUsers" th:name="maxInfiniteUsers"
type="checkbox"> type="checkbox">
<label class="custom-control-label" for="maxInfiniteUsers">Anzahl unbegrenzt</label> <label class="custom-control-label" for="maxInfiniteUsers">Anzahl
unbegrenzt</label>
</div> </div>
<div class="form-group mt-3" id="userMaximum"> <div class="form-group mt-3" id="userMaximum">
<label for="userMaximum">Teilnehmeranzahl</label> <label for="userMaximum">Teilnehmeranzahl</label>
@ -65,12 +66,13 @@
<input class="custom-control-input" id="visibility" th:name="visibility" <input class="custom-control-input" id="visibility" th:name="visibility"
type="checkbox"> type="checkbox">
<label class="custom-control-label" for="visibility">Private <label class="custom-control-label" for="visibility">Private
Gruppe</label> Gruppe</label>
</div> </div>
<div class="form-group" id="lectureParent"> <div class="form-group" id="lectureParent">
<label for="parent"></label> <label for="parent"></label>
<select class="form-control" id="parent" name="parent"> <select class="form-control" id="parent" name="parent">
<option disabled selected="true">--Bitte Veranstaltung auswählen--</option> <option disabled selected="true">--Bitte Veranstaltung auswählen--
</option>
<option th:each="lecture : ${lectures}" th:name="parent" th:value="${lecture.getId()}" th:text="${lecture.getTitle()}"> <option th:each="lecture : ${lectures}" th:name="parent" th:value="${lecture.getId()}" th:text="${lecture.getTitle()}">
</option> </option>
</select> </select>

View File

@ -112,7 +112,9 @@
<div th:if="${group.getRoles().get(user.getId()) == admin}"> <div th:if="${group.getRoles().get(user.getId()) == admin}">
<form method="get" <form method="get"
th:action="@{/gruppen2/details/members/{id}(id=${group.getId()})}"> th:action="@{/gruppen2/details/members/{id}(id=${group.getId()})}">
<button class="btn btn-secondary" style="background: slategrey; float: left">Mitglieder bearbeiten</button> <button class="btn btn-secondary" style="background: slategrey; float: left">
Mitglieder bearbeiten
</button>
</form> </form>
<br> <br>
<br> <br>
@ -122,7 +124,8 @@
<ul class="list-group-flush" style="background: slategrey" <ul class="list-group-flush" style="background: slategrey"
th:each="member : ${group.getMembers()}"> th:each="member : ${group.getMembers()}">
<li class="list-group-item" style="background: aliceblue"> <li class="list-group-item" style="background: aliceblue">
<span th:text="${member.getId()}"></span> <span th:if='${group.getVisibility() == public}' th:text="${member.getId()}"></span>
<span th:if='${group.getVisibility() == private}' th:text="${#strings.abbreviate(member.getGivenname(), 15) + ' ' + member.getFamilyname().substring(0, 1) + '.'}"></span>
<span class="badge badge-success" <span class="badge badge-success"
th:if='${group.getRoles().get(member.getId()) == admin}'>admin</span> th:if='${group.getRoles().get(member.getId()) == admin}'>admin</span>
</li> </li>

View File

@ -56,7 +56,8 @@
<input class="custom-file-input" id="file" th:name="file" <input class="custom-file-input" id="file" th:name="file"
type="file"> type="file">
<label class="custom-file-label" for="file">CSV Datei von <label class="custom-file-label" for="file">CSV Datei von
Mitgliedern hochladen</label> Mitgliedern
hochladen</label>
</div> </div>
<div class="input-group-append"> <div class="input-group-append">
<button class="btn btn-outline-secondary" <button class="btn btn-outline-secondary"
@ -99,7 +100,7 @@
</thead> </thead>
<tbody class="table-striped"> <tbody class="table-striped">
<tr th:each="member : ${group.getMembers()}"> <tr th:each="member : ${group.getMembers()}">
<th th:text="${member.getId()}"></th> <th th:text="${#strings.abbreviate(member.getGivenname(), 15) + ' ' + member.getFamilyname().substring(0, 1) + '.'}"></th>
<td> <td>
<span th:if='${group.getRoles().get(member.getId()) != admin}'>Mitglied</span> <span th:if='${group.getRoles().get(member.getId()) != admin}'>Mitglied</span>
<span th:if='${group.getRoles().get(member.getId()) == admin}'>Admin</span> <span th:if='${group.getRoles().get(member.getId()) == admin}'>Admin</span>
@ -113,8 +114,7 @@
<input th:name="user_id" th:value="${member.getId()}" <input th:name="user_id" th:value="${member.getId()}"
type="hidden"> type="hidden">
<button class="btn btn-warning btn-sm" type="submit" <button class="btn btn-warning btn-sm" type="submit"
style="margin: 5px">Rolle style="margin: 5px;">Rolle ändern
ändern
</button> </button>
</form> </form>
<form method="post" <form method="post"
@ -134,7 +134,9 @@
</tbody> </tbody>
</table> </table>
<form method="get" th:action="@{/gruppen2/details/{id}(id=${group.getId()})}"> <form method="get" th:action="@{/gruppen2/details/{id}(id=${group.getId()})}">
<button class="btn btn-primary" style="background: #52a1eb; border-style: none" type="submit">Fertig</button> <button class="btn btn-primary" style="background: #52a1eb; border-style: none" type="submit">
Fertig
</button>
</form> </form>
</div> </div>
</div> </div>

View File

@ -35,23 +35,24 @@
<h1>Gruppensuche</h1> <h1>Gruppensuche</h1>
<div class="shadow-sm p-2" <div class="shadow-sm p-2"
style="border: 10px solid aliceblue; border-radius: 5px; background: aliceblue"> style="border: 10px solid aliceblue; border-radius: 5px; background: aliceblue">
<form method="get" th:action="@{/gruppen2/findGroup}"> <form method="get" th:action="@{/gruppen2/findGroup}">
<div class="form-group"> <div class="form-group">
<label for="suchleiste">Suchbegriff:</label> <label for="suchleiste">Suchbegriff:</label>
<input class="form-control" id="suchleiste" <input class="form-control" id="suchleiste"
placeholder="z.B. Programmieren, Lerngruppe, ..." placeholder="z.B. Programmieren, Lerngruppe, ..."
th:name="suchbegriff" type="text"> th:name="suchbegriff" type="text">
</div> </div>
<button class="btn btn-primary" <button class="btn btn-primary"
style="background: #52a1eb; border-style: none" style="background: #52a1eb; border-style: none"
type="submit">Suchen type="submit">Suchen
</button> </button>
<button class="btn btn-primary" <button class="btn btn-primary"
style="background: deepskyblue; border-style: none" style="background: deepskyblue; border-style: none"
type="submit"> type="submit">
<a style="color: white" href="/gruppen2/findGroup?suchbegriff=">Alle anzeigen</a> <a href="/gruppen2/findGroup?suchbegriff=" style="color: white">Alle
</button> anzeigen</a>
</form> </button>
</form>
</div> </div>
<br> <br>
<table class="table"> <table class="table">

View File

@ -1,6 +1,7 @@
package mops.gruppen2; package mops.gruppen2;
import com.github.javafaker.Faker; import com.github.javafaker.Faker;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.Role; 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.UpdateGroupDescriptionEvent;
import mops.gruppen2.domain.event.UpdateGroupTitleEvent; import mops.gruppen2.domain.event.UpdateGroupTitleEvent;
import mops.gruppen2.domain.event.UpdateRoleEvent; import mops.gruppen2.domain.event.UpdateRoleEvent;
import mops.gruppen2.security.Account;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -29,11 +29,11 @@ public class TestBuilder {
public static Account account(String name) { public static Account account(String name) {
return new Account(name, return new Account(name,
"", "",
"", "",
"", "",
"", "",
null); null);
} }
public static Group apply(Group group, Event... events) { public static Group apply(Group group, Event... events) {
@ -52,12 +52,14 @@ public class TestBuilder {
* Baut eine UUID. * Baut eine UUID.
* *
* @param id Integer id * @param id Integer id
*
* @return UUID * @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-" return UUID.fromString("00000000-0000-0000-0000-"
+ "0".repeat(11 - String.valueOf(id).length()) + "0".repeat(11 - idString.length())
+ id); + idString);
} }
/** /**
@ -65,22 +67,23 @@ public class TestBuilder {
* *
* @param count Gruppenanzahl * @param count Gruppenanzahl
* @param membercount Mitgliederanzahl pro Gruppe * @param membercount Mitgliederanzahl pro Gruppe
*
* @return Eventliste * @return Eventliste
*/ */
public static List<Event> completePublicGroups(int count, int membercount) { public static List<Event> completePublicGroups(int count, int membercount) {
return IntStream.range(0, count) return IntStream.range(0, count)
.parallel() .parallel()
.mapToObj(i -> completePublicGroup(membercount)) .mapToObj(i -> completePublicGroup(membercount))
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static List<Event> completePrivateGroups(int count, int membercount) { public static List<Event> completePrivateGroups(int count, int membercount) {
return IntStream.range(0, count) return IntStream.range(0, count)
.parallel() .parallel()
.mapToObj(i -> completePrivateGroup(membercount)) .mapToObj(i -> completePrivateGroup(membercount))
.flatMap(Collection::stream) .flatMap(Collection::stream)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static List<Event> completePublicGroup(int membercount) { public static List<Event> completePublicGroup(int membercount) {
@ -119,29 +122,30 @@ public class TestBuilder {
* Generiert mehrere CreateGroupEvents, 1 <= groupId <= count. * Generiert mehrere CreateGroupEvents, 1 <= groupId <= count.
* *
* @param count Anzahl der verschiedenen Gruppen * @param count Anzahl der verschiedenen Gruppen
*
* @return Eventliste * @return Eventliste
*/ */
public static List<Event> createPublicGroupEvents(int count) { public static List<Event> createPublicGroupEvents(int count) {
return IntStream.range(0, count) return IntStream.range(0, count)
.parallel() .parallel()
.mapToObj(i -> createPublicGroupEvent()) .mapToObj(i -> createPublicGroupEvent())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static List<Event> createPrivateGroupEvents(int count) { public static List<Event> createPrivateGroupEvents(int count) {
return IntStream.range(0, count) return IntStream.range(0, count)
.parallel() .parallel()
.mapToObj(i -> createPublicGroupEvent()) .mapToObj(i -> createPublicGroupEvent())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static List<Event> createMixedGroupEvents(int count) { public static List<Event> createMixedGroupEvents(int count) {
return IntStream.range(0, count) return IntStream.range(0, count)
.parallel() .parallel()
.mapToObj(i -> faker.random().nextInt(0, 1) > 0.5 .mapToObj(i -> faker.random().nextInt(0, 1) > 0.5
? createPublicGroupEvent() ? createPublicGroupEvent()
: createPrivateGroupEvent()) : createPrivateGroupEvent())
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static Event createPrivateGroupEvent(UUID groupId) { public static Event createPrivateGroupEvent(UUID groupId) {
@ -191,13 +195,14 @@ public class TestBuilder {
* *
* @param count Anzahl der Mitglieder * @param count Anzahl der Mitglieder
* @param groupId Gruppe, zu welcher geaddet wird * @param groupId Gruppe, zu welcher geaddet wird
*
* @return Eventliste * @return Eventliste
*/ */
public static List<Event> addUserEvents(int count, UUID groupId) { public static List<Event> addUserEvents(int count, UUID groupId) {
return IntStream.range(0, count) return IntStream.range(0, count)
.parallel() .parallel()
.mapToObj(i -> addUserEvent(groupId, String.valueOf(i))) .mapToObj(i -> addUserEvent(groupId, String.valueOf(i)))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static Event addUserEvent(UUID groupId, String userId) { public static Event addUserEvent(UUID groupId, String userId) {
@ -221,8 +226,8 @@ public class TestBuilder {
public static List<Event> deleteUserEvents(int count, List<Event> eventList) { public static List<Event> deleteUserEvents(int count, List<Event> eventList) {
List<Event> removeEvents = new ArrayList<>(); List<Event> removeEvents = new ArrayList<>();
List<Event> shuffle = eventList.parallelStream() List<Event> shuffle = eventList.parallelStream()
.filter(event -> event instanceof AddUserEvent) .filter(event -> event instanceof AddUserEvent)
.collect(Collectors.toList()); .collect(Collectors.toList());
Collections.shuffle(shuffle); Collections.shuffle(shuffle);
@ -241,12 +246,13 @@ public class TestBuilder {
* Erzeugt mehrere DeleteUserEvents, sodass eine Gruppe komplett geleert wird. * Erzeugt mehrere DeleteUserEvents, sodass eine Gruppe komplett geleert wird.
* *
* @param group Gruppe welche geleert wird * @param group Gruppe welche geleert wird
*
* @return Eventliste * @return Eventliste
*/ */
public static List<Event> deleteUserEvents(Group group) { public static List<Event> deleteUserEvents(Group group) {
return group.getMembers().parallelStream() return group.getMembers().parallelStream()
.map(user -> deleteUserEvent(group.getId(), user.getId())) .map(user -> deleteUserEvent(group.getId(), user.getId()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public static Event deleteUserEvent(UUID groupId, String userId) { public static Event deleteUserEvent(UUID groupId, String userId) {

View File

@ -14,18 +14,17 @@ public class LayeredArchitectureTest {
.layer("Domain").definedBy("..domain..") .layer("Domain").definedBy("..domain..")
.layer("Service").definedBy("..service") .layer("Service").definedBy("..service")
.layer("Controller").definedBy("..controller..") .layer("Controller").definedBy("..controller..")
.layer("Repository").definedBy("..repository..") .layer("Repository").definedBy("..repository..");
.layer("Config").definedBy("..config..");
@ArchTest @ArchTest
public static final ArchRule domainLayerShouldOnlyBeAccessedByServiceAndControllerLayer = layeredArchitecture public static final ArchRule domainLayerShouldOnlyBeAccessedByServiceAndControllerLayer = layeredArchitecture
.whereLayer("Domain") .whereLayer("Domain")
.mayOnlyBeAccessedByLayers("Service", "Controller", "Config"); .mayOnlyBeAccessedByLayers("Service", "Controller");
@ArchTest @ArchTest
public static final ArchRule serviceLayerShouldOnlyBeAccessedByControllerLayer = layeredArchitecture public static final ArchRule serviceLayerShouldOnlyBeAccessedByControllerLayer = layeredArchitecture
.whereLayer("Service") .whereLayer("Service")
.mayOnlyBeAccessedByLayers("Controller", "Config"); .mayOnlyBeAccessedByLayers("Controller");
@ArchTest @ArchTest
public static final ArchRule repositoryLayerShouldOnlyBeAccessedByServiceLayer = layeredArchitecture public static final ArchRule repositoryLayerShouldOnlyBeAccessedByServiceLayer = layeredArchitecture

View File

@ -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);
}
}

View File

@ -1,35 +1,57 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.exception.GroupFullException;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.UserAlreadyExistsException; import mops.gruppen2.domain.exception.UserAlreadyExistsException;
import org.junit.jupiter.api.Test; 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.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
class AddUserEventTest { class AddUserEventTest {
@Test @Test
void userAlreadyExistExeption() throws EventException { void applyEvent() {
Group group = new Group(); Event createEvent = createPublicGroupEvent(uuidMock(0));
User user = new User("user1", "Stein", "Speck", "@sdasd"); Event addEvent = new AddUserEvent(uuidMock(0), "A", "Thomas", "Tom", "tho@mail.de");
group.getMembers().add(user);
group.setUserMaximum(10L);
UUID id = UUID.randomUUID();
Event event1 = new AddUserEvent(id, "user2", "Rock", "Roll", "and");
event1.apply(group);
Event event2 = new AddUserEvent(id, "user1", "Rock", "Roll", "and"); Group group = apply(createEvent, addEvent);
assertThrows(UserAlreadyExistsException.class, () -> assertThat(group.getMembers()).hasSize(1);
event2.apply(group) assertThat(group.getMembers().get(0).getGivenname()).isEqualTo("Thomas");
); assertThat(group.getMembers().get(0).getFamilyname()).isEqualTo("Tom");
assertThat(group.getMembers().size()).isEqualTo(2); 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);
}
} }

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -1,48 +1,38 @@
package mops.gruppen2.domain.event; package mops.gruppen2.domain.event;
import mops.gruppen2.TestBuilder;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.domain.exception.UserNotFoundException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.UUID; import static mops.gruppen2.TestBuilder.addUserEvent;
import static mops.gruppen2.TestBuilder.createPublicGroupEvent;
import static mops.gruppen2.domain.Role.MEMBER; import static mops.gruppen2.TestBuilder.uuidMock;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
class DeleteUserEventTest { class DeleteUserEventTest {
@Test @Test
void applyDeleteUser() throws EventException { void applyEvent() {
Group group = new Group(); Event createEvent = createPublicGroupEvent(uuidMock(0));
User user = new User("user1", "Stein", "Speck", "@sdasd"); Event addEvent = addUserEvent(uuidMock(0), "A");
group.getMembers().add(user); Event deleteEvent = new DeleteUserEvent(uuidMock(0), "A");
group.getRoles().put("user1", MEMBER);
User user2 = new User("user2", "Rock", "Roll", "and");
group.getMembers().add(user2);
group.getRoles().put("user2", MEMBER);
Event event = new DeleteUserEvent(UUID.randomUUID(), "user1"); Group group = TestBuilder.apply(createEvent, addEvent, deleteEvent);
event.apply(group);
assertThat(group.getMembers().size()).isEqualTo(1);
assertThat(group.getRoles().size()).isEqualTo(1);
assertThat(group.getMembers()).hasSize(0);
} }
@Test @Test
void userDoesNotExistExeption() { void applyEvent_userNotFound() {
Group group = new Group(); Event createEvent = createPublicGroupEvent(uuidMock(0));
User user = new User("user1", "Stein", "Speck", "@sdasd"); Event addEvent = addUserEvent(uuidMock(0), "A");
group.getMembers().add(user); Event deleteEvent = new DeleteUserEvent(uuidMock(0), "B");
group.getRoles().put("user1", MEMBER);
Event event = new DeleteUserEvent(UUID.randomUUID(), "user5"); Group group = TestBuilder.apply(createEvent, addEvent);
assertThrows(UserNotFoundException.class, () ->
event.apply(group) assertThrows(UserNotFoundException.class, () -> deleteEvent.apply(group));
); assertThat(group.getMembers()).hasSize(1);
assertThat(group.getMembers().size()).isEqualTo(1);
} }
} }

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -1,14 +1,14 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import mops.gruppen2.Gruppen2Application; import mops.gruppen2.Gruppen2Application;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.Role;
import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.GroupType; 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.domain.exception.UserNotFoundException;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
import mops.gruppen2.security.Account;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -33,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@Transactional @Transactional
@Rollback @Rollback
class ControllerServiceTest { class ControllerServiceTest {
Account account; Account account;
Account account2; Account account2;
Account account3; Account account3;
@ -44,13 +45,11 @@ class ControllerServiceTest {
EventRepository eventRepository; EventRepository eventRepository;
GroupService groupService; GroupService groupService;
@Autowired @Autowired
JsonService jsonService;
@Autowired
InviteService inviteService; InviteService inviteService;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
eventService = new EventService(jsonService, eventRepository); eventService = new EventService(eventRepository);
groupService = new GroupService(eventService, eventRepository); groupService = new GroupService(eventService, eventRepository);
userService = new UserService(groupService, eventService); userService = new UserService(groupService, eventService);
validationService = new ValidationService(userService, groupService); validationService = new ValidationService(userService, groupService);
@ -136,7 +135,7 @@ class ControllerServiceTest {
void createPublicGroupWithParentAndUnlimitedNumberTest() throws IOException { void createPublicGroupWithParentAndUnlimitedNumberTest() throws IOException {
controllerService.createGroupAsOrga(account2, "test", "hi", null, null, true, null, null, null); controllerService.createGroupAsOrga(account2, "test", "hi", null, null, true, null, null, null);
List<Group> groups1 = userService.getUserGroups(new User(account2.getName(), account2.getGivenname(), account2.getFamilyname(), account2.getEmail())); List<Group> 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<Group> groups = userService.getUserGroups(new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail())); List<Group> groups = userService.getUserGroups(new User(account.getName(), account.getGivenname(), account.getFamilyname(), account.getEmail()));
testTitleAndDescription(groups.get(0).getTitle(), groups.get(0).getDescription()); testTitleAndDescription(groups.get(0).getTitle(), groups.get(0).getDescription());
assertEquals(Visibility.PUBLIC, groups.get(0).getVisibility()); assertEquals(Visibility.PUBLIC, groups.get(0).getVisibility());

View File

@ -5,26 +5,23 @@ import mops.gruppen2.domain.dto.EventDTO;
import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.Event;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.Rollback; import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import static mops.gruppen2.TestBuilder.addUserEvent; import static mops.gruppen2.TestBuilder.addUserEvent;
import static mops.gruppen2.TestBuilder.addUserEvents; import static mops.gruppen2.TestBuilder.addUserEvents;
import static mops.gruppen2.TestBuilder.createPrivateGroupEvent;
import static mops.gruppen2.TestBuilder.createPrivateGroupEvents; import static mops.gruppen2.TestBuilder.createPrivateGroupEvents;
import static mops.gruppen2.TestBuilder.createPublicGroupEvent; import static mops.gruppen2.TestBuilder.createPublicGroupEvent;
import static mops.gruppen2.TestBuilder.createPublicGroupEvents; import static mops.gruppen2.TestBuilder.createPublicGroupEvents;
import static mops.gruppen2.TestBuilder.updateGroupDescriptionEvent; import static mops.gruppen2.TestBuilder.uuidMock;
import static mops.gruppen2.TestBuilder.uuidFromInt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
//TODO: Der ID autocounter wird nicht resettet -> Tests schlagen fehl beim nacheinanderausführen
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Gruppen2Application.class) @SpringBootTest(classes = Gruppen2Application.class)
@Transactional @Transactional
@ -33,14 +30,16 @@ class EventServiceTest {
@Autowired @Autowired
private EventRepository eventRepository; private EventRepository eventRepository;
@Autowired
private JsonService jsonService;
private EventService eventService; private EventService eventService;
@Autowired
private JdbcTemplate template;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
eventService = new EventService(jsonService, eventRepository); eventService = new EventService(eventRepository);
eventRepository.deleteAll(); eventRepository.deleteAll();
//noinspection SqlResolve
template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1");
} }
@Test @Test
@ -79,20 +78,20 @@ class EventServiceTest {
@Test @Test
void getEventsOfGroup() { void getEventsOfGroup() {
eventService.saveAll(addUserEvents(10, uuidFromInt(0)), eventService.saveAll(addUserEvents(10, uuidMock(0)),
addUserEvents(5, uuidFromInt(1))); addUserEvents(5, uuidMock(1)));
assertThat(eventService.getEventsOfGroup(uuidFromInt(0))).hasSize(10); assertThat(eventService.getEventsOfGroup(uuidMock(0))).hasSize(10);
assertThat(eventService.getEventsOfGroup(uuidFromInt(1))).hasSize(5); assertThat(eventService.getEventsOfGroup(uuidMock(1))).hasSize(5);
} }
@Test @Test
void findGroupIdsByUser() { void findGroupIdsByUser() {
eventService.saveAll(addUserEvent(uuidFromInt(0), "A"), eventService.saveAll(addUserEvent(uuidMock(0), "A"),
addUserEvent(uuidFromInt(1), "A"), addUserEvent(uuidMock(1), "A"),
addUserEvent(uuidFromInt(2), "A"), addUserEvent(uuidMock(2), "A"),
addUserEvent(uuidFromInt(3), "A"), addUserEvent(uuidMock(3), "A"),
addUserEvent(uuidFromInt(3), "B")); addUserEvent(uuidMock(3), "B"));
assertThat(eventService.findGroupIdsByUser("A")).hasSize(4); assertThat(eventService.findGroupIdsByUser("A")).hasSize(4);
assertThat(eventService.findGroupIdsByUser("B")).hasSize(1); assertThat(eventService.findGroupIdsByUser("B")).hasSize(1);

View File

@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.Rollback; import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional; 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.deleteGroupEvent;
import static mops.gruppen2.TestBuilder.updateGroupDescriptionEvent; import static mops.gruppen2.TestBuilder.updateGroupDescriptionEvent;
import static mops.gruppen2.TestBuilder.updateGroupTitleEvent; 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; import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@ -44,20 +45,20 @@ class GroupServiceTest {
@Autowired @Autowired
private EventService eventService; private EventService eventService;
private GroupService groupService; private GroupService groupService;
@Autowired
private JdbcTemplate template;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
groupService = new GroupService(eventService, eventRepository); groupService = new GroupService(eventService, eventRepository);
eventRepository.deleteAll(); eventRepository.deleteAll();
//noinspection SqlResolve
template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1");
} }
//TODO: Wofür ist dieser Test? //TODO: Wofür ist dieser Test?
@Test @Test
void rightClassForSuccessfulGroup() { void rightClassForSuccessfulGroup() {
/*List<Event> 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<Event> eventList = completePrivateGroup(1); List<Event> eventList = completePrivateGroup(1);
List<Group> groups = groupService.projectEventList(eventList); List<Group> groups = groupService.projectEventList(eventList);
@ -88,30 +89,21 @@ class GroupServiceTest {
@Test @Test
void getGroupEvents() { void getGroupEvents() {
//CreateGroupEvent test1 = new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L); eventService.saveAll(createPublicGroupEvent(uuidMock(0)),
//CreateGroupEvent test2 = new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.SIMPLE, Visibility.PUBLIC, 10L); createPublicGroupEvent(uuidMock(1)),
createPrivateGroupEvent(uuidMock(2)));
eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), List<UUID> groupIds = Arrays.asList(uuidMock(0), uuidMock(1));
createPublicGroupEvent(uuidFromInt(1)),
createPrivateGroupEvent(uuidFromInt(2)));
List<UUID> groupIds = Arrays.asList(uuidFromInt(0), uuidFromInt(1));
assertThat(groupService.getGroupEvents(groupIds)).hasSize(2); assertThat(groupService.getGroupEvents(groupIds)).hasSize(2);
assertThat(groupService.getGroupEvents(groupIds).get(0).getGroupId()).isEqualTo(uuidFromInt(0)); assertThat(groupService.getGroupEvents(groupIds).get(0).getGroupId()).isEqualTo(uuidMock(0));
assertThat(groupService.getGroupEvents(groupIds).get(1).getGroupId()).isEqualTo(uuidFromInt(1)); assertThat(groupService.getGroupEvents(groupIds).get(1).getGroupId()).isEqualTo(uuidMock(1));
} }
@Test @Test
void getAllGroupWithVisibilityPublicTestCreateAndDeleteSameGroup() { void getAllGroupWithVisibilityPublicTestCreateAndDeleteSameGroup() {
//CreateGroupEvent test1 = new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L); Event test1 = createPublicGroupEvent(uuidMock(0));
//DeleteGroupEvent test2 = new DeleteGroupEvent(uuidFromInt(0), "test1"); Event test2 = deleteGroupEvent(uuidMock(0));
Event test1 = createPublicGroupEvent(uuidFromInt(0));
Event test2 = deleteGroupEvent(uuidFromInt(0));
//Group group = new Group();
//test1.apply(group);
//test2.apply(group);
//TODO: Hier projectEventlist()? //TODO: Hier projectEventlist()?
Group group = TestBuilder.apply(test1, test2); Group group = TestBuilder.apply(test1, test2);
@ -122,50 +114,31 @@ class GroupServiceTest {
@Test @Test
void getAllGroupWithVisibilityPublicTestGroupPublic() { void getAllGroupWithVisibilityPublicTestGroupPublic() {
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); eventService.saveAll(createPublicGroupEvent(uuidMock(0)),
//eventService.saveEvent(new DeleteGroupEvent(uuidFromInt(0), "test1")); deleteGroupEvent(uuidMock(0)),
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); createPublicGroupEvent());
//eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(1), "test2", Role.MEMBER)); //Wofür ist das
eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)),
deleteGroupEvent(uuidFromInt(0)),
createPublicGroupEvent());
assertThat(groupService.getAllGroupWithVisibilityPublic("test1").size()).isEqualTo(1); assertThat(groupService.getAllGroupWithVisibilityPublic("test1").size()).isEqualTo(1);
} }
@Test @Test
void getAllGroupWithVisibilityPublicTestAddSomeEvents() { void getAllGroupWithVisibilityPublicTestAddSomeEvents() {
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); eventService.saveAll(createPublicGroupEvent(uuidMock(0)),
//eventService.saveEvent(new DeleteGroupEvent(uuidFromInt(0), "test1")); deleteGroupEvent(uuidMock(0)),
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(1), "test2", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); createPublicGroupEvent(),
//eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(1), "test2", Role.MEMBER)); // Wofür? createPublicGroupEvent(),
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(2), "test3", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); createPublicGroupEvent(),
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(3), "test4", null, GroupType.LECTURE, Visibility.PUBLIC, 10L)); createPrivateGroupEvent());
//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());
assertThat(groupService.getAllGroupWithVisibilityPublic("test1").size()).isEqualTo(3); assertThat(groupService.getAllGroupWithVisibilityPublic("test1").size()).isEqualTo(3);
} }
@Test @Test
void getAllGroupWithVisibilityPublic_UserInGroup() { void getAllGroupWithVisibilityPublic_UserInGroup() {
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); eventService.saveAll(createPublicGroupEvent(uuidMock(0)),
//eventService.saveEvent(new AddUserEvent(uuidFromInt(0), "test1", "test", "test", "test@test")); addUserEvent(uuidMock(0), "kobold"),
createPrivateGroupEvent(),
eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), createPublicGroupEvent());
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);
assertThat(groupService.getAllGroupWithVisibilityPublic("kobold")).hasSize(1); assertThat(groupService.getAllGroupWithVisibilityPublic("kobold")).hasSize(1);
assertThat(groupService.getAllGroupWithVisibilityPublic("peter")).hasSize(2); assertThat(groupService.getAllGroupWithVisibilityPublic("peter")).hasSize(2);
@ -173,56 +146,42 @@ class GroupServiceTest {
@Test @Test
void getAllLecturesWithVisibilityPublic() { 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(), eventService.saveAll(createLectureEvent(),
createPublicGroupEvent(), createPublicGroupEvent(),
createLectureEvent(), createLectureEvent(),
createLectureEvent(), createLectureEvent(),
createLectureEvent()); createLectureEvent());
assertThat(groupService.getAllLecturesWithVisibilityPublic().size()).isEqualTo(4); assertThat(groupService.getAllLecturesWithVisibilityPublic().size()).isEqualTo(4);
} }
@Test @Test
void findGroupWith_UserMember_AllGroups() { void findGroupWith_UserMember_AllGroups() {
//eventService.saveEvent(new CreateGroupEvent(uuidFromInt(0), "test1", null, GroupType.SIMPLE, Visibility.PUBLIC, 20L)); eventService.saveAll(createPublicGroupEvent(uuidMock(0)),
//eventService.saveEvent(new AddUserEvent(uuidFromInt(0), "test1", "test", "test", "test@test")); addUserEvent(uuidMock(0), "jens"),
//eventService.saveEvent(new UpdateGroupTitleEvent(uuidFromInt(0), "test1", "TestGroup")); updateGroupTitleEvent(uuidMock(0)),
//eventService.saveEvent(new UpdateGroupDescriptionEvent(uuidFromInt(0), "test1", "TestDescription")); updateGroupDescriptionEvent(uuidMock(0)));
//eventService.saveEvent(new UpdateRoleEvent(uuidFromInt(0), "test1", Role.MEMBER));
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(); assertThat(groupService.findGroupWith("", account("jens"))).isEmpty();
} }
@Test @Test
void findGroupWith_UserNoMember_AllGroups() { void findGroupWith_UserNoMember_AllGroups() {
eventService.saveAll(completePublicGroups(10, 0), eventService.saveAll(completePublicGroups(10, 0),
completePrivateGroups(10, 0)); completePrivateGroups(10, 0));
assertThat(groupService.findGroupWith("", account("jens"))).hasSize(10); assertThat(groupService.findGroupWith("", account("jens"))).hasSize(10);
} }
@Test @Test
void findGroupWith_FilterGroups() { void findGroupWith_FilterGroups() {
eventService.saveAll(createPublicGroupEvent(uuidFromInt(0)), eventService.saveAll(createPublicGroupEvent(uuidMock(0)),
updateGroupTitleEvent(uuidFromInt(0), "KK"), updateGroupTitleEvent(uuidMock(0), "KK"),
updateGroupDescriptionEvent(uuidFromInt(0), "ABCDE"), updateGroupDescriptionEvent(uuidMock(0), "ABCDE"),
createPublicGroupEvent(uuidFromInt(1)), createPublicGroupEvent(uuidMock(1)),
updateGroupTitleEvent(uuidFromInt(1), "ABCDEFG"), updateGroupTitleEvent(uuidMock(1), "ABCDEFG"),
updateGroupDescriptionEvent(uuidFromInt(1), "KK"), updateGroupDescriptionEvent(uuidMock(1), "KK"),
createPrivateGroupEvent()); createPrivateGroupEvent());
assertThat(groupService.findGroupWith("A", account("jesus"))).hasSize(2); assertThat(groupService.findGroupWith("A", account("jesus"))).hasSize(2);
assertThat(groupService.findGroupWith("F", account("jesus"))).hasSize(1); assertThat(groupService.findGroupWith("F", account("jesus"))).hasSize(1);