##// END OF EJS Templates
my-account: moved emails config into pyramid views.
marcink -
r1816:7c5e9070 default
parent child Browse files
Show More
@@ -0,0 +1,93 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import pytest
22
23 from rhodecode.apps._base import ADMIN_PREFIX
24 from rhodecode.model.db import User, UserEmailMap
25 from rhodecode.tests import (
26 TestController, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_EMAIL,
27 assert_session_flash)
28 from rhodecode.tests.fixture import Fixture
29
30 fixture = Fixture()
31
32
33 def route_path(name, **kwargs):
34 return {
35 'my_account_emails':
36 ADMIN_PREFIX + '/my_account/emails',
37 'my_account_emails_add':
38 ADMIN_PREFIX + '/my_account/emails/new',
39 'my_account_emails_delete':
40 ADMIN_PREFIX + '/my_account/emails/delete',
41 }[name].format(**kwargs)
42
43
44 class TestMyAccountEmails(TestController):
45 def test_my_account_my_emails(self):
46 self.log_user()
47 response = self.app.get(route_path('my_account_emails'))
48 response.mustcontain('No additional emails specified')
49
50 def test_my_account_my_emails_add_existing_email(self):
51 self.log_user()
52 response = self.app.get(route_path('my_account_emails'))
53 response.mustcontain('No additional emails specified')
54 response = self.app.post(route_path('my_account_emails_add'),
55 {'new_email': TEST_USER_REGULAR_EMAIL,
56 'csrf_token': self.csrf_token})
57 assert_session_flash(response, 'This e-mail address is already taken')
58
59 def test_my_account_my_emails_add_mising_email_in_form(self):
60 self.log_user()
61 response = self.app.get(route_path('my_account_emails'))
62 response.mustcontain('No additional emails specified')
63 response = self.app.post(route_path('my_account_emails_add'),
64 {'csrf_token': self.csrf_token})
65 assert_session_flash(response, 'Please enter an email address')
66
67 def test_my_account_my_emails_add_remove(self):
68 self.log_user()
69 response = self.app.get(route_path('my_account_emails'))
70 response.mustcontain('No additional emails specified')
71
72 response = self.app.post(route_path('my_account_emails_add'),
73 {'new_email': 'foo@barz.com',
74 'csrf_token': self.csrf_token})
75
76 response = self.app.get(route_path('my_account_emails'))
77
78 email_id = UserEmailMap.query().filter(
79 UserEmailMap.user == User.get_by_username(
80 TEST_USER_ADMIN_LOGIN)).filter(
81 UserEmailMap.email == 'foo@barz.com').one().email_id
82
83 response.mustcontain('foo@barz.com')
84 response.mustcontain('<input id="del_email_id" name="del_email_id" '
85 'type="hidden" value="%s" />' % email_id)
86
87 response = self.app.post(
88 route_path('my_account_emails_delete'), {
89 'del_email_id': email_id,
90 'csrf_token': self.csrf_token})
91 assert_session_flash(response, 'Email successfully deleted')
92 response = self.app.get(route_path('my_account_emails'))
93 response.mustcontain('No additional emails specified')
@@ -46,6 +46,16 b' def includeme(config):'
46 name='my_account_auth_tokens_delete',
46 name='my_account_auth_tokens_delete',
47 pattern=ADMIN_PREFIX + '/my_account/auth_tokens/delete')
47 pattern=ADMIN_PREFIX + '/my_account/auth_tokens/delete')
48
48
49 config.add_route(
50 name='my_account_emails',
51 pattern=ADMIN_PREFIX + '/my_account/emails')
52 config.add_route(
53 name='my_account_emails_add',
54 pattern=ADMIN_PREFIX + '/my_account/emails/new')
55 config.add_route(
56 name='my_account_emails_delete',
57 pattern=ADMIN_PREFIX + '/my_account/emails/delete')
58
49 # channelstream test
59 # channelstream test
50 config.add_route(
60 config.add_route(
51 name='my_account_notifications_test_channelstream',
61 name='my_account_notifications_test_channelstream',
@@ -21,6 +21,7 b''
21 import logging
21 import logging
22 import datetime
22 import datetime
23
23
24 import formencode
24 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
25 from pyramid.view import view_config
26 from pyramid.view import view_config
26
27
@@ -32,6 +33,7 b' from rhodecode.lib.channelstream import '
32 ChannelstreamException
33 ChannelstreamException
33 from rhodecode.lib.utils2 import safe_int, md5
34 from rhodecode.lib.utils2 import safe_int, md5
34 from rhodecode.model.auth_token import AuthTokenModel
35 from rhodecode.model.auth_token import AuthTokenModel
36 from rhodecode.model.db import UserEmailMap
35 from rhodecode.model.meta import Session
37 from rhodecode.model.meta import Session
36 from rhodecode.model.user import UserModel
38 from rhodecode.model.user import UserModel
37 from rhodecode.model.validation_schema.schemas import user_schema
39 from rhodecode.model.validation_schema.schemas import user_schema
@@ -161,7 +163,7 b' class MyAccountView(BaseAppView):'
161 @NotAnonymous()
163 @NotAnonymous()
162 @CSRFRequired()
164 @CSRFRequired()
163 @view_config(
165 @view_config(
164 route_name='my_account_auth_tokens_add', request_method='POST')
166 route_name='my_account_auth_tokens_add', request_method='POST',)
165 def my_account_auth_tokens_add(self):
167 def my_account_auth_tokens_add(self):
166 _ = self.request.translate
168 _ = self.request.translate
167 c = self.load_default_context()
169 c = self.load_default_context()
@@ -198,6 +200,65 b' class MyAccountView(BaseAppView):'
198
200
199 @LoginRequired()
201 @LoginRequired()
200 @NotAnonymous()
202 @NotAnonymous()
203 @view_config(
204 route_name='my_account_emails', request_method='GET',
205 renderer='rhodecode:templates/admin/my_account/my_account.mako')
206 def my_account_emails(self):
207 _ = self.request.translate
208
209 c = self.load_default_context()
210 c.active = 'emails'
211
212 c.user_email_map = UserEmailMap.query()\
213 .filter(UserEmailMap.user == c.user).all()
214 return self._get_template_context(c)
215
216 @LoginRequired()
217 @NotAnonymous()
218 @CSRFRequired()
219 @view_config(
220 route_name='my_account_emails_add', request_method='POST')
221 def my_account_emails_add(self):
222 _ = self.request.translate
223 c = self.load_default_context()
224
225 email = self.request.POST.get('new_email')
226
227 try:
228 UserModel().add_extra_email(c.user.user_id, email)
229 Session().commit()
230 h.flash(_("Added new email address `%s` for user account") % email,
231 category='success')
232 except formencode.Invalid as error:
233 msg = error.error_dict['email']
234 h.flash(msg, category='error')
235 except Exception:
236 log.exception("Exception in my_account_emails")
237 h.flash(_('An error occurred during email saving'),
238 category='error')
239 return HTTPFound(h.route_path('my_account_emails'))
240
241 @LoginRequired()
242 @NotAnonymous()
243 @CSRFRequired()
244 @view_config(
245 route_name='my_account_emails_delete', request_method='POST')
246 def my_account_emails_delete(self):
247 _ = self.request.translate
248 c = self.load_default_context()
249
250 del_email_id = self.request.POST.get('del_email_id')
251 if del_email_id:
252
253 UserModel().delete_extra_email(
254 c.user.user_id, del_email_id)
255 Session().commit()
256 h.flash(_("Email successfully deleted"),
257 category='success')
258 return HTTPFound(h.route_path('my_account_emails'))
259
260 @LoginRequired()
261 @NotAnonymous()
201 @CSRFRequired()
262 @CSRFRequired()
202 @view_config(
263 @view_config(
203 route_name='my_account_notifications_test_channelstream',
264 route_name='my_account_notifications_test_channelstream',
@@ -497,13 +497,6 b' def make_map(config):'
497 m.connect('my_account_perms', '/my_account/perms',
497 m.connect('my_account_perms', '/my_account/perms',
498 action='my_account_perms', conditions={'method': ['GET']})
498 action='my_account_perms', conditions={'method': ['GET']})
499
499
500 m.connect('my_account_emails', '/my_account/emails',
501 action='my_account_emails', conditions={'method': ['GET']})
502 m.connect('my_account_emails', '/my_account/emails',
503 action='my_account_emails_add', conditions={'method': ['POST']})
504 m.connect('my_account_emails', '/my_account/emails',
505 action='my_account_emails_delete', conditions={'method': ['DELETE']})
506
507 m.connect('my_account_notifications', '/my_account/notifications',
500 m.connect('my_account_notifications', '/my_account/notifications',
508 action='my_notifications',
501 action='my_notifications',
509 conditions={'method': ['GET']})
502 conditions={'method': ['GET']})
@@ -200,42 +200,6 b' class MyAccountController(BaseController'
200
200
201 return render('admin/my_account/my_account.mako')
201 return render('admin/my_account/my_account.mako')
202
202
203 def my_account_emails(self):
204 c.active = 'emails'
205 self.__load_data()
206
207 c.user_email_map = UserEmailMap.query()\
208 .filter(UserEmailMap.user == c.user).all()
209 return render('admin/my_account/my_account.mako')
210
211 @auth.CSRFRequired()
212 def my_account_emails_add(self):
213 email = request.POST.get('new_email')
214
215 try:
216 UserModel().add_extra_email(c.rhodecode_user.user_id, email)
217 Session().commit()
218 h.flash(_("Added new email address `%s` for user account") % email,
219 category='success')
220 except formencode.Invalid as error:
221 msg = error.error_dict['email']
222 h.flash(msg, category='error')
223 except Exception:
224 log.exception("Exception in my_account_emails")
225 h.flash(_('An error occurred during email saving'),
226 category='error')
227 return redirect(url('my_account_emails'))
228
229 @auth.CSRFRequired()
230 def my_account_emails_delete(self):
231 email_id = request.POST.get('del_email_id')
232 user_model = UserModel()
233 user_model.delete_extra_email(c.rhodecode_user.user_id, email_id)
234 Session().commit()
235 h.flash(_("Removed email address from user account"),
236 category='success')
237 return redirect(url('my_account_emails'))
238
239 def _extract_ordering(self, request):
203 def _extract_ordering(self, request):
240 column_index = safe_int(request.GET.get('order[0][column]'))
204 column_index = safe_int(request.GET.get('order[0][column]'))
241 order_dir = request.GET.get('order[0][dir]', 'desc')
205 order_dir = request.GET.get('order[0][dir]', 'desc')
@@ -34,7 +34,7 b''
34 % if my_account_oauth_url:
34 % if my_account_oauth_url:
35 <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li>
35 <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li>
36 % endif
36 % endif
37 <li class="${'active' if c.active=='emails' else ''}"><a href="${h.url('my_account_emails')}">${_('Emails')}</a></li>
37 <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('my_account_emails')}">${_('Emails')}</a></li>
38 <li class="${'active' if c.active=='repos' else ''}"><a href="${h.url('my_account_repos')}">${_('Repositories')}</a></li>
38 <li class="${'active' if c.active=='repos' else ''}"><a href="${h.url('my_account_repos')}">${_('Repositories')}</a></li>
39 <li class="${'active' if c.active=='watched' else ''}"><a href="${h.url('my_account_watched')}">${_('Watched')}</a></li>
39 <li class="${'active' if c.active=='watched' else ''}"><a href="${h.url('my_account_watched')}">${_('Watched')}</a></li>
40 <li class="${'active' if c.active=='pullrequests' else ''}"><a href="${h.url('my_account_pullrequests')}">${_('Pull Requests')}</a></li>
40 <li class="${'active' if c.active=='pullrequests' else ''}"><a href="${h.url('my_account_pullrequests')}">${_('Pull Requests')}</a></li>
@@ -25,10 +25,10 b''
25 <span class="user email">${em.email}</span>
25 <span class="user email">${em.email}</span>
26 </td>
26 </td>
27 <td class="td-action">
27 <td class="td-action">
28 ${h.secure_form(url('my_account_emails'),method='delete')}
28 ${h.secure_form(h.route_path('my_account_emails_delete'), method='POST')}
29 ${h.hidden('del_email_id',em.email_id)}
29 ${h.hidden('del_email_id',em.email_id)}
30 <button class="btn btn-link btn-danger" type="submit" id="remove_email_%s" % em.email_id
30 <button class="btn btn-link btn-danger" type="submit" id="${'remove_email_%s'.format(em.email_id)}"
31 onclick="return confirm('${_('Confirm to delete this email: %s') % em.email}');">
31 onclick="return confirm('${_('Confirm to delete this email: {}').format(em.email)}');">
32 ${_('Delete')}
32 ${_('Delete')}
33 </button>
33 </button>
34 ${h.end_form()}
34 ${h.end_form()}
@@ -48,7 +48,7 b''
48 </div>
48 </div>
49
49
50 <div>
50 <div>
51 ${h.secure_form(url('my_account_emails'), method='post')}
51 ${h.secure_form(h.route_path('my_account_emails_add'), method='POST')}
52 <div class="form">
52 <div class="form">
53 <!-- fields -->
53 <!-- fields -->
54 <div class="fields">
54 <div class="fields">
@@ -23,8 +23,7 b' import pytest'
23 from rhodecode.lib import helpers as h
23 from rhodecode.lib import helpers as h
24 from rhodecode.model.db import User, UserFollowing, Repository
24 from rhodecode.model.db import User, UserFollowing, Repository
25 from rhodecode.tests import (
25 from rhodecode.tests import (
26 TestController, url, TEST_USER_ADMIN_LOGIN, TEST_USER_REGULAR_EMAIL,
26 TestController, url, TEST_USER_ADMIN_LOGIN, assert_session_flash)
27 assert_session_flash)
28 from rhodecode.tests.fixture import Fixture
27 from rhodecode.tests.fixture import Fixture
29 from rhodecode.tests.utils import AssertResponse
28 from rhodecode.tests.utils import AssertResponse
30
29
@@ -90,56 +89,7 b' class TestMyAccountController(TestContro'
90 response.mustcontain('"name_raw": %s' % pr.pull_request_id)
89 response.mustcontain('"name_raw": %s' % pr.pull_request_id)
91 response.mustcontain('TestMyAccountPR')
90 response.mustcontain('TestMyAccountPR')
92
91
93 def test_my_account_my_emails(self):
94 self.log_user()
95 response = self.app.get(url('my_account_emails'))
96 response.mustcontain('No additional emails specified')
97
92
98 def test_my_account_my_emails_add_existing_email(self):
99 self.log_user()
100 response = self.app.get(url('my_account_emails'))
101 response.mustcontain('No additional emails specified')
102 response = self.app.post(url('my_account_emails'),
103 {'new_email': TEST_USER_REGULAR_EMAIL,
104 'csrf_token': self.csrf_token})
105 assert_session_flash(response, 'This e-mail address is already taken')
106
107 def test_my_account_my_emails_add_mising_email_in_form(self):
108 self.log_user()
109 response = self.app.get(url('my_account_emails'))
110 response.mustcontain('No additional emails specified')
111 response = self.app.post(url('my_account_emails'),
112 {'csrf_token': self.csrf_token})
113 assert_session_flash(response, 'Please enter an email address')
114
115 def test_my_account_my_emails_add_remove(self):
116 self.log_user()
117 response = self.app.get(url('my_account_emails'))
118 response.mustcontain('No additional emails specified')
119
120 response = self.app.post(url('my_account_emails'),
121 {'new_email': 'foo@barz.com',
122 'csrf_token': self.csrf_token})
123
124 response = self.app.get(url('my_account_emails'))
125
126 from rhodecode.model.db import UserEmailMap
127 email_id = UserEmailMap.query().filter(
128 UserEmailMap.user == User.get_by_username(
129 TEST_USER_ADMIN_LOGIN)).filter(
130 UserEmailMap.email == 'foo@barz.com').one().email_id
131
132 response.mustcontain('foo@barz.com')
133 response.mustcontain('<input id="del_email_id" name="del_email_id" '
134 'type="hidden" value="%s" />' % email_id)
135
136 response = self.app.post(
137 url('my_account_emails'), {
138 'del_email_id': email_id, '_method': 'delete',
139 'csrf_token': self.csrf_token})
140 assert_session_flash(response, 'Removed email address from user account')
141 response = self.app.get(url('my_account_emails'))
142 response.mustcontain('No additional emails specified')
143
93
144 @pytest.mark.parametrize(
94 @pytest.mark.parametrize(
145 "name, attrs", [
95 "name, attrs", [
General Comments 0
You need to be logged in to leave comments. Login now