예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
    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))
예제 #4
0
    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))
예제 #5
0
    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))