Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(common): return an InvalidRequest error when a parameter is invalid - 6.3.20 #1271

Merged
merged 24 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
aa9d287
wip: refacto params
thomasBousselin Nov 22, 2024
61c1916
wip: refacto params
thomasBousselin Nov 22, 2024
494e52e
wip: refacto params
thomasBousselin Nov 26, 2024
ea4bfaa
wip: refacto params compiling
thomasBousselin Nov 26, 2024
3ba3937
refacto: move param parser into the class they are building
thomasBousselin Nov 27, 2024
06c0a2f
feat: first working AllowedParameters annotation
thomasBousselin Nov 27, 2024
b0a2080
feat: first working AllowedParameters annotation
thomasBousselin Nov 27, 2024
2426fb0
feat: rename QueryParameter add allowed parameters to entityhandler
thomasBousselin Nov 28, 2024
46e3e66
feat: add AllowedParameters to all specification endpoint + shortcut QP
thomasBousselin Nov 29, 2024
7de92c0
feat: first PR comments
thomasBousselin Nov 29, 2024
fe5b40b
feat: first PR comments
thomasBousselin Nov 29, 2024
af9f3ae
feat: first PR comments
thomasBousselin Nov 29, 2024
0fbf3dd
feat: move to queryparameter
thomasBousselin Nov 29, 2024
00f61cb
feat: rename parameter params into queryParams
thomasBousselin Nov 29, 2024
d40a7cf
chore: misc fixes and renaming
bobeal Nov 30, 2024
c8eac87
feat: PR comments
thomasBousselin Dec 2, 2024
0ef2440
feat: harmonize reception of queryParameters
thomasBousselin Dec 2, 2024
964eace
feat: add tests
thomasBousselin Dec 2, 2024
17a8621
fix: error message formatting
thomasBousselin Dec 3, 2024
7fa9337
Apply suggestions from code review
thomasBousselin Dec 3, 2024
139ff4c
fix: error message formatting
thomasBousselin Dec 4, 2024
d35ef76
fix: allowed parameters on entityAccessControl endpoints
thomasBousselin Dec 5, 2024
f0c426b
Update search-service/src/main/kotlin/com/egm/stellio/search/csr/web/…
thomasBousselin Dec 5, 2024
104a5d4
fix: missing validated
thomasBousselin Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ subprojects {
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-validation")
// it provides support for JWT decoding and verification
implementation("org.springframework.security:spring-security-oauth2-jose")

Expand Down
2 changes: 1 addition & 1 deletion config/detekt/detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ style:
active: true
UnusedParameter:
active: true
allowedNames: 'ignored|expected'
allowedNames: 'ignored|expected|queryParams'
UnusedPrivateClass:
active: true
UnusedPrivateMember:
Expand Down
3 changes: 2 additions & 1 deletion search-service/config/detekt/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ID>Filename:V0_29__JsonLd_migration.kt$db.migration.V0_29__JsonLd_migration.kt</ID>
<ID>LongMethod:AttributeInstanceService.kt$AttributeInstanceService$@Transactional suspend fun create(attributeInstance: AttributeInstance): Either&lt;APIException, Unit&gt;</ID>
<ID>LongMethod:EnabledAuthorizationServiceTests.kt$EnabledAuthorizationServiceTests$@Test fun `it should return serialized access control entities with other rigths if user is owner`()</ID>
<ID>LongMethod:EntityAccessControlHandler.kt$EntityAccessControlHandler$@PostMapping("/{subjectId}/attrs", consumes = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE]) suspend fun addRightsOnEntities( @RequestHeader httpHeaders: HttpHeaders, @PathVariable subjectId: String, @RequestBody requestBody: Mono&lt;String&gt; ): ResponseEntity&lt;*&gt;</ID>
<ID>LongMethod:EntityAccessControlHandler.kt$EntityAccessControlHandler$@PostMapping("/{subjectId}/attrs", consumes = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE]) suspend fun addRightsOnEntities( @RequestHeader httpHeaders: HttpHeaders, @PathVariable subjectId: String, @RequestBody requestBody: Mono&lt;String&gt;, @AllowedParameters @RequestParam queryParams: MultiValueMap&lt;String, String&gt; ): ResponseEntity&lt;*&gt;</ID>
<ID>LongMethod:LinkedEntityServiceTests.kt$LinkedEntityServiceTests$@Test fun `it should inline entities up to the asked 2nd level`()</ID>
<ID>LongMethod:PatchAttributeTests.kt$PatchAttributeTests.Companion$@JvmStatic fun mergePatchProvider(): Stream&lt;Arguments&gt;</ID>
<ID>LongMethod:PatchAttributeTests.kt$PatchAttributeTests.Companion$@JvmStatic fun partialUpdatePatchProvider(): Stream&lt;Arguments&gt;</ID>
Expand All @@ -27,6 +27,7 @@
<ID>LongParameterList:EntityAttributeService.kt$EntityAttributeService$( entityUri: URI, ngsiLdAttributes: List&lt;NgsiLdAttribute&gt;, expandedAttributes: ExpandedAttributes, createdAt: ZonedDateTime, observedAt: ZonedDateTime?, sub: Sub? )</ID>
<ID>LongParameterList:EntityAttributeService.kt$EntityAttributeService$( entityUri: URI, ngsiLdAttributes: List&lt;NgsiLdAttribute&gt;, expandedAttributes: ExpandedAttributes, disallowOverwrite: Boolean, createdAt: ZonedDateTime, sub: Sub? )</ID>
<ID>LongParameterList:EntityEventService.kt$EntityEventService$( updatedDetails: UpdatedDetails, sub: String?, tenantName: String, entityId: URI, entityTypesAndPayload: Pair&lt;List&lt;ExpandedTerm&gt;, String&gt;, serializedAttribute: Pair&lt;ExpandedTerm, String&gt;, overwrite: Boolean )</ID>
<ID>LongParameterList:TemporalEntityHandler.kt$TemporalEntityHandler$( @RequestHeader httpHeaders: HttpHeaders, @PathVariable entityId: URI, @PathVariable attrId: String, @PathVariable instanceId: URI, @RequestBody requestBody: Mono&lt;String&gt;, @AllowedParameters(notImplemented = [QP.LOCAL, QP.VIA]) @RequestParam queryParams: MultiValueMap&lt;String, String&gt; )</ID>
<ID>LongParameterList:V0_29__JsonLd_migration.kt$V0_29__JsonLd_migration$( entityId: URI, attributeName: ExpandedTerm, datasetId: URI?, attributePayload: ExpandedAttributeInstance, ngsiLdAttributeInstance: NgsiLdAttributeInstance, defaultCreatedAt: ZonedDateTime )</ID>
<ID>NestedBlockDepth:V0_29__JsonLd_migration.kt$V0_29__JsonLd_migration$override fun migrate(context: Context)</ID>
<ID>SwallowedException:TemporalQueryUtils.kt$e: IllegalArgumentException</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import com.egm.stellio.shared.model.APIException
import com.egm.stellio.shared.model.AccessDeniedException
import com.egm.stellio.shared.model.EntityTypeSelection
import com.egm.stellio.shared.model.NgsiLdAttribute
import com.egm.stellio.shared.model.PaginationQuery
import com.egm.stellio.shared.model.ResourceNotFoundException
import com.egm.stellio.shared.queryparameter.PaginationQuery
import com.egm.stellio.shared.util.AccessRight
import com.egm.stellio.shared.util.AccessRight.CAN_ADMIN
import com.egm.stellio.shared.util.AccessRight.CAN_READ
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.egm.stellio.search.authorization.web
bobeal marked this conversation as resolved.
Show resolved Hide resolved

