magpie.services

Attributes

PERMISSION_REASON_ADMIN

PERMISSION_REASON_DEFAULT

LOGGER

SERVICE_TYPES

SERVICE_TYPE_DICT

Classes

Access

Applicable access modifier of Permission values.

Permission

Applicable Permission values (names) under certain Service and Resource.

PermissionSet

Explicit definition of a Permission with applicable Access and Scope to resolve it.

PermissionType

Applicable types of Permission according to context.

Scope

Applicable access modifier of Permission values.

classproperty

Mimics property decorator, but applied onto classmethod in backward compatible way.

ServiceMeta

ServiceInterface

Initialize the service.

ServiceOWS

Generic request-to-permission interpretation method of various OGC Web Service (OWS) implementations.

ServiceWPS

Service that represents a Web Processing Service endpoint.

ServiceBaseWMS

Service that represents basic capabilities of a Web Map Service endpoint.

ServiceNCWMS2

Service that represents a Web Map Service endpoint with functionalities specific to ncWMS2 .

ServiceGeoserverBase

Provides basic configuration parameters and functionalities shared by Geoserver implementations.

ServiceGeoserverWMS

Service that represents a Web Map Service endpoint with functionalities specific to Geoserver.

ServiceAccess

Initialize the service.

ServiceAPI

Service that provides resources per individual request path segments.

ServiceWFS

Service that represents a Web Feature Service endpoint.

ServiceGeoserverWFS

Service that represents a Web Feature Service endpoint with functionalities specific to Geoserver.

ServiceTHREDDS

Service that represents a THREDDS Data Server endpoint.

ServiceGeoserverWPS

Service that represents a Web Processing Service under a Geoserver instance.

ServiceGeoserverAPI

Service that represents a generic REST API under a Geoserver instance.

ServiceGeoserver

Service that encapsulates the multiple OWS endpoints from Geoserver services.

Functions

get_constant(→ magpie.typedefs.SettingValue)

Search in order for matched value of constant_name:

get_connected_session(→ sqlalchemy.orm.session.Session)

Retrieve the session attached to the request or recreated it to ensure it is open and within scoped transaction.

ows_parser_factory(→ OWSParser)

Retrieve the appropriate OWSParser parser using the Content-Type header.

fully_qualified_name(→ str)

Obtains the '<module>.<name>' full path definition of the object to allow finding and importing it.

get_logger(→ logging.Logger)

Immediately sets the logger level to avoid duplicate log outputs from the root logger and this logger when

get_request_user(→ Optional[magpie.models.User])

Obtains the user that corresponds to the authentication details found in the request.

service_factory(→ ServiceInterface)

Retrieve the specific service class from the provided database service entry.

get_resource_child_allowed(→ bool)

Verifies if the specified resource allows nesting children resources under it considering its specific type.

invalidate_service(→ None)

Invalidates any caching reference to the specified service name.

Module Contents

magpie.services.get_constant(constant_name: magpie.typedefs.Str, settings_container: magpie.typedefs.AnySettingsContainer | None = None, settings_name: magpie.typedefs.Str | None = None, default_value: magpie.typedefs.SettingValue | None = None, raise_not_set: bool = True, raise_missing: bool = True, print_missing: bool = False, empty_missing: bool = False) magpie.typedefs.SettingValue[source]
Search in order for matched value of constant_name:
  1. search in MAGPIE_CONSTANTS

  2. search in settings if specified

  3. search alternative setting names (see below)

  4. search in magpie.constants definitions

  5. search in environment variables

Parameter constant_name is expected to have the format MAGPIE_[VARIABLE_NAME] although any value can be passed to retrieve generic settings from all above-mentioned search locations.

If settings_name is provided as alternative name, it is used as is to search for results if constant_name was not found. Otherwise, magpie.[variable_name] is used for additional search when the format MAGPIE_[VARIABLE_NAME] was used for constant_name (i.e.: MAGPIE_ADMIN_USER will also search for magpie.admin_user and so on for corresponding constants).

Parameters:
  • constant_name – key to search for a value

  • settings_container – WSGI application settings container (if not provided, uses found one in current thread)

  • settings_name – alternative name for settings if specified

  • default_value – default value to be returned if not found anywhere, and exception raises are disabled.

  • raise_not_set – raise an exception if the found key is None, search until last case if others are None

  • raise_missing – raise exception if key is not found anywhere

  • print_missing – print message if key is not found anywhere, return None

  • empty_missing – consider an empty value for an existing key as if it was missing (i.e.: as if not set).

Returns:

found value or default_value

Raises:
  • ValueError – if resulting value is invalid based on options (by default raise missing/empty/None value)

  • LookupError – if no appropriate value could be found from all search locations (according to options)

magpie.services.get_connected_session(request: pyramid.request.Request) sqlalchemy.orm.session.Session[source]

Retrieve the session attached to the request or recreated it to ensure it is open and within scoped transaction.

magpie.services.ows_parser_factory(request: pyramid.request.Request) OWSParser[source]

Retrieve the appropriate OWSParser parser using the Content-Type header.

If the Content-Type header is missing or text/plain, and the request has a body, try to parse the body as JSON and set the content-type to application/json if successful.

Handle XML-like Content-Type headers such as application/x-www-form-urlencoded whenever applicable.

Otherwise, use the basic OWSGetParser or OWSPostParser according to the presence of a body. These provide minimal parsing to handle most typical OGC Web Services (OWS) request parameters.

