##// END OF EJS Templates
users: change last activity to re-use new column.
marcink -
r1546:b45c2eaa default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,239 +1,238 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 from pyramid.httpexceptions import HTTPFound
23 from pyramid.httpexceptions import HTTPFound
24 from pyramid.view import view_config
24 from pyramid.view import view_config
25
25
26 from rhodecode.apps._base import BaseAppView
26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.lib.auth import (
27 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, safe_unicode
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, or_
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__)
37
37
38
38
39 class AdminUsersView(BaseAppView):
39 class AdminUsersView(BaseAppView):
40 ALLOW_SCOPED_TOKENS = False
40 ALLOW_SCOPED_TOKENS = False
41 """
41 """
42 This view has alternative version inside EE, if modified please take a look
42 This view has alternative version inside EE, if modified please take a look
43 in there as well.
43 in there as well.
44 """
44 """
45
45
46 def load_default_context(self):
46 def load_default_context(self):
47 c = self._get_local_tmpl_context()
47 c = self._get_local_tmpl_context()
48 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
48 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
49 self._register_global_c(c)
49 self._register_global_c(c)
50 return c
50 return c
51
51
52 def _redirect_for_default_user(self, username):
52 def _redirect_for_default_user(self, username):
53 _ = self.request.translate
53 _ = self.request.translate
54 if username == User.DEFAULT_USER:
54 if username == User.DEFAULT_USER:
55 h.flash(_("You can't edit this user"), category='warning')
55 h.flash(_("You can't edit this user"), category='warning')
56 # TODO(marcink): redirect to 'users' admin panel once this
56 # TODO(marcink): redirect to 'users' admin panel once this
57 # is a pyramid view
57 # is a pyramid view
58 raise HTTPFound('/')
58 raise HTTPFound('/')
59
59
60 def _extract_ordering(self, request):
60 def _extract_ordering(self, request):
61 column_index = safe_int(request.GET.get('order[0][column]'))
61 column_index = safe_int(request.GET.get('order[0][column]'))
62 order_dir = request.GET.get(
62 order_dir = request.GET.get(
63 'order[0][dir]', 'desc')
63 'order[0][dir]', 'desc')
64 order_by = request.GET.get(
64 order_by = request.GET.get(
65 'columns[%s][data][sort]' % column_index, 'name_raw')
65 'columns[%s][data][sort]' % column_index, 'name_raw')
66
66
67 # translate datatable to DB columns
67 # translate datatable to DB columns
68 order_by = {
68 order_by = {
69 'first_name': 'name',
69 'first_name': 'name',
70 'last_name': 'lastname',
70 'last_name': 'lastname',
71 'last_activity': ''
71 'last_activity': ''
72 }.get(order_by) or order_by
72 }.get(order_by) or order_by
73
73
74 search_q = request.GET.get('search[value]')
74 search_q = request.GET.get('search[value]')
75 return search_q, order_by, order_dir
75 return search_q, order_by, order_dir
76
76
77 def _extract_chunk(self, request):
77 def _extract_chunk(self, request):
78 start = safe_int(request.GET.get('start'), 0)
78 start = safe_int(request.GET.get('start'), 0)
79 length = safe_int(request.GET.get('length'), 25)
79 length = safe_int(request.GET.get('length'), 25)
80 draw = safe_int(request.GET.get('draw'))
80 draw = safe_int(request.GET.get('draw'))
81 return draw, start, length
81 return draw, start, length
82
82
83 @HasPermissionAllDecorator('hg.admin')
83 @HasPermissionAllDecorator('hg.admin')
84 @view_config(
84 @view_config(
85 route_name='users', request_method='GET',
85 route_name='users', request_method='GET',
86 renderer='rhodecode:templates/admin/users/users.mako')
86 renderer='rhodecode:templates/admin/users/users.mako')
87 def users_list(self):
87 def users_list(self):
88 c = self.load_default_context()
88 c = self.load_default_context()
89 return self._get_template_context(c)
89 return self._get_template_context(c)
90
90
91 @HasPermissionAllDecorator('hg.admin')
91 @HasPermissionAllDecorator('hg.admin')
92 @view_config(
92 @view_config(
93 # renderer defined below
93 # renderer defined below
94 route_name='users_data', request_method='GET', renderer='json',
94 route_name='users_data', request_method='GET', renderer='json',
95 xhr=True)
95 xhr=True)
96 def users_list_data(self):
96 def users_list_data(self):
97 draw, start, limit = self._extract_chunk(self.request)
97 draw, start, limit = self._extract_chunk(self.request)
98 search_q, order_by, order_dir = self._extract_ordering(self.request)
98 search_q, order_by, order_dir = self._extract_ordering(self.request)
99
99
100 _render = PartialRenderer('data_table/_dt_elements.mako')
100 _render = PartialRenderer('data_table/_dt_elements.mako')
101
101
102 def user_actions(user_id, username):
102 def user_actions(user_id, username):
103 return _render("user_actions", user_id, username)
103 return _render("user_actions", user_id, username)
104
104
105 users_data_total_count = User.query()\
105 users_data_total_count = User.query()\
106 .filter(User.username != User.DEFAULT_USER) \
106 .filter(User.username != User.DEFAULT_USER) \
107 .count()
107 .count()
108
108
109 # json generate
109 # json generate
110 base_q = User.query().filter(User.username != User.DEFAULT_USER)
110 base_q = User.query().filter(User.username != User.DEFAULT_USER)
111
111
112 if search_q:
112 if search_q:
113 like_expression = u'%{}%'.format(safe_unicode(search_q))
113 like_expression = u'%{}%'.format(safe_unicode(search_q))
114 base_q = base_q.filter(or_(
114 base_q = base_q.filter(or_(
115 User.username.ilike(like_expression),
115 User.username.ilike(like_expression),
116 User._email.ilike(like_expression),
116 User._email.ilike(like_expression),
117 User.name.ilike(like_expression),
117 User.name.ilike(like_expression),
118 User.lastname.ilike(like_expression),
118 User.lastname.ilike(like_expression),
119 ))
119 ))
120
120
121 users_data_total_filtered_count = base_q.count()
121 users_data_total_filtered_count = base_q.count()
122
122
123 sort_col = getattr(User, order_by, None)
123 sort_col = getattr(User, order_by, None)
124 if sort_col and order_dir == 'asc':
124 if sort_col and order_dir == 'asc':
125 base_q = base_q.order_by(sort_col.asc())
125 base_q = base_q.order_by(sort_col.asc())
126 elif sort_col:
126 elif sort_col:
127 base_q = base_q.order_by(sort_col.desc())
127 base_q = base_q.order_by(sort_col.desc())
128
128
129 base_q = base_q.offset(start).limit(limit)
129 base_q = base_q.offset(start).limit(limit)
130 users_list = base_q.all()
130 users_list = base_q.all()
131
131
132 users_data = []
132 users_data = []
133 for user in users_list:
133 for user in users_list:
134 users_data.append({
134 users_data.append({
135 "username": h.gravatar_with_user(user.username),
135 "username": h.gravatar_with_user(user.username),
136 "email": user.email,
136 "email": user.email,
137 "first_name": h.escape(user.name),
137 "first_name": h.escape(user.name),
138 "last_name": h.escape(user.lastname),
138 "last_name": h.escape(user.lastname),
139 "last_login": h.format_date(user.last_login),
139 "last_login": h.format_date(user.last_login),
140 "last_activity": h.format_date(
140 "last_activity": h.format_date(user.last_activity),
141 h.time_to_datetime(user.user_data.get('last_activity', 0))),
142 "active": h.bool2icon(user.active),
141 "active": h.bool2icon(user.active),
143 "active_raw": user.active,
142 "active_raw": user.active,
144 "admin": h.bool2icon(user.admin),
143 "admin": h.bool2icon(user.admin),
145 "extern_type": user.extern_type,
144 "extern_type": user.extern_type,
146 "extern_name": user.extern_name,
145 "extern_name": user.extern_name,
147 "action": user_actions(user.user_id, user.username),
146 "action": user_actions(user.user_id, user.username),
148 })
147 })
149
148
150 data = ({
149 data = ({
151 'draw': draw,
150 'draw': draw,
152 'data': users_data,
151 'data': users_data,
153 'recordsTotal': users_data_total_count,
152 'recordsTotal': users_data_total_count,
154 'recordsFiltered': users_data_total_filtered_count,
153 'recordsFiltered': users_data_total_filtered_count,
155 })
154 })
156
155
157 return data
156 return data
158
157
159 @LoginRequired()
158 @LoginRequired()
160 @HasPermissionAllDecorator('hg.admin')
159 @HasPermissionAllDecorator('hg.admin')
161 @view_config(
160 @view_config(
162 route_name='edit_user_auth_tokens', request_method='GET',
161 route_name='edit_user_auth_tokens', request_method='GET',
163 renderer='rhodecode:templates/admin/users/user_edit.mako')
162 renderer='rhodecode:templates/admin/users/user_edit.mako')
164 def auth_tokens(self):
163 def auth_tokens(self):
165 _ = self.request.translate
164 _ = self.request.translate
166 c = self.load_default_context()
165 c = self.load_default_context()
167
166
168 user_id = self.request.matchdict.get('user_id')
167 user_id = self.request.matchdict.get('user_id')
169 c.user = User.get_or_404(user_id, pyramid_exc=True)
168 c.user = User.get_or_404(user_id, pyramid_exc=True)
170 self._redirect_for_default_user(c.user.username)
169 self._redirect_for_default_user(c.user.username)
171
170
172 c.active = 'auth_tokens'
171 c.active = 'auth_tokens'
173
172
174 c.lifetime_values = [
173 c.lifetime_values = [
175 (str(-1), _('forever')),
174 (str(-1), _('forever')),
176 (str(5), _('5 minutes')),
175 (str(5), _('5 minutes')),
177 (str(60), _('1 hour')),
176 (str(60), _('1 hour')),
178 (str(60 * 24), _('1 day')),
177 (str(60 * 24), _('1 day')),
179 (str(60 * 24 * 30), _('1 month')),
178 (str(60 * 24 * 30), _('1 month')),
180 ]
179 ]
181 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
180 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
182 c.role_values = [
181 c.role_values = [
183 (x, AuthTokenModel.cls._get_role_name(x))
182 (x, AuthTokenModel.cls._get_role_name(x))
184 for x in AuthTokenModel.cls.ROLES]
183 for x in AuthTokenModel.cls.ROLES]
185 c.role_options = [(c.role_values, _("Role"))]
184 c.role_options = [(c.role_values, _("Role"))]
186 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
185 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
187 c.user.user_id, show_expired=True)
186 c.user.user_id, show_expired=True)
188 return self._get_template_context(c)
187 return self._get_template_context(c)
189
188
190 def maybe_attach_token_scope(self, token):
189 def maybe_attach_token_scope(self, token):
191 # implemented in EE edition
190 # implemented in EE edition
192 pass
191 pass
193
192
194 @LoginRequired()
193 @LoginRequired()
195 @HasPermissionAllDecorator('hg.admin')
194 @HasPermissionAllDecorator('hg.admin')
196 @CSRFRequired()
195 @CSRFRequired()
197 @view_config(
196 @view_config(
198 route_name='edit_user_auth_tokens_add', request_method='POST')
197 route_name='edit_user_auth_tokens_add', request_method='POST')
199 def auth_tokens_add(self):
198 def auth_tokens_add(self):
200 _ = self.request.translate
199 _ = self.request.translate
201 c = self.load_default_context()
200 c = self.load_default_context()
202
201
203 user_id = self.request.matchdict.get('user_id')
202 user_id = self.request.matchdict.get('user_id')
204 c.user = User.get_or_404(user_id, pyramid_exc=True)
203 c.user = User.get_or_404(user_id, pyramid_exc=True)
205 self._redirect_for_default_user(c.user.username)
204 self._redirect_for_default_user(c.user.username)
206
205
207 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
206 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
208 description = self.request.POST.get('description')
207 description = self.request.POST.get('description')
209 role = self.request.POST.get('role')
208 role = self.request.POST.get('role')
210
209
211 token = AuthTokenModel().create(
210 token = AuthTokenModel().create(
212 c.user.user_id, description, lifetime, role)
211 c.user.user_id, description, lifetime, role)
213 self.maybe_attach_token_scope(token)
212 self.maybe_attach_token_scope(token)
214 Session().commit()
213 Session().commit()
215
214
216 h.flash(_("Auth token successfully created"), category='success')
215 h.flash(_("Auth token successfully created"), category='success')
217 return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
216 return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
218
217
219 @LoginRequired()
218 @LoginRequired()
220 @HasPermissionAllDecorator('hg.admin')
219 @HasPermissionAllDecorator('hg.admin')
221 @CSRFRequired()
220 @CSRFRequired()
222 @view_config(
221 @view_config(
223 route_name='edit_user_auth_tokens_delete', request_method='POST')
222 route_name='edit_user_auth_tokens_delete', request_method='POST')
224 def auth_tokens_delete(self):
223 def auth_tokens_delete(self):
225 _ = self.request.translate
224 _ = self.request.translate
226 c = self.load_default_context()
225 c = self.load_default_context()
227
226
228 user_id = self.request.matchdict.get('user_id')
227 user_id = self.request.matchdict.get('user_id')
229 c.user = User.get_or_404(user_id, pyramid_exc=True)
228 c.user = User.get_or_404(user_id, pyramid_exc=True)
230 self._redirect_for_default_user(c.user.username)
229 self._redirect_for_default_user(c.user.username)
231
230
232 del_auth_token = self.request.POST.get('del_auth_token')
231 del_auth_token = self.request.POST.get('del_auth_token')
233
232
234 if del_auth_token:
233 if del_auth_token:
235 AuthTokenModel().delete(del_auth_token, c.user.user_id)
234 AuthTokenModel().delete(del_auth_token, c.user.user_id)
236 Session().commit()
235 Session().commit()
237 h.flash(_("Auth token successfully deleted"), category='success')
236 h.flash(_("Auth token successfully deleted"), category='success')
238
237
239 return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
238 return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,158 +1,158 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <%
3 <%
4 elems = [
4 elems = [
5 (_('Created on'), h.format_date(c.user.created_on), '', ''),
5 (_('Created on'), h.format_date(c.user.created_on), '', ''),
6 (_('Source of Record'), c.user.extern_type, '', ''),
6 (_('Source of Record'), c.user.extern_type, '', ''),
7
7
8 (_('Last login'), c.user.last_login or '-', '', ''),
8 (_('Last login'), c.user.last_login or '-', '', ''),
9 (_('Last activity'), h.format_date(h.time_to_datetime(c.user.user_data.get('last_activity', 0))), '', ''),
9 (_('Last activity'), c.user.last_activity, '', ''),
10
10
11 (_('Repositories'), len(c.user.repositories), '', [x.repo_name for x in c.user.repositories]),
11 (_('Repositories'), len(c.user.repositories), '', [x.repo_name for x in c.user.repositories]),
12 (_('Repository groups'), len(c.user.repository_groups), '', [x.group_name for x in c.user.repository_groups]),
12 (_('Repository groups'), len(c.user.repository_groups), '', [x.group_name for x in c.user.repository_groups]),
13 (_('User groups'), len(c.user.user_groups), '', [x.users_group_name for x in c.user.user_groups]),
13 (_('User groups'), len(c.user.user_groups), '', [x.users_group_name for x in c.user.user_groups]),
14
14
15 (_('Member of User groups'), len(c.user.group_member), '', [x.users_group.users_group_name for x in c.user.group_member]),
15 (_('Member of User groups'), len(c.user.group_member), '', [x.users_group.users_group_name for x in c.user.group_member]),
16 (_('Force password change'), c.user.user_data.get('force_password_change', 'False'), '', ''),
16 (_('Force password change'), c.user.user_data.get('force_password_change', 'False'), '', ''),
17 ]
17 ]
18 %>
18 %>
19
19
20 <div class="panel panel-default">
20 <div class="panel panel-default">
21 <div class="panel-heading">
21 <div class="panel-heading">
22 <h3 class="panel-title">${_('User: %s') % c.user.username}</h3>
22 <h3 class="panel-title">${_('User: %s') % c.user.username}</h3>
23 </div>
23 </div>
24 <div class="panel-body">
24 <div class="panel-body">
25 ${base.dt_info_panel(elems)}
25 ${base.dt_info_panel(elems)}
26 </div>
26 </div>
27 </div>
27 </div>
28
28
29 <div class="panel panel-default">
29 <div class="panel panel-default">
30 <div class="panel-heading">
30 <div class="panel-heading">
31 <h3 class="panel-title">${_('Force Password Reset')}</h3>
31 <h3 class="panel-title">${_('Force Password Reset')}</h3>
32 </div>
32 </div>
33 <div class="panel-body">
33 <div class="panel-body">
34 ${h.secure_form(h.url('force_password_reset_user', user_id=c.user.user_id), method='post')}
34 ${h.secure_form(h.url('force_password_reset_user', user_id=c.user.user_id), method='post')}
35 <div class="field">
35 <div class="field">
36 <button class="btn btn-default" type="submit">
36 <button class="btn btn-default" type="submit">
37 <i class="icon-lock"></i>
37 <i class="icon-lock"></i>
38 %if c.user.user_data.get('force_password_change'):
38 %if c.user.user_data.get('force_password_change'):
39 ${_('Disable forced password reset')}
39 ${_('Disable forced password reset')}
40 %else:
40 %else:
41 ${_('Enable forced password reset')}
41 ${_('Enable forced password reset')}
42 %endif
42 %endif
43 </button>
43 </button>
44 </div>
44 </div>
45 <div class="field">
45 <div class="field">
46 <span class="help-block">
46 <span class="help-block">
47 ${_("When this is enabled user will have to change they password when they next use RhodeCode system. This will also forbid vcs operations until someone makes a password change in the web interface")}
47 ${_("When this is enabled user will have to change they password when they next use RhodeCode system. This will also forbid vcs operations until someone makes a password change in the web interface")}
48 </span>
48 </span>
49 </div>
49 </div>
50 ${h.end_form()}
50 ${h.end_form()}
51 </div>
51 </div>
52 </div>
52 </div>
53
53
54 <div class="panel panel-default">
54 <div class="panel panel-default">
55 <div class="panel-heading">
55 <div class="panel-heading">
56 <h3 class="panel-title">${_('Personal Repository Group')}</h3>
56 <h3 class="panel-title">${_('Personal Repository Group')}</h3>
57 </div>
57 </div>
58 <div class="panel-body">
58 <div class="panel-body">
59 ${h.secure_form(h.url('create_personal_repo_group', user_id=c.user.user_id), method='post')}
59 ${h.secure_form(h.url('create_personal_repo_group', user_id=c.user.user_id), method='post')}
60
60
61 %if c.personal_repo_group:
61 %if c.personal_repo_group:
62 <div class="panel-body-title-text">${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, url('repo_group_home', group_name=c.personal_repo_group.group_name))}</div>
62 <div class="panel-body-title-text">${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, url('repo_group_home', group_name=c.personal_repo_group.group_name))}</div>
63 %else:
63 %else:
64 <div class="panel-body-title-text">
64 <div class="panel-body-title-text">
65 ${_('This user currently does not have a personal repository group')}
65 ${_('This user currently does not have a personal repository group')}
66 <br/>
66 <br/>
67 ${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}
67 ${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}
68 </div>
68 </div>
69 %endif
69 %endif
70 <button class="btn btn-default" type="submit" ${'disabled="disabled"' if c.personal_repo_group else ''}>
70 <button class="btn btn-default" type="submit" ${'disabled="disabled"' if c.personal_repo_group else ''}>
71 <i class="icon-folder-close"></i>
71 <i class="icon-folder-close"></i>
72 ${_('Create personal repository group')}
72 ${_('Create personal repository group')}
73 </button>
73 </button>
74 ${h.end_form()}
74 ${h.end_form()}
75 </div>
75 </div>
76 </div>
76 </div>
77
77
78
78
79 <div class="panel panel-danger">
79 <div class="panel panel-danger">
80 <div class="panel-heading">
80 <div class="panel-heading">
81 <h3 class="panel-title">${_('Delete User')}</h3>
81 <h3 class="panel-title">${_('Delete User')}</h3>
82 </div>
82 </div>
83 <div class="panel-body">
83 <div class="panel-body">
84 ${h.secure_form(h.url('delete_user', user_id=c.user.user_id), method='delete')}
84 ${h.secure_form(h.url('delete_user', user_id=c.user.user_id), method='delete')}
85
85
86 <table class="display">
86 <table class="display">
87 <tr>
87 <tr>
88 <td>
88 <td>
89 ${ungettext('This user owns %s repository.', 'This user owns %s repositories.', len(c.user.repositories)) % len(c.user.repositories)}
89 ${ungettext('This user owns %s repository.', 'This user owns %s repositories.', len(c.user.repositories)) % len(c.user.repositories)}
90 </td>
90 </td>
91 <td>
91 <td>
92 %if len(c.user.repositories) > 0:
92 %if len(c.user.repositories) > 0:
93 <input type="radio" id="user_repos_1" name="user_repos" value="detach" checked="checked"/> <label for="user_repos_1">${_('Detach repositories')}</label>
93 <input type="radio" id="user_repos_1" name="user_repos" value="detach" checked="checked"/> <label for="user_repos_1">${_('Detach repositories')}</label>
94 %endif
94 %endif
95 </td>
95 </td>
96 <td>
96 <td>
97 %if len(c.user.repositories) > 0:
97 %if len(c.user.repositories) > 0:
98 <input type="radio" id="user_repos_2" name="user_repos" value="delete" /> <label for="user_repos_2">${_('Delete repositories')}</label>
98 <input type="radio" id="user_repos_2" name="user_repos" value="delete" /> <label for="user_repos_2">${_('Delete repositories')}</label>
99 %endif
99 %endif
100 </td>
100 </td>
101 </tr>
101 </tr>
102
102
103 <tr>
103 <tr>
104 <td>
104 <td>
105 ${ungettext('This user owns %s repository group.', 'This user owns %s repository groups.', len(c.user.repository_groups)) % len(c.user.repository_groups)}
105 ${ungettext('This user owns %s repository group.', 'This user owns %s repository groups.', len(c.user.repository_groups)) % len(c.user.repository_groups)}
106 </td>
106 </td>
107 <td>
107 <td>
108 %if len(c.user.repository_groups) > 0:
108 %if len(c.user.repository_groups) > 0:
109 <input type="radio" id="user_repo_groups_1" name="user_repo_groups" value="detach" checked="checked"/> <label for="user_repo_groups_1">${_('Detach repository groups')}</label>
109 <input type="radio" id="user_repo_groups_1" name="user_repo_groups" value="detach" checked="checked"/> <label for="user_repo_groups_1">${_('Detach repository groups')}</label>
110 %endif
110 %endif
111 </td>
111 </td>
112 <td>
112 <td>
113 %if len(c.user.repository_groups) > 0:
113 %if len(c.user.repository_groups) > 0:
114 <input type="radio" id="user_repo_groups_2" name="user_repo_groups" value="delete" /> <label for="user_repo_groups_2">${_('Delete repositories')}</label>
114 <input type="radio" id="user_repo_groups_2" name="user_repo_groups" value="delete" /> <label for="user_repo_groups_2">${_('Delete repositories')}</label>
115 %endif
115 %endif
116 </td>
116 </td>
117 </tr>
117 </tr>
118
118
119 <tr>
119 <tr>
120 <td>
120 <td>
121 ${ungettext('This user owns %s user group.', 'This user owns %s user groups.', len(c.user.user_groups)) % len(c.user.user_groups)}
121 ${ungettext('This user owns %s user group.', 'This user owns %s user groups.', len(c.user.user_groups)) % len(c.user.user_groups)}
122 </td>
122 </td>
123 <td>
123 <td>
124 %if len(c.user.user_groups) > 0:
124 %if len(c.user.user_groups) > 0:
125 <input type="radio" id="user_user_groups_1" name="user_user_groups" value="detach" checked="checked"/> <label for="user_user_groups_1">${_('Detach user groups')}</label>
125 <input type="radio" id="user_user_groups_1" name="user_user_groups" value="detach" checked="checked"/> <label for="user_user_groups_1">${_('Detach user groups')}</label>
126 %endif
126 %endif
127 </td>
127 </td>
128 <td>
128 <td>
129 %if len(c.user.user_groups) > 0:
129 %if len(c.user.user_groups) > 0:
130 <input type="radio" id="user_user_groups_2" name="user_user_groups" value="delete" /> <label for="user_user_groups_2">${_('Delete repositories')}</label>
130 <input type="radio" id="user_user_groups_2" name="user_user_groups" value="delete" /> <label for="user_user_groups_2">${_('Delete repositories')}</label>
131 %endif
131 %endif
132 </td>
132 </td>
133 </tr>
133 </tr>
134 </table>
134 </table>
135 <div style="margin: 0 0 20px 0" class="fake-space"></div>
135 <div style="margin: 0 0 20px 0" class="fake-space"></div>
136
136
137 <div class="field">
137 <div class="field">
138 <button class="btn btn-small btn-danger" type="submit"
138 <button class="btn btn-small btn-danger" type="submit"
139 onclick="return confirm('${_('Confirm to delete this user: %s') % c.user.username}');"
139 onclick="return confirm('${_('Confirm to delete this user: %s') % c.user.username}');"
140 ${"disabled" if not c.can_delete_user else ""}>
140 ${"disabled" if not c.can_delete_user else ""}>
141 ${_('Delete this user')}
141 ${_('Delete this user')}
142 </button>
142 </button>
143 </div>
143 </div>
144 % if c.can_delete_user_message:
144 % if c.can_delete_user_message:
145 <p class="help-block">${c.can_delete_user_message}</p>
145 <p class="help-block">${c.can_delete_user_message}</p>
146 % endif
146 % endif
147
147
148 <div class="field">
148 <div class="field">
149 <span class="help-block">
149 <span class="help-block">
150 %if len(c.user.repositories) > 0 or len(c.user.repository_groups) > 0 or len(c.user.user_groups) > 0:
150 %if len(c.user.repositories) > 0 or len(c.user.repository_groups) > 0 or len(c.user.user_groups) > 0:
151 <p class="help-block">${_("When selecting the detach option, the depending objects owned by this user will be assigned to the `%s` super admin in the system. The delete option will delete the user's repositories!") % (c.first_admin.full_name)}</p>
151 <p class="help-block">${_("When selecting the detach option, the depending objects owned by this user will be assigned to the `%s` super admin in the system. The delete option will delete the user's repositories!") % (c.first_admin.full_name)}</p>
152 %endif
152 %endif
153 </span>
153 </span>
154 </div>
154 </div>
155
155
156 ${h.end_form()}
156 ${h.end_form()}
157 </div>
157 </div>
158 </div>
158 </div>
General Comments 0
You need to be logged in to leave comments. Login now