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 | 46 | name='my_account_auth_tokens_delete', |
|
47 | 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 | 59 | # channelstream test |
|
50 | 60 | config.add_route( |
|
51 | 61 | name='my_account_notifications_test_channelstream', |
@@ -21,6 +21,7 b'' | |||
|
21 | 21 | import logging |
|
22 | 22 | import datetime |
|
23 | 23 | |
|
24 | import formencode | |
|
24 | 25 | from pyramid.httpexceptions import HTTPFound |
|
25 | 26 | from pyramid.view import view_config |
|
26 | 27 | |
@@ -32,6 +33,7 b' from rhodecode.lib.channelstream import ' | |||
|
32 | 33 | ChannelstreamException |
|
33 | 34 | from rhodecode.lib.utils2 import safe_int, md5 |
|
34 | 35 | from rhodecode.model.auth_token import AuthTokenModel |
|
36 | from rhodecode.model.db import UserEmailMap | |
|
35 | 37 | from rhodecode.model.meta import Session |
|
36 | 38 | from rhodecode.model.user import UserModel |
|
37 | 39 | from rhodecode.model.validation_schema.schemas import user_schema |
@@ -161,7 +163,7 b' class MyAccountView(BaseAppView):' | |||
|
161 | 163 | @NotAnonymous() |
|
162 | 164 | @CSRFRequired() |
|
163 | 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 | 167 | def my_account_auth_tokens_add(self): |
|
166 | 168 | _ = self.request.translate |
|
167 | 169 | c = self.load_default_context() |
@@ -198,6 +200,65 b' class MyAccountView(BaseAppView):' | |||
|
198 | 200 | |
|
199 | 201 | @LoginRequired() |
|
200 | 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 | 262 | @CSRFRequired() |
|
202 | 263 | @view_config( |
|
203 | 264 | route_name='my_account_notifications_test_channelstream', |
@@ -497,13 +497,6 b' def make_map(config):' | |||
|
497 | 497 | m.connect('my_account_perms', '/my_account/perms', |
|
498 | 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 | 500 | m.connect('my_account_notifications', '/my_account/notifications', |
|
508 | 501 | action='my_notifications', |
|
509 | 502 | conditions={'method': ['GET']}) |
@@ -200,42 +200,6 b' class MyAccountController(BaseController' | |||
|
200 | 200 | |
|
201 | 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 | 203 | def _extract_ordering(self, request): |
|
240 | 204 | column_index = safe_int(request.GET.get('order[0][column]')) |
|
241 | 205 | order_dir = request.GET.get('order[0][dir]', 'desc') |
@@ -34,7 +34,7 b'' | |||
|
34 | 34 | % if my_account_oauth_url: |
|
35 | 35 | <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li> |
|
36 | 36 | % endif |
|
37 |
<li class="${'active' if c.active=='emails' else ''}"><a href="${h. |
|
|
37 | <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('my_account_emails')}">${_('Emails')}</a></li> | |
|
38 | 38 | <li class="${'active' if c.active=='repos' else ''}"><a href="${h.url('my_account_repos')}">${_('Repositories')}</a></li> |
|
39 | 39 | <li class="${'active' if c.active=='watched' else ''}"><a href="${h.url('my_account_watched')}">${_('Watched')}</a></li> |
|
40 | 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 | 25 | <span class="user email">${em.email}</span> |
|
26 | 26 | </td> |
|
27 | 27 | <td class="td-action"> |
|
28 |
${h.secure_form( |
|
|
28 | ${h.secure_form(h.route_path('my_account_emails_delete'), method='POST')} | |
|
29 | 29 | ${h.hidden('del_email_id',em.email_id)} |
|
30 |
<button class="btn btn-link btn-danger" type="submit" id="remove_email_%s |
|
|
31 |
onclick="return confirm('${_('Confirm to delete this email: |
|
|
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: {}').format(em.email)}');"> | |
|
32 | 32 | ${_('Delete')} |
|
33 | 33 | </button> |
|
34 | 34 | ${h.end_form()} |
@@ -48,7 +48,7 b'' | |||
|
48 | 48 | </div> |
|
49 | 49 | |
|
50 | 50 | <div> |
|
51 |
${h.secure_form( |
|
|
51 | ${h.secure_form(h.route_path('my_account_emails_add'), method='POST')} | |
|
52 | 52 | <div class="form"> |
|
53 | 53 | <!-- fields --> |
|
54 | 54 | <div class="fields"> |
@@ -23,8 +23,7 b' import pytest' | |||
|
23 | 23 | from rhodecode.lib import helpers as h |
|
24 | 24 | from rhodecode.model.db import User, UserFollowing, Repository |
|
25 | 25 | from rhodecode.tests import ( |
|
26 |
TestController, url, TEST_USER_ADMIN_LOGIN, |
|
|
27 | assert_session_flash) | |
|
26 | TestController, url, TEST_USER_ADMIN_LOGIN, assert_session_flash) | |
|
28 | 27 | from rhodecode.tests.fixture import Fixture |
|
29 | 28 | from rhodecode.tests.utils import AssertResponse |
|
30 | 29 | |
@@ -90,56 +89,7 b' class TestMyAccountController(TestContro' | |||
|
90 | 89 | response.mustcontain('"name_raw": %s' % pr.pull_request_id) |
|
91 | 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 | 94 | @pytest.mark.parametrize( |
|
145 | 95 | "name, attrs", [ |
General Comments 0
You need to be logged in to leave comments.
Login now