Source code for magpie.api.management.service.service_formats
from typing import TYPE_CHECKING
from pyramid.httpexceptions import HTTPInternalServerError
from magpie.api.exception import evaluate_call
from magpie.api.management.resource.resource_formats import format_resource_tree
from magpie.api.management.resource.resource_utils import crop_tree_with_permission, get_resource_children
from magpie.permissions import PermissionType, format_permissions
from magpie.services import SERVICE_TYPE_DICT
from magpie.utils import get_twitcher_protected_service_url
if TYPE_CHECKING:
# pylint: disable=W0611,unused-import
from typing import List, Optional, Type
from sqlalchemy.orm.session import Session
from magpie.models import Resource, Service
from magpie.permissions import Permission, PermissionSet
from magpie.services import ServiceInterface
from magpie.typedefs import JSON, ResourcePermissionMap
[docs]
def format_service(service, # type: Service
permissions=None, # type: Optional[List[PermissionSet]]
permission_type=None, # type: Optional[PermissionType]
show_private_url=False, # type: bool
show_public_url=True, # type: bool
show_resources_allowed=False, # type: bool
show_configuration=False, # type: bool
basic_info=False, # type: bool
dotted=False, # type: bool
): # type: (...) -> JSON
"""
Formats a :term:`Service` information into JSON.
.. note::
Automatically finds :paramref:`permissions` of the :paramref:`service` if not specified.
To preserve `empty` permissions such as during listing of `user`/`group` resource permissions,
an empty ``list`` should be specified.
:param service: :term:`Service` to be formatted.
:param permissions:
Permissions to list along with the :paramref:`resource`.
By default, these are the applicable permissions for that corresponding resource type.
:param permission_type:
Override indication of provenance to apply to :paramref:`permissions`. Only applicable when they are provided.
:param show_private_url: Display the protected and private URL employed at service registration.
:param show_public_url: Display the generated public URL from configured :ref:`config_twitcher`.
:param show_resources_allowed: Display children resource details.
:param show_configuration: Display the applicable configuration of the :term:`Service` if it supports it.
:param basic_info:
If ``True``, return only sufficient details to identify the service, without any additional details about
:paramref:`permissions`, children resources or configuration information is returned.
:param dotted:
Employ a dot (``.``) instead of underscore (``_``) to separate :term:`Service` from its basic information.
.. seealso::
:func:`magpie.api.management.resource.resource_formats.format_resource`
"""
def fmt_svc():
# type: () -> JSON
sep = "." if dotted else "_"
svc_sync_type = str(service.sync_type) if service.sync_type is not None else service.sync_type
svc_type = SERVICE_TYPE_DICT[service.type]
svc_info = {
"service{}name".format(sep): str(service.resource_name),
"service{}type".format(sep): str(service.type),
"service{}sync_type".format(sep): svc_sync_type,
"service{}configurable".format(sep): svc_type.configurable,
"resource{}id".format(sep): service.resource_id,
}
if show_public_url:
svc_public_url = "service.public_url" if dotted else "public_url" # backward compat
svc_info[svc_public_url] = str(get_twitcher_protected_service_url(service.resource_name))
if show_private_url:
svc_info["service{}url".format(sep)] = str(service.url)
if basic_info:
return svc_info
if show_configuration:
# make sure to generate the default configuration if applicable
if svc_type.configurable:
svc_config = svc_type(service, request=None).get_config()
else:
svc_config = None
svc_info["configuration"] = svc_config
perms = svc_type.permissions if permissions is None else permissions
svc_info.update(format_permissions(perms, permission_type))
if show_resources_allowed:
svc_info["resource_child_allowed"] = svc_type.child_resource_allowed
svc_info["resource_types_allowed"] = sorted(svc_type.resource_type_names)
svc_info["resource_structure_allowed"] = {
res.resource_type_name: list(sorted(child_res.resource_type_name for child_res in children_res))
for res, children_res in svc_type.child_structure_allowed.items()
}
return svc_info
return evaluate_call(
lambda: fmt_svc(),
http_error=HTTPInternalServerError,
msg_on_fail="Failed to format service.",
content={"service": repr(service), "permissions": repr(permissions)}
)
[docs]
def format_service_resources(service, # type: Service
db_session, # type: Session
service_perms=None, # type: Optional[List[PermissionSet]]
resources_perms_dict=None, # type: Optional[ResourcePermissionMap]
permission_type=None, # type: Optional[PermissionType]
show_all_children=False, # type: bool
show_private_url=True, # type: bool
): # type: (...) -> JSON
"""
Formats the service and its children resource tree as a JSON body.
:param service: service for which to display details with sub-resources
:param db_session: database session
:param service_perms:
If provided, sets all :term:`Applied Permission` to display on the formatted :paramref:`service`.
Otherwise, sets :term:`Allowed Permissions <Allowed Permission>` specific to the :paramref:`service`'s type.
:param resources_perms_dict:
If provided (not ``None``), set the :term:`Applied Permission` on each specified resource matched by ID.
If ``None``, retrieve and set :term:`Allowed Permissions <Allowed Permission>` for the corresponding
:term:`Resources <Resource>` under the :term:`Service`.
To set empty :term:`Applied Permission` (e.g.: :term:`User` doesn't have permissions on that resource), provide
an explicit empty dictionary instead.
:param permission_type: Provide permission type being rendered.
:param show_all_children:
Display all children resources recursively, or only ones specified by ID with :paramref:`resources_perms_dict`.
:param show_private_url: displays the
:return: JSON body representation of the service resource tree
"""
def fmt_svc_res(svc, db, svc_perms, res_perms, show_all):
# type: (Service, Session, Optional[List[Permission]], Optional[List[Permission]], bool) -> JSON
tree = get_resource_children(svc, db)
if not show_all:
filter_res_ids = list(res_perms) if res_perms else []
tree, _ = crop_tree_with_permission(tree, filter_res_ids)
svc_perms = SERVICE_TYPE_DICT[svc.type].permissions if svc_perms is None else svc_perms
svc_res = format_service(svc, svc_perms, permission_type, show_private_url=show_private_url)
svc_res["resources"] = format_resource_tree(tree, resources_perms_dict=res_perms,
permission_type=permission_type, db_session=db)
return svc_res
return evaluate_call(
lambda: fmt_svc_res(service, db_session, service_perms, resources_perms_dict, show_all_children),
fallback=lambda: db_session.rollback(), http_error=HTTPInternalServerError,
msg_on_fail="Failed to format service resources tree",
content=format_service(service, service_perms, permission_type, show_private_url=show_private_url)
)
[docs]
def format_service_resource_type(resource_class, service_class):
# type: (Type[Resource], Type[ServiceInterface]) -> JSON
svc_res_info = {
"resource_type": resource_class.resource_type_name,
"resource_child_allowed": resource_class.child_resource_allowed,
}
svc_res_perm = service_class.get_resource_permissions(resource_class.resource_type_name)
svc_res_info.update(format_permissions(svc_res_perm, PermissionType.ALLOWED))
return svc_res_info