Merge pull request #2 from rbkmoney/ft/JD-267/move-from-dark-api

Ft/jd 267/move from dark api
This commit is contained in:
ElenaKushchenko 2021-06-04 17:20:26 +03:00 committed by GitHub
commit 240b2bc5b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 434 additions and 152 deletions

15
pom.xml
View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.rbkmoney</groupId>
<artifactId>service-parent-pom</artifactId>
<version>1.2.2</version>
<version>1.2.4</version>
</parent>
<artifactId>claim-management-api</artifactId>
@ -26,10 +26,11 @@
<exposed.ports>${server.port} ${management.port}</exposed.ports>
<dockerfile.registry>${env.REGISTRY}</dockerfile.registry>
<swag-claim-management.version>1.29-d665bf2-server</swag-claim-management.version>
<swag-claim-management.version>1.30-eafa8b6-server</swag-claim-management.version>
<keycloak-spring-security.version>12.0.1</keycloak-spring-security.version>
<bouncycastle-jdk15on.version>1.68</bouncycastle-jdk15on.version>
<spring-cloud-contract-wiremock.version>2.2.4.RELEASE</spring-cloud-contract-wiremock.version>
<spring-security.version>5.4.6</spring-security.version>
<jjwt.version>0.9.1</jjwt.version>
<kotlin-logging.version>2.0.6</kotlin-logging.version>
<mockito-kotlin.version>3.2.0</mockito-kotlin.version>
@ -115,6 +116,16 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>

View File