import arrow.core.computations.ResultEffect.bind
import arrow.core.left
import arrow.core.raise.either
import com.egm.stellio.search.authorization.service.AuthorizationService
Expand All @@ -12,10 +13,13 @@ import com.egm.stellio.search.entity.util.composeEntitiesQueryFromGet
import com.egm.stellio.shared.config.ApplicationProperties
import com.egm.stellio.shared.model.AccessDeniedException
import com.egm.stellio.shared.model.BadRequestDataException
import com.egm.stellio.shared.model.NgsiLdDataRepresentation.Companion.parseRepresentations
import com.egm.stellio.shared.model.NgsiLdRelationship
import com.egm.stellio.shared.model.toFinalRepresentation
import com.egm.stellio.shared.model.toNgsiLdAttribute
import com.egm.stellio.shared.model.toNgsiLdAttributes
import com.egm.stellio.shared.queryparameter.AllowedParameters
import com.egm.stellio.shared.queryparameter.QP
import com.egm.stellio.shared.util.AccessRight
import com.egm.stellio.shared.util.AuthContextModel.ALL_ASSIGNABLE_IAM_RIGHTS
import com.egm.stellio.shared.util.AuthContextModel.ALL_IAM_RIGHTS
Expand All @@ -34,7 +38,6 @@ import com.egm.stellio.shared.util.checkAndGetContext
import com.egm.stellio.shared.util.getApplicableMediaType
import com.egm.stellio.shared.util.getAuthzContextFromLinkHeaderOrDefault
import com.egm.stellio.shared.util.getSubFromSecurityContext
import com.egm.stellio.shared.util.parseRepresentations
import com.egm.stellio.shared.util.replaceDefaultContextToAuthzContext
import com.egm.stellio.shared.web.BaseHandler
import kotlinx.coroutines.reactive.awaitFirst
Expand Down Expand Up @@ -66,7 +69,8 @@ class EntityAccessControlHandler(
@GetMapping("/entities", produces = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
suspend fun getAuthorizedEntities(
@RequestHeader httpHeaders: HttpHeaders,
@RequestParam params: MultiValueMap<String, String>
@AllowedParameters(implemented = [QP.ID, QP.TYPE, QP.ATTRS, QP.COUNT, QP.OFFSET, QP.LIMIT])
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()

Expand All @@ -75,7 +79,7 @@ class EntityAccessControlHandler(

val entitiesQuery = composeEntitiesQueryFromGet(
applicationProperties.pagination,
params,
queryParams,
contexts
).bind()

Expand All @@ -96,13 +100,13 @@ class EntityAccessControlHandler(

val compactedEntities = compactEntities(entities, contexts)

val ngsiLdDataRepresentation = parseRepresentations(params, mediaType)
val ngsiLdDataRepresentation = parseRepresentations(queryParams, mediaType)
buildQueryResponse(
compactedEntities.toFinalRepresentation(ngsiLdDataRepresentation),
count,
"/ngsi-ld/v1/entityAccessControl/entities",
entitiesQuery.paginationQuery,
params,
queryParams,
mediaType,
contexts
)
Expand All @@ -114,6 +118,7 @@ class EntityAccessControlHandler(
@GetMapping("/groups", produces = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
suspend fun getGroupsMemberships(
@RequestHeader httpHeaders: HttpHeaders,
@AllowedParameters(implemented = [QP.COUNT, QP.OFFSET, QP.LIMIT])
@RequestParam params: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()
Expand Down Expand Up @@ -158,6 +163,7 @@ class EntityAccessControlHandler(
@GetMapping("/users", produces = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
suspend fun getUsers(
@RequestHeader httpHeaders: HttpHeaders,
@AllowedParameters(implemented = [QP.COUNT, QP.OFFSET, QP.LIMIT])
@RequestParam params: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()
Expand Down Expand Up @@ -204,7 +210,9 @@ class EntityAccessControlHandler(
suspend fun addRightsOnEntities(
@RequestHeader httpHeaders: HttpHeaders,
@PathVariable subjectId: String,
@RequestBody requestBody: Mono<String>
@RequestBody requestBody: Mono<String>,
@AllowedParameters
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()

Expand Down Expand Up @@ -282,7 +290,9 @@ class EntityAccessControlHandler(
@DeleteMapping("/{subjectId}/attrs/{entityId}")
suspend fun removeRightsOnEntity(
@PathVariable subjectId: String,
@PathVariable entityId: URI
@PathVariable entityId: URI,
@AllowedParameters
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()

Expand All @@ -305,7 +315,9 @@ class EntityAccessControlHandler(
suspend fun updateSpecificAccessPolicy(
@RequestHeader httpHeaders: HttpHeaders,
@PathVariable entityId: URI,
@RequestBody requestBody: Mono<String>
@RequestBody requestBody: Mono<String>,
@AllowedParameters
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()

Expand All @@ -331,7 +343,9 @@ class EntityAccessControlHandler(

@DeleteMapping("/{entityId}/attrs/specificAccessPolicy")
suspend fun deleteSpecificAccessPolicy(
@PathVariable entityId: URI
@PathVariable entityId: URI,
@AllowedParameters
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import com.egm.stellio.search.csr.model.MiscellaneousWarning
import com.egm.stellio.search.csr.model.NGSILDWarning
import com.egm.stellio.search.csr.model.RevalidationFailedWarning
import com.egm.stellio.shared.model.CompactedEntity
import com.egm.stellio.shared.util.QUERY_PARAM_GEOMETRY_PROPERTY
import com.egm.stellio.shared.util.QUERY_PARAM_LANG
import com.egm.stellio.shared.util.QUERY_PARAM_OPTIONS
import com.egm.stellio.shared.queryparameter.QueryParameter
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.core.codec.DecodingException
Expand All @@ -38,9 +36,9 @@ object ContextSourceCaller {
val uri = URI("${csr.endpoint}$path")

val queryParams = CollectionUtils.toMultiValueMap(params.toMutableMap())
queryParams.remove(QUERY_PARAM_GEOMETRY_PROPERTY)
queryParams.remove(QUERY_PARAM_OPTIONS) // only normalized request
queryParams.remove(QUERY_PARAM_LANG)
queryParams.remove(QueryParameter.GEOMETRY_PROPERTY.key)
queryParams.remove(QueryParameter.OPTIONS.key) // only normalized request
queryParams.remove(QueryParameter.LANG.key)

val request = WebClient.create()
.method(HttpMethod.GET)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ import com.egm.stellio.search.csr.service.ContextSourceRegistrationService
import com.egm.stellio.shared.config.ApplicationProperties
import com.egm.stellio.shared.model.APIException
import com.egm.stellio.shared.model.AccessDeniedException
import com.egm.stellio.shared.queryparameter.AllowedParameters
import com.egm.stellio.shared.queryparameter.OptionsValue
import com.egm.stellio.shared.queryparameter.PaginationQuery.Companion.parsePaginationParameters
import com.egm.stellio.shared.queryparameter.QP
import com.egm.stellio.shared.queryparameter.QueryParameter
import com.egm.stellio.shared.util.JSON_LD_CONTENT_TYPE
import com.egm.stellio.shared.util.JsonUtils.deserializeAsMap
import com.egm.stellio.shared.util.QUERY_PARAM_OPTIONS
import com.egm.stellio.shared.util.QUERY_PARAM_OPTIONS_SYSATTRS_VALUE
import com.egm.stellio.shared.util.Sub
import com.egm.stellio.shared.util.buildQueryResponse
import com.egm.stellio.shared.util.checkAndGetContext
import com.egm.stellio.shared.util.getApplicableMediaType
import com.egm.stellio.shared.util.getContextFromLinkHeaderOrDefault
import com.egm.stellio.shared.util.getSubFromSecurityContext
import com.egm.stellio.shared.util.parsePaginationParameters
import com.egm.stellio.shared.util.prepareGetSuccessResponseHeaders
import com.egm.stellio.shared.web.BaseHandler
import kotlinx.coroutines.reactive.awaitFirst
Expand All @@ -32,6 +34,7 @@ import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.util.MultiValueMap
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
Expand All @@ -46,6 +49,7 @@ import java.net.URI

@RestController
@RequestMapping("/ngsi-ld/v1/csourceRegistrations")
@Validated
class ContextSourceRegistrationHandler(
private val applicationProperties: ApplicationProperties,
private val contextSourceRegistrationService: ContextSourceRegistrationService
Expand Down Expand Up @@ -81,16 +85,25 @@ class ContextSourceRegistrationHandler(
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
suspend fun get(
@RequestHeader httpHeaders: HttpHeaders,
@RequestParam params: MultiValueMap<String, String>
@AllowedParameters(
implemented = [QP.OPTIONS, QP.COUNT, QP.OFFSET, QP.LIMIT],
notImplemented = [
QP.ID, QP.TYPE, QP.ID_PATTERN, QP.ATTRS, QP.Q, QP.CSF,
QP.GEOMETRY, QP.GEOREL, QP.COORDINATES, QP.GEOPROPERTY,
QP.TIMEPROPERTY, QP.TIMEREL, QP.TIMEAT, QP.ENDTIMEAT,
QP.GEOMETRY_PROPERTY, QP.LANG, QP.SCOPEQ,
]
)
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val contexts = getContextFromLinkHeaderOrDefault(httpHeaders, applicationProperties.contexts.core).bind()
val mediaType = getApplicableMediaType(httpHeaders).bind()
val sub = getSubFromSecurityContext()

val includeSysAttrs = params.getOrDefault(QUERY_PARAM_OPTIONS, emptyList())
.contains(QUERY_PARAM_OPTIONS_SYSATTRS_VALUE)
val includeSysAttrs = queryParams.getOrDefault(QueryParameter.OPTIONS.key, emptyList())
.contains(OptionsValue.SYS_ATTRS.value)
val paginationQuery = parsePaginationParameters(
params,
queryParams,
applicationProperties.pagination.limitDefault,
applicationProperties.pagination.limitMax
).bind()
Expand All @@ -107,7 +120,7 @@ class ContextSourceRegistrationHandler(
contextSourceRegistrationsCount,
"/ngsi-ld/v1/csourceRegistrations",
paginationQuery,
params,
queryParams,
mediaType,
contexts
)
Expand All @@ -123,9 +136,11 @@ class ContextSourceRegistrationHandler(
suspend fun getByURI(
@RequestHeader httpHeaders: HttpHeaders,
@PathVariable contextSourceRegistrationId: URI,
@RequestParam options: String?
@AllowedParameters(implemented = [QP.OPTIONS])
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val includeSysAttrs = options == QUERY_PARAM_OPTIONS_SYSATTRS_VALUE
val options = queryParams.getFirst(QP.OPTIONS.key)
val includeSysAttrs = options?.contains(OptionsValue.SYS_ATTRS.value) ?: false
val contexts = getContextFromLinkHeaderOrDefault(httpHeaders, applicationProperties.contexts.core).bind()
val mediaType = getApplicableMediaType(httpHeaders).bind()

Expand All @@ -144,7 +159,11 @@ class ContextSourceRegistrationHandler(
* Implements 6.9.3.3 - Delete ContextSourceRegistration
*/
@DeleteMapping("/{contextSourceRegistrationId}")
suspend fun delete(@PathVariable contextSourceRegistrationId: URI): ResponseEntity<*> = either {
suspend fun delete(
@PathVariable contextSourceRegistrationId: URI,
@AllowedParameters // no query parameter is defined in the specification
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val sub = getSubFromSecurityContext()
checkIsAllowed(contextSourceRegistrationId, sub).bind()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.egm.stellio.search.discovery.web
import arrow.core.raise.either
import com.egm.stellio.search.discovery.service.AttributeService
import com.egm.stellio.shared.config.ApplicationProperties
import com.egm.stellio.shared.queryparameter.AllowedParameters
import com.egm.stellio.shared.queryparameter.QP
import com.egm.stellio.shared.util.JSON_LD_CONTENT_TYPE
import com.egm.stellio.shared.util.JsonLdUtils.expandJsonLdTerm
import com.egm.stellio.shared.util.JsonUtils
Expand All @@ -13,16 +15,18 @@ import com.egm.stellio.shared.util.prepareGetSuccessResponseHeaders
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.util.MultiValueMap
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.util.Optional

@RestController
@RequestMapping("/ngsi-ld/v1/attributes")
@Validated
class AttributeHandler(
private val attributeService: AttributeService,
private val applicationProperties: ApplicationProperties
Expand All @@ -33,11 +37,14 @@ class AttributeHandler(
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
suspend fun getAttributes(
@RequestHeader httpHeaders: HttpHeaders,
@RequestParam details: Optional<Boolean>
@AllowedParameters(implemented = [QP.DETAILS], notImplemented = [QP.LOCAL, QP.VIA])
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val details = queryParams.getFirst(QP.DETAILS.key)?.toBoolean()

val contexts = getContextFromLinkHeaderOrDefault(httpHeaders, applicationProperties.contexts.core).bind()
val mediaType = getApplicableMediaType(httpHeaders).bind()
val detailedRepresentation = details.orElse(false)
val detailedRepresentation = details ?: false

val availableAttribute: Any = if (detailedRepresentation)
attributeService.getAttributeDetails(contexts)
Expand All @@ -56,7 +63,9 @@ class AttributeHandler(
@GetMapping("/{attrId}", produces = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
suspend fun getByAttributeId(
@RequestHeader httpHeaders: HttpHeaders,
@PathVariable attrId: String
@PathVariable attrId: String,
@AllowedParameters(notImplemented = [QP.LOCAL, QP.VIA])
@RequestParam queryParams: MultiValueMap<String, String>
): ResponseEntity<*> = either {
val contexts = getContextFromLinkHeaderOrDefault(httpHeaders, applicationProperties.contexts.core).bind()
val mediaType = getApplicableMediaType(httpHeaders).bind()
Expand Down
Loading
Loading