##// END OF EJS Templates
notifications: use an explicit FK mark when creating notifications, previous way was prone to cache problems.
marcink -
r2897:1a98e88c default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,196 +1,197 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import pytest
21 import pytest
22
22
23 from rhodecode.apps._base import ADMIN_PREFIX
23 from rhodecode.apps._base import ADMIN_PREFIX
24 from rhodecode.tests import (
24 from rhodecode.tests import (
25 TestController, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
25 TestController, TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
26 TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
26 TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
27 from rhodecode.tests.fixture import Fixture
27 from rhodecode.tests.fixture import Fixture
28
28
29 from rhodecode.model.db import Notification, User
29 from rhodecode.model.db import Notification, User
30 from rhodecode.model.user import UserModel
30 from rhodecode.model.user import UserModel
31 from rhodecode.model.notification import NotificationModel
31 from rhodecode.model.notification import NotificationModel
32 from rhodecode.model.meta import Session
32 from rhodecode.model.meta import Session
33
33
34 fixture = Fixture()
34 fixture = Fixture()
35
35
36
36
37 def route_path(name, params=None, **kwargs):
37 def route_path(name, params=None, **kwargs):
38 import urllib
38 import urllib
39 from rhodecode.apps._base import ADMIN_PREFIX
39 from rhodecode.apps._base import ADMIN_PREFIX
40
40
41 base_url = {
41 base_url = {
42 'notifications_show_all': ADMIN_PREFIX + '/notifications',
42 'notifications_show_all': ADMIN_PREFIX + '/notifications',
43 'notifications_mark_all_read': ADMIN_PREFIX + '/notifications/mark_all_read',
43 'notifications_mark_all_read': ADMIN_PREFIX + '/notifications/mark_all_read',
44 'notifications_show': ADMIN_PREFIX + '/notifications/{notification_id}',
44 'notifications_show': ADMIN_PREFIX + '/notifications/{notification_id}',
45 'notifications_update': ADMIN_PREFIX + '/notifications/{notification_id}/update',
45 'notifications_update': ADMIN_PREFIX + '/notifications/{notification_id}/update',
46 'notifications_delete': ADMIN_PREFIX + '/notifications/{notification_id}/delete',
46 'notifications_delete': ADMIN_PREFIX + '/notifications/{notification_id}/delete',
47
47
48 }[name].format(**kwargs)
48 }[name].format(**kwargs)
49
49
50 if params:
50 if params:
51 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
51 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
52 return base_url
52 return base_url
53
53
54
54
55 class TestNotificationsController(TestController):
55 class TestNotificationsController(TestController):
56
56
57 def teardown_method(self, method):
57 def teardown_method(self, method):
58 for n in Notification.query().all():
58 for n in Notification.query().all():
59 inst = Notification.get(n.notification_id)
59 inst = Notification.get(n.notification_id)
60 Session().delete(inst)
60 Session().delete(inst)
61 Session().commit()
61 Session().commit()
62
62
63 def test_show_all(self, user_util):
63 def test_show_all(self, user_util):
64 user = user_util.create_user(password='qweqwe')
64 user = user_util.create_user(password='qweqwe')
65 user_id = user.user_id
65 user_id = user.user_id
66 self.log_user(user.username, 'qweqwe')
66 self.log_user(user.username, 'qweqwe')
67
67
68 response = self.app.get(
68 response = self.app.get(
69 route_path('notifications_show_all', params={'type': 'all'}))
69 route_path('notifications_show_all', params={'type': 'all'}))
70 response.mustcontain(
70 response.mustcontain(
71 '<div class="table">No notifications here yet</div>')
71 '<div class="table">No notifications here yet</div>')
72
72
73 notification = NotificationModel().create(
73 notification = NotificationModel().create(
74 created_by=user_id, notification_subject=u'test_notification_1',
74 created_by=user_id, notification_subject=u'test_notification_1',
75 notification_body=u'notification_1', recipients=[user_id])
75 notification_body=u'notification_1', recipients=[user_id])
76 Session().commit()
76 Session().commit()
77 notification_id = notification.notification_id
77 notification_id = notification.notification_id
78
78
79 response = self.app.get(route_path('notifications_show_all',
79 response = self.app.get(route_path('notifications_show_all',
80 params={'type': 'all'}))
80 params={'type': 'all'}))
81 response.mustcontain('id="notification_%s"' % notification_id)
81 response.mustcontain('id="notification_%s"' % notification_id)
82
82
83 def test_show_unread(self, user_util):
83 def test_show_unread(self, user_util):
84 user = user_util.create_user(password='qweqwe')
84 user = user_util.create_user(password='qweqwe')
85 user_id = user.user_id
85 user_id = user.user_id
86 self.log_user(user.username, 'qweqwe')
86 self.log_user(user.username, 'qweqwe')
87
87
88 response = self.app.get(route_path('notifications_show_all'))
88 response = self.app.get(route_path('notifications_show_all'))
89 response.mustcontain(
89 response.mustcontain(
90 '<div class="table">No notifications here yet</div>')
90 '<div class="table">No notifications here yet</div>')
91
91
92 notification = NotificationModel().create(
92 notification = NotificationModel().create(
93 created_by=user_id, notification_subject=u'test_notification_1',
93 created_by=user_id, notification_subject=u'test_notification_1',
94 notification_body=u'notification_1', recipients=[user_id])
94 notification_body=u'notification_1', recipients=[user_id])
95
95
96 # mark the USER notification as unread
96 # mark the USER notification as unread
97 user_notification = NotificationModel().get_user_notification(
97 user_notification = NotificationModel().get_user_notification(
98 user_id, notification)
98 user_id, notification)
99 user_notification.read = False
99 user_notification.read = False
100
100
101 Session().commit()
101 Session().commit()
102 notification_id = notification.notification_id
102 notification_id = notification.notification_id
103
103
104 response = self.app.get(route_path('notifications_show_all'))
104 response = self.app.get(route_path('notifications_show_all'))
105 response.mustcontain('id="notification_%s"' % notification_id)
105 response.mustcontain('id="notification_%s"' % notification_id)
106 response.mustcontain('<div class="desc unread')
106 response.mustcontain('<div class="desc unread')
107
107
108 @pytest.mark.parametrize('user,password', [
108 @pytest.mark.parametrize('user,password', [
109 (TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS),
109 (TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS),
110 (TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS),
110 (TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS),
111 ])
111 ])
112 def test_delete(self, user, password, user_util):
112 def test_delete(self, user, password, user_util):
113 self.log_user(user, password)
113 self.log_user(user, password)
114 cur_user = self._get_logged_user()
114 cur_user = self._get_logged_user()
115
115
116 u1 = user_util.create_user()
116 u1 = user_util.create_user()
117 u2 = user_util.create_user()
117 u2 = user_util.create_user()
118
118
119 # make notifications
119 # make notifications
120 notification = NotificationModel().create(
120 notification = NotificationModel().create(
121 created_by=cur_user, notification_subject=u'test',
121 created_by=cur_user, notification_subject=u'test',
122 notification_body=u'hi there', recipients=[cur_user, u1, u2])
122 notification_body=u'hi there', recipients=[cur_user, u1, u2])
123 Session().commit()
123 Session().commit()
124 u1 = User.get(u1.user_id)
124 u1 = User.get(u1.user_id)
125 u2 = User.get(u2.user_id)
125 u2 = User.get(u2.user_id)
126
126
127 # check DB
127 # check DB
128 get_notif = lambda un: [x.notification for x in un]
128 get_notif = lambda un: [x.notification for x in un]
129 assert get_notif(cur_user.notifications) == [notification]
129 assert get_notif(cur_user.notifications) == [notification]
130 assert get_notif(u1.notifications) == [notification]
130 assert get_notif(u1.notifications) == [notification]
131 assert get_notif(u2.notifications) == [notification]
131 assert get_notif(u2.notifications) == [notification]
132 cur_usr_id = cur_user.user_id
132 cur_usr_id = cur_user.user_id
133
133
134 response = self.app.post(
134 response = self.app.post(
135 route_path('notifications_delete',
135 route_path('notifications_delete',
136 notification_id=notification.notification_id),
136 notification_id=notification.notification_id),
137 params={'csrf_token': self.csrf_token})
137 params={'csrf_token': self.csrf_token})
138 assert response.json == 'ok'
138 assert response.json == 'ok'
139
139
140 cur_user = User.get(cur_usr_id)
140 cur_user = User.get(cur_usr_id)
141 assert cur_user.notifications == []
141 assert cur_user.notifications == []
142
142
143 @pytest.mark.parametrize('user,password', [
143 @pytest.mark.parametrize('user,password', [
144 (TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS),
144 (TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS),
145 (TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS),
145 (TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS),
146 ])
146 ])
147 def test_show(self, user, password, user_util):
147 def test_show(self, user, password, user_util):
148 self.log_user(user, password)
148 self.log_user(user, password)
149 cur_user = self._get_logged_user()
149 cur_user = self._get_logged_user()
150 u1 = user_util.create_user()
150 u1 = user_util.create_user()
151 u2 = user_util.create_user()
151 u2 = user_util.create_user()
152
152
153 subject = u'test'
153 subject = u'test'
154 notif_body = u'hi there'
154 notif_body = u'hi there'
155 notification = NotificationModel().create(
155 notification = NotificationModel().create(
156 created_by=cur_user, notification_subject=subject,
156 created_by=cur_user, notification_subject=subject,
157 notification_body=notif_body, recipients=[cur_user, u1, u2])
157 notification_body=notif_body, recipients=[cur_user, u1, u2])
158 Session().commit()
158
159
159 response = self.app.get(
160 response = self.app.get(
160 route_path('notifications_show',
161 route_path('notifications_show',
161 notification_id=notification.notification_id))
162 notification_id=notification.notification_id))
162
163
163 response.mustcontain(subject)
164 response.mustcontain(subject)
164 response.mustcontain(notif_body)
165 response.mustcontain(notif_body)
165
166
166 @pytest.mark.parametrize('user,password', [
167 @pytest.mark.parametrize('user,password', [
167 (TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS),
168 (TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS),
168 (TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS),
169 (TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS),
169 ])
170 ])
170 def test_update(self, user, password, user_util):
171 def test_update(self, user, password, user_util):
171 self.log_user(user, password)
172 self.log_user(user, password)
172 cur_user = self._get_logged_user()
173 cur_user = self._get_logged_user()
173 u1 = user_util.create_user()
174 u1 = user_util.create_user()
174 u2 = user_util.create_user()
175 u2 = user_util.create_user()
175
176
176 # make notifications
177 # make notifications
177 recipients = [cur_user, u1, u2]
178 recipients = [cur_user, u1, u2]
178 notification = NotificationModel().create(
179 notification = NotificationModel().create(
179 created_by=cur_user, notification_subject=u'test',
180 created_by=cur_user, notification_subject=u'test',
180 notification_body=u'hi there', recipients=recipients)
181 notification_body=u'hi there', recipients=recipients)
181 Session().commit()
182 Session().commit()
182
183
183 for u_obj in recipients:
184 for u_obj in recipients:
184 # if it's current user, he has his message already read
185 # if it's current user, he has his message already read
185 read = u_obj.username == user
186 read = u_obj.username == user
186 assert len(u_obj.notifications) == 1
187 assert len(u_obj.notifications) == 1
187 assert u_obj.notifications[0].read == read
188 assert u_obj.notifications[0].read == read
188
189
189 response = self.app.post(
190 response = self.app.post(
190 route_path('notifications_update',
191 route_path('notifications_update',
191 notification_id=notification.notification_id),
192 notification_id=notification.notification_id),
192 params={'csrf_token': self.csrf_token})
193 params={'csrf_token': self.csrf_token})
193 assert response.json == 'ok'
194 assert response.json == 'ok'
194
195
195 cur_user = self._get_logged_user()
196 cur_user = self._get_logged_user()
196 assert True is cur_user.notifications[0].read
197 assert True is cur_user.notifications[0].read
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now