Skip to content

Commit

Permalink
Merge pull request #663 from it-at-m/191-lesen-und-schreiben-der-stim…
Browse files Browse the repository at this point in the history
…mzettelumschläge

191 lesen und schreiben der stimmzettelumschläge
  • Loading branch information
dragonfly28 authored Jan 8, 2025
2 parents dd08243 + a933f73 commit ec4fd68
Show file tree
Hide file tree
Showing 30 changed files with 1,498 additions and 5 deletions.
7 changes: 6 additions & 1 deletion docs/src/services/ergebnismeldung-service/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ Welche Aktionen für die jeweiligen Dokumente bereits in einem Wahllokal vollzog

#### Erfassung der Stimmabgaben mit Wahlschein
Im Wählerverzeichnis wird bei einer Wahl durch den Schriftführer über den sogenannten "Stimmabgabevermerk" vermerkt,
wenn ein Wahlberechtigter mit Wahlschein seinen Stimmzettel in die Urne gelegt hat.
wenn ein Wahlberechtigter mit Wahlschein seinen Stimmzettel in die Urne im Wahllokal gelegt hat.
Über das Schreiben und Lesen der Wahlscheine kann die aktuelle Anzahl an Stimmabgabevermerken an WLS übermittelt
bzw. ausgelesen werden.

### Erfassung der Anzahl an Stimmzettelumschlaegen
Bei der Briefwahl zählt der Wahlvorstand die Stimmzettelumschlaege.
Über das Schreiben und Lesen der Stimmzettelumschlaege kann die aktuelle Anzahl eines Wahlbezirkes für eine Wahl an WLS
übermittelt bzw. ausgelesen werden.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
id: add authorities ergebnismeldung stimmzettelumschlaege
author: dragonfly28
realm: ${SSO_REALM}
changes:
- addRole:
name: Ergebnismeldung_BUSINESSACTION_GetStimmzettelumschlaege
clientRole: true
clientId: ${SSO_CLIENT_ID}
- assignRoleToGroup:
group: allErgebnismeldungAuthorities
role: Ergebnismeldung_BUSINESSACTION_GetStimmzettelumschlaege
clientId: ${SSO_CLIENT_ID}

- addRole:
name: Ergebnismeldung_BUSINESSACTION_PostStimmzettelumschlaege
clientRole: true
clientId: ${SSO_CLIENT_ID}
- assignRoleToGroup:
group: allErgebnismeldungAuthorities
role: Ergebnismeldung_BUSINESSACTION_PostStimmzettelumschlaege
clientId: ${SSO_CLIENT_ID}

- addRole:
name: Ergebnismeldung_READ_Stimmzettelumschlaege
clientRole: true
clientId: ${SSO_CLIENT_ID}
- assignRoleToGroup:
group: allErgebnismeldungAuthorities
role: Ergebnismeldung_READ_Stimmzettelumschlaege
clientId: ${SSO_CLIENT_ID}
- addRole:
name: Ergebnismeldung_WRITE_Stimmzettelumschlaege
clientRole: true
clientId: ${SSO_CLIENT_ID}
- assignRoleToGroup:
group: allErgebnismeldungAuthorities
role: Ergebnismeldung_WRITE_Stimmzettelumschlaege
clientId: ${SSO_CLIENT_ID}
- addRole:
name: Ergebnismeldung_DELETE_Stimmzettelumschlaege
clientRole: true
clientId: ${SSO_CLIENT_ID}
- assignRoleToGroup:
group: allErgebnismeldungAuthorities
role: Ergebnismeldung_DELETE_Stimmzettelumschlaege
clientId: ${SSO_CLIENT_ID}
1 change: 1 addition & 0 deletions stack/keycloak/migration/keycloak-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ includes:
- path: add-authorities-ergebnismeldung-status.yml
- path: add-authorities-ergebnismeldung-wahlscheine.yml
- path: add-authorities-ergebnismeldung-begruendung.yml
- path: add-authorities-ergebnismeldung-stimmzettelumschlaege.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.common.security;

import java.util.Optional;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

