Class PolicyEnforcementPoint

java.lang.Object
org.gcube.informationsystem.resourceregistry.pep.PolicyEnforcementPoint
Direct Known Subclasses:
ContextPolicyEnforcementPoint, InstancesPolicyEnforcementPoint, QueryTemplatePolicyEnforcementPoint, StatisticsPolicyEnforcementPoint, SystemPolicyEnforcementPoint, TypePolicyEnforcementPoint

public abstract class PolicyEnforcementPoint extends Object
Base class for all Policy Enforcement Points (PEP) in the resource-registry service.

A PEP is the single coupling point between the HTTP/REST layer and the role-agnostic backend Management classes. Each collection (Contexts, Types, Instances, Queries, …) has exactly one PEP subclass.

State and utilities shared across all PEPs:

  • getUriInfo() — the JAX-RS UriInfo for the current request, used to read query parameters and build response headers.
  • isPrivilegedUser() — checks whether the current caller holds a globally-privileged role (IS-Manager or Infrastructure-Manager).
  • isUniversalUser() — checks whether the current caller holds a universal role (IS-Manager, Infrastructure-Manager, or IS-Admin).
Author:
Luca Frosini (ISTI - CNR)
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
    Specification for an entire HTTP endpoint's policy.
    static class 
    Specification for query parameter authorization and validation.
    static enum 
    Defines rules for binding the Context in the caller's JWT token to the target resource.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final Set<String>
    Set of all administrative roles: the universal roles and Context-Manager.
    static final Set<String>
    Set of all operational roles in the system.
    static final String
    Role constant representing the Context-Manager role.
    static final int
    Default value for the depth query parameter (mirrors ContextPath.DEPTH_QUERY_PARAMETER_DEFAULT_READ_VALUE).
    static final Set<String>
    Set of globally privileged administrative roles.
    static final String
    Role constant representing the Infrastructure-Manager role.
    static final String
    Role constant representing the IS-Admin role.
    static final String
    Role constant representing the IS-Contributor role.
    static final String
    Role constant representing the IS-Editor role.
    static final String
    Role constant representing the IS-Manager role.
    static final String
    Role constant representing the IS-Member role.
    static final String
    Legacy query parameter kept for server-side operational compatibility only.
    static final String
    Legacy query parameter kept for server-side operational compatibility only.
    static final int
    Default value for the limit pagination parameter (mirrors InstancePath.LIMIT_QUERY_PARAMETER_DEFAULT_VALUE).
    static final int
    System-enforced maximum value for the limit parameter (anti-DoS cap).
    Policy specification of the membershipScope query parameter, shared by every endpoint that accepts it: global is restricted to the UNIVERSAL_ROLES.
    static final int
    Default value for the offset pagination parameter (mirrors InstancePath.OFFSET_QUERY_PARAMETER_DEFAULT_VALUE).
    protected jakarta.ws.rs.container.ContainerRequestContext
    JAX-RS request context for the current request.
    static final Set<String>
    Set of universal roles, whose capabilities are recognized independently of the Context tree: the global managers and IS-Admin.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    PolicyEnforcementPoint(jakarta.ws.rs.container.ContainerRequestContext requestContext)
    Creates a new PolicyEnforcementPoint instance for the current HTTP request.
  • Method Summary

    Modifier and Type
    Method
    Description
    protected void
    Adds a structured content warning produced by the Management/backend layer.
    protected void
    Adds a structured ignored-fields-on-write warning (called internally by PEP subclasses after deserializing a write request body).
    protected void
    addLink(String rel, String targetUri)
    Records an RFC 8288 Link header relation to be emitted on the response, per appendix/08-hateoas-navigation.md.
    protected void
    Emits the standard RFC 8288 pagination Link relations for a paginated response, pointing at the current request path with limit/offset substituted.
    protected void
    addPreferenceApplied(org.gcube.informationsystem.resourceregistry.api.rest.OperationReturn operationReturn)
    Records the OperationReturn preference honored for the current request's Operation Envelope response.
    protected void
    Adds a structured query-parameter warning (called internally by resolve* methods), also recording it on the ContainerRequestContext "warnings" property from which the global WarningResponseFilter emits it as an X-Warning response header.
    protected void
    addResultScope(org.gcube.informationsystem.resourceregistry.api.rest.ResultScope scope)
    Records that the response was affected by the given ResultScope (e.g. a hierarchical lookup succeeded via descendant expansion, or the response was state-filtered).
    protected String
    buildUri(String... pathSegments)
    Builds an absolute target URI by joining the current request's base URI with the given path segments, e.g.
    protected void
    Enforces the Level 1 endpoint access rule: a caller holding none of the policy's roles (including a caller with no Resource Registry role at all) is rejected before any parsing, lookup, or token Context resolution.
    protected void
    Enforces the endpoint-level and context-level authorization rules specified by the given policy specification, and automatically validates query parameters.
    protected void
    Rejects with 403 Forbidden every privilege-expanding value declared by the policy's PolicyEnforcementPoint.QueryParamSpecs when the caller holds none of the entitled roles.
    protected void
    enforceTargetContextWithinTokenSubtree(UUID targetContextUuid, String operationName)
    Enforces that the given target Context is either the caller's token Context itself or one of its descendants (the token Context's subtree is self-inclusive).
    Returns an aggregated, immutable view of all warnings accumulated during this request: query-parameter warnings first, content warnings second, ignored-fields warnings third.
    Returns the canonical URI recorded for this request's single-instance read, or null if none was recorded (e.g. a List/Query response, or a write handled by the request-path-based fallback in ContentLocationResponseFilter).
    Returns an immutable view of only the content warnings accumulated during this request.
    Returns an immutable view of only the ignored-fields-on-write warnings accumulated during this request.
    Returns an immutable view of the Link relations accumulated during this request.
    org.gcube.informationsystem.resourceregistry.api.rest.OperationReturn
    Returns the operation-envelope return preference honored during this request, or null if none was recorded.
    Returns an immutable view of only the query-parameter warnings accumulated during this request.
    protected String
    Returns the first raw value of the given query parameter, or null when the parameter is absent or no UriInfo is available.
    Returns the current path the caller's token resolved to during this request when the token carried a previous path, or null otherwise (TokenContextResolution).
    Set<org.gcube.informationsystem.resourceregistry.api.rest.ResultScope>
    Returns an immutable view of the result scopes accumulated during this request, including ResultScope.PREVIOUS_PATH when the token was resolved through a previous path (TokenContextResolution).
    jakarta.ws.rs.core.UriInfo
    Returns the JAX-RS UriInfo for the current request.
    protected static jakarta.ws.rs.BadRequestException
    invalidQueryParameterValue(String paramName, String raw, String expectation)
    Builds the 400 Bad Request raised for a malformed or unknown query parameter value: such a value is never replaced by a default.
    protected boolean
    Returns true if the current caller holds at least one administrative role (ALL_ADMIN_ROLES: IS-Manager, Infrastructure-Manager, IS-Admin, or Context-Manager).
    protected boolean
    Returns true if the current caller holds at least one globally-privileged role (IS-Manager or Infrastructure-Manager).
    protected boolean
    Returns true if the current caller holds at least one universal role (UNIVERSAL_ROLES: IS-Manager, Infrastructure-Manager, or IS-Admin).
    protected boolean
    isUserAllowed(Set<String> allowedRoles)
    Helper method to check if the current user holds at least one of the allowed roles.
    protected void
    reportStateFilteredInstances(boolean filterState)
    Reports ResultScope.STATE_FILTERED for a hierarchical read, list, query or Query Template execution whose instance selection was state-filtered, when the requested subtree contains at least one descendant Context that is not effectively ACTIVE, whether or not that Context holds an instance the request would select.
    protected void
    Requires the caller's token to resolve to a live Context, for the operations that act in the token Context (reference 08, Token path resolution): a token path that matches only a Context in the cemetery, or no Context at all, gives the caller no authority over any Context, and the operation is refused with 403 Forbidden, whatever the caller's role and whether the operation reads or writes.
    protected boolean
    Resolves the allMeta query parameter from the current request.
    protected boolean
    resolveBoolean(String paramName, boolean defaultValue)
    Low-level helper: resolves a boolean query parameter with strict validation.
    protected boolean
    Resolves the bypassHierarchyCheck query parameter from the current request (Add to Context only).
    protected org.gcube.informationsystem.resourceregistry.api.rest.ContextsPolicy
    Resolves the contextsPolicy query parameter from the current request.
    protected int
    Resolves the depth query parameter from the current request.
    protected int
    resolveDepth(int defaultValue)
    Resolves the depth query parameter from the current request, falling back to an explicit caller-supplied default instead of the global DEPTH_DEFAULT.
    protected boolean
    Resolves the dryRun query parameter from the current request.
    protected <E extends Enum<E>>
    E
    resolveEnum(String paramName, E[] values, E defaultValue)
    Resolves an enumerated query parameter whose wire values are the exact toString() of the enum constants (lowercase): any other value, including a different case, is unknown.
    protected boolean
    Resolves the hierarchical query parameter from the current request.
    protected boolean
    Resolves the includeMeta query parameter from the current request.
    protected int
    Resolves the limit pagination parameter from the current request.
    protected org.gcube.informationsystem.resourceregistry.api.rest.MembershipScope
    Resolves the membershipScope query parameter from the current request.
    protected MembershipView
    Builds the view that selects the memberships listed by every contexts map of the response: the boundary requested with membershipScope, without the Contexts that are not effectively ACTIVE for a caller lacking the administrative state override.
    protected org.gcube.informationsystem.resourceregistry.api.rest.MetadataPolicy
    Resolves metadata inclusion policy for the current request.
    protected int
    Resolves the offset pagination parameter from the current request.
    protected boolean
    Resolves the polymorphic query parameter from the current request.
    protected org.gcube.informationsystem.resourceregistry.api.rest.PropagationMode
    Resolves the propagationMode query parameter from the current request.
    protected boolean
    Resolves the rawResult query parameter from the current request (raw-query endpoint only).
    protected UUID
    Resolves the Context UUID bound to the caller's authorization token.
    protected void
    Records the canonical URI of the single-instance representation this request is about to return, for ContentLocationResponseFilter to emit as the Content-Location response header (RFC 9110 Section 8.7), per 07-api-foundations-and-roles.md.
    protected void
    Validates the query parameters of the current request against the given set of accepted parameter names and accumulates an IGNORED warning for any parameter that is not in acceptedParams.
    protected void
    Reports as ignored the representation-enrichment parameters the request carries when another directive leaves no representation to enrich: metadataPolicy, a non-default contextsPolicy, and a non-default membershipScope.
    protected void
    Reports that the representation-enrichment parameters were requested but had no effect because the query's _emit projection replaced the full instance representation with a flat, projection-only response (Canonical _emit Precedence Rules, appendix/07-json-query-syntax-reference.md).

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • IS_MANAGER

      public static final String IS_MANAGER
      Role constant representing the IS-Manager role.
      See Also:
    • INFRASTRUCTURE_MANAGER

      public static final String INFRASTRUCTURE_MANAGER
      Role constant representing the Infrastructure-Manager role.
      See Also:
    • IS_ADMIN

      public static final String IS_ADMIN
      Role constant representing the IS-Admin role.
      See Also:
    • CONTEXT_MANAGER

      public static final String CONTEXT_MANAGER
      Role constant representing the Context-Manager role.
      See Also:
    • IS_EDITOR

      public static final String IS_EDITOR
      Role constant representing the IS-Editor role.
      See Also:
    • IS_CONTRIBUTOR

      public static final String IS_CONTRIBUTOR
      Role constant representing the IS-Contributor role.
      See Also:
    • IS_MEMBER

      public static final String IS_MEMBER
      Role constant representing the IS-Member role.
      See Also:
    • GLOBAL_PRIVILEGED_ROLES

      public static final Set<String> GLOBAL_PRIVILEGED_ROLES
      Set of globally privileged administrative roles.
    • UNIVERSAL_ROLES

      public static final Set<String> UNIVERSAL_ROLES
      Set of universal roles, whose capabilities are recognized independently of the Context tree: the global managers and IS-Admin. Context-Manager is subtree-bound and never belongs to it.
    • ALL_ADMIN_ROLES

      public static final Set<String> ALL_ADMIN_ROLES
      Set of all administrative roles: the universal roles and Context-Manager. They hold the administrative override of non-ACTIVE Context states.
    • ALL_OPERATIONAL_ROLES

      public static final Set<String> ALL_OPERATIONAL_ROLES
      Set of all operational roles in the system.
    • DEPTH_DEFAULT

      public static final int DEPTH_DEFAULT
      Default value for the depth query parameter (mirrors ContextPath.DEPTH_QUERY_PARAMETER_DEFAULT_READ_VALUE).
    • LIMIT_DEFAULT

      public static final int LIMIT_DEFAULT
      Default value for the limit pagination parameter (mirrors InstancePath.LIMIT_QUERY_PARAMETER_DEFAULT_VALUE).
      See Also:
    • LIMIT_MAX

      public static final int LIMIT_MAX
      System-enforced maximum value for the limit parameter (anti-DoS cap).
      See Also:
    • OFFSET_DEFAULT

      public static final int OFFSET_DEFAULT
      Default value for the offset pagination parameter (mirrors InstancePath.OFFSET_QUERY_PARAMETER_DEFAULT_VALUE).
      See Also:
    • MEMBERSHIP_SCOPE_PARAM_SPEC

      public static final PolicyEnforcementPoint.QueryParamSpec MEMBERSHIP_SCOPE_PARAM_SPEC
      Policy specification of the membershipScope query parameter, shared by every endpoint that accepts it: global is restricted to the UNIVERSAL_ROLES.
    • LEGACY_INCLUDE_META_QUERY_PARAMETER

      public static final String LEGACY_INCLUDE_META_QUERY_PARAMETER
      Legacy query parameter kept for server-side operational compatibility only.
      See Also:
    • LEGACY_ALL_META_QUERY_PARAMETER

      public static final String LEGACY_ALL_META_QUERY_PARAMETER
      Legacy query parameter kept for server-side operational compatibility only.
      See Also:
    • requestContext

      protected jakarta.ws.rs.container.ContainerRequestContext requestContext
      JAX-RS request context for the current request.
  • Constructor Details

    • PolicyEnforcementPoint

      protected PolicyEnforcementPoint(jakarta.ws.rs.container.ContainerRequestContext requestContext)
      Creates a new PolicyEnforcementPoint instance for the current HTTP request.
      Parameters:
      requestContext - the JAX-RS ContainerRequestContext for the current request
  • Method Details

    • getUriInfo

      public jakarta.ws.rs.core.UriInfo getUriInfo()
      Returns the JAX-RS UriInfo for the current request.
      Returns:
      the request URI information
    • addQueryParameterWarning

      protected void addQueryParameterWarning(QueryParameterWarning warning)
      Adds a structured query-parameter warning (called internally by resolve* methods), also recording it on the ContainerRequestContext "warnings" property from which the global WarningResponseFilter emits it as an X-Warning response header.
      Parameters:
      warning - the query-parameter warning to accumulate
    • addContentWarning

      protected void addContentWarning(ContentWarning warning)
      Adds a structured content warning produced by the Management/backend layer. Typically called by the PEP subclass after invoking a Management method, to propagate any backend warnings into the HTTP response.
      Parameters:
      warning - the content warning to accumulate
    • addIgnoredFieldsWarning

      protected void addIgnoredFieldsWarning(IgnoredFieldsWarning warning)
      Adds a structured ignored-fields-on-write warning (called internally by PEP subclasses after deserializing a write request body).
      Parameters:
      warning - the ignored-fields warning to accumulate
    • getQueryParameterWarnings

      public List<QueryParameterWarning> getQueryParameterWarnings()
      Returns an immutable view of only the query-parameter warnings accumulated during this request.
      Returns:
      immutable list of query-parameter warnings
    • getContentWarnings

      public List<ContentWarning> getContentWarnings()
      Returns an immutable view of only the content warnings accumulated during this request.
      Returns:
      immutable list of content warnings
    • getIgnoredFieldsWarnings

      public List<IgnoredFieldsWarning> getIgnoredFieldsWarnings()
      Returns an immutable view of only the ignored-fields-on-write warnings accumulated during this request.
      Returns:
      immutable list of ignored-fields warnings
    • getAllWarnings

      public List<ServiceWarning> getAllWarnings()
      Returns an aggregated, immutable view of all warnings accumulated during this request: query-parameter warnings first, content warnings second, ignored-fields warnings third. This accessor is a convenience for tests and callers holding this PEP instance directly; the actual X-Warning response headers are emitted by the global WarningResponseFilter from the same warnings, independently accumulated on the JAX-RS ContainerRequestContext "warnings" property by addQueryParameterWarning(org.gcube.informationsystem.resourceregistry.http.headers.warning.QueryParameterWarning), addContentWarning(org.gcube.informationsystem.resourceregistry.http.headers.warning.ContentWarning), and addIgnoredFieldsWarning(org.gcube.informationsystem.resourceregistry.http.headers.warning.IgnoredFieldsWarning).
      Returns:
      immutable list of all accumulated warnings
    • addResultScope

      protected void addResultScope(org.gcube.informationsystem.resourceregistry.api.rest.ResultScope scope)
      Records that the response was affected by the given ResultScope (e.g. a hierarchical lookup succeeded via descendant expansion, or the response was state-filtered). The REST layer emits these as a single combined X-Result-Scope response header via ResultScopeResponseFilter.
      Parameters:
      scope - the result scope to accumulate
    • getResultScopes

      public Set<org.gcube.informationsystem.resourceregistry.api.rest.ResultScope> getResultScopes()
      Returns an immutable view of the result scopes accumulated during this request, including ResultScope.PREVIOUS_PATH when the token was resolved through a previous path (TokenContextResolution).
      Returns:
      immutable set of accumulated result scopes
    • addPreferenceApplied

      protected void addPreferenceApplied(org.gcube.informationsystem.resourceregistry.api.rest.OperationReturn operationReturn)
      Records the OperationReturn preference honored for the current request's Operation Envelope response. The REST layer emits this as the Preference-Applied response header via PreferenceAppliedResponseFilter. Unlike addResultScope(ResultScope), this is a single value, not an accumulated set: exactly one OperationReturn ever applies per request.
      Parameters:
      operationReturn - the operation-return preference that was honored
    • getPreferenceApplied

      public org.gcube.informationsystem.resourceregistry.api.rest.OperationReturn getPreferenceApplied()
      Returns the operation-envelope return preference honored during this request, or null if none was recorded.
      Returns:
      the honored operation-return preference, or null
    • getResolvedContextPath

      public String getResolvedContextPath()
      Returns the current path the caller's token resolved to during this request when the token carried a previous path, or null otherwise (TokenContextResolution).
      Returns:
      the resolved current Context path, or null
    • addLink

      protected void addLink(String rel, String targetUri)
      Records an RFC 8288 Link header relation to be emitted on the response, per appendix/08-hateoas-navigation.md. The REST layer never builds these headers itself: the response is finalized by LinkResponseFilter, mirroring addResultScope(ResultScope)/addQueryParameterWarning(QueryParameterWarning).
      Parameters:
      rel - the link relation type (e.g. "parent", "collection", "up")
      targetUri - the absolute target URI of the related resource
    • addPaginationLinks

      protected void addPaginationLinks(PageResult page)
      Emits the standard RFC 8288 pagination Link relations for a paginated response, pointing at the current request path with limit/offset substituted.

      Emitted relations: first (always), prev (when offset > 0), next (when page.hasNext()).

      Parameters:
      page - the paginated page result whose limit/offset/hasNext drive link computation
    • buildUri

      protected String buildUri(String... pathSegments)
      Builds an absolute target URI by joining the current request's base URI with the given path segments, e.g. buildUri("contexts", parentUuid) yields https://host/rest-path/contexts/<uuid>. The target stays on the surface the request entered through: for a request under /access it is https://host/rest-path/access/contexts/<uuid>.
      Parameters:
      pathSegments - the path segments to append to the base URI, in order
      Returns:
      the absolute URI string, or null if no UriInfo is available
    • getLinks

      public List<LinkRelation> getLinks()
      Returns an immutable view of the Link relations accumulated during this request.
      Returns:
      immutable list of accumulated Link relations
    • setContentLocation

      protected void setContentLocation(String targetUri)
      Records the canonical URI of the single-instance representation this request is about to return, for ContentLocationResponseFilter to emit as the Content-Location response header (RFC 9110 Section 8.7), per 07-api-foundations-and-roles.md.

      Only single-instance reads call this (Context/Type/Instance/Query Template read()); a List/Query response is a collection, not "the" representation of one URI, so it must never call this. Most callers simply pass their own request path back (the common case: the addressed URI already is the canonical one) - the one exception is ContextPolicyEnforcementPoint.readCurrent(), which delegates to read(UUID) and therefore reports the resolved Context's own UUID-based URI, not the @current alias the client actually requested.

      Parameters:
      targetUri - the absolute canonical URI of the returned representation
    • getContentLocation

      public String getContentLocation()
      Returns the canonical URI recorded for this request's single-instance read, or null if none was recorded (e.g. a List/Query response, or a write handled by the request-path-based fallback in ContentLocationResponseFilter).
      Returns:
      the recorded canonical URI, or null
    • isPrivilegedUser

      protected boolean isPrivilegedUser()
      Returns true if the current caller holds at least one globally-privileged role (IS-Manager or Infrastructure-Manager).
      Returns:
      true if the caller is globally privileged, false otherwise
    • isUniversalUser

      protected boolean isUniversalUser()
      Returns true if the current caller holds at least one universal role (UNIVERSAL_ROLES: IS-Manager, Infrastructure-Manager, or IS-Admin). These roles see metadata identities in full; every other role sees them redacted.
      Returns:
      true if the caller holds a universal role, false otherwise
    • isAdministrativeUser

      protected boolean isAdministrativeUser()
      Returns true if the current caller holds at least one administrative role (ALL_ADMIN_ROLES: IS-Manager, Infrastructure-Manager, IS-Admin, or Context-Manager).

      Broader than isPrivilegedUser() (which only covers the two global roles). These roles already bypass the write-side operational lock on non-ACTIVE descendant Contexts (per 11-api-query-parameters.md's "Admin Overrides" row), so they must also see the unfiltered read view - a role that can write into a subtree it cannot read would be incoherent.

      Returns:
      true if the caller is administrative, false otherwise
    • isUserAllowed

      protected boolean isUserAllowed(Set<String> allowedRoles)
      Helper method to check if the current user holds at least one of the allowed roles.
      Parameters:
      allowedRoles - the set of allowed roles to check
      Returns:
      true if the user has at least one of the roles, false otherwise
    • requireLiveTokenContext

      protected void requireLiveTokenContext()
      Requires the caller's token to resolve to a live Context, for the operations that act in the token Context (reference 08, Token path resolution): a token path that matches only a Context in the cemetery, or no Context at all, gives the caller no authority over any Context, and the operation is refused with 403 Forbidden, whatever the caller's role and whether the operation reads or writes.
      Throws:
      jakarta.ws.rs.ForbiddenException - if the token path resolves to no live Context
    • resolveTokenContextUuid

      protected UUID resolveTokenContextUuid()
      Resolves the Context UUID bound to the caller's authorization token.
      Returns:
      the token's Context UUID, or null if it cannot be resolved
    • reportStateFilteredInstances

      protected void reportStateFilteredInstances(boolean filterState) throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException
      Reports ResultScope.STATE_FILTERED for a hierarchical read, list, query or Query Template execution whose instance selection was state-filtered, when the requested subtree contains at least one descendant Context that is not effectively ACTIVE, whether or not that Context holds an instance the request would select.

      The token deliberately depends only on the states of the Contexts, which the caller can read. A token emitted only when an instance was actually left out would reveal whether a hidden Context holds an instance matching the query, and a caller could probe that predicate by predicate. The memberships omitted from the contexts maps are a different matter and are reported exactly, by the membership view itself.

      Parameters:
      filterState - whether the read was evaluated with the state filter
      Throws:
      org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException - if the caller's Context cannot be resolved
    • enforceTargetContextWithinTokenSubtree

      protected void enforceTargetContextWithinTokenSubtree(UUID targetContextUuid, String operationName)
      Enforces that the given target Context is either the caller's token Context itself or one of its descendants (the token Context's subtree is self-inclusive).

      This check is a fail-closed Level 2 (Token Scope Binding) safeguard for endpoints whose target is a Context UUID that must be validated independently of any instance UUID also being enforced by enforcePolicy(EndpointPolicySpec, UUID, UUID) (e.g. Add to Context, whose targetUuid for role/query-parameter enforcement is the instance being shared, not the destination Context).

      Parameters:
      targetContextUuid - the Context UUID to validate against the token's subtree
      operationName - the operation name to include in the rejection message
      Throws:
      jakarta.ws.rs.ForbiddenException - if the token Context cannot be resolved, or if targetContextUuid lies outside the token Context's subtree
    • enforceAllowedRoles

      protected void enforceAllowedRoles(PolicyEnforcementPoint.EndpointPolicySpec policy)
      Enforces the Level 1 endpoint access rule: a caller holding none of the policy's roles (including a caller with no Resource Registry role at all) is rejected before any parsing, lookup, or token Context resolution.
      Parameters:
      policy - the policy specification whose allowed roles are checked
      Throws:
      jakarta.ws.rs.ForbiddenException - if the caller holds none of the allowed roles
    • enforcePolicy

      protected void enforcePolicy(PolicyEnforcementPoint.EndpointPolicySpec policy, UUID targetUuid, UUID parentUuid)
      Enforces the endpoint-level and context-level authorization rules specified by the given policy specification, and automatically validates query parameters.
      Parameters:
      policy - the policy specification to enforce
      targetUuid - the UUID of the target resource, or null if none
      parentUuid - the UUID of the parent resource (for PARENT scope checks), or null if none
      Throws:
      jakarta.ws.rs.ForbiddenException - if the caller lacks required roles or scope clearance
      jakarta.ws.rs.NotAuthorizedException - if the caller lacks parent context authorization
    • enforcePrivilegedQueryParameters

      protected void enforcePrivilegedQueryParameters(PolicyEnforcementPoint.EndpointPolicySpec policy)
      Rejects with 403 Forbidden every privilege-expanding value declared by the policy's PolicyEnforcementPoint.QueryParamSpecs when the caller holds none of the entitled roles.

      A privilege-expanding value is never ignored or narrowed for lack of privileges; an entitled caller sending it where it does not apply receives the ignore warning from the endpoint instead.

      Parameters:
      policy - the endpoint policy declaring the accepted query parameters
      Throws:
      jakarta.ws.rs.ForbiddenException - if a privilege-expanding value is sent by a role not entitled to it
    • validateQueryParameters

      protected void validateQueryParameters(Set<String> acceptedParams)
      Validates the query parameters of the current request against the given set of accepted parameter names and accumulates an IGNORED warning for any parameter that is not in acceptedParams.

      All unrecognised parameters are grouped into a single warning entry so that the caller receives one X-Warning header per validation call rather than one per stray parameter.

      This method is a no-op when getUriInfo() is null (e.g. in unit tests that invoke PEP methods directly without a JAX-RS context).

      Parameters:
      acceptedParams - the set of parameter names that are valid for the calling endpoint; all other parameters will be reported as ignored
    • invalidQueryParameterValue

      protected static jakarta.ws.rs.BadRequestException invalidQueryParameterValue(String paramName, String raw, String expectation)
      Builds the 400 Bad Request raised for a malformed or unknown query parameter value: such a value is never replaced by a default.
      Parameters:
      paramName - the query parameter name
      raw - the rejected raw value
      expectation - the accepted values or domain, for the error message
      Returns:
      the exception to throw
    • getRawQueryParameter

      protected String getRawQueryParameter(String paramName)
      Returns the first raw value of the given query parameter, or null when the parameter is absent or no UriInfo is available.
      Parameters:
      paramName - the query parameter name
      Returns:
      the raw value, or null
    • resolveEnum

      protected <E extends Enum<E>> E resolveEnum(String paramName, E[] values, E defaultValue)
      Resolves an enumerated query parameter whose wire values are the exact toString() of the enum constants (lowercase): any other value, including a different case, is unknown.
      Type Parameters:
      E - the enum type
      Parameters:
      paramName - the query parameter name
      values - the accepted enum constants
      defaultValue - the value to return when the parameter is absent
      Returns:
      the resolved constant
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not one of the accepted wire values
    • resolveBoolean

      protected boolean resolveBoolean(String paramName, boolean defaultValue)
      Low-level helper: resolves a boolean query parameter with strict validation.

      Only "true" and "false" (case-insensitive) are accepted as valid.

      Prefer the parameter-specific methods (resolvePolymorphic(), resolveIncludeMeta(), …) over calling this directly.

      Parameters:
      paramName - the query parameter name
      defaultValue - the value to return when the parameter is absent
      Returns:
      the resolved boolean value
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is neither true nor false
    • resolveLimit

      protected int resolveLimit()
      Resolves the limit pagination parameter from the current request.
      Returns:
      the resolved limit, always in [1..LIMIT_MAX]
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an integer, is 0, or is below -1
    • resolveOffset

      protected int resolveOffset()
      Resolves the offset pagination parameter from the current request.

      Absent → returns OFFSET_DEFAULT (0); a non-negative integer is returned as-is.

      Returns:
      the resolved offset, always >= 0
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an integer or is negative
    • resolvePolymorphic

      protected boolean resolvePolymorphic()
      Resolves the polymorphic query parameter from the current request.

      Default: true.

      Returns:
      the resolved value
    • resolveDepth

      protected int resolveDepth()
      Resolves the depth query parameter from the current request.

      Absent → returns DEPTH_DEFAULT; an integer >= -1 is returned as-is.

      Returns:
      the resolved depth, always >= -1
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an integer or is below -1
    • resolveDepth

      protected int resolveDepth(int defaultValue)
      Resolves the depth query parameter from the current request, falling back to an explicit caller-supplied default instead of the global DEPTH_DEFAULT.

      Used by endpoints whose default differs from DEPTH_DEFAULT (e.g. QUERY /types, which defaults to -1 for polymorphic-equivalent matching, unlike the 0 default of the Read endpoints).

      Parameters:
      defaultValue - the depth to return when the parameter is absent
      Returns:
      the resolved depth, always >= -1
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an integer or is below -1
    • resolveHierarchical

      protected boolean resolveHierarchical()
      Resolves the hierarchical query parameter from the current request.

      Default: false.

      Returns:
      the resolved value
    • resolvePropagationMode

      protected org.gcube.informationsystem.resourceregistry.api.rest.PropagationMode resolvePropagationMode()
      Resolves the propagationMode query parameter from the current request.

      Accepted values: the exact lowercase wire values of the PropagationMode enum constants (shallow, deep, surgical).

      Note: authorization is NOT performed here: a policy that restricts a value (e.g. surgical on Add to Context) declares it as privilege-expanding in its PolicyEnforcementPoint.QueryParamSpec, which enforcePolicy(org.gcube.informationsystem.resourceregistry.pep.PolicyEnforcementPoint.EndpointPolicySpec, java.util.UUID, java.util.UUID) enforces.

      Returns:
      the resolved PropagationMode, never null
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an accepted wire value
    • resolveDryRun

      protected boolean resolveDryRun()
      Resolves the dryRun query parameter from the current request.

      Default: false.

      Returns:
      the resolved value
    • resolveIncludeMeta

      protected boolean resolveIncludeMeta()
      Resolves the includeMeta query parameter from the current request.

      Default: false.

      Returns:
      the resolved value
    • resolveAllMeta

      protected boolean resolveAllMeta()
      Resolves the allMeta query parameter from the current request.

      Default: false. Requires includeMeta=true to have any effect; enforcement is the caller's responsibility.

      Returns:
      the resolved value
    • resolveMetadataPolicy

      protected org.gcube.informationsystem.resourceregistry.api.rest.MetadataPolicy resolveMetadataPolicy()
      Resolves metadata inclusion policy for the current request.

      Canonical parameter is metadataPolicy with accepted values none, root, all. Legacy parameters (includeMeta, allMeta) are accepted only for server-side operational compatibility and mapped to the canonical policy when metadataPolicy is not provided.

      • Canonical absent + includeMeta=false/absent + allMeta=false/absent -> none
      • Canonical absent + includeMeta=true + allMeta=false/absent -> root
      • Canonical absent + includeMeta=true + allMeta=true -> all
      • Canonical absent + includeMeta=false/absent + allMeta=true -> none (with warning)

      When canonical metadataPolicy is present, it has precedence; legacy parameters are ignored (with warning).

      Returns:
      resolved MetadataPolicy, never null
      Throws:
      jakarta.ws.rs.BadRequestException - if a supplied value is malformed or unknown
    • resolveContextsPolicy

      protected org.gcube.informationsystem.resourceregistry.api.rest.ContextsPolicy resolveContextsPolicy()
      Resolves the contextsPolicy query parameter from the current request.

      Accepted values: the exact lowercase wire values none, root, all. Default: ContextsPolicy.DEFAULT.

      Returns:
      the resolved ContextsPolicy, never null
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an accepted wire value
    • resolveMembershipScope

      protected org.gcube.informationsystem.resourceregistry.api.rest.MembershipScope resolveMembershipScope()
      Resolves the membershipScope query parameter from the current request.

      Accepted values: the exact lowercase wire values subtree, global. Default: MembershipScope.DEFAULT. The restriction of global to the UNIVERSAL_ROLES is enforced by enforcePolicy(org.gcube.informationsystem.resourceregistry.pep.PolicyEnforcementPoint.EndpointPolicySpec, java.util.UUID, java.util.UUID) through MEMBERSHIP_SCOPE_PARAM_SPEC, which every policy accepting the parameter declares.

      Returns:
      the resolved MembershipScope, never null
      Throws:
      jakarta.ws.rs.BadRequestException - if the value is not an accepted wire value
    • resolveMembershipView

      protected MembershipView resolveMembershipView() throws org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException
      Builds the view that selects the memberships listed by every contexts map of the response: the boundary requested with membershipScope, without the Contexts that are not effectively ACTIVE for a caller lacking the administrative state override. A membership omitted for its state is reported as ResultScope.STATE_FILTERED when it happens, so the token is emitted only if something was actually removed.
      Returns:
      the membership view of the current request
      Throws:
      jakarta.ws.rs.BadRequestException - if membershipScope is not an accepted wire value
      org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException - if the token Context cannot be resolved
    • warnEnrichmentParametersIgnoredByEmitProjection

      protected void warnEnrichmentParametersIgnoredByEmitProjection()
      Reports that the representation-enrichment parameters were requested but had no effect because the query's _emit projection replaced the full instance representation with a flat, projection-only response (Canonical _emit Precedence Rules, appendix/07-json-query-syntax-reference.md).

      Shared by every query engine that executes an _emit-capable JSON query (direct instance queries and Query Template execution), since the precedence rule is documented as applying uniformly across all of them.

    • warnEnrichmentParametersIgnored

      protected void warnEnrichmentParametersIgnored(String reason)
      Reports as ignored the representation-enrichment parameters the request carries when another directive leaves no representation to enrich: metadataPolicy, a non-default contextsPolicy, and a non-default membershipScope. The values are validated first, and the authorization of membershipScope=global has already been enforced by enforcePolicy(org.gcube.informationsystem.resourceregistry.pep.PolicyEnforcementPoint.EndpointPolicySpec, java.util.UUID, java.util.UUID), so only an entitled caller reaches this warning.
      Parameters:
      reason - the reason reported in the warning
      Throws:
      jakarta.ws.rs.BadRequestException - if a supplied value is malformed or unknown
    • resolveRawResult

      protected boolean resolveRawResult()
      Resolves the rawResult query parameter from the current request (raw-query endpoint only).

      Default: false.

      Returns:
      the resolved value
    • resolveBypassHierarchyCheck

      protected boolean resolveBypassHierarchyCheck()
      Resolves the bypassHierarchyCheck query parameter from the current request (Add to Context only).

      Default: false. The restriction of true to the UNIVERSAL_ROLES is enforced by enforcePolicy(org.gcube.informationsystem.resourceregistry.pep.PolicyEnforcementPoint.EndpointPolicySpec, java.util.UUID, java.util.UUID) through the policy's PolicyEnforcementPoint.QueryParamSpec.

      Returns:
      the resolved value