##// END OF EJS Templates
my-account: moved few my account views into pyramid.
marcink -
r1819:956c5cda default
parent child Browse files
Show More
@@ -0,0 +1,76 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, Repository, UserFollowing
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_repos':
36 ADMIN_PREFIX + '/my_account/repos',
37 'my_account_watched':
38 ADMIN_PREFIX + '/my_account/watched',
39 'my_account_perms':
40 ADMIN_PREFIX + '/my_account/perms',
41 'my_account_notifications':
42 ADMIN_PREFIX + '/my_account/notifications',
43 }[name].format(**kwargs)
44
45
46 class TestMyAccountSimpleViews(TestController):
47
48 def test_my_account_my_repos(self, autologin_user):
49 response = self.app.get(route_path('my_account_repos'))
50 repos = Repository.query().filter(
51 Repository.user == User.get_by_username(
52 TEST_USER_ADMIN_LOGIN)).all()
53 for repo in repos:
54 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
55
56 def test_my_account_my_watched(self, autologin_user):
57 response = self.app.get(route_path('my_account_watched'))
58
59 repos = UserFollowing.query().filter(
60 UserFollowing.user == User.get_by_username(
61 TEST_USER_ADMIN_LOGIN)).all()
62 for repo in repos:
63 response.mustcontain(
64 '"name_raw": "%s"' % repo.follows_repository.repo_name)
65
66 def test_my_account_perms(self, autologin_user):
67 response = self.app.get(route_path('my_account_perms'))
68 assert_response = response.assert_response()
69 assert assert_response.get_elements('.perm_tag.none')
70 assert assert_response.get_elements('.perm_tag.read')
71 assert assert_response.get_elements('.perm_tag.write')
72 assert assert_response.get_elements('.perm_tag.admin')
73
74 def test_my_account_notifications(self, autologin_user):
75 response = self.app.get(route_path('my_account_notifications'))
76 response.mustcontain('Test flash message')
@@ -56,6 +56,26 b' def includeme(config):'
56 56 name='my_account_emails_delete',
57 57 pattern=ADMIN_PREFIX + '/my_account/emails/delete')
58 58
59 config.add_route(
60 name='my_account_repos',
61 pattern=ADMIN_PREFIX + '/my_account/repos')
62
63 config.add_route(
64 name='my_account_watched',
65 pattern=ADMIN_PREFIX + '/my_account/watched')
66
67 config.add_route(
68 name='my_account_perms',
69 pattern=ADMIN_PREFIX + '/my_account/perms')
70
71 config.add_route(
72 name='my_account_notifications',
73 pattern=ADMIN_PREFIX + '/my_account/notifications')
74
75 config.add_route(
76 name='my_account_notifications_toggle_visibility',
77 pattern=ADMIN_PREFIX + '/my_account/toggle_visibility')
78
59 79 # channelstream test
60 80 config.add_route(
61 81 name='my_account_notifications_test_channelstream',
@@ -28,14 +28,18 b' from pyramid.view import view_config'
28 28 from rhodecode.apps._base import BaseAppView
29 29 from rhodecode import forms
30 30 from rhodecode.lib import helpers as h
31 from rhodecode.lib.ext_json import json
31 32 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired
32 33 from rhodecode.lib.channelstream import channelstream_request, \
33 34 ChannelstreamException
34 35 from rhodecode.lib.utils2 import safe_int, md5
35 36 from rhodecode.model.auth_token import AuthTokenModel
36 from rhodecode.model.db import UserEmailMap
37 from rhodecode.model.db import (
38 Repository, PullRequest, UserEmailMap, User, UserFollowing, joinedload)
37 39 from rhodecode.model.meta import Session
40 from rhodecode.model.scm import RepoList
38 41 from rhodecode.model.user import UserModel
42 from rhodecode.model.repo import RepoModel
39 43 from rhodecode.model.validation_schema.schemas import user_schema
40 44
41 45 log = logging.getLogger(__name__)
@@ -290,3 +294,85 b' class MyAccountView(BaseAppView):'
290 294 return {"response": 'ERROR: {}'.format(e.__class__.__name__)}
291 295 return {"response": 'Channelstream data sent. '
292 296 'You should see a new live message now.'}
297
298 def _load_my_repos_data(self, watched=False):
299 if watched:
300 admin = False
301 follows_repos = Session().query(UserFollowing)\
302 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
303 .options(joinedload(UserFollowing.follows_repository))\
304 .all()
305 repo_list = [x.follows_repository for x in follows_repos]
306 else:
307 admin = True
308 repo_list = Repository.get_all_repos(
309 user_id=self._rhodecode_user.user_id)
310 repo_list = RepoList(repo_list, perm_set=[
311 'repository.read', 'repository.write', 'repository.admin'])
312
313 repos_data = RepoModel().get_repos_as_dict(
314 repo_list=repo_list, admin=admin)
315 # json used to render the grid
316 return json.dumps(repos_data)
317
318 @LoginRequired()
319 @NotAnonymous()
320 @view_config(
321 route_name='my_account_repos', request_method='GET',
322 renderer='rhodecode:templates/admin/my_account/my_account.mako')
323 def my_account_repos(self):
324 c = self.load_default_context()
325 c.active = 'repos'
326
327 # json used to render the grid
328 c.data = self._load_my_repos_data()
329 return self._get_template_context(c)
330
331 @LoginRequired()
332 @NotAnonymous()
333 @view_config(
334 route_name='my_account_watched', request_method='GET',
335 renderer='rhodecode:templates/admin/my_account/my_account.mako')
336 def my_account_watched(self):
337 c = self.load_default_context()
338 c.active = 'watched'
339
340 # json used to render the grid
341 c.data = self._load_my_repos_data(watched=True)
342 return self._get_template_context(c)
343
344 @LoginRequired()
345 @NotAnonymous()
346 @view_config(
347 route_name='my_account_perms', request_method='GET',
348 renderer='rhodecode:templates/admin/my_account/my_account.mako')
349 def my_account_perms(self):
350 c = self.load_default_context()
351 c.active = 'perms'
352
353 c.perm_user = c.auth_user
354 return self._get_template_context(c)
355
356 @LoginRequired()
357 @NotAnonymous()
358 @view_config(
359 route_name='my_account_notifications', request_method='GET',
360 renderer='rhodecode:templates/admin/my_account/my_account.mako')
361 def my_notifications(self):
362 c = self.load_default_context()
363 c.active = 'notifications'
364
365 return self._get_template_context(c)
366
367 @LoginRequired()
368 @NotAnonymous()
369 @CSRFRequired()
370 @view_config(
371 route_name='my_account_notifications_toggle_visibility',
372 request_method='POST', renderer='json_ext')
373 def my_notifications_toggle_visibility(self):
374 user = self._rhodecode_db_user
375 new_status = not user.user_data.get('notification_status', True)
376 user.update_userdata(notification_status=new_status)
377 Session().commit()
378 return user.user_data['notification_status'] No newline at end of file
@@ -485,26 +485,9 b' def make_map(config):'
485 485 m.connect('my_account_password', '/my_account/password',
486 486 action='my_account_password', conditions={'method': ['GET']})
487 487
488 m.connect('my_account_repos', '/my_account/repos',
489 action='my_account_repos', conditions={'method': ['GET']})
490
491 m.connect('my_account_watched', '/my_account/watched',
492 action='my_account_watched', conditions={'method': ['GET']})
493
494 488 m.connect('my_account_pullrequests', '/my_account/pull_requests',
495 489 action='my_account_pullrequests', conditions={'method': ['GET']})
496 490
497 m.connect('my_account_perms', '/my_account/perms',
498 action='my_account_perms', conditions={'method': ['GET']})
499
500 m.connect('my_account_notifications', '/my_account/notifications',
501 action='my_notifications',
502 conditions={'method': ['GET']})
503 m.connect('my_account_notifications_toggle_visibility',
504 '/my_account/toggle_visibility',
505 action='my_notifications_toggle_visibility',
506 conditions={'method': ['POST']})
507
508 491 # NOTIFICATION REST ROUTES
509 492 with rmap.submapper(path_prefix=ADMIN_PREFIX,
510 493 controller='admin/notifications') as m:
@@ -29,26 +29,22 b' import formencode'
29 29 from formencode import htmlfill
30 30 from pyramid.httpexceptions import HTTPFound
31 31
32 from pylons import request, tmpl_context as c, url
32 from pylons import request, tmpl_context as c
33 33 from pylons.controllers.util import redirect
34 34 from pylons.i18n.translation import _
35 from sqlalchemy.orm import joinedload
36 35
37 36 from rhodecode.lib import helpers as h
38 37 from rhodecode.lib import auth
39 38 from rhodecode.lib.auth import (
40 39 LoginRequired, NotAnonymous, AuthUser)
41 40 from rhodecode.lib.base import BaseController, render
42 from rhodecode.lib.utils import jsonify
43 41 from rhodecode.lib.utils2 import safe_int, str2bool
44 42 from rhodecode.lib.ext_json import json
45 43
46 44 from rhodecode.model.db import (
47 45 Repository, PullRequest, UserEmailMap, User, UserFollowing)
48 46 from rhodecode.model.forms import UserForm
49 from rhodecode.model.scm import RepoList
50 47 from rhodecode.model.user import UserModel
51 from rhodecode.model.repo import RepoModel
52 48 from rhodecode.model.meta import Session
53 49 from rhodecode.model.pull_request import PullRequestModel
54 50 from rhodecode.model.comment import CommentsModel
@@ -78,26 +74,6 b' class MyAccountController(BaseController'
78 74 c.auth_user = AuthUser(
79 75 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
80 76
81 def _load_my_repos_data(self, watched=False):
82 if watched:
83 admin = False
84 follows_repos = Session().query(UserFollowing)\
85 .filter(UserFollowing.user_id == c.rhodecode_user.user_id)\
86 .options(joinedload(UserFollowing.follows_repository))\
87 .all()
88 repo_list = [x.follows_repository for x in follows_repos]
89 else:
90 admin = True
91 repo_list = Repository.get_all_repos(
92 user_id=c.rhodecode_user.user_id)
93 repo_list = RepoList(repo_list, perm_set=[
94 'repository.read', 'repository.write', 'repository.admin'])
95
96 repos_data = RepoModel().get_repos_as_dict(
97 repo_list=repo_list, admin=admin)
98 # json used to render the grid
99 return json.dumps(repos_data)
100
101 77 @auth.CSRFRequired()
102 78 def my_account_update(self):
103 79 """
@@ -177,29 +153,6 b' class MyAccountController(BaseController'
177 153 force_defaults=False
178 154 )
179 155
180 def my_account_repos(self):
181 c.active = 'repos'
182 self.__load_data()
183
184 # json used to render the grid
185 c.data = self._load_my_repos_data()
186 return render('admin/my_account/my_account.mako')
187
188 def my_account_watched(self):
189 c.active = 'watched'
190 self.__load_data()
191
192 # json used to render the grid
193 c.data = self._load_my_repos_data(watched=True)
194 return render('admin/my_account/my_account.mako')
195
196 def my_account_perms(self):
197 c.active = 'perms'
198 self.__load_data()
199 c.perm_user = c.auth_user
200
201 return render('admin/my_account/my_account.mako')
202
203 156 def _extract_ordering(self, request):
204 157 column_index = safe_int(request.GET.get('order[0][column]'))
205 158 order_dir = request.GET.get('order[0][dir]', 'desc')
@@ -280,15 +233,4 b' class MyAccountController(BaseController'
280 233 else:
281 234 return json.dumps(data)
282 235
283 def my_notifications(self):
284 c.active = 'notifications'
285 return render('admin/my_account/my_account.mako')
286 236
287 @auth.CSRFRequired()
288 @jsonify
289 def my_notifications_toggle_visibility(self):
290 user = c.rhodecode_user.get_instance()
291 new_status = not user.user_data.get('notification_status', True)
292 user.update_userdata(notification_status=new_status)
293 Session().commit()
294 return user.user_data['notification_status']
@@ -134,6 +134,14 b' function registerRCRoutes() {'
134 134 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
135 135 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
136 136 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
137 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
138 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
139 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
140 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
141 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
142 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
143 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
144 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
137 145 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
138 146 pyroutes.register('apiv2', '/_admin/api', []);
139 147 }
@@ -35,11 +35,11 b''
35 35 <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li>
36 36 % endif
37 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>
39 <li class="${'active' if c.active=='watched' else ''}"><a href="${h.url('my_account_watched')}">${_('Watched')}</a></li>
38 <li class="${'active' if c.active=='repos' else ''}"><a href="${h.route_path('my_account_repos')}">${_('Repositories')}</a></li>
39 <li class="${'active' if c.active=='watched' else ''}"><a href="${h.route_path('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>
41 <li class="${'active' if c.active=='perms' else ''}"><a href="${h.url('my_account_perms')}">${_('Permissions')}</a></li>
42 <li class="${'active' if c.active=='my_notifications' else ''}"><a href="${h.url('my_account_notifications')}">${_('Live Notifications')}</a></li>
41 <li class="${'active' if c.active=='perms' else ''}"><a href="${h.route_path('my_account_perms')}">${_('Permissions')}</a></li>
42 <li class="${'active' if c.active=='my_notifications' else ''}"><a href="${h.route_path('my_account_notifications')}">${_('Live Notifications')}</a></li>
43 43 </ul>
44 44 </div>
45 45
@@ -1,7 +1,7 b''
1 1 <template is="dom-bind" id="notificationsPage">
2 2 <iron-ajax id="toggleNotifications"
3 3 method="post"
4 url="${url('my_account_notifications_toggle_visibility')}"
4 url="${h.route_path('my_account_notifications_toggle_visibility')}"
5 5 content-type="application/json"
6 6 loading="{{changeNotificationsLoading}}"
7 7 on-response="handleNotifications"
@@ -57,26 +57,6 b' class TestMyAccountController(TestContro'
57 57
58 58 response.mustcontain('value="test_admin')
59 59
60 def test_my_account_my_repos(self):
61 self.log_user()
62 response = self.app.get(url('my_account_repos'))
63 repos = Repository.query().filter(
64 Repository.user == User.get_by_username(
65 TEST_USER_ADMIN_LOGIN)).all()
66 for repo in repos:
67 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
68
69 def test_my_account_my_watched(self):
70 self.log_user()
71 response = self.app.get(url('my_account_watched'))
72
73 repos = UserFollowing.query().filter(
74 UserFollowing.user == User.get_by_username(
75 TEST_USER_ADMIN_LOGIN)).all()
76 for repo in repos:
77 response.mustcontain(
78 '"name_raw": "%s"' % repo.follows_repository.repo_name)
79
80 60 @pytest.mark.backends("git", "hg")
81 61 def test_my_account_my_pullrequests(self, pr_util):
82 62 self.log_user()
@@ -89,8 +69,6 b' class TestMyAccountController(TestContro'
89 69 response.mustcontain('"name_raw": %s' % pr.pull_request_id)
90 70 response.mustcontain('TestMyAccountPR')
91 71
92
93
94 72 @pytest.mark.parametrize(
95 73 "name, attrs", [
96 74 ('firstname', {'firstname': 'new_username'}),
General Comments 0
You need to be logged in to leave comments. Login now