magpie.services.PERMISSION_REASON_ADMIN = 'administrator'[source]
magpie.services.PERMISSION_REASON_DEFAULT = 'no-permission'[source]
class magpie.services.Access[source]

Bases: magpie.utils.ExtendedEnum

Applicable access modifier of Permission values.

ALLOW = 'allow'
DENY = 'deny'
class magpie.services.Permission[source]

Bases: magpie.utils.ExtendedEnum

Applicable Permission values (names) under certain Service and Resource.

READ = 'read'
WRITE = 'write'
ACCESS = 'access'
BROWSE = 'browse'
GET_CAPABILITIES = 'getcapabilities'
GET_MAP = 'getmap'
GET_FEATURE_INFO = 'getfeatureinfo'
GET_LEGEND_GRAPHIC = 'getlegendgraphic'
GET_METADATA = 'getmetadata'
GET_PROPERTY_VALUE = 'getpropertyvalue'
GET_FEATURE = 'getfeature'
GET_FEATURE_WITH_LOCK = 'getfeaturewithlock'
GET_GML_OBJECT = 'getgmlobject'
DESCRIBE_FEATURE_TYPE = 'describefeaturetype'
DESCRIBE_LAYER = 'describelayer'
DESCRIBE_PROCESS = 'describeprocess'
EXECUTE = 'execute'
LOCK_FEATURE = 'lockfeature'
TRANSACTION = 'transaction'
CREATE_STORED_QUERY = 'createstoredquery'
DROP_STORED_QUERY = 'dropstoredquery'
LIST_STORED_QUERIES = 'liststoredqueries'
DESCRIBE_STORED_QUERIES = 'describestoredqueries'
class magpie.services.PermissionSet(permission: magpie.typedefs.AnyPermissionType, access: Access | magpie.typedefs.Str | None = None, scope: Scope | magpie.typedefs.Str | None = None, typ: PermissionType | None = None, reason: magpie.typedefs.Str | None = None)[source]

Bases: object

Explicit definition of a Permission with applicable Access and Scope to resolve it.

The Permission is the name of the applicable permission on the magpie.models.Resource. The Scope defines how the Permission should impact the resolution of the perceived Effective Permissions over a magpie.models.Resource tree hierarchy. The Access defines how the Permission access should be interpreted (granted or denied).

Optionally, a PermissionType can be provided to specifically indicate which kind of permission this set represents. This type is only for informative purposes, and is not saved to database nor displayed by the explicit string representation. It is returned within JSON representation and can be employed by Effective Permissions resolution to be more verbose about returned results.

On missing Access or Scope specifications, they default to Access.ALLOW and Scope.RECURSIVE to handle backward compatible naming convention of plain permission_name.

Initializes the permission definition, possibly using required conversion from other implementations.

Parameters:
  • permission – Name of the permission, or any other implementation from which the name can be inferred.

  • access – Effective behaviour of the permissions. Generally, grant or deny the specified permission.

  • scope – Scope for which the permission affects hierarchical resources. Important for effective resolution.

  • typ – Type of permission being represented. Informative only, does not impact behavior if omitted.

  • reason – Slightly more indicative information on why the current permission-type has this value. Value should be either explicitly provided or will be inferred if converted from input PermissionTuple.

__slots__ = ['_name', '_access', '_scope', '_tuple', '_type', '_reason']
__eq__(other: Any) bool[source]

Return self==value.

__ne__(other: Any) bool[source]

Return self!=value.

__lt__(other: Any) bool[source]

Ascending sort of permission according to their name, access and scope modifiers.

First sort by permission name alphabetically, followed by increasing restrictive access and increasing range of scoped resources.

Using this sorting methodology, similar permissions by name are grouped together first, and permissions of same name with modifiers are then ordered, the first having less priority when selecting a single item to display with conflicting possibilities. Respecting Access.DENY is more important than Access.ALLOW (to protect the Resource), and Scope.MATCH is closer to the actual Resource than Scope.RECURSIVE permission received from a farther parent in the hierarchy.

Sorted explicit string representation becomes:

[name1]-[allow]-[match]
[name1]-[allow]-[recursive]
[name1]-[deny]-[match]
[name1]-[deny]-[recursive]
[name2]-[allow]-[match]
[name2]-[allow]-[recursive]
[name2]-[deny]-[match]
[name2]-[deny]-[recursive]
...
We then obtain two crucial ordering results:
  1. We can easily pick the last sorted item with highest resolution priority to find the final result of corresponding permissions. (note: final result for same user or group, their direct/inherited resolution is not considered here).

  2. Picking the first element with lowest priority also displays the permission that impacts the widest range of resources. For instance in Magpie UI, indicating that a permission as Scope.RECURSIVE is more verbose as it tell other resources under it are also receive the specified Access modifier rather than only the punctual resource.

Warning

Alphabetically sorting permissions by string representation (implicit/explicit) is not equivalent to sorting them according to Permission priority according to how modifiers are resolved. To obtain the prioritized sorting as strings, a list of PermissionSet (with the strings as input) should be used to convert and correctly interpreted the raw strings, and then be converted back after sorting.

# valid priority-sorted strings
[str(perm) for perm in sorted(PermissionSet(p) for p in permission_strings)]

# not equivalent to raw sorting
list(sorted(permission_strings))
__hash__() int[source]

