Changeset - a042ec2fc12f
[Not reviewed]
default
0 2 0
Marcin Kuzminski - 13 years ago 2013-01-21 23:14:43
marcin@python-works.com
Grafted from: a665d8cdd351
improved extraction of user from changeset when sending notification.
Fallback to repo owner if we cannot get the user
2 files changed with 25 insertions and 2 deletions:
0 comments (0 inline, 0 general)
rhodecode/model/comment.py
Show inline comments
 
@@ -43,131 +43,134 @@ class ChangesetCommentsModel(BaseModel):
 

	
 
    cls = ChangesetComment
 

	
 
    def __get_changeset_comment(self, changeset_comment):
 
        return self._get_instance(ChangesetComment, changeset_comment)
 

	
 
    def __get_pull_request(self, pull_request):
 
        return self._get_instance(PullRequest, pull_request)
 

	
 
    def _extract_mentions(self, s):
 
        user_objects = []
 
        for username in extract_mentioned_users(s):
 
            user_obj = User.get_by_username(username, case_insensitive=True)
 
            if user_obj:
 
                user_objects.append(user_obj)
 
        return user_objects
 

	
 
    def create(self, text, repo, user, revision=None, pull_request=None,
 
               f_path=None, line_no=None, status_change=None):
 
        """
 
        Creates new comment for changeset or pull request.
 
        IF status_change is not none this comment is associated with a
 
        status change of changeset or changesets associated with pull request
 

	
 
        :param text:
 
        :param repo:
 
        :param user:
 
        :param revision:
 
        :param pull_request:
 
        :param f_path:
 
        :param line_no:
 
        :param status_change:
 
        """
 
        if not text:
 
            return
 

	
 
        repo = self._get_repo(repo)
 
        user = self._get_user(user)
 
        comment = ChangesetComment()
 
        comment.repo = repo
 
        comment.author = user
 
        comment.text = text
 
        comment.f_path = f_path
 
        comment.line_no = line_no
 

	
 
        if revision:
 
            cs = repo.scm_instance.get_changeset(revision)
 
            desc = "%s - %s" % (cs.short_id, h.shorter(cs.message, 256))
 
            author_email = cs.author_email
 
            comment.revision = revision
 
        elif pull_request:
 
            pull_request = self.__get_pull_request(pull_request)
 
            comment.pull_request = pull_request
 
            desc = pull_request.pull_request_id
 
        else:
 
            raise Exception('Please specify revision or pull_request_id')
 

	
 
        self.sa.add(comment)
 
        self.sa.flush()
 

	
 
        # make notification
 
        line = ''
 
        body = text
 

	
 
        #changeset
 
        if revision:
 
            if line_no:
 
                line = _('on line %s') % line_no
 
            subj = safe_unicode(
 
                h.link_to('Re commit: %(desc)s %(line)s' % \
 
                          {'desc': desc, 'line': line},
 
                          h.url('changeset_home', repo_name=repo.repo_name,
 
                                revision=revision,
 
                                anchor='comment-%s' % comment.comment_id,
 
                                qualified=True,
 
                          )
 
                )
 
            )
 
            notification_type = Notification.TYPE_CHANGESET_COMMENT
 
            # get the current participants of this changeset
 
            recipients = ChangesetComment.get_users(revision=revision)
 
            # add changeset author if it's in rhodecode system
 
            recipients += [User.get_by_email(author_email)]
 
            cs_author = User.get_from_cs_author(cs.author)
 
            if not cs_author:
 
                #use repo owner if we cannot extract the author correctly
 
                cs_author = repo.user
 
            recipients += [cs_author]
 
            email_kwargs = {
 
                'status_change': status_change,
 
            }
 
        #pull request
 
        elif pull_request:
 
            _url = h.url('pullrequest_show',
 
                repo_name=pull_request.other_repo.repo_name,
 
                pull_request_id=pull_request.pull_request_id,
 
                anchor='comment-%s' % comment.comment_id,
 
                qualified=True,
 
            )
 
            subj = safe_unicode(
 
                h.link_to('Re pull request: %(desc)s %(line)s' % \
 
                          {'desc': desc, 'line': line}, _url)
 
            )
 

	
 
            notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
 
            # get the current participants of this pull request
 
            recipients = ChangesetComment.get_users(pull_request_id=
 
                                                pull_request.pull_request_id)
 
            # add pull request author
 
            recipients += [pull_request.author]
 

	
 
            # add the reviewers to notification
 
            recipients += [x.user for x in pull_request.reviewers]
 

	
 
            #set some variables for email notification
 
            email_kwargs = {
 
                'pr_id': pull_request.pull_request_id,
 
                'status_change': status_change,
 
                'pr_comment_url': _url,
 
                'pr_comment_user': h.person(user.email),
 
                'pr_target_repo': h.url('summary_home',
 
                                   repo_name=pull_request.other_repo.repo_name,
 
                                   qualified=True)
 
            }
 
        # create notification objects, and emails
 
        NotificationModel().create(
 
            created_by=user, subject=subj, body=body,
 
            recipients=recipients, type_=notification_type,
 
            email_kwargs=email_kwargs
 
        )
 

	
 
        mention_recipients = set(self._extract_mentions(body))\
 
                                .difference(recipients)
 
        if mention_recipients:
 
            email_kwargs.update({'pr_mention': True})
 
            subj = _('[Mention]') + ' ' + subj