@ -17,12 +17,7 @@ import com.rbkmoney.damsel.claim_management.InvalidClaimStatus
import com.rbkmoney.damsel.claim_management.LimitExceeded
import com.rbkmoney.swag.claim_management.api.ProcessingApi
import com.rbkmoney.swag.claim_management.model.Claim
import com.rbkmoney.swag.claim_management.model.GeneralError
import com.rbkmoney.swag.claim_management.model.InlineResponse200
import com.rbkmoney.swag.claim_management.model.InlineResponse400
import com.rbkmoney.swag.claim_management.model.InlineResponse4001
import com.rbkmoney.swag.claim_management.model.InlineResponse4002
import com.rbkmoney.swag.claim_management.model.InlineResponse4003
import com.rbkmoney.swag.claim_management.model.Modification
import mu.KotlinLogging
import org.apache.thrift.TException
@ -53,54 +48,31 @@ class ClaimManagementController(
@NotNull @Size(min = 1, max = 40) xRequestId: String?,
@NotNull @Valid changeset: List<Modification>?,
@Size(min = 1, max = 40) xRequestDeadline: String?
): ResponseEntity<Claim> {
return try {
): ResponseEntity<Claim> =
performRequest("createClaim", xRequestId!!) {
log.info { "Process 'createClaim' get started, xRequestId=$xRequestId" }
partyManagementService.checkStatus(xRequestId)
deadlineChecker.checkDeadline(xRequestDeadline, xRequestId)
val claim = claimManagementService.createClaim(keycloakService.partyId, changeset!!)
log.info { "Claim created, xRequestId=$xRequestId, claimId=${claim.id}" }
ResponseEntity.ok(claim)
} catch (ex: DeadlineException) {
val msg = ex.message
val response: InlineResponse4001 = InlineResponse4001()
.code(InlineResponse4001.CodeEnum.INVALIDDEADLINE)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidChangeset) {
val msg = "Invalid changeset, xRequestId=$xRequestId, reason='${ex.reason}'"
val response: InlineResponse4001 = InlineResponse4001()
.code(InlineResponse4001.CodeEnum.INVALIDCHANGESET)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: TException) {
throw buildDarkApi5xxException("createClaim", xRequestId, ex)
}
}
@PreAuthorize("hasAuthority('party:read')")
override fun getClaimByID(
@NotNull @Size(min = 1, max = 40) xRequestId: String?,
@NotNull @Valid claimId: Long?,
@Size(min = 1, max = 40) xRequestDeadline: String?
): ResponseEntity<Claim> {
return try {
): ResponseEntity<Claim> =
performRequest("getClaimByID", xRequestId!!, claimId!!) {
log.info { "Process 'getClaimByID' get started, xRequestId=$xRequestId, claimId=$claimId" }
partyManagementService.checkStatus(xRequestId)
deadlineChecker.checkDeadline(xRequestDeadline, xRequestId)
val claim = claimManagementService.getClaimById(keycloakService.partyId, claimId!!)
val claim = claimManagementService.getClaimById(keycloakService.partyId, claimId)
log.info { "Got a claim, xRequestId=$xRequestId, claimId=$claimId" }
ResponseEntity.ok(claim)
} catch (ex: DeadlineException) {
val msg = ex.message
val response: GeneralError = GeneralError().message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: ClaimNotFound) {
throw buildNotFoundException(xRequestId!!, claimId!!, ex)
} catch (ex: TException) {
throw buildDarkApi5xxException("getClaimByID", xRequestId, ex)
}
}
@PreAuthorize("hasAuthority('party:write')")
override fun revokeClaimByID(
@ -109,38 +81,16 @@ class ClaimManagementController(
@NotNull @Valid claimRevision: Int?,
@Size(min = 1, max = 40) xRequestDeadline: String?,
@Valid reason: String?
): ResponseEntity<Void> {
return try {
): ResponseEntity<Void> =
performRequest("revokeClaimByID", xRequestId!!, claimId!!, claimRevision!!) {
log.info { "Process 'revokeClaimByID' get started, xRequestId=$xRequestId, claimId=$claimId" }
partyManagementService.checkStatus(xRequestId)
deadlineChecker.checkDeadline(xRequestDeadline, xRequestId)
claimManagementService.revokeClaimById(keycloakService.partyId, claimId!!, claimRevision!!, reason)
claimManagementService.revokeClaimById(keycloakService.partyId, claimId, claimRevision, reason)
log.info { "Successful revoke claim, xRequestId=$xRequestId, claimId=$claimId" }
ResponseEntity<Void>(HttpStatus.OK)
} catch (ex: DeadlineException) {
val msg = ex.message
val response: InlineResponse4002 = InlineResponse4002()
.code(InlineResponse4002.CodeEnum.INVALIDDEADLINE)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidClaimStatus) {
val msg = "Invalid claim status, xRequestId=$xRequestId, status=${ex.status}"
val response: InlineResponse4002 = InlineResponse4002()
.code(InlineResponse4002.CodeEnum.INVALIDCLAIMSTATUS)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidClaimRevision) {
val msg = "Invalid claim revision, xRequestId=$xRequestId, claimRevision=$claimRevision"
val response: InlineResponse4002 = InlineResponse4002()
.code(InlineResponse4002.CodeEnum.INVALIDCLAIMREVISION)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: ClaimNotFound) {
throw buildNotFoundException(xRequestId!!, claimId!!, ex)
} catch (ex: TException) {
throw buildDarkApi5xxException("revokeClaimByID", xRequestId, ex)
}
}
@PreAuthorize("hasAuthority('party:write')")
override fun requestReviewClaimByID(
@ -148,38 +98,16 @@ class ClaimManagementController(
@NotNull @Valid claimId: Long?,
@NotNull @Valid claimRevision: Int?,
@Size(min = 1, max = 40) xRequestDeadline: String?
): ResponseEntity<Void> {
return try {
): ResponseEntity<Void> =
performRequest("requestClaimReviewById", xRequestId!!, claimId!!, claimRevision!!) {
log.info { "Process 'requestReviewClaimByID' get started, xRequestId=$xRequestId, claimId=$claimId" }
partyManagementService.checkStatus(xRequestId)
deadlineChecker.checkDeadline(xRequestDeadline, xRequestId)
claimManagementService.requestClaimReviewById(keycloakService.partyId, claimId!!, claimRevision!!)
claimManagementService.requestClaimReviewById(keycloakService.partyId, claimId, claimRevision)
log.info { "Successful request claim review, xRequestId=$xRequestId, claimId=$claimId" }
ResponseEntity<Void>(HttpStatus.OK)
} catch (ex: DeadlineException) {
val msg = ex.message
val response: InlineResponse4002 = InlineResponse4002()
.code(InlineResponse4002.CodeEnum.INVALIDDEADLINE)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidClaimStatus) {
val msg = "Invalid claim status, xRequestId=$xRequestId, status=${ex.status}"
val response: InlineResponse4002 = InlineResponse4002()
.code(InlineResponse4002.CodeEnum.INVALIDCLAIMSTATUS)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidClaimRevision) {
val msg = "Invalid claim revision, xRequestId=$xRequestId, claimRevision=$claimRevision"
val response: InlineResponse4002 = InlineResponse4002()
.code(InlineResponse4002.CodeEnum.INVALIDCLAIMREVISION)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: ClaimNotFound) {
throw buildNotFoundException(xRequestId!!, claimId!!, ex)
} catch (ex: TException) {
throw buildDarkApi5xxException("requestClaimReviewById", xRequestId, ex)
}
}
@PreAuthorize("hasAuthority('party:read')")
override fun searchClaims(
@ -189,12 +117,12 @@ class ClaimManagementController(
@Size(min = 1, max = 40) continuationToken: String?,
@Valid claimId: Long?,
@Valid claimStatuses: List<String>?
): ResponseEntity<InlineResponse200> {
return try {
): ResponseEntity<InlineResponse200> =
performRequest("searchClaims", xRequestId!!, claimId!!) {
log.info { "Process 'searchClaims' get started, xRequestId=$xRequestId, claimId=$claimId" }
partyManagementService.checkStatus(xRequestId)
deadlineChecker.checkDeadline(xRequestDeadline, xRequestId)
val response: InlineResponse200 = claimManagementService.searchClaims(
val response = claimManagementService.searchClaims(
keycloakService.partyId,
limit!!,
continuationToken,
@ -205,96 +133,75 @@ class ClaimManagementController(
"For status list, xRequestId=$xRequestId, claimId=$claimId, list statuses=$claimStatuses, " +
"size results=${response.result.size}"
}
ResponseEntity.ok(response)
} catch (ex: DeadlineException) {
val msg = ex.message
val response: InlineResponse400 = InlineResponse400()
.code(InlineResponse400.CodeEnum.INVALIDDEADLINE)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: LimitExceeded) {
val msg = "Limit exceeded, xRequestId=$xRequestId"
val response: InlineResponse400 = InlineResponse400()
.code(InlineResponse400.CodeEnum.LIMITEXCEEDED)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: BadContinuationToken) {
val msg = "Bad continuation token, xRequestId=$xRequestId, reason=${ex.reason}"
val response: InlineResponse400 = InlineResponse400()
.code(InlineResponse400.CodeEnum.BADCONTINUATIONTOKEN)
.message(msg)
throw BadRequestException(msg, ex, response)
} catch (ex: TException) {
throw buildDarkApi5xxException("searchClaims", xRequestId, ex)
}
}
@PreAuthorize("hasAuthority('party:write')")
override fun updateClaimByID(
@NotNull @Size(min = 1, max = 40) xRequestId: String?,
@NotNull @Valid claimId: Long,
@NotNull @Valid claimId: Long?,
@NotNull @Valid claimRevision: Int?,
@NotNull @Valid changeset: List<Modification>?,
@Size(min = 1, max = 40) xRequestDeadline: String?
): ResponseEntity<Void> {
return try {
): ResponseEntity<Void> =
performRequest("updateClaimByID", xRequestId!!, claimId!!, claimRevision!!) {
log.info { "Process 'updateClaimByID' get started, requestId=$xRequestId, claimId=$claimId" }
partyManagementService.checkStatus(xRequestId)
deadlineChecker.checkDeadline(xRequestDeadline, xRequestId)
claimManagementService.updateClaimById(keycloakService.partyId, claimId, claimRevision!!, changeset!!)
claimManagementService.updateClaimById(keycloakService.partyId, claimId, claimRevision, changeset!!)
log.info { "Successful update claim, xRequestId=$xRequestId, claimId=$claimId" }
ResponseEntity<Void>(HttpStatus.OK)
}
private fun <T> performRequest(
methodName: String,
xRequestId: String,
claimId: Long? = null,
claimRevision: Int? = null,
operation: () -> ResponseEntity<T>
): ResponseEntity<T> =
try {
operation.invoke()
} catch (ex: DeadlineException) {
val msg = ex.message
val response: InlineResponse4003 = InlineResponse4003()
.code(InlineResponse4003.CodeEnum.INVALIDDEADLINE)
.message(msg)
val response = ErrorData(ErrorData.Code.INVALIDDEADLINE, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidClaimStatus) {
val msg = "Invalid claim status, xRequestId=$xRequestId, status=${ex.status}"
val response: InlineResponse4003 = InlineResponse4003()
.code(InlineResponse4003.CodeEnum.INVALIDCLAIMSTATUS)
.message(msg)
val response = ErrorData(ErrorData.Code.INVALIDCLAIMSTATUS, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidClaimRevision) {
val msg = "Invalid claim revision, xRequestId=$xRequestId, claimRevision=$claimRevision"
val response: InlineResponse4003 = InlineResponse4003()
.code(InlineResponse4003.CodeEnum.INVALIDCLAIMREVISION)
.message(msg)
val response = ErrorData(ErrorData.Code.INVALIDCLAIMREVISION, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: ChangesetConflict) {
val msg = "Changeset conflict, xRequestId=$xRequestId, conflictedId=${ex.conflictedId}"
val response: InlineResponse4003 = InlineResponse4003()
.code(InlineResponse4003.CodeEnum.CHANGESETCONFLICT)
.message(msg)
val response = ErrorData(ErrorData.Code.CHANGESETCONFLICT, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: InvalidChangeset) {
val msg = "Invalid changeset, xRequestId=$xRequestId, reason='${ex.reason}'"
val response: InlineResponse4003 = InlineResponse4003()
.code(InlineResponse4003.CodeEnum.INVALIDCHANGESET)
.message(msg)
val response = ErrorData(ErrorData.Code.INVALIDCHANGESET, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: LimitExceeded) {
val msg = "Limit exceeded, xRequestId=$xRequestId"
val response = ErrorData(ErrorData.Code.LIMITEXCEEDED, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: BadContinuationToken) {
val msg = "Bad continuation token, xRequestId=$xRequestId, reason=${ex.reason}"
val response = ErrorData(ErrorData.Code.BADCONTINUATIONTOKEN, msg)
throw BadRequestException(msg, ex, response)
} catch (ex: ClaimNotFound) {
throw buildNotFoundException(xRequestId!!, claimId, ex)
val msg = "Claim not found, claimId=$claimId, xRequestId=$xRequestId"
val response = ErrorData(message = msg)
throw NotFoundException(msg, ex, response)
} catch (ex: TException) {
throw buildDarkApi5xxException("updateClaimByID", xRequestId, ex)
throw DarkApi5xxException(
"Some TException while requesting api='$API_NAME', method='$methodName', xRequestId=$xRequestId",
ex
)
}
}
private fun buildNotFoundException(xRequestId: String, claimId: Long, ex: ClaimNotFound): NotFoundException {
val msg = "Claim not found, claimId=$claimId, xRequestId=$xRequestId"
val response = GeneralError().message(msg)
return NotFoundException(msg, ex, response)
}
private fun buildDarkApi5xxException(
methodName: String?,
xRequestId: String?,
ex: TException?
) = DarkApi5xxException(
"Some TException while requesting api='$API_NAME', method='$methodName', xRequestId=$xRequestId",
ex
)
companion object {
const val API_NAME = "claim-management"

View File

@ -0,0 +1,127 @@
package com.rbkmoney.claimmanagementapi.controller
import com.rbkmoney.claimmanagementapi.exception.client.BadRequestException
import com.rbkmoney.claimmanagementapi.exception.client.DarkApi4xxException
import com.rbkmoney.claimmanagementapi.exception.client.ForbiddenException
import com.rbkmoney.claimmanagementapi.exception.client.NotFoundException
import com.rbkmoney.claimmanagementapi.exception.server.DarkApi5xxException
import mu.KotlinLogging
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.AccessDeniedException
import org.springframework.web.HttpMediaTypeNotAcceptableException
import org.springframework.web.HttpMediaTypeNotSupportedException
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.MissingServletRequestParameterException
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestControllerAdvice
import org.springframework.web.client.HttpClientErrorException
import org.springframework.web.context.request.WebRequest
import java.lang.Exception
import java.net.http.HttpTimeoutException
@RestControllerAdvice
class ErrorControllerAdvice {
private val log = KotlinLogging.logger { }
// ----------------- 4xx -----------------------------------------------------
@ExceptionHandler(BadRequestException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun handleBadRequestException(e: BadRequestException): Any {
log.warn(e) { "<- Res [400]: Not valid" }
return e.response
}
@ExceptionHandler(MethodArgumentNotValidException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException) {
log.warn(e) { "<- Res [400]: MethodArgument not valid" }
}
@ExceptionHandler(MissingServletRequestParameterException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun handleMissingServletRequestParameterException(e: MissingServletRequestParameterException) {
log.warn(e) { "<- Res [400]: Missing ServletRequestParameter" }
}
@ExceptionHandler(AccessDeniedException::class)
@ResponseStatus(HttpStatus.FORBIDDEN)
fun handleAccessDeniedException(e: AccessDeniedException) {
log.warn(e) { "<- Res [403]: Request denied access" }
}
@ExceptionHandler(ForbiddenException::class)
@ResponseStatus(HttpStatus.FORBIDDEN)
fun handleForbiddenException(e: ForbiddenException) {
log.warn(e) { "<- Res [403]: Request denied access" }
}
@ExceptionHandler(NotFoundException::class)
@ResponseStatus(HttpStatus.NOT_FOUND)
fun handleFileNotFoundException(e: NotFoundException): Any {
log.warn(e) { "<- Res [404]: Not found" }
return e.response
}
@ExceptionHandler(HttpMediaTypeNotAcceptableException::class)
@ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
fun handleHttpMediaTypeNotAcceptable(e: HttpMediaTypeNotAcceptableException) {
log.warn(e) { "<- Res [406]: MediaType not acceptable" }
}
@ExceptionHandler(HttpMediaTypeNotSupportedException::class)
fun handleHttpMediaTypeNotSupported(
e: HttpMediaTypeNotSupportedException,
request: WebRequest
): ResponseEntity<*> {
log.warn(e) { "<- Res [415]: MediaType not supported" }
return ResponseEntity.status(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
.headers(httpHeaders(e))
.build<Any>()
}
@ExceptionHandler(DarkApi4xxException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun handleDarkApiClientException(e: DarkApi4xxException) {
log.warn(e) { "<- Res [400]: Unrecognized Error by controller" }
}
// ----------------- 5xx -----------------------------------------------------
@ExceptionHandler(HttpClientErrorException::class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
fun handleHttpClientErrorException(e: HttpClientErrorException) {
log.error(e) {
"<- Res [500]: Error with using inner http client, code=${e.statusCode}, body=${e.responseBodyAsString}"
}
}
@ExceptionHandler(HttpTimeoutException::class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
fun handleHttpTimeoutException(e: HttpTimeoutException) {
log.error(e) { "<- Res [500]: Timeout with using inner http client" }
}
@ExceptionHandler(DarkApi5xxException::class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
fun handleHttpTimeoutException(e: DarkApi5xxException) {
log.error(e) { "<- Res [500]: Unrecognized inner error" }
}
@ExceptionHandler(Exception::class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
fun handleException(e: Exception) {
log.error(e) { "<- Res [500]: Unrecognized inner error" }
}
private fun httpHeaders(e: HttpMediaTypeNotSupportedException): HttpHeaders {
val headers = HttpHeaders()
val mediaTypes = e.supportedMediaTypes
if (mediaTypes.isNotEmpty()) {
headers.accept = mediaTypes
}
return headers
}
}

View File

@ -0,0 +1,26 @@
package com.rbkmoney.claimmanagementapi.controller
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonValue
@JsonInclude(JsonInclude.Include.NON_NULL)
data class ErrorData(
@field:JsonProperty("code")
val code: Code? = null,
@field:JsonProperty("message")
val message: String? = null
) {
enum class Code(private val value: String) {
INVALIDCLAIMSTATUS("invalidClaimStatus"),
CHANGESETCONFLICT("changesetConflict"),
INVALIDCHANGESET("invalidChangeset"),
INVALIDCLAIMREVISION("invalidClaimRevision"),
LIMITEXCEEDED("limitExceeded"),
BADCONTINUATIONTOKEN("badContinuationToken"),
INVALIDDEADLINE("invalidDeadline");
@JsonValue
override fun toString() = value
}
}

View File

@ -0,0 +1,25 @@
package com.rbkmoney.claimmanagementapi.converter.claim
import com.rbkmoney.claimmanagementapi.converter.DarkApiConverter
import org.springframework.stereotype.Component
import com.rbkmoney.damsel.claim_management.ExternalInfoModificationUnit as ThriftExternalInfoModificationUnit
import com.rbkmoney.swag.claim_management.model.ClaimModificationType as SwagClaimModificationType
import com.rbkmoney.swag.claim_management.model.ExternalInfoModificationUnit as SwagExternalInfoModificationUnit
@Component
class ClaimExternalInfoModificationUnitConverter :
DarkApiConverter<ThriftExternalInfoModificationUnit, SwagExternalInfoModificationUnit> {
override fun convertToThrift(value: SwagExternalInfoModificationUnit) =
ThriftExternalInfoModificationUnit().apply {
documentId = value.documentId
roistatId = value.roistatId
}
override fun convertToSwag(value: ThriftExternalInfoModificationUnit) =
SwagExternalInfoModificationUnit().apply {
documentId = value.documentId
roistatId = value.roistatId
claimModificationType = SwagClaimModificationType.ClaimModificationTypeEnum.EXTERNALINFOMODIFICATIONUNIT
}
}

View File

@ -8,6 +8,7 @@ import com.rbkmoney.damsel.claim_management.Modification as ThriftModification
import com.rbkmoney.swag.claim_management.model.ClaimModification as SwagClaimModification
import com.rbkmoney.swag.claim_management.model.CommentModificationUnit as SwagCommentModificationUnit
import com.rbkmoney.swag.claim_management.model.DocumentModificationUnit as SwagDocumentModificationUnit
import com.rbkmoney.swag.claim_management.model.ExternalInfoModificationUnit as SwagExternalInfoModificationUnit
import com.rbkmoney.swag.claim_management.model.FileModificationUnit as SwagFileModificationUnit
import com.rbkmoney.swag.claim_management.model.Modification as SwagModification
import com.rbkmoney.swag.claim_management.model.StatusModificationUnit as SwagStatusModificationUnit
@ -17,7 +18,8 @@ class ClaimModificationConverter(
private val documentModificationUnitConverter: ClaimDocumentModificationUnitConverter,
private val commentModificationUnitConverter: ClaimCommentModificationUnitConverter,
private val statusModificationUnitConverter: ClaimStatusModificationUnitConverter,
private val fileModificationUnitConverter: ClaimFileModificationUnitConverter
private val fileModificationUnitConverter: ClaimFileModificationUnitConverter,
private val extInfoModificationUnitConverter: ClaimExternalInfoModificationUnitConverter
) : DarkApiConverter<ThriftModification, SwagClaimModification> {
override fun convertToThrift(value: SwagClaimModification): ThriftModification {
@ -44,6 +46,11 @@ class ClaimModificationConverter(
val fileModificationUnit = swagClaimModificationType as SwagFileModificationUnit
claimModification.fileModification = fileModificationUnitConverter.convertToThrift(fileModificationUnit)
}
ClaimModificationTypeEnum.EXTERNALINFOMODIFICATIONUNIT -> {
val extInfoModificationUnit = swagClaimModificationType as SwagExternalInfoModificationUnit
claimModification.externalInfoModification =
extInfoModificationUnitConverter.convertToThrift(extInfoModificationUnit)
}
else -> throw IllegalArgumentException("Unknown claim modification type: $swagClaimModificationType")
}
modification.claimModification = claimModification
@ -74,6 +81,11 @@ class ClaimModificationConverter(
swagClaimModification.claimModificationType =
fileModificationUnitConverter.convertToSwag(fileModificationUnit)
}
claimModification.isSetExternalInfoModification -> {
val externalInfoModificationUnit = claimModification.externalInfoModification
swagClaimModification.claimModificationType =
extInfoModificationUnitConverter.convertToSwag(externalInfoModificationUnit)
}
else -> throw IllegalArgumentException("Unknown claim modification type")
}
swagClaimModification.modificationType = SwagModification.ModificationTypeEnum.CLAIMMODIFICATION

View File

@ -0,0 +1,173 @@
package com.rbkmoney.claimmanagementapi.controller
import com.fasterxml.jackson.databind.ObjectMapper
import com.rbkmoney.claimmanagementapi.config.AbstractKeycloakOpenIdAsWiremockConfig
import com.rbkmoney.claimmanagementapi.service.ClaimManagementService
import com.rbkmoney.claimmanagementapi.service.ClaimManagementServiceTest
import com.rbkmoney.claimmanagementapi.service.PartyManagementService
import com.rbkmoney.damsel.claim_management.ChangesetConflict
import com.rbkmoney.damsel.claim_management.ClaimNotFound
import com.rbkmoney.damsel.claim_management.InvalidChangeset
import com.rbkmoney.damsel.claim_management.InvalidClaimRevision
import com.rbkmoney.damsel.claim_management.InvalidClaimStatus
import org.apache.thrift.TException
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.ArgumentMatchers
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.reset
import org.mockito.kotlin.whenever
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.UUID
class ErrorControllerTest : AbstractKeycloakOpenIdAsWiremockConfig() {
@Autowired
private lateinit var mockMvc: MockMvc
@Autowired
private lateinit var objectMapper: ObjectMapper
@MockBean
private lateinit var partyManagementService: PartyManagementService
@MockBean
private lateinit var claimManagementService: ClaimManagementService
@BeforeEach
fun setUp() {
doNothing().whenever(partyManagementService).checkStatus(ArgumentMatchers.anyString())
doNothing().whenever(partyManagementService).checkStatus()
}
@Test
fun testThenClaimManagementClientThrowingExceptions() {
whenever(claimManagementService.getClaimById(ArgumentMatchers.anyString(), ArgumentMatchers.anyLong()))
.doAnswer { throw ClaimNotFound() }
mockMvc.perform(
MockMvcRequestBuilders.get("/processing/claims/{claimID}", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateReadJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
).andExpect(MockMvcResultMatchers.status().isNotFound)
reset(claimManagementService)
whenever(
claimManagementService.updateClaimById(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyList()
)
).doAnswer { throw ClaimNotFound() }
mockMvc.perform(
MockMvcRequestBuilders.put("/processing/claims/{claimID}/update", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateWriteJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
.param("claimRevision", 123.toString())
.content(objectMapper.writeValueAsBytes(ClaimManagementServiceTest.modifications))
).andExpect(MockMvcResultMatchers.status().isNotFound)
reset(claimManagementService)
whenever(
claimManagementService.updateClaimById(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyList()
)
).doAnswer { throw InvalidClaimStatus() }
mockMvc.perform(
MockMvcRequestBuilders.put("/processing/claims/{claimID}/update", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateWriteJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
.param("claimRevision", 123.toString())
.content(objectMapper.writeValueAsBytes(ClaimManagementServiceTest.modifications))
).andExpect(MockMvcResultMatchers.status().isBadRequest)
reset(claimManagementService)
whenever(
claimManagementService.updateClaimById(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyList()
)
).doAnswer { throw InvalidClaimRevision() }
mockMvc.perform(
MockMvcRequestBuilders.put("/processing/claims/{claimID}/update", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateWriteJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
.param("claimRevision", 123.toString())
.content(objectMapper.writeValueAsBytes(ClaimManagementServiceTest.modifications))
).andExpect(MockMvcResultMatchers.status().isBadRequest)
reset(claimManagementService)
whenever(
claimManagementService.updateClaimById(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyList()
)
).doAnswer { throw ChangesetConflict() }
mockMvc.perform(
MockMvcRequestBuilders.put("/processing/claims/{claimID}/update", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateWriteJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
.param("claimRevision", 123.toString())
.content(objectMapper.writeValueAsBytes(ClaimManagementServiceTest.modifications))
).andExpect(MockMvcResultMatchers.status().isBadRequest)
reset(claimManagementService)
whenever(
claimManagementService.updateClaimById(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyList()
)
).doAnswer { throw InvalidChangeset() }
mockMvc.perform(
MockMvcRequestBuilders.put("/processing/claims/{claimID}/update", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateWriteJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
.param("claimRevision", 123.toString())
.content(objectMapper.writeValueAsBytes(ClaimManagementServiceTest.modifications))
).andExpect(MockMvcResultMatchers.status().isBadRequest)
reset(claimManagementService)
whenever(
claimManagementService.updateClaimById(
ArgumentMatchers.anyString(),
ArgumentMatchers.anyLong(),
ArgumentMatchers.anyInt(),
ArgumentMatchers.anyList()
)
).doAnswer { throw TException() }
mockMvc.perform(
MockMvcRequestBuilders.put("/processing/claims/{claimID}/update", ArgumentMatchers.anyLong())
.contentType(MediaType.APPLICATION_JSON_UTF8)
.header("Authorization", "Bearer " + generateWriteJwt())
.header("X-Request-ID", string())
.header("X-Request-Deadline", Instant.now().plus(1, ChronoUnit.DAYS).toString())
.param("claimRevision", 123.toString())
.content(objectMapper.writeValueAsBytes(ClaimManagementServiceTest.modifications))
).andExpect(MockMvcResultMatchers.status().isInternalServerError)
}
private fun string() = UUID.randomUUID().toString()
}

View File

@ -156,7 +156,8 @@ class ClaimConvertersTest {
ClaimDocumentModificationUnitConverter(),
ClaimCommentModificationUnitConverter(),
ClaimStatusModificationUnitConverter(ClaimStatusModificationConverter()),
ClaimFileModificationUnitConverter()
ClaimFileModificationUnitConverter(),
ClaimExternalInfoModificationUnitConverter()
)
val swagStatusModUnit = SwagStatusModificationUnit().apply {
claimModificationType = ClaimModificationTypeEnum.STATUSMODIFICATIONUNIT

View File

@ -133,7 +133,7 @@ class ClaimManagementServiceTest {
return changeset
}
private val modifications: List<SwagModification>
val modifications: List<SwagModification>
get() {
val documentModification = DocumentModification()
.apply { documentModificationType = DocumentModificationTypeEnum.DOCUMENTCREATED }