示例#1
0
    def convert_answer_to_comment(self):
        """ Tools to convert an answer (forum.post) to a comment (mail.message).
        The original post is unlinked and a new comment is posted on the question
        using the post create_uid as the comment's author. """
        self.ensure_one()
        if not self.parent_id:
            return self.env['mail.message']

        # karma-based action check: use the post field that computed own/all value
        if not self.can_comment_convert:
            raise KarmaError(_('%d karma required to convert an answer to a comment.') % self.karma_comment_convert)

        # post the message
        question = self.parent_id
        self_sudo = self.sudo()
        values = {
            'author_id': self_sudo.create_uid.partner_id.id,  # use sudo here because of access to res.users model
            'email_from': self_sudo.create_uid.email_formatted,  # use sudo here because of access to res.users model
            'body': tools.html_sanitize(self.content, sanitize_attributes=True, strip_style=True, strip_classes=True),
            'message_type': 'comment',
            'subtype': 'mail.mt_comment',
            'date': self.create_date,
        }
        new_message = question.with_context(mail_create_nosubscribe=True).message_post(**values)

        # unlink the original answer, using SUPERUSER_ID to avoid karma issues
        self.sudo().unlink()

        return new_message
示例#2
0
    def convert_comment_to_answer(self, message_id, default=None):
        """ Tool to convert a comment (mail.message) into an answer (forum.post).
        The original comment is unlinked and a new answer from the comment's author
        is created. Nothing is done if the comment's author already answered the
        question. """
        comment = self.env['mail.message'].sudo().browse(message_id)
        post = self.browse(comment.res_id)
        if not comment.author_id or not comment.author_id.user_ids:  # only comment posted by users can be converted
            return False

        # karma-based action check: must check the message's author to know if own / all
        karma_convert = comment.author_id.id == self.env.user.partner_id.id and post.forum_id.karma_comment_convert_own or post.forum_id.karma_comment_convert_all
        can_convert = self.env.user.karma >= karma_convert
        if not can_convert:
            raise KarmaError('Not enough karma to convert a comment to an answer')

        # check the message's author has not already an answer
        question = post.parent_id if post.parent_id else post
        post_create_uid = comment.author_id.user_ids[0]
        if any(answer.create_uid.id == post_create_uid.id for answer in question.child_ids):
            return False

        # create the new post
        post_values = {
            'forum_id': question.forum_id.id,
            'content': comment.body,
            'parent_id': question.id,
        }
        # done with the author user to have create_uid correctly set
        new_post = self.sudo(post_create_uid.id).create(post_values)

        # delete comment
        comment.unlink()

        return new_post
示例#3
0
 def get_mail_message_access(self, res_ids, operation, model_name=None):
     # XDO FIXME: to be correctly fixed with new get_mail_message_access and filter access rule
     if operation in ('write', 'unlink') and (not model_name or model_name == 'forum.post'):
         # Make sure only author or moderator can edit/delete messages
         for post in self.browse(res_ids):
             if not post.can_edit:
                 raise KarmaError(_('%d karma required to edit a post.') % post.karma_edit)
     return super(Post, self).get_mail_message_access(res_ids, operation, model_name=model_name)
示例#4
0
 def unlink(self):
     if any(not post.can_unlink for post in self):
         raise KarmaError('Not enough karma to unlink a post')
     # if unlinking an answer with accepted answer: remove provided karma
     for post in self:
         if post.is_correct:
             post.create_uid.sudo().add_karma(post.forum_id.karma_gen_answer_accepted * -1)
             self.env.user.sudo().add_karma(post.forum_id.karma_gen_answer_accepted * -1)
     return super(Post, self).unlink()
示例#5
0
 def unlink(self):
     for post in self:
         if not post.can_unlink:
             raise KarmaError(_('%d karma required to unlink a post.') % post.karma_unlink)
     # if unlinking an answer with accepted answer: remove provided karma
     for post in self:
         if post.is_correct:
             post.create_uid.sudo().add_karma(post.forum_id.karma_gen_answer_accepted * -1)
             self.env.user.sudo().add_karma(post.forum_id.karma_gen_answer_accepted * -1)
     return super(Post, self).unlink()
示例#6
0
 def unlink_comment(self, message_id):
     user = self.env.user
     comment = self.env['mail.message'].sudo().browse(message_id)
     if not comment.model == 'forum.post' or not comment.res_id == self.id:
         return False
     # karma-based action check: must check the message's author to know if own or all
     karma_unlink = comment.author_id.id == user.partner_id.id and self.forum_id.karma_comment_unlink_own or self.forum_id.karma_comment_unlink_all
     can_unlink = user.karma >= karma_unlink
     if not can_unlink:
         raise KarmaError(_('%d karma required to unlink a comment.') % karma_unlink)
     return comment.unlink()
