Ejemplo n.º 1
0
def create_service_resource_view(request):
    """
    Register a new resource directly under a service or under one of its children resources.
    """
    service = ar.get_service_matchdict_checked(request)
    resource_name = ar.get_multiformat_body(request, "resource_name")
    resource_display_name = ar.get_multiformat_body(request, "resource_display_name", default=resource_name)
    resource_type = ar.get_multiformat_body(request, "resource_type")
    parent_id = ar.get_multiformat_body(request, "parent_id")  # no check because None/empty is allowed
    db_session = request.db
    if parent_id is None:
        parent_id = service.resource_id
    else:
        parent_id = ax.evaluate_call(lambda: int(parent_id),
                                     http_error=HTTPUnprocessableEntity,
                                     msg_on_fail=s.ServiceResources_POST_UnprocessableEntityResponseSchema.description)
        # validate target service is actually the root service of the provided parent resource ID
        root_service = ru.get_resource_root_service_by_id(parent_id, db_session=db_session)
        ax.verify_param(root_service, not_none=True, param_name="parent_id",
                        msg_on_fail=s.ServiceResources_POST_NotFoundResponseSchema.description,
                        http_error=HTTPNotFound)
        ax.verify_param(root_service.resource_id, is_equal=True,
                        param_compare=service.resource_id, param_name="parent_id",
                        msg_on_fail=s.ServiceResources_POST_ForbiddenResponseSchema.description,
                        http_error=HTTPForbidden)
    return ru.create_resource(resource_name, resource_display_name, resource_type,
                              parent_id=parent_id, db_session=db_session)
Ejemplo n.º 2
0
def create_resource_view(request):
    """
    Register a new resource.
    """
    resource_name = ar.get_value_multiformat_post_checked(request, "resource_name")
    resource_display_name = ar.get_multiformat_any(request, "resource_display_name", default=resource_name)
    resource_type = ar.get_value_multiformat_post_checked(request, "resource_type")
    parent_id = ar.get_value_multiformat_post_checked(request, "parent_id")
    return ru.create_resource(resource_name, resource_display_name, resource_type, parent_id, request.db)
Ejemplo n.º 3
0
def create_service_direct_resource_view(request):
    """
    Register a new resource directly under a service.
    """
    service = ar.get_service_matchdict_checked(request)
    resource_name = ar.get_multiformat_post(request, "resource_name")
    resource_display_name = ar.get_multiformat_post(request,
                                                    "resource_display_name",
                                                    default=resource_name)
    resource_type = ar.get_multiformat_post(request, "resource_type")
    parent_id = ar.get_multiformat_post(
        request, "parent_id")  # no check because None/empty is allowed
    if not parent_id:
        parent_id = service.resource_id
    return create_resource(resource_name,
                           resource_display_name,
                           resource_type,
                           parent_id=parent_id,
                           db_session=request.db)
Ejemplo n.º 4
0
def parse_resource_path(
        permission_config_entry,  # type: ConfigItem
        entry_index,  # type: int
        service_info,  # type: ConfigItem
        cookies_or_session=None,  # type: CookiesOrSessionType
        magpie_url=None,  # type: Optional[Str]
):  # type: (...) -> Tuple[Optional[int], bool]
    """
    Parses the `resource` field of a permission config entry and retrieves the final resource id. Creates missing
    resources as necessary if they can be automatically resolved.

    If `cookies` are provided, uses requests to a running `Magpie` instance (with `magpie_url`) to apply permission.
    If `session` to db is provided, uses direct db connection instead to apply permission.

    :returns: tuple of found id (if any, `None` otherwise), and success status of the parsing operation (error)
    """
    if not magpie_url and use_request(cookies_or_session):
        raise ValueError(
            "cannot use cookies without corresponding request URL")

    resource = None
    resource_path = permission_config_entry.get("resource", "")
    if resource_path.startswith("/"):
        resource_path = resource_path[1:]
    if resource_path.endswith("/"):
        resource_path = resource_path[:-1]
    if resource_path:
        try:
            svc_name = service_info["service_name"]
            svc_type = service_info["service_type"]
            if use_request(cookies_or_session):
                res_path = get_magpie_url() + ServiceResourcesAPI.path.format(
                    service_name=svc_name)
                res_resp = requests.get(res_path, cookies=cookies_or_session)
                res_dict = get_json(res_resp)[svc_name]["resources"]
            else:
                from magpie.api.management.service.service_formats import format_service_resources
                svc = models.Service.by_service_name(
                    svc_name, db_session=cookies_or_session)
                res_dict = format_service_resources(
                    svc, show_all_children=True, db_session=cookies_or_session)
            parent = res_dict["resource_id"]
            child_resources = res_dict["resources"]
            for res in resource_path.split("/"):
                # search in existing children resources
                if len(child_resources):
                    # noinspection PyTypeChecker
                    res_id = list(
                        filter(
                            lambda r: res in
                            [r, child_resources[r]["resource_name"]],
                            child_resources))
                    if res_id:
                        res_info = child_resources[
                            res_id[0]]  # type: Dict[Str, JSON]
                        child_resources = res_info[
                            "children"]  # update next sub-resource iteration
                        parent = res_info["resource_id"]
                        continue
                # missing resource, attempt creation
                svc_res_types = SERVICE_TYPE_DICT[svc_type].resource_type_names
                type_count = len(svc_res_types)
                if type_count != 1:
                    warn_permission(
                        "Cannot automatically generate resources",
                        entry_index,
                        detail=
                        "Service [{}] of type [{}] allows {} sub-resource types"
                        .format(svc_name, svc_type, type_count))
                    raise Exception(
                        "Missing resource to apply permission.")  # fail fast
                res_type = svc_res_types[0]
                if use_request(cookies_or_session):
                    body = {
                        "resource_name": res,
                        "resource_type": res_type,
                        "parent_id": parent
                    }
                    # noinspection PyUnboundLocalVariable
                    resp = requests.post(res_path,
                                         json=body,
                                         cookies=cookies_or_session)
                else:
                    from magpie.api.management.resource.resource_utils import create_resource
                    resp = create_resource(res,
                                           res,
                                           res_type,
                                           parent,
                                           db_session=cookies_or_session)
                if resp.status_code != 201:
                    resp.raise_for_status()
                child_resources = {}
                parent = get_json(resp)["resource"]["resource_id"]
            resource = parent
            if not resource:
                raise Exception(
                    "Could not extract child resource from resource path.")
        except Exception as ex:
            if isinstance(ex, HTTPException):
                detail = "{} ({}), {}".format(
                    type(ex).__name__, ex.status_code, str(ex))
            else:
                detail = repr(ex)
            warn_permission("Failed resources parsing.",
                            entry_index,
                            detail=detail)
            return None, False
    return resource, True