def delete_resource(request): resource = ar.get_resource_matchdict_checked(request) service_push = asbool( ar.get_multiformat_body(request, "service_push", default=False)) res_content = {"resource": format_resource(resource, basic_info=True)} ax.evaluate_call( lambda: models.RESOURCE_TREE_SERVICE.delete_branch( resource_id=resource.resource_id, db_session=request.db), fallback=lambda: request.db.rollback(), http_error=HTTPForbidden, msg_on_fail="Delete resource branch from tree service failed.", content=res_content) def remove_service_magpie_and_phoenix(res, svc_push, db): if res.resource_type != "service": svc_push = False db.delete(res) if svc_push: sync_services_phoenix(db.query(models.Service)) ax.evaluate_call( lambda: remove_service_magpie_and_phoenix(resource, service_push, request.db), fallback=lambda: request.db.rollback(), http_error=HTTPForbidden, msg_on_fail=s.Resource_DELETE_ForbiddenResponseSchema.description, content=res_content) return ax.valid_http(http_success=HTTPOk, detail=s.Resource_DELETE_OkResponseSchema.description)
def unregister_service_view(request): """ Unregister a service. """ service = ar.get_service_matchdict_checked(request) service_push = asbool( ar.get_multiformat_delete(request, "service_push", default=False)) svc_content = sf.format_service(service, show_private_url=True) svc_res_id = service.resource_id ax.evaluate_call(lambda: models.resource_tree_service.delete_branch( resource_id=svc_res_id, db_session=request.db), fallback=lambda: request.db.rollback(), httpError=HTTPForbidden, msgOnFail="Delete service from resource tree failed.", content=svc_content) def remove_service_magpie_and_phoenix(svc, svc_push, db_session): db_session.delete(svc) if svc_push and svc.type in SERVICES_PHOENIX_ALLOWED: sync_services_phoenix(db_session.query(models.Service)) ax.evaluate_call( lambda: remove_service_magpie_and_phoenix(service, service_push, request.db), fallback=lambda: request.db.rollback(), httpError=HTTPForbidden, msgOnFail=s.Service_DELETE_ForbiddenResponseSchema.description, content=svc_content) return ax.valid_http(httpSuccess=HTTPOk, detail=s.Service_DELETE_OkResponseSchema.description)
def delete_user_group_view(request): """ Remove a user from a group. """ db = request.db user = ar.get_user_matchdict_checked_or_logged(request) group = ar.get_group_matchdict_checked(request) def del_usr_grp(usr, grp): db.query(models.UserGroup) \ .filter(models.UserGroup.user_id == usr.id) \ .filter(models.UserGroup.group_id == grp.id) \ .delete() ax.evaluate_call( lambda: del_usr_grp(user, group), fallback=lambda: db.rollback(), httpError=HTTPNotFound, msgOnFail=s.UserGroup_DELETE_NotFoundResponseSchema.description, content={ u"user_name": user.user_name, u"group_name": group.group_name }) return ax.valid_http( httpSuccess=HTTPOk, detail=s.UserGroup_DELETE_OkResponseSchema.description)
def resource_factory(**kwargs): resource_type = evaluate_call(lambda: kwargs["resource_type"], httpError=HTTPInternalServerError, msgOnFail="kwargs do not contain required 'resource_type'", content={u"kwargs": repr(kwargs)}) return evaluate_call(lambda: RESOURCE_TYPE_DICT[resource_type](**kwargs), httpError=HTTPInternalServerError, msgOnFail="kwargs unpacking failed from specified 'resource_type' and 'RESOURCE_TYPE_DICT'", content={u"kwargs": repr(kwargs), u"RESOURCE_TYPE_DICT": repr(RESOURCE_TYPE_DICT)})
def delete_user_resource_permission_response(user, resource, permission, db_session): # type: (models.User, ServiceOrResourceType, Permission, Session) -> HTTPException """ Get validated response on deleted user resource permission. :returns: valid HTTP response on successful operations. :raises HTTPException: error HTTP response of corresponding situation. """ check_valid_service_or_resource_permission(permission.value, resource, db_session) resource_id = resource.resource_id del_perm = UserResourcePermissionService.get(user.id, resource_id, permission.value, db_session) ax.evaluate_call( lambda: db_session.delete(del_perm), fallback=lambda: db_session.rollback(), httpError=HTTPNotFound, msgOnFail=s.UserResourcePermissions_DELETE_NotFoundResponseSchema. description, content={ u"resource_id": resource_id, u"user_id": user.id, u"permission_name": permission.value }) return ax.valid_http( httpSuccess=HTTPOk, detail=s.UserResourcePermissions_DELETE_OkResponseSchema.description)
def create_group_resource_permission_response(group, resource, permission, db_session): # type: (models.Group, ServiceOrResourceType, Permission, Session) -> HTTPException """ Creates a permission on a group/resource combination if it is permitted and not conflicting. :returns: valid HTTP response on successful operations. :raises HTTPException: error HTTP response of corresponding situation. """ resource_id = resource.resource_id check_valid_service_or_resource_permission(permission.value, resource, db_session) perm_content = {u"permission_name": str(permission.value), u"resource": format_resource(resource, basic_info=True), u"group": format_group(group, basic_info=True)} existing_perm = ax.evaluate_call( lambda: GroupResourcePermissionService.get(group.id, resource_id, permission.value, db_session=db_session), fallback=lambda: db_session.rollback(), httpError=HTTPForbidden, msgOnFail=s.GroupResourcePermissions_POST_ForbiddenGetResponseSchema.description, content=perm_content ) ax.verify_param(existing_perm, isNone=True, httpError=HTTPConflict, msgOnFail=s.GroupResourcePermissions_POST_ConflictResponseSchema.description, content=perm_content) # noinspection PyArgumentList new_perm = ax.evaluate_call( lambda: models.GroupResourcePermission(resource_id=resource_id, group_id=group.id, perm_name=permission.value), fallback=lambda: db_session.rollback(), httpError=HTTPForbidden, content=perm_content, msgOnFail=s.GroupResourcePermissions_POST_ForbiddenCreateResponseSchema.description) ax.evaluate_call(lambda: db_session.add(new_perm), fallback=lambda: db_session.rollback(), httpError=HTTPForbidden, content=perm_content, msgOnFail=s.GroupResourcePermissions_POST_ForbiddenAddResponseSchema.description) return ax.valid_http(httpSuccess=HTTPCreated, content=perm_content, detail=s.GroupResourcePermissions_POST_CreatedResponseSchema.description)
def service_factory(service, request): # type: (models.Service, Request) -> ServiceInterface """ Retrieve the specific service class from the provided database service entry. """ ax.verify_param(service, param_compare=models.Service, is_type=True, http_error=HTTPBadRequest, content={"service": repr(service)}, msg_on_fail="Cannot process invalid service object") service_type = ax.evaluate_call( lambda: service.type, http_error=HTTPInternalServerError, msg_on_fail="Cannot retrieve service type from object") ax.verify_param( service_type, is_in=True, param_compare=SERVICE_TYPE_DICT.keys(), http_error=HTTPNotImplemented, content={"service_type": service_type}, msg_on_fail="Undefined service type mapping to service object") return ax.evaluate_call( lambda: SERVICE_TYPE_DICT[service_type](service, request), http_error=HTTPInternalServerError, msg_on_fail="Failed to find requested service type.")
def delete_user_resource_permission_response(user, resource, permission, db_session, similar=True): # type: (models.User, ServiceOrResourceType, PermissionSet, Session, bool) -> HTTPException """ Get validated response on deleted user resource permission. :param user: user for which to delete the permission. :param resource: service or resource for which to delete the permission. :param permission: permission with modifiers to be deleted. :param db_session: database connection. :param 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. """ ru.check_valid_service_or_resource_permission(permission.name, resource, db_session) res_id = resource.resource_id if similar: found_perm = get_similar_user_resource_permission(user, resource, permission, db_session) else: found_perm = permission del_perm = UserResourcePermissionService.get(user.id, res_id, str(found_perm), db_session) permission.type = PermissionType.APPLIED err_content = {"resource_id": res_id, "user_id": user.id, "permission_name": str(permission), "permission": permission.json()} ax.verify_param(del_perm, not_none=True, http_error=HTTPNotFound, content=err_content, msg_on_fail=s.UserResourcePermissionName_DELETE_NotFoundResponseSchema.description) ax.evaluate_call(lambda: db_session.delete(del_perm), fallback=lambda: db_session.rollback(), http_error=HTTPNotFound, content=err_content, msg_on_fail=s.UserResourcePermissionName_DELETE_NotFoundResponseSchema.description) return ax.valid_http(http_success=HTTPOk, detail=s.UserResourcePermissionName_DELETE_OkResponseSchema.description)
def create_user_resource_permission_response(user, resource, permission, db_session): # type: (models.User, ServiceOrResourceType, Permission, Session) -> HTTPException """ Creates a permission on a user/resource combination if it is permitted and not conflicting. :returns: valid HTTP response on successful operation. """ check_valid_service_or_resource_permission(permission.value, resource, db_session) resource_id = resource.resource_id existing_perm = UserResourcePermissionService.by_resource_user_and_perm( user_id=user.id, resource_id=resource_id, perm_name=permission.value, db_session=db_session) ax.verify_param( existing_perm, isNone=True, httpError=HTTPConflict, content={ u"resource_id": resource_id, u"user_id": user.id, u"permission_name": permission.value }, msgOnFail=s.UserResourcePermissions_POST_ConflictResponseSchema. description) # noinspection PyArgumentList new_perm = models.UserResourcePermission(resource_id=resource_id, user_id=user.id, perm_name=permission.value) usr_res_data = { u"resource_id": resource_id, u"user_id": user.id, u"permission_name": permission.value } ax.verify_param( new_perm, notNone=True, httpError=HTTPForbidden, content={ u"resource_id": resource_id, u"user_id": user.id }, msgOnFail=s.UserResourcePermissions_POST_ForbiddenResponseSchema. description) ax.evaluate_call( lambda: db_session.add(new_perm), fallback=lambda: db_session.rollback(), httpError=HTTPForbidden, content=usr_res_data, msgOnFail=s.UserResourcePermissions_POST_ForbiddenResponseSchema. description) return ax.valid_http( httpSuccess=HTTPCreated, content=usr_res_data, detail=s.UserResourcePermissions_POST_CreatedResponseSchema.description )
def _add_to_group(usr, grp): # type: (models.User, models.Group) -> None # noinspection PyArgumentList group_entry = models.UserGroup(group_id=grp.id, user_id=usr.id) ax.evaluate_call( lambda: db_session.add(group_entry), fallback=lambda: db_session.rollback(), httpError=HTTPForbidden, msgOnFail=s.UserGroup_GET_ForbiddenResponseSchema.description)
def update_service_view(request): """ Update service information. """ service = ar.get_service_matchdict_checked(request) service_push = asbool(ar.get_multiformat_body(request, "service_push", default=False)) def select_update(new_value, old_value): return new_value if new_value is not None and not new_value == "" else old_value # None/Empty values are accepted in case of unspecified svc_name = select_update(ar.get_multiformat_body(request, "service_name"), service.resource_name) svc_url = select_update(ar.get_multiformat_body(request, "service_url"), service.url) ax.verify_param(svc_name, param_compare="types", not_equal=True, param_name="service_name", http_error=HTTPForbidden, msg_on_fail=s.Service_PATCH_ForbiddenResponseSchema_ReservedKeyword.description) ax.verify_param(svc_name == service.resource_name and svc_url == service.url, not_equal=True, param_compare=True, param_name="service_name/service_url", http_error=HTTPBadRequest, msg_on_fail=s.Service_PATCH_BadRequestResponseSchema.description) # config explicitly provided as None (null) means override (erase) # to leave it as is, just don't specific the field old_svc_config = service.configuration new_svc_config = ar.get_multiformat_body(request, "configuration") if old_svc_config != new_svc_config: if new_svc_config is not None: ax.verify_param(new_svc_config, param_compare=dict, is_type=True, http_error=HTTPUnprocessableEntity, msg_on_fail=s.Service_CheckConfig_UnprocessableEntityResponseSchema.description) service.configuration = new_svc_config if svc_name != service.resource_name: all_services = request.db.query(models.Service) all_svc_names = [svc.resource_name for svc in all_services] ax.verify_param(svc_name, not_in=True, param_compare=all_svc_names, with_param=False, http_error=HTTPConflict, content={"service_name": str(svc_name)}, msg_on_fail=s.Service_PATCH_ConflictResponseSchema.description) def update_service_magpie_and_phoenix(_svc, new_name, new_url, svc_push, db_session): _svc.resource_name = new_name _svc.url = new_url has_getcap = Permission.GET_CAPABILITIES in SERVICE_TYPE_DICT[_svc.type].permissions if svc_push and _svc.type in SERVICES_PHOENIX_ALLOWED and has_getcap: # (re)apply getcapabilities to updated service to ensure updated push su.add_service_getcapabilities_perms(_svc, db_session) sync_services_phoenix(db_session.query(models.Service)) # push all services old_svc_content = sf.format_service(service, show_private_url=True) err_svc_content = {"service": old_svc_content, "new_service_name": svc_name, "new_service_url": svc_url} ax.evaluate_call(lambda: update_service_magpie_and_phoenix(service, svc_name, svc_url, service_push, request.db), fallback=lambda: request.db.rollback(), http_error=HTTPForbidden, msg_on_fail=s.Service_PATCH_ForbiddenResponseSchema.description, content=err_svc_content) return ax.valid_http(http_success=HTTPOk, detail=s.Service_PATCH_OkResponseSchema.description, content={"service": sf.format_service(service, show_private_url=True)})
def delete_user_view(request): """ Delete a user by name. """ user = ar.get_user_matchdict_checked_or_logged(request) ax.evaluate_call( lambda: request.db.delete(user), fallback=lambda: request.db.rollback(), httpError=HTTPForbidden, msgOnFail=s.User_DELETE_ForbiddenResponseSchema.description) return ax.valid_http(httpSuccess=HTTPOk, detail=s.User_DELETE_OkResponseSchema.description)
def test_evaluate_call_callable_incorrect_usage(self): """ Verifies that incorrect usage of utility is raised accordingly. """ utils.check_raises( lambda: ax.evaluate_call(int), HTTPInternalServerError, msg="invalid callable non-lambda 'call' should raise") utils.check_raises( lambda: ax.evaluate_call(lambda: int, fallback=int), # noqa HTTPInternalServerError, msg="invalid callable non-lambda 'fallback' should raise")
def assign_user_group(user, group, db_session): # type: (models.User, models.Group, Session) -> None """ Creates a user-group relationship (user membership to a group). :returns: nothing - user-group is created. :raises HTTPError: corresponding error matching problem encountered. """ ax.verify_param(user.id, param_compare=[usr.id for usr in group.users], not_in=True, with_param=False, http_error=HTTPConflict, content={"user_name": user.user_name, "group_name": group.group_name}, msg_on_fail=s.UserGroups_POST_ConflictResponseSchema.description) ax.evaluate_call(lambda: db_session.add(models.UserGroup(group_id=group.id, user_id=user.id)), # noqa fallback=lambda: db_session.rollback(), http_error=HTTPForbidden, msg_on_fail=s.UserGroups_POST_RelationshipForbiddenResponseSchema.description, content={"user_name": user.user_name, "group_name": group.group_name})
def resource_factory(**kwargs): resource_type = ax.evaluate_call( lambda: kwargs["resource_type"], http_error=HTTPInternalServerError, msg_on_fail="kwargs do not contain required 'resource_type'", content={"kwargs": repr(kwargs)}) msg = "kwargs unpacking failed from specified 'resource_type' and 'RESOURCE_TYPE_DICT'" return ax.evaluate_call( lambda: RESOURCE_TYPE_DICT[resource_type](**kwargs), # noqa http_error=HTTPInternalServerError, msg_on_fail=msg, content={ "kwargs": repr(kwargs), "RESOURCE_TYPE_DICT": repr(RESOURCE_TYPE_DICT) })
def get_user_service_permissions_view(request): """ List all permissions a user has on a service. """ user = ar.get_user_matchdict_checked_or_logged(request) service = ar.get_service_matchdict_checked(request) inherit_groups_perms = asbool( ar.get_query_param(request, ["inherit", "inherited"])) resolve_groups_perms = asbool( ar.get_query_param(request, ["resolve", "resolved"])) perm_type = PermissionType.INHERITED if inherit_groups_perms else PermissionType.DIRECT perms = ax.evaluate_call( lambda: uu.get_user_service_permissions( service=service, user=user, request=request, inherit_groups_permissions=inherit_groups_perms, resolve_groups_permissions=resolve_groups_perms), fallback=lambda: request.db.rollback(), http_error=HTTPNotFound, msg_on_fail=s.UserServicePermissions_GET_NotFoundResponseSchema. description, content={ "service_name": str(service.resource_name), "user_name": str(user.user_name) }) return ax.valid_http( http_success=HTTPOk, content=format_permissions(perms, perm_type), detail=s.UserServicePermissions_GET_OkResponseSchema.description)
def _add_service_magpie_and_phoenix(svc, svc_push, db): db.add(svc) if svc_push and svc.type in SERVICES_PHOENIX_ALLOWED: sync_services_phoenix(db.query(models.Service)) # sometimes, resource ID is not updated, fetch the service to obtain it if not svc.resource_id: svc = ax.evaluate_call( lambda: models.Service.by_service_name(service_name, db_session=db_session), fallback=lambda: db_session.rollback(), http_error=HTTPInternalServerError, msg_on_fail=s.Services_POST_InternalServerErrorResponseSchema. description, content={ "service_name": str(service_name), "resource_id": svc.resource_id }) ax.verify_param( svc.resource_id, not_none=True, param_compare=int, is_type=True, http_error=HTTPInternalServerError, msg_on_fail=s.Services_POST_InternalServerErrorResponseSchema. description, content={ "service_name": str(service_name), "resource_id": svc.resource_id }, param_name="service_name") return svc
def get_service_type_resources_view(request): """ List details of resource types supported under a specific service type. """ def _get_resource_types_info(res_type_names): res_type_classes = [ rtc for rtn, rtc in models.RESOURCE_TYPE_DICT.items() if rtn in res_type_names ] return [ sf.format_service_resource_type(rtc, SERVICE_TYPE_DICT[service_type]) for rtc in res_type_classes ] service_type = ar.get_value_matchdict_checked(request, "service_type") ax.verify_param( service_type, paramCompare=SERVICE_TYPE_DICT.keys(), isIn=True, httpError=HTTPNotFound, msgOnFail=s.ServiceTypeResources_GET_NotFoundResponseSchema.description ) resource_types_names = ax.evaluate_call( lambda: SERVICE_TYPE_DICT[service_type].resource_type_names, httpError=HTTPForbidden, content={u"service_type": str(service_type)}, msgOnFail=s.ServiceTypeResourceTypes_GET_ForbiddenResponseSchema. description) return ax.valid_http( httpSuccess=HTTPOk, detail=s.ServiceTypeResourceTypes_GET_OkResponseSchema.description, content={ u"resource_types": _get_resource_types_info(resource_types_names) })
def assign_user_group_view(request): """ Assign a user to a group. """ user = ar.get_user_matchdict_checked_or_logged(request) group_name = ar.get_value_multiformat_body_checked(request, "group_name") group = ax.evaluate_call( lambda: GroupService.by_group_name(group_name, db_session=request.db), fallback=lambda: request.db.rollback(), http_error=HTTPForbidden, msg_on_fail=s.UserGroups_POST_ForbiddenResponseSchema.description) ax.verify_param( group, not_none=True, http_error=HTTPNotFound, msg_on_fail=s.UserGroups_POST_GroupNotFoundResponseSchema.description) uu.assign_user_group(user, group, db_session=request.db) return ax.valid_http( http_success=HTTPCreated, detail=s.UserGroups_POST_CreatedResponseSchema.description, content={ "user_name": user.user_name, "group_name": group.group_name })
def sign_in(request): """ Signs in a user session. """ provider_name = ar.get_value_multiformat_body_checked(request, "provider_name", default=MAGPIE_DEFAULT_PROVIDER) provider_name = provider_name.lower() # magpie supports login from both username or corresponding email # therefore validate pattern combination manually after fetch otherwise email format fails patter match user_name = ar.get_value_multiformat_body_checked(request, "user_name", pattern=None) # bad request if missing pattern = ax.EMAIL_REGEX if "@" in user_name else ax.PARAM_REGEX ax.verify_param(user_name, matches=True, param_compare=pattern, param_name="user_name", http_error=HTTPUnprocessableEntity, msg_on_fail=s.UnprocessableEntityResponseSchema.description) verify_provider(provider_name) if provider_name in MAGPIE_INTERNAL_PROVIDERS.keys(): # password can be None for external login, validate only here as needed password = ar.get_value_multiformat_body_checked(request, "password", pattern=None) # check manually to avoid inserting value in result body # obtain the raw path, without any '/magpie' prefix (if any), let 'application_url' handle it signin_internal_path = request.route_url("ziggurat.routes.sign_in", _app_url="") signin_internal_data = {"user_name": user_name, "password": password, "provider_name": provider_name} signin_sub_request = Request.blank(signin_internal_path, base_url=request.application_url, headers={"Accept": CONTENT_TYPE_JSON}, POST=signin_internal_data) signin_response = request.invoke_subrequest(signin_sub_request, use_tweens=True) if signin_response.status_code == HTTPOk.code: return convert_response(signin_response) login_failure(request, s.Signin_POST_UnauthorizedResponseSchema.description) elif provider_name in MAGPIE_EXTERNAL_PROVIDERS.keys(): return ax.evaluate_call(lambda: process_sign_in_external(request, user_name, provider_name), http_error=HTTPInternalServerError, content={"user_name": user_name, "provider_name": provider_name}, msg_on_fail=s.Signin_POST_External_InternalServerErrorResponseSchema.description)
def get_discoverable_group_by_name(group_name, db_session): # type: (Str, Session) -> models.Group """ Obtains the requested discoverable group by name. .. note:: For security reason, an existing group that is **NOT** discoverable will return NotFound instead of Forbidden. Otherwise we give an indication to a potentially non-admin user that *some group* of that name exists. :return: found group matched by name :raises HTTPNotFound: if the group cannot be found or if matched group name is not discoverable. """ public_groups = get_discoverable_groups(db_session) found_group = ax.evaluate_call( lambda: [grp for grp in public_groups if grp.group_name == group_name], http_error=HTTPNotFound, msg_on_fail=s.RegisterGroup_NotFoundResponseSchema.description, content={"group_name": group_name}) ax.verify_param( found_group, param_name="group_name", not_empty=True, http_error=HTTPNotFound, content_type=CONTENT_TYPE_JSON, msg_on_fail=s.RegisterGroup_NotFoundResponseSchema.description) return found_group[0]
def get_permission_multiformat_body_checked(request, service_or_resource): # type: (Request, ServiceOrResourceType) -> PermissionSet """ Retrieves the permission from the body and validates that it is allowed for the specified `service` or `resource`. Validation combines basic field checks followed by contextual values applicable for the `service` or `resource`. The permission can be provided either by literal string name (explicit or implicit format) or JSON object. .. seealso:: - :func:`get_value_multiformat_body_checked` """ # import here to avoid circular import error with undefined functions between (api_request, resource_utils) from magpie.api.management.resource.resource_utils import check_valid_service_or_resource_permission perm_key = "permission" permission = get_multiformat_body(request, perm_key) if not permission: perm_key = "permission_name" permission = get_multiformat_body(request, perm_key) if isinstance(permission, six.string_types): check_value(permission, perm_key) elif isinstance(permission, dict) and len(permission): for perm_sub_key, perm_sub_val in permission.items(): if perm_sub_val is not None: check_value(perm_sub_val, "{}.{}".format(perm_key, perm_sub_key)) else: ax.raise_http(http_error=HTTPBadRequest, content={perm_key: str(permission)}, detail=s.Permission_Check_BadRequestResponseSchema.description) perm = ax.evaluate_call(lambda: PermissionSet(permission), http_error=HTTPUnprocessableEntity, content={perm_key: str(permission)}, msg_on_fail=s.UnprocessableEntityResponseSchema.description) check_valid_service_or_resource_permission(perm.name, service_or_resource, request.db) return perm
def login_failure(request, reason=None): """ Response from redirect upon login failure, either because of invalid or incorrect user credentials. .. seealso:: - :func:`sign_in` """ http_err = HTTPUnauthorized if reason is None: reason = s.Signin_POST_UnauthorizedResponseSchema.description try: user_name = ar.get_value_multiformat_body_checked(request, "user_name", default=None) ar.get_value_multiformat_body_checked(request, "password", default=None, pattern=None) except HTTPException: http_err = HTTPBadRequest reason = s.Signin_POST_BadRequestResponseSchema.description else: user_name_list = ax.evaluate_call( lambda: [user.user_name for user in UserService.all(models.User, db_session=request.db)], fallback=lambda: request.db.rollback(), http_error=HTTPForbidden, msg_on_fail=s.Signin_POST_ForbiddenResponseSchema.description) if user_name in user_name_list: http_err = HTTPInternalServerError reason = s.Signin_POST_Internal_InternalServerErrorResponseSchema.description content = ag.get_request_info(request, default_message=s.Signin_POST_UnauthorizedResponseSchema.description) content.setdefault("detail", str(reason)) ax.raise_http(http_error=http_err, content=content, detail=s.Signin_POST_UnauthorizedResponseSchema.description)
def sign_in(request): """ Signs in a user session. """ provider_name = get_value_multiformat_post_checked(request, "provider_name", default=MAGPIE_DEFAULT_PROVIDER) provider_name = provider_name.lower() user_name = get_value_multiformat_post_checked(request, "user_name") password = get_multiformat_post(request, "password") # no check since password is None for external login verify_provider(provider_name) if provider_name in MAGPIE_INTERNAL_PROVIDERS.keys(): # obtain the raw path, without any '/magpie' prefix (if any), let 'application_url' handle it signin_internal_path = request.route_url("ziggurat.routes.sign_in", _app_url="") signin_internal_data = {u"user_name": user_name, u"password": password, u"provider_name": provider_name} signin_sub_request = Request.blank(signin_internal_path, base_url=request.application_url, headers={"Accept": CONTENT_TYPE_JSON}, POST=signin_internal_data) signin_response = request.invoke_subrequest(signin_sub_request, use_tweens=True) if signin_response.status_code == HTTPOk.code: return convert_response(signin_response) login_failure(request, s.Signin_POST_UnauthorizedResponseSchema.description) elif provider_name in MAGPIE_EXTERNAL_PROVIDERS.keys(): return ax.evaluate_call(lambda: process_sign_in_external(request, user_name, provider_name), httpError=HTTPInternalServerError, content={u"user_name": user_name, u"provider_name": provider_name}, msgOnFail=s.Signin_POST_External_InternalServerErrorResponseSchema.description)
def format_resource(resource, permissions=None, basic_info=False): """ Formats the ``resource`` information into JSON. """ def fmt_res(res, perms, info): result = { u"resource_name": str(res.resource_name), u"resource_display_name": str(res.resource_display_name or res.resource_name), u"resource_type": str(res.resource_type), u"resource_id": res.resource_id } if not info: result.update({ u"parent_id": res.parent_id, u"root_service_id": res.root_service_id, u"children": {}, u"permission_names": list() if perms is None else format_permissions(perms) }) return result return evaluate_call( lambda: fmt_res(resource, permissions, basic_info), httpError=HTTPInternalServerError, msgOnFail="Failed to format resource.", content={u"resource": repr(resource), u"permissions": repr(permissions), u"basic_info": str(basic_info)} )
def get_user_service_permissions_view(request): """ List all permissions a user has on a service. """ user = ar.get_user_matchdict_checked_or_logged(request) service = ar.get_service_matchdict_checked(request) inherit_groups_perms = asbool(ar.get_query_param(request, "inherit")) perms = ax.evaluate_call( lambda: uu.get_user_service_permissions(service=service, user=user, request=request, inherit_groups_permissions= inherit_groups_perms), fallback=lambda: request.db.rollback(), httpError=HTTPNotFound, msgOnFail=s.UserServicePermissions_GET_NotFoundResponseSchema. description, content={ u"service_name": str(service.resource_name), u"user_name": str(user.user_name) }) return ax.valid_http( httpSuccess=HTTPOk, detail=s.UserServicePermissions_GET_OkResponseSchema.description, content={u"permission_names": sorted(p.value for p in perms)})
def get_group_resource_permissions_response(group, resource, db_session): # type: (models.Group, models.Resource, Session) -> HTTPException """ Get validated response with group resource permissions as content. :returns: valid HTTP response on successful operations. :raises HTTPException: error HTTP response of corresponding situation. """ def get_grp_res_perms(grp, res, db): if res.owner_group_id == grp.id: # FIXME: no 'magpie.models.Resource.permissions' - ok for now because no owner handling... return models.RESOURCE_TYPE_DICT[res.type].permissions perms = db.query(models.GroupResourcePermission) \ .filter(models.GroupResourcePermission.resource_id == res.resource_id) \ .filter(models.GroupResourcePermission.group_id == grp.id) return [PermissionSet(p, typ=PermissionType.APPLIED) for p in perms] group_permissions = ax.evaluate_call( lambda: format_permissions( get_grp_res_perms(group, resource, db_session), PermissionType. APPLIED), http_error=HTTPInternalServerError, msg_on_fail=s. GroupResourcePermissions_InternalServerErrorResponseSchema.description, content={ "group": repr(group), "resource": repr(resource) }) return ax.valid_http( http_success=HTTPOk, detail=s.GroupResourcePermissions_GET_OkResponseSchema.description, content=group_permissions)
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)
def format_group(group, basic_info=False, public_info=False, db_session=None): # type: (Group, bool, bool, Optional[Session]) -> JSON """ Obtains the JSON formatted group definition according to field selection flags. :param group: Group for which to provide details. :param 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}``). :param 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. :param db_session: Database connection to retrieve additional details (required when ``public_info=False``). """ def fmt_grp(grp, is_basic, is_public): info = {"group_name": str(grp.group_name)} if not is_public: info["group_id"] = grp.id if is_basic: return info info["description"] = str(grp.description) if grp.description else None if is_public: return info info["discoverable"] = grp.discoverable info["priority"] = grp.priority info["member_count"] = grp.get_member_count(db_session) info["user_names"] = [usr.user_name for usr in grp.users] return info return evaluate_call(lambda: fmt_grp(group, basic_info, public_info), http_error=HTTPInternalServerError, msg_on_fail="Failed to format group.", content={"group": repr(group)})
def update_user_view(request): """ Update user information by user name. """ user_name = ar.get_value_matchdict_checked(request, key="user_name") ax.verify_param( user_name, paramCompare=get_constant("MAGPIE_LOGGED_USER"), notEqual=True, httpError=HTTPBadRequest, paramName="user_name", content={u"user_name": user_name}, msgOnFail=s.Service_PUT_BadRequestResponseSchema_ReservedKeyword. description) user = ar.get_user_matchdict_checked(request, user_name_key="user_name") new_user_name = ar.get_multiformat_post(request, "user_name", default=user.user_name) new_email = ar.get_multiformat_post(request, "email", default=user.email) new_password = ar.get_multiformat_post(request, "password", default=user.user_password) uu.check_user_info(new_user_name, new_email, new_password, group_name=new_user_name) update_username = user.user_name != new_user_name update_password = user.user_password != new_password update_email = user.email != new_email ax.verify_param(any([update_username, update_password, update_email]), isTrue=True, httpError=HTTPBadRequest, content={u"user_name": user.user_name}, msgOnFail=s.User_PUT_BadRequestResponseSchema.description) if user.user_name != new_user_name: existing_user = ax.evaluate_call( lambda: UserService.by_user_name(new_user_name, db_session=request.db), fallback=lambda: request.db.rollback(), httpError=HTTPForbidden, msgOnFail=s.User_PUT_ForbiddenResponseSchema.description) ax.verify_param( existing_user, isNone=True, httpError=HTTPConflict, msgOnFail=s.User_PUT_ConflictResponseSchema.description) user.user_name = new_user_name if user.email != new_email: user.email = new_email if user.user_password != new_password and new_password is not None: UserService.set_password(user, new_password) UserService.regenerate_security_code(user) return ax.valid_http(httpSuccess=HTTPOk, detail=s.Users_PUT_OkResponseSchema.description)