Beispiel #1
0
class RoleUpdateSchema(marshmallow.Schema):
    role = marshmallow.fields.String(
        example='contributor',
        validate=OneOf(UserRoleInWorkspace.get_all_role_slug())
    )

    @post_load
    def make_role(self, data):
        return RoleUpdate(**data)
Beispiel #2
0
    def get_roles_for_select_field(cls):
        """

        :return: list of DictLikeClass instances representing available Roles
        (to be used in select fields)
        """
        result = list()

        for role_id in UserRoleInWorkspace.get_all_role_values():
            role = RoleType(role_id)
            result.append(role)

        return result
Beispiel #3
0
 def create_one(self,
                user: User,
                workspace: Workspace,
                role_level: int,
                with_notif: bool,
                flush: bool = True) -> UserRoleInWorkspace:
     role = UserRoleInWorkspace()
     role.user_id = user.user_id
     role.workspace = workspace
     role.role = role_level
     role.do_notify = with_notif
     if flush:
         self._session.flush()
     return role
Beispiel #4
0
    def update_role(
        self,
        role: UserRoleInWorkspace,
        role_level: int,
        with_notif: typing.Optional[bool] = None,
        save_now: bool = False,
    ):
        """
        Update role of user in this workspace
        :param role: UserRoleInWorkspace object
        :param role_level: level of new role wanted
        :param with_notif: is user notification enabled in this workspace ?
        :param save_now: database flush
        :return: updated role
        """
        role.role = role_level
        if with_notif is not None:
            role.do_notify == with_notif
        if save_now:
            self.save(role)

        return role
Beispiel #5
0
class WorkspaceMemberSchema(marshmallow.Schema):
    role = marshmallow.fields.String(
        example='contributor',
        validate=OneOf(UserRoleInWorkspace.get_all_role_slug())
    )
    user_id = marshmallow.fields.Int(
        example=3,
        validate=Range(min=1, error="Value must be greater than 0"),
    )
    workspace_id = marshmallow.fields.Int(
        example=4,
        validate=Range(min=1, error="Value must be greater than 0"),
    )
    user = marshmallow.fields.Nested(
        UserDigestSchema()
    )
    workspace = marshmallow.fields.Nested(
        WorkspaceDigestSchema(exclude=('sidebar_entries',))
    )
    is_active = marshmallow.fields.Bool()

    class Meta:
        description = 'Workspace Member information'