Return hash(self).

__str__() magpie.typedefs.Str[source]

Obtains the compound literal representation of the PermissionSet.

Employed for database storage supporting ziggurat format.

__repr__() magpie.typedefs.Str[source]

Obtains the visual representation of the PermissionSet.

like(other: Any) bool[source]

Evaluates if one permission is similar to another permission definition regardless of modifiers.

This is different than == operator which will evaluate exactly equal permission definitions.

json() magpie.typedefs.PermissionDict[source]

Obtains the JSON representation of this PermissionSet.

webhook_params() magpie.typedefs.JSON[source]

Obtain JSON representation employed for Webhook reference.

ace(user_or_group: magpie.models.User | magpie.models.Group | None) magpie.typedefs.AccessControlEntryType[source]

Converts the PermissionSet into an ACE that pyramid can understand.

property reason: magpie.typedefs.Str | None

Indicative reason of the returned value defined by type() or inferred by the PermissionTuple.

See also

combine()

Returns:

Single string that describes the reason (source) of the permission, or multiple strings if updated by combination of multiple permissions.

classmethod resolve(permission1: magpie.typedefs.ResolvablePermissionType, permission2: magpie.typedefs.ResolvablePermissionType, context: PermissionType = PermissionType.INHERITED, multiple_choice: magpie.typedefs.Str | None = None) magpie.typedefs.ResolvablePermissionType[source]

Resolves provided permissions into a single one considering various modifiers and groups for a resource.

Permissions MUST have the same Permission name. The associated Resource on which the two compared permissions are applied on should also be the same This method SHOULD NOT be used by itself to obtain for Effective Permission since it does not handle multi-level Resource resolution. Resolution is accomplished in this case only for a given level in the tree hierarchy.

The comparison considers both the Access and Scope of every Inherited Permission of the User, as well as its Group memberships sorted by their priority.

See also

Parameters:
  • permission1 – Permission to compare.

  • permission2 – Permission to compare.

  • context – Control the resolution context (local/effective) of the permissions (safeguard against invalid definitions).

  • multiple_choice – Alternate explanation to default PERMISSION_REASON_MULTIPLE applied if multiple Permission refer to distinct Group of equal priority and equivalent access definitions, meaning they are interchangeable without impacting resolution to access the same target Resource.

Returns:

Permission with highest priority to resolve access a resource without considering scope.

property group_priority: magpie.typedefs.GroupPriority | None

Priority accessor in case of group inherited permission resolved by PermissionTuple.

property perm_tuple: ziggurat_foundations.permissions.PermissionTuple | None

Get the original PermissionTuple if available (PermissionSet must have been created by one).

property implicit_permission: magpie.typedefs.Str | None

Obtain the implicit string representation of the PermissionSet as plain Permission name.

This representation is backward compatible with prior versions of Magpie where explicit representation of permission names in the database did not exist.

If the contained modifiers of the PermissionSet (notably the Access.DENY) result in a string representation that is not possible according to non existing permissions for older Magpie instances, the returned value will be None.

See also

property explicit_permission: magpie.typedefs.Str

Obtain the explicit string representation of the PermissionSet.

This format is always guaranteed to be completely defined contrary to implicit_permission().

See also

property name: Permission
permission
property access: Access
property scope: Scope
property type: PermissionType | None
classmethod _convert(permission: magpie.typedefs.AnyPermissionType) PermissionSet | None[source]

Converts any permission representation to the PermissionSet with applicable enum members.

Supports older Permission representation such that implicit conversion of permission name without access and scope values are padded with defaults. Also, pre-defined partial or full definition from literal string representation are parsed to generate the PermissionSet instance.

Parameters:

permission – implicit or explicit permission name string, or any other known permission implementation

Raises:

ValueError – when the permission name cannot be identified or parsed

class magpie.services.PermissionType[source]

Bases: magpie.utils.ExtendedEnum

Applicable types of Permission according to context.

ACCESS = 'access'
ALLOWED = 'allowed'
APPLIED = 'applied'
DIRECT = 'direct'
INHERITED = 'inherited'
EFFECTIVE = 'effective'
OWNED = 'owned'
class magpie.services.Scope[source]

Bases: magpie.utils.ExtendedEnum

Applicable access modifier of Permission values.

MATCH = 'match'
RECURSIVE = 'recursive'
class magpie.services.classproperty[source]

Bases: property

Mimics property decorator, but applied onto classmethod in backward compatible way.

Note

This decorator purposely only supports getter attribute to define unmodifiable class properties.

Initialize self. See help(type(self)) for accurate signature.

__get__(cls, owner)[source]

Return an attribute of instance, which is of type owner.

magpie.services.fully_qualified_name(obj: Any | Type[Any]) str[source]

Obtains the '<module>.<name>' full path definition of the object to allow finding and importing it.

magpie.services.get_logger(name: magpie.typedefs.Str, level: int | None = None, force_stdout: bool = None, message_format: magpie.typedefs.Str | None = None, datetime_format: magpie.typedefs.Str | None = None) logging.Logger[source]

Immediately sets the logger level to avoid duplicate log outputs from the root logger and this logger when level is logging.NOTSET.

magpie.services.get_request_user(request: pyramid.request.Request) magpie.models.User | None[source]

Obtains the user that corresponds to the authentication details found in the request.