@Component
@Profile("no-security")
public class AnonymousHandler implements AuthenticationHandler {
@Override
public boolean canHandle(Authentication authentication) {
return authentication instanceof AnonymousAuthenticationToken;
}

@Override
public Optional<String> getDetail(String detailKey, Authentication authentication) {
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.common.security;

import java.util.Optional;
import org.springframework.security.core.Authentication;

public interface AuthenticationHandler {

boolean canHandle(Authentication authentication);

Optional<String> getDetail(String detailKey, Authentication authentication);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.common.security;

import java.util.Optional;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Component;

@Component
public class JWTHandler implements AuthenticationHandler {

@Override
public boolean canHandle(final Authentication authentication) {
return authentication instanceof JwtAuthenticationToken;
}

public Optional<String> getDetail(final String detailKey, final Authentication authentication) {
if (authentication instanceof JwtAuthenticationToken jwtToken) {
return Optional.ofNullable(jwtToken.getToken().getClaimAsString(detailKey));
} else {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.domain.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Stimmzettelumschlaege {

@EmbeddedId
private BezirkUndWahlID bezirkUndWahlID;

private LocalDateTime urneneroeffnungsUhrzeit;

@NotNull
private long anzahlWaehler;

private Long anzahlWaehler2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.domain.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
import java.util.Optional;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.security.access.prepost.PreAuthorize;

@PreAuthorize("hasAuthority('Ergebnismeldung_READ_Stimmzettelumschlaege')")
public interface StimmzettelumschlaegeRepository extends CrudRepository<Stimmzettelumschlaege, BezirkUndWahlID> {

String CACHE = "STIMMZETTELUMSCHLAEGE_CACHE";

@Override
Iterable<Stimmzettelumschlaege> findAll();

@Override
@Cacheable(value = CACHE, key = "#p0")
Optional<Stimmzettelumschlaege> findById(BezirkUndWahlID bezirkUndWahlID);

@Override
@CachePut(value = CACHE, key = "#p0.bezirkUndWahlID")
@PreAuthorize("hasAuthority('Ergebnismeldung_WRITE_Stimmzettelumschlaege')")
<S extends Stimmzettelumschlaege> S save(S stimmzettelumschlaege);

@Override
@CacheEvict(value = CACHE, key = "#p0")
@PreAuthorize("hasAuthority('Ergebnismeldung_DELETE_Stimmzettelumschlaege')")
void deleteById(BezirkUndWahlID bezirkUndWahlID);

@Override
@CacheEvict(value = CACHE, key = "#p0.bezirkUndWahlID")
@PreAuthorize("hasAuthority('Ergebnismeldung_DELETE_Stimmzettelumschlaege')")
void delete(Stimmzettelumschlaege entity);

@Override
@CacheEvict(value = CACHE, allEntries = true)
@PreAuthorize("hasAuthority('Ergebnismeldung_DELETE_Stimmzettelumschlaege')")
void deleteAll(Iterable<? extends Stimmzettelumschlaege> entities);

@Override
@CacheEvict(value = CACHE, allEntries = true)
@PreAuthorize("hasAuthority('Ergebnismeldung_DELETE_Stimmzettelumschlaege')")
void deleteAll();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ public class ExceptionConstants {

public static ExceptionDataWrapper GETAWERTE_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("600",
"getAWerte: Parameter unvollstaendig");

public static ExceptionDataWrapper GETAWERTE_UNSAVEABLE = new ExceptionDataWrapper("601",
"getAWerte: Die AWerte vom Client konnten nicht gespeichert werden.");

public static final ExceptionDataWrapper GET_STATUS_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("606", "getStatus: Parameter unvollstaendig");
public static final ExceptionDataWrapper POST_STATUS_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("607", "postStatus: Parameter unvollstaendig");
public static final ExceptionDataWrapper STATUS_UNSAVEABLE = new ExceptionDataWrapper("622", "postStatus: Der Status konnte nicht gespeichert werden.");
public static final ExceptionDataWrapper GET_STATUS_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("606",
"getStatus: Parameter unvollstaendig");
public static final ExceptionDataWrapper POST_STATUS_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("607",
"postStatus: Parameter unvollstaendig");
public static final ExceptionDataWrapper STATUS_UNSAVEABLE = new ExceptionDataWrapper("622",
"postStatus: Der Status konnte nicht gespeichert werden.");

public static final ExceptionDataWrapper GET_WAHLSCHEINE_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("612",
"getWahlscheine: Parameter unvollstaendig");
Expand All @@ -24,6 +26,15 @@ public class ExceptionConstants {
public static final ExceptionDataWrapper WAHLSCHEINE_UNSAVEABLE = new ExceptionDataWrapper("618",
"postWahlscheine: Die Wahlscheine konnten nicht gespeichert werden.");

public static final ExceptionDataWrapper GET_STIMMZETTELUMSCHLAEGE_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("610",
"getStimmzettelumschlaege: Parameter unvollstaendig");
public static final ExceptionDataWrapper POST_STIMMZETTELUMSCHLAEGE_PARAMETER_UNVOLLSTAENDIG = new ExceptionDataWrapper("611",
"postStimmzettelumschlaege: Parameter unvollstaendig");
public static final ExceptionDataWrapper STIMMZETTELUMSCHLAEGE_UNSAVEABLE = new ExceptionDataWrapper("619",
"postStimmzettelumschlaege: Die Stimmzettelumschlaege konnten nicht gespeichert werden.");
public static final ExceptionDataWrapper WAHLBEZIRKART_NOT_LOADABLE = new ExceptionDataWrapper("800",
"Die Wahlbezirkart des Principals konnte nicht geladen werden.");

public static final ExceptionDataWrapper KOMMUNIKATIONSFEHLER_MIT_MONITORING = new ExceptionDataWrapper("100",
"Bei der Kommunikation mit dem MonitoringService kam es zu einem Fehler.");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.rest.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.rest.AbstractController;
import de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.service.stimmzettelumschlaege.StimmzettelumschlaegeService;
import de.muenchen.oss.wahllokalsystem.wls.common.exception.rest.model.WlsExceptionDTO;
import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.val;
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.RestController;

@RestController
@RequestMapping("/businessActions/stimmzettelumschlaege")
@RequiredArgsConstructor
public class StimmzettelumschlaegeController extends AbstractController {

private final StimmzettelumschlaegeService stimmzettelumschlaegeService;
private final StimmzettelumschlaegeDTOMapper stimmzettelumschlaegeDTOMapper;

@Operation(description = "Lesen der Anzahl an Stimmzettelumschlaegen eines Wahlbezirkes für eine Wahl")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200", description = "Es existiert eine Anzahl an Stimmzettelumschlaegen",
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = StimmzettelumschlaegeDTO.class)) }
),
@ApiResponse(
responseCode = "204", description = "Es existiert keine Anzahl an Stimmzettelumschlaegen zu den entsprechenden Kriterien",
content = { @Content() }
),
@ApiResponse(
responseCode = "400", description = "Validierung der Anfrage war nicht erfolgreich",
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = WlsExceptionDTO.class)) }
),
@ApiResponse(
responseCode = "500", description = "Probleme bei der Verarbeitung der Anfrage",
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = WlsExceptionDTO.class)) }
)
}
)
@GetMapping("{wahlID}/{wahlbezirkID}")
public ResponseEntity<StimmzettelumschlaegeDTO> getStimmzettelumschlaege(@PathVariable("wahlID") final String wahlID,
@PathVariable("wahlbezirkID") final String wahlbezirkID) {
val stimmzettelumschlaege = stimmzettelumschlaegeService.getStimmzettelumschlaege(new BezirkUndWahlID(wahlID, wahlbezirkID));
return okWithBodyOrNoContent(stimmzettelumschlaege.map(stimmzettelumschlaegeDTOMapper::toDTO));
}