Beispiel #6
0
    def _build_email_body_for_content(
            self,
            mako_template_filepath: str,
            role: UserRoleInWorkspace,
            content: Content,
            actor: User
    ) -> str:
        """
        Build an email body and return it as a string
        :param mako_template_filepath: the absolute path to the mako template to be used for email body building
        :param role: the role related to user to whom the email must be sent. The role is required (and not the user only) in order to show in the mail why the user receive the notification
        :param content: the content item related to the notification
        :param actor: the user at the origin of the action / notification (for example the one who wrote a comment
        :param config: the global configuration
        :return: the built email body as string. In case of multipart email, this method must be called one time for text and one time for html
        """
        logger.debug(self, 'Building email content from MAKO template {}'.format(mako_template_filepath))

        main_title = content.label
        content_intro = ''
        content_text = ''
        call_to_action_text = ''

        # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for call_to_action_url  # nopep8
        call_to_action_url =''
        # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for status_icon_url  # nopep8
        status_icon_url = ''
        # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for workspace_url  # nopep8
        workspace_url = ''
        # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for logo_url  # nopep8
        logo_url = ''

        action = content.get_last_action().id
        if ActionDescription.COMMENT == action:
            content_intro = l_('<span id="content-intro-username">{}</span> added a comment:').format(actor.display_name)
            content_text = content.description
            call_to_action_text = l_('Answer')

        elif ActionDescription.CREATION == action:

            # Default values (if not overriden)
            content_text = content.description
            call_to_action_text = l_('View online')

            if ContentType.Thread == content.type:
                call_to_action_text = l_('Answer')
                content_intro = l_('<span id="content-intro-username">{}</span> started a thread entitled:').format(actor.display_name)
                content_text = '<p id="content-body-intro">{}</p>'.format(content.label) + \
                               content.get_last_comment_from(actor).description

            elif ContentType.File == content.type:
                content_intro = l_('<span id="content-intro-username">{}</span> added a file entitled:').format(actor.display_name)
                if content.description:
                    content_text = content.description
                else:
                    content_text = '<span id="content-body-only-title">{}</span>'.format(content.label)

            elif ContentType.Page == content.type:
                content_intro = l_('<span id="content-intro-username">{}</span> added a page entitled:').format(actor.display_name)
                content_text = '<span id="content-body-only-title">{}</span>'.format(content.label)

        elif ActionDescription.REVISION == action:
            content_text = content.description
            call_to_action_text = l_('View online')

            if ContentType.File == content.type:
                content_intro = l_('<span id="content-intro-username">{}</span> uploaded a new revision.').format(actor.display_name)
                content_text = ''

            elif ContentType.Page == content.type:
                content_intro = l_('<span id="content-intro-username">{}</span> updated this page.').format(actor.display_name)
                previous_revision = content.get_previous_revision()
                title_diff = ''
                if previous_revision.label != content.label:
                    title_diff = htmldiff(previous_revision.label, content.label)
                content_text = str(l_('<p id="content-body-intro">Here is an overview of the changes:</p>'))+ \
                    title_diff + \
                    htmldiff(previous_revision.description, content.description)

            elif ContentType.Thread == content.type:
                content_intro = l_('<span id="content-intro-username">{}</span> updated the thread description.').format(actor.display_name)
                previous_revision = content.get_previous_revision()
                title_diff = ''
                if previous_revision.label != content.label:
                    title_diff = htmldiff(previous_revision.label, content.label)
                content_text = str(l_('<p id="content-body-intro">Here is an overview of the changes:</p>'))+ \
                    title_diff + \
                    htmldiff(previous_revision.description, content.description)

        elif ActionDescription.EDITION == action:
            call_to_action_text = l_('View online')

            if ContentType.File == content.type:
                content_intro = l_('<span id="content-intro-username">{}</span> updated the file description.').format(actor.display_name)
                content_text = '<p id="content-body-intro">{}</p>'.format(content.get_label()) + \
                    content.description

        elif ActionDescription.STATUS_UPDATE == action:
            call_to_action_text = l_('View online')
            intro_user_msg = l_(
                '<span id="content-intro-username">{}</span> '
                'updated the following status:'
            )
            content_intro = intro_user_msg.format(actor.display_name)
            intro_body_msg = '<p id="content-body-intro">{}: {}</p>'
            content_text = intro_body_msg.format(
                content.get_label(),
                content.get_status().label,
            )

        if '' == content_intro and content_text == '':
            # Skip notification, but it's not normal
            logger.error(
                self, 'A notification is being sent but no content. '
                      'Here are some debug informations: [content_id: {cid}]'
                      '[action: {act}][author: {actor}]'.format(
                    cid=content.content_id, act=action, actor=actor
                )
            )
            raise ValueError('Unexpected empty notification')

        context = {
            'user': role.user,
            'workspace': role.workspace,
            'workspace_url': workspace_url,
            'main_title': main_title,
            'status_label': content.get_status().label,
            'status_icon_url': status_icon_url,
            'role_label': role.role_as_label(),
            'content_intro': content_intro,
            'content_text': content_text,
            'call_to_action_text': call_to_action_text,
            'call_to_action_url': call_to_action_url,
            'logo_url': logo_url,
        }
        user = role.user
        workspace = role.workspace
        body_content = self._render_template(
            mako_template_filepath=mako_template_filepath,
            context=context,
        )
        return body_content
Beispiel #7
0
    def create_role(cls) -> UserRoleInWorkspace:
        role = UserRoleInWorkspace()

        return role
