##// END OF EJS Templates
user/user-groups: show if users or user groups are a part of review rules....
marcink -
r2054:0026cc40 default
parent child Browse files
Show More

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

@@ -1,413 +1,417 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
3 # Copyright (C) 2011-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 """
21 """
22 User Groups crud controller for pylons
22 User Groups crud controller for pylons
23 """
23 """
24
24
25 import logging
25 import logging
26 import formencode
26 import formencode
27
27
28 import peppercorn
28 import peppercorn
29 from formencode import htmlfill
29 from formencode import htmlfill
30 from pylons import request, tmpl_context as c, url, config
30 from pylons import request, tmpl_context as c, url, config
31 from pylons.controllers.util import redirect
31 from pylons.controllers.util import redirect
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33
33
34 from rhodecode.lib import auth
34 from rhodecode.lib import auth
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib import audit_logger
36 from rhodecode.lib import audit_logger
37 from rhodecode.lib.exceptions import UserGroupAssignedException,\
37 from rhodecode.lib.exceptions import UserGroupAssignedException,\
38 RepoGroupAssignmentError
38 RepoGroupAssignmentError
39 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
39 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
40 from rhodecode.lib.auth import (
40 from rhodecode.lib.auth import (
41 LoginRequired, NotAnonymous, HasUserGroupPermissionAnyDecorator,
41 LoginRequired, NotAnonymous, HasUserGroupPermissionAnyDecorator,
42 HasPermissionAnyDecorator)
42 HasPermissionAnyDecorator)
43 from rhodecode.lib.base import BaseController, render
43 from rhodecode.lib.base import BaseController, render
44 from rhodecode.model.permission import PermissionModel
44 from rhodecode.model.permission import PermissionModel
45 from rhodecode.model.user_group import UserGroupModel
45 from rhodecode.model.user_group import UserGroupModel
46 from rhodecode.model.db import User, UserGroup
46 from rhodecode.model.db import User, UserGroup
47 from rhodecode.model.forms import (
47 from rhodecode.model.forms import (
48 UserGroupForm, UserGroupPermsForm, UserIndividualPermissionsForm,
48 UserGroupForm, UserGroupPermsForm, UserIndividualPermissionsForm,
49 UserPermissionsForm)
49 UserPermissionsForm)
50 from rhodecode.model.meta import Session
50 from rhodecode.model.meta import Session
51
51
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 class UserGroupsController(BaseController):
56 class UserGroupsController(BaseController):
57 """REST Controller styled on the Atom Publishing Protocol"""
57 """REST Controller styled on the Atom Publishing Protocol"""
58
58
59 @LoginRequired()
59 @LoginRequired()
60 def __before__(self):
60 def __before__(self):
61 super(UserGroupsController, self).__before__()
61 super(UserGroupsController, self).__before__()
62 c.available_permissions = config['available_permissions']
62 c.available_permissions = config['available_permissions']
63 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
63 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
64
64
65 def __load_data(self, user_group_id):
65 def __load_data(self, user_group_id):
66 c.group_members_obj = [x.user for x in c.user_group.members]
66 c.group_members_obj = [x.user for x in c.user_group.members]
67 c.group_members_obj.sort(key=lambda u: u.username.lower())
67 c.group_members_obj.sort(key=lambda u: u.username.lower())
68 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
68 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
69
69
70 def __load_defaults(self, user_group_id):
70 def __load_defaults(self, user_group_id):
71 """
71 """
72 Load defaults settings for edit, and update
72 Load defaults settings for edit, and update
73
73
74 :param user_group_id:
74 :param user_group_id:
75 """
75 """
76 user_group = UserGroup.get_or_404(user_group_id)
76 user_group = UserGroup.get_or_404(user_group_id)
77 data = user_group.get_dict()
77 data = user_group.get_dict()
78 # fill owner
78 # fill owner
79 if user_group.user:
79 if user_group.user:
80 data.update({'user': user_group.user.username})
80 data.update({'user': user_group.user.username})
81 else:
81 else:
82 replacement_user = User.get_first_super_admin().username
82 replacement_user = User.get_first_super_admin().username
83 data.update({'user': replacement_user})
83 data.update({'user': replacement_user})
84 return data
84 return data
85
85
86 def _revoke_perms_on_yourself(self, form_result):
86 def _revoke_perms_on_yourself(self, form_result):
87 _updates = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
87 _updates = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
88 form_result['perm_updates'])
88 form_result['perm_updates'])
89 _additions = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
89 _additions = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
90 form_result['perm_additions'])
90 form_result['perm_additions'])
91 _deletions = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
91 _deletions = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
92 form_result['perm_deletions'])
92 form_result['perm_deletions'])
93 admin_perm = 'usergroup.admin'
93 admin_perm = 'usergroup.admin'
94 if _updates and _updates[0][1] != admin_perm or \
94 if _updates and _updates[0][1] != admin_perm or \
95 _additions and _additions[0][1] != admin_perm or \
95 _additions and _additions[0][1] != admin_perm or \
96 _deletions and _deletions[0][1] != admin_perm:
96 _deletions and _deletions[0][1] != admin_perm:
97 return True
97 return True
98 return False
98 return False
99
99
100 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
100 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
101 @auth.CSRFRequired()
101 @auth.CSRFRequired()
102 def create(self):
102 def create(self):
103
103
104 users_group_form = UserGroupForm()()
104 users_group_form = UserGroupForm()()
105 try:
105 try:
106 form_result = users_group_form.to_python(dict(request.POST))
106 form_result = users_group_form.to_python(dict(request.POST))
107 user_group = UserGroupModel().create(
107 user_group = UserGroupModel().create(
108 name=form_result['users_group_name'],
108 name=form_result['users_group_name'],
109 description=form_result['user_group_description'],
109 description=form_result['user_group_description'],
110 owner=c.rhodecode_user.user_id,
110 owner=c.rhodecode_user.user_id,
111 active=form_result['users_group_active'])
111 active=form_result['users_group_active'])
112 Session().flush()
112 Session().flush()
113 creation_data = user_group.get_api_data()
113 creation_data = user_group.get_api_data()
114 user_group_name = form_result['users_group_name']
114 user_group_name = form_result['users_group_name']
115
115
116 audit_logger.store_web(
116 audit_logger.store_web(
117 'user_group.create', action_data={'data': creation_data},
117 'user_group.create', action_data={'data': creation_data},
118 user=c.rhodecode_user)
118 user=c.rhodecode_user)
119
119
120 user_group_link = h.link_to(
120 user_group_link = h.link_to(
121 h.escape(user_group_name),
121 h.escape(user_group_name),
122 url('edit_users_group', user_group_id=user_group.users_group_id))
122 url('edit_users_group', user_group_id=user_group.users_group_id))
123 h.flash(h.literal(_('Created user group %(user_group_link)s')
123 h.flash(h.literal(_('Created user group %(user_group_link)s')
124 % {'user_group_link': user_group_link}),
124 % {'user_group_link': user_group_link}),
125 category='success')
125 category='success')
126 Session().commit()
126 Session().commit()
127 except formencode.Invalid as errors:
127 except formencode.Invalid as errors:
128 return htmlfill.render(
128 return htmlfill.render(
129 render('admin/user_groups/user_group_add.mako'),
129 render('admin/user_groups/user_group_add.mako'),
130 defaults=errors.value,
130 defaults=errors.value,
131 errors=errors.error_dict or {},
131 errors=errors.error_dict or {},
132 prefix_error=False,
132 prefix_error=False,
133 encoding="UTF-8",
133 encoding="UTF-8",
134 force_defaults=False)
134 force_defaults=False)
135 except Exception:
135 except Exception:
136 log.exception("Exception creating user group")
136 log.exception("Exception creating user group")
137 h.flash(_('Error occurred during creation of user group %s') \
137 h.flash(_('Error occurred during creation of user group %s') \
138 % request.POST.get('users_group_name'), category='error')
138 % request.POST.get('users_group_name'), category='error')
139
139
140 return redirect(
140 return redirect(
141 url('edit_users_group', user_group_id=user_group.users_group_id))
141 url('edit_users_group', user_group_id=user_group.users_group_id))
142
142
143 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
143 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
144 def new(self):
144 def new(self):
145 """GET /user_groups/new: Form to create a new item"""
145 """GET /user_groups/new: Form to create a new item"""
146 # url('new_users_group')
146 # url('new_users_group')
147 return render('admin/user_groups/user_group_add.mako')
147 return render('admin/user_groups/user_group_add.mako')
148
148
149 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
149 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
150 @auth.CSRFRequired()
150 @auth.CSRFRequired()
151 def update(self, user_group_id):
151 def update(self, user_group_id):
152
152
153 user_group_id = safe_int(user_group_id)
153 user_group_id = safe_int(user_group_id)
154 c.user_group = UserGroup.get_or_404(user_group_id)
154 c.user_group = UserGroup.get_or_404(user_group_id)
155 c.active = 'settings'
155 c.active = 'settings'
156 self.__load_data(user_group_id)
156 self.__load_data(user_group_id)
157
157
158 users_group_form = UserGroupForm(
158 users_group_form = UserGroupForm(
159 edit=True, old_data=c.user_group.get_dict(), allow_disabled=True)()
159 edit=True, old_data=c.user_group.get_dict(), allow_disabled=True)()
160
160
161 old_values = c.user_group.get_api_data()
161 old_values = c.user_group.get_api_data()
162 try:
162 try:
163 form_result = users_group_form.to_python(request.POST)
163 form_result = users_group_form.to_python(request.POST)
164 pstruct = peppercorn.parse(request.POST.items())
164 pstruct = peppercorn.parse(request.POST.items())
165 form_result['users_group_members'] = pstruct['user_group_members']
165 form_result['users_group_members'] = pstruct['user_group_members']
166
166
167 user_group, added_members, removed_members = \
167 user_group, added_members, removed_members = \
168 UserGroupModel().update(c.user_group, form_result)
168 UserGroupModel().update(c.user_group, form_result)
169 updated_user_group = form_result['users_group_name']
169 updated_user_group = form_result['users_group_name']
170
170
171 audit_logger.store_web(
171 audit_logger.store_web(
172 'user_group.edit', action_data={'old_data': old_values},
172 'user_group.edit', action_data={'old_data': old_values},
173 user=c.rhodecode_user)
173 user=c.rhodecode_user)
174
174
175 # TODO(marcink): use added/removed to set user_group.edit.member.add
175 # TODO(marcink): use added/removed to set user_group.edit.member.add
176
176
177 h.flash(_('Updated user group %s') % updated_user_group,
177 h.flash(_('Updated user group %s') % updated_user_group,
178 category='success')
178 category='success')
179 Session().commit()
179 Session().commit()
180 except formencode.Invalid as errors:
180 except formencode.Invalid as errors:
181 defaults = errors.value
181 defaults = errors.value
182 e = errors.error_dict or {}
182 e = errors.error_dict or {}
183
183
184 return htmlfill.render(
184 return htmlfill.render(
185 render('admin/user_groups/user_group_edit.mako'),
185 render('admin/user_groups/user_group_edit.mako'),
186 defaults=defaults,
186 defaults=defaults,
187 errors=e,
187 errors=e,
188 prefix_error=False,
188 prefix_error=False,
189 encoding="UTF-8",
189 encoding="UTF-8",
190 force_defaults=False)
190 force_defaults=False)
191 except Exception:
191 except Exception:
192 log.exception("Exception during update of user group")
192 log.exception("Exception during update of user group")
193 h.flash(_('Error occurred during update of user group %s')
193 h.flash(_('Error occurred during update of user group %s')
194 % request.POST.get('users_group_name'), category='error')
194 % request.POST.get('users_group_name'), category='error')
195
195
196 return redirect(url('edit_users_group', user_group_id=user_group_id))
196 return redirect(url('edit_users_group', user_group_id=user_group_id))
197
197
198 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
198 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
199 @auth.CSRFRequired()
199 @auth.CSRFRequired()
200 def delete(self, user_group_id):
200 def delete(self, user_group_id):
201 user_group_id = safe_int(user_group_id)
201 user_group_id = safe_int(user_group_id)
202 c.user_group = UserGroup.get_or_404(user_group_id)
202 c.user_group = UserGroup.get_or_404(user_group_id)
203 force = str2bool(request.POST.get('force'))
203 force = str2bool(request.POST.get('force'))
204
204
205 old_values = c.user_group.get_api_data()
205 old_values = c.user_group.get_api_data()
206 try:
206 try:
207 UserGroupModel().delete(c.user_group, force=force)
207 UserGroupModel().delete(c.user_group, force=force)
208 audit_logger.store_web(
208 audit_logger.store_web(
209 'user.delete', action_data={'old_data': old_values},
209 'user.delete', action_data={'old_data': old_values},
210 user=c.rhodecode_user)
210 user=c.rhodecode_user)
211 Session().commit()
211 Session().commit()
212 h.flash(_('Successfully deleted user group'), category='success')
212 h.flash(_('Successfully deleted user group'), category='success')
213 except UserGroupAssignedException as e:
213 except UserGroupAssignedException as e:
214 h.flash(str(e), category='error')
214 h.flash(str(e), category='error')
215 except Exception:
215 except Exception:
216 log.exception("Exception during deletion of user group")
216 log.exception("Exception during deletion of user group")
217 h.flash(_('An error occurred during deletion of user group'),
217 h.flash(_('An error occurred during deletion of user group'),
218 category='error')
218 category='error')
219 return redirect(url('users_groups'))
219 return redirect(url('users_groups'))
220
220
221 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
221 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
222 def edit(self, user_group_id):
222 def edit(self, user_group_id):
223 """GET /user_groups/user_group_id/edit: Form to edit an existing item"""
223 """GET /user_groups/user_group_id/edit: Form to edit an existing item"""
224 # url('edit_users_group', user_group_id=ID)
224 # url('edit_users_group', user_group_id=ID)
225
225
226 user_group_id = safe_int(user_group_id)
226 user_group_id = safe_int(user_group_id)
227 c.user_group = UserGroup.get_or_404(user_group_id)
227 c.user_group = UserGroup.get_or_404(user_group_id)
228 c.active = 'settings'
228 c.active = 'settings'
229 self.__load_data(user_group_id)
229 self.__load_data(user_group_id)
230
230
231 defaults = self.__load_defaults(user_group_id)
231 defaults = self.__load_defaults(user_group_id)
232
232
233 return htmlfill.render(
233 return htmlfill.render(
234 render('admin/user_groups/user_group_edit.mako'),
234 render('admin/user_groups/user_group_edit.mako'),
235 defaults=defaults,
235 defaults=defaults,
236 encoding="UTF-8",
236 encoding="UTF-8",
237 force_defaults=False
237 force_defaults=False
238 )
238 )
239
239
240 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
240 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
241 def edit_perms(self, user_group_id):
241 def edit_perms(self, user_group_id):
242 user_group_id = safe_int(user_group_id)
242 user_group_id = safe_int(user_group_id)
243 c.user_group = UserGroup.get_or_404(user_group_id)
243 c.user_group = UserGroup.get_or_404(user_group_id)
244 c.active = 'perms'
244 c.active = 'perms'
245
245
246 defaults = {}
246 defaults = {}
247 # fill user group users
247 # fill user group users
248 for p in c.user_group.user_user_group_to_perm:
248 for p in c.user_group.user_user_group_to_perm:
249 defaults.update({'u_perm_%s' % p.user.user_id:
249 defaults.update({'u_perm_%s' % p.user.user_id:
250 p.permission.permission_name})
250 p.permission.permission_name})
251
251
252 for p in c.user_group.user_group_user_group_to_perm:
252 for p in c.user_group.user_group_user_group_to_perm:
253 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
253 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
254 p.permission.permission_name})
254 p.permission.permission_name})
255
255
256 return htmlfill.render(
256 return htmlfill.render(
257 render('admin/user_groups/user_group_edit.mako'),
257 render('admin/user_groups/user_group_edit.mako'),
258 defaults=defaults,
258 defaults=defaults,
259 encoding="UTF-8",
259 encoding="UTF-8",
260 force_defaults=False
260 force_defaults=False
261 )
261 )
262
262
263 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
263 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
264 @auth.CSRFRequired()
264 @auth.CSRFRequired()
265 def update_perms(self, user_group_id):
265 def update_perms(self, user_group_id):
266 """
266 """
267 grant permission for given usergroup
267 grant permission for given usergroup
268
268
269 :param user_group_id:
269 :param user_group_id:
270 """
270 """
271 user_group_id = safe_int(user_group_id)
271 user_group_id = safe_int(user_group_id)
272 c.user_group = UserGroup.get_or_404(user_group_id)
272 c.user_group = UserGroup.get_or_404(user_group_id)
273 form = UserGroupPermsForm()().to_python(request.POST)
273 form = UserGroupPermsForm()().to_python(request.POST)
274
274
275 if not c.rhodecode_user.is_admin:
275 if not c.rhodecode_user.is_admin:
276 if self._revoke_perms_on_yourself(form):
276 if self._revoke_perms_on_yourself(form):
277 msg = _('Cannot change permission for yourself as admin')
277 msg = _('Cannot change permission for yourself as admin')
278 h.flash(msg, category='warning')
278 h.flash(msg, category='warning')
279 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
279 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
280
280
281 try:
281 try:
282 UserGroupModel().update_permissions(user_group_id,
282 UserGroupModel().update_permissions(user_group_id,
283 form['perm_additions'], form['perm_updates'], form['perm_deletions'])
283 form['perm_additions'], form['perm_updates'], form['perm_deletions'])
284 except RepoGroupAssignmentError:
284 except RepoGroupAssignmentError:
285 h.flash(_('Target group cannot be the same'), category='error')
285 h.flash(_('Target group cannot be the same'), category='error')
286 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
286 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
287
287
288 # TODO(marcink): implement global permissions
288 # TODO(marcink): implement global permissions
289 # audit_log.store_web('user_group.edit.permissions')
289 # audit_log.store_web('user_group.edit.permissions')
290 Session().commit()
290 Session().commit()
291 h.flash(_('User Group permissions updated'), category='success')
291 h.flash(_('User Group permissions updated'), category='success')
292 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
292 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
293
293
294
294
295
295
296 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
296 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
297 def edit_global_perms(self, user_group_id):
297 def edit_global_perms(self, user_group_id):
298 user_group_id = safe_int(user_group_id)
298 user_group_id = safe_int(user_group_id)
299 c.user_group = UserGroup.get_or_404(user_group_id)
299 c.user_group = UserGroup.get_or_404(user_group_id)
300 c.active = 'global_perms'
300 c.active = 'global_perms'
301
301
302 c.default_user = User.get_default_user()
302 c.default_user = User.get_default_user()
303 defaults = c.user_group.get_dict()
303 defaults = c.user_group.get_dict()
304 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
304 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
305 defaults.update(c.user_group.get_default_perms())
305 defaults.update(c.user_group.get_default_perms())
306
306
307 return htmlfill.render(
307 return htmlfill.render(
308 render('admin/user_groups/user_group_edit.mako'),
308 render('admin/user_groups/user_group_edit.mako'),
309 defaults=defaults,
309 defaults=defaults,
310 encoding="UTF-8",
310 encoding="UTF-8",
311 force_defaults=False
311 force_defaults=False
312 )
312 )
313
313
314 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
314 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
315 @auth.CSRFRequired()
315 @auth.CSRFRequired()
316 def update_global_perms(self, user_group_id):
316 def update_global_perms(self, user_group_id):
317 user_group_id = safe_int(user_group_id)
317 user_group_id = safe_int(user_group_id)
318 user_group = UserGroup.get_or_404(user_group_id)
318 user_group = UserGroup.get_or_404(user_group_id)
319 c.active = 'global_perms'
319 c.active = 'global_perms'
320
320
321 try:
321 try:
322 # first stage that verifies the checkbox
322 # first stage that verifies the checkbox
323 _form = UserIndividualPermissionsForm()
323 _form = UserIndividualPermissionsForm()
324 form_result = _form.to_python(dict(request.POST))
324 form_result = _form.to_python(dict(request.POST))
325 inherit_perms = form_result['inherit_default_permissions']
325 inherit_perms = form_result['inherit_default_permissions']
326 user_group.inherit_default_permissions = inherit_perms
326 user_group.inherit_default_permissions = inherit_perms
327 Session().add(user_group)
327 Session().add(user_group)
328
328
329 if not inherit_perms:
329 if not inherit_perms:
330 # only update the individual ones if we un check the flag
330 # only update the individual ones if we un check the flag
331 _form = UserPermissionsForm(
331 _form = UserPermissionsForm(
332 [x[0] for x in c.repo_create_choices],
332 [x[0] for x in c.repo_create_choices],
333 [x[0] for x in c.repo_create_on_write_choices],
333 [x[0] for x in c.repo_create_on_write_choices],
334 [x[0] for x in c.repo_group_create_choices],
334 [x[0] for x in c.repo_group_create_choices],
335 [x[0] for x in c.user_group_create_choices],
335 [x[0] for x in c.user_group_create_choices],
336 [x[0] for x in c.fork_choices],
336 [x[0] for x in c.fork_choices],
337 [x[0] for x in c.inherit_default_permission_choices])()
337 [x[0] for x in c.inherit_default_permission_choices])()
338
338
339 form_result = _form.to_python(dict(request.POST))
339 form_result = _form.to_python(dict(request.POST))
340 form_result.update({'perm_user_group_id': user_group.users_group_id})
340 form_result.update({'perm_user_group_id': user_group.users_group_id})
341
341
342 PermissionModel().update_user_group_permissions(form_result)
342 PermissionModel().update_user_group_permissions(form_result)
343
343
344 Session().commit()
344 Session().commit()
345 h.flash(_('User Group global permissions updated successfully'),
345 h.flash(_('User Group global permissions updated successfully'),
346 category='success')
346 category='success')
347
347
348 except formencode.Invalid as errors:
348 except formencode.Invalid as errors:
349 defaults = errors.value
349 defaults = errors.value
350 c.user_group = user_group
350 c.user_group = user_group
351 return htmlfill.render(
351 return htmlfill.render(
352 render('admin/user_groups/user_group_edit.mako'),
352 render('admin/user_groups/user_group_edit.mako'),
353 defaults=defaults,
353 defaults=defaults,
354 errors=errors.error_dict or {},
354 errors=errors.error_dict or {},
355 prefix_error=False,
355 prefix_error=False,
356 encoding="UTF-8",
356 encoding="UTF-8",
357 force_defaults=False)
357 force_defaults=False)
358 except Exception:
358 except Exception:
359 log.exception("Exception during permissions saving")
359 log.exception("Exception during permissions saving")
360 h.flash(_('An error occurred during permissions saving'),
360 h.flash(_('An error occurred during permissions saving'),
361 category='error')
361 category='error')
362
362
363 return redirect(url('edit_user_group_global_perms', user_group_id=user_group_id))
363 return redirect(url('edit_user_group_global_perms', user_group_id=user_group_id))
364
364
365 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
365 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
366 def edit_advanced(self, user_group_id):
366 def edit_advanced(self, user_group_id):
367 user_group_id = safe_int(user_group_id)
367 user_group_id = safe_int(user_group_id)
368 c.user_group = UserGroup.get_or_404(user_group_id)
368 c.user_group = UserGroup.get_or_404(user_group_id)
369 c.active = 'advanced'
369 c.active = 'advanced'
370 c.group_members_obj = sorted(
370 c.group_members_obj = sorted(
371 (x.user for x in c.user_group.members),
371 (x.user for x in c.user_group.members),
372 key=lambda u: u.username.lower())
372 key=lambda u: u.username.lower())
373
373
374 c.group_to_repos = sorted(
374 c.group_to_repos = sorted(
375 (x.repository for x in c.user_group.users_group_repo_to_perm),
375 (x.repository for x in c.user_group.users_group_repo_to_perm),
376 key=lambda u: u.repo_name.lower())
376 key=lambda u: u.repo_name.lower())
377
377
378 c.group_to_repo_groups = sorted(
378 c.group_to_repo_groups = sorted(
379 (x.group for x in c.user_group.users_group_repo_group_to_perm),
379 (x.group for x in c.user_group.users_group_repo_group_to_perm),
380 key=lambda u: u.group_name.lower())
380 key=lambda u: u.group_name.lower())
381
381
382 c.group_to_review_rules = sorted(
383 (x.users_group for x in c.user_group.user_group_review_rules),
384 key=lambda u: u.users_group_name.lower())
385
382 return render('admin/user_groups/user_group_edit.mako')
386 return render('admin/user_groups/user_group_edit.mako')
383
387
384 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
388 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
385 def edit_advanced_set_synchronization(self, user_group_id):
389 def edit_advanced_set_synchronization(self, user_group_id):
386 user_group_id = safe_int(user_group_id)
390 user_group_id = safe_int(user_group_id)
387 user_group = UserGroup.get_or_404(user_group_id)
391 user_group = UserGroup.get_or_404(user_group_id)
388
392
389 existing = user_group.group_data.get('extern_type')
393 existing = user_group.group_data.get('extern_type')
390
394
391 if existing:
395 if existing:
392 new_state = user_group.group_data
396 new_state = user_group.group_data
393 new_state['extern_type'] = None
397 new_state['extern_type'] = None
394 else:
398 else:
395 new_state = user_group.group_data
399 new_state = user_group.group_data
396 new_state['extern_type'] = 'manual'
400 new_state['extern_type'] = 'manual'
397 new_state['extern_type_set_by'] = c.rhodecode_user.username
401 new_state['extern_type_set_by'] = c.rhodecode_user.username
398
402
399 try:
403 try:
400 user_group.group_data = new_state
404 user_group.group_data = new_state
401 Session().add(user_group)
405 Session().add(user_group)
402 Session().commit()
406 Session().commit()
403
407
404 h.flash(_('User Group synchronization updated successfully'),
408 h.flash(_('User Group synchronization updated successfully'),
405 category='success')
409 category='success')
406 except Exception:
410 except Exception:
407 log.exception("Exception during sync settings saving")
411 log.exception("Exception during sync settings saving")
408 h.flash(_('An error occurred during synchronization update'),
412 h.flash(_('An error occurred during synchronization update'),
409 category='error')
413 category='error')
410
414
411 return redirect(
415 return redirect(
412 url('edit_user_group_advanced', user_group_id=user_group_id))
416 url('edit_user_group_advanced', user_group_id=user_group_id))
413
417
@@ -1,491 +1,496 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-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 """
21 """
22 Users crud controller for pylons
22 Users crud controller for pylons
23 """
23 """
24
24
25 import logging
25 import logging
26 import formencode
26 import formencode
27
27
28 from formencode import htmlfill
28 from formencode import htmlfill
29 from pylons import request, tmpl_context as c, url, config
29 from pylons import request, tmpl_context as c, url, config
30 from pylons.controllers.util import redirect
30 from pylons.controllers.util import redirect
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 from rhodecode.authentication.plugins import auth_rhodecode
33 from rhodecode.authentication.plugins import auth_rhodecode
34
34
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib import auth
36 from rhodecode.lib import auth
37 from rhodecode.lib import audit_logger
37 from rhodecode.lib import audit_logger
38 from rhodecode.lib.auth import (
38 from rhodecode.lib.auth import (
39 LoginRequired, HasPermissionAllDecorator, AuthUser)
39 LoginRequired, HasPermissionAllDecorator, AuthUser)
40 from rhodecode.lib.base import BaseController, render
40 from rhodecode.lib.base import BaseController, render
41 from rhodecode.lib.exceptions import (
41 from rhodecode.lib.exceptions import (
42 DefaultUserException, UserOwnsReposException, UserOwnsRepoGroupsException,
42 DefaultUserException, UserOwnsReposException, UserOwnsRepoGroupsException,
43 UserOwnsUserGroupsException, UserCreationError)
43 UserOwnsUserGroupsException, UserCreationError)
44 from rhodecode.lib.utils2 import safe_int, AttributeDict
44 from rhodecode.lib.utils2 import safe_int, AttributeDict
45
45
46 from rhodecode.model.db import (
46 from rhodecode.model.db import (
47 PullRequestReviewers, User, UserEmailMap, UserIpMap, RepoGroup)
47 PullRequestReviewers, User, UserEmailMap, UserIpMap, RepoGroup)
48 from rhodecode.model.forms import (
48 from rhodecode.model.forms import (
49 UserForm, UserPermissionsForm, UserIndividualPermissionsForm)
49 UserForm, UserPermissionsForm, UserIndividualPermissionsForm)
50 from rhodecode.model.repo_group import RepoGroupModel
50 from rhodecode.model.repo_group import RepoGroupModel
51 from rhodecode.model.user import UserModel
51 from rhodecode.model.user import UserModel
52 from rhodecode.model.meta import Session
52 from rhodecode.model.meta import Session
53 from rhodecode.model.permission import PermissionModel
53 from rhodecode.model.permission import PermissionModel
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 class UsersController(BaseController):
58 class UsersController(BaseController):
59 """REST Controller styled on the Atom Publishing Protocol"""
59 """REST Controller styled on the Atom Publishing Protocol"""
60
60
61 @LoginRequired()
61 @LoginRequired()
62 def __before__(self):
62 def __before__(self):
63 super(UsersController, self).__before__()
63 super(UsersController, self).__before__()
64 c.available_permissions = config['available_permissions']
64 c.available_permissions = config['available_permissions']
65 c.allowed_languages = [
65 c.allowed_languages = [
66 ('en', 'English (en)'),
66 ('en', 'English (en)'),
67 ('de', 'German (de)'),
67 ('de', 'German (de)'),
68 ('fr', 'French (fr)'),
68 ('fr', 'French (fr)'),
69 ('it', 'Italian (it)'),
69 ('it', 'Italian (it)'),
70 ('ja', 'Japanese (ja)'),
70 ('ja', 'Japanese (ja)'),
71 ('pl', 'Polish (pl)'),
71 ('pl', 'Polish (pl)'),
72 ('pt', 'Portuguese (pt)'),
72 ('pt', 'Portuguese (pt)'),
73 ('ru', 'Russian (ru)'),
73 ('ru', 'Russian (ru)'),
74 ('zh', 'Chinese (zh)'),
74 ('zh', 'Chinese (zh)'),
75 ]
75 ]
76 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
76 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
77
77
78 def _get_personal_repo_group_template_vars(self):
78 def _get_personal_repo_group_template_vars(self):
79 DummyUser = AttributeDict({
79 DummyUser = AttributeDict({
80 'username': '${username}',
80 'username': '${username}',
81 'user_id': '${user_id}',
81 'user_id': '${user_id}',
82 })
82 })
83 c.default_create_repo_group = RepoGroupModel() \
83 c.default_create_repo_group = RepoGroupModel() \
84 .get_default_create_personal_repo_group()
84 .get_default_create_personal_repo_group()
85 c.personal_repo_group_name = RepoGroupModel() \
85 c.personal_repo_group_name = RepoGroupModel() \
86 .get_personal_group_name(DummyUser)
86 .get_personal_group_name(DummyUser)
87
87
88 @HasPermissionAllDecorator('hg.admin')
88 @HasPermissionAllDecorator('hg.admin')
89 @auth.CSRFRequired()
89 @auth.CSRFRequired()
90 def create(self):
90 def create(self):
91 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
91 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
92 user_model = UserModel()
92 user_model = UserModel()
93 user_form = UserForm()()
93 user_form = UserForm()()
94 try:
94 try:
95 form_result = user_form.to_python(dict(request.POST))
95 form_result = user_form.to_python(dict(request.POST))
96 user = user_model.create(form_result)
96 user = user_model.create(form_result)
97 Session().flush()
97 Session().flush()
98 creation_data = user.get_api_data()
98 creation_data = user.get_api_data()
99 username = form_result['username']
99 username = form_result['username']
100
100
101 audit_logger.store_web(
101 audit_logger.store_web(
102 'user.create', action_data={'data': creation_data},
102 'user.create', action_data={'data': creation_data},
103 user=c.rhodecode_user)
103 user=c.rhodecode_user)
104
104
105 user_link = h.link_to(h.escape(username),
105 user_link = h.link_to(h.escape(username),
106 url('edit_user',
106 url('edit_user',
107 user_id=user.user_id))
107 user_id=user.user_id))
108 h.flash(h.literal(_('Created user %(user_link)s')
108 h.flash(h.literal(_('Created user %(user_link)s')
109 % {'user_link': user_link}), category='success')
109 % {'user_link': user_link}), category='success')
110 Session().commit()
110 Session().commit()
111 except formencode.Invalid as errors:
111 except formencode.Invalid as errors:
112 self._get_personal_repo_group_template_vars()
112 self._get_personal_repo_group_template_vars()
113 return htmlfill.render(
113 return htmlfill.render(
114 render('admin/users/user_add.mako'),
114 render('admin/users/user_add.mako'),
115 defaults=errors.value,
115 defaults=errors.value,
116 errors=errors.error_dict or {},
116 errors=errors.error_dict or {},
117 prefix_error=False,
117 prefix_error=False,
118 encoding="UTF-8",
118 encoding="UTF-8",
119 force_defaults=False)
119 force_defaults=False)
120 except UserCreationError as e:
120 except UserCreationError as e:
121 h.flash(e, 'error')
121 h.flash(e, 'error')
122 except Exception:
122 except Exception:
123 log.exception("Exception creation of user")
123 log.exception("Exception creation of user")
124 h.flash(_('Error occurred during creation of user %s')
124 h.flash(_('Error occurred during creation of user %s')
125 % request.POST.get('username'), category='error')
125 % request.POST.get('username'), category='error')
126 return redirect(h.route_path('users'))
126 return redirect(h.route_path('users'))
127
127
128 @HasPermissionAllDecorator('hg.admin')
128 @HasPermissionAllDecorator('hg.admin')
129 def new(self):
129 def new(self):
130 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
130 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
131 self._get_personal_repo_group_template_vars()
131 self._get_personal_repo_group_template_vars()
132 return render('admin/users/user_add.mako')
132 return render('admin/users/user_add.mako')
133
133
134 @HasPermissionAllDecorator('hg.admin')
134 @HasPermissionAllDecorator('hg.admin')
135 @auth.CSRFRequired()
135 @auth.CSRFRequired()
136 def update(self, user_id):
136 def update(self, user_id):
137
137
138 user_id = safe_int(user_id)
138 user_id = safe_int(user_id)
139 c.user = User.get_or_404(user_id)
139 c.user = User.get_or_404(user_id)
140 c.active = 'profile'
140 c.active = 'profile'
141 c.extern_type = c.user.extern_type
141 c.extern_type = c.user.extern_type
142 c.extern_name = c.user.extern_name
142 c.extern_name = c.user.extern_name
143 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
143 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
144 available_languages = [x[0] for x in c.allowed_languages]
144 available_languages = [x[0] for x in c.allowed_languages]
145 _form = UserForm(edit=True, available_languages=available_languages,
145 _form = UserForm(edit=True, available_languages=available_languages,
146 old_data={'user_id': user_id,
146 old_data={'user_id': user_id,
147 'email': c.user.email})()
147 'email': c.user.email})()
148 form_result = {}
148 form_result = {}
149 old_values = c.user.get_api_data()
149 old_values = c.user.get_api_data()
150 try:
150 try:
151 form_result = _form.to_python(dict(request.POST))
151 form_result = _form.to_python(dict(request.POST))
152 skip_attrs = ['extern_type', 'extern_name']
152 skip_attrs = ['extern_type', 'extern_name']
153 # TODO: plugin should define if username can be updated
153 # TODO: plugin should define if username can be updated
154 if c.extern_type != "rhodecode":
154 if c.extern_type != "rhodecode":
155 # forbid updating username for external accounts
155 # forbid updating username for external accounts
156 skip_attrs.append('username')
156 skip_attrs.append('username')
157
157
158 UserModel().update_user(
158 UserModel().update_user(
159 user_id, skip_attrs=skip_attrs, **form_result)
159 user_id, skip_attrs=skip_attrs, **form_result)
160
160
161 audit_logger.store_web(
161 audit_logger.store_web(
162 'user.edit', action_data={'old_data': old_values},
162 'user.edit', action_data={'old_data': old_values},
163 user=c.rhodecode_user)
163 user=c.rhodecode_user)
164
164
165 Session().commit()
165 Session().commit()
166 h.flash(_('User updated successfully'), category='success')
166 h.flash(_('User updated successfully'), category='success')
167 except formencode.Invalid as errors:
167 except formencode.Invalid as errors:
168 defaults = errors.value
168 defaults = errors.value
169 e = errors.error_dict or {}
169 e = errors.error_dict or {}
170
170
171 return htmlfill.render(
171 return htmlfill.render(
172 render('admin/users/user_edit.mako'),
172 render('admin/users/user_edit.mako'),
173 defaults=defaults,
173 defaults=defaults,
174 errors=e,
174 errors=e,
175 prefix_error=False,
175 prefix_error=False,
176 encoding="UTF-8",
176 encoding="UTF-8",
177 force_defaults=False)
177 force_defaults=False)
178 except UserCreationError as e:
178 except UserCreationError as e:
179 h.flash(e, 'error')
179 h.flash(e, 'error')
180 except Exception:
180 except Exception:
181 log.exception("Exception updating user")
181 log.exception("Exception updating user")
182 h.flash(_('Error occurred during update of user %s')
182 h.flash(_('Error occurred during update of user %s')
183 % form_result.get('username'), category='error')
183 % form_result.get('username'), category='error')
184 return redirect(url('edit_user', user_id=user_id))
184 return redirect(url('edit_user', user_id=user_id))
185
185
186 @HasPermissionAllDecorator('hg.admin')
186 @HasPermissionAllDecorator('hg.admin')
187 @auth.CSRFRequired()
187 @auth.CSRFRequired()
188 def delete(self, user_id):
188 def delete(self, user_id):
189 user_id = safe_int(user_id)
189 user_id = safe_int(user_id)
190 c.user = User.get_or_404(user_id)
190 c.user = User.get_or_404(user_id)
191
191
192 _repos = c.user.repositories
192 _repos = c.user.repositories
193 _repo_groups = c.user.repository_groups
193 _repo_groups = c.user.repository_groups
194 _user_groups = c.user.user_groups
194 _user_groups = c.user.user_groups
195
195
196 handle_repos = None
196 handle_repos = None
197 handle_repo_groups = None
197 handle_repo_groups = None
198 handle_user_groups = None
198 handle_user_groups = None
199 # dummy call for flash of handle
199 # dummy call for flash of handle
200 set_handle_flash_repos = lambda: None
200 set_handle_flash_repos = lambda: None
201 set_handle_flash_repo_groups = lambda: None
201 set_handle_flash_repo_groups = lambda: None
202 set_handle_flash_user_groups = lambda: None
202 set_handle_flash_user_groups = lambda: None
203
203
204 if _repos and request.POST.get('user_repos'):
204 if _repos and request.POST.get('user_repos'):
205 do = request.POST['user_repos']
205 do = request.POST['user_repos']
206 if do == 'detach':
206 if do == 'detach':
207 handle_repos = 'detach'
207 handle_repos = 'detach'
208 set_handle_flash_repos = lambda: h.flash(
208 set_handle_flash_repos = lambda: h.flash(
209 _('Detached %s repositories') % len(_repos),
209 _('Detached %s repositories') % len(_repos),
210 category='success')
210 category='success')
211 elif do == 'delete':
211 elif do == 'delete':
212 handle_repos = 'delete'
212 handle_repos = 'delete'
213 set_handle_flash_repos = lambda: h.flash(
213 set_handle_flash_repos = lambda: h.flash(
214 _('Deleted %s repositories') % len(_repos),
214 _('Deleted %s repositories') % len(_repos),
215 category='success')
215 category='success')
216
216
217 if _repo_groups and request.POST.get('user_repo_groups'):
217 if _repo_groups and request.POST.get('user_repo_groups'):
218 do = request.POST['user_repo_groups']
218 do = request.POST['user_repo_groups']
219 if do == 'detach':
219 if do == 'detach':
220 handle_repo_groups = 'detach'
220 handle_repo_groups = 'detach'
221 set_handle_flash_repo_groups = lambda: h.flash(
221 set_handle_flash_repo_groups = lambda: h.flash(
222 _('Detached %s repository groups') % len(_repo_groups),
222 _('Detached %s repository groups') % len(_repo_groups),
223 category='success')
223 category='success')
224 elif do == 'delete':
224 elif do == 'delete':
225 handle_repo_groups = 'delete'
225 handle_repo_groups = 'delete'
226 set_handle_flash_repo_groups = lambda: h.flash(
226 set_handle_flash_repo_groups = lambda: h.flash(
227 _('Deleted %s repository groups') % len(_repo_groups),
227 _('Deleted %s repository groups') % len(_repo_groups),
228 category='success')
228 category='success')
229
229
230 if _user_groups and request.POST.get('user_user_groups'):
230 if _user_groups and request.POST.get('user_user_groups'):
231 do = request.POST['user_user_groups']
231 do = request.POST['user_user_groups']
232 if do == 'detach':
232 if do == 'detach':
233 handle_user_groups = 'detach'
233 handle_user_groups = 'detach'
234 set_handle_flash_user_groups = lambda: h.flash(
234 set_handle_flash_user_groups = lambda: h.flash(
235 _('Detached %s user groups') % len(_user_groups),
235 _('Detached %s user groups') % len(_user_groups),
236 category='success')
236 category='success')
237 elif do == 'delete':
237 elif do == 'delete':
238 handle_user_groups = 'delete'
238 handle_user_groups = 'delete'
239 set_handle_flash_user_groups = lambda: h.flash(
239 set_handle_flash_user_groups = lambda: h.flash(
240 _('Deleted %s user groups') % len(_user_groups),
240 _('Deleted %s user groups') % len(_user_groups),
241 category='success')
241 category='success')
242
242
243 old_values = c.user.get_api_data()
243 old_values = c.user.get_api_data()
244 try:
244 try:
245 UserModel().delete(c.user, handle_repos=handle_repos,
245 UserModel().delete(c.user, handle_repos=handle_repos,
246 handle_repo_groups=handle_repo_groups,
246 handle_repo_groups=handle_repo_groups,
247 handle_user_groups=handle_user_groups)
247 handle_user_groups=handle_user_groups)
248
248
249 audit_logger.store_web(
249 audit_logger.store_web(
250 'user.delete', action_data={'old_data': old_values},
250 'user.delete', action_data={'old_data': old_values},
251 user=c.rhodecode_user)
251 user=c.rhodecode_user)
252
252
253 Session().commit()
253 Session().commit()
254 set_handle_flash_repos()
254 set_handle_flash_repos()
255 set_handle_flash_repo_groups()
255 set_handle_flash_repo_groups()
256 set_handle_flash_user_groups()
256 set_handle_flash_user_groups()
257 h.flash(_('Successfully deleted user'), category='success')
257 h.flash(_('Successfully deleted user'), category='success')
258 except (UserOwnsReposException, UserOwnsRepoGroupsException,
258 except (UserOwnsReposException, UserOwnsRepoGroupsException,
259 UserOwnsUserGroupsException, DefaultUserException) as e:
259 UserOwnsUserGroupsException, DefaultUserException) as e:
260 h.flash(e, category='warning')
260 h.flash(e, category='warning')
261 except Exception:
261 except Exception:
262 log.exception("Exception during deletion of user")
262 log.exception("Exception during deletion of user")
263 h.flash(_('An error occurred during deletion of user'),
263 h.flash(_('An error occurred during deletion of user'),
264 category='error')
264 category='error')
265 return redirect(h.route_path('users'))
265 return redirect(h.route_path('users'))
266
266
267 @HasPermissionAllDecorator('hg.admin')
267 @HasPermissionAllDecorator('hg.admin')
268 @auth.CSRFRequired()
268 @auth.CSRFRequired()
269 def reset_password(self, user_id):
269 def reset_password(self, user_id):
270 """
270 """
271 toggle reset password flag for this user
271 toggle reset password flag for this user
272 """
272 """
273 user_id = safe_int(user_id)
273 user_id = safe_int(user_id)
274 c.user = User.get_or_404(user_id)
274 c.user = User.get_or_404(user_id)
275 try:
275 try:
276 old_value = c.user.user_data.get('force_password_change')
276 old_value = c.user.user_data.get('force_password_change')
277 c.user.update_userdata(force_password_change=not old_value)
277 c.user.update_userdata(force_password_change=not old_value)
278
278
279 if old_value:
279 if old_value:
280 msg = _('Force password change disabled for user')
280 msg = _('Force password change disabled for user')
281 audit_logger.store_web(
281 audit_logger.store_web(
282 'user.edit.password_reset.disabled',
282 'user.edit.password_reset.disabled',
283 user=c.rhodecode_user)
283 user=c.rhodecode_user)
284 else:
284 else:
285 msg = _('Force password change enabled for user')
285 msg = _('Force password change enabled for user')
286 audit_logger.store_web(
286 audit_logger.store_web(
287 'user.edit.password_reset.enabled',
287 'user.edit.password_reset.enabled',
288 user=c.rhodecode_user)
288 user=c.rhodecode_user)
289
289
290 Session().commit()
290 Session().commit()
291 h.flash(msg, category='success')
291 h.flash(msg, category='success')
292 except Exception:
292 except Exception:
293 log.exception("Exception during password reset for user")
293 log.exception("Exception during password reset for user")
294 h.flash(_('An error occurred during password reset for user'),
294 h.flash(_('An error occurred during password reset for user'),
295 category='error')
295 category='error')
296
296
297 return redirect(url('edit_user_advanced', user_id=user_id))
297 return redirect(url('edit_user_advanced', user_id=user_id))
298
298
299 @HasPermissionAllDecorator('hg.admin')
299 @HasPermissionAllDecorator('hg.admin')
300 @auth.CSRFRequired()
300 @auth.CSRFRequired()
301 def create_personal_repo_group(self, user_id):
301 def create_personal_repo_group(self, user_id):
302 """
302 """
303 Create personal repository group for this user
303 Create personal repository group for this user
304 """
304 """
305 from rhodecode.model.repo_group import RepoGroupModel
305 from rhodecode.model.repo_group import RepoGroupModel
306
306
307 user_id = safe_int(user_id)
307 user_id = safe_int(user_id)
308 c.user = User.get_or_404(user_id)
308 c.user = User.get_or_404(user_id)
309 personal_repo_group = RepoGroup.get_user_personal_repo_group(
309 personal_repo_group = RepoGroup.get_user_personal_repo_group(
310 c.user.user_id)
310 c.user.user_id)
311 if personal_repo_group:
311 if personal_repo_group:
312 return redirect(url('edit_user_advanced', user_id=user_id))
312 return redirect(url('edit_user_advanced', user_id=user_id))
313
313
314 personal_repo_group_name = RepoGroupModel().get_personal_group_name(
314 personal_repo_group_name = RepoGroupModel().get_personal_group_name(
315 c.user)
315 c.user)
316 named_personal_group = RepoGroup.get_by_group_name(
316 named_personal_group = RepoGroup.get_by_group_name(
317 personal_repo_group_name)
317 personal_repo_group_name)
318 try:
318 try:
319
319
320 if named_personal_group and named_personal_group.user_id == c.user.user_id:
320 if named_personal_group and named_personal_group.user_id == c.user.user_id:
321 # migrate the same named group, and mark it as personal
321 # migrate the same named group, and mark it as personal
322 named_personal_group.personal = True
322 named_personal_group.personal = True
323 Session().add(named_personal_group)
323 Session().add(named_personal_group)
324 Session().commit()
324 Session().commit()
325 msg = _('Linked repository group `%s` as personal' % (
325 msg = _('Linked repository group `%s` as personal' % (
326 personal_repo_group_name,))
326 personal_repo_group_name,))
327 h.flash(msg, category='success')
327 h.flash(msg, category='success')
328 elif not named_personal_group:
328 elif not named_personal_group:
329 RepoGroupModel().create_personal_repo_group(c.user)
329 RepoGroupModel().create_personal_repo_group(c.user)
330
330
331 msg = _('Created repository group `%s`' % (
331 msg = _('Created repository group `%s`' % (
332 personal_repo_group_name,))
332 personal_repo_group_name,))
333 h.flash(msg, category='success')
333 h.flash(msg, category='success')
334 else:
334 else:
335 msg = _('Repository group `%s` is already taken' % (
335 msg = _('Repository group `%s` is already taken' % (
336 personal_repo_group_name,))
336 personal_repo_group_name,))
337 h.flash(msg, category='warning')
337 h.flash(msg, category='warning')
338 except Exception:
338 except Exception:
339 log.exception("Exception during repository group creation")
339 log.exception("Exception during repository group creation")
340 msg = _(
340 msg = _(
341 'An error occurred during repository group creation for user')
341 'An error occurred during repository group creation for user')
342 h.flash(msg, category='error')
342 h.flash(msg, category='error')
343 Session().rollback()
343 Session().rollback()
344
344
345 return redirect(url('edit_user_advanced', user_id=user_id))
345 return redirect(url('edit_user_advanced', user_id=user_id))
346
346
347 @HasPermissionAllDecorator('hg.admin')
347 @HasPermissionAllDecorator('hg.admin')
348 def show(self, user_id):
348 def show(self, user_id):
349 """GET /users/user_id: Show a specific item"""
349 """GET /users/user_id: Show a specific item"""
350 # url('user', user_id=ID)
350 # url('user', user_id=ID)
351 User.get_or_404(-1)
351 User.get_or_404(-1)
352
352
353 @HasPermissionAllDecorator('hg.admin')
353 @HasPermissionAllDecorator('hg.admin')
354 def edit(self, user_id):
354 def edit(self, user_id):
355 """GET /users/user_id/edit: Form to edit an existing item"""
355 """GET /users/user_id/edit: Form to edit an existing item"""
356 # url('edit_user', user_id=ID)
356 # url('edit_user', user_id=ID)
357 user_id = safe_int(user_id)
357 user_id = safe_int(user_id)
358 c.user = User.get_or_404(user_id)
358 c.user = User.get_or_404(user_id)
359 if c.user.username == User.DEFAULT_USER:
359 if c.user.username == User.DEFAULT_USER:
360 h.flash(_("You can't edit this user"), category='warning')
360 h.flash(_("You can't edit this user"), category='warning')
361 return redirect(h.route_path('users'))
361 return redirect(h.route_path('users'))
362
362
363 c.active = 'profile'
363 c.active = 'profile'
364 c.extern_type = c.user.extern_type
364 c.extern_type = c.user.extern_type
365 c.extern_name = c.user.extern_name
365 c.extern_name = c.user.extern_name
366 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
366 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
367
367
368 defaults = c.user.get_dict()
368 defaults = c.user.get_dict()
369 defaults.update({'language': c.user.user_data.get('language')})
369 defaults.update({'language': c.user.user_data.get('language')})
370 return htmlfill.render(
370 return htmlfill.render(
371 render('admin/users/user_edit.mako'),
371 render('admin/users/user_edit.mako'),
372 defaults=defaults,
372 defaults=defaults,
373 encoding="UTF-8",
373 encoding="UTF-8",
374 force_defaults=False)
374 force_defaults=False)
375
375
376 @HasPermissionAllDecorator('hg.admin')
376 @HasPermissionAllDecorator('hg.admin')
377 def edit_advanced(self, user_id):
377 def edit_advanced(self, user_id):
378 user_id = safe_int(user_id)
378 user_id = safe_int(user_id)
379 user = c.user = User.get_or_404(user_id)
379 user = c.user = User.get_or_404(user_id)
380 if user.username == User.DEFAULT_USER:
380 if user.username == User.DEFAULT_USER:
381 h.flash(_("You can't edit this user"), category='warning')
381 h.flash(_("You can't edit this user"), category='warning')
382 return redirect(h.route_path('users'))
382 return redirect(h.route_path('users'))
383
383
384 c.active = 'advanced'
384 c.active = 'advanced'
385 c.personal_repo_group = RepoGroup.get_user_personal_repo_group(user_id)
385 c.personal_repo_group = RepoGroup.get_user_personal_repo_group(user_id)
386 c.personal_repo_group_name = RepoGroupModel()\
386 c.personal_repo_group_name = RepoGroupModel()\
387 .get_personal_group_name(user)
387 .get_personal_group_name(user)
388
389 c.user_to_review_rules = sorted(
390 (x.user for x in c.user.user_review_rules),
391 key=lambda u: u.username.lower())
392
388 c.first_admin = User.get_first_super_admin()
393 c.first_admin = User.get_first_super_admin()
389 defaults = user.get_dict()
394 defaults = user.get_dict()
390
395
391 # Interim workaround if the user participated on any pull requests as a
396 # Interim workaround if the user participated on any pull requests as a
392 # reviewer.
397 # reviewer.
393 has_review = len(user.reviewer_pull_requests)
398 has_review = len(user.reviewer_pull_requests)
394 c.can_delete_user = not has_review
399 c.can_delete_user = not has_review
395 c.can_delete_user_message = ''
400 c.can_delete_user_message = ''
396 inactive_link = h.link_to(
401 inactive_link = h.link_to(
397 'inactive', h.url('edit_user', user_id=user_id, anchor='active'))
402 'inactive', h.url('edit_user', user_id=user_id, anchor='active'))
398 if has_review == 1:
403 if has_review == 1:
399 c.can_delete_user_message = h.literal(_(
404 c.can_delete_user_message = h.literal(_(
400 'The user participates as reviewer in {} pull request and '
405 'The user participates as reviewer in {} pull request and '
401 'cannot be deleted. \nYou can set the user to '
406 'cannot be deleted. \nYou can set the user to '
402 '"{}" instead of deleting it.').format(
407 '"{}" instead of deleting it.').format(
403 has_review, inactive_link))
408 has_review, inactive_link))
404 elif has_review:
409 elif has_review:
405 c.can_delete_user_message = h.literal(_(
410 c.can_delete_user_message = h.literal(_(
406 'The user participates as reviewer in {} pull requests and '
411 'The user participates as reviewer in {} pull requests and '
407 'cannot be deleted. \nYou can set the user to '
412 'cannot be deleted. \nYou can set the user to '
408 '"{}" instead of deleting it.').format(
413 '"{}" instead of deleting it.').format(
409 has_review, inactive_link))
414 has_review, inactive_link))
410
415
411 return htmlfill.render(
416 return htmlfill.render(
412 render('admin/users/user_edit.mako'),
417 render('admin/users/user_edit.mako'),
413 defaults=defaults,
418 defaults=defaults,
414 encoding="UTF-8",
419 encoding="UTF-8",
415 force_defaults=False)
420 force_defaults=False)
416
421
417 @HasPermissionAllDecorator('hg.admin')
422 @HasPermissionAllDecorator('hg.admin')
418 def edit_global_perms(self, user_id):
423 def edit_global_perms(self, user_id):
419 user_id = safe_int(user_id)
424 user_id = safe_int(user_id)
420 c.user = User.get_or_404(user_id)
425 c.user = User.get_or_404(user_id)
421 if c.user.username == User.DEFAULT_USER:
426 if c.user.username == User.DEFAULT_USER:
422 h.flash(_("You can't edit this user"), category='warning')
427 h.flash(_("You can't edit this user"), category='warning')
423 return redirect(h.route_path('users'))
428 return redirect(h.route_path('users'))
424
429
425 c.active = 'global_perms'
430 c.active = 'global_perms'
426
431
427 c.default_user = User.get_default_user()
432 c.default_user = User.get_default_user()
428 defaults = c.user.get_dict()
433 defaults = c.user.get_dict()
429 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
434 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
430 defaults.update(c.default_user.get_default_perms())
435 defaults.update(c.default_user.get_default_perms())
431 defaults.update(c.user.get_default_perms())
436 defaults.update(c.user.get_default_perms())
432
437
433 return htmlfill.render(
438 return htmlfill.render(
434 render('admin/users/user_edit.mako'),
439 render('admin/users/user_edit.mako'),
435 defaults=defaults,
440 defaults=defaults,
436 encoding="UTF-8",
441 encoding="UTF-8",
437 force_defaults=False)
442 force_defaults=False)
438
443
439 @HasPermissionAllDecorator('hg.admin')
444 @HasPermissionAllDecorator('hg.admin')
440 @auth.CSRFRequired()
445 @auth.CSRFRequired()
441 def update_global_perms(self, user_id):
446 def update_global_perms(self, user_id):
442 user_id = safe_int(user_id)
447 user_id = safe_int(user_id)
443 user = User.get_or_404(user_id)
448 user = User.get_or_404(user_id)
444 c.active = 'global_perms'
449 c.active = 'global_perms'
445 try:
450 try:
446 # first stage that verifies the checkbox
451 # first stage that verifies the checkbox
447 _form = UserIndividualPermissionsForm()
452 _form = UserIndividualPermissionsForm()
448 form_result = _form.to_python(dict(request.POST))
453 form_result = _form.to_python(dict(request.POST))
449 inherit_perms = form_result['inherit_default_permissions']
454 inherit_perms = form_result['inherit_default_permissions']
450 user.inherit_default_permissions = inherit_perms
455 user.inherit_default_permissions = inherit_perms
451 Session().add(user)
456 Session().add(user)
452
457
453 if not inherit_perms:
458 if not inherit_perms:
454 # only update the individual ones if we un check the flag
459 # only update the individual ones if we un check the flag
455 _form = UserPermissionsForm(
460 _form = UserPermissionsForm(
456 [x[0] for x in c.repo_create_choices],
461 [x[0] for x in c.repo_create_choices],
457 [x[0] for x in c.repo_create_on_write_choices],
462 [x[0] for x in c.repo_create_on_write_choices],
458 [x[0] for x in c.repo_group_create_choices],
463 [x[0] for x in c.repo_group_create_choices],
459 [x[0] for x in c.user_group_create_choices],
464 [x[0] for x in c.user_group_create_choices],
460 [x[0] for x in c.fork_choices],
465 [x[0] for x in c.fork_choices],
461 [x[0] for x in c.inherit_default_permission_choices])()
466 [x[0] for x in c.inherit_default_permission_choices])()
462
467
463 form_result = _form.to_python(dict(request.POST))
468 form_result = _form.to_python(dict(request.POST))
464 form_result.update({'perm_user_id': user.user_id})
469 form_result.update({'perm_user_id': user.user_id})
465
470
466 PermissionModel().update_user_permissions(form_result)
471 PermissionModel().update_user_permissions(form_result)
467
472
468 # TODO(marcink): implement global permissions
473 # TODO(marcink): implement global permissions
469 # audit_log.store_web('user.edit.permissions')
474 # audit_log.store_web('user.edit.permissions')
470
475
471 Session().commit()
476 Session().commit()
472 h.flash(_('User global permissions updated successfully'),
477 h.flash(_('User global permissions updated successfully'),
473 category='success')
478 category='success')
474
479
475 except formencode.Invalid as errors:
480 except formencode.Invalid as errors:
476 defaults = errors.value
481 defaults = errors.value
477 c.user = user
482 c.user = user
478 return htmlfill.render(
483 return htmlfill.render(
479 render('admin/users/user_edit.mako'),
484 render('admin/users/user_edit.mako'),
480 defaults=defaults,
485 defaults=defaults,
481 errors=errors.error_dict or {},
486 errors=errors.error_dict or {},
482 prefix_error=False,
487 prefix_error=False,
483 encoding="UTF-8",
488 encoding="UTF-8",
484 force_defaults=False)
489 force_defaults=False)
485 except Exception:
490 except Exception:
486 log.exception("Exception during permissions saving")
491 log.exception("Exception during permissions saving")
487 h.flash(_('An error occurred during permissions saving'),
492 h.flash(_('An error occurred during permissions saving'),
488 category='error')
493 category='error')
489 return redirect(url('edit_user_global_perms', user_id=user_id))
494 return redirect(url('edit_user_global_perms', user_id=user_id))
490
495
491
496
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,83 +1,84 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 (_('Owner'), lambda:base.gravatar_with_user(c.user_group.user.email), '', ''),
5 (_('Owner'), lambda:base.gravatar_with_user(c.user_group.user.email), '', ''),
6 (_('Created on'), h.format_date(c.user_group.created_on), '', '',),
6 (_('Created on'), h.format_date(c.user_group.created_on), '', '',),
7
7
8 (_('Members'), len(c.group_members_obj),'', [x for x in c.group_members_obj]),
8 (_('Members'), len(c.group_members_obj),'', [x for x in c.group_members_obj]),
9 (_('Automatic member sync'), 'Yes' if c.user_group.group_data.get('extern_type') else 'No', '', '',),
9 (_('Automatic member sync'), 'Yes' if c.user_group.group_data.get('extern_type') else 'No', '', '',),
10
10
11 (_('Assigned to repositories'), len(c.group_to_repos),'', [x for x in c.group_to_repos]),
11 (_('Assigned to repositories'), len(c.group_to_repos),'', [x for x in c.group_to_repos]),
12 (_('Assigned to repo groups'), len(c.group_to_repo_groups), '', [x for x in c.group_to_repo_groups]),
12 (_('Assigned to repo groups'), len(c.group_to_repo_groups), '', [x for x in c.group_to_repo_groups]),
13
13
14 (_('Assigned to review rules'), len(c.group_to_review_rules), '', [x for x in c.group_to_review_rules]),
14 ]
15 ]
15 %>
16 %>
16
17
17 <div class="panel panel-default">
18 <div class="panel panel-default">
18 <div class="panel-heading">
19 <div class="panel-heading">
19 <h3 class="panel-title">${_('User Group: %s') % c.user_group.users_group_name}</h3>
20 <h3 class="panel-title">${_('User Group: %s') % c.user_group.users_group_name}</h3>
20 </div>
21 </div>
21 <div class="panel-body">
22 <div class="panel-body">
22 ${base.dt_info_panel(elems)}
23 ${base.dt_info_panel(elems)}
23 </div>
24 </div>
24
25
25 </div>
26 </div>
26
27
27 <div class="panel panel-default">
28 <div class="panel panel-default">
28 <div class="panel-heading">
29 <div class="panel-heading">
29 <h3 class="panel-title">${_('Group members sync')}</h3>
30 <h3 class="panel-title">${_('Group members sync')}</h3>
30 </div>
31 </div>
31 <div class="panel-body">
32 <div class="panel-body">
32 <% sync_type = c.user_group.group_data.get('extern_type') %>
33 <% sync_type = c.user_group.group_data.get('extern_type') %>
33
34
34 % if sync_type:
35 % if sync_type:
35 <p>
36 <p>
36 ${_('This group is set to be automatically synchronised.')}<br/>
37 ${_('This group is set to be automatically synchronised.')}<br/>
37 ${_('This group synchronization was set by')}: <strong>${sync_type}</strong>
38 ${_('This group synchronization was set by')}: <strong>${sync_type}</strong>
38 </p>
39 </p>
39 % else:
40 % else:
40 <p>
41 <p>
41 ${_('This group is not set to be automatically synchronised')}
42 ${_('This group is not set to be automatically synchronised')}
42 </p>
43 </p>
43 % endif
44 % endif
44
45
45 <div>
46 <div>
46 ${h.secure_form(h.url('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='post')}
47 ${h.secure_form(h.url('edit_user_group_advanced_sync', user_group_id=c.user_group.users_group_id), method='post')}
47 <div class="field">
48 <div class="field">
48 <button class="btn btn-default" type="submit">
49 <button class="btn btn-default" type="submit">
49 %if sync_type:
50 %if sync_type:
50 ${_('Disable synchronization')}
51 ${_('Disable synchronization')}
51 %else:
52 %else:
52 ${_('Enable synchronization')}
53 ${_('Enable synchronization')}
53 %endif
54 %endif
54 </button>
55 </button>
55 </div>
56 </div>
56 <div class="field">
57 <div class="field">
57 <span class="help-block">
58 <span class="help-block">
58 ${_('Users will be added or removed from this group when they authenticate with RhodeCode system, based on LDAP group membership. '
59 ${_('Users will be added or removed from this group when they authenticate with RhodeCode system, based on LDAP group membership. '
59 'This requires `LDAP+User group` authentication plugin to be configured and enabled. (EE only feature)')}
60 'This requires `LDAP+User group` authentication plugin to be configured and enabled. (EE only feature)')}
60 </span>
61 </span>
61 </div>
62 </div>
62 ${h.end_form()}
63 ${h.end_form()}
63 </div>
64 </div>
64
65
65 </div>
66 </div>
66 </div>
67 </div>
67
68
68
69
69 <div class="panel panel-danger">
70 <div class="panel panel-danger">
70 <div class="panel-heading">
71 <div class="panel-heading">
71 <h3 class="panel-title">${_('Delete User Group')}</h3>
72 <h3 class="panel-title">${_('Delete User Group')}</h3>
72 </div>
73 </div>
73 <div class="panel-body">
74 <div class="panel-body">
74 ${h.secure_form(h.url('delete_users_group', user_group_id=c.user_group.users_group_id),method='delete')}
75 ${h.secure_form(h.url('delete_users_group', user_group_id=c.user_group.users_group_id),method='delete')}
75 ${h.hidden('force', 1)}
76 ${h.hidden('force', 1)}
76 <button class="btn btn-small btn-danger" type="submit"
77 <button class="btn btn-small btn-danger" type="submit"
77 onclick="return confirm('${_('Confirm to delete user group `%(ugroup)s` with all permission assignments') % {'ugroup': c.user_group.users_group_name}}');">
78 onclick="return confirm('${_('Confirm to delete user group `%(ugroup)s` with all permission assignments') % {'ugroup': c.user_group.users_group_name}}');">
78 <i class="icon-remove-sign"></i>
79 <i class="icon-remove-sign"></i>
79 ${_('Delete This User Group')}
80 ${_('Delete This User Group')}
80 </button>
81 </button>
81 ${h.end_form()}
82 ${h.end_form()}
82 </div>
83 </div>
83 </div>
84 </div>
@@ -1,159 +1,161 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'), c.user.last_activity, '', ''),
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 (_('Reviewer of pull requests'), len(c.user.reviewer_pull_requests), '', ['Pull Request #{}'.format(x.pull_request.pull_request_id) for x in c.user.reviewer_pull_requests]),
15 (_('Reviewer of pull requests'), len(c.user.reviewer_pull_requests), '', ['Pull Request #{}'.format(x.pull_request.pull_request_id) for x in c.user.reviewer_pull_requests]),
16 (_('Assigned to review rules'), len(c.user_to_review_rules), '', [x for x in c.user_to_review_rules]),
17
16 (_('Member of User groups'), len(c.user.group_member), '', [x.users_group.users_group_name for x in c.user.group_member]),
18 (_('Member of User groups'), len(c.user.group_member), '', [x.users_group.users_group_name for x in c.user.group_member]),
17 (_('Force password change'), c.user.user_data.get('force_password_change', 'False'), '', ''),
19 (_('Force password change'), c.user.user_data.get('force_password_change', 'False'), '', ''),
18 ]
20 ]
19 %>
21 %>
20
22
21 <div class="panel panel-default">
23 <div class="panel panel-default">
22 <div class="panel-heading">
24 <div class="panel-heading">
23 <h3 class="panel-title">${_('User: %s') % c.user.username}</h3>
25 <h3 class="panel-title">${_('User: %s') % c.user.username}</h3>
24 </div>
26 </div>
25 <div class="panel-body">
27 <div class="panel-body">
26 ${base.dt_info_panel(elems)}
28 ${base.dt_info_panel(elems)}
27 </div>
29 </div>
28 </div>
30 </div>
29
31
30 <div class="panel panel-default">
32 <div class="panel panel-default">
31 <div class="panel-heading">
33 <div class="panel-heading">
32 <h3 class="panel-title">${_('Force Password Reset')}</h3>
34 <h3 class="panel-title">${_('Force Password Reset')}</h3>
33 </div>
35 </div>
34 <div class="panel-body">
36 <div class="panel-body">
35 ${h.secure_form(h.url('force_password_reset_user', user_id=c.user.user_id), method='post')}
37 ${h.secure_form(h.url('force_password_reset_user', user_id=c.user.user_id), method='post')}
36 <div class="field">
38 <div class="field">
37 <button class="btn btn-default" type="submit">
39 <button class="btn btn-default" type="submit">
38 <i class="icon-lock"></i>
40 <i class="icon-lock"></i>
39 %if c.user.user_data.get('force_password_change'):
41 %if c.user.user_data.get('force_password_change'):
40 ${_('Disable forced password reset')}
42 ${_('Disable forced password reset')}
41 %else:
43 %else:
42 ${_('Enable forced password reset')}
44 ${_('Enable forced password reset')}
43 %endif
45 %endif
44 </button>
46 </button>
45 </div>
47 </div>
46 <div class="field">
48 <div class="field">
47 <span class="help-block">
49 <span class="help-block">
48 ${_("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")}
50 ${_("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")}
49 </span>
51 </span>
50 </div>
52 </div>
51 ${h.end_form()}
53 ${h.end_form()}
52 </div>
54 </div>
53 </div>
55 </div>
54
56
55 <div class="panel panel-default">
57 <div class="panel panel-default">
56 <div class="panel-heading">
58 <div class="panel-heading">
57 <h3 class="panel-title">${_('Personal Repository Group')}</h3>
59 <h3 class="panel-title">${_('Personal Repository Group')}</h3>
58 </div>
60 </div>
59 <div class="panel-body">
61 <div class="panel-body">
60 ${h.secure_form(h.url('create_personal_repo_group', user_id=c.user.user_id), method='post')}
62 ${h.secure_form(h.url('create_personal_repo_group', user_id=c.user.user_id), method='post')}
61
63
62 %if c.personal_repo_group:
64 %if c.personal_repo_group:
63 <div class="panel-body-title-text">${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, h.route_path('repo_group_home', repo_group_name=c.personal_repo_group.group_name))}</div>
65 <div class="panel-body-title-text">${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, h.route_path('repo_group_home', repo_group_name=c.personal_repo_group.group_name))}</div>
64 %else:
66 %else:
65 <div class="panel-body-title-text">
67 <div class="panel-body-title-text">
66 ${_('This user currently does not have a personal repository group')}
68 ${_('This user currently does not have a personal repository group')}
67 <br/>
69 <br/>
68 ${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}
70 ${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}
69 </div>
71 </div>
70 %endif
72 %endif
71 <button class="btn btn-default" type="submit" ${'disabled="disabled"' if c.personal_repo_group else ''}>
73 <button class="btn btn-default" type="submit" ${'disabled="disabled"' if c.personal_repo_group else ''}>
72 <i class="icon-folder-close"></i>
74 <i class="icon-folder-close"></i>
73 ${_('Create personal repository group')}
75 ${_('Create personal repository group')}
74 </button>
76 </button>
75 ${h.end_form()}
77 ${h.end_form()}
76 </div>
78 </div>
77 </div>
79 </div>
78
80
79
81
80 <div class="panel panel-danger">
82 <div class="panel panel-danger">
81 <div class="panel-heading">
83 <div class="panel-heading">
82 <h3 class="panel-title">${_('Delete User')}</h3>
84 <h3 class="panel-title">${_('Delete User')}</h3>
83 </div>
85 </div>
84 <div class="panel-body">
86 <div class="panel-body">
85 ${h.secure_form(h.url('delete_user', user_id=c.user.user_id), method='delete')}
87 ${h.secure_form(h.url('delete_user', user_id=c.user.user_id), method='delete')}
86
88
87 <table class="display">
89 <table class="display">
88 <tr>
90 <tr>
89 <td>
91 <td>
90 ${_ungettext('This user owns %s repository.', 'This user owns %s repositories.', len(c.user.repositories)) % len(c.user.repositories)}
92 ${_ungettext('This user owns %s repository.', 'This user owns %s repositories.', len(c.user.repositories)) % len(c.user.repositories)}
91 </td>
93 </td>
92 <td>
94 <td>
93 %if len(c.user.repositories) > 0:
95 %if len(c.user.repositories) > 0:
94 <input type="radio" id="user_repos_1" name="user_repos" value="detach" checked="checked"/> <label for="user_repos_1">${_('Detach repositories')}</label>
96 <input type="radio" id="user_repos_1" name="user_repos" value="detach" checked="checked"/> <label for="user_repos_1">${_('Detach repositories')}</label>
95 %endif
97 %endif
96 </td>
98 </td>
97 <td>
99 <td>
98 %if len(c.user.repositories) > 0:
100 %if len(c.user.repositories) > 0:
99 <input type="radio" id="user_repos_2" name="user_repos" value="delete" /> <label for="user_repos_2">${_('Delete repositories')}</label>
101 <input type="radio" id="user_repos_2" name="user_repos" value="delete" /> <label for="user_repos_2">${_('Delete repositories')}</label>
100 %endif
102 %endif
101 </td>
103 </td>
102 </tr>
104 </tr>
103
105
104 <tr>
106 <tr>
105 <td>
107 <td>
106 ${_ungettext('This user owns %s repository group.', 'This user owns %s repository groups.', len(c.user.repository_groups)) % len(c.user.repository_groups)}
108 ${_ungettext('This user owns %s repository group.', 'This user owns %s repository groups.', len(c.user.repository_groups)) % len(c.user.repository_groups)}
107 </td>
109 </td>
108 <td>
110 <td>
109 %if len(c.user.repository_groups) > 0:
111 %if len(c.user.repository_groups) > 0:
110 <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>
112 <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>
111 %endif
113 %endif
112 </td>
114 </td>
113 <td>
115 <td>
114 %if len(c.user.repository_groups) > 0:
116 %if len(c.user.repository_groups) > 0:
115 <input type="radio" id="user_repo_groups_2" name="user_repo_groups" value="delete" /> <label for="user_repo_groups_2">${_('Delete repositories')}</label>
117 <input type="radio" id="user_repo_groups_2" name="user_repo_groups" value="delete" /> <label for="user_repo_groups_2">${_('Delete repositories')}</label>
116 %endif
118 %endif
117 </td>
119 </td>
118 </tr>
120 </tr>
119
121
120 <tr>
122 <tr>
121 <td>
123 <td>
122 ${_ungettext('This user owns %s user group.', 'This user owns %s user groups.', len(c.user.user_groups)) % len(c.user.user_groups)}
124 ${_ungettext('This user owns %s user group.', 'This user owns %s user groups.', len(c.user.user_groups)) % len(c.user.user_groups)}
123 </td>
125 </td>
124 <td>
126 <td>
125 %if len(c.user.user_groups) > 0:
127 %if len(c.user.user_groups) > 0:
126 <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>
128 <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>
127 %endif
129 %endif
128 </td>
130 </td>
129 <td>
131 <td>
130 %if len(c.user.user_groups) > 0:
132 %if len(c.user.user_groups) > 0:
131 <input type="radio" id="user_user_groups_2" name="user_user_groups" value="delete" /> <label for="user_user_groups_2">${_('Delete repositories')}</label>
133 <input type="radio" id="user_user_groups_2" name="user_user_groups" value="delete" /> <label for="user_user_groups_2">${_('Delete repositories')}</label>
132 %endif
134 %endif
133 </td>
135 </td>
134 </tr>
136 </tr>
135 </table>
137 </table>
136 <div style="margin: 0 0 20px 0" class="fake-space"></div>
138 <div style="margin: 0 0 20px 0" class="fake-space"></div>
137
139
138 <div class="field">
140 <div class="field">
139 <button class="btn btn-small btn-danger" type="submit"
141 <button class="btn btn-small btn-danger" type="submit"
140 onclick="return confirm('${_('Confirm to delete this user: %s') % c.user.username}');"
142 onclick="return confirm('${_('Confirm to delete this user: %s') % c.user.username}');"
141 ${"disabled" if not c.can_delete_user else ""}>
143 ${"disabled" if not c.can_delete_user else ""}>
142 ${_('Delete this user')}
144 ${_('Delete this user')}
143 </button>
145 </button>
144 </div>
146 </div>
145 % if c.can_delete_user_message:
147 % if c.can_delete_user_message:
146 <p class="help-block pre-formatting">${c.can_delete_user_message}</p>
148 <p class="help-block pre-formatting">${c.can_delete_user_message}</p>
147 % endif
149 % endif
148
150
149 <div class="field">
151 <div class="field">
150 <span class="help-block">
152 <span class="help-block">
151 %if len(c.user.repositories) > 0 or len(c.user.repository_groups) > 0 or len(c.user.user_groups) > 0:
153 %if len(c.user.repositories) > 0 or len(c.user.repository_groups) > 0 or len(c.user.user_groups) > 0:
152 <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>
154 <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>
153 %endif
155 %endif
154 </span>
156 </span>
155 </div>
157 </div>
156
158
157 ${h.end_form()}
159 ${h.end_form()}
158 </div>
160 </div>
159 </div>
161 </div>
General Comments 0
You need to be logged in to leave comments. Login now