Prior to resolving the user matching the authenticated user ID, reattaches the detached session or closed transaction if commit occurred beforehand. This can happen for example when creating a user from a pending-user where the user must be committed to allow webhooks to refer to it immediately, although the request has not completed processing. Operations using the request.user reference following that user creation could have a detached object state from the session. Ensure that any resolved user is also attached to the reestablished database session reference in the request.

After reattaching to the session, following step is the original configuration setup similarly to typical methodology:

config.include("ziggurat_foundations.ext.pyramid.get_user")
Parameters:

request – request to look for authenticated user.

Returns:

authenticated user or none if unauthenticated.

magpie.services.LOGGER[source]
class magpie.services.ServiceMeta[source]

Bases: type

property resource_types: List[Type[magpie.models.Resource]][source]

Allowed resources type classes under the service.

property resource_type_names: List[magpie.typedefs.Str][source]

Allowed resources type names under the service.

property child_resource_allowed: bool[source]

Lists all resources allowed somewhere within its resource hierarchy under the service.

Note

Resources are not necessarily all allowed directly under the service. This depends on whether ServiceInterface.child_structure_allowed is defined or not. If not defined, resources are applicable anywhere. Otherwise, they must respect the explicit structure definitions.

See also

Use ServiceInterface.nested_resource_allowed() to obtain only scoped types allowed under a given resource considering allowed path structures.

class magpie.services.ServiceInterface(service: magpie.models.Service, request: pyramid.request.Request | None)[source]

Bases: object

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

property service_type: magpie.typedefs.Str | None[source]
Abstractmethod:

Service type identifier (required, unique across implementation).

permissions: List[magpie.permissions.Permission] = [][source]

Permission allowed directly on the service as top-level resource.

resource_types_permissions: magpie.typedefs.ResourceTypePermissions[source]

Mapping of resource types to lists of permissions defining allowed children resource permissions under the service.

child_structure_allowed: Dict[Type[magpie.typedefs.ServiceOrResourceType], List[Type[magpie.models.Resource]]][source]

Control mapping of resource types limiting the allowed structure of nested children resources.

When not defined, any nested resource type combination is allowed if they themselves allow children resources. Otherwise, nested child resource under the service can only be created at specific positions within the hierarchy that matches exactly one of the defined control conditions.

For example, the below definition allows only resources typed route directly under the service. The following nested resource under that first-level route can then be either another route followed by a child process or directly a process. Because process type doesn’t allow any children resource (see models.Process.child_resource_allowed), those are the only allowed combinations (cannot further nest resources under the final process resource).

child_structure_allowed = {
    models.Service: [models.Route],
    models.Route: [models.Route, models.Process],
    models.Process: [],
}

See also

_config: magpie.typedefs.ServiceConfiguration | None = None[source]
configurable = False[source]

Indicates if the service supports custom configuration.

__str__()[source]

Return str(self).

abstract permission_requested() magpie.typedefs.PermissionRequested[source]

Defines how to interpret the incoming request into Permission definitions for the given service.

Each service must implement its own definition. The method must specifically define how to convert generic request path, query, etc. elements into permissions that match the service and its children resources.

If None is returned, the ACL will effectively be resolved to denied access. Otherwise, one or more returned Permission will indicate which permissions should be looked for to resolve the ACL of the authenticated user and its groups.

If the request cannot be parsed for any reason to retrieve needed parameters (e.g.: Bad Request), the :exception:`HTTPBadRequest` can be raised to indicate specifically the cause, which will help magpie.adapter.magpieowssecurity.MagpieOWSSecurity create a better response with the relevant error details.