示例#7
0
    def create(self, vals):
        if 'content' in vals and vals.get('forum_id'):
            vals['content'] = self._update_content(vals['content'], vals['forum_id'])

        post = super(Post, self.with_context(mail_create_nolog=True)).create(vals)
        # deleted or closed questions
        if post.parent_id and (post.parent_id.state == 'close' or post.parent_id.active is False):
            raise UserError(_('Posting answer on a [Deleted] or [Closed] question is not possible.'))
        # karma-based access
        if not post.parent_id and not post.can_ask:
            raise KarmaError(_('%d karma required to create a new question.') % post.forum_id.karma_ask)
        elif post.parent_id and not post.can_answer:
            raise KarmaError(_('%d karma required to answer a question.') % post.forum_id.karma_answer)
        if not post.parent_id and not post.can_post:
            post.sudo().state = 'pending'

        # add karma for posting new questions
        if not post.parent_id and post.state == 'active':
            self.env.user.sudo().add_karma(post.forum_id.karma_gen_question_new)
        post.post_notification()
        return post
示例#8
0
    def _update_content(self, content, forum_id):
        forum = self.env['forum.forum'].browse(forum_id)
        if content and self.env.user.karma < forum.karma_dofollow:
            for match in re.findall(r'<a\s.*href=".*?">', content):
                match = re.escape(match)  # replace parenthesis or special char in regex
                content = re.sub(match, match[:3] + 'rel="nofollow" ' + match[3:], content)

        if self.env.user.karma <= forum.karma_editor:
            filter_regexp = r'(<img.*?>)|(<a[^>]*?href[^>]*?>)|(<[a-z|A-Z]+[^>]*style\s*=\s*[\'"][^\'"]*\s*background[^:]*:[^url;]*url)'
            content_match = re.search(filter_regexp, content, re.I)
            if content_match:
                raise KarmaError(_('%d karma required to post an image or link.') % forum.karma_editor)
        return content
示例#9
0
    def flag(self):
        if not self.can_flag:
            raise KarmaError('Not enough karma to flag a post')

        if(self.state == 'flagged'):
            return {'error': 'post_already_flagged'}
        elif(self.state == 'active'):
            self.write({
                'state': 'flagged',
                'flag_user_id': self.env.user.id,
            })
            return self.can_moderate and {'success': 'post_flagged_moderator'} or {'success': 'post_flagged_non_moderator'}
        else:
            return {'error': 'post_non_flaggable'}
示例#10
0
 def validate(self):
     for post in self:
         if not post.can_moderate:
             raise KarmaError(_('%d karma required to validate a post.') % post.forum_id.karma_moderate)
         # if state == pending, no karma previously added for the new question
         if post.state == 'pending':
             post.create_uid.sudo().add_karma(post.forum_id.karma_gen_question_new)
         post.write({
             'state': 'active',
             'active': True,
             'moderator_id': self.env.user.id,
         })
         post.post_notification()
     return True
示例#11
0
    def flag(self):
        if not self.can_flag:
            raise KarmaError(_('%d karma required to flag a post.') % self.forum_id.karma_flag)

        if(self.state == 'flagged'):
            return {'error': 'post_already_flagged'}
        elif(self.state == 'active'):
            self.write({
                'state': 'flagged',
                'flag_user_id': self.env.user.id,
            })
            return self.can_moderate and {'success': 'post_flagged_moderator'} or {'success': 'post_flagged_non_moderator'}
        else:
            return {'error': 'post_non_flaggable'}
示例#12
0
 def message_post(self, parent_id=False, subtype=None, **kwargs):
     """ Temporary workaround to avoid spam. If someone replies on a channel
     through the 'Presentation Published' email, it should be considered as a
     note as we don't want all channel followers to be notified of this answer. """
     self.ensure_one()
     if kwargs.get('message_type') == 'comment' and not self.can_review:
         raise KarmaError(_('Not enough karma to review'))
     if parent_id:
         parent_message = self.env['mail.message'].sudo().browse(parent_id)
         if parent_message.subtype_id and parent_message.subtype_id == self.env.ref('website_slides.mt_channel_slide_published'):
             if kwargs.get('subtype_id'):
                 kwargs['subtype_id'] = False
             subtype = 'mail.mt_note'
     return super(Channel, self).message_post(parent_id=parent_id, subtype=subtype, **kwargs)
