1

"finish" service refactor + fix obvious bugs after refactor (everything should run pretty much)

This commit is contained in:
Christoph
2020-04-08 20:48:42 +02:00
parent 9da2d51897
commit 482dde7960
48 changed files with 655 additions and 520 deletions

View File

@ -3,7 +3,9 @@ package mops.gruppen2.controller;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiParam;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.api.GroupRequestWrapper; import mops.gruppen2.domain.api.GroupRequestWrapper;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.service.APIService; import mops.gruppen2.service.APIService;
@ -25,6 +27,7 @@ import java.util.UUID;
//TODO: API-Service? //TODO: API-Service?
@RestController @RestController
@RequestMapping("/gruppen2/api") @RequestMapping("/gruppen2/api")
@Log4j2
public class APIController { public class APIController {
private final EventStoreService eventStoreService; private final EventStoreService eventStoreService;
@ -40,6 +43,7 @@ public class APIController {
@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 updateGroups(@ApiParam("Letzter Status des Anfragestellers") public GroupRequestWrapper updateGroups(@ApiParam("Letzter Status des Anfragestellers")
@PathVariable long lastEventId) throws EventException { @PathVariable long lastEventId) throws EventException {
log.info("ApiRequest to /updateGroups\n");
return APIService.wrap(eventStoreService.findMaxEventId(), return APIService.wrap(eventStoreService.findMaxEventId(),
projectionService.projectNewGroups(lastEventId)); projectionService.projectNewGroups(lastEventId));
} }
@ -49,7 +53,8 @@ public class APIController {
@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> getGroupIdsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen") public List<String> getGroupIdsOfUser(@ApiParam("Teilnehmer dessen groupIds zurückgegeben werden sollen")
@PathVariable String userId) { @PathVariable String userId) {
return IdService.uuidToString(eventStoreService.findExistingUserGroups(userId)); log.info("ApiRequest to /getGroupIdsOfUser\n");
return IdService.uuidsToString(eventStoreService.findExistingUserGroups(new User(userId)));
} }
@GetMapping("/getGroup/{groupId}") @GetMapping("/getGroup/{groupId}")
@ -57,6 +62,7 @@ public class APIController {
@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 getGroupById(@ApiParam("GruppenId der gefordeten Gruppe") public Group getGroupById(@ApiParam("GruppenId der gefordeten Gruppe")
@PathVariable String groupId) throws EventException { @PathVariable String groupId) throws EventException {
log.info("ApiRequest to /getGroup\n");
return projectionService.projectSingleGroup(UUID.fromString(groupId)); return projectionService.projectSingleGroup(UUID.fromString(groupId));
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.controller; package mops.gruppen2.controller;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; 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;
@ -21,25 +22,23 @@ import org.springframework.web.context.annotation.SessionScope;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.security.RolesAllowed; import javax.annotation.security.RolesAllowed;
import java.util.UUID;
import static mops.gruppen2.service.ControllerService.getGroupType; import static mops.gruppen2.service.ControllerService.getGroupType;
import static mops.gruppen2.service.ControllerService.getParent;
import static mops.gruppen2.service.ControllerService.getUserLimit; import static mops.gruppen2.service.ControllerService.getUserLimit;
import static mops.gruppen2.service.ControllerService.getVisibility; import static mops.gruppen2.service.ControllerService.getVisibility;
import static mops.gruppen2.service.IdService.uuidToString;
@Controller @Controller
@SessionScope @SessionScope
@RequestMapping("/gruppen2") @RequestMapping("/gruppen2")
@Log4j2
public class GroupCreationController { public class GroupCreationController {
private final GroupService groupService; private final GroupService groupService;
private final ValidationService validationService;
private final ProjectionService projectionService; private final ProjectionService projectionService;
public GroupCreationController(GroupService groupService, ValidationService validationService, ProjectionService projectionService) { public GroupCreationController(GroupService groupService, ProjectionService projectionService) {
this.groupService = groupService; this.groupService = groupService;
this.validationService = validationService;
this.projectionService = projectionService; this.projectionService = projectionService;
} }
@ -48,9 +47,9 @@ public class GroupCreationController {
public String createGroupAsOrga(KeycloakAuthenticationToken token, public String createGroupAsOrga(KeycloakAuthenticationToken token,
Model model) { Model model) {
Account account = new Account(token); log.info("GET to /createOrga\n");
model.addAttribute("account", account); model.addAttribute("account", new Account(token));
model.addAttribute("lectures", projectionService.projectLectures()); model.addAttribute("lectures", projectionService.projectLectures());
return "createOrga"; return "createOrga";
@ -66,25 +65,25 @@ public class GroupCreationController {
@RequestParam("lecture") boolean isLecture, @RequestParam("lecture") boolean isLecture,
@RequestParam("maxInfiniteUsers") boolean isInfinite, @RequestParam("maxInfiniteUsers") boolean isInfinite,
@RequestParam("userMaximum") long userLimit, @RequestParam("userMaximum") long userLimit,
@RequestParam(value = "parent", required = false) String parent, @RequestParam("parent") String parent,
@RequestParam(value = "file", required = false) MultipartFile file) { @RequestParam(value = "file", required = false) MultipartFile file) {
validationService.checkFields(description, title, userLimit, isInfinite); log.info("POST to /createOrga\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
UUID parentUUID = IdService.stringToUUID(parent);
Group group = groupService.createGroup(user, Group group = groupService.createGroup(user,
title, title,
description, description,
getVisibility(isPrivate), getVisibility(isPrivate),
getGroupType(isLecture), getGroupType(isLecture),
getUserLimit(isInfinite, userLimit), getUserLimit(isInfinite, userLimit),
parentUUID); getParent(parent, isLecture));
groupService.addUsersToGroup(CsvService.readCsvFile(file), group, user); groupService.addUsersToGroup(CsvService.readCsvFile(file), group, user);
return "redirect:/gruppen2/details/" + uuidToString(group.getId()); return "redirect:/gruppen2/details/" + IdService.uuidToString(group.getId());
} }
@RolesAllowed("ROLE_studentin") @RolesAllowed("ROLE_studentin")
@ -92,6 +91,8 @@ public class GroupCreationController {
public String createGroupAsStudent(KeycloakAuthenticationToken token, public String createGroupAsStudent(KeycloakAuthenticationToken token,
Model model) { Model model) {
log.info("GET to /createStudent\n");
model.addAttribute("account", new Account(token)); model.addAttribute("account", new Account(token));
model.addAttribute("lectures", projectionService.projectLectures()); model.addAttribute("lectures", projectionService.projectLectures());
@ -107,21 +108,23 @@ public class GroupCreationController {
@RequestParam("visibility") boolean isPrivate, @RequestParam("visibility") boolean isPrivate,
@RequestParam("maxInfiniteUsers") boolean isInfinite, @RequestParam("maxInfiniteUsers") boolean isInfinite,
@RequestParam("userMaximum") long userLimit, @RequestParam("userMaximum") long userLimit,
@RequestParam(value = "parent", required = false) String parent) { @RequestParam("parent") String parent) {
validationService.checkFields(description, title, userLimit, isInfinite); log.info("POST to /createStudent\n");
ValidationService.validateTitle(title);
ValidationService.validateDescription(description);
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
UUID parentUUID = IdService.stringToUUID(parent);
Group group = groupService.createGroup(user, Group group = groupService.createGroup(user,
title, title,
description, description,
getVisibility(isPrivate), getVisibility(isPrivate),
GroupType.SIMPLE, GroupType.SIMPLE,
getUserLimit(isInfinite, userLimit), getUserLimit(isInfinite, userLimit),
parentUUID); getParent(parent, false));
return "redirect:/gruppen2/details/" + uuidToString(group.getId()); return "redirect:/gruppen2/details/" + IdService.uuidToString(group.getId());
} }
} }

View File

@ -1,5 +1,6 @@
package mops.gruppen2.controller; package mops.gruppen2.controller;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; 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;
@ -30,15 +31,14 @@ import java.util.UUID;
@Controller @Controller
@SessionScope @SessionScope
@RequestMapping("/gruppen2") @RequestMapping("/gruppen2")
@Log4j2
public class GroupDetailsController { public class GroupDetailsController {
private final ValidationService validationService;
private final InviteService inviteService; private final InviteService inviteService;
private final GroupService groupService; private final GroupService groupService;
private final ProjectionService projectionService; private final ProjectionService projectionService;
public GroupDetailsController(ValidationService validationService, InviteService inviteService, GroupService groupService, ProjectionService projectionService) { public GroupDetailsController(InviteService inviteService, GroupService groupService, ProjectionService projectionService) {
this.validationService = validationService;
this.inviteService = inviteService; this.inviteService = inviteService;
this.groupService = groupService; this.groupService = groupService;
this.projectionService = projectionService; this.projectionService = projectionService;
@ -51,35 +51,37 @@ public class GroupDetailsController {
HttpServletRequest request, HttpServletRequest request,
@PathVariable("id") String groupId) { @PathVariable("id") String groupId) {
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); log.info("GET to /details\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
UUID parentId = group.getParent();
String actualURL = request.getRequestURL().toString();
String serverURL = actualURL.substring(0, actualURL.indexOf("gruppen2/"));
Group parent = projectionService.projectSingleGroup(parentId);
validationService.throwIfGroupNotExisting(group.getTitle());
model.addAttribute("account", account); model.addAttribute("account", account);
if (!validationService.checkIfUserInGroup(group, user)) {
validationService.throwIfNoAccessToPrivate(group, user); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
model.addAttribute("group", group); model.addAttribute("group", group);
model.addAttribute("parentId", parentId);
model.addAttribute("parent", parent); // Parent Badge
UUID parentId = group.getParent();
Group parent = projectionService.projectParent(parentId);
// Detailseite für private Gruppen
if (!ValidationService.checkIfGroupAccess(group, user)) {
return "detailsNoMember"; return "detailsNoMember";
} }
model.addAttribute("parentId", parentId);
model.addAttribute("parent", parent);
model.addAttribute("group", group);
model.addAttribute("roles", group.getRoles()); model.addAttribute("roles", group.getRoles());
model.addAttribute("user", user); model.addAttribute("user", user);
model.addAttribute("admin", Role.ADMIN); model.addAttribute("admin", Role.ADMIN);
model.addAttribute("public", Visibility.PUBLIC); model.addAttribute("public", Visibility.PUBLIC);
model.addAttribute("private", Visibility.PRIVATE); model.addAttribute("private", Visibility.PRIVATE);
model.addAttribute("parent", parent);
// Invitelink Anzeige für Admins
if (ValidationService.checkIfAdmin(group, user)) {
String actualURL = request.getRequestURL().toString();
String serverURL = actualURL.substring(0, actualURL.indexOf("gruppen2/"));
if (validationService.checkIfAdmin(group, user)) {
model.addAttribute("link", serverURL + "gruppen2/acceptinvite/" + inviteService.getLinkByGroup(group)); model.addAttribute("link", serverURL + "gruppen2/acceptinvite/" + inviteService.getLinkByGroup(group));
} }
@ -92,11 +94,13 @@ public class GroupDetailsController {
Model model, Model model,
@PathVariable("id") String groupId) { @PathVariable("id") String groupId) {
log.info("GET to /details/changeMetadata\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
validationService.throwIfNoAdmin(group, user); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
ValidationService.throwIfNoAdmin(group, user);
model.addAttribute("account", account); model.addAttribute("account", account);
model.addAttribute("title", group.getTitle()); model.addAttribute("title", group.getTitle());
@ -117,13 +121,13 @@ public class GroupDetailsController {
@RequestParam("description") String description, @RequestParam("description") String description,
@RequestParam("groupId") String groupId) { @RequestParam("groupId") String groupId) {
log.info("POST to /details/changeMetadata\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
ValidationService.throwIfNoAdmin(group, user);
validationService.throwIfNoAdmin(group, user);
validationService.checkFields(title, description);
groupService.updateTitle(user, group, title); groupService.updateTitle(user, group, title);
groupService.updateDescription(user, group, description); groupService.updateDescription(user, group, description);
@ -136,11 +140,13 @@ public class GroupDetailsController {
Model model, Model model,
@PathVariable("id") String groupId) { @PathVariable("id") String groupId) {
log.info("GET to /details/members\n");
Account account = new Account(token); Account account = new Account(token);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
User user = new User(account); User user = new User(account);
validationService.throwIfNoAdmin(group, user); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
ValidationService.throwIfNoAdmin(group, user);
model.addAttribute("account", account); model.addAttribute("account", account);
model.addAttribute("members", group.getMembers()); model.addAttribute("members", group.getMembers());
@ -157,15 +163,17 @@ public class GroupDetailsController {
@RequestParam("group_id") String groupId, @RequestParam("group_id") String groupId,
@RequestParam("user_id") String userId) { @RequestParam("user_id") String userId) {
log.info("POST to /details/members/changeRole\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
User principle = new User(account); ValidationService.throwIfNoAdmin(group, user);
User user = new User(userId); groupService.toggleMemberRole(new User(userId), group);
validationService.throwIfNoAdmin(group, principle); // Falls sich der User selbst die Rechte genommen hat
groupService.toggleMemberRole(user, group); if (!ValidationService.checkIfAdmin(group, user)) {
if (!validationService.checkIfAdmin(group, principle)) {
return "redirect:/gruppen2/details/" + groupId; return "redirect:/gruppen2/details/" + groupId;
} }
@ -179,12 +187,12 @@ public class GroupDetailsController {
@RequestParam("maximum") long userLimit, @RequestParam("maximum") long userLimit,
@RequestParam("group_id") String groupId) { @RequestParam("group_id") String groupId) {
log.info("POST to /details/members/changeMaximum\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
validationService.throwIfNewUserLimitIsValid(userLimit, group);
groupService.updateUserLimit(user, group, userLimit); groupService.updateUserLimit(user, group, userLimit);
return "redirect:/gruppen2/details/members/" + groupId; return "redirect:/gruppen2/details/members/" + groupId;
@ -197,17 +205,15 @@ public class GroupDetailsController {
@RequestParam("group_id") String groupId, @RequestParam("group_id") String groupId,
@RequestParam("user_id") String userId) { @RequestParam("user_id") String userId) {
log.info("POST to /details/members/deleteUser\n");
Account account = new Account(token); Account account = new Account(token);
User principle = new User(account); User user = new User(account);
User user = new User(userId, "", "", "");
// Der eingeloggte User kann sich nicht selbst entfernen
if (!userId.equals(user.getId())) {
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
groupService.deleteUser(new User(userId), group);
validationService.throwIfNoAdmin(group, principle);
groupService.deleteUser(user, group);
if (!validationService.checkIfUserInGroup(group, principle)) {
return "redirect:/gruppen2";
} }
return "redirect:/gruppen2/details/members/" + groupId; return "redirect:/gruppen2/details/members/" + groupId;
@ -220,17 +226,16 @@ public class GroupDetailsController {
Model model, Model model,
@RequestParam("id") String groupId) { @RequestParam("id") String groupId) {
log.info("POST to /detailsBeitreten\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
validationService.throwIfUserAlreadyInGroup(group, user);
validationService.throwIfGroupFull(group);
groupService.addUser(user, group);
model.addAttribute("account", account); model.addAttribute("account", account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
groupService.addUser(user, group);
return "redirect:/gruppen2"; return "redirect:/gruppen2";
} }
@ -240,10 +245,12 @@ public class GroupDetailsController {
public String leaveGroup(KeycloakAuthenticationToken token, public String leaveGroup(KeycloakAuthenticationToken token,
@RequestParam("group_id") String groupId) { @RequestParam("group_id") String groupId) {
log.info("POST to /leaveGroup\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
groupService.deleteUser(user, group); groupService.deleteUser(user, group);
return "redirect:/gruppen2"; return "redirect:/gruppen2";
@ -255,12 +262,12 @@ public class GroupDetailsController {
public String deleteGroup(KeycloakAuthenticationToken token, public String deleteGroup(KeycloakAuthenticationToken token,
@RequestParam("group_id") String groupId) { @RequestParam("group_id") String groupId) {
log.info("POST to /deleteGroup\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
validationService.throwIfNoAdmin(group, user);
groupService.deleteGroup(user, group); groupService.deleteGroup(user, group);
return "redirect:/gruppen2"; return "redirect:/gruppen2";
@ -273,10 +280,12 @@ public class GroupDetailsController {
@RequestParam("group_id") String groupId, @RequestParam("group_id") String groupId,
@RequestParam(value = "file", required = false) MultipartFile file) { @RequestParam(value = "file", required = false) MultipartFile file) {
log.info("POST to /details/members/addUsersFromCsv\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(IdService.stringToUUID(groupId));
Group group = projectionService.projectSingleGroup(IdService.stringToUUID(groupId));
groupService.addUsersToGroup(CsvService.readCsvFile(file), group, user); groupService.addUsersToGroup(CsvService.readCsvFile(file), group, user);
return "redirect:/gruppen2/details/members/" + groupId; return "redirect:/gruppen2/details/members/" + groupId;

View File

@ -1,6 +1,8 @@
package mops.gruppen2.controller; package mops.gruppen2.controller;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.PageNotFoundException; import mops.gruppen2.domain.exception.PageNotFoundException;
import mops.gruppen2.service.ProjectionService; import mops.gruppen2.service.ProjectionService;
@ -14,6 +16,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@Controller @Controller
@Log4j2
public class GruppenfindungController { public class GruppenfindungController {
private final ProjectionService projectionService; private final ProjectionService projectionService;
@ -32,12 +35,15 @@ public class GruppenfindungController {
public String index(KeycloakAuthenticationToken token, public String index(KeycloakAuthenticationToken token,
Model model) { Model model) {
log.info("GET to /gruppen2\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
model.addAttribute("account", account); model.addAttribute("account", account);
model.addAttribute("gruppen", projectionService.projectUserGroups(user.getId())); model.addAttribute("gruppen", projectionService.projectUserGroups(user));
model.addAttribute("user", user); model.addAttribute("user", user);
model.addAttribute("lecture", GroupType.LECTURE);
return "index"; return "index";
} }

View File

@ -1,12 +1,15 @@
package mops.gruppen2.controller; package mops.gruppen2.controller;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account; import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
import mops.gruppen2.service.GroupService; import mops.gruppen2.service.GroupService;
import mops.gruppen2.service.InviteService; import mops.gruppen2.service.InviteService;
import mops.gruppen2.service.ProjectionService; import mops.gruppen2.service.ProjectionService;
import mops.gruppen2.service.SearchService;
import mops.gruppen2.service.ValidationService; import mops.gruppen2.service.ValidationService;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
@ -20,40 +23,61 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.annotation.SessionScope; import org.springframework.web.context.annotation.SessionScope;
import javax.annotation.security.RolesAllowed; import javax.annotation.security.RolesAllowed;
import java.util.ArrayList; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@Controller @Controller
@SessionScope @SessionScope
@RequestMapping("/gruppen2") @RequestMapping("/gruppen2")
@Log4j2
public class SearchAndInviteController { public class SearchAndInviteController {
private final ValidationService validationService;
private final InviteService inviteService; private final InviteService inviteService;
private final GroupService groupService; private final GroupService groupService;
private final ProjectionService projectionService; private final ProjectionService projectionService;
private final SearchService searchService;
public SearchAndInviteController(ValidationService validationService, InviteService inviteService, GroupService groupService, ProjectionService projectionService) { public SearchAndInviteController(InviteService inviteService, GroupService groupService, ProjectionService projectionService, SearchService searchService) {
this.validationService = validationService;
this.inviteService = inviteService; this.inviteService = inviteService;
this.groupService = groupService; this.groupService = groupService;
this.projectionService = projectionService; this.projectionService = projectionService;
this.searchService = searchService;
} }
@RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"}) @RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"})
@GetMapping("/findGroup") @GetMapping("/searchPage")
public String findGroup(KeycloakAuthenticationToken token, public String findGroup(KeycloakAuthenticationToken token,
Model model, Model model) {
@RequestParam(value = "suchbegriff", required = false) String search) {
log.info("GET to /searchPage\n");
Account account = new Account(token); Account account = new Account(token);
List<Group> groups = new ArrayList<>(); User user = new User(account);
groups = validationService.checkSearch(search, groups, account);
model.addAttribute("account", account);
model.addAttribute("gruppen", Collections.emptyList()); // TODO: verschönern
model.addAttribute("inviteService", inviteService); //TODO: don't inject service
return "search";
}
@RolesAllowed({"ROLE_orga", "ROLE_studentin", "ROLE_actuator"})
@GetMapping("/search")
public String search(KeycloakAuthenticationToken token,
Model model,
@RequestParam("suchbegriff") String search) {
log.info("GET to /search\n");
Account account = new Account(token);
User user = new User(account);
List<Group> groups = searchService.searchPublicGroups(search, user);
model.addAttribute("account", account); model.addAttribute("account", account);
model.addAttribute("gruppen", groups); model.addAttribute("gruppen", groups);
model.addAttribute("inviteService", inviteService); model.addAttribute("inviteService", inviteService); //TODO: don't inject service
return "search"; return "search";
} }
@ -64,20 +88,26 @@ public class SearchAndInviteController {
Model model, Model model,
@RequestParam("id") String groupId) { @RequestParam("id") String groupId) {
log.info("GET to /detailsSearch\n");
Account account = new Account(token); Account account = new Account(token);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
UUID parentId = group.getParent();
Group parent = projectionService.projectSingleGroup(parentId);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
// Parent Badge
UUID parentId = group.getParent();
Group parent = projectionService.projectParent(parentId);
model.addAttribute("account", account); model.addAttribute("account", account);
if (validationService.checkIfUserInGroup(group, user)) { if (ValidationService.checkIfMember(group, user)) {
return "redirect:/gruppen2/details/" + groupId; return "redirect:/gruppen2/details/" + groupId;
} }
model.addAttribute("group", group); model.addAttribute("group", group);
model.addAttribute("parentId", parentId); model.addAttribute("parentId", parentId);
model.addAttribute("parent", parent); model.addAttribute("parent", parent);
model.addAttribute("lecture", GroupType.LECTURE);
return "detailsNoMember"; return "detailsNoMember";
} }
@ -88,17 +118,26 @@ public class SearchAndInviteController {
Model model, Model model,
@PathVariable("link") String link) { @PathVariable("link") String link) {
log.info("GET to /acceptInvite\n");
Account account = new Account(token);
User user = new User(account);
Group group = projectionService.projectSingleGroup(inviteService.getGroupIdFromLink(link)); Group group = projectionService.projectSingleGroup(inviteService.getGroupIdFromLink(link));
validationService.throwIfGroupNotExisting(group.getTitle()); model.addAttribute("account", account);
model.addAttribute("account", new Account(token));
model.addAttribute("group", group); model.addAttribute("group", group);
// Gruppe öffentlich
if (group.getVisibility() == Visibility.PUBLIC) { if (group.getVisibility() == Visibility.PUBLIC) {
return "redirect:/gruppen2/details/" + group.getId(); return "redirect:/gruppen2/details/" + group.getId();
} }
// Bereits Mitglied
if (ValidationService.checkIfMember(group, user)) {
return "redirect:/gruppen2/details/" + group.getId();
}
return "joinprivate"; return "joinprivate";
} }
@ -108,12 +147,14 @@ public class SearchAndInviteController {
public String postAcceptInvite(KeycloakAuthenticationToken token, public String postAcceptInvite(KeycloakAuthenticationToken token,
@RequestParam("id") String groupId) { @RequestParam("id") String groupId) {
log.info("POST to /acceptInvite\n");
Account account = new Account(token); Account account = new Account(token);
User user = new User(account); User user = new User(account);
Group group = projectionService.projectSingleGroup(UUID.fromString(groupId)); Group group = projectionService.projectSingleGroup(UUID.fromString(groupId));
validationService.throwIfUserAlreadyInGroup(group, user); ValidationService.throwIfMember(group, user);
validationService.throwIfGroupFull(group); ValidationService.throwIfGroupFull(group);
groupService.addUser(user, group); groupService.addUser(user, group);

View File

@ -3,6 +3,7 @@ package mops.gruppen2.domain;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -16,26 +17,29 @@ import java.util.UUID;
@Getter @Getter
@Setter @Setter
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString
public class Group { public class Group {
@EqualsAndHashCode.Include @EqualsAndHashCode.Include
private UUID id; private UUID id;
@ToString.Exclude
private UUID parent; private UUID parent;
//TODO: Single Type for Public/Private/Lecture?
private GroupType type; private GroupType type;
private Visibility visibility; private Visibility visibility;
private String title; private String title;
private String description; private String description;
private long userLimit;
// Default + Minimum: 1
@ToString.Exclude
private long userLimit = 1;
//TODO: List to Hashmap //TODO: List to Hashmap
@ToString.Exclude
private final List<User> members = new ArrayList<>(); private final List<User> members = new ArrayList<>();
@ToString.Exclude
private final Map<String, Role> roles = new HashMap<>(); private final Map<String, Role> roles = new HashMap<>();
@Override
public String toString() {
return title + ": " + description;
}
} }

View File

@ -4,18 +4,22 @@ import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor // Für Jackson: CSV-Import @NoArgsConstructor // Für Jackson: CSV-Import
@EqualsAndHashCode(onlyExplicitlyIncluded = true) @EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString
public class User { public class User {
@EqualsAndHashCode.Include @EqualsAndHashCode.Include
private String id; private String id;
private String givenname; private String givenname;
@ToString.Exclude
private String familyname; private String familyname;
@ToString.Exclude
private String email; private String email;
public User(Account account) { public User(Account account) {

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
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;
@ -16,6 +18,8 @@ import java.util.UUID;
*/ */
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class AddUserEvent extends Event { public class AddUserEvent extends Event {
private String givenname; private String givenname;
@ -50,5 +54,8 @@ public class AddUserEvent extends Event {
group.getMembers().add(user); group.getMembers().add(user);
group.getRoles().put(userId, Role.MEMBER); group.getRoles().put(userId, Role.MEMBER);
log.trace("\t\t\t\t\tNeue Members: {}", group.getMembers());
log.trace("\t\t\t\t\tNeue Rollen: {}", group.getRoles());
} }
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
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;
@ -10,19 +12,19 @@ import java.util.UUID;
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class CreateGroupEvent extends Event { public class CreateGroupEvent extends Event {
private Visibility groupVisibility; private Visibility groupVisibility;
private UUID groupParent; private UUID groupParent;
private GroupType groupType; private GroupType groupType;
private long groupUserLimit;
public CreateGroupEvent(UUID groupId, String userId, UUID parent, GroupType type, Visibility visibility, long userLimit) { public CreateGroupEvent(UUID groupId, String userId, UUID parent, GroupType type, Visibility visibility) {
super(groupId, userId); super(groupId, userId);
groupParent = parent; groupParent = parent;
groupType = type; groupType = type;
groupVisibility = visibility; groupVisibility = visibility;
groupUserLimit = userLimit;
} }
@Override @Override
@ -31,6 +33,7 @@ public class CreateGroupEvent extends Event {
group.setParent(groupParent); group.setParent(groupParent);
group.setType(groupType); group.setType(groupType);
group.setVisibility(groupVisibility); group.setVisibility(groupVisibility);
group.setUserLimit(groupUserLimit);
log.trace("\t\t\t\t\tNeue Gruppe: {}", group.toString());
} }
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
@ -9,6 +11,8 @@ import java.util.UUID;
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class DeleteGroupEvent extends Event { public class DeleteGroupEvent extends Event {
public DeleteGroupEvent(UUID groupId, String userId) { public DeleteGroupEvent(UUID groupId, String userId) {
@ -29,5 +33,7 @@ public class DeleteGroupEvent extends Event {
group.setType(null); group.setType(null);
group.setParent(null); group.setParent(null);
group.setUserLimit(0L); group.setUserLimit(0L);
log.trace("\t\t\t\t\tGelöschte Gruppe: {}", group);
} }
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
@ -14,6 +16,8 @@ import java.util.UUID;
*/ */
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class DeleteUserEvent extends Event { public class DeleteUserEvent extends Event {
public DeleteUserEvent(UUID groupId, String userId) { public DeleteUserEvent(UUID groupId, String userId) {
@ -24,12 +28,17 @@ public class DeleteUserEvent extends Event {
super(group.getId(), user.getId()); super(group.getId(), user.getId());
} }
//TODO: what the fuck use List.remove
@Override @Override
protected void applyEvent(Group group) throws EventException { protected void applyEvent(Group group) throws EventException {
for (User user : group.getMembers()) { for (User user : group.getMembers()) {
if (user.getId().equals(userId)) { if (user.getId().equals(userId)) {
group.getMembers().remove(user); group.getMembers().remove(user);
group.getRoles().remove(user.getId()); group.getRoles().remove(user.getId());
log.trace("\t\t\t\t\tNeue Members: {}", group.getMembers());
log.trace("\t\t\t\t\tNeue Rollen: {}", group.getRoles());
return; return;
} }
} }

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import mops.gruppen2.domain.exception.GroupIdMismatchException; import mops.gruppen2.domain.exception.GroupIdMismatchException;
@ -12,6 +13,7 @@ import mops.gruppen2.domain.exception.GroupIdMismatchException;
import java.util.UUID; import java.util.UUID;
@Log4j2
@JsonTypeInfo( @JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, use = JsonTypeInfo.Id.NAME,
property = "type" property = "type"
@ -34,18 +36,26 @@ public abstract class Event {
protected UUID groupId; protected UUID groupId;
protected String userId; protected String userId;
public void apply(Group group) throws EventException { public Group apply(Group group) throws EventException {
checkGroupIdMatch(group.getId()); checkGroupIdMatch(group.getId());
log.trace("Event angewendet:\t{}", this);
applyEvent(group); applyEvent(group);
return group;
} }
private void checkGroupIdMatch(UUID groupId) { private void checkGroupIdMatch(UUID groupId) {
if (groupId == null || this.groupId.equals(groupId)) { // CreateGroupEvents müssen die Id erst initialisieren
if (this instanceof CreateGroupEvent) {
return; return;
} }
if (!this.groupId.equals(groupId)) {
throw new GroupIdMismatchException(getClass().toString()); throw new GroupIdMismatchException(getClass().toString());
} }
}
protected abstract void applyEvent(Group group) throws EventException; protected abstract void applyEvent(Group group) throws EventException;
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.BadParameterException; import mops.gruppen2.domain.exception.BadParameterException;
@ -13,6 +15,8 @@ import java.util.UUID;
*/ */
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class UpdateGroupDescriptionEvent extends Event { public class UpdateGroupDescriptionEvent extends Event {
private String newGroupDescription; private String newGroupDescription;
@ -34,5 +38,7 @@ public class UpdateGroupDescriptionEvent extends Event {
} }
group.setDescription(newGroupDescription); group.setDescription(newGroupDescription);
log.trace("\t\t\t\t\tNeue Beschreibung: {}", group.getDescription());
} }
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.BadParameterException; import mops.gruppen2.domain.exception.BadParameterException;
@ -13,6 +15,8 @@ import java.util.UUID;
*/ */
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class UpdateGroupTitleEvent extends Event { public class UpdateGroupTitleEvent extends Event {
private String newGroupTitle; private String newGroupTitle;
@ -34,6 +38,8 @@ public class UpdateGroupTitleEvent extends Event {
} }
group.setTitle(newGroupTitle); group.setTitle(newGroupTitle);
log.trace("\t\t\t\t\tNeuer Titel: {}", group.getTitle());
} }
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
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;
@ -14,6 +16,8 @@ import java.util.UUID;
*/ */
@Getter @Getter
@NoArgsConstructor // For Jackson @NoArgsConstructor // For Jackson
@ToString
@Log4j2
public class UpdateRoleEvent extends Event { public class UpdateRoleEvent extends Event {
private Role newRole; private Role newRole;
@ -32,6 +36,9 @@ public class UpdateRoleEvent extends Event {
protected void applyEvent(Group group) throws UserNotFoundException { protected void applyEvent(Group group) throws UserNotFoundException {
if (group.getRoles().containsKey(userId)) { if (group.getRoles().containsKey(userId)) {
group.getRoles().put(userId, newRole); group.getRoles().put(userId, newRole);
log.trace("\t\t\t\t\tNeue Rollen: {}", group.getRoles());
return; return;
} }

View File

@ -2,6 +2,8 @@ package mops.gruppen2.domain.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User; import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.BadParameterException; import mops.gruppen2.domain.exception.BadParameterException;
@ -11,6 +13,8 @@ import java.util.UUID;
@Getter @Getter
@NoArgsConstructor @NoArgsConstructor
@ToString
@Log4j2
public class UpdateUserLimitEvent extends Event { public class UpdateUserLimitEvent extends Event {
private long userLimit; private long userLimit;
@ -32,5 +36,7 @@ public class UpdateUserLimitEvent extends Event {
} }
group.setUserLimit(userLimit); group.setUserLimit(userLimit);
log.trace("\t\t\t\t\tNeues UserLimit: {}", group.getUserLimit());
} }
} }

View File

@ -5,6 +5,6 @@ import org.springframework.http.HttpStatus;
public class UserNotFoundException extends EventException { public class UserNotFoundException extends EventException {
public UserNotFoundException(String info) { public UserNotFoundException(String info) {
super(HttpStatus.NOT_FOUND, "Der User wurde nicht gefunden.", info); super(HttpStatus.NOT_FOUND, "Der User existiert nicht.", info);
} }
} }

View File

@ -5,6 +5,8 @@ import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.UUID;
@Service @Service
@Log4j2 @Log4j2
@ -33,4 +35,10 @@ public final class ControllerService {
return isInfinite ? Long.MAX_VALUE : userLimit; return isInfinite ? Long.MAX_VALUE : userLimit;
} }
/**
* Ermittelt die UUID des Parents, falls vorhanden.
*/
public static UUID getParent(String parent, boolean isLecture) {
return isLecture ? IdService.emptyUUID() : IdService.stringToUUID(parent);
}
} }

View File

@ -23,23 +23,20 @@ public final class CsvService {
private CsvService() {} private CsvService() {}
public static List<User> readCsvFile(MultipartFile file) throws EventException { public static List<User> readCsvFile(MultipartFile file) throws EventException {
if (file == null) { if (file == null || file.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
if (!file.isEmpty()) {
try { try {
List<User> userList = read(file.getInputStream()); List<User> userList = read(file.getInputStream());
return userList.stream() return userList.stream()
.distinct() .distinct()
.collect(Collectors.toList()); //filter duplicates from list .collect(Collectors.toList()); //filter duplicates from list
} catch (IOException e) { } catch (IOException e) {
log.error("File konnte nicht gelesen werden:\n{}", e.getMessage()); log.error("File konnte nicht gelesen werden!", e);
e.printStackTrace();
throw new WrongFileException(file.getOriginalFilename()); throw new WrongFileException(file.getOriginalFilename());
} }
} }
return Collections.emptyList();
}
private static List<User> read(InputStream stream) throws IOException { private static List<User> read(InputStream stream) throws IOException {
CsvMapper mapper = new CsvMapper(); CsvMapper mapper = new CsvMapper();

View File

@ -1,11 +0,0 @@
package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
@Service
@Log4j2
public final class EventBuilderService {
private EventBuilderService() {}
}

View File

@ -2,6 +2,7 @@ package mops.gruppen2.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.dto.EventDTO; import mops.gruppen2.domain.dto.EventDTO;
import mops.gruppen2.domain.event.AddUserEvent; import mops.gruppen2.domain.event.AddUserEvent;
import mops.gruppen2.domain.event.CreateGroupEvent; import mops.gruppen2.domain.event.CreateGroupEvent;
@ -86,8 +87,7 @@ public class EventStoreService {
getEventType(event), getEventType(event),
payload); payload);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
log.error("Event ({}) konnte nicht serialisiert werden!", e.getMessage()); log.error("Event ({}) konnte nicht serialisiert werden!", event, e);
e.printStackTrace();
throw new BadPayloadException(EventStoreService.class.toString()); throw new BadPayloadException(EventStoreService.class.toString());
} }
} }
@ -109,8 +109,7 @@ public class EventStoreService {
try { try {
return JsonService.deserializeEvent(dto.getEvent_payload()); return JsonService.deserializeEvent(dto.getEvent_payload());
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
log.error("Payload\n {}\n konnte nicht deserialisiert werden!", e.getMessage()); log.error("Payload {} konnte nicht deserialisiert werden!", dto.getEvent_payload(), e);
e.printStackTrace();
throw new BadPayloadException(EventStoreService.class.toString()); throw new BadPayloadException(EventStoreService.class.toString());
} }
} }
@ -164,7 +163,7 @@ public class EventStoreService {
List<String> changedGroupIds = eventStore.findGroupIdsWhereEventIdGreaterThanStatus(status); List<String> changedGroupIds = eventStore.findGroupIdsWhereEventIdGreaterThanStatus(status);
List<EventDTO> groupEventDTOS = eventStore.findEventDTOsByGroup(changedGroupIds); List<EventDTO> groupEventDTOS = eventStore.findEventDTOsByGroup(changedGroupIds);
log.trace("Seit Event {} haben sich {} Gruppen geändert!", status, changedGroupIds.size()); log.debug("Seit Event {} haben sich {} Gruppen geändert!", status, changedGroupIds.size());
return getEventsFromDTOs(groupEventDTOS); return getEventsFromDTOs(groupEventDTOS);
} }
@ -189,8 +188,14 @@ public class EventStoreService {
* *
* @return GruppenIds (UUID) als Liste * @return GruppenIds (UUID) als Liste
*/ */
public List<UUID> findExistingUserGroups(String userId) { public List<UUID> findExistingUserGroups(User user) {
List<Event> userEvents = findLatestEventsFromGroupsByUser(userId); List<Event> userEvents = findLatestEventsFromGroupsByUser(user);
List<UUID> deletedIds = findLatestEventsFromGroupsByType("DeleteGroupEvent")
.stream()
.map(Event::getGroupId)
.collect(Collectors.toList());
userEvents.removeIf(event -> deletedIds.contains(event.getGroupId()));
return userEvents.stream() return userEvents.stream()
.filter(event -> event instanceof AddUserEvent) .filter(event -> event instanceof AddUserEvent)
@ -211,8 +216,7 @@ public class EventStoreService {
try { try {
return eventStore.findMaxEventId(); return eventStore.findMaxEventId();
} catch (NullPointerException e) { } catch (NullPointerException e) {
log.trace("Eine maxId von 0 wurde zurückgegeben, da keine Events vorhanden sind."); log.debug("Keine Events vorhanden!");
e.printStackTrace();
return 0; return 0;
} }
} }
@ -227,18 +231,18 @@ public class EventStoreService {
List<Event> findEventsByGroupAndType(List<UUID> groupIds, String... types) { List<Event> findEventsByGroupAndType(List<UUID> groupIds, String... types) {
return getEventsFromDTOs(eventStore.findEventDTOsByGroupAndType(Arrays.asList(types), return getEventsFromDTOs(eventStore.findEventDTOsByGroupAndType(Arrays.asList(types),
IdService.uuidToString(groupIds))); IdService.uuidsToString(groupIds)));
} }
/** /**
* Sucht zu jeder Gruppe das letzte Add- oder DeleteUserEvent heraus, welches den übergebenen User betrifft. * Sucht zu jeder Gruppe das letzte Add- oder DeleteUserEvent heraus, welches den übergebenen User betrifft.
* *
* @param userId User, zu welchem die Events gesucht werden * @param user User, zu welchem die Events gesucht werden
* *
* @return Eine Liste von einem Add- oder DeleteUserEvent pro Gruppe * @return Eine Liste von einem Add- oder DeleteUserEvent pro Gruppe
*/ */
List<Event> findLatestEventsFromGroupsByUser(String userId) { List<Event> findLatestEventsFromGroupsByUser(User user) {
return getEventsFromDTOs(eventStore.findLatestEventDTOsPartitionedByGroupByUser(userId)); return getEventsFromDTOs(eventStore.findLatestEventDTOsPartitionedByGroupByUser(user.getId()));
} }

View File

@ -18,7 +18,6 @@ import mops.gruppen2.domain.event.UpdateUserLimitEvent;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -31,12 +30,10 @@ import java.util.UUID;
public class GroupService { public class GroupService {
private final EventStoreService eventStoreService; private final EventStoreService eventStoreService;
private final ValidationService validationService;
private final InviteService inviteService; private final InviteService inviteService;
public GroupService(EventStoreService eventStoreService, ValidationService validationService, InviteService inviteService) { public GroupService(EventStoreService eventStoreService, InviteService inviteService) {
this.eventStoreService = eventStoreService; this.eventStoreService = eventStoreService;
this.validationService = validationService;
this.inviteService = inviteService; this.inviteService = inviteService;
} }
@ -45,9 +42,7 @@ public class GroupService {
/** /**
* 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 und erzeugt nötige Events für die Initiale Setzung der Attribute.
* 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.
* *
* @param user Keycloak-Account * @param user Keycloak-Account
* @param title Gruppentitel * @param title Gruppentitel
@ -61,12 +56,18 @@ public class GroupService {
long userLimit, long userLimit,
UUID parent) { UUID parent) {
Group group = createGroup(user, parent, groupType, visibility, userLimit); // Regeln:
// isPrivate -> !isLecture
// isLecture -> !isPrivate
ValidationService.validateFlags(visibility, groupType);
Group group = createGroup(user, parent, groupType, visibility);
// Die Reihenfolge ist wichtig, da der ausführende User Admin sein muss
addUser(user, group); addUser(user, group);
updateRole(user, group, Role.ADMIN);
updateTitle(user, group, title); updateTitle(user, group, title);
updateDescription(user, group, description); updateDescription(user, group, description);
updateRole(user, group, Role.ADMIN); updateUserLimit(user, group, userLimit);
inviteService.createLink(group); inviteService.createLink(group);
@ -78,7 +79,7 @@ public class GroupService {
/** /**
* Fügt eine Liste von Usern zu einer Gruppe hinzu (in der Datenbank). * Fügt eine Liste von Usern zu einer Gruppe hinzu.
* Duplikate werden übersprungen, die erzeugten Events werden gespeichert. * Duplikate werden übersprungen, die erzeugten Events werden gespeichert.
* Dabei wird das Teilnehmermaximum eventuell angehoben. * Dabei wird das Teilnehmermaximum eventuell angehoben.
* *
@ -103,7 +104,7 @@ public class GroupService {
* @return Das neue Teilnehmermaximum * @return Das neue Teilnehmermaximum
*/ */
private static long getAdjustedUserLimit(List<User> newUsers, Group group) { private static long getAdjustedUserLimit(List<User> newUsers, Group group) {
return Math.max(group.getMembers().size() + newUsers.size(), group.getMembers().size()); return Math.max(group.getMembers().size() + newUsers.size(), group.getUserLimit());
} }
/** /**
@ -115,7 +116,8 @@ public class GroupService {
* @throws EventException Falls der User nicht gefunden wird * @throws EventException Falls der User nicht gefunden wird
*/ */
public void toggleMemberRole(User user, Group group) throws EventException { public void toggleMemberRole(User user, Group group) throws EventException {
validationService.throwIfNotInGroup(group, user); ValidationService.throwIfNoMember(group, user);
ValidationService.throwIfLastAdmin(user, group);
Role role = group.getRoles().get(user.getId()); Role role = group.getRoles().get(user.getId());
updateRole(user, group, role.toggle()); updateRole(user, group, role.toggle());
@ -126,25 +128,26 @@ public class GroupService {
// Spezifische Events werden erzeugt, validiert, auf die Gruppe angewandt und gespeichert // Spezifische Events werden erzeugt, validiert, auf die Gruppe angewandt und gespeichert
//TODO: more validation /**
private Group createGroup(User user, UUID parent, GroupType groupType, Visibility visibility, long userLimit) { * Erzeugt eine Gruppe, speichert diese und gibt diese zurück.
*/
private Group createGroup(User user, UUID parent, GroupType groupType, Visibility visibility) {
Event event = new CreateGroupEvent(UUID.randomUUID(), Event event = new CreateGroupEvent(UUID.randomUUID(),
user.getId(), user.getId(),
parent, parent,
groupType, visibility, groupType,
userLimit); visibility);
Group group = ProjectionService.projectSingleGroup(Collections.singletonList(event)); Group group = new Group();
event.apply(group);
log.trace("Es wurde eine Gruppe erstellt. ({}, {})", visibility, group.getId());
eventStoreService.saveEvent(event); eventStoreService.saveEvent(event);
return group; return group;
} }
//TODO: test if exception interrupts runtime
public void addUser(User user, Group group) { public void addUser(User user, Group group) {
validationService.throwIfUserAlreadyInGroup(group, user); ValidationService.throwIfMember(group, user);
ValidationService.throwIfGroupFull(group);
Event event = new AddUserEvent(group, user); Event event = new AddUserEvent(group, user);
event.apply(group); event.apply(group);
@ -159,45 +162,48 @@ public class GroupService {
try { try {
addUser(user, group); addUser(user, group);
} catch (Exception e) { } catch (Exception e) {
log.trace("Doppelter User wurde nicht hinzugefügt ({})!", user.getId()); log.debug("Doppelter User {} wurde nicht zu Gruppe {} hinzugefügt!", user, group);
} }
} }
public void deleteUser(User user, Group group) throws EventException { public void deleteUser(User user, Group group) throws EventException {
validationService.throwIfNotInGroup(group, user); ValidationService.throwIfNoMember(group, user);
validationService.throwIfLastAdmin(user, group); ValidationService.throwIfLastAdmin(user, group);
if (ValidationService.checkIfGroupEmpty(group)) {
deleteGroup(user, group);
} else {
Event event = new DeleteUserEvent(group, user); Event event = new DeleteUserEvent(group, user);
event.apply(group); event.apply(group);
eventStoreService.saveEvent(event); eventStoreService.saveEvent(event);
if (validationService.checkIfGroupEmpty(group)) {
deleteGroup(user, group);
} }
} }
public void deleteGroup(User user, Group group) { public void deleteGroup(User user, Group group) {
inviteService.destroyLink(group); ValidationService.throwIfNoAdmin(group, user);
log.trace("Eine Gruppe wurde gelöscht ({})", group.getId());
Event event = new DeleteGroupEvent(group, user); Event event = new DeleteGroupEvent(group, user);
event.apply(group); event.apply(group);
inviteService.destroyLink(group);
eventStoreService.saveEvent(event); eventStoreService.saveEvent(event);
} }
//TODO: Validate title
public void updateTitle(User user, Group group, String title) { public void updateTitle(User user, Group group, String title) {
ValidationService.throwIfNoAdmin(group, user);
ValidationService.validateTitle(title);
Event event = new UpdateGroupTitleEvent(group, user, title); Event event = new UpdateGroupTitleEvent(group, user, title);
event.apply(group); event.apply(group);
eventStoreService.saveEvent(event); eventStoreService.saveEvent(event);
} }
//TODO: Validate description
public void updateDescription(User user, Group group, String description) { public void updateDescription(User user, Group group, String description) {
ValidationService.throwIfNoAdmin(group, user);
ValidationService.validateDescription(description);
Event event = new UpdateGroupDescriptionEvent(group, user, description); Event event = new UpdateGroupDescriptionEvent(group, user, description);
event.apply(group); event.apply(group);
@ -205,14 +211,22 @@ public class GroupService {
} }
public void updateRole(User user, Group group, Role role) { public void updateRole(User user, Group group, Role role) {
ValidationService.throwIfNoMember(group, user);
Event event = new UpdateRoleEvent(group, user, role); Event event = new UpdateRoleEvent(group, user, role);
event.apply(group); event.apply(group);
eventStoreService.saveEvent(event); eventStoreService.saveEvent(event);
} }
//TODO: Validate limit
public void updateUserLimit(User user, Group group, long userLimit) { public void updateUserLimit(User user, Group group, long userLimit) {
ValidationService.throwIfNoAdmin(group, user);
ValidationService.validateUserLimit(userLimit, group);
if (userLimit == group.getUserLimit()) {
return;
}
Event event = new UpdateUserLimitEvent(group, user, userLimit); Event event = new UpdateUserLimitEvent(group, user, userLimit);
event.apply(group); event.apply(group);

View File

@ -13,7 +13,7 @@ public final class IdService {
private IdService() {} private IdService() {}
public static List<UUID> stringToUUIDs(List<String> groupIds) { public static List<UUID> stringsToUUID(List<String> groupIds) {
return groupIds.stream() return groupIds.stream()
.map(IdService::stringToUUID) .map(IdService::stringToUUID)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -28,14 +28,10 @@ public final class IdService {
* @return Id als UUID * @return Id als UUID
*/ */
public static UUID stringToUUID(String groupId) { public static UUID stringToUUID(String groupId) {
if (groupId == null || groupId.isEmpty()) { return groupId.isEmpty() ? emptyUUID() : UUID.fromString(groupId);
return UUID.fromString("00000000-0000-0000-0000-000000000000");
} }
return UUID.fromString(groupId); public static List<String> uuidsToString(List<UUID> groupIds) {
}
public static List<String> uuidToString(List<UUID> groupIds) {
return groupIds.stream() return groupIds.stream()
.map(UUID::toString) .map(UUID::toString)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -45,11 +41,11 @@ public final class IdService {
return groupId.toString(); return groupId.toString();
} }
public static boolean idIsEmpty(UUID id) { public static boolean isEmpty(UUID id) {
if (id == null) { return id == null || emptyUUID().equals(id);
return true;
} }
return "00000000-0000-0000-0000-000000000000".equals(id.toString()); public static UUID emptyUUID() {
return UUID.fromString("00000000-0000-0000-0000-000000000000");
} }
} }

View File

@ -25,21 +25,20 @@ public class InviteService {
group.getId().toString(), group.getId().toString(),
UUID.randomUUID().toString())); UUID.randomUUID().toString()));
log.trace("Link wurde erzeugt! (Gruppe: {})", group.getId()); log.debug("Link wurde erzeugt! (Gruppe: {})", group.getId());
} }
void destroyLink(Group group) { void destroyLink(Group group) {
inviteRepository.deleteLinkOfGroup(group.getId().toString()); inviteRepository.deleteLinkOfGroup(group.getId().toString());
log.trace("Link wurde zerstört! (Gruppe: {})", group.getId()); log.debug("Link wurde zerstört! (Gruppe: {})", group.getId());
} }
public UUID getGroupIdFromLink(String link) { public UUID getGroupIdFromLink(String link) {
try { try {
return UUID.fromString(inviteRepository.findGroupIdByLink(link)); return UUID.fromString(inviteRepository.findGroupIdByLink(link));
} catch (Exception e) { } catch (Exception e) {
log.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link); log.error("Gruppe zu Link ({}) konnte nicht gefunden werden!", link, e);
e.printStackTrace();
throw new InvalidInviteException(link); throw new InvalidInviteException(link);
} }
} }
@ -48,8 +47,7 @@ public class InviteService {
try { try {
return inviteRepository.findLinkByGroupId(group.getId().toString()); return inviteRepository.findLinkByGroupId(group.getId().toString());
} catch (Exception e) { } catch (Exception e) {
log.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", group.getId()); log.error("Link zu Gruppe ({}) konnte nicht gefunden werden!", group.getId(), e);
e.printStackTrace();
throw new NoInviteExistException(group.getId().toString()); throw new NoInviteExistException(group.getId().toString());
} }
} }

View File

@ -3,6 +3,7 @@ package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.Event;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
@ -62,6 +63,10 @@ public class ProjectionService {
* @throws EventException Projektionsfehler, z.B. falls Events von verschiedenen Gruppen übergeben werden * @throws EventException Projektionsfehler, z.B. falls Events von verschiedenen Gruppen übergeben werden
*/ */
static Group projectSingleGroup(List<Event> events) throws EventException { static Group projectSingleGroup(List<Event> events) throws EventException {
if (events.isEmpty()) {
throw new GroupNotFoundException(ProjectionService.class.toString());
}
Group group = new Group(); Group group = new Group();
events.forEach(event -> event.apply(group)); events.forEach(event -> event.apply(group));
@ -154,18 +159,17 @@ public class ProjectionService {
* Projiziert Gruppen, in welchen der User aktuell teilnimmt. * Projiziert Gruppen, in welchen der User aktuell teilnimmt.
* Die Gruppen enthalten nur Metainformationen: Titel und Beschreibung. * Die Gruppen enthalten nur Metainformationen: Titel und Beschreibung.
* *
* @param userId Die Id * @param user Die Id
* *
* @return Liste aus Gruppen * @return Liste aus Gruppen
*/ */
@Cacheable("groups") @Cacheable("groups")
public List<Group> projectUserGroups(String userId) { public List<Group> projectUserGroups(User user) {
List<UUID> groupIds = eventStoreService.findExistingUserGroups(userId); List<UUID> groupIds = eventStoreService.findExistingUserGroups(user);
List<Event> groupEvents = eventStoreService.findEventsByGroupAndType(groupIds, List<Event> groupEvents = eventStoreService.findEventsByGroupAndType(groupIds,
"CreateGroupEvent", "CreateGroupEvent",
"UpdateGroupTitleEvent", "UpdateGroupTitleEvent",
"UpdateGroupDescriptionEvent", "UpdateGroupDescriptionEvent");
"DeleteGroupEvent");
return projectGroups(groupEvents); return projectGroups(groupEvents);
} }
@ -182,28 +186,38 @@ public class ProjectionService {
* @throws GroupNotFoundException Wenn die Gruppe nicht gefunden wird * @throws GroupNotFoundException Wenn die Gruppe nicht gefunden wird
*/ */
public Group projectSingleGroup(UUID groupId) throws GroupNotFoundException { public Group projectSingleGroup(UUID groupId) throws GroupNotFoundException {
if (IdService.idIsEmpty(groupId)) { if (IdService.isEmpty(groupId)) {
return new Group(); throw new GroupNotFoundException(groupId + ": " + ProjectionService.class);
} }
try { try {
List<Event> events = eventStoreService.findGroupEvents(groupId); List<Event> events = eventStoreService.findGroupEvents(groupId);
return projectGroups(events).get(0); return projectSingleGroup(events);
} catch (IndexOutOfBoundsException e) { } catch (Exception e) {
log.error("Gruppe {} wurde nicht gefunden!", groupId.toString()); log.error("Gruppe {} wurde nicht gefunden!", groupId.toString(), e);
e.printStackTrace(); throw new GroupNotFoundException(groupId + ": " + ProjectionService.class);
throw new GroupNotFoundException(ProjectionService.class.toString());
} }
} }
/**
* Projiziert eine einzelne Gruppe, welche leer sein darf.
*/
public Group projectParent(UUID parentId) {
if (IdService.isEmpty(parentId)) {
return new Group();
}
return projectSingleGroup(parentId);
}
/** /**
* Entfernt alle Gruppen, in welchen ein User teilnimmt, aus einer Gruppenliste. * Entfernt alle Gruppen, in welchen ein User teilnimmt, aus einer Gruppenliste.
* *
* @param groups Gruppenliste, aus der entfernt wird * @param groups Gruppenliste, aus der entfernt wird
* @param userId User, welcher teilnimmt * @param user User, welcher teilnimmt
*/ */
void removeUserGroups(List<Group> groups, String userId) { void removeUserGroups(List<Group> groups, User user) {
List<UUID> userGroups = eventStoreService.findExistingUserGroups(userId); List<UUID> userGroups = eventStoreService.findExistingUserGroups(user);
groups.removeIf(group -> userGroups.contains(group.getId())); groups.removeIf(group -> userGroups.contains(group.getId()));
} }

View File

@ -3,6 +3,7 @@ package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.GroupType; import mops.gruppen2.domain.GroupType;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.exception.EventException; import mops.gruppen2.domain.exception.EventException;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -32,16 +33,16 @@ public class SearchService {
* @throws EventException Projektionsfehler * @throws EventException Projektionsfehler
*/ */
@Cacheable("groups") @Cacheable("groups")
public List<Group> searchPublicGroups(String search, String userId) throws EventException { public List<Group> searchPublicGroups(String search, User user) throws EventException {
List<Group> groups = projectionService.projectPublicGroups(); List<Group> groups = projectionService.projectPublicGroups();
projectionService.removeUserGroups(groups, userId); projectionService.removeUserGroups(groups, user);
sortByGroupType(groups); sortByGroupType(groups);
if (search.isEmpty()) { if (search.isEmpty()) {
return groups; return groups;
} }
log.trace("Es wurde gesucht nach: {}", search); log.debug("Es wurde gesucht nach: {}", search);
return groups.stream() return groups.stream()
.filter(group -> group.toString().toLowerCase().contains(search.toLowerCase())) .filter(group -> group.toString().toLowerCase().contains(search.toLowerCase()))

View File

@ -1,172 +1,156 @@
package mops.gruppen2.service; package mops.gruppen2.service;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
import mops.gruppen2.domain.Account;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.Role; import mops.gruppen2.domain.GroupType;
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.BadParameterException; import mops.gruppen2.domain.exception.BadParameterException;
import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.GroupFullException;
import mops.gruppen2.domain.exception.GroupNotFoundException;
import mops.gruppen2.domain.exception.NoAccessException; import mops.gruppen2.domain.exception.NoAccessException;
import mops.gruppen2.domain.exception.NoAdminAfterActionException; import mops.gruppen2.domain.exception.NoAdminAfterActionException;
import mops.gruppen2.domain.exception.UserAlreadyExistsException; import mops.gruppen2.domain.exception.UserAlreadyExistsException;
import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.domain.exception.UserNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static mops.gruppen2.domain.Role.ADMIN; import static mops.gruppen2.domain.Role.ADMIN;
@Service @Service
@Log4j2 @Log4j2
public class ValidationService { public final class ValidationService {
private final SearchService searchService; private ValidationService() {}
private final ProjectionService projectionService;
public ValidationService(SearchService searchService, ProjectionService projectionService) {
this.searchService = searchService;
this.projectionService = projectionService;
}
//TODO: make static or change return + assignment // ######################################## CHECK ############################################
public List<Group> checkSearch(String search, List<Group> groups, Account account) {
if (search != null) {
groups = searchService.searchPublicGroups(search, account.getName());
}
return groups;
}
//TODO: what the fuck
public void throwIfGroupNotExisting(String title) {
if (title == null) {
throw new GroupNotFoundException("@details");
}
}
public void throwIfUserAlreadyInGroup(Group group, User user) { /**
if (checkIfUserInGroup(group, user)) { * Überprüft, ob ein User in einer Gruppe teilnimmt.
throw new UserAlreadyExistsException("@details"); */
} public static boolean checkIfMember(Group group, User user) {
}
void throwIfNotInGroup(Group group, User user) {
if (!checkIfUserInGroup(group, user)) {
throw new UserNotFoundException(getClass().toString());
}
}
public boolean checkIfUserInGroup(Group group, User user) {
return group.getMembers().contains(user); return group.getMembers().contains(user);
} }
public void throwIfGroupFull(Group group) { public static boolean checkIfLastMember(User user, Group group) {
if (group.getUserLimit() < group.getMembers().size() + 1) { return checkIfMember(group, user) && group.getMembers().size() == 1;
throw new GroupFullException("Du kannst der Gruppe daher leider nicht beitreten.");
}
} }
//TODO: necessary? /**
boolean checkIfGroupEmpty(UUID groupId) { * Überprüft, ob eine Gruppe voll ist.
return projectionService.projectSingleGroup(groupId).getMembers().isEmpty(); */
public static boolean checkIfGroupFull(Group group) {
return group.getMembers().size() >= group.getUserLimit();
} }
boolean checkIfGroupEmpty(Group group) { /**
* Überprüft, ob eine Gruppe leer ist.
*/
public static boolean checkIfGroupEmpty(Group group) {
return group.getMembers().isEmpty(); return group.getMembers().isEmpty();
} }
public void throwIfNoAdmin(Group group, User user) { /**
throwIfNoAccessToPrivate(group, user); * Überprüft, ob ein User in einer Gruppe Admin ist.
if (group.getRoles().get(user.getId()) != ADMIN) { */
throw new NoAccessException(""); public static boolean checkIfAdmin(Group group, User user) {
} if (checkIfMember(group, user)) {
}
public void throwIfNoAccessToPrivate(Group group, User user) {
if (!checkIfUserInGroup(group, user) && group.getVisibility() == Visibility.PRIVATE) {
throw new NoAccessException("");
}
}
public boolean checkIfAdmin(Group group, User user) {
if (checkIfUserInGroup(group, user)) {
return group.getRoles().get(user.getId()) == ADMIN; return group.getRoles().get(user.getId()) == ADMIN;
} }
return false; return false;
} }
public static boolean checkIfLastAdmin(User user, Group group) {
return checkIfAdmin(group, user) && group.getRoles().values().stream()
.filter(role -> role == ADMIN)
.count() == 1;
}
public static boolean checkIfGroupAccess(Group group, User user) {
return (group.getVisibility() == Visibility.PRIVATE && checkIfMember(group, user))
|| group.getVisibility() == Visibility.PUBLIC;
}
// ######################################## THROW ############################################
public static void throwIfMember(Group group, User user) {
if (checkIfMember(group, user)) {
log.error("Benutzer {} ist schon in Gruppe {}", user, group);
throw new UserAlreadyExistsException(user.toString());
}
}
public static void throwIfNoMember(Group group, User user) {
if (!checkIfMember(group, user)) {
log.error("Benutzer {} ist nicht in Gruppe {}!", user, group);
throw new UserNotFoundException(user.toString());
}
}
public static void throwIfNoAdmin(Group group, User user) {
if (!checkIfAdmin(group, user)) {
log.error("User {} ist kein Admin in Gruppe {}!", user, group);
throw new NoAccessException(group.toString());
}
}
/** /**
* Schmeißt keine Exception, wenn der User der letzte User ist. * Schmeißt keine Exception, wenn der User der letzte User ist.
*/ */
void throwIfLastAdmin(User user, Group group) { public static void throwIfLastAdmin(User user, Group group) {
if (!checkIfLastMember(user, group) && checkIfLastAdmin(user, group)) { if (!checkIfLastMember(user, group) && checkIfLastAdmin(user, group)) {
throw new NoAdminAfterActionException("Du bist letzter Admin!"); throw new NoAdminAfterActionException("Du bist letzter Admin!");
} }
} }
boolean checkIfLastAdmin(User user, Group group) { public static void throwIfGroupFull(Group group) {
for (Map.Entry<String, Role> entry : group.getRoles().entrySet()) { if (checkIfGroupFull(group)) {
if (entry.getValue() == ADMIN && !(entry.getKey().equals(user.getId()))) { log.error("Die Gruppe {} ist voll!", group);
return false; throw new GroupFullException(group.toString());
} }
} }
return true;
}
boolean checkIfLastMember(User user, Group group) { public static void throwIfNoGroupAccess(Group group, User user) {
return group.getMembers().contains(user) && group.getMembers().size() == 1; if (!checkIfGroupAccess(group, user)) {
log.error("Der User {} hat keinen Zugriff auf Gruppe {}!", user, group);
throw new NoAccessException(group.toString());
}
} }
/**
* Überprüft, ob alle Felder richtig gesetzt sind.
*
* @param description Die Beschreibung der Gruppe
* @param title Der Titel der Gruppe
* @param userLimit Das user Limit der Gruppe
*/
public void checkFields(String title, String description, Long userLimit, Boolean maxInfiniteUsers) {
if (description == null || description.trim().isEmpty()) {
throw new BadParameterException("Die Beschreibung wurde nicht korrekt angegeben");
}
// ##################################### VALIDATE FIELDS #####################################
//TODO: max title length?
public static void validateTitle(String title) {
if (title == null || title.trim().isEmpty()) { if (title == null || title.trim().isEmpty()) {
throw new BadParameterException("Der Titel wurde nicht korrekt angegeben"); log.error("Der Titel {} ist fehlerhaft!", title);
} throw new BadParameterException("Der Titel darf nicht leer sein!");
if (userLimit == null && maxInfiniteUsers == null) {
throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben");
}
if (userLimit != null && (userLimit < 1 || userLimit > 100_000L)) {
throw new BadParameterException("Teilnehmeranzahl wurde nicht korrekt angegeben");
} }
} }
public void checkFields(String title, String description) { //TODO: max description length?
public static void validateDescription(String description) {
if (description == null || description.trim().isEmpty()) { if (description == null || description.trim().isEmpty()) {
throw new BadParameterException("Die Beschreibung wurde nicht korrekt angegeben"); log.error("Die Beschreibung {} ist fehlerhaft!", description);
} throw new BadParameterException("Die Beschreibung darf nicht leer sein!");
if (title == null || title.trim().isEmpty()) {
throw new BadParameterException("Der Titel wurde nicht korrekt angegeben");
} }
} }
public void throwIfNewUserLimitIsValid(Long newUserLimit, Group group) { public static void validateFlags(Visibility visibility, GroupType groupType) {
if (newUserLimit == null) { if (visibility == Visibility.PRIVATE && groupType == GroupType.LECTURE) {
throw new BadParameterException("Es wurde keine neue maximale Teilnehmeranzahl angegeben!"); throw new BadParameterException("Eine Veranstaltung kann nicht privat sein!");
}
} }
if (newUserLimit < 1 || newUserLimit > 100_000L) { public static void validateUserLimit(long userLimit, Group group) {
throw new BadParameterException("Die neue maximale Teilnehmeranzahl wurde nicht korrekt angegeben!"); if (userLimit < 1) {
throw new BadParameterException("Das Userlimit muss größer als 1 sein!");
} }
if (group.getMembers().size() > newUserLimit) { if (userLimit < group.getMembers().size()) {
throw new BadParameterException("Die neue maximale Teilnehmeranzahl ist kleiner als die aktuelle Teilnehmeranzahl!"); throw new BadParameterException("Das Userlimit kann nicht unter der momentanen Mitgliederanzahl sein!");
} }
} }
} }

View File

@ -1,13 +1,21 @@
application.name=gruppen2 # Logging
logging.pattern.console=[${application.name}],%magenta(%-5level), %d{dd-MM-yyyy HH:mm:ss.SSS}, %highlight(%msg),%thread,%logger.%M%n logging.application.name = gruppen2
logging.pattern.console = [${logging.application.name}], %magenta(%-5level), %d{dd-MM-yyyy HH:mm:ss.SSS},\t%blue(%msg)\n\t\t\t\t\t\t\t\t\t\t\t%thread,%logger.%M%n
spring.output.ansi.enabled = always
logging.level.mops.gruppen2 = trace
logging.level.org.springframework.jdbc.core = info
# Database
spring.datasource.platform = h2 spring.datasource.platform = h2
spring.datasource.url=jdbc:h2:mem:blogdb
spring.datasource.driver-class-name = org.h2.Driver spring.datasource.driver-class-name = org.h2.Driver
spring.datasource.initialization-mode = always
spring.datasource.url = jdbc:h2:mem:blogdb
spring.datasource.username = sa spring.datasource.username = sa
spring.datasource.password = spring.datasource.password =
spring.jpa.database-platform = org.hibernate.dialect.H2Dialect spring.jpa.database-platform = org.hibernate.dialect.H2Dialect
spring.h2.console.enabled = false spring.h2.console.enabled = false
logging.level.org.springframework.jdbc.core=INFO
# Security
keycloak.principal-attribute = preferred_username keycloak.principal-attribute = preferred_username
keycloak.auth-server-url = https://keycloak.cs.hhu.de/auth keycloak.auth-server-url = https://keycloak.cs.hhu.de/auth
keycloak.realm = MOPS keycloak.realm = MOPS
@ -18,7 +26,8 @@ keycloak.verify-token-audience=true
keycloak.use-resource-role-mappings = true keycloak.use-resource-role-mappings = true
keycloak.autodetect-bearer-only = true keycloak.autodetect-bearer-only = true
keycloak.confidential-port = 443 keycloak.confidential-port = 443
# Misc
server.error.include-stacktrace = always server.error.include-stacktrace = always
management.endpoints.web.exposure.include = info,health management.endpoints.web.exposure.include = info,health
spring.cache.type=NONE spring.cache.type = none
logging.level.mops.gruppen2=trace

View File

@ -1,11 +1,19 @@
application.name=gruppen2 # Logging
logging.pattern.console=[${application.name}],%magenta(%-5level), %d{dd-MM-yyyy HH:mm:ss.SSS}, %highlight(%msg),%thread,%logger.%M%n logging.application.name = gruppen2
logging.pattern.console = [${logging.application.name}],%magenta(%-5level), %d{dd-MM-yyyy HH:mm:ss.SSS}, %highlight(%msg),%thread,%logger.%M%n
spring.output.ansi.enabled = always
logging.level.mops.gruppen2 = info
logging.level.org.springframework.jdbc.core = info
# Database
spring.datasource.platform = mysql spring.datasource.platform = mysql
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.initialization-mode=NEVER spring.datasource.initialization-mode = never
spring.datasource.url = jdbc:mysql://dbmysql:3306/gruppen2 spring.datasource.url = jdbc:mysql://dbmysql:3306/gruppen2
spring.datasource.username = root spring.datasource.username = root
spring.datasource.password = geheim spring.datasource.password = geheim
# Security
keycloak.principal-attribute = preferred_username keycloak.principal-attribute = preferred_username
keycloak.auth-server-url = https://keycloak.cs.hhu.de/auth keycloak.auth-server-url = https://keycloak.cs.hhu.de/auth
keycloak.realm = MOPS keycloak.realm = MOPS
@ -16,4 +24,7 @@ keycloak.verify-token-audience=true
keycloak.use-resource-role-mappings = true keycloak.use-resource-role-mappings = true
keycloak.autodetect-bearer-only = true keycloak.autodetect-bearer-only = true
keycloak.confidential-port = 443 keycloak.confidential-port = 443
# Misc
management.endpoints.web.exposure.include = info,health management.endpoints.web.exposure.include = info,health
server.error.include-stacktrace = always

View File

@ -30,7 +30,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li> <li>
<a href="/findGroup" th:href="@{/gruppen2/findGroup}">Suche</a> <a href="/searchPage" th:href="@{/gruppen2/searchPage}">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>

View File

@ -31,7 +31,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li> <li>
<a th:href="@{/gruppen2/findGroup}" href="/findGroup">Suche</a> <a th:href="@{/gruppen2/searchPage}" href="/searchPage">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
@ -53,31 +53,33 @@
<textarea class="form-control" id="description" required rows="3" th:name="description"></textarea> <textarea class="form-control" id="description" required rows="3" th:name="description"></textarea>
</div> </div>
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<!--DO NOT WRAP--> <!--DUMMY-->
<input type="hidden" name="maxInfiniteUsers" value="0"/><input class="custom-control-input" type="checkbox" id="maxInfiniteUsers" onclick="this.previousSibling.value=1-this.previousSibling.value"/> <input type="hidden" id="maxInfiniteUsersDummy" name="maxInfiniteUsers" value="0"/>
<input class="custom-control-input" type="checkbox" id="maxInfiniteUsers" onchange="$('#maxInfiniteUsersDummy').val(this.checked ? 1 : 0)"/>
<label class="custom-control-label" for="maxInfiniteUsers">Anzahl <label class="custom-control-label" for="maxInfiniteUsers">Anzahl
unbegrenzt</label> 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>
<input class="form-control" th:name="userMaximum" type="number" min="1" max="100000" value="1"> <input class="form-control" id="userMax" th:name="userMaximum" type="number" min="1" max="100000" value="1">
</div> </div>
<div class="custom-control custom-checkbox" id="privateCheckbox"> <div class="custom-control custom-checkbox" id="privateCheckbox">
<!--DO NOT WRAP--> <!--DUMMY-->
<input type="hidden" name="visibility" value="0"/><input class="custom-control-input" type="checkbox" id="visibility" onclick="this.previousSibling.value=1-this.previousSibling.value"/> <input type="hidden" id="visibilityDummy" name="visibility" value="0"/>
<input class="custom-control-input" type="checkbox" id="visibility" onchange="$('#visibilityDummy').val(this.checked ? 1 : 0)"/>
<label class="custom-control-label" for="visibility">Privat</label> <label class="custom-control-label" for="visibility">Privat</label>
</div> </div>
<div class="custom-control custom-checkbox" id="lectureCheckbox"> <div class="custom-control custom-checkbox" id="lectureCheckbox">
<!--DO NOT WRAP--> <!--DUMMY-->
<input type="hidden" name="lecture" value="0"/><input class="custom-control-input" type="checkbox" id="lecture" onclick="this.previousSibling.value=1-this.previousSibling.value"/> <input type="hidden" id="lectureDummy" name="lecture" value="0"/>
<input class="custom-control-input" type="checkbox" id="lecture" onchange="$('#lectureDummy').val(this.checked ? 1 : 0)"/>
<label class="custom-control-label" for="lecture">Veranstaltung</label> <label class="custom-control-label" for="lecture">Veranstaltung</label>
</div> </div>
<div class="form-group" id="lectureParent"> <div class="form-group mt-3" id="lectureParent">
<label for="parent"></label> <label for="parent">Veranstaltungszugehörigkeit</label>
<select class="form-control" id="parent" th:name="parent"> <select class="form-control" id="parent" th:name="parent">
<option disabled selected>--Bitte Veranstaltung auswählen-- <option value="" selected>--Keine--</option>
</option> <option th:each="lecture : ${lectures}" name="parent" th:value="${lecture.getId()}" th:text="${lecture.getTitle()}"></option>
<option th:each="lecture : ${lectures}" th:name="parent" th:value="${lecture.getId()}" th:text="${lecture.getTitle()}"></option>
</select> </select>
</div> </div>
<div class="form-group pt-4"> <div class="form-group pt-4">
@ -105,7 +107,6 @@
</div> </div>
<script> <script>
//TODO: Hab ich kaputt gemacht
// Add the following code if you want the name of the file appear on select // Add the following code if you want the name of the file appear on select
$(".custom-file-input").on("change", function () { $(".custom-file-input").on("change", function () {
const fileName = $(this).val().split("\\").pop(); const fileName = $(this).val().split("\\").pop();
@ -115,28 +116,28 @@
// Collapse lectureParent if lecture // Collapse lectureParent if lecture
$(document).ready(function () { $(document).ready(function () {
$('#lecture').change(function () { $('#lecture').change(function () {
$('#lectureParent').prop('disabled', function (i, v) { return !v; }); $('#parent').prop('disable', function (i, v) { return !v; });
}); });
}); });
// Collapse provateCheckbox if lecture // Collapse provateCheckbox if lecture
$(document).ready(function () { $(document).ready(function () {
$('#lecture').change(function () { $('#lecture').change(function () {
$('#privateCheckbox').prop('disabled', function (i, v) { return !v; }); $('#visibility').prop('disabled', function (i, v) { return !v; });
}); });
}); });
// Collapse lectureCheckbox if private // Collapse lectureCheckbox if private
$(document).ready(function () { $(document).ready(function () {
$('#visibility').change(function () { $('#visibility').change(function () {
$('#lectureCheckbox').prop('disabled', function (i, v) { return !v; }); $('#lecture').prop('disabled', function (i, v) { return !v; });
}); });
}); });
// Collapse userMaximum if infinite // Collapse userMaximum if infinite
$(document).ready(function () { $(document).ready(function () {
$('#maxInfiniteUsers').change(function () { $('#maxInfiniteUsers').change(function () {
$('#userMaximum').prop('disabled', function (i, v) { return !v; }); $('#userMax').prop('readonly', function (i, v) { return !v; });
}); });
}); });
</script> </script>

View File

@ -27,7 +27,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li> <li>
<a th:href="@{/gruppen2/findGroup}" href="/findGroup">Suche</a> <a th:href="@{/gruppen2/searchPage}" href="/searchPage">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
@ -50,8 +50,9 @@
<textarea class="form-control" id="description" required rows="3" th:name="description"></textarea> <textarea class="form-control" id="description" required rows="3" th:name="description"></textarea>
</div> </div>
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<!--DO NOT WRAP--> <!--DUMMY-->
<input type="hidden" name="maxInfiniteUsers" value="0"/><input class="custom-control-input" type="checkbox" id="maxInfiniteUsers" onclick="this.previousSibling.value=1-this.previousSibling.value"/> <input type="hidden" id="maxInfiniteUsersDummy" name="maxInfiniteUsers" value="0"/>
<input class="custom-control-input" type="checkbox" id="maxInfiniteUsers" onchange="$('#maxInfiniteUsersDummy').val(this.checked ? 1 : 0)"/>
<label class="custom-control-label" for="maxInfiniteUsers">Anzahl <label class="custom-control-label" for="maxInfiniteUsers">Anzahl
unbegrenzt</label> unbegrenzt</label>
</div> </div>
@ -61,15 +62,15 @@
type="number" min="1" max="10000"> type="number" min="1" max="10000">
</div> </div>
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<!--DO NOT WRAP--> <!--DUMMY-->
<input type="hidden" name="visibility" value="0"/><input class="custom-control-input" type="checkbox" id="visibility" onclick="this.previousSibling.value=1-this.previousSibling.value"/> <input type="hidden" id="visibilityDummy" name="visibility" value="0"/>
<input class="custom-control-input" type="checkbox" id="visibility" onchange="$('#visibilityDummy').val(this.checked ? 1 : 0)"/>
<label class="custom-control-label" for="visibility">Privat</label> <label class="custom-control-label" for="visibility">Privat</label>
</div> </div>
<div class="form-group" id="lectureParent"> <div class="form-group" id="lectureParent">
<label for="parent"></label> <label for="parent">Veranstaltungszugehörigkeit</label>
<select class="form-control" id="parent" name="parent"> <select class="form-control" id="parent" name="parent">
<option disabled selected>--Bitte Veranstaltung auswählen-- <option value="" selected>--Keine--</option>
</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

@ -24,7 +24,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li> <li>
<a href="/findGroup" th:href="@{/gruppen2/findGroup}">Suche</a> <a href="/searchPage" th:href="@{/gruppen2/searchPage}">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
@ -54,7 +54,7 @@
<span class="badge badge-pill badge-success" style="background: lightseagreen" <span class="badge badge-pill badge-success" style="background: lightseagreen"
th:if='${group.getType() == group.getType().LECTURE}'>Veranstaltung</span> th:if='${group.getType() == group.getType().LECTURE}'>Veranstaltung</span>
<span class="badge badge-pill badge-info" style="background: mediumorchid" <span class="badge badge-pill badge-info" style="background: mediumorchid"
th:text="${parent.getTitle()}">Parent</span> th:text="${parent?.getTitle()}">Parent</span>
<div class="input-group mb-3" style="margin-top: 10px" <div class="input-group mb-3" style="margin-top: 10px"
th:if="${roles.get(user.getId()) == admin}"> th:if="${roles.get(user.getId()) == admin}">

View File

@ -22,15 +22,13 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li class="active"> <li class="active">
<a th:href="@{/gruppen2/findGroup}" href="/findGroup">Suche</a> <a th:href="@{/gruppen2/searchPage}" href="/searchPage">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
</header> </header>
<main th:fragment="bodycontent"> <main th:fragment="bodycontent">
<div class="container-fluid"> <div class="container-fluid">
<div class="row">
<div class="col-9">
<div class="shadow-sm p-4" style="border: 1px solid aliceblue; border-radius: 5px; background: aliceblue"> <div class="shadow-sm p-4" style="border: 1px solid aliceblue; border-radius: 5px; background: aliceblue">
<h1 style="color: black; font-weight: bold; font-optical-sizing: auto; overflow-wrap: break-word" th:text="${group.getTitle()}"></h1> <h1 style="color: black; font-weight: bold; font-optical-sizing: auto; overflow-wrap: break-word" th:text="${group.getTitle()}"></h1>
<h3> <h3>
@ -40,42 +38,14 @@
th:if="${group.getVisibility() == group.getVisibility().PUBLIC}">Öffentliche Gruppe</span> th:if="${group.getVisibility() == group.getVisibility().PUBLIC}">Öffentliche Gruppe</span>
<span class="badge badge-pill badge-success" <span class="badge badge-pill badge-success"
style="background: lightseagreen" style="background: lightseagreen"
th:if='${group.getType() == group.getType().LECTURE}'> Veranstaltung</span> th:if='${group.getType() == lecture}'> Veranstaltung</span>
<span class="badge badge-pill badge-info" style="background: mediumorchid" <span class="badge badge-pill badge-info" style="background: mediumorchid"
th:text="${parent.getTitle()}">Parent</span> th:text="${parent?.getTitle()}">Parent</span>
</h3> </h3>
<div class="shadow-sm p-4" style="background: white"> <div class="shadow-sm p-4" style="background: white">
<p style="overflow-wrap: break-word; font-optical-sizing: auto" <p style="overflow-wrap: break-word; font-optical-sizing: auto"
th:text="${group.getDescription()}"></p> th:text="${group.getDescription()}"></p>
</div> </div>
<div class="form-group mt-2">
<div class="text-right">
<form method="post" th:action="@{/gruppen2/detailsBeitreten}">
<button class="btn btn-primary"
style="background: #52a1eb; border-style: none;"
th:href="@{/gruppen2/detailsBeitreten}"
th:name="id" th:value="${group.getId()}"
type="submit">Gruppe beitreten
</button>
</form>
</div>
</div>
</div>
</div>
<div class="col-3" style="white-space: nowrap">
<div style="display: inline-block; margin: 0">
<h2>Mitglieder</h2>
<div th:switch="${group.getUserLimit() != 100000}">
<h4 th:case="${true}">
<a th:text="${group.getMembers().size()}"></a>
<a>von maximal</a>
<a th:text="${group.getUserLimit()}"></a>
<a>Benutzern.</a>
</h4>
<h4 th:case="false">unbegrenzte Teilnehmeranzahl</h4>
</div>
</div>
</div>
</div> </div>
</div> </div>
</main> </main>

View File

@ -27,7 +27,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li> <li>
<a th:href="@{/gruppen2/findGroup}" href="/findGroup">Suche</a> <a th:href="@{/gruppen2/searchPage}" href="/searchPage">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
@ -37,6 +37,7 @@
<div class="row"> <div class="row">
<div class="col-10"> <div class="col-10">
<h1>Mitglieder bearbeiten</h1> <h1>Mitglieder bearbeiten</h1>
<!--TODO: Anzeige bei unbegrenzt-->
<div th:switch="${group.getUserLimit() != 100000}"> <div th:switch="${group.getUserLimit() != 100000}">
<h5 th:case="${true}"> <h5 th:case="${true}">
<a th:text="${group.getMembers().size()}"></a> <a th:text="${group.getMembers().size()}"></a>

View File

@ -23,7 +23,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li> <li>
<a href="/findGroup" th:href="@{/gruppen2/findGroup}">Suche</a> <a href="/searchPage" th:href="@{/gruppen2/searchPage}">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
@ -50,7 +50,7 @@
<h3 style="color: dodgerblue; font-weight: bold; font-optical-sizing: auto; overflow-wrap: break-word"> <h3 style="color: dodgerblue; font-weight: bold; font-optical-sizing: auto; overflow-wrap: break-word">
<span class="badge badge-pill badge-success" <span class="badge badge-pill badge-success"
style="background: lightseagreen; margin-right: 25px; float: right" style="background: lightseagreen; margin-right: 25px; float: right"
th:if='${gruppe.getType() == gruppe.getType().LECTURE}'>Veranstaltung</span> th:if='${gruppe.getType() == lecture}'>Veranstaltung</span>
<a th:href="@{/gruppen2/details/{id}(id=${gruppe.getId()})}" <a th:href="@{/gruppen2/details/{id}(id=${gruppe.getId()})}"
th:text="${gruppe.getTitle()}"></a> th:text="${gruppe.getTitle()}"></a>
</h3> </h3>

View File

@ -10,6 +10,7 @@
</th:block> </th:block>
</head> </head>
<body> <body>
<header> <header>
<nav class="navigation navigation-secondary" is="mops-navigation" th:fragment="navigation" <nav class="navigation navigation-secondary" is="mops-navigation" th:fragment="navigation"
th:switch="${account.getRoles().contains('orga')}"> th:switch="${account.getRoles().contains('orga')}">
@ -24,25 +25,24 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li class="active"> <li class="active">
<a href="/findGroup" th:href="@{/gruppen2/findGroup}">Suche</a> <a href="/searchPage" th:href="@{/gruppen2/searchPage}">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
</header> </header>
<main th:fragment="bodycontent"> <main th:fragment="bodycontent">
<div class="container-fluid"> <div class="container-fluid">
<div class="row">
<div class="col-9">
<div class="shadow-sm p-4" <div class="shadow-sm p-4"
style="border: 1px solid aliceblue; border-radius: 5px; background: aliceblue"> style="border: 1px solid aliceblue; border-radius: 5px; background: aliceblue">
<h1 style="color: black; font-weight: bold; font-optical-sizing: auto; overflow-wrap: break-word" <h1 style="color: black; font-weight: bold; font-optical-sizing: auto; overflow-wrap: break-word"
th:text="${group.getTitle()}"></h1> th:text="${group.getTitle()}"></h1>
<h3>Möchtest du dieser privaten Gruppe beitreten?</h3>
<div class="shadow-sm p-4" style="background: white"> <div class="shadow-sm p-4" style="background: white">
<p style="overflow-wrap: break-word; font-optical-sizing: auto" <p style="overflow-wrap: break-word; font-optical-sizing: auto"
th:text="${group.getDescription()}"></p> th:text="${group.getDescription()}"></p>
</div> </div>
<div class="form-group mt-2"> <div class="form-group mt-2" th:if="${group.getMembers().size() < group.getUserLimit()}">
<h3>Möchtest du dieser privaten Gruppe beitreten?</h3>
<div class="text-right"> <div class="text-right">
<form method="post" th:action="@{/gruppen2/acceptinvite}"> <form method="post" th:action="@{/gruppen2/acceptinvite}">
<input name="id" th:value="${group.getId()}" type="hidden"/> <input name="id" th:value="${group.getId()}" type="hidden"/>
@ -58,22 +58,11 @@
</form> </form>
</div> </div>
</div> </div>
</div> <h3 class="mt-2" th:if="${group.getMembers().size() >= group.getUserLimit()}">Gruppe ist
</div> voll und
<div class="col-3" style="white-space: nowrap"> kann nicht
<div style="display: inline-block; margin: 0"> beigetreten
<h2>Mitglieder</h2> werden.</h3>
<div th:switch="${group.getUserLimit() != 100000}">
<h4 th:case="${true}">
<a th:text="${group.getMembers().size()}"></a>
<a>von maximal</a>
<a th:text="${group.getUserLimit()}"></a>
<a>Benutzern.</a>
</h4>
<h4 th:case="false">unbegrenzte Teilnehmeranzahl</h4>
</div>
</div>
</div>
</div> </div>
</div> </div>
</main> </main>

View File

@ -23,7 +23,7 @@
<a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a> <a href="/createStudent" th:href="@{/gruppen2/createStudent}">Erstellen</a>
</li> </li>
<li class="active"> <li class="active">
<a th:href="@{/gruppen2/findGroup}" href="/findGroup">Suche</a> <a th:href="@{/gruppen2/searchPage}" href="/searchPage">Suche</a>
</li> </li>
</ul> </ul>
</nav> </nav>
@ -35,7 +35,7 @@
<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/search}">
<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"
@ -46,10 +46,8 @@
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" type="submit">
style="background: deepskyblue; border-style: none" <a href="/gruppen2/search?suchbegriff=" style="color: white">Alle
type="submit">
<a href="/gruppen2/findGroup?suchbegriff=" style="color: white">Alle
anzeigen</a> anzeigen</a>
</button> </button>
</form> </form>

View File

@ -14,6 +14,7 @@ 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.domain.event.UpdateUserLimitEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -93,6 +94,7 @@ public class TestBuilder {
eventList.add(createPublicGroupEvent(groupId)); eventList.add(createPublicGroupEvent(groupId));
eventList.add(updateGroupTitleEvent(groupId)); eventList.add(updateGroupTitleEvent(groupId));
eventList.add(updateGroupDescriptionEvent(groupId)); eventList.add(updateGroupDescriptionEvent(groupId));
eventList.add(new UpdateUserLimitEvent(groupId, "fgsadggas", Long.MAX_VALUE));
eventList.addAll(addUserEvents(membercount, groupId)); eventList.addAll(addUserEvents(membercount, groupId));
return eventList; return eventList;
@ -105,6 +107,7 @@ public class TestBuilder {
eventList.add(createPrivateGroupEvent(groupId)); eventList.add(createPrivateGroupEvent(groupId));
eventList.add(updateGroupTitleEvent(groupId)); eventList.add(updateGroupTitleEvent(groupId));
eventList.add(updateGroupDescriptionEvent(groupId)); eventList.add(updateGroupDescriptionEvent(groupId));
eventList.add(new UpdateUserLimitEvent(groupId, "fgsadggas", Long.MAX_VALUE));
eventList.addAll(addUserEvents(membercount, groupId)); eventList.addAll(addUserEvents(membercount, groupId));
return eventList; return eventList;
@ -170,8 +173,7 @@ public class TestBuilder {
faker.random().hex(), faker.random().hex(),
null, null,
GroupType.SIMPLE, GroupType.SIMPLE,
visibility, visibility
10000000L
); );
} }
@ -185,8 +187,7 @@ public class TestBuilder {
faker.random().hex(), faker.random().hex(),
null, null,
GroupType.LECTURE, GroupType.LECTURE,
Visibility.PUBLIC, Visibility.PUBLIC
10000000L
); );
} }
@ -286,6 +287,10 @@ public class TestBuilder {
); );
} }
public static Event updateUserLimitMaxEvent(UUID groupId) {
return new UpdateUserLimitEvent(groupId, firstname(), Long.MAX_VALUE);
}
public static Event updateRoleEvent(UUID groupId, String userId, Role role) { public static Event updateRoleEvent(UUID groupId, String userId, Role role) {
return new UpdateRoleEvent( return new UpdateRoleEvent(
groupId, groupId,

View File

@ -22,6 +22,7 @@ import static mops.gruppen2.TestBuilder.createPublicGroupEvent;
import static mops.gruppen2.TestBuilder.deleteGroupEvent; import static mops.gruppen2.TestBuilder.deleteGroupEvent;
import static mops.gruppen2.TestBuilder.deleteUserEvent; import static mops.gruppen2.TestBuilder.deleteUserEvent;
import static mops.gruppen2.TestBuilder.updateGroupTitleEvent; import static mops.gruppen2.TestBuilder.updateGroupTitleEvent;
import static mops.gruppen2.TestBuilder.updateUserLimitMaxEvent;
import static mops.gruppen2.TestBuilder.uuidMock; 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;
@ -36,13 +37,13 @@ class APIControllerTest {
private EventRepository eventRepository; private EventRepository eventRepository;
@Autowired @Autowired
private APIController apiController; private APIController apiController;
@Autowired
private EventStoreService eventStoreService; private EventStoreService eventStoreService;
@Autowired @Autowired
private JdbcTemplate template; private JdbcTemplate template;
@BeforeEach @BeforeEach
void setUp() { void setUp() {
eventStoreService = new EventStoreService(eventRepository);
eventRepository.deleteAll(); eventRepository.deleteAll();
//noinspection SqlResolve //noinspection SqlResolve
template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1"); template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1");
@ -61,6 +62,7 @@ class APIControllerTest {
@WithMockUser(username = "api_user", roles = "api_user") @WithMockUser(username = "api_user", roles = "api_user")
void updateGroup_singleGroup() { void updateGroup_singleGroup() {
eventStoreService.saveAll(createPublicGroupEvent(uuidMock(0)), eventStoreService.saveAll(createPublicGroupEvent(uuidMock(0)),
updateUserLimitMaxEvent(uuidMock(0)),
addUserEvent(uuidMock(0)), addUserEvent(uuidMock(0)),
addUserEvent(uuidMock(0)), addUserEvent(uuidMock(0)),
addUserEvent(uuidMock(0)), addUserEvent(uuidMock(0)),
@ -69,7 +71,7 @@ class APIControllerTest {
assertThat(apiController.updateGroups(0L).getGroupList()).hasSize(1); assertThat(apiController.updateGroups(0L).getGroupList()).hasSize(1);
assertThat(apiController.updateGroups(4L).getGroupList()).hasSize(1); assertThat(apiController.updateGroups(4L).getGroupList()).hasSize(1);
assertThat(apiController.updateGroups(10L).getGroupList()).hasSize(0); assertThat(apiController.updateGroups(10L).getGroupList()).hasSize(0);
assertThat(apiController.updateGroups(0L).getStatus()).isEqualTo(5); assertThat(apiController.updateGroups(0L).getStatus()).isEqualTo(6);
} }
@ -77,9 +79,11 @@ class APIControllerTest {
@WithMockUser(username = "api_user", roles = "api_user") @WithMockUser(username = "api_user", roles = "api_user")
void updateGroup_multipleGroups() { void updateGroup_multipleGroups() {
eventStoreService.saveAll(createPublicGroupEvent(uuidMock(0)), eventStoreService.saveAll(createPublicGroupEvent(uuidMock(0)),
updateUserLimitMaxEvent(uuidMock(0)),
addUserEvent(uuidMock(0)), addUserEvent(uuidMock(0)),
addUserEvent(uuidMock(0)), addUserEvent(uuidMock(0)),
createPrivateGroupEvent(uuidMock(1)), createPrivateGroupEvent(uuidMock(1)),
updateUserLimitMaxEvent(uuidMock(1)),
addUserEvent(uuidMock(1)), addUserEvent(uuidMock(1)),
addUserEvent(uuidMock(1)), addUserEvent(uuidMock(1)),
addUserEvent(uuidMock(1))); addUserEvent(uuidMock(1)));

View File

@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test;
import static mops.gruppen2.TestBuilder.addUserEvent; import static mops.gruppen2.TestBuilder.addUserEvent;
import static mops.gruppen2.TestBuilder.apply; import static mops.gruppen2.TestBuilder.apply;
import static mops.gruppen2.TestBuilder.createPublicGroupEvent; import static mops.gruppen2.TestBuilder.createPublicGroupEvent;
import static mops.gruppen2.TestBuilder.updateUserLimitMaxEvent;
import static mops.gruppen2.TestBuilder.uuidMock; 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;
@ -17,9 +18,10 @@ class AddUserEventTest {
@Test @Test
void applyEvent() { void applyEvent() {
Event createEvent = createPublicGroupEvent(uuidMock(0)); Event createEvent = createPublicGroupEvent(uuidMock(0));
Event updateLimitEvent = updateUserLimitMaxEvent(uuidMock(0));
Event addEvent = new AddUserEvent(uuidMock(0), "A", "Thomas", "Tom", "tho@mail.de"); Event addEvent = new AddUserEvent(uuidMock(0), "A", "Thomas", "Tom", "tho@mail.de");
Group group = apply(createEvent, addEvent); Group group = apply(createEvent, updateLimitEvent, addEvent);
assertThat(group.getMembers()).hasSize(1); assertThat(group.getMembers()).hasSize(1);
assertThat(group.getMembers().get(0).getGivenname()).isEqualTo("Thomas"); assertThat(group.getMembers().get(0).getGivenname()).isEqualTo("Thomas");
@ -30,11 +32,12 @@ class AddUserEventTest {
@Test @Test
void applyEvent_userAlreadyExists() { void applyEvent_userAlreadyExists() {
Event createEvent = createPublicGroupEvent(uuidMock(0)); Event createEvent = createPublicGroupEvent(uuidMock(0));
Event updateLimitEvent = updateUserLimitMaxEvent(uuidMock(0));
Event addEventA = addUserEvent(uuidMock(0), "A"); Event addEventA = addUserEvent(uuidMock(0), "A");
Event addEventB = addUserEvent(uuidMock(0), "B"); Event addEventB = addUserEvent(uuidMock(0), "B");
Event addEventC = addUserEvent(uuidMock(0), "A"); Event addEventC = addUserEvent(uuidMock(0), "A");
Group group = apply(createEvent, addEventA, addEventB); Group group = apply(createEvent, updateLimitEvent, addEventA, addEventB);
assertThrows(UserAlreadyExistsException.class, () -> addEventA.apply(group)); assertThrows(UserAlreadyExistsException.class, () -> addEventA.apply(group));
assertThrows(UserAlreadyExistsException.class, () -> addEventC.apply(group)); assertThrows(UserAlreadyExistsException.class, () -> addEventC.apply(group));

View File

@ -17,15 +17,13 @@ class CreateGroupEventTest {
"A", "A",
uuidMock(1), uuidMock(1),
GroupType.SIMPLE, GroupType.SIMPLE,
Visibility.PUBLIC, Visibility.PUBLIC);
100L);
Group group = TestBuilder.apply(createEvent); Group group = TestBuilder.apply(createEvent);
assertThat(group.getMembers()).hasSize(0); assertThat(group.getMembers()).hasSize(0);
assertThat(group.getType()).isEqualTo(GroupType.SIMPLE); assertThat(group.getType()).isEqualTo(GroupType.SIMPLE);
assertThat(group.getVisibility()).isEqualTo(Visibility.PUBLIC); assertThat(group.getVisibility()).isEqualTo(Visibility.PUBLIC);
assertThat(group.getUserLimit()).isEqualTo(100);
assertThat(group.getId()).isEqualTo(uuidMock(0)); assertThat(group.getId()).isEqualTo(uuidMock(0));
assertThat(group.getParent()).isEqualTo(uuidMock(1)); assertThat(group.getParent()).isEqualTo(uuidMock(1));
} }

View File

@ -17,8 +17,7 @@ class DeleteGroupEventTest {
"A", "A",
uuidMock(1), uuidMock(1),
GroupType.SIMPLE, GroupType.SIMPLE,
Visibility.PUBLIC, Visibility.PUBLIC);
100L);
Event deleteEvent = new DeleteGroupEvent(uuidMock(0), "A"); Event deleteEvent = new DeleteGroupEvent(uuidMock(0), "A");
Group group = TestBuilder.apply(createEvent, deleteEvent); Group group = TestBuilder.apply(createEvent, deleteEvent);

View File

@ -7,6 +7,7 @@ import org.junit.jupiter.api.Test;
import static mops.gruppen2.TestBuilder.addUserEvent; import static mops.gruppen2.TestBuilder.addUserEvent;
import static mops.gruppen2.TestBuilder.createPublicGroupEvent; import static mops.gruppen2.TestBuilder.createPublicGroupEvent;
import static mops.gruppen2.TestBuilder.updateUserLimitMaxEvent;
import static mops.gruppen2.TestBuilder.uuidMock; 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;
@ -16,10 +17,11 @@ class DeleteUserEventTest {
@Test @Test
void applyEvent() { void applyEvent() {
Event createEvent = createPublicGroupEvent(uuidMock(0)); Event createEvent = createPublicGroupEvent(uuidMock(0));
Event updateLimitEvent = updateUserLimitMaxEvent(uuidMock(0));
Event addEvent = addUserEvent(uuidMock(0), "A"); Event addEvent = addUserEvent(uuidMock(0), "A");
Event deleteEvent = new DeleteUserEvent(uuidMock(0), "A"); Event deleteEvent = new DeleteUserEvent(uuidMock(0), "A");
Group group = TestBuilder.apply(createEvent, addEvent, deleteEvent); Group group = TestBuilder.apply(createEvent, updateLimitEvent, addEvent, deleteEvent);
assertThat(group.getMembers()).hasSize(0); assertThat(group.getMembers()).hasSize(0);
} }
@ -27,10 +29,11 @@ class DeleteUserEventTest {
@Test @Test
void applyEvent_userNotFound() { void applyEvent_userNotFound() {
Event createEvent = createPublicGroupEvent(uuidMock(0)); Event createEvent = createPublicGroupEvent(uuidMock(0));
Event updateLimitEvent = updateUserLimitMaxEvent(uuidMock(0));
Event addEvent = addUserEvent(uuidMock(0), "A"); Event addEvent = addUserEvent(uuidMock(0), "A");
Event deleteEvent = new DeleteUserEvent(uuidMock(0), "B"); Event deleteEvent = new DeleteUserEvent(uuidMock(0), "B");
Group group = TestBuilder.apply(createEvent, addEvent); Group group = TestBuilder.apply(createEvent, updateLimitEvent, addEvent);
assertThrows(UserNotFoundException.class, () -> deleteEvent.apply(group)); assertThrows(UserNotFoundException.class, () -> deleteEvent.apply(group));
assertThat(group.getMembers()).hasSize(1); assertThat(group.getMembers()).hasSize(1);

View File

@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test;
import static mops.gruppen2.TestBuilder.addUserEvent; import static mops.gruppen2.TestBuilder.addUserEvent;
import static mops.gruppen2.TestBuilder.apply; import static mops.gruppen2.TestBuilder.apply;
import static mops.gruppen2.TestBuilder.createPublicGroupEvent; import static mops.gruppen2.TestBuilder.createPublicGroupEvent;
import static mops.gruppen2.TestBuilder.updateUserLimitMaxEvent;
import static mops.gruppen2.TestBuilder.uuidMock; 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;
@ -17,10 +18,11 @@ class UpdateRoleEventTest {
@Test @Test
void applyEvent() { void applyEvent() {
Event createEvent = createPublicGroupEvent(uuidMock(0)); Event createEvent = createPublicGroupEvent(uuidMock(0));
Event updateLimitEvent = updateUserLimitMaxEvent(uuidMock(0));
Event addEvent = addUserEvent(uuidMock(0), "A"); Event addEvent = addUserEvent(uuidMock(0), "A");
Event updateEvent = new UpdateRoleEvent(uuidMock(0), "A", Role.ADMIN); Event updateEvent = new UpdateRoleEvent(uuidMock(0), "A", Role.ADMIN);
Group group = apply(createEvent, addEvent, updateEvent); Group group = apply(createEvent, updateLimitEvent, addEvent, updateEvent);
assertThat(group.getRoles().get("A")).isEqualTo(Role.ADMIN); assertThat(group.getRoles().get("A")).isEqualTo(Role.ADMIN);
} }
@ -28,10 +30,11 @@ class UpdateRoleEventTest {
@Test @Test
void applyEvent_userNotFound() { void applyEvent_userNotFound() {
Event createEvent = createPublicGroupEvent(uuidMock(0)); Event createEvent = createPublicGroupEvent(uuidMock(0));
Event updateLimitEvent = updateUserLimitMaxEvent(uuidMock(0));
Event addEvent = addUserEvent(uuidMock(0), "A"); Event addEvent = addUserEvent(uuidMock(0), "A");
Event updateEvent = new UpdateRoleEvent(uuidMock(0), "B", Role.ADMIN); Event updateEvent = new UpdateRoleEvent(uuidMock(0), "B", Role.ADMIN);
Group group = apply(createEvent, addEvent); Group group = apply(createEvent, updateLimitEvent, addEvent);
assertThrows(UserNotFoundException.class, () -> updateEvent.apply(group)); assertThrows(UserNotFoundException.class, () -> updateEvent.apply(group));
assertThat(group.getRoles().get("A")).isEqualTo(Role.MEMBER); assertThat(group.getRoles().get("A")).isEqualTo(Role.MEMBER);

View File

@ -1,6 +1,7 @@
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.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;
@ -93,7 +94,7 @@ class EventStoreServiceTest {
addUserEvent(uuidMock(3), "A"), addUserEvent(uuidMock(3), "A"),
addUserEvent(uuidMock(3), "B")); addUserEvent(uuidMock(3), "B"));
assertThat(eventStoreService.findExistingUserGroups("A")).hasSize(4); assertThat(eventStoreService.findExistingUserGroups(new User("A"))).hasSize(4);
assertThat(eventStoreService.findExistingUserGroups("B")).hasSize(1); assertThat(eventStoreService.findExistingUserGroups(new User("B"))).hasSize(1);
} }
} }

View File

@ -3,6 +3,7 @@ package mops.gruppen2.service;
import mops.gruppen2.Gruppen2Application; import mops.gruppen2.Gruppen2Application;
import mops.gruppen2.TestBuilder; import mops.gruppen2.TestBuilder;
import mops.gruppen2.domain.Group; import mops.gruppen2.domain.Group;
import mops.gruppen2.domain.User;
import mops.gruppen2.domain.Visibility; import mops.gruppen2.domain.Visibility;
import mops.gruppen2.domain.event.Event; import mops.gruppen2.domain.event.Event;
import mops.gruppen2.repository.EventRepository; import mops.gruppen2.repository.EventRepository;
@ -58,7 +59,7 @@ class GroupServiceTest {
@BeforeEach @BeforeEach
void setUp() { void setUp() {
groupService = new GroupService(eventStoreService, validationService, inviteService); groupService = new GroupService(eventStoreService, inviteService);
eventRepository.deleteAll(); eventRepository.deleteAll();
//noinspection SqlResolve //noinspection SqlResolve
template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1"); template.execute("ALTER TABLE event ALTER COLUMN event_id RESTART WITH 1");
@ -184,7 +185,7 @@ class GroupServiceTest {
updateGroupTitleEvent(uuidMock(0)), updateGroupTitleEvent(uuidMock(0)),
updateGroupDescriptionEvent(uuidMock(0))); updateGroupDescriptionEvent(uuidMock(0)));
assertThat(searchService.searchPublicGroups("", "jens")).isEmpty(); assertThat(searchService.searchPublicGroups("", new User("jens"))).isEmpty();
} }
//TODO: SearchServiceTest //TODO: SearchServiceTest
@ -193,7 +194,7 @@ class GroupServiceTest {
eventStoreService.saveAll(completePublicGroups(10, 0), eventStoreService.saveAll(completePublicGroups(10, 0),
completePrivateGroups(10, 0)); completePrivateGroups(10, 0));
assertThat(searchService.searchPublicGroups("", "jens")).hasSize(10); assertThat(searchService.searchPublicGroups("", new User("jens"))).hasSize(10);
} }
//TODO: SearchServiceTest //TODO: SearchServiceTest
@ -207,9 +208,9 @@ class GroupServiceTest {
updateGroupDescriptionEvent(uuidMock(1), "KK"), updateGroupDescriptionEvent(uuidMock(1), "KK"),
createPrivateGroupEvent()); createPrivateGroupEvent());
assertThat(searchService.searchPublicGroups("A", "jesus")).hasSize(2); assertThat(searchService.searchPublicGroups("A", new User("jesus"))).hasSize(2);
assertThat(searchService.searchPublicGroups("F", "jesus")).hasSize(1); assertThat(searchService.searchPublicGroups("F", new User("jesus"))).hasSize(1);
assertThat(searchService.searchPublicGroups("Z", "jesus")).hasSize(0); assertThat(searchService.searchPublicGroups("Z", new User("jesus"))).hasSize(0);
} }
} }