def open(self): if EventSocket.closing: self.close(reason="Shutting down") return # We can't go though the 'normal' BaseHandler exception translation try: check_permission(self.current_user, [Permissions.EVENT_READ]) except (HTTPError, RequestForbidden) as ex: self.close(reason=str(ex)) return EventSocket.listeners.add(self)
def patch(self): """ --- summary: Initiate a rescan of the plugin directory description: | The body of the request needs to contain a set of instructions detailing the operations to perform. Currently the only operation supported is `rescan`: ```JSON { "operations": [ { "operation": "rescan" } ] } ``` * Will remove from the registry and database any currently stopped plugins who's directory has been removed. * Will add and start any new plugin directories. parameters: - name: patch in: body required: true description: Instructions for operations schema: $ref: '#/definitions/Patch' responses: 204: description: Rescan successfully initiated 50x: $ref: '#/definitions/50xError' tags: - Admin """ operations = self.parser.parse_patch( self.request.decoded_body, many=True, from_string=True ) for op in operations: if op.operation == "rescan": check_permission(self.current_user, [Permissions.SYSTEM_CREATE]) with thrift_context() as client: yield client.rescanSystemDirectory() else: error_msg = "Unsupported operation '%s'" % op.operation self.logger.warning(error_msg) raise ModelValidationError(error_msg) self.set_status(204)
def get(self, user_identifier): """ --- summary: Retrieve a specific User parameters: - name: user_identifier in: path required: true description: The ID or name of the User type: string responses: 200: description: User with the given ID schema: $ref: '#/definitions/User' 404: $ref: '#/definitions/404Error' 50x: $ref: '#/definitions/50xError' tags: - Users """ if user_identifier == "anonymous": principal = brew_view.anonymous_principal else: # Need fine-grained access control here if user_identifier not in [ str(self.current_user.id), self.current_user.username, ]: check_permission(self.current_user, [Permissions.USER_READ]) try: principal = Principal.objects.get(id=str(user_identifier)) except (DoesNotExist, ValidationError): principal = Principal.objects.get( username=str(user_identifier)) principal.permissions = coalesce_permissions(principal.roles)[1] self.write(MongoParser.serialize_principal(principal, to_string=False))
def patch(self, user_id): """ --- summary: Partially update a User description: | The body of the request needs to contain a set of instructions detailing the updates to apply: ```JSON { "operations": [ { "operation": "add", "path": "/roles", "value": "admin" } ] } ``` parameters: - name: user_id in: path required: true description: The ID of the User type: string - name: patch in: body required: true description: Instructions for how to update the User schema: $ref: '#/definitions/Patch' responses: 200: description: User with the given ID schema: $ref: '#/definitions/User' 400: $ref: '#/definitions/400Error' 404: $ref: '#/definitions/404Error' 50x: $ref: '#/definitions/50xError' tags: - Users """ principal = Principal.objects.get(id=str(user_id)) operations = MongoParser.parse_patch(self.request.decoded_body, many=True, from_string=True) # Most things only need a permission check if updating a different user if user_id != str(self.current_user.id): check_permission(self.current_user, [Permissions.USER_UPDATE]) for op in operations: if op.path == "/roles": # Updating roles always requires USER_UPDATE check_permission(self.current_user, [Permissions.USER_UPDATE]) try: if op.operation == "add": principal.roles.append(Role.objects.get(name=op.value)) elif op.operation == "remove": principal.roles.remove(Role.objects.get(name=op.value)) elif op.operation == "set": principal.roles = [ Role.objects.get(name=name) for name in op.value ] else: raise ModelValidationError( "Unsupported operation '%s'" % op.operation) except DoesNotExist: raise ModelValidationError("Role '%s' does not exist" % op.value) elif op.path == "/username": if op.operation == "update": principal.username = op.value else: raise ModelValidationError("Unsupported operation '%s'" % op.operation) elif op.path == "/password": if op.operation != "update": raise ModelValidationError("Unsupported operation '%s'" % op.operation) if isinstance(op.value, dict): current_password = op.value.get("current_password") new_password = op.value.get("new_password") else: current_password = None new_password = op.value if user_id == str(self.current_user.id): if current_password is None: raise ModelValidationError( "In order to update your own password, you must provide " "your current password") if not custom_app_context.verify(current_password, self.current_user.hash): raise RequestForbidden("Invalid password") principal.hash = custom_app_context.hash(new_password) if "changed" in principal.metadata: principal.metadata["changed"] = True elif op.path == "/preferences/theme": if op.operation == "set": principal.preferences["theme"] = op.value else: raise ModelValidationError("Unsupported operation '%s'" % op.operation) else: raise ModelValidationError("Unsupported path '%s'" % op.path) principal.save() principal.permissions = coalesce_permissions(principal.roles)[1] self.write(MongoParser.serialize_principal(principal, to_string=False))
def patch(self, user_id): """ --- summary: Partially update a User description: | The body of the request needs to contain a set of instructions detailing the updates to apply: ```JSON { "operations": [ { "operation": "add", "path": "/roles", "value": "admin" } ] } ``` parameters: - name: user_id in: path required: true description: The ID of the User type: string - name: patch in: body required: true description: Instructions for how to update the User schema: $ref: '#/definitions/Patch' responses: 200: description: User with the given ID schema: $ref: '#/definitions/User' 400: $ref: '#/definitions/400Error' 404: $ref: '#/definitions/404Error' 50x: $ref: '#/definitions/50xError' tags: - Users """ principal = Principal.objects.get(id=str(user_id)) operations = BeerGardenSchemaParser.parse_patch( self.request.decoded_body, many=True, from_string=True ) for op in operations: if op.path == '/roles': check_permission(self.current_user, [Permissions.USER_UPDATE]) try: if op.operation == 'add': principal.roles.append(Role.objects.get(name=op.value)) elif op.operation == 'remove': principal.roles.remove(Role.objects.get(name=op.value)) elif op.operation == 'set': principal.roles = [Role.objects.get(name=name) for name in op.value] else: raise ModelValidationError("Unsupported operation '%s'" % op.operation) except DoesNotExist: raise ModelValidationError("Role '%s' does not exist" % op.value) elif op.path == '/preferences/theme': if user_id != self.current_user.id: check_permission(self.current_user, [Permissions.USER_UPDATE]) if op.operation == 'set': principal.preferences['theme'] = op.value else: raise ModelValidationError("Unsupported operation '%s'" % op.operation) else: check_permission(self.current_user, [Permissions.USER_UPDATE]) raise ModelValidationError("Unsupported path '%s'" % op.path) principal.save() self.write(BeerGardenSchemaParser.serialize_principal(principal, to_string=False))