Adjusted API to be more in line with resource orientation

This commit is contained in:
2023-08-19 03:52:50 +02:00
parent 37f57f788b
commit b411c97f53
5 changed files with 184 additions and 121 deletions
@@ -12,10 +12,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag import io.swagger.v3.oas.annotations.tags.Tag
import org.mapstruct.factory.Mappers import org.mapstruct.factory.Mappers
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.created
import org.springframework.http.ResponseEntity.ok
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import org.springframework.web.util.UriComponentsBuilder
@RestController @RestController
@RequestMapping(value = ["/wahlrecht/v1"]) @RequestMapping(value = ["/wahlrecht/v1"])
@@ -58,14 +60,14 @@ class ElectionController(private val service: ElectionService) {
content = [Content(mediaType = "application/json", schema = Schema(implementation = Election::class))] content = [Content(mediaType = "application/json", schema = Schema(implementation = Election::class))]
)] )]
) )
@GetMapping(value = ["/elections/by-name/{electionName}"], produces = [MediaType.APPLICATION_JSON_VALUE]) @GetMapping(value = ["/elections/{electionName}"], produces = [MediaType.APPLICATION_JSON_VALUE])
@SecurityRequirement(name = "bearerAuth") @SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2") @SecurityRequirement(name = "oauth2")
fun getElectionByName( fun getElectionByName(
@PathVariable @Parameter(description = "the election name", example = "Bezirkswahl 2019") electionName: String? @PathVariable @Parameter(description = "the election name", example = "Bezirkswahl 2019") electionName: String?
): ResponseEntity<Election> { ): ResponseEntity<Election> {
val election = mapper.mapToExternal(service.elections[electionName]!!) val election = mapper.mapToExternal(service.elections[electionName]!!)
return ResponseEntity.ok() return ok()
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.body(election) .body(election)
} }
@@ -84,8 +86,14 @@ class ElectionController(private val service: ElectionService) {
@PutMapping("/election") @PutMapping("/election")
@SecurityRequirement(name = "bearerAuth") @SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2") @SecurityRequirement(name = "oauth2")
fun putElection(@RequestBody election: Election?): ResponseEntity<*> { fun putElection(@RequestBody election: Election?, uriComponentsBuilder: UriComponentsBuilder):
ResponseEntity<Void> {
val createdNew = service.storeElection(mapper.mapToDB(election!!)) val createdNew = service.storeElection(mapper.mapToDB(election!!))
return if (createdNew) ResponseEntity<Any>(HttpStatus.CREATED) else ResponseEntity<Any>(HttpStatus.OK) return if (createdNew) {
created(uriComponentsBuilder.path("/elections/{electionName}")
.buildAndExpand(election.name).toUri())
.build()
}
else ok().build()
} }
} }
@@ -14,10 +14,12 @@ import io.swagger.v3.oas.annotations.tags.Tag
import lombok.RequiredArgsConstructor import lombok.RequiredArgsConstructor
import lombok.extern.slf4j.Slf4j import lombok.extern.slf4j.Slf4j
import org.mapstruct.factory.Mappers import org.mapstruct.factory.Mappers
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.created
import org.springframework.http.ResponseEntity.ok
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import org.springframework.web.util.UriComponentsBuilder
@Slf4j @Slf4j
@RestController @RestController
@@ -40,16 +42,16 @@ class ElectionResultController(private val service: ElectionResultService) {
)] )]
) )
@GetMapping( @GetMapping(
value = ["/electionResult/by-election-name/{electionName}"], value = ["/electionResults/{electionName}"],
produces = [MediaType.APPLICATION_JSON_VALUE] produces = [MediaType.APPLICATION_JSON_VALUE]
) )
@SecurityRequirement(name = "bearerAuth") @SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2") @SecurityRequirement(name = "oauth2")
fun getElectionByName( fun getElectionResultByElectionName(
@PathVariable @Parameter(description = "the election name", example = "Bezirkswahl 2019") electionName: String @PathVariable @Parameter(description = "the election name", example = "Bezirkswahl 2019") electionName: String
): ResponseEntity<ElectionResult> { ): ResponseEntity<ElectionResult> {
val result = mapper.mapToExternal(service.getElectionResult(electionName)) val result = mapper.mapToExternal(service.getElectionResult(electionName))
return ResponseEntity.ok() return ok()
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.body(result) .body(result)
} }
@@ -68,8 +70,14 @@ class ElectionResultController(private val service: ElectionResultService) {
@PutMapping("/electionResult") @PutMapping("/electionResult")
@SecurityRequirement(name = "bearerAuth") @SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2") @SecurityRequirement(name = "oauth2")
fun putElection(@RequestBody electionResult: ElectionResult?): ResponseEntity<*> { fun putElection(@RequestBody electionResult: ElectionResult?,
uriComponentsBuilder: UriComponentsBuilder): ResponseEntity<Void> {
val createdNew = service.storeResult(mapper.mapToDB(electionResult!!)) val createdNew = service.storeResult(mapper.mapToDB(electionResult!!))
return if (createdNew) ResponseEntity<Any>(HttpStatus.CREATED) else ResponseEntity<Any>(HttpStatus.OK) return if (createdNew) {
created(uriComponentsBuilder.path("/electionResult/{electionName}")
.buildAndExpand(electionResult.electionName).toUri())
.build()
}
else ok().build()
} }
} }
@@ -13,17 +13,20 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.security.SecurityRequirement import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag import io.swagger.v3.oas.annotations.tags.Tag
import org.mapstruct.factory.Mappers import org.mapstruct.factory.Mappers
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity import org.springframework.http.ResponseEntity
import org.springframework.http.ResponseEntity.created
import org.springframework.http.ResponseEntity.ok
import org.springframework.stereotype.Controller import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.* import org.springframework.web.bind.annotation.*
import org.springframework.web.util.UriComponentsBuilder
@Controller @Controller
@RequestMapping(value = ["/wahlrecht/v1"]) @RequestMapping(value = ["/wahlrecht/v1"])
@Tag(name = "Parties", description = "all requests relating to parties") @Tag(name = "Parties", description = "all requests relating to parties")
class PartyController(private val service: PartyService) { class PartyController(private val service: PartyService) {
private val mapper = Mappers.getMapper(PartyInElectionMapper::class.java) private val mapper = Mappers.getMapper(PartyInElectionMapper::class.java)
@Operation( @Operation(
summary = "Returns all stored parties for given election name", summary = "Returns all stored parties for given election name",
responses = [ApiResponse( responses = [ApiResponse(
@@ -39,7 +42,7 @@ class PartyController(private val service: PartyService) {
content = [Content(mediaType = "application/json", schema = Schema(implementation = ErrorMessage::class))] content = [Content(mediaType = "application/json", schema = Schema(implementation = ErrorMessage::class))]
)] )]
) )
@GetMapping(value = ["/parties/by-election-name/{electionName}"], produces = [MediaType.APPLICATION_JSON_VALUE]) @GetMapping(value = ["/parties/{electionName}"], produces = [MediaType.APPLICATION_JSON_VALUE])
@SecurityRequirement(name = "bearerAuth") @SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2") @SecurityRequirement(name = "oauth2")
fun getPartiesByElectionName( fun getPartiesByElectionName(
@@ -52,11 +55,41 @@ class PartyController(private val service: PartyService) {
) )
} }
.toList() .toList()
return ResponseEntity.ok() return ok()
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.body(parties) .body(parties)
} }
@Operation(
summary = "Returns stored party for given election name and party abbreviation",
responses = [ApiResponse(
responseCode = "200",
description = "Returns stored party",
content = [Content(
mediaType = "application/json",
schema = Schema(implementation = PartyInElection::class)
)]
), ApiResponse(
responseCode = "404",
description = "No party found",
content = [Content(mediaType = "application/json", schema = Schema(implementation = ErrorMessage::class))]
)]
)
@GetMapping(value = ["/parties/{electionName}/{abbreviation}"], produces = [MediaType.APPLICATION_JSON_VALUE])
@SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2")
fun getPartyByElectionNameAndAbbreviation(
@PathVariable @Parameter(description = "the election name", example = "Bezirkswahl 2019") electionName: String,
@PathVariable @Parameter(description = "the party abbreviation", example = "SPD") abbreviation: String
): ResponseEntity<PartyInElection> {
val party = mapper.mapToExternal(
service.getPartyByElectionNameAndAbbreviation(electionName, abbreviation)
)
return ok()
.contentType(MediaType.APPLICATION_JSON)
.body(party)
}
@Operation( @Operation(
summary = "Stores a new party in an election", summary = "Stores a new party in an election",
responses = [ApiResponse( responses = [ApiResponse(
@@ -70,8 +103,13 @@ class PartyController(private val service: PartyService) {
@PutMapping("/party") @PutMapping("/party")
@SecurityRequirement(name = "bearerAuth") @SecurityRequirement(name = "bearerAuth")
@SecurityRequirement(name = "oauth2") @SecurityRequirement(name = "oauth2")
fun putParty(@RequestBody party: PartyInElection?): ResponseEntity<*> { fun putParty(@RequestBody party: PartyInElection?,
uriComponentsBuilder: UriComponentsBuilder): ResponseEntity<Void> {
val createdNew = service.storeParty(mapper.mapToDB(party!!)) val createdNew = service.storeParty(mapper.mapToDB(party!!))
return if (createdNew) ResponseEntity<Any>(HttpStatus.CREATED) else ResponseEntity<Any>(HttpStatus.OK) return if (createdNew) {
created(uriComponentsBuilder.path("/parties/{electionName}/{abbreviation}")
.buildAndExpand(party.electionName, party.abbreviation).toUri())
.build()
} else ok().build()
} }
} }
@@ -5,4 +5,6 @@ import org.springframework.data.mongodb.repository.MongoRepository
interface PartyRepository : MongoRepository<PartyInElection, String> { interface PartyRepository : MongoRepository<PartyInElection, String> {
fun findByElectionName(name: String): Collection<PartyInElection> fun findByElectionName(name: String): Collection<PartyInElection>
fun findByElectionNameAndAbbreviation(electionName: String, abbreviation: String): PartyInElection?
} }
@@ -18,6 +18,13 @@ class PartyService(
fetchParties() fetchParties()
} }
fun getPartyByElectionNameAndAbbreviation(electionName: String,
abbreviation: String): PartyInElection {
return partyRepository.findByElectionNameAndAbbreviation(electionName, abbreviation)
?: throw ResponseStatusException(HttpStatus.NOT_FOUND,
"no party found for $electionName and $abbreviation")
}
fun getPartiesByElectionName(electionName: String): Collection<PartyInElection> { fun getPartiesByElectionName(electionName: String): Collection<PartyInElection> {
val parties = partyRepository.findByElectionName(electionName) val parties = partyRepository.findByElectionName(electionName)
if (parties.isEmpty()) { if (parties.isEmpty()) {