##// END OF EJS Templates
user-profile: migrated to pyramid views.
marcink -
r1502:f2363971 default
parent child Browse files
Show More
@@ -0,0 +1,53 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-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 logging
22 from pylons import tmpl_context as c
23
24 from rhodecode.lib.utils2 import StrictAttributeDict
25
26 log = logging.getLogger(__name__)
27
28
29 class TemplateArgs(StrictAttributeDict):
30 pass
31
32
33 class BaseAppView(object):
34
35 def __init__(self, context, request):
36 self.request = request
37 self.context = context
38 self.session = request.session
39 self._rhodecode_user = request.user
40
41 def _get_local_tmpl_context(self):
42 return TemplateArgs()
43
44 def _get_template_context(self, tmpl_args):
45
46 for k, v in tmpl_args.items():
47 setattr(c, k, v)
48
49 return {
50 'defaults': {},
51 'errors': {},
52 }
53
@@ -0,0 +1,28 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-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
22 def includeme(config):
23 config.add_route(
24 name='user_profile',
25 pattern='/_profiles/{username}')
26
27 # Scan module for configuration decorators.
28 config.scan()
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
@@ -0,0 +1,75 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.model.db import User
24 from rhodecode.tests import (
25 TestController, TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
26 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
27 from rhodecode.tests.fixture import Fixture
28 from rhodecode.tests.utils import AssertResponse
29
30 fixture = Fixture()
31
32
33 def route_path(name, **kwargs):
34 return '/_profiles/{username}'.format(**kwargs)
35
36
37 class TestUsersController(TestController):
38
39 def test_user_profile(self, user_util):
40 edit_link_css = '.user-profile .panel-edit'
41 self.log_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS)
42 user = user_util.create_user(
43 'test-my-user', password='qweqwe', email='testme@rhodecode.org')
44 username = user.username
45
46 response = self.app.get(route_path('user_profile', username=username))
47 response.mustcontain('testme')
48 response.mustcontain('testme@rhodecode.org')
49 assert_response = AssertResponse(response)
50 assert_response.no_element_exists(edit_link_css)
51
52 # edit should be available to superadmin users
53 self.logout_user()
54 self.log_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
55 response = self.app.get(route_path('user_profile', username=username))
56 assert_response = AssertResponse(response)
57 assert_response.element_contains(edit_link_css, 'Edit')
58
59 def test_user_profile_not_available(self, user_util):
60 user = user_util.create_user()
61 username = user.username
62
63 # not logged in, redirect
64 self.app.get(route_path('user_profile', username=username), status=302)
65
66 self.log_user()
67 # after log-in show
68 self.app.get(route_path('user_profile', username=username), status=200)
69
70 # default user, not allowed to show it
71 self.app.get(
72 route_path('user_profile', username=User.DEFAULT_USER), status=404)
73
74 # actual 404
75 self.app.get(route_path('user_profile', username='unknown'), status=404)
@@ -0,0 +1,53 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-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 logging
22
23 from pyramid.httpexceptions import HTTPNotFound
24 from pyramid.view import view_config
25
26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.lib.auth import LoginRequired, NotAnonymous
28
29 from rhodecode.model.db import User
30 from rhodecode.model.user import UserModel
31
32 log = logging.getLogger(__name__)
33
34
35 class UserProfileView(BaseAppView):
36
37 @LoginRequired()
38 @NotAnonymous()
39 @view_config(
40 route_name='user_profile', request_method='GET',
41 renderer='rhodecode:templates/users/user.mako')
42 def login(self):
43 # register local template context
44 c = self._get_local_tmpl_context()
45 c.active = 'user_profile'
46
47 username = self.request.matchdict.get('username')
48
49 c.user = UserModel().get_by_username(username)
50 if not c.user or c.user.username == User.DEFAULT_USER:
51 raise HTTPNotFound()
52
53 return self._get_template_context(c)
@@ -281,7 +281,11 b' def includeme(config):'
281 config.include('rhodecode.admin')
281 config.include('rhodecode.admin')
282 config.include('rhodecode.authentication')
282 config.include('rhodecode.authentication')
283 config.include('rhodecode.integrations')
283 config.include('rhodecode.integrations')
284
285 # apps
284 config.include('rhodecode.apps.login')
286 config.include('rhodecode.apps.login')
287 config.include('rhodecode.apps.user_profile')
288
285 config.include('rhodecode.tweens')
289 config.include('rhodecode.tweens')
286 config.include('rhodecode.api')
290 config.include('rhodecode.api')
287 config.include('rhodecode.svn_support')
291 config.include('rhodecode.svn_support')
@@ -92,7 +92,7 b' class JSRoutesMapper(Mapper):'
92 def _extract_route_information(self, route):
92 def _extract_route_information(self, route):
93 """
93 """
94 Convert a route into tuple(name, path, args), eg:
94 Convert a route into tuple(name, path, args), eg:
95 ('user_profile', '/profile/%(username)s', ['username'])
95 ('show_user', '/profile/%(username)s', ['username'])
96 """
96 """
97 routepath = route.routepath
97 routepath = route.routepath
98 def replace(matchobj):
98 def replace(matchobj):
@@ -198,10 +198,6 b' def make_map(config):'
198 rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
198 rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
199 action='user_group_autocomplete_data', jsroute=True)
199 action='user_group_autocomplete_data', jsroute=True)
200
200
201 rmap.connect(
202 'user_profile', '/_profiles/{username}', controller='users',
203 action='user_profile')
204
205 # TODO: johbo: Static links, to be replaced by our redirection mechanism
201 # TODO: johbo: Static links, to be replaced by our redirection mechanism
206 rmap.connect('rst_help',
202 rmap.connect('rst_help',
207 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
203 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
@@ -871,7 +871,7 b' def link_to_user(author, length=0, **kwa'
871 if user:
871 if user:
872 return link_to(
872 return link_to(
873 escape(display_person),
873 escape(display_person),
874 url('user_profile', username=user.username),
874 route_path('user_profile', username=user.username),
875 **kwargs)
875 **kwargs)
876 else:
876 else:
877 return escape(display_person)
877 return escape(display_person)
@@ -12,16 +12,16 b' A new user `${user.username}` has regist'
12 - Username: ${user.username}
12 - Username: ${user.username}
13 - Full Name: ${user.firstname} ${user.lastname}
13 - Full Name: ${user.firstname} ${user.lastname}
14 - Email: ${user.email}
14 - Email: ${user.email}
15 - Profile link: ${h.url('user_profile', username=user.username, qualified=True)}
15 - Profile link: ${h.route_path('user_profile', username=user.username, qualified=True)}
16
16
17 ${self.plaintext_footer()}
17 ${self.plaintext_footer()}
18 </%def>
18 </%def>
19
19
20 ## BODY GOES BELOW
20 ## BODY GOES BELOW
21 <table style="text-align:left;vertical-align:middle;">
21 <table style="text-align:left;vertical-align:middle;">
22 <tr><td colspan="2" style="width:100%;padding-bottom:15px;border-bottom:1px solid #dbd9da;"><h4><a href="${h.url('user_profile', username=user.username, qualified=True)}" style="color:#427cc9;text-decoration:none;cursor:pointer">${_('New user %(user)s has registered on %(date)s') % {'user': user.username, 'date': h.format_date(date)}}</a></h4></td></tr>
22 <tr><td colspan="2" style="width:100%;padding-bottom:15px;border-bottom:1px solid #dbd9da;"><h4><a href="${h.route_path('user_profile', username=user.username, qualified=True)}" style="color:#427cc9;text-decoration:none;cursor:pointer">${_('New user %(user)s has registered on %(date)s') % {'user': user.username, 'date': h.format_date(date)}}</a></h4></td></tr>
23 <tr><td style="padding-right:20px;padding-top:20px;">${_('Username')}</td><td style="line-height:1;padding-top:20px;"><img style="margin-bottom:-5px;text-align:left;border:1px solid #dbd9da" src="${h.gravatar_url(user.email, 16)}" height="16" width="16">&nbsp;${user.username}</td></tr>
23 <tr><td style="padding-right:20px;padding-top:20px;">${_('Username')}</td><td style="line-height:1;padding-top:20px;"><img style="margin-bottom:-5px;text-align:left;border:1px solid #dbd9da" src="${h.gravatar_url(user.email, 16)}" height="16" width="16">&nbsp;${user.username}</td></tr>
24 <tr><td style="padding-right:20px;">${_('Full Name')}</td><td>${user.firstname} ${user.lastname}</td></tr>
24 <tr><td style="padding-right:20px;">${_('Full Name')}</td><td>${user.firstname} ${user.lastname}</td></tr>
25 <tr><td style="padding-right:20px;">${_('Email')}</td><td>${user.email}</td></tr>
25 <tr><td style="padding-right:20px;">${_('Email')}</td><td>${user.email}</td></tr>
26 <tr><td style="padding-right:20px;">${_('Profile')}</td><td><a href="${h.url('user_profile', username=user.username, qualified=True)}">${h.url('user_profile', username=user.username, qualified=True)}</a></td></tr>
26 <tr><td style="padding-right:20px;">${_('Profile')}</td><td><a href="${h.route_path('user_profile', username=user.username, qualified=True)}">${h.route_path('user_profile', username=user.username, qualified=True)}</a></td></tr>
27 </table> No newline at end of file
27 </table>
@@ -12,7 +12,7 b''
12 </%def>
12 </%def>
13
13
14 <%def name="menu_bar_nav()">
14 <%def name="menu_bar_nav()">
15 ${self.menu_items(active='admin')}
15 ${self.menu_items(active='my_account')}
16 </%def>
16 </%def>
17
17
18 <%def name="main()">
18 <%def name="main()">
@@ -26,7 +26,7 b''
26 <div class="sidebar">
26 <div class="sidebar">
27 <ul class="nav nav-pills nav-stacked">
27 <ul class="nav nav-pills nav-stacked">
28 <li class="${'active' if c.active=='user_profile' else ''}">
28 <li class="${'active' if c.active=='user_profile' else ''}">
29 <a href="${h.url('user_profile', username=c.user.username)}">${_('Profile')}</a></li>
29 <a href="${h.route_path('user_profile', username=c.user.username)}">${_('Profile')}</a></li>
30 ## These placeholders are here only for styling purposes. For every new item added to the list, you should remove one placeholder
30 ## These placeholders are here only for styling purposes. For every new item added to the list, you should remove one placeholder
31 <li class="placeholder"><a href="#" style="visibility: hidden;">placeholder</a></li>
31 <li class="placeholder"><a href="#" style="visibility: hidden;">placeholder</a></li>
32 <li class="placeholder"><a href="#" style="visibility: hidden;">placeholder</a></li>
32 <li class="placeholder"><a href="#" style="visibility: hidden;">placeholder</a></li>
@@ -276,7 +276,7 b' class TestGistsController(TestController'
276 assert_response = AssertResponse(response)
276 assert_response = AssertResponse(response)
277 assert_response.element_equals_to(
277 assert_response.element_equals_to(
278 'div.rc-user span.user',
278 'div.rc-user span.user',
279 '<span class="user"> %s</span>' % h.link_to_user('test_admin'))
279 '<a href="/_profiles/test_admin">test_admin</a></span>')
280
280
281 response.mustcontain('gist-desc')
281 response.mustcontain('gist-desc')
282
282
@@ -299,7 +299,7 b' class TestGistsController(TestController'
299 assert_response = AssertResponse(response)
299 assert_response = AssertResponse(response)
300 assert_response.element_equals_to(
300 assert_response.element_equals_to(
301 'div.rc-user span.user',
301 'div.rc-user span.user',
302 '<span class="user"> %s</span>' % h.link_to_user('test_admin'))
302 '<a href="/_profiles/test_admin">test_admin</a></span>')
303 response.mustcontain('gist-desc')
303 response.mustcontain('gist-desc')
304
304
305 def test_show_as_raw(self, create_gist):
305 def test_show_as_raw(self, create_gist):
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now