##// END OF EJS Templates
admin-users: moved grid browsing to pyramid....
marcink -
r1520:67ca1dd5 default
parent child Browse files
Show More
@@ -53,6 +53,15 b' def includeme(config):'
53 name='admin_settings_sessions_cleanup',
53 name='admin_settings_sessions_cleanup',
54 pattern=ADMIN_PREFIX + '/settings/sessions/cleanup')
54 pattern=ADMIN_PREFIX + '/settings/sessions/cleanup')
55
55
56 # users admin
57 config.add_route(
58 name='users',
59 pattern=ADMIN_PREFIX + '/users')
60
61 config.add_route(
62 name='users_data',
63 pattern=ADMIN_PREFIX + '/users_data')
64
56 # user auth tokens
65 # user auth tokens
57 config.add_route(
66 config.add_route(
58 name='edit_user_auth_tokens',
67 name='edit_user_auth_tokens',
@@ -22,18 +22,18 b' import pytest'
22
22
23 from rhodecode.model.db import User, UserApiKeys
23 from rhodecode.model.db import User, UserApiKeys
24
24
25 from rhodecode.apps._base import ADMIN_PREFIX
26 from rhodecode.tests import (
25 from rhodecode.tests import (
27 TestController, TEST_USER_REGULAR_LOGIN, assert_session_flash)
26 TestController, TEST_USER_REGULAR_LOGIN, assert_session_flash)
28 from rhodecode.tests.fixture import Fixture
27 from rhodecode.tests.fixture import Fixture
29 from rhodecode.tests.utils import AssertResponse
30
28
31 fixture = Fixture()
29 fixture = Fixture()
32
30
33
31
32 def route_path(name, params=None, **kwargs):
33 import urllib
34 from rhodecode.apps._base import ADMIN_PREFIX
34
35
35 def route_path(name, **kwargs):
36 base_url = {
36 return {
37 'users':
37 'users':
38 ADMIN_PREFIX + '/users',
38 ADMIN_PREFIX + '/users',
39 'users_data':
39 'users_data':
@@ -46,9 +46,37 b' def route_path(name, **kwargs):'
46 ADMIN_PREFIX + '/users/{user_id}/edit/auth_tokens/delete',
46 ADMIN_PREFIX + '/users/{user_id}/edit/auth_tokens/delete',
47 }[name].format(**kwargs)
47 }[name].format(**kwargs)
48
48
49 if params:
50 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
51 return base_url
52
49
53
50 class TestAdminUsersView(TestController):
54 class TestAdminUsersView(TestController):
51
55
56 def test_show_users(self):
57 self.log_user()
58 self.app.get(route_path('users'))
59
60 def test_show_users_data(self, xhr_header):
61 self.log_user()
62 response = self.app.get(route_path(
63 'users_data'), extra_environ=xhr_header)
64
65 all_users = User.query().filter(
66 User.username != User.DEFAULT_USER).count()
67 assert response.json['recordsTotal'] == all_users
68
69 def test_show_users_data_filtered(self, xhr_header):
70 self.log_user()
71 response = self.app.get(route_path(
72 'users_data', params={'search[value]': 'empty_search'}),
73 extra_environ=xhr_header)
74
75 all_users = User.query().filter(
76 User.username != User.DEFAULT_USER).count()
77 assert response.json['recordsTotal'] == all_users
78 assert response.json['recordsFiltered'] == 0
79
52 def test_auth_tokens_default_user(self):
80 def test_auth_tokens_default_user(self):
53 self.log_user()
81 self.log_user()
54 user = User.get_default_user()
82 user = User.get_default_user()
@@ -28,9 +28,9 b' from rhodecode.lib.auth import ('
28 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
28 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
29 from rhodecode.lib import helpers as h
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib.utils import PartialRenderer
30 from rhodecode.lib.utils import PartialRenderer
31 from rhodecode.lib.utils2 import safe_int
31 from rhodecode.lib.utils2 import safe_int, safe_unicode
32 from rhodecode.model.auth_token import AuthTokenModel
32 from rhodecode.model.auth_token import AuthTokenModel
33 from rhodecode.model.db import User
33 from rhodecode.model.db import User, or_
34 from rhodecode.model.meta import Session
34 from rhodecode.model.meta import Session
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
@@ -58,6 +58,105 b' class AdminUsersView(BaseAppView):'
58 # is a pyramid view
58 # is a pyramid view
59 raise HTTPFound('/')
59 raise HTTPFound('/')
60
60
61 def _extract_ordering(self, request):
62 column_index = safe_int(request.GET.get('order[0][column]'))
63 order_dir = request.GET.get(
64 'order[0][dir]', 'desc')
65 order_by = request.GET.get(
66 'columns[%s][data][sort]' % column_index, 'name_raw')
67
68 # translate datatable to DB columns
69 order_by = {
70 'first_name': 'name',
71 'last_name': 'lastname',
72 'last_activity': ''
73 }.get(order_by) or order_by
74
75 search_q = request.GET.get('search[value]')
76 return search_q, order_by, order_dir
77
78 def _extract_chunk(self, request):
79 start = safe_int(request.GET.get('start'), 0)
80 length = safe_int(request.GET.get('length'), 25)
81 draw = safe_int(request.GET.get('draw'))
82 return draw, start, length
83
84 @HasPermissionAllDecorator('hg.admin')
85 @view_config(
86 route_name='users', request_method='GET',
87 renderer='rhodecode:templates/admin/users/users.mako')
88 def users_list(self):
89 c = self.load_default_context()
90 return self._get_template_context(c)
91
92 @HasPermissionAllDecorator('hg.admin')
93 @view_config(
94 # renderer defined below
95 route_name='users_data', request_method='GET', renderer='json',
96 xhr=True)
97 def users_list_data(self):
98 draw, start, limit = self._extract_chunk(self.request)
99 search_q, order_by, order_dir = self._extract_ordering(self.request)
100
101 _render = PartialRenderer('data_table/_dt_elements.mako')
102
103 def user_actions(user_id, username):
104 return _render("user_actions", user_id, username)
105
106 users_data_total_count = User.query()\
107 .filter(User.username != User.DEFAULT_USER) \
108 .count()
109
110 # json generate
111 base_q = User.query().filter(User.username != User.DEFAULT_USER)
112
113 if search_q:
114 like_expression = u'{}%'.format(safe_unicode(search_q))
115 base_q = base_q.filter(or_(
116 User.username.ilike(like_expression),
117 User._email.ilike(like_expression),
118 User.name.ilike(like_expression),
119 User.lastname.ilike(like_expression),
120 ))
121
122 users_data_total_filtered_count = base_q.count()
123
124 sort_col = getattr(User, order_by, None)
125 if sort_col and order_dir == 'asc':
126 base_q = base_q.order_by(sort_col.asc())
127 elif sort_col:
128 base_q = base_q.order_by(sort_col.desc())
129
130 base_q = base_q.offset(start).limit(limit)
131 users_list = base_q.all()
132
133 users_data = []
134 for user in users_list:
135 users_data.append({
136 "username": h.gravatar_with_user(user.username),
137 "email": user.email,
138 "first_name": h.escape(user.name),
139 "last_name": h.escape(user.lastname),
140 "last_login": h.format_date(user.last_login),
141 "last_activity": h.format_date(
142 h.time_to_datetime(user.user_data.get('last_activity', 0))),
143 "active": h.bool2icon(user.active),
144 "active_raw": user.active,
145 "admin": h.bool2icon(user.admin),
146 "extern_type": user.extern_type,
147 "extern_name": user.extern_name,
148 "action": user_actions(user.user_id, user.username),
149 })
150
151 data = ({
152 'draw': draw,
153 'data': users_data,
154 'recordsTotal': users_data_total_count,
155 'recordsFiltered': users_data_total_filtered_count,
156 })
157
158 return data
159
61 @LoginRequired()
160 @LoginRequired()
62 @HasPermissionAllDecorator('hg.admin')
161 @HasPermissionAllDecorator('hg.admin')
63 @view_config(
162 @view_config(
@@ -292,8 +292,6 b' def make_map(config):'
292 controller='admin/users') as m:
292 controller='admin/users') as m:
293 m.connect('users', '/users',
293 m.connect('users', '/users',
294 action='create', conditions={'method': ['POST']})
294 action='create', conditions={'method': ['POST']})
295 m.connect('users', '/users',
296 action='index', conditions={'method': ['GET']})
297 m.connect('new_user', '/users/new',
295 m.connect('new_user', '/users/new',
298 action='new', conditions={'method': ['GET']})
296 action='new', conditions={'method': ['GET']})
299 m.connect('update_user', '/users/{user_id}',
297 m.connect('update_user', '/users/{user_id}',
@@ -77,7 +77,7 b' class MyAccountController(BaseController'
77 if c.user.username == User.DEFAULT_USER:
77 if c.user.username == User.DEFAULT_USER:
78 h.flash(_("You can't edit this user since it's"
78 h.flash(_("You can't edit this user since it's"
79 " crucial for entire application"), category='warning')
79 " crucial for entire application"), category='warning')
80 return redirect(url('users'))
80 return redirect(h.route_path('users'))
81
81
82 c.auth_user = AuthUser(
82 c.auth_user = AuthUser(
83 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
83 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
@@ -50,7 +50,6 b' from rhodecode.model.user import UserMod'
50 from rhodecode.model.meta import Session
50 from rhodecode.model.meta import Session
51 from rhodecode.model.permission import PermissionModel
51 from rhodecode.model.permission import PermissionModel
52 from rhodecode.lib.utils import action_logger
52 from rhodecode.lib.utils import action_logger
53 from rhodecode.lib.ext_json import json
54 from rhodecode.lib.utils2 import datetime_to_time, safe_int, AttributeDict
53 from rhodecode.lib.utils2 import datetime_to_time, safe_int, AttributeDict
55
54
56 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
@@ -76,51 +75,6 b' class UsersController(BaseController):'
76 ]
75 ]
77 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
76 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
78
77
79 @HasPermissionAllDecorator('hg.admin')
80 def index(self):
81 """GET /users: All items in the collection"""
82 # url('users')
83
84 from rhodecode.lib.utils import PartialRenderer
85 _render = PartialRenderer('data_table/_dt_elements.mako')
86
87 def username(user_id, username):
88 return _render("user_name", user_id, username)
89
90 def user_actions(user_id, username):
91 return _render("user_actions", user_id, username)
92
93 # json generate
94 c.users_list = User.query()\
95 .filter(User.username != User.DEFAULT_USER) \
96 .all()
97
98 users_data = []
99 for user in c.users_list:
100 users_data.append({
101 "username": h.gravatar_with_user(user.username),
102 "username_raw": user.username,
103 "email": user.email,
104 "first_name": h.escape(user.name),
105 "last_name": h.escape(user.lastname),
106 "last_login": h.format_date(user.last_login),
107 "last_login_raw": datetime_to_time(user.last_login),
108 "last_activity": h.format_date(
109 h.time_to_datetime(user.user_data.get('last_activity', 0))),
110 "last_activity_raw": user.user_data.get('last_activity', 0),
111 "active": h.bool2icon(user.active),
112 "active_raw": user.active,
113 "admin": h.bool2icon(user.admin),
114 "admin_raw": user.admin,
115 "extern_type": user.extern_type,
116 "extern_name": user.extern_name,
117 "action": user_actions(user.user_id, user.username),
118 })
119
120
121 c.data = json.dumps(users_data)
122 return render('admin/users/users.mako')
123
124 def _get_personal_repo_group_template_vars(self):
78 def _get_personal_repo_group_template_vars(self):
125 DummyUser = AttributeDict({
79 DummyUser = AttributeDict({
126 'username': '${username}',
80 'username': '${username}',
@@ -135,7 +89,6 b' class UsersController(BaseController):'
135 @auth.CSRFRequired()
89 @auth.CSRFRequired()
136 def create(self):
90 def create(self):
137 """POST /users: Create a new item"""
91 """POST /users: Create a new item"""
138 # url('users')
139 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
92 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
140 user_model = UserModel()
93 user_model = UserModel()
141 user_form = UserForm()()
94 user_form = UserForm()()
@@ -168,7 +121,7 b' class UsersController(BaseController):'
168 log.exception("Exception creation of user")
121 log.exception("Exception creation of user")
169 h.flash(_('Error occurred during creation of user %s')
122 h.flash(_('Error occurred during creation of user %s')
170 % request.POST.get('username'), category='error')
123 % request.POST.get('username'), category='error')
171 return redirect(url('users'))
124 return redirect(h.route_path('users'))
172
125
173 @HasPermissionAllDecorator('hg.admin')
126 @HasPermissionAllDecorator('hg.admin')
174 def new(self):
127 def new(self):
@@ -312,7 +265,7 b' class UsersController(BaseController):'
312 log.exception("Exception during deletion of user")
265 log.exception("Exception during deletion of user")
313 h.flash(_('An error occurred during deletion of user'),
266 h.flash(_('An error occurred during deletion of user'),
314 category='error')
267 category='error')
315 return redirect(url('users'))
268 return redirect(h.route_path('users'))
316
269
317 @HasPermissionAllDecorator('hg.admin')
270 @HasPermissionAllDecorator('hg.admin')
318 @auth.CSRFRequired()
271 @auth.CSRFRequired()
@@ -404,7 +357,7 b' class UsersController(BaseController):'
404 c.user = User.get_or_404(user_id)
357 c.user = User.get_or_404(user_id)
405 if c.user.username == User.DEFAULT_USER:
358 if c.user.username == User.DEFAULT_USER:
406 h.flash(_("You can't edit this user"), category='warning')
359 h.flash(_("You can't edit this user"), category='warning')
407 return redirect(url('users'))
360 return redirect(h.route_path('users'))
408
361
409 c.active = 'profile'
362 c.active = 'profile'
410 c.extern_type = c.user.extern_type
363 c.extern_type = c.user.extern_type
@@ -425,7 +378,7 b' class UsersController(BaseController):'
425 user = c.user = User.get_or_404(user_id)
378 user = c.user = User.get_or_404(user_id)
426 if user.username == User.DEFAULT_USER:
379 if user.username == User.DEFAULT_USER:
427 h.flash(_("You can't edit this user"), category='warning')
380 h.flash(_("You can't edit this user"), category='warning')
428 return redirect(url('users'))
381 return redirect(h.route_path('users'))
429
382
430 c.active = 'advanced'
383 c.active = 'advanced'
431 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
384 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
@@ -457,7 +410,7 b' class UsersController(BaseController):'
457 c.user = User.get_or_404(user_id)
410 c.user = User.get_or_404(user_id)
458 if c.user.username == User.DEFAULT_USER:
411 if c.user.username == User.DEFAULT_USER:
459 h.flash(_("You can't edit this user"), category='warning')
412 h.flash(_("You can't edit this user"), category='warning')
460 return redirect(url('users'))
413 return redirect(h.route_path('users'))
461
414
462 c.active = 'global_perms'
415 c.active = 'global_perms'
463
416
@@ -531,7 +484,7 b' class UsersController(BaseController):'
531 c.user = User.get_or_404(user_id)
484 c.user = User.get_or_404(user_id)
532 if c.user.username == User.DEFAULT_USER:
485 if c.user.username == User.DEFAULT_USER:
533 h.flash(_("You can't edit this user"), category='warning')
486 h.flash(_("You can't edit this user"), category='warning')
534 return redirect(url('users'))
487 return redirect(h.route_path('users'))
535
488
536 c.active = 'perms_summary'
489 c.active = 'perms_summary'
537 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
490 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
@@ -544,7 +497,7 b' class UsersController(BaseController):'
544 c.user = User.get_or_404(user_id)
497 c.user = User.get_or_404(user_id)
545 if c.user.username == User.DEFAULT_USER:
498 if c.user.username == User.DEFAULT_USER:
546 h.flash(_("You can't edit this user"), category='warning')
499 h.flash(_("You can't edit this user"), category='warning')
547 return redirect(url('users'))
500 return redirect(h.route_path('users'))
548
501
549 c.active = 'emails'
502 c.active = 'emails'
550 c.user_email_map = UserEmailMap.query() \
503 c.user_email_map = UserEmailMap.query() \
@@ -602,7 +555,7 b' class UsersController(BaseController):'
602 c.user = User.get_or_404(user_id)
555 c.user = User.get_or_404(user_id)
603 if c.user.username == User.DEFAULT_USER:
556 if c.user.username == User.DEFAULT_USER:
604 h.flash(_("You can't edit this user"), category='warning')
557 h.flash(_("You can't edit this user"), category='warning')
605 return redirect(url('users'))
558 return redirect(h.route_path('users'))
606
559
607 c.active = 'ips'
560 c.active = 'ips'
608 c.user_ip_map = UserIpMap.query() \
561 c.user_ip_map = UserIpMap.query() \
@@ -10,7 +10,7 b''
10 <%def name="breadcrumbs_links()">
10 <%def name="breadcrumbs_links()">
11 ${h.link_to(_('Admin'),h.url('admin_home'))}
11 ${h.link_to(_('Admin'),h.url('admin_home'))}
12 &raquo;
12 &raquo;
13 ${h.link_to(_('Users'),h.url('users'))}
13 ${h.link_to(_('Users'),h.route_path('users'))}
14 &raquo;
14 &raquo;
15 ${_('Add User')}
15 ${_('Add User')}
16 </%def>
16 </%def>
@@ -11,7 +11,7 b''
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 ${h.link_to(_('Admin'),h.url('admin_home'))}
12 ${h.link_to(_('Admin'),h.url('admin_home'))}
13 &raquo;
13 &raquo;
14 ${h.link_to(_('Users'),h.url('users'))}
14 ${h.link_to(_('Users'),h.route_path('users'))}
15 &raquo;
15 &raquo;
16 ${c.user.username}
16 ${c.user.username}
17 </%def>
17 </%def>
@@ -34,60 +34,31 b''
34 </div>
34 </div>
35 </div>
35 </div>
36
36
37 <script>
37 <script type="text/javascript">
38
38 $(document).ready(function() {
39 $(document).ready(function() {
39
40
40 var get_datatable_count = function(){
41 var getDatatableCount = function(){
41 var datatable = $('#user_list_table').dataTable();
42 var table = $('#user_list_table').dataTable();
42 var api = datatable.api();
43 var page = table.api().page.info();
43 var total = api.page.info().recordsDisplay;
44 var active = page.recordsDisplay;
44 var active = datatable.fnGetFilteredData();
45 var total = page.recordsTotal;
45 var _text = _gettext("{0} active out of {1} users").format(active, total);
46 $('#user_count').text(_text);
47 };
48
49 // custom filter that filters by username OR email
50 $.fn.dataTable.ext.search.push(
51 function( settings, data, dataIndex ) {
52 var query = $('#q_filter').val();
53
54 var username = data[0];
55 var email = data[1];
56 var first_name = data[2];
57 var last_name = data[3];
58
46
59 var query_str = username + " " +
47 var _text = _gettext("{0} out of {1} users").format(active, total);
60 email + " " +
48 $('#user_count').text(_text);
61 first_name + " " +
62 last_name;
63
64 if ((query_str).indexOf(query) !== -1) {
65 return true;
66 }
67 return false;
68 }
69 );
70 // filtered data plugin
71 $.fn.dataTableExt.oApi.fnGetFilteredData = function ( oSettings ) {
72 var res = [];
73 for ( var i=0, iLen=oSettings.fnRecordsDisplay() ; i<iLen ; i++ ) {
74 var record = oSettings.aoData[i]._aData;
75 if(record['active_raw']){
76 res.push(record);
77 }
78 }
79 return res.length;
80 };
49 };
81
50
82 // user list
51 // user list
83 $('#user_list_table').DataTable({
52 $('#user_list_table').DataTable({
84 data: ${c.data|n},
53 processing: false,
54 serverSide: true,
55 ajax: "${h.route_path('users_data')}",
85 dom: 'rtp',
56 dom: 'rtp',
86 pageLength: ${c.visual.admin_grid_items},
57 pageLength: ${c.visual.admin_grid_items},
87 order: [[ 1, "asc" ]],
58 order: [[ 0, "asc" ]],
88 columns: [
59 columns: [
89 { data: {"_": "username",
60 { data: {"_": "username",
90 "sort": "username_raw"}, title: "${_('Username')}", className: "td-user" },
61 "sort": "username"}, title: "${_('Username')}", className: "td-user" },
91 { data: {"_": "email",
62 { data: {"_": "email",
92 "sort": "email"}, title: "${_('Email')}", className: "td-email" },
63 "sort": "email"}, title: "${_('Email')}", className: "td-email" },
93 { data: {"_": "first_name",
64 { data: {"_": "first_name",
@@ -95,12 +66,12 b''
95 { data: {"_": "last_name",
66 { data: {"_": "last_name",
96 "sort": "last_name"}, title: "${_('Last Name')}", className: "td-user" },
67 "sort": "last_name"}, title: "${_('Last Name')}", className: "td-user" },
97 { data: {"_": "last_activity",
68 { data: {"_": "last_activity",
98 "sort": "last_activity_raw",
69 "sort": "last_activity",
99 "type": Number}, title: "${_('Last activity')}", className: "td-time" },
70 "type": Number}, title: "${_('Last activity')}", className: "td-time", orderable: false },
100 { data: {"_": "active",
71 { data: {"_": "active",
101 "sort": "active_raw"}, title: "${_('Active')}", className: "td-active" },
72 "sort": "active"}, title: "${_('Active')}", className: "td-active" },
102 { data: {"_": "admin",
73 { data: {"_": "admin",
103 "sort": "admin_raw"}, title: "${_('Admin')}", className: "td-admin" },
74 "sort": "admin"}, title: "${_('Admin')}", className: "td-admin" },
104 { data: {"_": "extern_type",
75 { data: {"_": "extern_type",
105 "sort": "extern_type"}, title: "${_('Auth type')}", className: "td-type" },
76 "sort": "extern_type"}, title: "${_('Auth type')}", className: "td-type" },
106 { data: {"_": "action",
77 { data: {"_": "action",
@@ -110,9 +81,7 b''
110 paginate: DEFAULT_GRID_PAGINATION,
81 paginate: DEFAULT_GRID_PAGINATION,
111 emptyTable: _gettext("No users available yet.")
82 emptyTable: _gettext("No users available yet.")
112 },
83 },
113 "initComplete": function( settings, json ) {
84
114 get_datatable_count();
115 },
116 "createdRow": function ( row, data, index ) {
85 "createdRow": function ( row, data, index ) {
117 if (!data['active_raw']){
86 if (!data['active_raw']){
118 $(row).addClass('closed')
87 $(row).addClass('closed')
@@ -120,23 +89,29 b''
120 }
89 }
121 });
90 });
122
91
123 // update the counter when doing search
92 $('#user_list_table').on('xhr.dt', function(e, settings, json, xhr){
124 $('#user_list_table').on( 'search.dt', function (e,settings) {
93 $('#user_list_table').css('opacity', 1);
125 get_datatable_count();
94 });
95
96 $('#user_list_table').on('preXhr.dt', function(e, settings, data){
97 $('#user_list_table').css('opacity', 0.3);
126 });
98 });
127
99
128 // filter, filter both grids
100 // refresh counters on draw
129 $('#q_filter').on( 'keyup', function () {
101 $('#user_list_table').on('draw.dt', function(){
130 var user_api = $('#user_list_table').dataTable().api();
102 getDatatableCount();
131 user_api
132 .draw();
133 });
103 });
134
104
135 // refilter table if page load via back button
105 // filter
136 $("#q_filter").trigger('keyup');
106 $('#q_filter').on('keyup',
107 $.debounce(250, function() {
108 $('#user_list_table').DataTable().search(
109 $('#q_filter').val()
110 ).draw();
111 })
112 );
137
113
138 });
114 });
139
140 </script>
115 </script>
141
116
142 </%def>
117 </%def>
@@ -75,7 +75,7 b''
75 <li><a href="${h.url('admin_home')}">${_('Admin journal')}</a></li>
75 <li><a href="${h.url('admin_home')}">${_('Admin journal')}</a></li>
76 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
76 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
77 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
77 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
78 <li><a href="${h.url('users')}">${_('Users')}</a></li>
78 <li><a href="${h.route_path('users')}">${_('Users')}</a></li>
79 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
79 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
80 <li><a href="${h.url('admin_permissions_application')}">${_('Permissions')}</a></li>
80 <li><a href="${h.url('admin_permissions_application')}">${_('Permissions')}</a></li>
81 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
81 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
@@ -36,6 +36,20 b' from rhodecode.tests.utils import Assert'
36 fixture = Fixture()
36 fixture = Fixture()
37
37
38
38
39 def route_path(name, params=None, **kwargs):
40 import urllib
41 from rhodecode.apps._base import ADMIN_PREFIX
42
43 base_url = {
44 'users_data':
45 ADMIN_PREFIX + '/users_data',
46 }[name].format(**kwargs)
47
48 if params:
49 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
50 return base_url
51
52
39 class TestAdminUsersController(TestController):
53 class TestAdminUsersController(TestController):
40 test_user_1 = 'testme'
54 test_user_1 = 'testme'
41 destroy_users = set()
55 destroy_users = set()
@@ -44,7 +58,7 b' class TestAdminUsersController(TestContr'
44 def teardown_method(cls, method):
58 def teardown_method(cls, method):
45 fixture.destroy_users(cls.destroy_users)
59 fixture.destroy_users(cls.destroy_users)
46
60
47 def test_create(self):
61 def test_create(self, xhr_header):
48 self.log_user()
62 self.log_user()
49 username = 'newtestuser'
63 username = 'newtestuser'
50 password = 'test12'
64 password = 'test12'
@@ -53,7 +67,7 b' class TestAdminUsersController(TestContr'
53 lastname = 'lastname'
67 lastname = 'lastname'
54 email = 'mail@mail.com'
68 email = 'mail@mail.com'
55
69
56 response = self.app.get(url('new_user'))
70 self.app.get(url('new_user'))
57
71
58 response = self.app.post(url('users'), params={
72 response = self.app.post(url('users'), params={
59 'username': username,
73 'username': username,
@@ -81,8 +95,8 b' class TestAdminUsersController(TestContr'
81 assert new_user.lastname == lastname
95 assert new_user.lastname == lastname
82 assert new_user.email == email
96 assert new_user.email == email
83
97
84 response.follow()
98 response = self.app.get(route_path('users_data'),
85 response = response.follow()
99 extra_environ=xhr_header)
86 response.mustcontain(username)
100 response.mustcontain(username)
87
101
88 def test_create_err(self):
102 def test_create_err(self):
@@ -93,7 +107,7 b' class TestAdminUsersController(TestContr'
93 lastname = 'lastname'
107 lastname = 'lastname'
94 email = 'errmail.com'
108 email = 'errmail.com'
95
109
96 response = self.app.get(url('new_user'))
110 self.app.get(url('new_user'))
97
111
98 response = self.app.post(url('users'), params={
112 response = self.app.post(url('users'), params={
99 'username': username,
113 'username': username,
General Comments 0
You need to be logged in to leave comments. Login now