示例#13
0
    def validate(self):
        if not self.can_moderate:
            raise KarmaError('Not enough karma to validate a post')

        # if state == pending, no karma previously added for the new question
        if self.state == 'pending':
            self.create_uid.sudo().add_karma(self.forum_id.karma_gen_question_new)

        self.write({
            'state': 'active',
            'active': True,
            'moderator_id': self.env.user.id,
        })
        self.post_notification()
        return True
示例#14
0
    def mark_as_offensive(self, reason_id):
        if not self.can_moderate:
            raise KarmaError(_('%d karma required to mark a post as offensive.') % self.forum_id.karma_moderate)

        # remove some karma
        _logger.info('Downvoting user <%s> for posting spam/offensive contents', self.create_uid)
        self.create_uid.sudo().add_karma(self.forum_id.karma_gen_answer_flagged)

        self.write({
            'state': 'offensive',
            'moderator_id': self.env.user.id,
            'closed_date': datetime.today().strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT),
            'closed_reason_id': reason_id,
            'active': False,
        })
        return True
示例#15
0
 def mark_as_offensive(self, reason_id):
     for post in self:
         if not post.can_moderate:
             raise KarmaError(_('%d karma required to mark a post as offensive.') % post.forum_id.karma_moderate)
         # remove some karma
         _logger.info('Downvoting user <%s> for posting spam/offensive contents', post.create_uid)
         post.create_uid.sudo().add_karma(post.forum_id.karma_gen_answer_flagged)
         # TODO: potential bottleneck, could be done in batch
         post.write({
             'state': 'offensive',
             'moderator_id': self.env.user.id,
             'closed_date': fields.Datetime.now(),
             'closed_reason_id': reason_id,
             'active': False,
         })
     return True
示例#16
0
    def write(self, vals):
        trusted_keys = ['active', 'is_correct', 'tag_ids']  # fields where security is checked manually
        if 'content' in vals:
            vals['content'] = self._update_content(vals['content'], self.forum_id.id)

        tag_ids = False
        if 'tag_ids' in vals:
            tag_ids = set(tag.get('id') for tag in self.resolve_2many_commands('tag_ids', vals['tag_ids']))

        for post in self:
            if 'state' in vals:
                if vals['state'] in ['active', 'close']:
                    if not post.can_close:
                        raise KarmaError(_('%d karma required to close or reopen a post.') % post.karma_close)
                    trusted_keys += ['state', 'closed_uid', 'closed_date', 'closed_reason_id']
                elif vals['state'] == 'flagged':
                    if not post.can_flag:
                        raise KarmaError(_('%d karma required to flag a post.') % post.forum_id.karma_flag)
                    trusted_keys += ['state', 'flag_user_id']
            if 'active' in vals:
                if not post.can_unlink:
                    raise KarmaError(_('%d karma required to delete or reactivate a post.') % post.karma_unlink)
            if 'is_correct' in vals:
                if not post.can_accept:
                    raise KarmaError(_('%d karma required to accept or refuse an answer.') % post.karma_accept)
                # update karma except for self-acceptance
                mult = 1 if vals['is_correct'] else -1
                if vals['is_correct'] != post.is_correct and post.create_uid.id != self._uid:
                    post.create_uid.sudo().add_karma(post.forum_id.karma_gen_answer_accepted * mult)
                    self.env.user.sudo().add_karma(post.forum_id.karma_gen_answer_accept * mult)
            if tag_ids:
                if set(post.tag_ids.ids) != tag_ids and self.env.user.karma < post.forum_id.karma_edit_retag:
                    raise KarmaError(_('%d karma required to retag.') % post.forum_id.karma_edit_retag)
            if any(key not in trusted_keys for key in vals) and not post.can_edit:
                raise KarmaError(_('%d karma required to edit a post.') % post.karma_edit)

        res = super(Post, self).write(vals)

        # if post content modify, notify followers
        if 'content' in vals or 'name' in vals:
            for post in self:
                if post.parent_id:
                    body, subtype = _('Answer Edited'), 'website_forum.mt_answer_edit'
                    obj_id = post.parent_id
                else:
                    body, subtype = _('Question Edited'), 'website_forum.mt_question_edit'
                    obj_id = post
                obj_id.message_post(body=body, subtype=subtype)
        if 'active' in vals:
            answers = self.env['forum.post'].with_context(active_test=False).search([('parent_id', 'in', self.ids)])
            if answers:
                answers.write({'active': vals['active']})
        return res
