magpie.api.management.group.group_utils

Attributes

SERVICE_TYPE_DICT

Classes

WebhookAction

Supported Webhook actions.

PermissionSet

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

PermissionType

Applicable types of Permission according to context.

Functions

format_group(→ magpie.typedefs.JSON)

Obtains the JSON formatted Group definition according to field selection flags.

format_resource(→ magpie.typedefs.JSON)

Formats a Resource information into JSON.

check_valid_service_or_resource_permission(...)

Checks if a permission is valid to be applied to a specific service or a resource under a root service.

get_permission_update_params(...)

Generates the Webhook parameters based on provided references.

process_webhook_requests(→ None)

Checks the config for any webhooks that correspond to the input action, and prepares corresponding requests.

format_permissions(→ Dict[magpie.typedefs.Str, ...)

Obtains the formatted permission representations after validation that each of their name is a known member of

get_all_group_names(→ List[magpie.typedefs.Str])

Get all existing group names from the database.

get_group_resources(→ magpie.typedefs.JSON)

Get formatted JSON body describing all service resources the group as permissions on.

create_group(→ pyramid.httpexceptions.HTTPException)

Creates a group if it is permitted and not conflicting.

get_similar_group_resource_permission(...)

Obtains the group service/resource permission that corresponds to the provided one.

create_group_resource_permission_response(...)

Creates a permission on a group/resource combination if it is permitted and not conflicting.

get_group_resources_permissions_dict(...)

Get a dictionary of resources and corresponding permissions that a group has on the resources.

get_group_resource_permissions_response(...)

Get validated response with group resource permissions as content.

delete_group_resource_permission_response(...)

Get validated response on deleted group resource permission.

get_group_services(→ magpie.typedefs.JSON)

Nest and regroup the resource permissions under corresponding root service types.

get_group_services_response(...)

Get validated response of services the group has permissions on.

get_group_service_permissions(...)

Get all permissions the group has on a specific service.

get_group_service_permissions_response(...)

Get validated response of found group service permissions.

get_group_service_resources_permissions_dict(...)

Get all permissions the group has on a specific service's children resources.

get_group_service_resources_response(...)

Get validated response of all found service resources which the group has permissions on.

Module Contents

magpie.api.management.group.group_utils.format_group(group: magpie.models.Group, basic_info: bool = False, public_info: bool = False, dotted: bool = False, db_session: sqlalchemy.orm.session.Session | None = None) magpie.typedefs.JSON[source]

Obtains the JSON formatted Group definition according to field selection flags.

Parameters:
  • group – Group for which to provide details.

  • basic_info – If True, return only sufficient details to identify the group (useful for routes that refer to a group, but that are not requesting it specifically), or return full details (for routes that specifically request its information, e.g.: GET /groups/{grp}).

  • public_info – Indicate if the returned details are intended for public information (True) or admin-only (False). Only higher level users should be provided additional details to avoid leaking potentially sensitive parameters.

  • dotted – Employ a dot (.) instead of underscore (_) to separate Group from its basic information.

  • db_session – Database connection to retrieve additional details (required when public_info=False).

magpie.api.management.group.group_utils.format_resource(resource: magpie.models.Resource, permissions: Collection[magpie.typedefs.AnyPermissionType] | None = None, permission_type: magpie.permissions.PermissionType | None = None, basic_info: bool = False, dotted: bool = False) magpie.typedefs.JSON[source]

Formats a Resource information into JSON.

Parameters:
  • resourceResource to be formatted.

  • permissions – Permissions to list along with the resource. By default, these are the applicable permissions for that corresponding resource type.

  • permission_type – Override indication of provenance to apply to permissions. Only applicable when they are provided.

  • basic_info – If True, return only sufficient details to identify the resource, without any additional permissions detail, nor hierarchical resource information is returned.

  • dotted – Employ a dot (.) instead of underscore (_) to separate Resource from its basic information.

magpie.api.management.group.group_utils.check_valid_service_or_resource_permission(permission_name: magpie.typedefs.Str | magpie.permissions.Permission, service_or_resource: magpie.typedefs.ServiceOrResourceType, db_session: sqlalchemy.orm.session.Session) magpie.permissions.Permission | None[source]

Checks if a permission is valid to be applied to a specific service or a resource under a root service.

Parameters:
  • permission_name – permission name to be validated

  • service_or_resource – resource item corresponding to either a Service or a Resource

  • db_session – db connection

Returns:

valid Permission if allowed by the service/resource

Raises:

HTTPBadRequest – if the permission is not valid for the targeted service/resource

class magpie.api.management.group.group_utils.WebhookAction[source]

Bases: magpie.utils.ExtendedEnum

Supported Webhook actions.

CREATE_USER = 'create_user'

Triggered when a new User gets successfully created.

See also

User Creation

DELETE_USER = 'delete_user'

Triggered when an existing User gets successfully deleted.

See also

User Deletion

UPDATE_USER_STATUS = 'update_user_status'

Triggered when an existing User status gets successfully updated.

CREATE_USER_PERMISSION = 'create_user_permission'

Triggered when a Permission onto a Service or Resource gets created for a User.

DELETE_USER_PERMISSION = 'delete_user_permission'

Triggered when a Permission onto a Service or Resource gets deleted for a User.

CREATE_GROUP_PERMISSION = 'create_group_permission'

Triggered when a Permission onto a Service or Resource gets created for a Group.

DELETE_GROUP_PERMISSION = 'delete_group_permission'

Triggered when a Permission onto a Service or Resource gets deleted for a Group.

magpie.api.management.group.group_utils.get_permission_update_params(target: magpie.models.User | magpie.models.Group, resource: magpie.typedefs.ServiceOrResourceType, permission: magpie.permissions.PermissionSet, db_session: sqlalchemy.orm.session.Session) magpie.typedefs.WebhookTemplateParameters[source]

Generates the Webhook parameters based on provided references.

magpie.api.management.group.group_utils.process_webhook_requests(action: WebhookAction, params: magpie.typedefs.WebhookTemplateParameters, update_user_status_on_error: bool = False, settings: magpie.typedefs.AnySettingsContainer | None = None) None[source]

Checks the config for any webhooks that correspond to the input action, and prepares corresponding requests.

Parameters:
  • action – tag identifying which webhooks to use in the config

  • params – Dictionary containing the required parameters and associated values for the request following the event action. Parameters will replace templates found in the payload definition of the webhook.

  • update_user_status_on_error – update the user status or not in case of a webhook error.

  • settings – application settings where webhooks configuration can be retrieved.

class magpie.api.management.group.group_utils.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.api.management.group.group_utils.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'
magpie.api.management.group.group_utils.format_permissions(permissions: Collection[magpie.typedefs.AnyPermissionType] | None, permission_type: PermissionType | None = None, force_unique: bool = True) Dict[magpie.typedefs.Str, List[magpie.typedefs.Str] | magpie.typedefs.PermissionDict | magpie.typedefs.Str][source]

Obtains the formatted permission representations after validation that each of their name is a known member of Permission enum, and optionally with modifiers as defined by PermissionSet.

The returned lists are sorted alphabetically by permission name, and then in order of resolution priority (from highest to lowest) for each subset or corresponding name.

The permissions are cleaned from any duplicate entries, unless force_unique is specified to allow it. If no or empty permissions is provided, empty lists are returned.

Note

Field permission_names provides both the older implicit permission names and the newer explicit name representation. For this reason, there will be semantically “duplicate” permissions in that list, but there will not be any literal string duplicates. Implicit names are immediately followed by their explicit name, unless implicit names do not apply for the given permission (e.g.: when Access.DENY did not exist). Only detailed and explicit JSON representations are provided in the permissions list.

When permission_type is equal to PermissionType.ALLOWED, the collection of every applicable PermissionSet is automatically generated by expanding all combinations of Access and Scope with every provided Permission name in permissions. This allows more concise definition of allowed permissions under magpie.services.Services and their children Resource by only defining Permission names without manually listing all variations of PermissionSet.

For other permission_type values, which represent Applied Permission only explicitly provided permissions are returned, to effectively return the collection of active permissions.

Parameters:
  • permissions – multiple permissions of any implementation and type, to be rendered both as names and JSON.

  • permission_type – indication of the represented permissions to be formatted, for informative indication.

  • force_unique – whether to remove duplicate entries by association of name, access and scope or not.

Returns:

JSON with the permissions listed as implicit+explicit names, as permission set objects, and their type.

magpie.api.management.group.group_utils.SERVICE_TYPE_DICT[source]
magpie.api.management.group.group_utils.get_all_group_names(db_session: sqlalchemy.orm.session.Session) List[magpie.typedefs.Str][source]

Get all existing group names from the database.

magpie.api.management.group.group_utils.get_group_resources(group: magpie.models.Group, db_session: sqlalchemy.orm.session.Session, service_types: List[magpie.typedefs.Str] | None = None) magpie.typedefs.JSON[source]

Get formatted JSON body describing all service resources the group as permissions on.

magpie.api.management.group.group_utils.create_group(group_name: magpie.typedefs.Str, description: magpie.typedefs.Str, discoverable: bool, terms: magpie.typedefs.Str, db_session: sqlalchemy.orm.session.Session) pyramid.httpexceptions.HTTPException[source]

Creates a group if it is permitted and not conflicting.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.

magpie.api.management.group.group_utils.get_similar_group_resource_permission(group: magpie.models.Group, resource: magpie.typedefs.ServiceOrResourceType, permission: magpie.permissions.PermissionSet, db_session: sqlalchemy.orm.session.Session) magpie.permissions.PermissionSet | None[source]

Obtains the group service/resource permission that corresponds to the provided one.

Lookup considers only similar applied permission such that other permission modifiers don’t affect comparison.

magpie.api.management.group.group_utils.create_group_resource_permission_response(group: magpie.models.Group, resource: magpie.typedefs.ServiceOrResourceType, permission: magpie.permissions.PermissionSet, db_session: sqlalchemy.orm.session.Session, overwrite: bool = False) pyramid.httpexceptions.HTTPException[source]

Creates a permission on a group/resource combination if it is permitted and not conflicting.

Parameters:
  • group – group for which to create/update the permission.

  • resource – service or resource for which to create the permission.

  • permission – permission with modifiers to be applied.

  • db_session – database connection.

  • overwrite – If the corresponding (group, resource, permission[name]) exists, there is a conflict. Conflict is considered only by permission-name regardless of other modifiers. If overwrite is False, the conflict will be raised and not be applied. If overwrite is True, the permission modifiers will be replaced by the new ones, or created if missing.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.

magpie.api.management.group.group_utils.get_group_resources_permissions_dict(group: magpie.models.Group, db_session: sqlalchemy.orm.session.Session, resource_ids: Iterable[int] | None = None, resource_types: Iterable[magpie.typedefs.Str] | None = None) magpie.typedefs.ResourcePermissionMap[source]

Get a dictionary of resources and corresponding permissions that a group has on the resources.

Filter search by resource_ids and/or resource_types if specified.

magpie.api.management.group.group_utils.get_group_resource_permissions_response(group: magpie.models.Group, resource: magpie.models.Resource, db_session: sqlalchemy.orm.session.Session) pyramid.httpexceptions.HTTPException[source]

Get validated response with group resource permissions as content.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.

magpie.api.management.group.group_utils.delete_group_resource_permission_response(group: magpie.models.Group, resource: magpie.typedefs.ServiceOrResourceType, permission: magpie.permissions.PermissionSet, db_session: sqlalchemy.orm.session.Session, similar: bool = True) pyramid.httpexceptions.HTTPException[source]

Get validated response on deleted group resource permission.

Parameters:
  • group – group for which to delete the permission.

  • resource – service or resource for which to delete the permission.

  • permission – permission with modifiers to be deleted.

  • db_session – database connection.

  • similar – Allow matching provided permission against any similar database permission. Otherwise, must match exactly.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.

magpie.api.management.group.group_utils.get_group_services(resources_permissions_dict: magpie.typedefs.JSON, db_session: sqlalchemy.orm.session.Session, service_types: List[magpie.typedefs.Str] | None = None) magpie.typedefs.JSON[source]

Nest and regroup the resource permissions under corresponding root service types.

magpie.api.management.group.group_utils.get_group_services_response(group: magpie.models.Group, db_session: sqlalchemy.orm.session.Session, service_types: List[magpie.typedefs.Str] | None = None) pyramid.httpexceptions.HTTPException[source]

Get validated response of services the group has permissions on.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.

magpie.api.management.group.group_utils.get_group_service_permissions(group: magpie.models.Group, service: magpie.models.Service, db_session: sqlalchemy.orm.session.Session) List[magpie.permissions.PermissionSet][source]

Get all permissions the group has on a specific service.

magpie.api.management.group.group_utils.get_group_service_permissions_response(group: magpie.models.Group, service: magpie.models.Service, db_session: sqlalchemy.orm.session.Session) pyramid.httpexceptions.HTTPException[source]

Get validated response of found group service permissions.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.

magpie.api.management.group.group_utils.get_group_service_resources_permissions_dict(group: magpie.models.Group, service: magpie.models.Service, db_session: sqlalchemy.orm.session.Session) magpie.typedefs.ResourcePermissionMap[source]

Get all permissions the group has on a specific service’s children resources.

magpie.api.management.group.group_utils.get_group_service_resources_response(group: magpie.models.Group, service: magpie.models.Service, db_session: sqlalchemy.orm.session.Session) pyramid.httpexceptions.HTTPException[source]

Get validated response of all found service resources which the group has permissions on.

Returns:

valid HTTP response on successful operations.

Raises:

HTTPException – error HTTP response of corresponding situation.