rhodecode/model/db.py
Show inline comments
 
@@ -409,96 +409,116 @@ class User(Base, BaseModel):
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.email.ilike(email))
 
        else:
 
            q = cls.query().filter(cls.email == email)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_email_key_%s" % email))
 

	
 
        ret = q.scalar()
 
        if ret is None:
 
            q = UserEmailMap.query()
 
            # try fetching in alternate email map
 
            if case_insensitive:
 
                q = q.filter(UserEmailMap.email.ilike(email))
 
            else:
 
                q = q.filter(UserEmailMap.email == email)
 
            q = q.options(joinedload(UserEmailMap.user))
 
            if cache:
 
                q = q.options(FromCache("sql_cache_short",
 
                                        "get_email_map_key_%s" % email))
 
            ret = getattr(q.scalar(), 'user', None)
 

	
 
        return ret
 

	
 
    @classmethod
 
    def get_from_cs_author(cls, author):
 
        """
 
        Tries to get User objects out of commit author string
 

	
 
        :param author:
 
        """
 
        from rhodecode.lib.helpers import email, author_name
 
        # Valid email in the attribute passed, see if they're in the system
 
        _email = email(author)
 
        if _email:
 
            user = cls.get_by_email(_email, case_insensitive=True)
 
            if user:
 
                return user
 
        # Maybe we can match by username?
 
        _author = author_name(author)
 
        user = cls.get_by_username(_author, case_insensitive=True)
 
        if user:
 
            return user
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 
        self.last_login = datetime.datetime.now()
 
        Session().add(self)
 
        log.debug('updated user %s lastlogin' % self.username)
 

	
 
    def get_api_data(self):
 
        """
 
        Common function for generating user related data for API
 
        """
 
        user = self
 
        data = dict(
 
            user_id=user.user_id,
 
            username=user.username,
 
            firstname=user.name,
 
            lastname=user.lastname,
 
            email=user.email,
 
            emails=user.emails,
 
            api_key=user.api_key,
 
            active=user.active,
 
            admin=user.admin,
 
            ldap_dn=user.ldap_dn,
 
            last_login=user.last_login,
 
            ip_addresses=user.ip_addresses
 
        )
 
        return data
 

	
 
    def __json__(self):
 
        data = dict(
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 
        data.update(self.get_api_data())
 
        return data
 

	
 

	
 
class UserEmailMap(Base, BaseModel):
 
    __tablename__ = 'user_email_map'
 
    __table_args__ = (
 
        Index('uem_email_idx', 'email'),
 
        UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
0 comments (0 inline, 0 general)