Skip to content

Commit

Permalink
Merge pull request #250 from it-at-m/159-implementierung-urnenwahlvor…
Browse files Browse the repository at this point in the history
…bereitung-service-post-impl

159 implementierung urnenwahlvorbereitung service post impl
  • Loading branch information
MrSebastian committed May 28, 2024
2 parents 699d120 + 546ac5b commit 94fdc38
Show file tree
Hide file tree
Showing 22 changed files with 545 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ public class ExceptionConstants {
private static final String CODE_SUCHKRITERIEN_UNVOLLSTAENDIG = "901";
private static final String MSG_SUCHKRITERIEN_UNVOLLSTAENDIG = "Fehler beim Laden: Suchkriterien unvollständig.";

private static final String CODE_PARAMS_UNVOLLSTAENDIG = "902";
private static final String MSG_PARAMS_UNVOLLSTAENDIG = "Fehler beim Speichern: Parameter unvollständig.";

private static final String CODE_UNSAVEABLE = "903";
private static final String MSG_UNSAVEABLE = "Fehler beim speichern: Daten konnten nicht gespeichert werden.";

public static ExceptionDataWrapper SUCHKRITERIEN_UNVOLLSTAENDIG = new ExceptionDataWrapper(CODE_SUCHKRITERIEN_UNVOLLSTAENDIG,
MSG_SUCHKRITERIEN_UNVOLLSTAENDIG);

public static ExceptionDataWrapper PARAMS_UNVOLLSTAENDIG = new ExceptionDataWrapper(CODE_PARAMS_UNVOLLSTAENDIG, MSG_PARAMS_UNVOLLSTAENDIG);

public static ExceptionDataWrapper UNSAVEABLE = new ExceptionDataWrapper(CODE_UNSAVEABLE, MSG_UNSAVEABLE);

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.exception;

import de.muenchen.oss.wahllokalsystem.wls.common.exception.FachlicheWlsException;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.TechnischeWlsException;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.WlsException;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.builder.states.CodeIsSet;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
Expand All @@ -12,7 +15,16 @@ public class ExceptionFactory {
private final ServiceIDFormatter serviceIDFormatter;

public FachlicheWlsException createFachlicheWlsException(final ExceptionDataWrapper exceptionDataWrapper) {
return FachlicheWlsException.withCode(exceptionDataWrapper.code()).inService(serviceIDFormatter.getId())
.buildWithMessage(exceptionDataWrapper.message());
return finalizeWlsException(FachlicheWlsException.withCode(exceptionDataWrapper.code()), exceptionDataWrapper.message());
}

public TechnischeWlsException createTechnischeWlsException(final ExceptionDataWrapper exceptionDataWrapper) {
return finalizeWlsException(TechnischeWlsException.withCode(exceptionDataWrapper.code()), exceptionDataWrapper.message());
}

private <T extends WlsException> T finalizeWlsException(final CodeIsSet<T> initializedExceptionBuilder, final String message) {
return initializedExceptionBuilder
.inService(serviceIDFormatter.getId())
.buildWithMessage(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.exception;

import de.muenchen.oss.wahllokalsystem.wls.common.exception.errorhandler.AbstractExceptionHandler;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.rest.model.DTOMapper;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.rest.model.WlsExceptionDTO;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.util.ServiceIDFormatter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends AbstractExceptionHandler {

private final ServiceIDFormatter serviceIDFormatter;

public GlobalExceptionHandler(final ServiceIDFormatter serviceIDFormatter, final DTOMapper dtoMapper) {
super(dtoMapper);
this.serviceIDFormatter = serviceIDFormatter;
}

@ExceptionHandler
public ResponseEntity<WlsExceptionDTO> handleThrowables(final Throwable throwable) {
log.info("handling throwable", throwable);
return createResponse(getWahlExceptionDTO(throwable));
}

@Override
protected String getService() {
return serviceIDFormatter.getId();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand All @@ -19,6 +23,7 @@ public class UrnenwahlvorbereitungController {
private final UrnenwahlvorbereitungService service;

private final UrnenwahlvorbereitungDTOMapper urnenwahlvorbereitungDTOMapper;
private final UrnenwahlvorbereitungService urnenwahlvorbereitungService;

@Operation(description = "Laden der Wahlvorbereitungsdaten des Urnenwahllokals {wahlbezirkID}")
@GetMapping("{wahlbezirkID}")
Expand All @@ -28,6 +33,15 @@ public ResponseEntity<UrnenwahlvorbereitungDTO> getUrnenwahlVorbereitung(@PathVa
return withBodyOrNoContent(urnenwahlvorbereitungModel.map(urnenwahlvorbereitungDTOMapper::toDTO));
}

@Operation(description = "Aktualisiert die Wahlvorbereitungsdaten des Urnenwahllokals {wahlbezirkID}")
@PostMapping("{wahlbezirkID}")
@ResponseStatus(HttpStatus.CREATED)
public void postUrnenwahlvorbereitung(@PathVariable("wahlbezirkID") final String wahlbezirkID,
@RequestBody final UrnenwahlvorbereitungWriteDTO urnenwahlvorbereitungDTO) {
val vorbereitungToSet = urnenwahlvorbereitungDTOMapper.toModel(wahlbezirkID, urnenwahlvorbereitungDTO);
urnenwahlvorbereitungService.setUrnenwahlvorbereitung(vorbereitungToSet);
}

private <T> ResponseEntity<T> withBodyOrNoContent(final Optional<T> body) {
return body.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.noContent().build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
public interface UrnenwahlvorbereitungDTOMapper {

UrnenwahlvorbereitungDTO toDTO(UrnenwahlvorbereitungModel model);

UrnenwahlvorbereitungModel toModel(String wahlbezirkID, UrnenwahlvorbereitungWriteDTO dto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.rest.urnenwahlvorbereitung;

import de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.rest.common.WahlurneDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import lombok.Builder;

@Builder
public record UrnenwahlvorbereitungWriteDTO(@Schema(requiredMode = Schema.RequiredMode.REQUIRED) long anzahlWahlkabinen,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) long anzahlWahltische,
@Schema(requiredMode = Schema.RequiredMode.REQUIRED) long anzahlNebenraeume,
@NotNull @Size(min = 1) List<WahlurneDTO> urnenAnzahl) {

public UrnenwahlvorbereitungWriteDTO(final long anzahlWahlkabinen, final long anzahlWahltische, final long anzahlNebenraeume,
final List<WahlurneDTO> urnenAnzahl) {
this.anzahlWahlkabinen = anzahlWahlkabinen;
this.anzahlWahltische = anzahlWahltische;
this.anzahlNebenraeume = anzahlNebenraeume;
this.urnenAnzahl = Objects.requireNonNullElseGet(urnenAnzahl, ArrayList::new);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
public interface UrnenwahlvorbereitungModelMapper {

UrnenwahlvorbereitungModel toModel(UrnenwahlVorbereitung entity);

UrnenwahlVorbereitung toEntity(UrnenwahlvorbereitungModel model);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.service.urnenwahlvorbereitung;

import de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.domain.UrnenwahlVorbereitungRepository;
import de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.exception.ExceptionConstants;
import de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.exception.ExceptionFactory;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -19,6 +21,7 @@ public class UrnenwahlvorbereitungService {
private final UrnenwahlvorbereitungModelMapper urnenwahlvorbereitungModelMapper;

private final UrnenwahlvorbereitungValidator urnenwahlvorbereitungValidator;
private final ExceptionFactory exceptionFactory;

@PreAuthorize(
"hasAuthority('Wahlvorbereitung_BUSINESSACTION_GetUrnenwahlVorbereitung')"
Expand All @@ -35,4 +38,22 @@ public Optional<UrnenwahlvorbereitungModel> getUrnenwahlvorbereitung(@P("wahlbez

return dataFromRepo.map(urnenwahlvorbereitungModelMapper::toModel);
}

@PreAuthorize(
"hasAuthority('Wahlvorbereitung_BUSINESSACTION_PostUrnenwahlVorbereitung')"
+ "and @bezirkIdPermisionEvaluator.tokenUserBezirkIdMatches(#vorbereitungToSet.wahlbezirkID, authentication)"
)
public void setUrnenwahlvorbereitung(@P("vorbereitungToSet") final UrnenwahlvorbereitungModel vorbereitungToSet) {
log.debug("#postUrnenwahlVorbereitung");
log.debug("in: urnenwahlVorbereitung > {}", vorbereitungToSet);

urnenwahlvorbereitungValidator.validModelToSetOrThrow(vorbereitungToSet);

try {
urnenwahlVorbereitungRepository.save(urnenwahlvorbereitungModelMapper.toEntity(vorbereitungToSet));
} catch (final Exception onSaveException) {
log.error("Fehler beim speichern: ", onSaveException);
throw exceptionFactory.createTechnischeWlsException(ExceptionConstants.UNSAVEABLE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.exception.ExceptionConstants;
import de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.exception.ExceptionFactory;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

@Component
Expand All @@ -16,4 +17,11 @@ public void validWahlbezirkIDOrThrow(final String wahlbezirkID) {
throw exceptionFactory.createFachlicheWlsException(ExceptionConstants.SUCHKRITERIEN_UNVOLLSTAENDIG);
}
}

public void validModelToSetOrThrow(final UrnenwahlvorbereitungModel modelToValidate) {
if (modelToValidate == null || StringUtils.isEmpty(modelToValidate.wahlbezirkID()) || modelToValidate.urnenAnzahl()
.isEmpty()) { //urnenanzahl cannot be null because of the records constructor
throw exceptionFactory.createFachlicheWlsException(ExceptionConstants.PARAMS_UNVOLLSTAENDIG);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.muenchen.oss.wahllokalsystem.wahlvorbereitungservice.configuration;

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

Expand All @@ -14,6 +15,7 @@
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithAnonymousUser;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ActiveProfiles;
Expand Down Expand Up @@ -62,5 +64,23 @@ void accessGetUrnenwahlvorbereitungAuthorizedThenNoContent() throws Exception {

mockMvc.perform(request).andExpect(status().isNoContent());
}

@Test
@WithAnonymousUser
void accessPostUrnenwahlvorbereitungUnauthorizedThenUnauthorized() throws Exception {
val request = MockMvcRequestBuilders.post("/businessActions/urnenwahlVorbereitung/wahlbezirkID").with(csrf())
.contentType(MediaType.APPLICATION_JSON).content("{}");

mockMvc.perform(request).andExpect(status().isUnauthorized());
}

@Test
@WithMockUser
void accessPostUrnenwahlvorbereitungAuthorizedThenIsCreated() throws Exception {
val request = MockMvcRequestBuilders.post("/businessActions/urnenwahlVorbereitung/wahlbezirkID").with(csrf())
.contentType(MediaType.APPLICATION_JSON).content("{}");

mockMvc.perform(request).andExpect(status().isCreated());
}
}
}
Loading

0 comments on commit 94fdc38

Please sign in to comment.