Skip to content

Commit bce4a56

Browse files
authored
Merge branch 'develop' into #2078-Read-Only-Schutz-für-Vereinsstammdate-backend
2 parents 95e882e + f2ba5ec commit bce4a56

10 files changed

Lines changed: 369 additions & 49 deletions

File tree

bogenliga/bogenliga-application/src/main/java/de/bogenliga/application/services/v1/dsbmannschaft/service/DsbMannschaftService.java

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package de.bogenliga.application.services.v1.dsbmannschaft.service;
22

33
import java.security.Principal;
4+
import java.time.LocalDate;
45
import java.time.Year;
6+
import java.time.ZoneId;
7+
import java.util.Date;
58
import java.util.List;
69

710
import javax.naming.NoPermissionException;
@@ -47,7 +50,7 @@ public class DsbMannschaftService implements ServiceFacade {
4750
private static final String PRECONDITION_MSG_DSBMANNSCHAFT_VEREIN_ID_NEGATIVE = "DsbMannschaft Vereins Id must not be negative";
4851
private static final String PRECONDITION_MSG_DSBMANNSCHAFT_NUMMER_NEGATIVE = "DsbMannschaft Nummer must not be negative";
4952
private static final String PRECONDITION_MSG_DSBMANNSCHAFT_BENUTZER_ID_NEGATIVE = "DsbMannschaft Benutzer Id must not be negative";
50-
private static final String PRECONDITION_MSG_DSBMANNSCHAFT_VERANSTALTUNG_FULL = "DsbMannschaft Veranstaltung has already reached its maximum capacity";
53+
private static final String ERROR_MSG_VERANSTALTUNG_FULL = "Die Veranstaltung hat ihre maximale Kapazität erreicht. Es kann keine weitere Mannschaft hinzugefügt werden.";
5154
private static final String PRECONDITION_MSG_ID_NEGATIVE = "ID must not be negative.";
5255
private static final String PRECONDITION_MSG_WRONG_YEAR = "Year has to be a valid year.";
5356
private static final String PRECONDITION_MSG_VERANSTALTUNG_SIZE_NEGATIV = "DsbMannschaft Veranstaltung size can not be negativ";
@@ -361,9 +364,9 @@ public DsbMannschaftDTO create(@RequestBody final DsbMannschaftDTO dsbMannschaft
361364
}
362365

363366

364-
Preconditions.checkArgument(actualMannschaftInVeranstaltungCount.size() < veranstaltungsgroesse
365-
366-
, PRECONDITION_MSG_DSBMANNSCHAFT_VERANSTALTUNG_FULL);
367+
if (actualMannschaftInVeranstaltungCount.size() >= veranstaltungsgroesse) {
368+
throw new BusinessException(ErrorCode.VERANSTALTUNG_MAX_CAPACITY_ERROR, ERROR_MSG_VERANSTALTUNG_FULL);
369+
}
367370
}
368371
LOG.debug("Receive 'create' request with verein id '{}', nummer '{}', benutzer id '{}', veranstaltung id '{}',",
369372

@@ -642,8 +645,9 @@ public DsbMannschaftDTO update(@RequestBody final DsbMannschaftDTO dsbMannschaft
642645
if(veranstaltungDO != null) {
643646
veranstaltungsgroesse = veranstaltungDO.getVeranstaltungGroesse();
644647
}
645-
Preconditions.checkArgument(mannschaftenInZielveranstaltung.size() < veranstaltungsgroesse
646-
, PRECONDITION_MSG_DSBMANNSCHAFT_VERANSTALTUNG_FULL);
648+
if (mannschaftenInZielveranstaltung.size() >= veranstaltungsgroesse) {
649+
throw new BusinessException(ErrorCode.VERANSTALTUNG_MAX_CAPACITY_ERROR, ERROR_MSG_VERANSTALTUNG_FULL);
650+
}
647651
}
648652

649653

@@ -670,7 +674,7 @@ public DsbMannschaftDTO update(@RequestBody final DsbMannschaftDTO dsbMannschaft
670674
* <pre>{@code Request: DELETE /v1/dsbmitglied/app.bogenliga.frontend.autorefresh.active}</pre>
671675
*/
672676
@DeleteMapping(value = "{id}")
673-
@RequiresOnePermissions(perm = {UserPermission.CAN_DELETE_STAMMDATEN, UserPermission.CAN_MODIFY_MY_VERANSTALTUNG})
677+
@RequiresOnePermissions(perm = {UserPermission.CAN_DELETE_STAMMDATEN, UserPermission.CAN_MODIFY_MY_VERANSTALTUNG, UserPermission.CAN_MODIFY_MY_VEREIN})
674678
public void delete(@PathVariable("id") final long id, final Principal principal) {
675679
Preconditions.checkArgument(id >= 0, PRECONDITION_MSG_ID_NEGATIVE);
676680
// allow value == null, the value will be ignored
@@ -679,17 +683,47 @@ public void delete(@PathVariable("id") final long id, final Principal principal)
679683

680684
LOG.debug("Receive 'delete' request with id '{}'", id);
681685

682-
if(!this.requiresOnePermissionAspect.hasPermission(UserPermission.CAN_DELETE_STAMMDATEN)
683-
&& !this.requiresOnePermissionAspect.hasSpecificPermissionLigaLeiterID(UserPermission.CAN_MODIFY_MY_VERANSTALTUNG, dsbMannschaftComponent.findById(id).getVeranstaltungId())){
686+
if (!this.requiresOnePermissionAspect.hasPermission(UserPermission.CAN_DELETE_STAMMDATEN)
687+
&& !this.requiresOnePermissionAspect.hasSpecificPermissionLigaLeiterID(
688+
UserPermission.CAN_MODIFY_MY_VERANSTALTUNG,
689+
dsbMannschaftDO.getVeranstaltungId())
690+
&& !this.requiresOnePermissionAspect.hasSpecificPermissionSportleiter(
691+
UserPermission.CAN_MODIFY_MY_VEREIN,
692+
dsbMannschaftDO.getVereinId())) {
684693
throw new BusinessException(
685694
ErrorCode.NO_PERMISSION_ERROR,
686695
ERROR_MSG_DELETE_MANNSCHAFT_NO_PERMISSION
687696
);
688697
}
689698

690699
// Wenn eine Veranstaltung zugeordnet ist (id!=null) und die Phase ist nicht "Geplant", dann nicht löschen
691-
if (dsbMannschaftDO.getVeranstaltungId() != null && !veranstaltungComponent.findById(dsbMannschaftDO.getVeranstaltungId()).getVeranstaltungPhase().equals("Geplant"))
692-
throw new BusinessException(ErrorCode.ENTITY_CONFLICT_ERROR, "Mannschaft kann nicht gelöscht werden - es liegen weitere abhängige Daten vor.");
700+
if (dsbMannschaftDO.getVeranstaltungId() != null) {
701+
final VeranstaltungDO veranstaltungDO =
702+
veranstaltungComponent.findById(dsbMannschaftDO.getVeranstaltungId());
703+
704+
if (veranstaltungDO != null) {
705+
706+
if (!veranstaltungDO.getVeranstaltungPhase().equals("Geplant")) {
707+
throw new BusinessException(
708+
ErrorCode.ENTITY_CONFLICT_ERROR,
709+
"Mannschaft kann nicht gelöscht werden - es liegen weitere abhängige Daten vor."
710+
);
711+
}
712+
713+
// Neue Prüfung: nur vor Meldedeadline löschen
714+
if (veranstaltungDO.getVeranstaltungMeldeDeadline() != null) {
715+
final Date today = new Date();
716+
final Date meldeDeadline = veranstaltungDO.getVeranstaltungMeldeDeadline();
717+
718+
if (!today.before(meldeDeadline)) {
719+
throw new BusinessException(
720+
ErrorCode.MANNSCHAFT_DELETE_AFTER_MELDEDEADLINE,
721+
"Mannschaft kann nach Erreichen der Meldedeadline nicht mehr gelöscht werden."
722+
);
723+
}
724+
}
725+
}
726+
}
693727

694728
dsbMannschaftComponent.delete(dsbMannschaftDO, userId);
695729
}

bogenliga/bogenliga-application/src/main/java/de/bogenliga/application/services/v1/dsbmitglied/service/DsbMitgliedService.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,22 @@ public List<DsbMitgliedDTO> findBySearch(@PathVariable("searchstring") final Str
176176
* @return list of {@link DsbMitgliedDTO} as JSON
177177
*/
178178
@GetMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
179-
@RequiresPermission(UserPermission.CAN_READ_DSBMITGLIEDER)
180-
public DsbMitgliedDTO findById(@PathVariable("id") final long id) {
179+
@RequiresOnePermissions(perm = {UserPermission.CAN_READ_DSBMITGLIEDER, UserPermission.CAN_READ_MY_VEREIN})
180+
public DsbMitgliedDTO findById(@PathVariable("id") final long id) throws NoPermissionException {
181181
Preconditions.checkArgument(id >= 0, PRECONDITION_MSG_ID_NEGATIVE);
182+
final DsbMitgliedDO dsbMitgliedDO = dsbMitgliedComponent.findById(id);
182183

183-
LOG.debug("Receive 'findByDsbMitgliedId' request with ID '{}'", id);
184+
if (this.requiresOnePermissionAspect.hasPermission(UserPermission.CAN_READ_DSBMITGLIEDER)
185+
|| this.requiresOnePermissionAspect.hasSpecificPermissionSportleiter(UserPermission.CAN_READ_MY_VEREIN, dsbMitgliedDO.getVereinsId()))
186+
{
187+
LOG.debug("Receive 'findByDsbMitgliedId' request with ID '{}'", id);
184188

185-
final DsbMitgliedDO dsbMitgliedDO = dsbMitgliedComponent.findById(id);
186-
return DsbMitgliedDTOMapper.toDTO.apply(dsbMitgliedDO);
189+
return DsbMitgliedDTOMapper.toDTO.apply(dsbMitgliedDO);
190+
}
191+
else
192+
{
193+
throw new NoPermissionException();
194+
}
187195
}
188196

189197

bogenliga/bogenliga-application/src/main/java/de/bogenliga/application/services/v1/wettkampf/service/AnzeigenService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public void delete(@PathVariable final Long id, final Principal principal) {
177177
*
178178
* @return list of {@link AnzeigenDTO} as JSON
179179
*/
180-
@GetMapping(value = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
180+
@GetMapping(value = "AnzeigenMatch{id}", produces = MediaType.APPLICATION_JSON_VALUE)
181181
public AnzeigenMatchDTO findAnzeigenMatchByPhysischeBildschirmId(@PathVariable("id") final String id) {
182182
Preconditions.checkArgument(id.length() == 4, "ID must be four characters long.");
183183

bogenliga/bogenliga-application/src/test/java/de/bogenliga/application/services/v1/dsbmannschaft/service/DsbMannschaftServiceTest.java

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.util.Collections;
88
import java.util.List;
99
import javax.naming.NoPermissionException;
10+
11+
import de.bogenliga.application.springconfiguration.security.types.UserPermission;
1012
import org.assertj.core.api.Java6Assertions;
1113
import org.junit.Before;
1214
import org.junit.Rule;
@@ -760,6 +762,60 @@ public void delete() {
760762
}catch (BusinessException e) { }
761763
}
762764

765+
@Test
766+
public void delete_meldedeadline_ueberschritten_exception() {
767+
// prepare test data
768+
final DsbMannschaftDO expected = getDsbMannschaftDO();
769+
770+
final VeranstaltungDO veranstaltungDO = getVeranstaltungDO();
771+
veranstaltungDO.setVeranstaltungPhase("Geplant");
772+
veranstaltungDO.setVeranstaltungMeldeDeadline(
773+
new Date(System.currentTimeMillis() - 24L * 60L * 60L * 1000L)
774+
); // gestern
775+
776+
// configure mocks
777+
when(requiresOnePermissionAspect.hasPermission(any())).thenReturn(true);
778+
when(dsbMannschaftComponent.findById(anyLong())).thenReturn(expected);
779+
when(veranstaltungComponent.findById(anyLong())).thenReturn(veranstaltungDO);
780+
781+
// assert
782+
assertThatExceptionOfType(BusinessException.class)
783+
.isThrownBy(() -> underTest.delete(ID, principal))
784+
.withMessageContaining("Meldedeadline");
785+
786+
// verify
787+
verify(dsbMannschaftComponent).findById(ID);
788+
verify(veranstaltungComponent).findById(VERANSTALTUNG_ID);
789+
verify(dsbMannschaftComponent, never()).delete(any(), anyLong());
790+
}
791+
792+
@Test
793+
public void delete_vor_meldedeadline_erlaubt() {
794+
// prepare test data
795+
final DsbMannschaftDO expected = getDsbMannschaftDO();
796+
797+
final VeranstaltungDO veranstaltungDO = getVeranstaltungDO();
798+
veranstaltungDO.setVeranstaltungPhase("Geplant");
799+
veranstaltungDO.setVeranstaltungMeldeDeadline(
800+
new Date(System.currentTimeMillis() + 24L * 60L * 60L * 1000L)
801+
); // morgen
802+
803+
// configure mocks
804+
when(requiresOnePermissionAspect.hasPermission(any())).thenReturn(true);
805+
when(dsbMannschaftComponent.findById(anyLong())).thenReturn(expected);
806+
when(veranstaltungComponent.findById(anyLong())).thenReturn(veranstaltungDO);
807+
808+
// act
809+
underTest.delete(ID, principal);
810+
811+
// verify
812+
verify(dsbMannschaftComponent).delete(dsbMannschaftVOArgumentCaptor.capture(), anyLong());
813+
814+
final DsbMannschaftDO deletedDsbMannschaft = dsbMannschaftVOArgumentCaptor.getValue();
815+
assertThat(deletedDsbMannschaft).isNotNull();
816+
assertThat(deletedDsbMannschaft.getId()).isEqualTo(expected.getId());
817+
}
818+
763819
@Test
764820
public void delete_nicht_geplant_exception() {
765821
// prepare test data
@@ -778,6 +834,89 @@ public void delete_nicht_geplant_exception() {
778834
.isThrownBy(()-> underTest.delete(ID, principal));
779835
}
780836

837+
@Test
838+
public void delete_no_permission_exception() {
839+
// prepare test data
840+
final DsbMannschaftDO expected = getDsbMannschaftDO();
841+
842+
// configure mocks
843+
when(dsbMannschaftComponent.findById(anyLong())).thenReturn(expected);
844+
when(requiresOnePermissionAspect.hasPermission(UserPermission.CAN_DELETE_STAMMDATEN)).thenReturn(false);
845+
when(requiresOnePermissionAspect.hasSpecificPermissionLigaLeiterID(
846+
UserPermission.CAN_MODIFY_MY_VERANSTALTUNG, VERANSTALTUNG_ID)).thenReturn(false);
847+
when(requiresOnePermissionAspect.hasSpecificPermissionSportleiter(
848+
UserPermission.CAN_MODIFY_MY_VEREIN, VEREIN_ID)).thenReturn(false);
849+
850+
// assert
851+
assertThatExceptionOfType(BusinessException.class)
852+
.isThrownBy(() -> underTest.delete(ID, principal));
853+
854+
// verify
855+
verify(dsbMannschaftComponent, never()).delete(any(), anyLong());
856+
}
857+
858+
@Test
859+
public void delete_erlaubt_fuer_sportleiter_des_eigenen_vereins() {
860+
// prepare test data
861+
final DsbMannschaftDO expected = getDsbMannschaftDO();
862+
final VeranstaltungDO veranstaltungDO = getVeranstaltungDO();
863+
veranstaltungDO.setVeranstaltungPhase("Geplant");
864+
veranstaltungDO.setVeranstaltungMeldeDeadline(
865+
new Date(System.currentTimeMillis() + 24L * 60L * 60L * 1000L)
866+
); // morgen
867+
868+
// configure mocks
869+
when(requiresOnePermissionAspect.hasPermission(UserPermission.CAN_DELETE_STAMMDATEN)).thenReturn(false);
870+
when(requiresOnePermissionAspect.hasSpecificPermissionLigaLeiterID(
871+
UserPermission.CAN_MODIFY_MY_VERANSTALTUNG, VERANSTALTUNG_ID)).thenReturn(false);
872+
when(requiresOnePermissionAspect.hasSpecificPermissionSportleiter(
873+
UserPermission.CAN_MODIFY_MY_VEREIN, VEREIN_ID)).thenReturn(true);
874+
875+
when(dsbMannschaftComponent.findById(anyLong())).thenReturn(expected);
876+
when(veranstaltungComponent.findById(anyLong())).thenReturn(veranstaltungDO);
877+
878+
// act
879+
underTest.delete(ID, principal);
880+
881+
// verify
882+
verify(dsbMannschaftComponent).delete(dsbMannschaftVOArgumentCaptor.capture(), anyLong());
883+
884+
final DsbMannschaftDO deletedDsbMannschaft = dsbMannschaftVOArgumentCaptor.getValue();
885+
assertThat(deletedDsbMannschaft).isNotNull();
886+
assertThat(deletedDsbMannschaft.getId()).isEqualTo(expected.getId());
887+
}
888+
889+
@Test
890+
public void delete_erlaubt_fuer_ligaleiter() {
891+
// prepare test data
892+
final DsbMannschaftDO expected = getDsbMannschaftDO();
893+
final VeranstaltungDO veranstaltungDO = getVeranstaltungDO();
894+
veranstaltungDO.setVeranstaltungPhase("Geplant");
895+
veranstaltungDO.setVeranstaltungMeldeDeadline(
896+
new Date(System.currentTimeMillis() + 24L * 60L * 60L * 1000L)
897+
); // morgen
898+
899+
// configure mocks
900+
when(requiresOnePermissionAspect.hasPermission(UserPermission.CAN_DELETE_STAMMDATEN)).thenReturn(false);
901+
when(requiresOnePermissionAspect.hasSpecificPermissionLigaLeiterID(
902+
UserPermission.CAN_MODIFY_MY_VERANSTALTUNG, VERANSTALTUNG_ID)).thenReturn(true);
903+
when(requiresOnePermissionAspect.hasSpecificPermissionSportleiter(
904+
UserPermission.CAN_MODIFY_MY_VEREIN, VEREIN_ID)).thenReturn(false);
905+
906+
when(dsbMannschaftComponent.findById(anyLong())).thenReturn(expected);
907+
when(veranstaltungComponent.findById(anyLong())).thenReturn(veranstaltungDO);
908+
909+
// act
910+
underTest.delete(ID, principal);
911+
912+
// verify
913+
verify(dsbMannschaftComponent).delete(dsbMannschaftVOArgumentCaptor.capture(), anyLong());
914+
915+
final DsbMannschaftDO deletedDsbMannschaft = dsbMannschaftVOArgumentCaptor.getValue();
916+
assertThat(deletedDsbMannschaft).isNotNull();
917+
assertThat(deletedDsbMannschaft.getId()).isEqualTo(expected.getId());
918+
}
919+
781920
@Test
782921
public void assignMannschaftToVeranstaltung() {
783922

0 commit comments

Comments
 (0)