Beispiel #8
0
class RoleApi(object):

    ALL_ROLE_VALUES = UserRoleInWorkspace.get_all_role_values()
    # Dict containing readable members roles for given role
    members_read_rights = {
        UserRoleInWorkspace.NOT_APPLICABLE: [],
        UserRoleInWorkspace.READER: [
            UserRoleInWorkspace.WORKSPACE_MANAGER,
        ],
        UserRoleInWorkspace.CONTRIBUTOR: [
            UserRoleInWorkspace.WORKSPACE_MANAGER,
            UserRoleInWorkspace.CONTENT_MANAGER,
            UserRoleInWorkspace.CONTRIBUTOR,
        ],
        UserRoleInWorkspace.CONTENT_MANAGER: [
            UserRoleInWorkspace.WORKSPACE_MANAGER,
            UserRoleInWorkspace.CONTENT_MANAGER,
            UserRoleInWorkspace.CONTRIBUTOR,
            UserRoleInWorkspace.READER,
        ],
        UserRoleInWorkspace.WORKSPACE_MANAGER: [
            UserRoleInWorkspace.WORKSPACE_MANAGER,
            UserRoleInWorkspace.CONTENT_MANAGER,
            UserRoleInWorkspace.CONTRIBUTOR,
            UserRoleInWorkspace.READER,
        ],
    }

    @classmethod
    def role_can_read_member_role(cls, reader_role: int, tested_role: int) \
            -> bool:
        """
        :param reader_role: role as viewer
        :param tested_role: role as viwed
        :return: True if given role can view member role in workspace.
        """
        if reader_role in cls.members_read_rights:
            return tested_role in cls.members_read_rights[reader_role]
        return False

    @classmethod
    def create_role(cls) -> UserRoleInWorkspace:
        role = UserRoleInWorkspace()

        return role

    def __init__(self, session: Session, current_user: typing.Optional[User]):
        self._session = session
        self._user = current_user

    def _get_one_rsc(self, user_id, workspace_id):
        """
        :param user_id:
        :param workspace_id:
        :return: a Query object, filtered query but without fetching the object.
        """
        return self._session.query(UserRoleInWorkspace).\
            filter(UserRoleInWorkspace.workspace_id == workspace_id).\
            filter(UserRoleInWorkspace.user_id == user_id)

    def get_one(self, user_id, workspace_id):
        return self._get_one_rsc(user_id, workspace_id).one()

    def create_one(
            self,
            user: User,
            workspace: Workspace,
            role_level: int,
            with_notif: bool,
            flush: bool=True
    ) -> UserRoleInWorkspace:
        role = self.create_role()
        role.user_id = user.user_id
        role.workspace = workspace
        role.role = role_level
        role.do_notify = with_notif
        if flush:
            self._session.flush()
        return role

    def delete_one(self, user_id, workspace_id, flush=True):
        self._get_one_rsc(user_id, workspace_id).delete()
        if flush:
            self._session.flush()

    def _get_all_for_user(self, user_id):
        return self._session.query(UserRoleInWorkspace)\
            .filter(UserRoleInWorkspace.user_id == user_id)

    def get_all_for_user(self, user_id):
        return self._get_all_for_user(user_id).all()

    def get_all_for_user_order_by_workspace(
            self,
            user_id: int
    ) -> UserRoleInWorkspace:
        return self._get_all_for_user(user_id)\
            .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()

    def get_all_for_workspace(self, workspace_id):
        return self._session.query(UserRoleInWorkspace)\
            .filter(UserRoleInWorkspace.workspace_id == workspace_id).all()

    def save(self, role: UserRoleInWorkspace):
        self._session.flush()

    @classmethod
    def get_roles_for_select_field(cls):
        """

        :return: list of DictLikeClass instances representing available Roles
        (to be used in select fields)
        """
        result = list()

        for role_id in UserRoleInWorkspace.get_all_role_values():
            role = RoleType(role_id)
            result.append(role)

        return result