abstract resource_requested() magpie.typedefs.MultiResourceRequested[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

user_requested()[source]

Obtain the User that was identified to obtain protected Resource access.

property __acl__: magpie.typedefs.AccessControlListType[source]

Access Control List (ACL) formed of ACE defining combinations rules to grant or refuse access.

Each ACE is defined as (outcome, user/group, permission) tuples. Called by the configured Pyramid pyramid.authorization.ACLAuthorizationPolicy.

Caching is automatically handled according to configured application settings and whether the specific ACL combination being requested was already processed recently.

_get_acl_cached(service_name: magpie.typedefs.Str, request_method: magpie.typedefs.Str, request_path: magpie.typedefs.Str, user_id: int | None) magpie.typedefs.AccessControlListType[source]

Cache this method with beaker based on the provided caching key parameters.

If the cache is not hit (expired timeout or new key entry), calls ServiceInterface.get_acl() to retrieve effective permissions of the requested resource and specific permission for the applicable service and user executing the request.

Note

Function arguments are required to generate caching keys by which cached elements will be retrieved. Actual arguments are not needed as we employ stored objects in the instance.

Warning

Anything within this method or any underlying calls that can potentially retrieve database contents, whether for direct object or dynamically generated relationships (eg: user.groups) must attempt to reestablish any detached or invalid session/transaction due to the potentially desynchronized references between objects before/after both incoming service and this acl cache regions.

_get_acl(user: magpie.models.User, resources: magpie.typedefs.MultiResourceRequested, permissions: Collection[magpie.permissions.Permission]) magpie.typedefs.AccessControlListType[source]

Resolves resource-tree and user/group inherited permissions into simplified ACL of requested resources.

Contrary to effective_permissions() that can be resolved only for individual Resource, ACL is involved during actual request access, which could refer to multiple Resource references or distinct Permission names if the identified parent Service supports it.

When more than one item is specified for validation (any combination of Resource or Permission), ALL of them must be granted access to resolve as Access.ALLOW. Any denied access blocks the whole set of requested elements.

See also

_get_connected_object(obj: magpie.typedefs.ServiceOrResourceType | magpie.models.User) magpie.typedefs.ServiceOrResourceType | None[source]

Retrieve the object with an active session and attached state by refreshing connection with request session.

This operation is required mostly in cases of mismatching references between cached and active objects obtained according to timing of requests and whether caching took placed between them, and for different caching region levels (service, ACL or both). It also attempts to correct and encountered problems due to concurrent requests.

_get_request_path_parts() List[magpie.typedefs.Str] | None[source]

Obtain the request path parts stripped of anything prior to the referenced service name.

get_config() magpie.typedefs.ServiceConfiguration[source]

Obtains the custom configuration of the registered service.

classmethod get_resource_permissions(resource_type_name: magpie.typedefs.Str) List[magpie.permissions.Permission][source]

Obtains the allowed permissions of the service’s child resource fetched by resource type name.

classmethod validate_nested_resource_type(parent_resource: magpie.typedefs.ServiceOrResourceType, child_resource_type: magpie.typedefs.Str) bool[source]

Validate whether a new child resource type is allowed under the parent resource under the service.

Parameters:
  • parent_resource – Parent under which the new resource must be validated. This can be the service itself.

  • child_resource_type – Type to validate at the position defined under the parent resource.

Returns:

status indicating if insertion is allowed for this type and at this parent position.

classmethod nested_resource_allowed(parent_resource: magpie.typedefs.ServiceOrResourceType) List[Type[magpie.models.Resource]][source]

Obtain the nested resource types allowed as children resource within structure definitions.

allowed_permissions(resource: magpie.typedefs.ServiceOrResourceType) List[magpie.permissions.Permission][source]

Obtains the allowed permissions for or under the service according to provided service or resource.

effective_permissions(user: magpie.models.User, resource: magpie.typedefs.ServiceOrResourceType, permissions: Collection[magpie.permissions.Permission] | None = None, allow_match: bool = True) List[magpie.permissions.PermissionSet][source]

Obtains the Effective Resolution of permissions the user has over the specified resource.

Recursively rewinds the resource tree from the specified resource up to the top-most parent service the resource resides under (or directly if the resource is the service) and retrieve permissions along the way that should be applied to children when using scoped-resource inheritance. Rewinding of the tree can terminate earlier when permissions can be immediately resolved such as when more restrictive conditions enforce denied access.

Both user and group permission inheritance is resolved simultaneously to tree hierarchy with corresponding allow and deny conditions. User Direct Permissions have priority over all its groups Inherited Permissions, and denied permissions have priority over allowed access ones.

All applicable permissions on the resource (as defined by allowed_permissions()) will have their resolution (Allow/Deny) provided as output, unless a specific subset of permissions is requested using permissions. Other permissions are ignored in this case to only resolve requested ones. For example, this parameter can be used to request only ACL resolution from specific permissions applicable for a given request, as obtained by permission_requested().

Permissions scoped as match can be ignored using allow_match, such as when the targeted resource does not exist.

Parameters:
Returns:

Resolved set Effective Permission for specified parameter combinations.

class magpie.services.ServiceOWS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceInterface

Generic request-to-permission interpretation method of various OGC Web Service (OWS) implementations.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

params_expected: List[magpie.typedefs.Str] = [][source]

Request query parameters that are expected and should be preprocessed by parsing the submitted request.

_get_request() pyramid.request.Request[source]
_set_request(request: pyramid.request.Request) None[source]
request[source]
abstract resource_requested() magpie.typedefs.MultiResourceRequested[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

permission_requested() magpie.typedefs.PermissionRequested[source]

Defines how to interpret the incoming request into Permission definitions for the given service.

Each service must implement its own definition. The method must specifically define how to convert generic request path, query, etc. elements into permissions that match the service and its children resources.

If None is returned, the ACL will effectively be resolved to denied access. Otherwise, one or more returned Permission will indicate which permissions should be looked for to resolve the ACL of the authenticated user and its groups.

If the request cannot be parsed for any reason to retrieve needed parameters (e.g.: Bad Request), the :exception:`HTTPBadRequest` can be raised to indicate specifically the cause, which will help magpie.adapter.magpieowssecurity.MagpieOWSSecurity create a better response with the relevant error details.

class magpie.services.ServiceWPS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceOWS

Service that represents a Web Processing Service endpoint.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_type = 'wps'[source]
permissions[source]
params_expected = ['service', 'request', 'version', 'identifier'][source]
resource_types_permissions[source]
resource_requested() Tuple[magpie.typedefs.ServiceOrResourceType, bool] | None[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

class magpie.services.ServiceBaseWMS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceOWS

Service that represents basic capabilities of a Web Map Service endpoint.

See also

https://www.ogc.org/standards/wms (OpenGIS WMS 1.3.0 implementation)

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

abstract resource_requested()[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

permissions[source]
params_expected = ['service', 'request', 'version', 'layers', 'layername', 'dataset'][source]
class magpie.services.ServiceNCWMS2(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceBaseWMS

Service that represents a Web Map Service endpoint with functionalities specific to ncWMS2 .

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_type = 'ncwms'[source]
permissions[source]
resource_types_permissions[source]
resource_requested() Tuple[magpie.typedefs.ServiceOrResourceType, bool] | None[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

class magpie.services.ServiceGeoserverBase(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceOWS

Provides basic configuration parameters and functionalities shared by Geoserver implementations.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

property service_base: magpie.typedefs.Str[source]
Abstractmethod:

Name of the base OWS functionality serviced by Geoserver.

property resource_scoped: bool[source]
Classmethod:

Abstractmethod:

Indicates if the Service is allowed to employ scoped models.Workspace naming.

When allowed, the models.Workspace can be inferred from the request parameter defined by resource_param to retrieve scoped name as <WORKSPACE>:<RESOURCE>. When not allowed, the resource name is left untouched and Magpie will not attempt to infer any models.Workspace from it. In that case, models.Workspace can only be specified in the request path for isolated Resource references.

Note

When this parameter is False for a given Service implementation, children Resources can still be named in a similar <namespace>:<element> fashion. The only distinction is that the full Resource should include this complete definition instead of nesting <namespace> and <element> into two distinct Resources.

property resource_multi: bool[source]
Abstractmethod:

Indicates if the Service supports multiple simultaneous Resource references.

When supported, the value retrieved from resource_param can be comma-separated to represent multiple Resource of the same nature, which can all be retrieved with the same request. Otherwise, single value only is considered by default.

Note

Permission modifier Access.ALLOW will have to be resolved for all those Resource references for the request to be granted access.

property resource_param: magpie.typedefs.Str | List[magpie.typedefs.Str][source]
Abstractmethod:

Name of the request query parameter(s) to access requested leaf children resource.

If a single string is defined, the parameter must be equal to this value (case insensitive). When using a list, any specified name combination will be resolved as the same parameter.

Note

The resulting parameter(s) are automatically added to params_expected() to ensure they are always retrieved in the parser from the request query parameters.

See also

resource_param_requested() to obtain the resolved parameter considering any applicable combination.

property resource_types_permissions: magpie.typedefs.ResourceTypePermissions[source]
Abstractmethod:

Explicit permissions provided for resources for a given OWS implementation.

property params_expected: List[magpie.typedefs.Str][source]

Specify typical Geoserver request query parameters expected for any sub-service implementation.

The resource_param is also added to ensure it is always parsed based on the derived implementation.

resource_param_requested() List[magpie.typedefs.Str][source]

Obtain the resolved value(s) of the resource query parameter from OWS parser applied onto the request.

resource_requested() magpie.typedefs.MultiResourceRequested[source]

Parse the requested resource down to the applicable models.Workspace.

Note

Further child resource processing must be accomplished by the derived implementation as needed.

class magpie.services.ServiceGeoserverWMS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceGeoserverBase, ServiceBaseWMS

Service that represents a Web Map Service endpoint with functionalities specific to Geoserver.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_base = 'wms'[source]
service_type = 'geoserverwms'[source]
resource_scoped = True[source]
resource_multi = True[source]
resource_param = 'layers'[source]
permissions[source]
child_structure_allowed[source]
resource_types_permissions[source]
class magpie.services.ServiceAccess(service: magpie.models.Service, request: pyramid.request.Request | None)[source]

Bases: ServiceInterface

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_type = 'access'[source]
permissions[source]
resource_types_permissions[source]
resource_requested() magpie.typedefs.TargetResourceRequested[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

permission_requested() magpie.typedefs.PermissionRequested[source]

Defines how to interpret the incoming request into Permission definitions for the given service.

Each service must implement its own definition. The method must specifically define how to convert generic request path, query, etc. elements into permissions that match the service and its children resources.

If None is returned, the ACL will effectively be resolved to denied access. Otherwise, one or more returned Permission will indicate which permissions should be looked for to resolve the ACL of the authenticated user and its groups.

If the request cannot be parsed for any reason to retrieve needed parameters (e.g.: Bad Request), the :exception:`HTTPBadRequest` can be raised to indicate specifically the cause, which will help magpie.adapter.magpieowssecurity.MagpieOWSSecurity create a better response with the relevant error details.

class magpie.services.ServiceAPI(service: magpie.models.Service, request: pyramid.request.Request | None)[source]

Bases: ServiceInterface

Service that provides resources per individual request path segments.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_type = 'api'[source]
permissions[source]
resource_types_permissions[source]
child_structure_allowed[source]
resource_requested() magpie.typedefs.TargetResourceRequested[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

permission_requested() magpie.typedefs.PermissionRequested[source]

Defines how to interpret the incoming request into Permission definitions for the given service.

Each service must implement its own definition. The method must specifically define how to convert generic request path, query, etc. elements into permissions that match the service and its children resources.

If None is returned, the ACL will effectively be resolved to denied access. Otherwise, one or more returned Permission will indicate which permissions should be looked for to resolve the ACL of the authenticated user and its groups.

If the request cannot be parsed for any reason to retrieve needed parameters (e.g.: Bad Request), the :exception:`HTTPBadRequest` can be raised to indicate specifically the cause, which will help magpie.adapter.magpieowssecurity.MagpieOWSSecurity create a better response with the relevant error details.

class magpie.services.ServiceWFS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceOWS

Service that represents a Web Feature Service endpoint.

See also

https://www.ogc.org/standards/wfs (OpenGIS WFS 2.0.0 implementation)

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_type = 'wfs'[source]
permissions[source]
params_expected = ['service', 'request', 'version', 'typenames'][source]
resource_types_permissions[source]
resource_requested() magpie.typedefs.TargetResourceRequested[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

class magpie.services.ServiceGeoserverWFS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceGeoserverBase, ServiceWFS

Service that represents a Web Feature Service endpoint with functionalities specific to Geoserver.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_base = 'wfs'[source]
service_type = 'geoserverwfs'[source]
resource_scoped = True[source]
resource_multi = True[source]
resource_param = ['typenames', 'typename'][source]
permissions[source]
resource_types_permissions[source]
child_structure_allowed[source]
class magpie.services.ServiceTHREDDS(service: magpie.models.Service, request: pyramid.request.Request | None)[source]

Bases: ServiceInterface

Service that represents a THREDDS Data Server endpoint.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_type = 'thredds'[source]
permissions[source]
resource_types_permissions[source]
child_structure_allowed[source]
configurable = True[source]
get_config() magpie.typedefs.ServiceConfiguration[source]

Obtains the custom configuration of the registered service.

get_path_parts() List[magpie.typedefs.Str] | None[source]
static is_match(value: magpie.typedefs.Str, pattern: magpie.typedefs.Str) magpie.typedefs.Str | None[source]
resource_requested() magpie.typedefs.TargetResourceRequested[source]

Defines how to interpret the incoming request into the targeted model.Resource for the given service.

Each service must implement its own definition.

The expected return value must be either of the following:

- List<(target-resource, target?)>  When multiple resources need validation ('target?' as below for each).
- (target-resource, True)           when the exact resource is found according to request parsing.
- (parent-resource, False)          when any parent of the resource is found according to request parsing.
- None                              when invalid request or not found resource.

The parent-resource should indicate the closest higher-level resource in the hierarchy that would nest the otherwise desired target-resource. The idea behind this is that Magpie will be able to resolve the effective recursive scoped permission even if not all corresponding resources were explicitly defined in the database.

For example, if the request would be interpreted with the following hierarchy after service-specific resolution:

ServiceA
    Resource1         <== closest *existing* parent resource
        [Resource2]   <== target (according to service/request resolution), but not existing in database

A permission defined as Allow/Recursive on Resource1 should normally allow access to Resource2. If Resource2 is not present in the database though, it cannot be looked for, and the corresponding ACL cannot be generated. Because the (real) protected service using Magpie can have a large and dynamic hierarchy, it is not convenient to enforce perpetual sync between it and its resource representation in Magpie. Using (parent-resource, False) will allow resolution of permission from the closest available parent.

Note

In case of parent-resource returned, only recursive-scoped permissions will be considered, since the missing target-resource is the only one that should be checked for match-scoped permissions. For this reason, the service-specific implementation should preferably return the explicit target resource whenever possible.

If the returned resource is None, the ACL will effectively be resolved to denied access. This can be used to indicate failure to retrieve the expected resource or that corresponding resource does not exist. Otherwise, this method implementation should convert any request path, query parameters, etc. into an existing resource.

If a list of (target-resource, target?) is returned, all of those resources should individually perform Effective Resolution and should ALL simultaneously be granted access to let the request through. This can be used to resolve ambiguous or equivalent parameter combinations from parsing the request, or to validate access to parameters that allow multi-resource references using some kind of list value representation.

See also

Returns:

One or many tuple of reference resource (target/parent), and explicit match status of the corresponding resource (True/False)

permission_requested() magpie.typedefs.PermissionRequested[source]

Defines how to interpret the incoming request into Permission definitions for the given service.

Each service must implement its own definition. The method must specifically define how to convert generic request path, query, etc. elements into permissions that match the service and its children resources.

If None is returned, the ACL will effectively be resolved to denied access. Otherwise, one or more returned Permission will indicate which permissions should be looked for to resolve the ACL of the authenticated user and its groups.

If the request cannot be parsed for any reason to retrieve needed parameters (e.g.: Bad Request), the :exception:`HTTPBadRequest` can be raised to indicate specifically the cause, which will help magpie.adapter.magpieowssecurity.MagpieOWSSecurity create a better response with the relevant error details.

class magpie.services.ServiceGeoserverWPS(service: magpie.models.Service, request: pyramid.request.Request)[source]

Bases: ServiceGeoserverBase, ServiceWPS

Service that represents a Web Processing Service under a Geoserver instance.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_base = 'wps'[source]
service_type = 'geoserverwps'[source]
resource_scoped = False[source]
resource_multi = True[source]
resource_param = 'identifier'[source]
resource_types_permissions[source]
child_structure_allowed[source]
class magpie.services.ServiceGeoserverAPI(service: magpie.models.Service, request: pyramid.request.Request | None)[source]

Bases: ServiceAPI, ServiceGeoserverBase

Service that represents a generic REST API under a Geoserver instance.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_base = 'api'[source]
service_type = 'geoserverapi'[source]
resource_scoped = False[source]
resource_multi = False[source]
resource_param = None[source]
resource_types_permissions[source]
class magpie.services.ServiceGeoserver(service: magpie.models.Service, request: pyramid.request.Request | None)[source]

Bases: ServiceGeoserverBase

Service that encapsulates the multiple OWS endpoints from Geoserver services.

Initialize the service.

Parameters:
  • service – Base service resource that must be handled by this service implementation.

  • request – Active request to handle requested resources, permissions and effective access. The request can be omitted if basic service definition details are to be retrieved. It is mandatory for any requested or effective component that should be resolved.

service_base = None[source]
service_type = 'geoserver'[source]
service_map[source]
property service_supported: Set[Type[ServiceGeoserverBase]][source]
child_structure_allowed[source]

Allowed children resource structure for Geoserver.

Note

In the context of Geoserver, WPS are applied on available resources (WFS, WMS, etc.). For this reason, the models.Process also needs to be scoped under models.Workspace in order to grant access to those resources to work on them, but the models.Workspace name MUST be in the path (i.e.: identifier=<WORKSPACE>:<PROCESS_ID> request parameter does not work). Without the models.Workspace scope in the path, identifier parameter fails to be resolved by Geoserver, as if it was unspecified. Attribute ServiceGeoserverWPS.resource_scoped controls the behaviour of splitting the defined resource_param into models.Workspace and child components.

Note

The models.Route is allowed at the root of the service and for any nested models.Route resource to support various endpoints such as the /web user interface, or the REST interface for the new generation of OGC API services typically on /ogc/{features|maps|processes} endpoints. No special logic is applied for the different services nested under those endpoints. All of them are handled as typical RESTful APIs, for which permissions and appropriate sub-paths should be defined accordingly with their respective specifications and schema.

configurable = True[source]
get_config() magpie.typedefs.ServiceConfiguration[source]

Obtain the configuration defining which OWS services are enabled under this instance.

Should provide a mapping of all OWS service type names to enabled boolean status.

property params_expected: List[magpie.typedefs.Str][source]

Specify typical Geoserver request query parameters expected for any sub-service implementation.

The resource_param is also added to ensure it is always parsed based on the derived implementation.

property permissions: List[magpie.permissions.Permission][source]
property resource_types_permissions: magpie.typedefs.ResourceTypePermissions[source]

Explicit permissions provided for resources for a given OWS implementation.

_set_request(request: pyramid.request.Request) None[source]
service_requested() Type[ServiceGeoserverBase] | None[source]

Obtain the applicable OWS implementation according to parsed request parameters.

property resource_scoped: bool[source]

Indicates if the Service is allowed to employ scoped models.Workspace naming.

When allowed, the models.Workspace can be inferred from the request parameter defined by resource_param to retrieve scoped name as <WORKSPACE>:<RESOURCE>. When not allowed, the resource name is left untouched and Magpie will not attempt to infer any models.Workspace from it. In that case, models.Workspace can only be specified in the request path for isolated Resource references.

Note

When this parameter is False for a given Service implementation, children Resources can still be named in a similar <namespace>:<element> fashion. The only distinction is that the full Resource should include this complete definition instead of nesting <namespace> and <element> into two distinct Resources.

property resource_multi: bool[source]

Indicates if the Service supports multiple simultaneous Resource references.

When supported, the value retrieved from resource_param can be comma-separated to represent multiple Resource of the same nature, which can all be retrieved with the same request. Otherwise, single value only is considered by default.

Note

Permission modifier Access.ALLOW will have to be resolved for all those Resource references for the request to be granted access.

property resource_param: magpie.typedefs.Str | List[magpie.typedefs.Str][source]

Name of the request query parameter(s) to access requested leaf children resource.

If a single string is defined, the parameter must be equal to this value (case insensitive). When using a list, any specified name combination will be resolved as the same parameter.

Note

The resulting parameter(s) are automatically added to params_expected() to ensure they are always retrieved in the parser from the request query parameters.

See also

resource_param_requested() to obtain the resolved parameter considering any applicable combination.

resource_requested() magpie.typedefs.MultiResourceRequested[source]

Parse the requested resource down to the applicable models.Workspace.

Note

Further child resource processing must be accomplished by the derived implementation as needed.

permission_requested() magpie.typedefs.PermissionRequested[source]

Defines how to interpret the incoming request into Permission definitions for the given service.

Each service must implement its own definition. The method must specifically define how to convert generic request path, query, etc. elements into permissions that match the service and its children resources.

If None is returned, the ACL will effectively be resolved to denied access. Otherwise, one or more returned Permission will indicate which permissions should be looked for to resolve the ACL of the authenticated user and its groups.

If the request cannot be parsed for any reason to retrieve needed parameters (e.g.: Bad Request), the :exception:`HTTPBadRequest` can be raised to indicate specifically the cause, which will help magpie.adapter.magpieowssecurity.MagpieOWSSecurity create a better response with the relevant error details.

magpie.services.SERVICE_TYPES[source]
magpie.services.SERVICE_TYPE_DICT[source]
magpie.services.service_factory(service: magpie.models.Service, request: pyramid.request.Request) ServiceInterface[source]

Retrieve the specific service class from the provided database service entry.

magpie.services.get_resource_child_allowed(resource: magpie.typedefs.ServiceOrResourceType) bool[source]

Verifies if the specified resource allows nesting children resources under it considering its specific type.

Makes sure to obtain the specific Service or Resource implementation to verify children support. If this is not accomplished, the default attribute of base Service or Resource would erroneously indicate that children are allowed.

Parameters:

resource – Item for which to verify if children resources are allowed.

Returns:

Whether the resource can nest more resources or not.

magpie.services.invalidate_service(service_name: magpie.typedefs.Str) None[source]

Invalidates any caching reference to the specified service name.