:py:mod:`magpie.models` ======================= .. py:module:: magpie.models Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: magpie.models.Group magpie.models.GroupPermission magpie.models.UserGroupStatus magpie.models.UserGroup magpie.models.GroupResourcePermission magpie.models.Resource magpie.models.UserPermission magpie.models.UserResourcePermission magpie.models.User magpie.models.UserPending magpie.models.UserStatuses magpie.models.UserSearchService magpie.models.ExternalIdentity magpie.models.RootFactory magpie.models.UserFactory magpie.models.Service magpie.models.PathBase magpie.models.File magpie.models.Directory magpie.models.Layer magpie.models.Workspace magpie.models.Route magpie.models.Process magpie.models.RemoteResource magpie.models.RemoteResourcesSyncInfo magpie.models.RemoteResourceTreeService magpie.models.RemoteResourceTreeServicePostgresSQL magpie.models.TokenOperation magpie.models.TemporaryToken Functions ~~~~~~~~~ .. autoapisummary:: magpie.models.get_session_callable magpie.models.resource_factory magpie.models.find_children_by_name Attributes ~~~~~~~~~~ .. autoapisummary:: magpie.models._UserType magpie.models.LOGGER magpie.models.Base magpie.models.RESOURCE_TREE_SERVICE magpie.models.REMOTE_RESOURCE_TREE_SERVICE magpie.models.RESOURCE_TYPES magpie.models.RESOURCE_TYPE_DICT .. py:data:: _UserType :type: magpie.typedefs.TypeAlias :value: 'User' .. py:data:: LOGGER .. py:data:: Base .. py:function:: get_session_callable(request: pyramid.request.Request) -> sqlalchemy.orm.session.Session .. py:class:: Group Bases: :py:obj:`ziggurat_foundations.models.group.GroupMixin`, :py:obj:`Base` Mixin for Group model .. py:property:: discoverable Indicates if the group is discoverable for users to self-register to it. .. py:property:: terms Text containing the terms and conditions. .. py:property:: priority :type: magpie.typedefs.GroupPriority Sorting priority weight of the group for resolving conflicting permissions. .. py:attribute:: _priority .. py:method:: get_member_count(db_session: Optional[sqlalchemy.orm.session.Session] = None) -> int .. py:class:: GroupPermission Bases: :py:obj:`ziggurat_foundations.models.group_permission.GroupPermissionMixin`, :py:obj:`Base` Mixin for GroupPermission model .. py:class:: UserGroupStatus Bases: :py:obj:`magpie.utils.FlexibleNameEnum` Supported statuses of user-group relationships. .. py:attribute:: ALL :value: 'all' .. py:attribute:: ACTIVE :value: 'active' .. py:attribute:: PENDING :value: 'pending' .. py:method:: allowed() -> List[magpie.typedefs.Str] :classmethod: Returns all supported representation values that can be mapped to a valid status. .. py:class:: UserGroup Bases: :py:obj:`ziggurat_foundations.models.user_group.UserGroupMixin`, :py:obj:`Base` Mixin for UserGroup model .. py:class:: GroupResourcePermission Bases: :py:obj:`ziggurat_foundations.models.group_resource_permission.GroupResourcePermissionMixin`, :py:obj:`Base` Mixin for GroupResourcePermission model .. py:class:: Resource Bases: :py:obj:`ziggurat_foundations.models.resource.ResourceMixin`, :py:obj:`Base` Mixin for Resource model .. py:property:: root_service_id .. py:property:: __acl__ :type: magpie.typedefs.AccessControlListType User or group that owns a resource are granted full access to it. .. py:attribute:: resource_type_name :type: magpie.typedefs.Str .. py:attribute:: permissions :type: List[magpie.permissions.Permission] :value: [] .. py:attribute:: child_resource_allowed :value: True .. py:attribute:: resource_display_name .. py:method:: __str__() Return str(self). .. py:class:: UserPermission Bases: :py:obj:`ziggurat_foundations.models.user_permission.UserPermissionMixin`, :py:obj:`Base` Mixin for UserPermission model .. py:class:: UserResourcePermission Bases: :py:obj:`ziggurat_foundations.models.user_resource_permission.UserResourcePermissionMixin`, :py:obj:`Base` Mixin for UserResourcePermission model .. py:class:: User Bases: :py:obj:`ziggurat_foundations.models.user.UserMixin`, :py:obj:`Base` Base mixin for User object representation. It supplies all the basic functionality from password hash generation and matching to utility methods used for querying database for users and their permissions or resources they have access to. It is meant to be extended with other application specific properties .. py:method:: __str__() Return str(self). .. py:method:: get_groups_by_status(status: UserGroupStatus, db_session: sqlalchemy.orm.session.Session = None) -> Set[magpie.typedefs.Str] List all groups a user belongs to, filtered by UserGroup status type. .. py:class:: UserPending Bases: :py:obj:`Base` Temporary definition of a :class:`User` pending for approval by an administrator. .. py:property:: __tablename__ .. py:property:: id Unique identifier of user. .. py:property:: user_name Unique user name. .. py:property:: user_password Password hash of the user. .. py:property:: email Email of the user. .. py:property:: registered_date Date of user's registration. .. py:property:: status Pending user status is enforced. Avoid error in case the corresponding attribute of :class:`User` was accessed. .. py:property:: groups Pending user is not a member of any group. Avoid error in case this field gets accessed when simultaneously handling :class:`User` and :class`UserPending`. .. py:property:: passwordmanager Employ the same password manager attached to :class:`User` instances from :class:`UserService`. This allows all functionalities of password generation, encryption and comparison to be directly transferable between this pending user until it eventually gets upgraded to a full :class:`User` once validated. .. py:method:: get_groups_by_status(status: UserGroupStatus, db_session: sqlalchemy.orm.session.Session = None) -> List[magpie.typedefs.Str] Pending user is not a member of any group. Avoid error in case this method gets accessed when simultaneously handling :class:`User` and :class`UserPending`. .. py:method:: upgrade(db_session: Optional[sqlalchemy.orm.session.Session] = None) -> User Upgrades this :class`UserPending` instance to a complete and corresponding :class:`User` definition. Automatically handles instance updates in the database. All relevant :class:`User` metadata is transferred from available :class:`UserPending` details. All operations that should take place during normal :class:`User` creation will take effect, including minimal :class:`Group` membership creation and :term:`Webhook` triggers. This current :class:`UserPending` instance is finally removed and should not be accessed following upgrade. :param db_session: Database connection to use, otherwise retrieved from the user pending object. :returns: created user instance .. py:class:: UserStatuses Bases: :py:obj:`enum.IntFlag`, :py:obj:`magpie.utils.FlexibleNameEnum` Values applicable to :term:`User` statues. Provides allowed values for the ``status`` search query of :class:`User` and :class:`UserPending` entries. Also, defines the possible values of :attr:`User.status` field, omitting :attr:`UserStatuses.Pending` reserved for objects defined by :class:`UserPending`. Initialize self. See help(type(self)) for accurate signature. .. py:attribute:: OK :value: 1 .. py:attribute:: WebhookError :value: 2 .. py:attribute:: Pending :value: 4 .. py:method:: _get_one(status: AnyUserStatus) -> Optional[UserStatuses] :classmethod: .. py:method:: get(status: Union[None, int, magpie.typedefs.Str, UserStatuses, Iterable[None, int, magpie.typedefs.Str, UserStatuses]], default: Optional[UserStatuses] = None) -> Optional[UserStatuses] :classmethod: Obtains the combined flag :class:`UserStatuses` .. py:method:: allowed() -> List[Union[None, int, magpie.typedefs.Str]] :classmethod: Returns all supported representation values that can be mapped to a valid status for :class:`UserSearchService`. .. py:method:: all() -> UserStatuses :classmethod: Representation of all flags combined. .. py:method:: __or__(other: Union[UserStatuses, int]) -> UserStatuses Return self|value. .. py:method:: __and__(other: Union[UserStatuses, int]) -> UserStatuses Return self&value. .. py:method:: __xor__(other: Union[UserStatuses, int]) -> UserStatuses Return self^value. .. py:method:: __iter__() -> Iterable[UserStatuses] .. py:method:: __len__() .. py:class:: UserSearchService Bases: :py:obj:`ziggurat_foundations.models.services.user.UserService` Extends the :mod:`ziggurat_foundations` :class:`UserService` with additional features provided by `Magpie`. .. note:: For any search result where parameter ``status`` is equal to or contains :attr:`UserStatuses.Pending` combined with any other :class:`UserStatuses` members, or through the *all* representation, the returned iterable could be a mix of both :term:`User` models or only :class:`UserPending`. Therefore, only fields supported by both of those models should be accessed from the result. .. py:method:: by_status(status: Optional[UserStatuses] = None, db_session: Optional[sqlalchemy.orm.session.Session] = None) -> Iterable[AnyUser] :classmethod: Search for appropriate :class:`User` and/or :class:`UserPending` according to specified :class:`UserStatuses`. When the :paramref:`status` is ``None``, *normal* retrieval of all non-pending :class:`User` is executed, as if directly using the :class:`UserService` implementation. Otherwise, a combination of appropriate search criterion is executed based on the :paramref:`status` flags. .. py:method:: by_user_name(user_name: magpie.typedefs.Str, status: Optional[UserStatuses] = None, db_session: Optional[sqlalchemy.orm.session.Session] = None) -> Optional[AnyUser] :classmethod: Retrieves the user matching the given name. Search is always accomplished against :class:`User` table unless :attr:`UserStatuses.Pending` is provided in the :paramref:`status`. If more that one status is provided such that both :class:`UserPending` and :class:`User` could yield results, the :class:`User` is returned first, as there should not be any conflict between those two models. .. py:method:: by_name_or_email(user_name: magpie.typedefs.Str, email: magpie.typedefs.Str, status: Optional[UserStatuses] = None, db_session: Optional[sqlalchemy.orm.session.Session] = None) -> Optional[AnyUser] :classmethod: Retrieves the first matched user by either name or email, whichever comes first. If the :paramref:`status` is provided, search is executed against relevant :class:`User` and/or :class`UserPending` definitions. The :paramref:`user_name` is looked for first across both tables (as needed) and then by :paramref:`email` if not previously matched. .. seealso:: :meth:`by_user_name` :meth:`by_email` :meth:`by_email_and_username` .. py:class:: ExternalIdentity Bases: :py:obj:`ziggurat_foundations.models.external_identity.ExternalIdentityMixin`, :py:obj:`Base` Mixin for External Identity model - it represents oAuth(or other) accounts attached to your user object .. py:class:: RootFactory(request: pyramid.request.Request) Bases: :py:obj:`object` Used to build base Access Control List (ACL) of the request user. All API and UI routes will employ this set of effective principals to determine if the user is authorized to access the pyramid view according to the ``permission`` value it was configured with. .. note:: Keep in mind that `Magpie` is configured with default permission :py:data:`magpie.constants.MAGPIE_ADMIN_PERMISSION`. Views that require more permissive authorization must be overridden with ``permission`` argument. .. seealso:: - ``set_default_permission`` within :func:`magpie.includeme` initialization steps .. py:property:: __acl__ :type: magpie.typedefs.AccessControlListType Administrators have all permissions, user/group-specific permissions added if user is logged in. .. py:attribute:: __name__ .. py:attribute:: __parent__ :value: '' .. py:class:: UserFactory(request: pyramid.request.Request) Bases: :py:obj:`RootFactory` Used to build base Access Control List (ACL) of the request user. All API and UI routes will employ this set of effective principals to determine if the user is authorized to access the pyramid view according to the ``permission`` value it was configured with. .. note:: Keep in mind that `Magpie` is configured with default permission :py:data:`magpie.constants.MAGPIE_ADMIN_PERMISSION`. Views that require more permissive authorization must be overridden with ``permission`` argument. .. seealso:: - ``set_default_permission`` within :func:`magpie.includeme` initialization steps .. py:property:: __acl__ :type: magpie.typedefs.AccessControlListType Grant access to :term:`Request User` according to its relationship to :term:`Context User`. If it is the same user (either from explicit name or by :py:data:`magpie.constants.MAGPIE_LOGGED_USER` reserved keyword), allow :py:data:`magpie.constants.MAGPIE_LOGGED_PERMISSION` for itself to access corresponding views. If request user is unauthenticated (``None``), :py:data:`magpie.constants.MAGPIE_LOGGED_USER` or itself, also grant :py:data:`magpie.constants.MAGPIE_CONTEXT_PERMISSION` to allow access to contextually-available details (e.g.: user can view his own information and public ones). All ACL permissions from :class:`RootFactory` are applied on top of user-specific permissions added here. .. py:method:: __getitem__(user_name: magpie.typedefs.Str) -> UserFactory .. py:class:: Service Bases: :py:obj:`Resource` Resource of `service` type. .. py:property:: permissions .. py:property:: url .. py:property:: type Identifier matching ``magpie.services.ServiceInterface.service_type``. .. py:property:: sync_type Identifier matching ``magpie.cli.SyncServiceInterface.sync_type``. .. py:property:: configuration Configuration modifiers for parsing access to resources and permissions. .. seealso:: - :meth:`magpie.services.ServiceInterface.get_config` .. py:attribute:: __tablename__ :value: 'services' .. py:attribute:: resource_id .. py:attribute:: resource_type_name :value: 'service' .. py:attribute:: __mapper_args__ .. py:method:: by_service_name(service_name, db_session) :staticmethod: .. py:class:: PathBase Bases: :py:obj:`object` .. py:attribute:: permissions .. py:class:: File Bases: :py:obj:`Resource`, :py:obj:`PathBase` Resource that represents the leaf node in a file-system-like hierarchy. In the context of `THREDDS`, this represents the corresponding files exposed by the service. This resource cannot have any children resource under it. .. py:attribute:: child_resource_allowed :value: False .. py:attribute:: resource_type_name :value: 'file' .. py:attribute:: __mapper_args__ .. py:class:: Directory Bases: :py:obj:`Resource`, :py:obj:`PathBase` Resource that represents an intermediate directory node within a file-system-like hierarchy. In the context of `THREDDS`, this represents the corresponding directories exposed by the service. Any amount of :class:`Directory` can be nested under itself to form the tree hierarchy. .. py:attribute:: resource_type_name :value: 'directory' .. py:attribute:: __mapper_args__ .. py:class:: Layer Bases: :py:obj:`Resource` Resource that defines multiple corresponding representations of a layer according to the :term:`OWS` it lies under. In the context of `WFS`, this is the represented collection of features. In the context of `WMS`, this is the referenced features employed to generate the map. .. py:attribute:: child_resource_allowed :value: False .. py:attribute:: resource_type_name :value: 'layer' .. py:attribute:: __mapper_args__ .. py:attribute:: permissions .. py:class:: Workspace Bases: :py:obj:`Resource` Resource employed to contain a group of scoped :class:`Layer` within a `Geoserver` instance. .. py:attribute:: resource_type_name :value: 'workspace' .. py:attribute:: __mapper_args__ .. py:attribute:: permissions .. py:class:: Route Bases: :py:obj:`Resource` Resource employed to represent a single request path fragment. .. py:attribute:: resource_type_name :value: 'route' .. py:attribute:: __mapper_args__ .. py:attribute:: permissions .. py:class:: Process Bases: :py:obj:`Resource` Resource that represents a process under an :term:`OWS` instance servicing a `WPS` endpoint. .. py:attribute:: child_resource_allowed :value: False .. py:attribute:: resource_type_name :value: 'process' .. py:attribute:: __mapper_args__ .. py:attribute:: permissions .. py:class:: RemoteResource Bases: :py:obj:`ziggurat_foundations.models.base.BaseModel`, :py:obj:`Base` Basic class that all other classes inherit from that supplies some basic methods useful for interaction with packages like: deform, colander or wtforms .. py:attribute:: __tablename__ :value: 'remote_resources' .. py:attribute:: __possible_permissions__ :value: () .. py:attribute:: _ziggurat_services .. py:attribute:: resource_id .. py:attribute:: service_id .. py:attribute:: parent_id .. py:attribute:: ordering .. py:attribute:: resource_name .. py:attribute:: resource_display_name .. py:attribute:: resource_type .. py:method:: __repr__() Return repr(self). .. py:class:: RemoteResourcesSyncInfo Bases: :py:obj:`ziggurat_foundations.models.base.BaseModel`, :py:obj:`Base` Basic class that all other classes inherit from that supplies some basic methods useful for interaction with packages like: deform, colander or wtforms .. py:attribute:: __tablename__ :value: 'remote_resources_sync_info' .. py:attribute:: id .. py:attribute:: service_id .. py:attribute:: service .. py:attribute:: remote_resource_id .. py:attribute:: last_sync .. py:method:: by_service_id(service_id, session) :staticmethod: .. py:method:: __repr__() Return repr(self). .. py:class:: RemoteResourceTreeService(service_cls) Bases: :py:obj:`ziggurat_foundations.models.services.resource_tree.ResourceTreeService` .. py:class:: RemoteResourceTreeServicePostgresSQL(service_cls) Bases: :py:obj:`ziggurat_foundations.models.services.resource_tree_postgres.ResourceTreeServicePostgreSQL` This is necessary, because ResourceTreeServicePostgresSQL.model is the Resource class. If we want to change it for a RemoteResource, we need this class. The ResourceTreeService.__init__ call sets the model. .. py:method:: build_subtree_strut(result, *args, **kwargs) :classmethod: Returns a dictionary in form of ``{node:Resource, children:{node_id: Resource}}``. :param result: :return: .. py:class:: TokenOperation Bases: :py:obj:`magpie.utils.ExtendedEnum` Supported operations by the temporary tokens. .. py:attribute:: GROUP_ACCEPT_TERMS :value: 'group-accept-terms' Temporary token associated to an URL endpoint called by a user that accepts the terms and conditions (T&C) to join a particular group. .. py:attribute:: USER_PASSWORD_RESET :value: 'user-password-reset' Temporary token associated to an URL endpoint to request a user password reset. .. py:attribute:: USER_REGISTRATION_CONFIRM_EMAIL :value: 'user-registration-confirm-email' Temporary token associated to a pending user registration that requires email validation by visiting the link. .. py:attribute:: USER_REGISTRATION_ADMIN_APPROVE :value: 'user-registration-admin-approve' Temporary token associated to a pending user registration that will be approved by an administrator when visited. .. py:attribute:: USER_REGISTRATION_ADMIN_DECLINE :value: 'user-registration-admin-decline' Temporary token associated to a pending user registration that will be declined by an administrator when visited. .. py:attribute:: WEBHOOK_USER_STATUS_ERROR :value: 'webhook-user-status-error' Temporary token employed to provide a callback URL that a registered webhook can call following the triggered event to indicate that the corresponding operation resulted into an invalid user status. .. py:class:: TemporaryToken(*_, **__) Bases: :py:obj:`ziggurat_foundations.models.base.BaseModel`, :py:obj:`Base` Model that defines a token for temporary URL completion of a given pending operation. .. py:attribute:: __tablename__ :value: 'tmp_tokens' .. py:attribute:: token .. py:attribute:: operation .. py:attribute:: created .. py:attribute:: user_id .. py:attribute:: _user .. py:attribute:: user_pending_id .. py:attribute:: _pending_user .. py:attribute:: group_id .. py:attribute:: group .. py:method:: user() -> AnyUser .. py:method:: url(settings: magpie.typedefs.AnySettingsContainer = None) -> magpie.typedefs.Str .. py:method:: expired() -> bool .. py:method:: by_token(token: Union[magpie.typedefs.Str, sqlalchemy.dialects.postgresql.UUID], db_session: Optional[sqlalchemy.orm.session.Session] = None) -> Optional[TemporaryToken] :staticmethod: .. py:method:: by_user(user: AnyUser, db_session: Optional[sqlalchemy.orm.session.Session] = None) -> Optional[sqlalchemy.orm.query.Query] :staticmethod: .. py:method:: json() -> magpie.typedefs.JSON .. py:data:: RESOURCE_TREE_SERVICE .. py:data:: REMOTE_RESOURCE_TREE_SERVICE .. py:data:: RESOURCE_TYPES .. py:data:: RESOURCE_TYPE_DICT :type: Dict[magpie.typedefs.Str, Type[Resource]] .. py:function:: resource_factory(**kwargs: Any) -> Resource .. py:function:: find_children_by_name(child_name: magpie.typedefs.Str, parent_id: Optional[int], db_session: sqlalchemy.orm.session.Session) -> Optional[Resource]