##// END OF EJS Templates
fix default permissions migrations that can cause troubles for some old users
fix default permissions migrations that can cause troubles for some old users

File last commit:

r2610:3fdf7c3b beta
r2795:456a5190 beta
Show More
notification.py
274 lines | 9.7 KiB | text/x-python | PythonLexer
#302 - basic notification system, models+tests
r1702 # -*- coding: utf-8 -*-
"""
rhodecode.model.notification
docs update
r1839 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#302 - basic notification system, models+tests
r1702
Model for notifications
pep8ify
r1800
#302 - basic notification system, models+tests
r1702 :created_on: Nov 20, 2011
:author: marcink
2012 copyrights
r1824 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
#302 - basic notification system, models+tests
r1702 :license: GPLv3, see COPYING for more details.
"""
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
Notification fixes...
r1717 import os
#302 - basic notification system, models+tests
r1702 import logging
import traceback
from pylons.i18n.translation import _
- refactoring to overcome poor usage of global pylons config...
r1723 import rhodecode
Notification fixes...
r1717 from rhodecode.lib import helpers as h
#302 - basic notification system, models+tests
r1702 from rhodecode.model import BaseModel
from rhodecode.model.db import Notification, User, UserNotification
Notification system improvements...
r1712 log = logging.getLogger(__name__)
#302 - basic notification system, models+tests
r1702
notification to commit author + gardening
r1716
#302 - basic notification system, models+tests
r1702 class NotificationModel(BaseModel):
Added associated classes into child models
r2522 cls = Notification
Notification system improvements...
r1712 def __get_notification(self, notification):
if isinstance(notification, Notification):
return notification
Mysql fixes...
r2149 elif isinstance(notification, (int, long)):
Notification system improvements...
r1712 return Notification.get(notification)
else:
if notification:
Mysql fixes...
r2149 raise Exception('notification must be int, long or Instance'
Notification system improvements...
r1712 ' of Notification got %s' % type(notification))
implements #222 registration feedback...
r1731 def create(self, created_by, subject, body, recipients=None,
type_=Notification.TYPE_MESSAGE, with_email=True,
email_kwargs={}):
notification fixes and improvements
r1703 """
pep8ify
r1800
notification fixes and improvements
r1703 Creates notification of given type
pep8ify
r1800
notification fixes and improvements
r1703 :param created_by: int, str or User instance. User who created this
notification
:param subject:
:param body:
auto white-space removal
r1818 :param recipients: list of int, str or User objects, when None
implements #222 registration feedback...
r1731 is given send to all admins
notification fixes and improvements
r1703 :param type_: type of notification
implements #222 registration feedback...
r1731 :param with_email: send email with this notification
:param email_kwargs: additional dict to pass as args to email template
notification fixes and improvements
r1703 """
#235 forking page repo group selection...
r1722 from rhodecode.lib.celerylib import tasks, run_task
#302 - basic notification system, models+tests
r1702
implements #222 registration feedback...
r1731 if recipients and not getattr(recipients, '__iter__', False):
#302 - basic notification system, models+tests
r1702 raise Exception('recipients must be a list of iterable')
Share common getter functions in base model, and remove duplicated functions from other models
r2432 created_by_obj = self._get_user(created_by)
#302 - basic notification system, models+tests
r1702
implements #222 registration feedback...
r1731 if recipients:
recipients_objs = []
for u in recipients:
Share common getter functions in base model, and remove duplicated functions from other models
r2432 obj = self._get_user(u)
implements #222 registration feedback...
r1731 if obj:
recipients_objs.append(obj)
recipients_objs = set(recipients_objs)
code garden
r2077 log.debug('sending notifications %s to %s' % (
type_, recipients_objs)
)
implements #222 registration feedback...
r1731 else:
# empty recipients means to all admins
recipients_objs = User.query().filter(User.admin == True).all()
code garden
r2077 log.debug('sending notifications %s to admins: %s' % (
type_, recipients_objs)
)
notif = Notification.create(
created_by=created_by_obj, subject=subject,
body=body, recipients=recipients_objs, type_=type_
)
Notification fixes...
r1717
implements #222 registration feedback...
r1731 if with_email is False:
return notif
Don't send emails to person who comment on changeset
r2387 #don't send email to person who created this comment
rec_objs = set(recipients_objs).difference(set([created_by_obj]))
# send email with notification to all other participants
for rec in rec_objs:
Notification fixes...
r1717 email_subject = NotificationModel().make_description(notif, False)
implements #222 registration feedback...
r1731 type_ = type_
Notification fixes...
r1717 email_body = body
Add changeset status change into emails
r2296 ## this is passed into template
pep8ify
r1800 kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
implements #222 registration feedback...
r1731 kwargs.update(email_kwargs)
Notification fixes...
r1717 email_body_html = EmailNotificationModel()\
implements #222 registration feedback...
r1731 .get_email_tmpl(type_, **kwargs)
Use __unicode__ instead of __repr__ in models.
r2156
#235 forking page repo group selection...
r1722 run_task(tasks.send_email, rec.email, email_subject, email_body,
Notification fixes...
r1717 email_body_html)
return notif
#302 - basic notification system, models+tests
r1702
Tests updates, Session refactoring
r1713 def delete(self, user, notification):
# we don't want to remove actual notification just the assignment
Notification system improvements...
r1712 try:
Tests updates, Session refactoring
r1713 notification = self.__get_notification(notification)
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Tests updates, Session refactoring
r1713 if notification and user:
Notification fixes...
r1717 obj = UserNotification.query()\
.filter(UserNotification.user == user)\
.filter(UserNotification.notification
== notification)\
.one()
Tests updates, Session refactoring
r1713 self.sa.delete(obj)
Notification system improvements...
r1712 return True
except Exception:
log.error(traceback.format_exc())
raise
#302 - basic notification system, models+tests
r1702
Added pull requests filter into notification inbox....
r2433 def get_for_user(self, user, filter_=None):
"""
Get mentions for given user, filter them if filter dict is given
:param user:
:type user:
:param filter:
"""
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Added pull requests filter into notification inbox....
r2433
q = UserNotification.query()\
.filter(UserNotification.user == user)\
.join((Notification, UserNotification.notification_id ==
Notification.notification_id))
if filter_:
Added filtering on inbox by comments
r2503 q = q.filter(Notification.type_.in_(filter_))
#302 - basic notification system, models+tests
r1702
Added pull requests filter into notification inbox....
r2433 return q.all()
added mark as read for single notifications
r2610 def mark_read(self, user, notification):
try:
notification = self.__get_notification(notification)
user = self._get_user(user)
if notification and user:
obj = UserNotification.query()\
.filter(UserNotification.user == user)\
.filter(UserNotification.notification
== notification)\
.one()
obj.read = True
self.sa.add(obj)
return True
except Exception:
log.error(traceback.format_exc())
raise
Added pull requests filter into notification inbox....
r2433 def mark_all_read_for_user(self, user, filter_=None):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Added pull requests filter into notification inbox....
r2433 q = UserNotification.query()\
.filter(UserNotification.user == user)\
Implemented initial code-review status of changesets
r2217 .filter(UserNotification.read == False)\
Added pull requests filter into notification inbox....
r2433 .join((Notification, UserNotification.notification_id ==
Notification.notification_id))
if filter_:
Added filtering on inbox by comments
r2503 q = q.filter(Notification.type_.in_(filter_))
Added pull requests filter into notification inbox....
r2433
# this is a little inefficient but sqlalchemy doesn't support
# update on joined tables :(
for obj in q.all():
obj.read = True
self.sa.add(obj)
mark all read button for notifications
r1791
Tests updates, Session refactoring
r1713 def get_unread_cnt_for_user(self, user):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
#302 - basic notification system, models+tests
r1702 return UserNotification.query()\
Notification system improvements...
r1712 .filter(UserNotification.read == False)\
Tests updates, Session refactoring
r1713 .filter(UserNotification.user == user).count()
#302 - basic notification system, models+tests
r1702
Tests updates, Session refactoring
r1713 def get_unread_for_user(self, user):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
#302 - basic notification system, models+tests
r1702 return [x.notification for x in UserNotification.query()\
Notification system improvements...
r1712 .filter(UserNotification.read == False)\
Tests updates, Session refactoring
r1713 .filter(UserNotification.user == user).all()]
Notification system improvements...
r1712
def get_user_notification(self, user, notification):
Share common getter functions in base model, and remove duplicated functions from other models
r2432 user = self._get_user(user)
Notification system improvements...
r1712 notification = self.__get_notification(notification)
return UserNotification.query()\
.filter(UserNotification.notification == notification)\
.filter(UserNotification.user == user).scalar()
Notification fixes...
r1717 def make_description(self, notification, show_age=True):
Notification system improvements...
r1712 """
Creates a human readable description based on properties
of notification object
"""
- added commenting to pull requests...
r2443 #alias
_n = notification
code garden
r2082 _map = {
- added commenting to pull requests...
r2443 _n.TYPE_CHANGESET_COMMENT: _('commented on commit'),
_n.TYPE_MESSAGE: _('sent message'),
_n.TYPE_MENTION: _('mentioned you'),
_n.TYPE_REGISTRATION: _('registered in RhodeCode'),
_n.TYPE_PULL_REQUEST: _('opened new pull request'),
_n.TYPE_PULL_REQUEST_COMMENT: _('commented on pull request')
code garden
r2082 }
implements #222 registration feedback...
r1731
Format datetime in notifications according to unified function
r2445 # action == _map string
tmpl = "%(user)s %(action)s at %(when)s"
Notification fixes...
r1717 if show_age:
when = h.age(notification.created_on)
else:
Format datetime in notifications according to unified function
r2445 when = h.fmt_date(notification.created_on)
Use __unicode__ instead of __repr__ in models.
r2156
code garden
r2082 data = dict(
user=notification.created_by_user.username,
action=_map[notification.type_], when=when,
)
Notification system improvements...
r1712 return tmpl % data
Notification fixes...
r1717
class EmailNotificationModel(BaseModel):
test fixes
r1732 TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
Notification fixes...
r1717 TYPE_PASSWORD_RESET = 'passoword_link'
test fixes
r1732 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
Added basic models for saving open pull requests...
r2434 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
Notification fixes...
r1717 TYPE_DEFAULT = 'default'
def __init__(self):
- refactoring to overcome poor usage of global pylons config...
r1723 self._template_root = rhodecode.CONFIG['pylons.paths']['templates'][0]
self._tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
Notification fixes...
r1717
self.email_types = {
code garden
r2082 self.TYPE_CHANGESET_COMMENT: 'email_templates/changeset_comment.html',
self.TYPE_PASSWORD_RESET: 'email_templates/password_reset.html',
self.TYPE_REGISTRATION: 'email_templates/registration.html',
self.TYPE_DEFAULT: 'email_templates/default.html'
Notification fixes...
r1717 }
def get_email_tmpl(self, type_, **kwargs):
"""
return generated template for email based on given type
auto white-space removal
r1818
Notification fixes...
r1717 :param type_:
"""
- refactoring to overcome poor usage of global pylons config...
r1723
test fixes
r1732 base = self.email_types.get(type_, self.email_types[self.TYPE_DEFAULT])
- refactoring to overcome poor usage of global pylons config...
r1723 email_template = self._tmpl_lookup.get_template(base)
Notification fixes...
r1717 # translator inject
code garden
r2082 _kwargs = {'_': _}
Notification fixes...
r1717 _kwargs.update(kwargs)
log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
return email_template.render(**_kwargs)