예제 #1
0
    def delete(self, name):
        """
        ---
        summary: Delete group
        description: |
            Remove group from database.

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
        responses:
            200:
                description: When group was removed successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            403:
                description: When user doesn't have `manage_users` capability.
            404:
                description: When group doesn't exist
            503:
                description: |
                    Request canceled due to database statement timeout.
        """
        group = (db.session.query(Group).filter(Group.name == name)).first()

        if group is None:
            raise NotFound("No such group")

        if group.immutable is True:
            raise Forbidden(
                f"Group '{name}' is immutable and can't be removed.")

        db.session.delete(group)
        db.session.commit()

        hooks.on_removed_group(group)
        logger.info("Group was deleted", extra={"group": name})
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": name})
예제 #2
0
    def post(self, name):
        """
        ---
        summary: Create a new group
        description: |
            Creates a new group.

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
        requestBody:
            description: Group information
            content:
              application/json:
                schema: GroupCreateRequestSchema
        responses:
            200:
                description: When group was created successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When group name or request body is invalid
            403:
                description: When user doesn't have `manage_users` capability
            409:
                description: When group exists yet
        """
        schema = GroupCreateRequestSchema()
        obj = loads_schema(request.get_data(as_text=True), schema)

        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())

        if db.session.query(
                exists().where(Group.name == group_name_obj["name"])).scalar():
            raise Conflict("Group exists yet")

        group = Group(name=group_name_obj["name"],
                      capabilities=obj["capabilities"])
        db.session.add(group)
        db.session.commit()

        logger.info(
            "Group created",
            extra={
                "group": group.name,
                "capabilities": group.capabilities
            },
        )
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": name})
예제 #3
0
    def delete(self, name, login):
        """
        ---
        summary: Delete member from group
        description: |
            Removes member from existing group.

            Works only for user-defined groups (excluding private and 'public')

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
            - in: path
              name: login
              schema:
                type: string
              description: Member login
        responses:
            200:
                description: When member was removed successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When request body is invalid
            403:
                description: When user doesn't have `manage_users` capability, group is immutable or user is pending
            404:
                description: When user or group doesn't exist
        """
        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())

        user_login_obj = load_schema({"login": login}, UserLoginSchemaBase())

        member = db.session.query(User).filter(User.login == login).first()
        if member is None:
            raise NotFound("No such user")

        if member.pending:
            raise Forbidden("User is pending and need to be accepted first")

        group = db.session.query(Group).options(joinedload(
            Group.users)).filter(Group.name == name).first()
        if group is None:
            raise NotFound("No such group")

        if group.immutable:
            raise Forbidden(
                "Removing members from private or public group is not allowed")

        group.users.remove(member)
        member.reset_sessions()
        db.session.commit()

        logger.info('Group member deleted',
                    extra={
                        'user': member.login,
                        'group': group.name
                    })
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": name})
예제 #4
0
    def put(self, name):
        """
        ---
        summary: Update group name and capabilities
        description: |
            Updates group name and capabilities.

            Works only for user-defined groups (excluding private and 'public')

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
        requestBody:
            description: Group information
            content:
              application/json:
                schema: GroupUpdateRequestSchema
        responses:
            200:
                description: When group was updated successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When group name or request body is invalid
            403:
                description: When user doesn't have `manage_users` capability or group is immutable
            404:
                description: When group doesn't exist
        """
        schema = GroupUpdateRequestSchema()
        obj = loads_schema(request.get_data(as_text=True), schema)

        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())

        group = db.session.query(Group).filter(Group.name == name).first()
        if group is None:
            raise NotFound("No such group")

        if obj["name"] is not None:
            if obj["name"] != name and group.immutable:
                raise Forbidden(
                    "Renaming group not allowed - group is immutable")
            group.name = obj["name"]

        if obj["capabilities"] is not None:
            group.capabilities = obj["capabilities"]

        # Invalidate all sessions due to potentially changed capabilities
        for member in group.users:
            member.reset_sessions()

        db.session.commit()

        logger.info('Group updated',
                    extra={
                        "group": group.name,
                        "capabilities": group.capabilities
                    })
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": group.name})
예제 #5
0
    def delete(self, name, login):
        """
        ---
        summary: Delete member from group
        description: |
            Removes member from existing group.

            Works only for user-defined groups (excluding private and 'public')

            Requires `manage_users` capability or group_admin membership.
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
            - in: path
              name: login
              schema:
                type: string
              description: Member login
        responses:
            200:
                description: When member was removed successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When request body is invalid
            403:
                description: |
                    When user doesn't have `manage_users` capability,
                    group is immutable or user is pending
            404:
                description: When user or group doesn't exist
            409:
                description: When member is already removed
        """
        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())
        user_login_obj = load_schema({"login": login}, UserLoginSchemaBase())

        group = (db.session.query(Group).options(
            joinedload(Group.members),
            joinedload(Group.members, Member.user)).filter(
                Group.name == group_name_obj["name"])).first()
        if not (g.auth_user.has_rights(Capabilities.manage_users)
                or g.auth_user.is_group_admin(group.id)):
            raise Forbidden("You are not permitted to manage this group")

        if group is None:
            raise NotFound("No such group")

        if group.immutable:
            raise Forbidden(
                "Removing members from immutable group is not allowed")

        member = (db.session.query(User).filter(
            User.login == user_login_obj["login"]).first())
        if g.auth_user.login == member.login:
            raise Forbidden("You can't remove yourself from the group, "
                            "only system admin can remove group admins.")
        if member is None:
            raise NotFound("No such user")

        if member.pending:
            raise Forbidden("User is pending and need to be accepted first")

        if not group.remove_member(member):
            raise Conflict("Member is already removed")
        db.session.commit()

        logger.info("Group member deleted",
                    extra={
                        "user": member.login,
                        "group": group.name
                    })
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": name})
예제 #6
0
    def put(self, name, login):
        """
        ---
        summary: Update group membership
        description: |
            Updates group membership for specific member e.g. to set admin role.

            Works only for user-defined groups (excluding private and 'public')

            Requires `manage_users` capability
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
            - in: path
              name: login
              schema:
                type: string
              description: Member login
        requestBody:
            description: Group membership information
            content:
              application/json:
                schema: GroupMemberUpdateRequestSchema
        responses:
            200:
                description: When member was added successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When request body is invalid
            403:
                description: |
                    When user doesn't have `manage_users` capability,
                    group is immutable or user is pending
            404:
                description: When user or group doesn't exist
            409:
                description: When member is already added
        """
        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())

        user_login_obj = load_schema({"login": login}, UserLoginSchemaBase())

        membership = loads_schema(request.get_data(as_text=True),
                                  GroupMemberUpdateRequestSchema())

        group = (db.session.query(Group).options(
            joinedload(Group.members),
            joinedload(Group.members, Member.user)).filter(
                Group.name == group_name_obj["name"])).first()

        if group is None:
            raise NotFound("No such group")

        if group.immutable:
            raise Forbidden(
                "Change membership in immutable group is not allowed")

        member = (db.session.query(User).filter(
            User.login == user_login_obj["login"]).first())
        if member is None:
            raise NotFound("No such user")

        if member.pending:
            raise Forbidden("User is pending and need to be accepted first")

        member.set_group_admin(group.id, membership["group_admin"])
        db.session.commit()

        logger.info("Group member updated",
                    extra={
                        "user": member.login,
                        "group": group.name
                    })
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": name})
예제 #7
0
    def post(self, name, login):
        """
        ---
        summary: Add a member to the specific group
        description: |
            Adds new member to existing group

            Works only for user-defined groups (excluding private and 'public')

            Requires `manage_users` capability
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
            - in: path
              name: login
              schema:
                type: string
              description: Member login
        responses:
            200:
                description: When member was added successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When request body is invalid
            403:
                description: |
                    When user doesn't have `manage_users` capability,
                    group is immutable or user is pending
            404:
                description: When user or group doesn't exist
        """
        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())

        user_login_obj = load_schema({"login": login}, UserLoginSchemaBase())

        group = (db.session.query(Group).options(
            joinedload(Group.members),
            joinedload(Group.members, Member.user)).filter(
                Group.name == group_name_obj["name"])).first()

        if group is None:
            raise NotFound("No such group")

        if group.immutable:
            raise Forbidden("Adding members to immutable group is not allowed")

        member = (db.session.query(User).filter(
            User.login == user_login_obj["login"]).first())
        if member is None:
            raise NotFound("No such user")

        if member.pending:
            raise Forbidden("User is pending and need to be accepted first")

        if not group.add_member(member):
            raise Conflict("Member is already added")
        db.session.commit()

        logger.info("Group member added",
                    extra={
                        "user": member.login,
                        "group": group.name
                    })
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": name})
예제 #8
0
    def put(self, name):
        """
        ---
        summary: Update group attributes
        description: |
            Updates group attributes.

            If the group is immutable, you can only change capabilities.

            Requires `manage_users` capability.
        security:
            - bearerAuth: []
        tags:
            - group
        parameters:
            - in: path
              name: name
              schema:
                type: string
              description: Group name
        requestBody:
            description: Group information
            content:
              application/json:
                schema: GroupUpdateRequestSchema
        responses:
            200:
                description: When group was updated successfully
                content:
                  application/json:
                    schema: GroupSuccessResponseSchema
            400:
                description: When group name or request body is invalid
            403:
                description: |
                    When user doesn't have `manage_users` capability
                    or group is immutable
            404:
                description: When group doesn't exist
        """
        schema = GroupUpdateRequestSchema()
        obj = loads_schema(request.get_data(as_text=True), schema)

        group_name_obj = load_schema({"name": name}, GroupNameSchemaBase())

        group = (db.session.query(Group).filter(
            Group.name == group_name_obj["name"]).first())
        if group is None:
            raise NotFound("No such group")

        immutable_fields = ["name", "default", "workspace"]
        if group.immutable:
            for field in immutable_fields:
                if obj[field] is not None:
                    raise Forbidden(
                        f"Can't change '{field}', group is immutable")

        if obj["name"] is not None:
            group.name = obj["name"]

        if obj["capabilities"] is not None:
            group.capabilities = obj["capabilities"]

        if obj["default"] is not None:
            group.default = obj["default"]

        if obj["workspace"] is not None:
            group.default = obj["workspace"]

        db.session.commit()

        logger.info(
            "Group updated",
            extra={
                "group": group.name,
                "capabilities": group.capabilities
            },
        )
        schema = GroupSuccessResponseSchema()
        return schema.dump({"name": group.name})