def resolve_permissions( self, user, project_id: fields.Integer(minimum=1) ) -> fields.List(fields.String()): permissions = (UserPermissionLinker.query.filter_by( project_id=project_id, user_id=user.id).join( UserPermissionLinker.permission).with_entities( Permission.slug).all()) permissions = list(map(lambda x: x.slug, permissions)) return permissions
class Schema(object): users = fields.List(CONCISE_USER_SCHEMA, description='The individual users in a group.', io='r') roles = fields.Custom( ROLE_MAP_SCHEMA, description='The role(s) that all members of the group possess', attribute='roles', formatter=role_list_as_map, default=[], io='r', )
class Schema(object): name = fields.String(description='The unique name of the resource.') resourceType = fields.Custom( fields.String(), attribute='resource_type', converter=None, formatter=lambda rsc_type: rsc_type.name.name, title='resourceType', description='The string representation of the resource type.', io='r', ) users = fields.List( CONCISE_USER_SCHEMA, description= 'The user(s) that hold one or more roles for this resource.', io='r', ) groups = fields.List( CONCISE_GROUP_SCHEMA, description= 'The group(s) that hold one or more roles for this resource.', io='r', )
class Schema(object): permissions = fields.List( PERMISSION_SCHEMA, title='Role Permissions', description='The permissions the role has.', ) resourceType = fields.Custom( fields.String(), attribute='resource_type', converter=None, formatter=lambda rsc_type: rsc_type.name.name, title='resourceType', description='The resource type this role is associated with.', io='r', )
def session_timed_log( self, session_uuid: fields.UUID()) -> fields.List(fields.String()): session = Session.query.filter(Session.uuid == session_uuid).first() session_base_path = path.session_logs + session.start.date().isoformat().replace('-', '') + '/' + \ session.user.username + '_' + session.host.hostname + '_' + \ session.start.time().isoformat().split('.')[0].replace(':', '') + '_' + \ session_uuid session_log_path = session_base_path + '.log' session_timer_path = session_base_path + '.timer' results = [] session_time = 0. session_seek = 0 with open(session_log_path, 'rb') as session_log: with open(session_timer_path, 'r') as session_timer: session_data = session_log.read() # todo improve this (use csv reader?) lines = session_timer.readlines() for l in lines: rel_time, rel_seek = l.split(' ') rel_time = float(rel_time) rel_seek = int(rel_seek) session_time += rel_time current_seek = session_seek session_seek += rel_seek results.append({ 'session_time': session_time, 'session_seek': session_seek, 'session_size': len(session_data), 'data_size': rel_seek, 'data': base64.b64encode( session_data[current_seek:session_seek]).decode( 'utf-8', 'strict') }) return results
class QueryPolicyResource(PrincipalResource): resource = Relation('resource', io='r') class Meta(object): manager = principals(QueryPolicyManager) model = QueryPolicy natural_key = 'name' excluded_fields = ('id', ) id_attribute = 'resource_id' permissions = {'view_resource': 'view_resource'} filters = {'name': True, 'description': True} class Schema(object): name = fields.String( description= 'A unique human-readable name to denote the query policy.') description = fields.String( description= 'A description of what data the query policy is governing the access to.' ) policyFilters = POLICY_FILTERS_SCHEMA resource = fields.ItemUri( 'web.server.api.permission_api_models.BackendResource', attribute='resource_id', ) # pylint: disable=R0201 # pylint: disable=E1101 # Flask Potion does not allow class methods. @Route.GET( '/enabled_dimensions', rel='getAuthorizableDimensions', response_schema=fields.List( fields.String( description='A dimension for which authorization is enabled.', enum=CONFIG_FILTERS.AUTHORIZABLE_DIMENSIONS, ), description= 'The list of dimensions for which authorization filters will have effect.', ), ) def get_authorizable_dimensions(self): return CONFIG_FILTERS.AUTHORIZABLE_DIMENSIONS @Route.GET( '/dimensions', rel='getAllDimensions', response_schema=fields.List( fields.String(description='A dimension in Druid.', enum=DIMENSIONS), description='The list of all Druid dimensions.', ), ) def get_all_dimensions(self): return DIMENSIONS
from web.server.api.api_models import PrincipalResource from web.server.routes.views.query_policy import QueryPolicyManager from web.server.security.permissions import principals EMPTY_LIST = [] CONFIG_FILTERS = current_app.zen_config.filters DIMENSIONS = list( current_app.druid_context.dimension_values_lookup.get_dimension_value_map( False).keys()) SPECIFIC_VALUES_SCHEMA = fields.List( fields.String(description='An individual dimension value.'), nullable=True, default=EMPTY_LIST, description= 'A list of dimension values that the policy holder will be allowed to or prevented ' 'from querying on. To allow the user to query against all values, you would omit ' 'this field and instead set `allowAllValues` to true.', ) ALL_VALUES_SCHEMA = fields.Boolean( description= 'Set to true if the policy holder should be allowed to query across ALL values ' 'for the specified dimension.', default=False, nullable=True, ) DIMENSION_VALUES_SCHEMA = fields.Object({ 'excludeValues': SPECIFIC_VALUES_SCHEMA,
fields.String( description='The string representation of the resource type.'), } ROLE_NAME_SCHEMA = fields.String( title='roleName', description= 'The string representation of a role name. (e.g. `dashboard_admin`)', ) # The schema for a mapping of resource names to role names # Structure should be # { <resourceName>: [<roleName>, <otherRoleName>], <otherResourceName>: [<roleName>], ... } RESOURCE_MAP_SCHEMA = fields.Object( properties=fields.List( ROLE_NAME_SCHEMA, description='A list of all the roles held for a given resource.', ), pattern_properties={ fields.String(title='resourceName', description='An individual resource.'): fields.List(ROLE_NAME_SCHEMA) }, nullable=False, description='A mapping of resource names to role names. ', ) # The schema representing the role assignments for an individual resource type # Structure should be # { # 'resources': { # <resourceName>: [<roleName>, <otherRoleName>],
DETAILED_DASHBOARD_SCHEMA = alchemy_fields.InlineModel( DASHBOARD_DETAILED_FIELDS, model=Dashboard, description='The dashboard model.' ) USER_URI_SCHEMA = fields.ItemUri('web.server.api.user_api_models.UserResource') HISTORY_CHANGE_SCHEMA = generate_history_record_schema( fields.ItemUri( 'web.server.api.dashboard_api_models.DashboardResource', attribute='object_id' ), 'dashboard', ) DASHBOARD_CHANGES_SCHEMA = fields.List( HISTORY_CHANGE_SCHEMA, description='Dashboard history records' ) # Schemas for properties that are never sent by the user but must be stubbed # out to make flask potion happy. UNUSED_LAST_MODIFIED_SCHEMA = fields.DateTimeString( description='The last time the dashboard was modified.', attribute='last_modified', io='r', ) UNUSED_TOTAL_VIEWS_SCHEMA = fields.Integer( description='The total number of times the dashboard has been viewed.', minimum=0, attribute='total_views', io='r',
def genres( self ) -> fields.List(fields.String, description="A list of genres"): return ['biography', 'history', 'essay', 'law', 'philosophy']
def session_by_command(self, cmd: fields.String(), **kwargs) -> fields.List(fields.Inline('self')): return Session.query.join(Command).filter( Command.cmd.like('%{0}%'.format(cmd)))
class RoleResource(PrincipalResource): '''The potion class for performing CRUD operations on the `Role` class. ''' resourceType = Relation('resource-type', attribute='resource_type', io='r') class Meta(object): model = Role natural_key = 'name' # Read Permissions are the defaults as defined in # `web.server.security.permissions.PERMISSION_DEFAULTS` # # Create, Update and Delete Permissions are enforced by the # Signal Handlers installed when the API for this Resource # are initialized in `web.server.security.signal_handlers.py` filters = { 'name': True, 'resourceType': { None: ResourceTypeFilter, 'eq': ResourceTypeFilter }, } class Schema(object): permissions = fields.List( PERMISSION_SCHEMA, title='Role Permissions', description='The permissions the role has.', ) resourceType = fields.Custom( fields.String(), attribute='resource_type', converter=None, formatter=lambda rsc_type: rsc_type.name.name, title='resourceType', description='The resource type this role is associated with.', io='r', ) # pylint: disable=E1101 @ItemRoute.PATCH( '/permissions', title='Update Role Permissions', description= 'Updates the role\'s permissions with the values specified.', rel='updatePermissions', schema=fields.List( PERMISSION_SCHEMA, title='Updated Permissions', description='The updated role permissions.', ), ) def update_role_permissions(self, role, new_permissions): with AuthorizedOperation('update_permissions', 'role', role.id): self.manager.update(role, {'permissions': new_permissions}) return None, NO_CONTENT @ItemRoute.POST( '/permission', title='Add Role Permission', description='Adds a single permission to a Role.', rel='addPermission', schema=FieldSet({ 'permissionId': fields.Integer( description= 'The id of the new permission to be added to this role.') }), response_schema=UPDATE_ROLE_PERMISSIONS_RESPONSE_SCHEMA, ) def add_single_permision(self, role, permissionId): with AuthorizedOperation('update_permissions', 'role', role.id): new_permission = find_by_id(Permission, permissionId) if not new_permission: raise ItemNotFound('permission', id=permissionId) if new_permission.resource_type_id != role.resource_type_id: error_message = ( 'The resource type associated with the permission ' 'must match the resource type of the role.') return ( StandardResponse( error_message, BAD_REQUEST, False, roleResourceType=new_permission.resource_type, permissionResourceType=role.resource_type, ), BAD_REQUEST, ) exists = True if new_permission not in role.permissions: exists = False role.permissions.append(new_permission) self.manager.update(role, {'permissions': role.permissions}) added_message = 'already exists for' if exists else 'has been added' success_message = 'Permission \'%s\' %s to Role \'%s\'.' % ( new_permission.permission, added_message, role.name, ) return StandardResponse(success_message, OK, True) @ItemRoute.DELETE( '/permission', title='Delete Role Permission', description='Deletes a single permission from a role.', schema=FieldSet({ 'permissionId': fields.Integer( description= 'The id of the new permission to be deleted from this role.') }), response_schema=UPDATE_ROLE_PERMISSIONS_RESPONSE_SCHEMA, rel='deletePermission', ) def delete_individual_permission(self, role, permissionId): with AuthorizedOperation('update_permissions', 'role', role.id): old_permission = find_by_id(Permission, permissionId) if not old_permission: raise ItemNotFound('permission', id=permissionId) if old_permission.resource_type_id != role.resource_type_id: error_message = ( 'The resource type associated with the permission ' 'must match the resource type of the role.') return ( StandardResponse( error_message, BAD_REQUEST, False, roleResourceType=old_permission.resource_type, permissionResourceType=role.resource_type, ), BAD_REQUEST, ) exists = True try: role.permissions.remove(old_permission) self.manager.update(role, {'permissions': role.permissions}) except ValueError: exists = False deleted_message = ('has been removed from' if exists else 'does not exist for') success_message = 'Permission \'%s\' %s Role \'%s\'.' % ( old_permission.permission, deleted_message, role.name, ) return StandardResponse(success_message, OK, True)
nullable=True, ), 'permissionResourceType': alchemy_fields.InlineModel( RESOURCE_TYPE_FIELDS, description='The Resource type corresponding to the Permission.', model=ResourceType, nullable=True, ), } UPDATE_ROLE_PERMISSIONS_RESPONSE_SCHEMA = augment_standard_schema( ROLE_PERMISSIONS_FIELDS) ROLE_LIST_SCHEMA = fields.List( ROLE_NAME_SCHEMA, title='roles', description='A listing of roles held by a user or security group on an ' 'indvidual resource or all resources of a specific type.', ) DEFAULT_ROLE_SCHEMA = fields.Object({ 'roleName': ROLE_NAME_SCHEMA, 'applyToUnregistered': fields.Boolean( nullable=False, description= 'Indicates whether or not this role only applies to registered users. If ' 'set to `false` it only applies to registered users. If set to `false`, it ' 'applies to unregistered/anonymous users as well as long as public access ' 'is enabled.', ),
class GroupResource(PrincipalResource): '''The potion class for performing CRUD operations on the `Group` class. ''' users = Relation('user', io='r') class Meta(object): name = 'group' title = 'Groups API' description = ( 'The API through which CRUD operations can be performed on User Groups.' ) model = Group natural_key = 'name' filters = {'name': True} # Read Permissions are the defaults as defined in # `web.server.security.permissions.PERMISSION_DEFAULTS` # # Create, Update and Delete Permissions are enforced by the # Signal Handlers installed when the API for this Resource # are initialized in `web.server.security.signal_handlers.py` class Schema(object): users = fields.List(CONCISE_USER_SCHEMA, description='The individual users in a group.', io='r') roles = fields.Custom( ROLE_MAP_SCHEMA, description='The role(s) that all members of the group possess', attribute='roles', formatter=role_list_as_map, default=[], io='r', ) # Flask-Potion requires that these be methods and NOT functions # pylint: disable=R0201 @ItemRoute.POST( '/roles', title='Add Group Role', description='Adds a single role to a group.', schema=GROUP_ROLES_SCHEMA, response_schema=STANDARD_RESPONSE_SCHEMA, rel='addRole', ) def add_role_by_name(self, group, request): with AuthorizedOperation('edit_resource', 'group', group.id): role_name = request['roleName'] resource_name = request.get('resourceName') resource_type = request['resourceType'] (_, exists) = add_group_role(group, role_name, resource_type, resource_name) action = 'already exists' if exists else 'has been added' message = 'Role \'%s\' %s for %s' % ( role_name, action, get_resource_string(resource_name, resource_type), ) g.request_logger.info(message) response_code = OK if exists else CREATED return (StandardResponse(message, response_code, True), response_code) # Flask-Potion requires that these be methods and NOT functions # pylint: disable=R0201 @ItemRoute.PATCH( '/roles', title='Update Group Roles', description= 'Updates all the roles for a group with the values specified.', schema=ROLE_MAP_SCHEMA, response_schema=STANDARD_RESPONSE_SCHEMA, rel='updateRoles', ) def update_roles(self, group, request): with AuthorizedOperation('edit_resource', 'group', group.id): roles = update_group_roles_from_map(group, request) message = ( 'Successfully updated the roles attached to group \'%s\'. ' 'New roles are now: \'%s\'' % (group.name, [group_role_as_dictionary(role) for role in roles])) g.request_logger.info(message) return StandardResponse(message, OK, True) # Flask-Potion requires that these be methods and NOT functions # pylint: disable=R0201 @ItemRoute.DELETE( '/roles', title='Delete Group Role', description='Deletes a single role from a group.', schema=GROUP_ROLES_SCHEMA, response_schema=STANDARD_RESPONSE_SCHEMA, rel='deleteRole', ) def delete_role_by_name(self, group, request): with AuthorizedOperation('edit_resource', 'group', group.id): role_name = request['roleName'] resource_name = request['resourceName'] resource_type = request['resourceType'] (_, exists) = delete_group_role(group, role_name, resource_type, resource_name) action = 'has been deleted' if exists else 'does not exist' message = 'Role \'%s\' %s for %s' % ( role_name, action, get_resource_string(resource_name, resource_type), ) g.request_logger.info(message) return StandardResponse(message, OK, True) @ItemRoute.PATCH( '/users', title='Update Group Users', description= 'Updates the users that are currently in the group with the values specified.', schema=fields.List( fields.String(title='username', description='The user\'s username')), response_schema=STANDARD_RESPONSE_SCHEMA, rel='updateUsers', ) def update_users(self, group, request): with AuthorizedOperation('edit_resource', 'group', group.id): users = update_group_users(group, request) directory_listing = [ get_user_string(user, include_ip=False) for user in users ] message = ( 'Updated the member list for group \'%s\'. The current users are \'%s\'.' % (group.name, directory_listing)) g.request_logger.info(message) return StandardResponse(message, OK, True) @ItemRoute.POST( '/users', title='Add Group User', description='Adds a user to the group.', schema=fields.String(title='username', description='The user\'s username'), response_schema=STANDARD_RESPONSE_SCHEMA, rel='addUser', ) def add_user_by_username(self, group, request): with AuthorizedOperation('edit_resource', 'group', group.id): user, exists = add_group_user(group, request) action = ('has been added to the member list of' if exists else 'is already a member of') message = 'User \'%s\' %s group \'%s\'. ' % ( get_user_string(user, include_ip=False), action, group.name, ) g.request_logger.info(message) return StandardResponse(message, OK if exists else CREATED, True) @ItemRoute.DELETE( '/users', title='Delete Group User', description='Deletes a user from the group.', schema=fields.String(title='username', description='The user\'s username'), response_schema=STANDARD_RESPONSE_SCHEMA, rel='deleteUser', ) def delete_user_by_username(self, group, request): with AuthorizedOperation('edit_resource', 'group', group.id): user, exists = delete_group_user(group, request) action = ('has been deleted from the member list of' if exists else 'is not a member of') message = 'User \'%s\' %s group \'%s\'. ' % ( get_user_string(user, include_ip=False), action, group.name, ) g.request_logger.info(message) return StandardResponse(message, OK, True)
class UserResource(PrincipalResource): '''The potion class for performing CRUD operations on the `User` class. ''' class Meta(object): title = 'Users API' description = ( 'The API through which CRUD operations can be performed on User(s).' ) model = User natural_key = 'username' permissions = {'read': 'yes'} # Read Permissions are the defaults as defined in # `web.server.security.permissions.PERMISSION_DEFAULTS` # # Create, Update and Delete Permissions are enforced by the # Signal Handlers installed when the API for this Resource # are initialized in `web.server.security.signal_handlers.py` # Allow users to filter resources by name, username, status, and phone filters = { 'username': True, 'status': True, 'firstName': True, 'lastName': True, 'phoneNumber': True, } exclude_fields = ('password', 'reset_password_token') class Schema(object): username = USERNAME_SCHEMA roles = fields.Custom( ROLE_MAP_SCHEMA, description='The role(s) that the user currently possesses.', attribute='roles', formatter=role_list_as_map, default=[], ) firstName = fields.String( description='The first name of the user.', attribute='first_name', pattern=INTERNATIONALIZED_ALPHANUMERIC_AND_DELIMITER, ) lastName = fields.String( description='The last name of the user.', attribute='last_name', pattern=INTERNATIONALIZED_ALPHANUMERIC_AND_DELIMITER_OR_EMPTY, ) phoneNumber = fields.String( description='The phone number of the user.', attribute='phone_number') # Disabling this warning because Hyper-Schema is enforcing # that the value of this field MUST match one of the values # of the Enum. # pylint:disable=E1136 # pylint: disable=E1101 status = fields.Custom( fields.String(enum=USER_STATUSES), attribute='status_id', formatter=lambda status_id: UserStatusEnum(status_id).name.lower(), converter=lambda status_value: UserStatusEnum[status_value.upper()] .value, default=UserStatusEnum.ACTIVE.value, nullable=False, ) # The parameter is coming directly from the API which uses camelCase instead of # snake_case # pylint: disable=C0103 # pylint: disable=E1101 @ItemRoute.POST( '/password', title='Update User Password', description= 'Updates the user\'s password with the new value specified.', rel='updatePassword', schema=FieldSet({ 'newPassword': fields.String( min_length=10, max_length=255, description='The new password for the user.', ) }), ) def update_password(self, user, newPassword): # TODO(vedant) Refactor this into a separate module like # we do for the Groups API with AuthorizedOperation('change_password', 'user', user.id): hashed_password = current_app.user_manager.hash_password( newPassword) self.manager.update(user, {'password': hashed_password}) return None, NO_CONTENT @ItemRoute.POST( '/reset_password', title='Reset User Password', description= 'Resets the user\'s password and sends them a password reset email.', rel='resetPassword', schema=None, response_schema=None, ) def reset_password(self, user): with AuthorizedOperation('reset_password', 'user', user.id): # TODO(vedant) - Change the return value of `reset_password` to convey a value # with more resolution than True/False username = user.username # TODO(vedant) - This is for legacy users who signed up with usernames that do # not represent an e-mail address if not EMAIL_REGEX.match(username): message = 'User {username} does not have a valid e-mail address.'.format( username=username) return StandardResponse(message, BAD_REQUEST, False), BAD_REQUEST send_reset_password(username) message = ('User password has been reset and instructions ' 'e-mailed to {username}.'.format(username=username)) g.request_logger.info(message) return None, NO_CONTENT @ItemRoute.DELETE( '/force', rel='forceDestroy', title='Force Delete User', description= 'Force delete a User and ALL their created artifacts (Dashboards, etc.)', ) def force_delete(self, user): with AuthorizedOperation('delete_resource', 'user', user.id): before_delete.send(user) force_delete_user(user) after_delete.send(user) return None, NO_CONTENT @Route.POST( '/invite', title='Invite New User', description='', rel='inviteUser', schema=fields.List(INVITE_OBJECT_SCHEMA), response_schema=fields.List( fields.Inline('self'), description='A listing of all the invited users'), ) def invite_user(self, invitees): with AuthorizedOperation('invite_user', 'site', ROOT_SITE_RESOURCE_ID): invited_users = [invitee.email for invitee in invitees] try: pending_users = invite_users(invitees) emails = [user.username for user in pending_users] g.request_logger.info( 'Successfully invited the following users: \'%s\'.', emails) return pending_users except UserAlreadyInvited as e: g.request_logger.error( 'Attempt to invite the following users has failed: \'%s\'. ' 'The following users already have platform accounts: \'%s\'', invited_users, e.already_registered_users, ) raise # Flask-Potion requires that these be methods and NOT functions # pylint: disable=R0201 # pylint: disable=E1101 @ItemRoute.POST( '/roles', title='Add User Role', description='Adds a single role to a user.', schema=USER_ROLES_SCHEMA, response_schema=STANDARD_RESPONSE_SCHEMA, rel='addRole', ) def add_role_by_name(self, user, request): with AuthorizedOperation('edit_resource', 'user', user.id): # TODO(vedant) Refactor this into a separate module like # we do for the Groups API role_name = request['roleName'] resource_type = request['resourceType'] resource_name = request.get('resourceName') result = add_user_role_api(user, role_name, resource_type, resource_name, commit=True) success = False if isinstance(result, Success): success = True response_code = OK if success else BAD_REQUEST return ( StandardResponse(result['data']['message'], response_code, success), response_code, ) # Flask-Potion requires that these be methods and NOT functions # pylint: disable=R0201 @ItemRoute.DELETE( '/roles', title='Delete User Role', description='Deletes a single role from a user.', schema=USER_ROLES_SCHEMA, response_schema=STANDARD_RESPONSE_SCHEMA, rel='deleteRole', ) def delete_role_by_name(self, user, request): with AuthorizedOperation('edit_resource', 'user', user.id): # TODO(vedant) Refactor this into a separate module like # we do for the Groups API role_name = request['roleName'] resource_type = request['resourceType'] resource_name = request.get('resourceName') result = delete_user_role_api(user, role_name, resource_type, resource_name, commit=True) return StandardResponse(result['data']['message'], OK, True) @ItemRoute.PATCH( '/roles', title='Update User Roles', description= 'Updates all the roles for a user with the values specified.', schema=ROLE_MAP_SCHEMA, response_schema=fields.Inline('self'), rel='updateRoles', ) def update_roles(self, user, request): with AuthorizedOperation('edit_resource', 'user', user.id): roles = update_user_roles_from_map(user, request) message = ( 'Successfully updated the roles attached to user \'%s\'. ' 'New roles are now: \'%s\'' % (user.username, [user_role_as_dictionary(role) for role in roles])) g.request_logger.info(message) return self.manager.read(user.id) @Route.GET( '/default/roles', title='Get Default User Role(s)', description= 'Gets all role(s) that are possessed by all registered users and optionally, ' 'unregistered users.', rel='getDefaultRoles', ) @authorization_required('view_resource', 'user', is_api_request=True) def list_default_roles(self): return StandardResponse( 'Successfully retrieved a listing of all public roles. ', OK, True, roles=role_list_as_map(list_default_roles()), ) @Route.POST( '/default/roles', title='Add Default User Role', description= 'Adds a single role to a user that will apply to all registered users and ' 'optionally, unregistered users.', schema=DEFAULT_ROLES_SCHEMA, rel='addDefaultRole', ) @authorization_required('edit_resource', 'user', is_api_request=True) def add_default_role_by_name(self, request): role_name = request['roleName'] resource_type = request['resourceType'] resource_name = request.get('resourceName') (_, exists) = add_default_role(role_name, resource_type, resource_name) action = 'has been added' if exists else 'already exists' message = 'Role \'%s\' %s for %s' % ( role_name, action, get_resource_string(resource_name, resource_type), ) g.request_logger.info(message) response_code = OK if exists else CREATED return (StandardResponse(message, response_code, True), response_code) @Route.DELETE( '/default/roles', title='Delete Default User Role', description= 'Deletes a single role from a user that will apply to both anonymous ' '(unregistered) as well as registered users.', schema=DEFAULT_ROLES_SCHEMA, response_schema=STANDARD_RESPONSE_SCHEMA, rel='deletePublicRole', ) @authorization_required('delete_resource', 'user', is_api_request=True) def delete_default_role_by_name(self, request): role_name = request['roleName'] resource_type = request['resourceType'] resource_name = request.get('resourceName') (_, exists) = delete_default_role(role_name, resource_type, resource_name) action = 'has been deleted' if exists else 'does not exist' message = 'Role \'%s\' %s for %s' % ( role_name, action, get_resource_string(resource_name, resource_type), ) g.request_logger.info(message) return StandardResponse(message, OK, True)