示例#17
0
    def message_post(self, message_type='notification', **kwargs):
        if self.ids and message_type == 'comment':  # user comments have a restriction on karma
            # add followers of comments on the parent post
            if self.parent_id:
                partner_ids = kwargs.get('partner_ids', [])
                comment_subtype = self.sudo().env.ref('mail.mt_comment')
                question_followers = self.env['mail.followers'].sudo().search([
                    ('res_model', '=', self._name),
                    ('res_id', '=', self.parent_id.id),
                    ('partner_id', '!=', False),
                ]).filtered(lambda fol: comment_subtype in fol.subtype_ids).mapped('partner_id')
                partner_ids += question_followers.ids
                kwargs['partner_ids'] = partner_ids

            self.ensure_one()
            if not self.can_comment:
                raise KarmaError(_('%d karma required to comment.') % self.karma_comment)
            if not kwargs.get('record_name') and self.parent_id:
                kwargs['record_name'] = self.parent_id.name
        return super(Post, self).message_post(message_type=message_type, **kwargs)
示例#18
0
 def flag(self):
     res = []
     for post in self:
         if not post.can_flag:
             raise KarmaError(_('%d karma required to flag a post.') % post.forum_id.karma_flag)
         if post.state == 'flagged':
            res.append({'error': 'post_already_flagged'})
         elif post.state == 'active':
             # TODO: potential performance bottleneck, can be batched
             post.write({
                 'state': 'flagged',
                 'flag_user_id': self.env.user.id,
             })
             res.append(
                 post.can_moderate and
                 {'success': 'post_flagged_moderator'} or
                 {'success': 'post_flagged_non_moderator'}
             )
         else:
             res.append({'error': 'post_non_flaggable'})
     return res
示例#19
0
 def refuse(self):
     for post in self:
         if not post.can_moderate:
             raise KarmaError(_('%d karma required to refuse a post.') % post.forum_id.karma_moderate)
         post.moderator_id = self.env.user
     return True
示例#20
0
 def test_karma_error_http(self, **kwargs):
     raise KarmaError("This is a karma http test")
示例#21
0
 def _check_karma_rights(self, upvote=None):
     # karma check
     if upvote and not self.post_id.can_upvote:
         raise KarmaError('You don\'t have enough karma to upvote.')
     elif not upvote and not self.post_id.can_downvote:
         raise KarmaError('You don\'t have enough karma to downvote.')
示例#22
0
 def check_mail_message_access(self, res_ids, operation, model_name=None):
     if operation in ('write', 'unlink') and (not model_name or model_name == 'forum.post'):
         # Make sure only author or moderator can edit/delete messages
         if any(not post.can_edit for post in self.browse(res_ids)):
             raise KarmaError('Not enough karma to edit a post.')
     return super(Post, self).check_mail_message_access(res_ids, operation, model_name=model_name)
示例#23
0
 def _check_karma_rights(self, upvote=None):
     # karma check
     if upvote and not self.post_id.can_upvote:
         raise KarmaError(_('%d karma required to upvote.') % self.post_id.forum_id.karma_upvote)
     elif not upvote and not self.post_id.can_downvote:
         raise KarmaError(_('%d karma required to downvote.') % self.post_id.forum_id.karma_downvote)
示例#24
0
    def refuse(self):
        if not self.can_moderate:
            raise KarmaError(_('%d karma required to refuse a post.') % self.forum_id.karma_moderate)

        self.moderator_id = self.env.user
        return True
示例#25
0
 def create(self, vals):
     forum = self.env['forum.forum'].browse(vals.get('forum_id'))
     if self.env.user.karma < forum.karma_tag_create:
         raise KarmaError(_('%d karma required to create a new Tag.') % forum.karma_tag_create)
     return super(Tags, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals)
示例#26
0
    def refuse(self):
        if not self.can_moderate:
            raise KarmaError(_('Not enough karma to refuse a post'))

        self.moderator_id = self.env.user
        return True
示例#27
0
 def message_post(self, message_type='notification', **kwargs):
     self.ensure_one()
     if message_type == 'comment' and not self.channel_id.can_comment:  # user comments have a restriction on karma
         raise KarmaError(_('Not enough karma to comment'))
     return super(Slide, self).message_post(message_type=message_type,
                                            **kwargs)
示例#28
0
 def test_karma_error_rpc(self, **kwargs):
     raise KarmaError("This is a karma rpc test")