Skip to content

Commit

Permalink
Upgrade tapir / openapiCirceYaml versions (#7014)
Browse files Browse the repository at this point in the history
* Upgrade tapir / openapiCirceYaml versions

* Update withSecurity endpoint definitions, add examples, remove duplicated 403 definitions

* Add changelog entry

* Add impl class to translate securityErrors to messages, fix codec for securityErrors

* move ImpersonatedUserNotExistsError to AuthenticationError - Unauthorized

* Extend SecurityErrorWithMessage with AnyVal
  • Loading branch information
philemone authored Oct 17, 2024
1 parent 289921e commit ba4f89a
Show file tree
Hide file tree
Showing 8 changed files with 354 additions and 525 deletions.
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,8 @@ val cronParserV = "9.1.6" // 9.1.7+ requires JDK 16+
val javaxValidationApiV = "2.0.1.Final"
val caffeineCacheV = "3.1.8"
val sttpV = "3.9.8"
val tapirV = "1.10.5"
val openapiCirceYamlV = "0.9.0"
val tapirV = "1.11.7"
val openapiCirceYamlV = "0.11.3"
//we use legacy version because this one supports Scala 2.12
val monocleV = "2.1.0"
val jmxPrometheusJavaagentV = "0.20.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@ package pl.touk.nussknacker.restmodel

import pl.touk.nussknacker.restmodel.BaseEndpointDefinitions.ToSecure
import pl.touk.nussknacker.security.AuthCredentials
import pl.touk.nussknacker.ui.security.api.SecurityError
import pl.touk.nussknacker.ui.security.api.SecurityError.{
CannotAuthenticateUser,
ImpersonatedUserDataNotFoundError,
ImpersonationMissingPermissionError,
ImpersonationNotSupportedError,
InsufficientPermission
}
import sttp.model.StatusCode.{Forbidden, NotFound, NotImplemented, Unauthorized}
import pl.touk.nussknacker.ui.security.api.{AuthenticationError, AuthorizationError, SecurityError}
import pl.touk.nussknacker.ui.security.api.SecurityError._
import sttp.model.StatusCode.{Forbidden, NotImplemented, Unauthorized}
import sttp.tapir.EndpointIO.Example
import sttp.tapir._

Expand All @@ -29,7 +23,6 @@ trait BaseEndpointDefinitions {

object BaseEndpointDefinitions {

type EndpointError[ERROR] = Either[SecurityError, ERROR]
type SecuredEndpoint[INPUT, BUSINESS_ERROR, OUTPUT, -R] =
Endpoint[AuthCredentials, INPUT, Either[BUSINESS_ERROR, SecurityError], OUTPUT, R]

Expand All @@ -46,11 +39,11 @@ object BaseEndpointDefinitions {
oneOf(
oneOfVariantFromMatchType(
Unauthorized,
plainBody[CannotAuthenticateUser.type]
.example(
Example.of(
summary = Some("Authentication failed"),
value = CannotAuthenticateUser
plainBody[AuthenticationError]
.examples(
List(
Example.of(name = Some("CannotAuthenticateUser"), value = CannotAuthenticateUser),
Example.of(name = Some("ImpersonatedUserNotExistsError"), value = ImpersonatedUserNotExistsError)
)
)
),
Expand All @@ -67,37 +60,19 @@ object BaseEndpointDefinitions {
)
)
),
oneOfVariantFromMatchType(
NotFound,
plainBody[ImpersonatedUserDataNotFoundError.type]
.description("Identity provided in the Nu-Impersonate-User-Identity header did not match any user")
.example(
Example.of(
summary = Some("No impersonated user's data found for provided identity"),
value = ImpersonatedUserDataNotFoundError
)
)
),
oneOfVariantFromMatchType(
Forbidden,
plainBody[ImpersonationMissingPermissionError.type]
.example(
Example.of(
summary = Some("Authorization failed, user does not have permission to impersonate"),
value = ImpersonationMissingPermissionError
oneOfBody[AuthorizationError](
plainBody[AuthorizationError]
.examples(
List(
Example.of(name = Some("InsufficientPermission"), value = InsufficientPermission),
Example
.of(name = Some("ImpersonationMissingPermission"), value = ImpersonationMissingPermissionError)
)
)
)
)
),
oneOfVariantFromMatchType(
Forbidden,
plainBody[InsufficientPermission.type]
.example(
Example.of(
summary = Some("Authorization failed"),
value = InsufficientPermission
)
)
)
)
)
}
Expand All @@ -106,37 +81,15 @@ object BaseEndpointDefinitions {

private object Codecs {

implicit val authenticationErrorCodec: Codec[String, CannotAuthenticateUser.type, CodecFormat.TextPlain] = {
implicit val authorizationErrorCodec: Codec[String, AuthorizationError, CodecFormat.TextPlain] = {
Codec.string.map(
Mapping.from[String, CannotAuthenticateUser.type](_ => CannotAuthenticateUser)(_ =>
"The supplied authentication is invalid"
)
Mapping.from[String, AuthorizationError](deserializationNotSupportedException)(s => s.errorMessage)
)
}

implicit val authorizationErrorCodec: Codec[String, InsufficientPermission.type, CodecFormat.TextPlain] = {
implicit val authenticationErrorCodec: Codec[String, AuthenticationError, CodecFormat.TextPlain] = {
Codec.string.map(
Mapping.from[String, InsufficientPermission.type](_ => InsufficientPermission)(_ =>
"The supplied authentication is not authorized to access this resource"
)
)
}

implicit val impersonationPermissionErrorCodec
: Codec[String, ImpersonationMissingPermissionError.type, CodecFormat.TextPlain] = {
Codec.string.map(
Mapping.from[String, ImpersonationMissingPermissionError.type](_ => ImpersonationMissingPermissionError)(_ =>
ImpersonationMissingPermissionError.errorMessage
)
)
}

implicit val impersonatedDataNotFoundErrorCodec
: Codec[String, ImpersonatedUserDataNotFoundError.type, CodecFormat.TextPlain] = {
Codec.string.map(
Mapping.from[String, ImpersonatedUserDataNotFoundError.type](_ => ImpersonatedUserDataNotFoundError)(_ =>
ImpersonatedUserDataNotFoundError.errorMessage
)
Mapping.from[String, AuthenticationError](deserializationNotSupportedException)(s => s.errorMessage)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,6 @@ object TestingApiHttpService {
)
)

val noProcessingTypeExample: EndpointOutput.OneOfVariant[NoProcessingType] =
oneOfVariantFromMatchType(
NotFound,
plainBody[NoProcessingType]
.example(
Example.of(
summary = Some("ProcessingType type: {processingType} not found"),
value = NoProcessingType("'processingType'")
)
)
)

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class TestingApiEndpoints(auth: EndpointInput[AuthCredentials]) extends BaseEndp
)
.errorOut(
oneOf[TestingError](
noScenarioExample // TODO
noScenarioExample
)
)
.withSecurity(auth)
Expand Down Expand Up @@ -205,7 +205,7 @@ class TestingApiEndpoints(auth: EndpointInput[AuthCredentials]) extends BaseEndp
.errorOut(
oneOf[TestingError](
testDataGenerationErrorExample,
noScenarioExample // TODO
noScenarioExample
)
)
.withSecurity(auth)
Expand Down
Loading

0 comments on commit ba4f89a

Please sign in to comment.