Skip to content

Commit f2ba5ec

Browse files
authored
Merge pull request #638 from bettercodepaul/#2087-löschung-nach-deadline-backend
feat(backend): verhindere Löschen von Mannschaften nach Meldedeadline…
2 parents 0b60402 + 7300ea1 commit f2ba5ec

3 files changed

Lines changed: 178 additions & 6 deletions

File tree

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

Lines changed: 38 additions & 5 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;
@@ -671,7 +674,7 @@ public DsbMannschaftDTO update(@RequestBody final DsbMannschaftDTO dsbMannschaft
671674
* <pre>{@code Request: DELETE /v1/dsbmitglied/app.bogenliga.frontend.autorefresh.active}</pre>
672675
*/
673676
@DeleteMapping(value = "{id}")
674-
@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})
675678
public void delete(@PathVariable("id") final long id, final Principal principal) {
676679
Preconditions.checkArgument(id >= 0, PRECONDITION_MSG_ID_NEGATIVE);
677680
// allow value == null, the value will be ignored
@@ -680,17 +683,47 @@ public void delete(@PathVariable("id") final long id, final Principal principal)
680683

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

683-
if(!this.requiresOnePermissionAspect.hasPermission(UserPermission.CAN_DELETE_STAMMDATEN)
684-
&& !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())) {
685693
throw new BusinessException(
686694
ErrorCode.NO_PERMISSION_ERROR,
687695
ERROR_MSG_DELETE_MANNSCHAFT_NO_PERMISSION
688696
);
689697
}
690698

691699
// Wenn eine Veranstaltung zugeordnet ist (id!=null) und die Phase ist nicht "Geplant", dann nicht löschen
692-
if (dsbMannschaftDO.getVeranstaltungId() != null && !veranstaltungComponent.findById(dsbMannschaftDO.getVeranstaltungId()).getVeranstaltungPhase().equals("Geplant"))
693-
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+
}
694727

695728
dsbMannschaftComponent.delete(dsbMannschaftDO, userId);
696729
}

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

bogenliga/bogenliga-common/src/main/java/de/bogenliga/application/common/errorhandling/ErrorCode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public enum ErrorCode {
4444
INSUFFICIENT_CREDENTIALS(ErrorCategory.BUSINESS, "INSUFFICIENT_CREDENTIALS"),
4545
DUBLICATE_USERNAME(ErrorCategory.BUSINESS, "DUBLICATE_USERNAME"),
4646
INCORRECT_AMOUNT_OF_TEAMS(ErrorCategory.BUSINESS, "INCORRECT_AMOUNT_OF_TEAMS"),
47-
47+
MANNSCHAFT_DELETE_AFTER_MELDEDEADLINE(ErrorCategory.BUSINESS, "MANNSCHAFT_DELETE_AFTER_MELDEDEADLINE"),
4848
UNDEFINED(ErrorCategory.UNDEFINED, "UNDEFINED");
4949

5050
private final ErrorCategory errorCategory;

0 commit comments

Comments
 (0)