@Operation(description = "Setzen der Anzahl an Stimmzettelumschlaegen eines Wahlbezirkes für eine Wahl")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200", description = "Anzahl an Stimmzettelumschlaegen erfolgreich gespeichert"
),
@ApiResponse(
responseCode = "400", description = "Validierung der Anfrage war nicht erfolgreich",
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = WlsExceptionDTO.class)) }
),
@ApiResponse(
responseCode = "500", description = "Probleme bei der Verarbeitung der Anfrage",
content = { @Content(mediaType = "application/json", schema = @Schema(implementation = WlsExceptionDTO.class)) }
)
}
)
@PostMapping("{wahlID}/{wahlbezirkID}")
public void postStimmzettelumschlaege(@PathVariable("wahlID") final String wahlID, @PathVariable("wahlbezirkID") final String wahlbezirkID,
@RequestBody final StimmzettelumschlaegeDTO stimmzettelumschlaegeDTO) {
stimmzettelumschlaegeService.setStimmzettelumschlaege(new BezirkUndWahlID(wahlID, wahlbezirkID),
stimmzettelumschlaegeDTOMapper.toModel(stimmzettelumschlaegeDTO));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.rest.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;

public record StimmzettelumschlaegeDTO(@NotNull BezirkUndWahlID bezirkUndWahlID,
LocalDateTime urneneroeffnungsUhrzeit,
@NotNull long anzahlWaehler,
Long anzahlWaehler2) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.rest.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.service.stimmzettelumschlaege.StimmzettelumschlaegeModel;
import org.mapstruct.Mapper;

@Mapper
public interface StimmzettelumschlaegeDTOMapper {

StimmzettelumschlaegeDTO toDTO(StimmzettelumschlaegeModel stimmzettelumschlaegeModel);

StimmzettelumschlaegeModel toModel(StimmzettelumschlaegeDTO stimmzettelumschlaegeDTO);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.service.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.wls.common.security.domain.BezirkUndWahlID;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;

public record StimmzettelumschlaegeModel(@NotNull BezirkUndWahlID bezirkUndWahlID,
LocalDateTime urneneroeffnungsUhrzeit,
@NotNull long anzahlWaehler,
long anzahlWaehler2) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.service.stimmzettelumschlaege;

import de.muenchen.oss.wahllokalsystem.ergebnismeldungservice.domain.stimmzettelumschlaege.Stimmzettelumschlaege;
import org.mapstruct.Mapper;

@Mapper
public interface StimmzettelumschlaegeModelMapper {

StimmzettelumschlaegeModel toModel(Stimmzettelumschlaege entity);

Stimmzettelumschlaege toEntity(StimmzettelumschlaegeModel model);
}
Loading

0 comments on commit ec4fd68

Please sign in to comment.