##// END OF EJS Templates
i18n: expose custom name to catch the translation strings.
marcink -
r1098:5d0049e7 default
parent child Browse files
Show More
@@ -1,249 +1,249 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 """
23 23 permissions controller for RhodeCode Enterprise
24 24 """
25 25
26 26
27 27 import logging
28 28
29 29 import formencode
30 30 from formencode import htmlfill
31 31 from pylons import request, tmpl_context as c, url
32 32 from pylons.controllers.util import redirect
33 33 from pylons.i18n.translation import _
34 34
35 35 from rhodecode.lib import helpers as h
36 36 from rhodecode.lib import auth
37 37 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
38 38 from rhodecode.lib.base import BaseController, render
39 39 from rhodecode.model.db import User, UserIpMap
40 40 from rhodecode.model.forms import (
41 41 ApplicationPermissionsForm, ObjectPermissionsForm, UserPermissionsForm)
42 42 from rhodecode.model.meta import Session
43 43 from rhodecode.model.permission import PermissionModel
44 44 from rhodecode.model.settings import SettingsModel
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48
49 49 class PermissionsController(BaseController):
50 50 """REST Controller styled on the Atom Publishing Protocol"""
51 51 # To properly map this controller, ensure your config/routing.py
52 52 # file has a resource setup:
53 53 # map.resource('permission', 'permissions')
54 54
55 55 @LoginRequired()
56 56 def __before__(self):
57 57 super(PermissionsController, self).__before__()
58 58
59 59 def __load_data(self):
60 PermissionModel().set_global_permission_choices(c, translator=_)
60 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
61 61
62 62 @HasPermissionAllDecorator('hg.admin')
63 63 def permission_application(self):
64 64 c.active = 'application'
65 65 self.__load_data()
66 66
67 67 c.user = User.get_default_user()
68 68
69 69 # TODO: johbo: The default user might be based on outdated state which
70 70 # has been loaded from the cache. A call to refresh() ensures that the
71 71 # latest state from the database is used.
72 72 Session().refresh(c.user)
73 73
74 74 app_settings = SettingsModel().get_all_settings()
75 75 defaults = {
76 76 'anonymous': c.user.active,
77 77 'default_register_message': app_settings.get(
78 78 'rhodecode_register_message')
79 79 }
80 80 defaults.update(c.user.get_default_perms())
81 81
82 82 return htmlfill.render(
83 83 render('admin/permissions/permissions.html'),
84 84 defaults=defaults,
85 85 encoding="UTF-8",
86 86 force_defaults=False)
87 87
88 88 @HasPermissionAllDecorator('hg.admin')
89 89 @auth.CSRFRequired()
90 90 def permission_application_update(self):
91 91 c.active = 'application'
92 92 self.__load_data()
93 93 _form = ApplicationPermissionsForm(
94 94 [x[0] for x in c.register_choices],
95 95 [x[0] for x in c.password_reset_choices],
96 96 [x[0] for x in c.extern_activate_choices])()
97 97
98 98 try:
99 99 form_result = _form.to_python(dict(request.POST))
100 100 form_result.update({'perm_user_name': User.DEFAULT_USER})
101 101 PermissionModel().update_application_permissions(form_result)
102 102
103 103 settings = [
104 104 ('register_message', 'default_register_message'),
105 105 ]
106 106 for setting, form_key in settings:
107 107 sett = SettingsModel().create_or_update_setting(
108 108 setting, form_result[form_key])
109 109 Session().add(sett)
110 110
111 111 Session().commit()
112 112 h.flash(_('Application permissions updated successfully'),
113 113 category='success')
114 114
115 115 except formencode.Invalid as errors:
116 116 defaults = errors.value
117 117
118 118 return htmlfill.render(
119 119 render('admin/permissions/permissions.html'),
120 120 defaults=defaults,
121 121 errors=errors.error_dict or {},
122 122 prefix_error=False,
123 123 encoding="UTF-8",
124 124 force_defaults=False)
125 125 except Exception:
126 126 log.exception("Exception during update of permissions")
127 127 h.flash(_('Error occurred during update of permissions'),
128 128 category='error')
129 129
130 130 return redirect(url('admin_permissions_application'))
131 131
132 132 @HasPermissionAllDecorator('hg.admin')
133 133 def permission_objects(self):
134 134 c.active = 'objects'
135 135 self.__load_data()
136 136 c.user = User.get_default_user()
137 137 defaults = {}
138 138 defaults.update(c.user.get_default_perms())
139 139 return htmlfill.render(
140 140 render('admin/permissions/permissions.html'),
141 141 defaults=defaults,
142 142 encoding="UTF-8",
143 143 force_defaults=False)
144 144
145 145 @HasPermissionAllDecorator('hg.admin')
146 146 @auth.CSRFRequired()
147 147 def permission_objects_update(self):
148 148 c.active = 'objects'
149 149 self.__load_data()
150 150 _form = ObjectPermissionsForm(
151 151 [x[0] for x in c.repo_perms_choices],
152 152 [x[0] for x in c.group_perms_choices],
153 153 [x[0] for x in c.user_group_perms_choices])()
154 154
155 155 try:
156 156 form_result = _form.to_python(dict(request.POST))
157 157 form_result.update({'perm_user_name': User.DEFAULT_USER})
158 158 PermissionModel().update_object_permissions(form_result)
159 159
160 160 Session().commit()
161 161 h.flash(_('Object permissions updated successfully'),
162 162 category='success')
163 163
164 164 except formencode.Invalid as errors:
165 165 defaults = errors.value
166 166
167 167 return htmlfill.render(
168 168 render('admin/permissions/permissions.html'),
169 169 defaults=defaults,
170 170 errors=errors.error_dict or {},
171 171 prefix_error=False,
172 172 encoding="UTF-8",
173 173 force_defaults=False)
174 174 except Exception:
175 175 log.exception("Exception during update of permissions")
176 176 h.flash(_('Error occurred during update of permissions'),
177 177 category='error')
178 178
179 179 return redirect(url('admin_permissions_object'))
180 180
181 181 @HasPermissionAllDecorator('hg.admin')
182 182 def permission_global(self):
183 183 c.active = 'global'
184 184 self.__load_data()
185 185
186 186 c.user = User.get_default_user()
187 187 defaults = {}
188 188 defaults.update(c.user.get_default_perms())
189 189
190 190 return htmlfill.render(
191 191 render('admin/permissions/permissions.html'),
192 192 defaults=defaults,
193 193 encoding="UTF-8",
194 194 force_defaults=False)
195 195
196 196 @HasPermissionAllDecorator('hg.admin')
197 197 @auth.CSRFRequired()
198 198 def permission_global_update(self):
199 199 c.active = 'global'
200 200 self.__load_data()
201 201 _form = UserPermissionsForm(
202 202 [x[0] for x in c.repo_create_choices],
203 203 [x[0] for x in c.repo_create_on_write_choices],
204 204 [x[0] for x in c.repo_group_create_choices],
205 205 [x[0] for x in c.user_group_create_choices],
206 206 [x[0] for x in c.fork_choices],
207 207 [x[0] for x in c.inherit_default_permission_choices])()
208 208
209 209 try:
210 210 form_result = _form.to_python(dict(request.POST))
211 211 form_result.update({'perm_user_name': User.DEFAULT_USER})
212 212 PermissionModel().update_user_permissions(form_result)
213 213
214 214 Session().commit()
215 215 h.flash(_('Global permissions updated successfully'),
216 216 category='success')
217 217
218 218 except formencode.Invalid as errors:
219 219 defaults = errors.value
220 220
221 221 return htmlfill.render(
222 222 render('admin/permissions/permissions.html'),
223 223 defaults=defaults,
224 224 errors=errors.error_dict or {},
225 225 prefix_error=False,
226 226 encoding="UTF-8",
227 227 force_defaults=False)
228 228 except Exception:
229 229 log.exception("Exception during update of permissions")
230 230 h.flash(_('Error occurred during update of permissions'),
231 231 category='error')
232 232
233 233 return redirect(url('admin_permissions_global'))
234 234
235 235 @HasPermissionAllDecorator('hg.admin')
236 236 def permission_ips(self):
237 237 c.active = 'ips'
238 238 c.user = User.get_default_user()
239 239 c.user_ip_map = (
240 240 UserIpMap.query().filter(UserIpMap.user == c.user).all())
241 241
242 242 return render('admin/permissions/permissions.html')
243 243
244 244 @HasPermissionAllDecorator('hg.admin')
245 245 def permission_perms(self):
246 246 c.active = 'perms'
247 247 c.user = User.get_default_user()
248 248 c.perm_user = c.user.AuthUser
249 249 return render('admin/permissions/permissions.html')
@@ -1,487 +1,487 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 User Groups crud controller for pylons
23 23 """
24 24
25 25 import logging
26 26 import formencode
27 27
28 28 import peppercorn
29 29 from formencode import htmlfill
30 30 from pylons import request, tmpl_context as c, url, config
31 31 from pylons.controllers.util import redirect
32 32 from pylons.i18n.translation import _
33 33
34 34 from sqlalchemy.orm import joinedload
35 35
36 36 from rhodecode.lib import auth
37 37 from rhodecode.lib import helpers as h
38 38 from rhodecode.lib.exceptions import UserGroupAssignedException,\
39 39 RepoGroupAssignmentError
40 40 from rhodecode.lib.utils import jsonify, action_logger
41 41 from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int
42 42 from rhodecode.lib.auth import (
43 43 LoginRequired, NotAnonymous, HasUserGroupPermissionAnyDecorator,
44 44 HasPermissionAnyDecorator, XHRRequired)
45 45 from rhodecode.lib.base import BaseController, render
46 46 from rhodecode.model.permission import PermissionModel
47 47 from rhodecode.model.scm import UserGroupList
48 48 from rhodecode.model.user_group import UserGroupModel
49 49 from rhodecode.model.db import (
50 50 User, UserGroup, UserGroupRepoToPerm, UserGroupRepoGroupToPerm)
51 51 from rhodecode.model.forms import (
52 52 UserGroupForm, UserGroupPermsForm, UserIndividualPermissionsForm,
53 53 UserPermissionsForm)
54 54 from rhodecode.model.meta import Session
55 55 from rhodecode.lib.utils import action_logger
56 56 from rhodecode.lib.ext_json import json
57 57
58 58 log = logging.getLogger(__name__)
59 59
60 60
61 61 class UserGroupsController(BaseController):
62 62 """REST Controller styled on the Atom Publishing Protocol"""
63 63
64 64 @LoginRequired()
65 65 def __before__(self):
66 66 super(UserGroupsController, self).__before__()
67 67 c.available_permissions = config['available_permissions']
68 PermissionModel().set_global_permission_choices(c, translator=_)
68 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
69 69
70 70 def __load_data(self, user_group_id):
71 71 c.group_members_obj = [x.user for x in c.user_group.members]
72 72 c.group_members_obj.sort(key=lambda u: u.username.lower())
73 73 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
74 74
75 75 def __load_defaults(self, user_group_id):
76 76 """
77 77 Load defaults settings for edit, and update
78 78
79 79 :param user_group_id:
80 80 """
81 81 user_group = UserGroup.get_or_404(user_group_id)
82 82 data = user_group.get_dict()
83 83 # fill owner
84 84 if user_group.user:
85 85 data.update({'user': user_group.user.username})
86 86 else:
87 87 replacement_user = User.get_first_super_admin().username
88 88 data.update({'user': replacement_user})
89 89 return data
90 90
91 91 def _revoke_perms_on_yourself(self, form_result):
92 92 _updates = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
93 93 form_result['perm_updates'])
94 94 _additions = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
95 95 form_result['perm_additions'])
96 96 _deletions = filter(lambda u: c.rhodecode_user.user_id == int(u[0]),
97 97 form_result['perm_deletions'])
98 98 admin_perm = 'usergroup.admin'
99 99 if _updates and _updates[0][1] != admin_perm or \
100 100 _additions and _additions[0][1] != admin_perm or \
101 101 _deletions and _deletions[0][1] != admin_perm:
102 102 return True
103 103 return False
104 104
105 105 # permission check inside
106 106 @NotAnonymous()
107 107 def index(self):
108 108 """GET /users_groups: All items in the collection"""
109 109 # url('users_groups')
110 110
111 111 from rhodecode.lib.utils import PartialRenderer
112 112 _render = PartialRenderer('data_table/_dt_elements.html')
113 113
114 114 def user_group_name(user_group_id, user_group_name):
115 115 return _render("user_group_name", user_group_id, user_group_name)
116 116
117 117 def user_group_actions(user_group_id, user_group_name):
118 118 return _render("user_group_actions", user_group_id, user_group_name)
119 119
120 120 ## json generate
121 121 group_iter = UserGroupList(UserGroup.query().all(),
122 122 perm_set=['usergroup.admin'])
123 123
124 124 user_groups_data = []
125 125 for user_gr in group_iter:
126 126 user_groups_data.append({
127 127 "group_name": user_group_name(
128 128 user_gr.users_group_id, h.escape(user_gr.users_group_name)),
129 129 "group_name_raw": user_gr.users_group_name,
130 130 "desc": h.escape(user_gr.user_group_description),
131 131 "members": len(user_gr.members),
132 132 "active": h.bool2icon(user_gr.users_group_active),
133 133 "owner": h.escape(h.link_to_user(user_gr.user.username)),
134 134 "action": user_group_actions(
135 135 user_gr.users_group_id, user_gr.users_group_name)
136 136 })
137 137
138 138 c.data = json.dumps(user_groups_data)
139 139 return render('admin/user_groups/user_groups.html')
140 140
141 141 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
142 142 @auth.CSRFRequired()
143 143 def create(self):
144 144 """POST /users_groups: Create a new item"""
145 145 # url('users_groups')
146 146
147 147 users_group_form = UserGroupForm()()
148 148 try:
149 149 form_result = users_group_form.to_python(dict(request.POST))
150 150 user_group = UserGroupModel().create(
151 151 name=form_result['users_group_name'],
152 152 description=form_result['user_group_description'],
153 153 owner=c.rhodecode_user.user_id,
154 154 active=form_result['users_group_active'])
155 155 Session().flush()
156 156
157 157 user_group_name = form_result['users_group_name']
158 158 action_logger(c.rhodecode_user,
159 159 'admin_created_users_group:%s' % user_group_name,
160 160 None, self.ip_addr, self.sa)
161 161 user_group_link = h.link_to(h.escape(user_group_name),
162 162 url('edit_users_group',
163 163 user_group_id=user_group.users_group_id))
164 164 h.flash(h.literal(_('Created user group %(user_group_link)s')
165 165 % {'user_group_link': user_group_link}),
166 166 category='success')
167 167 Session().commit()
168 168 except formencode.Invalid as errors:
169 169 return htmlfill.render(
170 170 render('admin/user_groups/user_group_add.html'),
171 171 defaults=errors.value,
172 172 errors=errors.error_dict or {},
173 173 prefix_error=False,
174 174 encoding="UTF-8",
175 175 force_defaults=False)
176 176 except Exception:
177 177 log.exception("Exception creating user group")
178 178 h.flash(_('Error occurred during creation of user group %s') \
179 179 % request.POST.get('users_group_name'), category='error')
180 180
181 181 return redirect(
182 182 url('edit_users_group', user_group_id=user_group.users_group_id))
183 183
184 184 @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
185 185 def new(self):
186 186 """GET /user_groups/new: Form to create a new item"""
187 187 # url('new_users_group')
188 188 return render('admin/user_groups/user_group_add.html')
189 189
190 190 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
191 191 @auth.CSRFRequired()
192 192 def update(self, user_group_id):
193 193 """PUT /user_groups/user_group_id: Update an existing item"""
194 194 # Forms posted to this method should contain a hidden field:
195 195 # <input type="hidden" name="_method" value="PUT" />
196 196 # Or using helpers:
197 197 # h.form(url('users_group', user_group_id=ID),
198 198 # method='put')
199 199 # url('users_group', user_group_id=ID)
200 200
201 201 user_group_id = safe_int(user_group_id)
202 202 c.user_group = UserGroup.get_or_404(user_group_id)
203 203 c.active = 'settings'
204 204 self.__load_data(user_group_id)
205 205
206 206 users_group_form = UserGroupForm(
207 207 edit=True, old_data=c.user_group.get_dict(), allow_disabled=True)()
208 208
209 209 try:
210 210 form_result = users_group_form.to_python(request.POST)
211 211 pstruct = peppercorn.parse(request.POST.items())
212 212 form_result['users_group_members'] = pstruct['user_group_members']
213 213
214 214 UserGroupModel().update(c.user_group, form_result)
215 215 updated_user_group = form_result['users_group_name']
216 216 action_logger(c.rhodecode_user,
217 217 'admin_updated_users_group:%s' % updated_user_group,
218 218 None, self.ip_addr, self.sa)
219 219 h.flash(_('Updated user group %s') % updated_user_group,
220 220 category='success')
221 221 Session().commit()
222 222 except formencode.Invalid as errors:
223 223 defaults = errors.value
224 224 e = errors.error_dict or {}
225 225
226 226 return htmlfill.render(
227 227 render('admin/user_groups/user_group_edit.html'),
228 228 defaults=defaults,
229 229 errors=e,
230 230 prefix_error=False,
231 231 encoding="UTF-8",
232 232 force_defaults=False)
233 233 except Exception:
234 234 log.exception("Exception during update of user group")
235 235 h.flash(_('Error occurred during update of user group %s')
236 236 % request.POST.get('users_group_name'), category='error')
237 237
238 238 return redirect(url('edit_users_group', user_group_id=user_group_id))
239 239
240 240 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
241 241 @auth.CSRFRequired()
242 242 def delete(self, user_group_id):
243 243 """DELETE /user_groups/user_group_id: Delete an existing item"""
244 244 # Forms posted to this method should contain a hidden field:
245 245 # <input type="hidden" name="_method" value="DELETE" />
246 246 # Or using helpers:
247 247 # h.form(url('users_group', user_group_id=ID),
248 248 # method='delete')
249 249 # url('users_group', user_group_id=ID)
250 250 user_group_id = safe_int(user_group_id)
251 251 c.user_group = UserGroup.get_or_404(user_group_id)
252 252 force = str2bool(request.POST.get('force'))
253 253
254 254 try:
255 255 UserGroupModel().delete(c.user_group, force=force)
256 256 Session().commit()
257 257 h.flash(_('Successfully deleted user group'), category='success')
258 258 except UserGroupAssignedException as e:
259 259 h.flash(str(e), category='error')
260 260 except Exception:
261 261 log.exception("Exception during deletion of user group")
262 262 h.flash(_('An error occurred during deletion of user group'),
263 263 category='error')
264 264 return redirect(url('users_groups'))
265 265
266 266 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
267 267 def edit(self, user_group_id):
268 268 """GET /user_groups/user_group_id/edit: Form to edit an existing item"""
269 269 # url('edit_users_group', user_group_id=ID)
270 270
271 271 user_group_id = safe_int(user_group_id)
272 272 c.user_group = UserGroup.get_or_404(user_group_id)
273 273 c.active = 'settings'
274 274 self.__load_data(user_group_id)
275 275
276 276 defaults = self.__load_defaults(user_group_id)
277 277
278 278 return htmlfill.render(
279 279 render('admin/user_groups/user_group_edit.html'),
280 280 defaults=defaults,
281 281 encoding="UTF-8",
282 282 force_defaults=False
283 283 )
284 284
285 285 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
286 286 def edit_perms(self, user_group_id):
287 287 user_group_id = safe_int(user_group_id)
288 288 c.user_group = UserGroup.get_or_404(user_group_id)
289 289 c.active = 'perms'
290 290
291 291 defaults = {}
292 292 # fill user group users
293 293 for p in c.user_group.user_user_group_to_perm:
294 294 defaults.update({'u_perm_%s' % p.user.user_id:
295 295 p.permission.permission_name})
296 296
297 297 for p in c.user_group.user_group_user_group_to_perm:
298 298 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
299 299 p.permission.permission_name})
300 300
301 301 return htmlfill.render(
302 302 render('admin/user_groups/user_group_edit.html'),
303 303 defaults=defaults,
304 304 encoding="UTF-8",
305 305 force_defaults=False
306 306 )
307 307
308 308 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
309 309 @auth.CSRFRequired()
310 310 def update_perms(self, user_group_id):
311 311 """
312 312 grant permission for given usergroup
313 313
314 314 :param user_group_id:
315 315 """
316 316 user_group_id = safe_int(user_group_id)
317 317 c.user_group = UserGroup.get_or_404(user_group_id)
318 318 form = UserGroupPermsForm()().to_python(request.POST)
319 319
320 320 if not c.rhodecode_user.is_admin:
321 321 if self._revoke_perms_on_yourself(form):
322 322 msg = _('Cannot change permission for yourself as admin')
323 323 h.flash(msg, category='warning')
324 324 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
325 325
326 326 try:
327 327 UserGroupModel().update_permissions(user_group_id,
328 328 form['perm_additions'], form['perm_updates'], form['perm_deletions'])
329 329 except RepoGroupAssignmentError:
330 330 h.flash(_('Target group cannot be the same'), category='error')
331 331 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
332 332 #TODO: implement this
333 333 #action_logger(c.rhodecode_user, 'admin_changed_repo_permissions',
334 334 # repo_name, self.ip_addr, self.sa)
335 335 Session().commit()
336 336 h.flash(_('User Group permissions updated'), category='success')
337 337 return redirect(url('edit_user_group_perms', user_group_id=user_group_id))
338 338
339 339 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
340 340 def edit_perms_summary(self, user_group_id):
341 341 user_group_id = safe_int(user_group_id)
342 342 c.user_group = UserGroup.get_or_404(user_group_id)
343 343 c.active = 'perms_summary'
344 344 permissions = {
345 345 'repositories': {},
346 346 'repositories_groups': {},
347 347 }
348 348 ugroup_repo_perms = UserGroupRepoToPerm.query()\
349 349 .options(joinedload(UserGroupRepoToPerm.permission))\
350 350 .options(joinedload(UserGroupRepoToPerm.repository))\
351 351 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
352 352 .all()
353 353
354 354 for gr in ugroup_repo_perms:
355 355 permissions['repositories'][gr.repository.repo_name] \
356 356 = gr.permission.permission_name
357 357
358 358 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
359 359 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
360 360 .options(joinedload(UserGroupRepoGroupToPerm.group))\
361 361 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
362 362 .all()
363 363
364 364 for gr in ugroup_group_perms:
365 365 permissions['repositories_groups'][gr.group.group_name] \
366 366 = gr.permission.permission_name
367 367 c.permissions = permissions
368 368 return render('admin/user_groups/user_group_edit.html')
369 369
370 370 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
371 371 def edit_global_perms(self, user_group_id):
372 372 user_group_id = safe_int(user_group_id)
373 373 c.user_group = UserGroup.get_or_404(user_group_id)
374 374 c.active = 'global_perms'
375 375
376 376 c.default_user = User.get_default_user()
377 377 defaults = c.user_group.get_dict()
378 378 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
379 379 defaults.update(c.user_group.get_default_perms())
380 380
381 381 return htmlfill.render(
382 382 render('admin/user_groups/user_group_edit.html'),
383 383 defaults=defaults,
384 384 encoding="UTF-8",
385 385 force_defaults=False
386 386 )
387 387
388 388 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
389 389 @auth.CSRFRequired()
390 390 def update_global_perms(self, user_group_id):
391 391 """PUT /users_perm/user_group_id: Update an existing item"""
392 392 # url('users_group_perm', user_group_id=ID, method='put')
393 393 user_group_id = safe_int(user_group_id)
394 394 user_group = UserGroup.get_or_404(user_group_id)
395 395 c.active = 'global_perms'
396 396
397 397 try:
398 398 # first stage that verifies the checkbox
399 399 _form = UserIndividualPermissionsForm()
400 400 form_result = _form.to_python(dict(request.POST))
401 401 inherit_perms = form_result['inherit_default_permissions']
402 402 user_group.inherit_default_permissions = inherit_perms
403 403 Session().add(user_group)
404 404
405 405 if not inherit_perms:
406 406 # only update the individual ones if we un check the flag
407 407 _form = UserPermissionsForm(
408 408 [x[0] for x in c.repo_create_choices],
409 409 [x[0] for x in c.repo_create_on_write_choices],
410 410 [x[0] for x in c.repo_group_create_choices],
411 411 [x[0] for x in c.user_group_create_choices],
412 412 [x[0] for x in c.fork_choices],
413 413 [x[0] for x in c.inherit_default_permission_choices])()
414 414
415 415 form_result = _form.to_python(dict(request.POST))
416 416 form_result.update({'perm_user_group_id': user_group.users_group_id})
417 417
418 418 PermissionModel().update_user_group_permissions(form_result)
419 419
420 420 Session().commit()
421 421 h.flash(_('User Group global permissions updated successfully'),
422 422 category='success')
423 423
424 424 except formencode.Invalid as errors:
425 425 defaults = errors.value
426 426 c.user_group = user_group
427 427 return htmlfill.render(
428 428 render('admin/user_groups/user_group_edit.html'),
429 429 defaults=defaults,
430 430 errors=errors.error_dict or {},
431 431 prefix_error=False,
432 432 encoding="UTF-8",
433 433 force_defaults=False)
434 434
435 435 except Exception:
436 436 log.exception("Exception during permissions saving")
437 437 h.flash(_('An error occurred during permissions saving'),
438 438 category='error')
439 439
440 440 return redirect(url('edit_user_group_global_perms', user_group_id=user_group_id))
441 441
442 442 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
443 443 def edit_advanced(self, user_group_id):
444 444 user_group_id = safe_int(user_group_id)
445 445 c.user_group = UserGroup.get_or_404(user_group_id)
446 446 c.active = 'advanced'
447 447 c.group_members_obj = sorted(
448 448 (x.user for x in c.user_group.members),
449 449 key=lambda u: u.username.lower())
450 450
451 451 c.group_to_repos = sorted(
452 452 (x.repository for x in c.user_group.users_group_repo_to_perm),
453 453 key=lambda u: u.repo_name.lower())
454 454
455 455 c.group_to_repo_groups = sorted(
456 456 (x.group for x in c.user_group.users_group_repo_group_to_perm),
457 457 key=lambda u: u.group_name.lower())
458 458
459 459 return render('admin/user_groups/user_group_edit.html')
460 460
461 461 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
462 462 @XHRRequired()
463 463 @jsonify
464 464 def user_group_members(self, user_group_id):
465 465 user_group_id = safe_int(user_group_id)
466 466 user_group = UserGroup.get_or_404(user_group_id)
467 467 group_members_obj = sorted((x.user for x in user_group.members),
468 468 key=lambda u: u.username.lower())
469 469
470 470 group_members = [
471 471 {
472 472 'id': user.user_id,
473 473 'first_name': user.name,
474 474 'last_name': user.lastname,
475 475 'username': user.username,
476 476 'icon_link': h.gravatar_url(user.email, 30),
477 477 'value_display': h.person(user.email),
478 478 'value': user.username,
479 479 'value_type': 'user',
480 480 'active': user.active,
481 481 }
482 482 for user in group_members_obj
483 483 ]
484 484
485 485 return {
486 486 'members': group_members
487 487 }
@@ -1,748 +1,748 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Users crud controller for pylons
23 23 """
24 24
25 25 import logging
26 26 import formencode
27 27
28 28 from formencode import htmlfill
29 29 from pylons import request, tmpl_context as c, url, config
30 30 from pylons.controllers.util import redirect
31 31 from pylons.i18n.translation import _
32 32
33 33 from rhodecode.authentication.plugins import auth_rhodecode
34 34 from rhodecode.lib.exceptions import (
35 35 DefaultUserException, UserOwnsReposException, UserOwnsRepoGroupsException,
36 36 UserOwnsUserGroupsException, UserCreationError)
37 37 from rhodecode.lib import helpers as h
38 38 from rhodecode.lib import auth
39 39 from rhodecode.lib.auth import (
40 40 LoginRequired, HasPermissionAllDecorator, AuthUser, generate_auth_token)
41 41 from rhodecode.lib.base import BaseController, render
42 42 from rhodecode.model.auth_token import AuthTokenModel
43 43
44 44 from rhodecode.model.db import (
45 45 PullRequestReviewers, User, UserEmailMap, UserIpMap, RepoGroup)
46 46 from rhodecode.model.forms import (
47 47 UserForm, UserPermissionsForm, UserIndividualPermissionsForm)
48 48 from rhodecode.model.repo_group import RepoGroupModel
49 49 from rhodecode.model.user import UserModel
50 50 from rhodecode.model.meta import Session
51 51 from rhodecode.model.permission import PermissionModel
52 52 from rhodecode.lib.utils import action_logger
53 53 from rhodecode.lib.ext_json import json
54 54 from rhodecode.lib.utils2 import datetime_to_time, safe_int, AttributeDict
55 55
56 56 log = logging.getLogger(__name__)
57 57
58 58
59 59 class UsersController(BaseController):
60 60 """REST Controller styled on the Atom Publishing Protocol"""
61 61
62 62 @LoginRequired()
63 63 def __before__(self):
64 64 super(UsersController, self).__before__()
65 65 c.available_permissions = config['available_permissions']
66 66 c.allowed_languages = [
67 67 ('en', 'English (en)'),
68 68 ('de', 'German (de)'),
69 69 ('fr', 'French (fr)'),
70 70 ('it', 'Italian (it)'),
71 71 ('ja', 'Japanese (ja)'),
72 72 ('pl', 'Polish (pl)'),
73 73 ('pt', 'Portuguese (pt)'),
74 74 ('ru', 'Russian (ru)'),
75 75 ('zh', 'Chinese (zh)'),
76 76 ]
77 PermissionModel().set_global_permission_choices(c, translator=_)
77 PermissionModel().set_global_permission_choices(c, gettext_translator=_)
78 78
79 79 @HasPermissionAllDecorator('hg.admin')
80 80 def index(self):
81 81 """GET /users: All items in the collection"""
82 82 # url('users')
83 83
84 84 from rhodecode.lib.utils import PartialRenderer
85 85 _render = PartialRenderer('data_table/_dt_elements.html')
86 86
87 87 def username(user_id, username):
88 88 return _render("user_name", user_id, username)
89 89
90 90 def user_actions(user_id, username):
91 91 return _render("user_actions", user_id, username)
92 92
93 93 # json generate
94 94 c.users_list = User.query()\
95 95 .filter(User.username != User.DEFAULT_USER) \
96 96 .all()
97 97
98 98 users_data = []
99 99 for user in c.users_list:
100 100 users_data.append({
101 101 "username": h.gravatar_with_user(user.username),
102 102 "username_raw": user.username,
103 103 "email": user.email,
104 104 "first_name": h.escape(user.name),
105 105 "last_name": h.escape(user.lastname),
106 106 "last_login": h.format_date(user.last_login),
107 107 "last_login_raw": datetime_to_time(user.last_login),
108 108 "last_activity": h.format_date(
109 109 h.time_to_datetime(user.user_data.get('last_activity', 0))),
110 110 "last_activity_raw": user.user_data.get('last_activity', 0),
111 111 "active": h.bool2icon(user.active),
112 112 "active_raw": user.active,
113 113 "admin": h.bool2icon(user.admin),
114 114 "admin_raw": user.admin,
115 115 "extern_type": user.extern_type,
116 116 "extern_name": user.extern_name,
117 117 "action": user_actions(user.user_id, user.username),
118 118 })
119 119
120 120
121 121 c.data = json.dumps(users_data)
122 122 return render('admin/users/users.html')
123 123
124 124 def _get_personal_repo_group_template_vars(self):
125 125 DummyUser = AttributeDict({
126 126 'username': '${username}',
127 127 'user_id': '${user_id}',
128 128 })
129 129 c.default_create_repo_group = RepoGroupModel() \
130 130 .get_default_create_personal_repo_group()
131 131 c.personal_repo_group_name = RepoGroupModel() \
132 132 .get_personal_group_name(DummyUser)
133 133
134 134 @HasPermissionAllDecorator('hg.admin')
135 135 @auth.CSRFRequired()
136 136 def create(self):
137 137 """POST /users: Create a new item"""
138 138 # url('users')
139 139 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
140 140 user_model = UserModel()
141 141 user_form = UserForm()()
142 142 try:
143 143 form_result = user_form.to_python(dict(request.POST))
144 144 user = user_model.create(form_result)
145 145 Session().flush()
146 146 username = form_result['username']
147 147 action_logger(c.rhodecode_user, 'admin_created_user:%s' % username,
148 148 None, self.ip_addr, self.sa)
149 149
150 150 user_link = h.link_to(h.escape(username),
151 151 url('edit_user',
152 152 user_id=user.user_id))
153 153 h.flash(h.literal(_('Created user %(user_link)s')
154 154 % {'user_link': user_link}), category='success')
155 155 Session().commit()
156 156 except formencode.Invalid as errors:
157 157 self._get_personal_repo_group_template_vars()
158 158 return htmlfill.render(
159 159 render('admin/users/user_add.html'),
160 160 defaults=errors.value,
161 161 errors=errors.error_dict or {},
162 162 prefix_error=False,
163 163 encoding="UTF-8",
164 164 force_defaults=False)
165 165 except UserCreationError as e:
166 166 h.flash(e, 'error')
167 167 except Exception:
168 168 log.exception("Exception creation of user")
169 169 h.flash(_('Error occurred during creation of user %s')
170 170 % request.POST.get('username'), category='error')
171 171 return redirect(url('users'))
172 172
173 173 @HasPermissionAllDecorator('hg.admin')
174 174 def new(self):
175 175 """GET /users/new: Form to create a new item"""
176 176 # url('new_user')
177 177 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
178 178 self._get_personal_repo_group_template_vars()
179 179 return render('admin/users/user_add.html')
180 180
181 181 @HasPermissionAllDecorator('hg.admin')
182 182 @auth.CSRFRequired()
183 183 def update(self, user_id):
184 184 """PUT /users/user_id: Update an existing item"""
185 185 # Forms posted to this method should contain a hidden field:
186 186 # <input type="hidden" name="_method" value="PUT" />
187 187 # Or using helpers:
188 188 # h.form(url('update_user', user_id=ID),
189 189 # method='put')
190 190 # url('user', user_id=ID)
191 191 user_id = safe_int(user_id)
192 192 c.user = User.get_or_404(user_id)
193 193 c.active = 'profile'
194 194 c.extern_type = c.user.extern_type
195 195 c.extern_name = c.user.extern_name
196 196 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
197 197 available_languages = [x[0] for x in c.allowed_languages]
198 198 _form = UserForm(edit=True, available_languages=available_languages,
199 199 old_data={'user_id': user_id,
200 200 'email': c.user.email})()
201 201 form_result = {}
202 202 try:
203 203 form_result = _form.to_python(dict(request.POST))
204 204 skip_attrs = ['extern_type', 'extern_name']
205 205 # TODO: plugin should define if username can be updated
206 206 if c.extern_type != "rhodecode":
207 207 # forbid updating username for external accounts
208 208 skip_attrs.append('username')
209 209
210 210 UserModel().update_user(user_id, skip_attrs=skip_attrs, **form_result)
211 211 usr = form_result['username']
212 212 action_logger(c.rhodecode_user, 'admin_updated_user:%s' % usr,
213 213 None, self.ip_addr, self.sa)
214 214 h.flash(_('User updated successfully'), category='success')
215 215 Session().commit()
216 216 except formencode.Invalid as errors:
217 217 defaults = errors.value
218 218 e = errors.error_dict or {}
219 219
220 220 return htmlfill.render(
221 221 render('admin/users/user_edit.html'),
222 222 defaults=defaults,
223 223 errors=e,
224 224 prefix_error=False,
225 225 encoding="UTF-8",
226 226 force_defaults=False)
227 227 except UserCreationError as e:
228 228 h.flash(e, 'error')
229 229 except Exception:
230 230 log.exception("Exception updating user")
231 231 h.flash(_('Error occurred during update of user %s')
232 232 % form_result.get('username'), category='error')
233 233 return redirect(url('edit_user', user_id=user_id))
234 234
235 235 @HasPermissionAllDecorator('hg.admin')
236 236 @auth.CSRFRequired()
237 237 def delete(self, user_id):
238 238 """DELETE /users/user_id: Delete an existing item"""
239 239 # Forms posted to this method should contain a hidden field:
240 240 # <input type="hidden" name="_method" value="DELETE" />
241 241 # Or using helpers:
242 242 # h.form(url('delete_user', user_id=ID),
243 243 # method='delete')
244 244 # url('user', user_id=ID)
245 245 user_id = safe_int(user_id)
246 246 c.user = User.get_or_404(user_id)
247 247
248 248 _repos = c.user.repositories
249 249 _repo_groups = c.user.repository_groups
250 250 _user_groups = c.user.user_groups
251 251
252 252 handle_repos = None
253 253 handle_repo_groups = None
254 254 handle_user_groups = None
255 255 # dummy call for flash of handle
256 256 set_handle_flash_repos = lambda: None
257 257 set_handle_flash_repo_groups = lambda: None
258 258 set_handle_flash_user_groups = lambda: None
259 259
260 260 if _repos and request.POST.get('user_repos'):
261 261 do = request.POST['user_repos']
262 262 if do == 'detach':
263 263 handle_repos = 'detach'
264 264 set_handle_flash_repos = lambda: h.flash(
265 265 _('Detached %s repositories') % len(_repos),
266 266 category='success')
267 267 elif do == 'delete':
268 268 handle_repos = 'delete'
269 269 set_handle_flash_repos = lambda: h.flash(
270 270 _('Deleted %s repositories') % len(_repos),
271 271 category='success')
272 272
273 273 if _repo_groups and request.POST.get('user_repo_groups'):
274 274 do = request.POST['user_repo_groups']
275 275 if do == 'detach':
276 276 handle_repo_groups = 'detach'
277 277 set_handle_flash_repo_groups = lambda: h.flash(
278 278 _('Detached %s repository groups') % len(_repo_groups),
279 279 category='success')
280 280 elif do == 'delete':
281 281 handle_repo_groups = 'delete'
282 282 set_handle_flash_repo_groups = lambda: h.flash(
283 283 _('Deleted %s repository groups') % len(_repo_groups),
284 284 category='success')
285 285
286 286 if _user_groups and request.POST.get('user_user_groups'):
287 287 do = request.POST['user_user_groups']
288 288 if do == 'detach':
289 289 handle_user_groups = 'detach'
290 290 set_handle_flash_user_groups = lambda: h.flash(
291 291 _('Detached %s user groups') % len(_user_groups),
292 292 category='success')
293 293 elif do == 'delete':
294 294 handle_user_groups = 'delete'
295 295 set_handle_flash_user_groups = lambda: h.flash(
296 296 _('Deleted %s user groups') % len(_user_groups),
297 297 category='success')
298 298
299 299 try:
300 300 UserModel().delete(c.user, handle_repos=handle_repos,
301 301 handle_repo_groups=handle_repo_groups,
302 302 handle_user_groups=handle_user_groups)
303 303 Session().commit()
304 304 set_handle_flash_repos()
305 305 set_handle_flash_repo_groups()
306 306 set_handle_flash_user_groups()
307 307 h.flash(_('Successfully deleted user'), category='success')
308 308 except (UserOwnsReposException, UserOwnsRepoGroupsException,
309 309 UserOwnsUserGroupsException, DefaultUserException) as e:
310 310 h.flash(e, category='warning')
311 311 except Exception:
312 312 log.exception("Exception during deletion of user")
313 313 h.flash(_('An error occurred during deletion of user'),
314 314 category='error')
315 315 return redirect(url('users'))
316 316
317 317 @HasPermissionAllDecorator('hg.admin')
318 318 @auth.CSRFRequired()
319 319 def reset_password(self, user_id):
320 320 """
321 321 toggle reset password flag for this user
322 322
323 323 :param user_id:
324 324 """
325 325 user_id = safe_int(user_id)
326 326 c.user = User.get_or_404(user_id)
327 327 try:
328 328 old_value = c.user.user_data.get('force_password_change')
329 329 c.user.update_userdata(force_password_change=not old_value)
330 330 Session().commit()
331 331 if old_value:
332 332 msg = _('Force password change disabled for user')
333 333 else:
334 334 msg = _('Force password change enabled for user')
335 335 h.flash(msg, category='success')
336 336 except Exception:
337 337 log.exception("Exception during password reset for user")
338 338 h.flash(_('An error occurred during password reset for user'),
339 339 category='error')
340 340
341 341 return redirect(url('edit_user_advanced', user_id=user_id))
342 342
343 343 @HasPermissionAllDecorator('hg.admin')
344 344 @auth.CSRFRequired()
345 345 def create_personal_repo_group(self, user_id):
346 346 """
347 347 Create personal repository group for this user
348 348
349 349 :param user_id:
350 350 """
351 351 from rhodecode.model.repo_group import RepoGroupModel
352 352
353 353 user_id = safe_int(user_id)
354 354 c.user = User.get_or_404(user_id)
355 355 personal_repo_group = RepoGroup.get_user_personal_repo_group(
356 356 c.user.user_id)
357 357 if personal_repo_group:
358 358 return redirect(url('edit_user_advanced', user_id=user_id))
359 359
360 360 personal_repo_group_name = RepoGroupModel().get_personal_group_name(
361 361 c.user)
362 362 named_personal_group = RepoGroup.get_by_group_name(
363 363 personal_repo_group_name)
364 364 try:
365 365
366 366 if named_personal_group and named_personal_group.user_id == c.user.user_id:
367 367 # migrate the same named group, and mark it as personal
368 368 named_personal_group.personal = True
369 369 Session().add(named_personal_group)
370 370 Session().commit()
371 371 msg = _('Linked repository group `%s` as personal' % (
372 372 personal_repo_group_name,))
373 373 h.flash(msg, category='success')
374 374 elif not named_personal_group:
375 375 RepoGroupModel().create_personal_repo_group(c.user)
376 376
377 377 msg = _('Created repository group `%s`' % (
378 378 personal_repo_group_name,))
379 379 h.flash(msg, category='success')
380 380 else:
381 381 msg = _('Repository group `%s` is already taken' % (
382 382 personal_repo_group_name,))
383 383 h.flash(msg, category='warning')
384 384 except Exception:
385 385 log.exception("Exception during repository group creation")
386 386 msg = _(
387 387 'An error occurred during repository group creation for user')
388 388 h.flash(msg, category='error')
389 389 Session().rollback()
390 390
391 391 return redirect(url('edit_user_advanced', user_id=user_id))
392 392
393 393 @HasPermissionAllDecorator('hg.admin')
394 394 def show(self, user_id):
395 395 """GET /users/user_id: Show a specific item"""
396 396 # url('user', user_id=ID)
397 397 User.get_or_404(-1)
398 398
399 399 @HasPermissionAllDecorator('hg.admin')
400 400 def edit(self, user_id):
401 401 """GET /users/user_id/edit: Form to edit an existing item"""
402 402 # url('edit_user', user_id=ID)
403 403 user_id = safe_int(user_id)
404 404 c.user = User.get_or_404(user_id)
405 405 if c.user.username == User.DEFAULT_USER:
406 406 h.flash(_("You can't edit this user"), category='warning')
407 407 return redirect(url('users'))
408 408
409 409 c.active = 'profile'
410 410 c.extern_type = c.user.extern_type
411 411 c.extern_name = c.user.extern_name
412 412 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
413 413
414 414 defaults = c.user.get_dict()
415 415 defaults.update({'language': c.user.user_data.get('language')})
416 416 return htmlfill.render(
417 417 render('admin/users/user_edit.html'),
418 418 defaults=defaults,
419 419 encoding="UTF-8",
420 420 force_defaults=False)
421 421
422 422 @HasPermissionAllDecorator('hg.admin')
423 423 def edit_advanced(self, user_id):
424 424 user_id = safe_int(user_id)
425 425 user = c.user = User.get_or_404(user_id)
426 426 if user.username == User.DEFAULT_USER:
427 427 h.flash(_("You can't edit this user"), category='warning')
428 428 return redirect(url('users'))
429 429
430 430 c.active = 'advanced'
431 431 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
432 432 c.personal_repo_group = c.perm_user.personal_repo_group
433 433 c.personal_repo_group_name = RepoGroupModel()\
434 434 .get_personal_group_name(user)
435 435 c.first_admin = User.get_first_super_admin()
436 436 defaults = user.get_dict()
437 437
438 438 # Interim workaround if the user participated on any pull requests as a
439 439 # reviewer.
440 440 has_review = bool(PullRequestReviewers.query().filter(
441 441 PullRequestReviewers.user_id == user_id).first())
442 442 c.can_delete_user = not has_review
443 443 c.can_delete_user_message = _(
444 444 'The user participates as reviewer in pull requests and '
445 445 'cannot be deleted. You can set the user to '
446 446 '"inactive" instead of deleting it.') if has_review else ''
447 447
448 448 return htmlfill.render(
449 449 render('admin/users/user_edit.html'),
450 450 defaults=defaults,
451 451 encoding="UTF-8",
452 452 force_defaults=False)
453 453
454 454 @HasPermissionAllDecorator('hg.admin')
455 455 def edit_auth_tokens(self, user_id):
456 456 user_id = safe_int(user_id)
457 457 c.user = User.get_or_404(user_id)
458 458 if c.user.username == User.DEFAULT_USER:
459 459 h.flash(_("You can't edit this user"), category='warning')
460 460 return redirect(url('users'))
461 461
462 462 c.active = 'auth_tokens'
463 463 show_expired = True
464 464 c.lifetime_values = [
465 465 (str(-1), _('forever')),
466 466 (str(5), _('5 minutes')),
467 467 (str(60), _('1 hour')),
468 468 (str(60 * 24), _('1 day')),
469 469 (str(60 * 24 * 30), _('1 month')),
470 470 ]
471 471 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
472 472 c.role_values = [(x, AuthTokenModel.cls._get_role_name(x))
473 473 for x in AuthTokenModel.cls.ROLES]
474 474 c.role_options = [(c.role_values, _("Role"))]
475 475 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
476 476 c.user.user_id, show_expired=show_expired)
477 477 defaults = c.user.get_dict()
478 478 return htmlfill.render(
479 479 render('admin/users/user_edit.html'),
480 480 defaults=defaults,
481 481 encoding="UTF-8",
482 482 force_defaults=False)
483 483
484 484 @HasPermissionAllDecorator('hg.admin')
485 485 @auth.CSRFRequired()
486 486 def add_auth_token(self, user_id):
487 487 user_id = safe_int(user_id)
488 488 c.user = User.get_or_404(user_id)
489 489 if c.user.username == User.DEFAULT_USER:
490 490 h.flash(_("You can't edit this user"), category='warning')
491 491 return redirect(url('users'))
492 492
493 493 lifetime = safe_int(request.POST.get('lifetime'), -1)
494 494 description = request.POST.get('description')
495 495 role = request.POST.get('role')
496 496 AuthTokenModel().create(c.user.user_id, description, lifetime, role)
497 497 Session().commit()
498 498 h.flash(_("Auth token successfully created"), category='success')
499 499 return redirect(url('edit_user_auth_tokens', user_id=c.user.user_id))
500 500
501 501 @HasPermissionAllDecorator('hg.admin')
502 502 @auth.CSRFRequired()
503 503 def delete_auth_token(self, user_id):
504 504 user_id = safe_int(user_id)
505 505 c.user = User.get_or_404(user_id)
506 506 if c.user.username == User.DEFAULT_USER:
507 507 h.flash(_("You can't edit this user"), category='warning')
508 508 return redirect(url('users'))
509 509
510 510 auth_token = request.POST.get('del_auth_token')
511 511 if request.POST.get('del_auth_token_builtin'):
512 512 user = User.get(c.user.user_id)
513 513 if user:
514 514 user.api_key = generate_auth_token(user.username)
515 515 Session().add(user)
516 516 Session().commit()
517 517 h.flash(_("Auth token successfully reset"), category='success')
518 518 elif auth_token:
519 519 AuthTokenModel().delete(auth_token, c.user.user_id)
520 520 Session().commit()
521 521 h.flash(_("Auth token successfully deleted"), category='success')
522 522
523 523 return redirect(url('edit_user_auth_tokens', user_id=c.user.user_id))
524 524
525 525 @HasPermissionAllDecorator('hg.admin')
526 526 def edit_global_perms(self, user_id):
527 527 user_id = safe_int(user_id)
528 528 c.user = User.get_or_404(user_id)
529 529 if c.user.username == User.DEFAULT_USER:
530 530 h.flash(_("You can't edit this user"), category='warning')
531 531 return redirect(url('users'))
532 532
533 533 c.active = 'global_perms'
534 534
535 535 c.default_user = User.get_default_user()
536 536 defaults = c.user.get_dict()
537 537 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
538 538 defaults.update(c.default_user.get_default_perms())
539 539 defaults.update(c.user.get_default_perms())
540 540
541 541 return htmlfill.render(
542 542 render('admin/users/user_edit.html'),
543 543 defaults=defaults,
544 544 encoding="UTF-8",
545 545 force_defaults=False)
546 546
547 547 @HasPermissionAllDecorator('hg.admin')
548 548 @auth.CSRFRequired()
549 549 def update_global_perms(self, user_id):
550 550 """PUT /users_perm/user_id: Update an existing item"""
551 551 # url('user_perm', user_id=ID, method='put')
552 552 user_id = safe_int(user_id)
553 553 user = User.get_or_404(user_id)
554 554 c.active = 'global_perms'
555 555 try:
556 556 # first stage that verifies the checkbox
557 557 _form = UserIndividualPermissionsForm()
558 558 form_result = _form.to_python(dict(request.POST))
559 559 inherit_perms = form_result['inherit_default_permissions']
560 560 user.inherit_default_permissions = inherit_perms
561 561 Session().add(user)
562 562
563 563 if not inherit_perms:
564 564 # only update the individual ones if we un check the flag
565 565 _form = UserPermissionsForm(
566 566 [x[0] for x in c.repo_create_choices],
567 567 [x[0] for x in c.repo_create_on_write_choices],
568 568 [x[0] for x in c.repo_group_create_choices],
569 569 [x[0] for x in c.user_group_create_choices],
570 570 [x[0] for x in c.fork_choices],
571 571 [x[0] for x in c.inherit_default_permission_choices])()
572 572
573 573 form_result = _form.to_python(dict(request.POST))
574 574 form_result.update({'perm_user_id': user.user_id})
575 575
576 576 PermissionModel().update_user_permissions(form_result)
577 577
578 578 Session().commit()
579 579 h.flash(_('User global permissions updated successfully'),
580 580 category='success')
581 581
582 582 Session().commit()
583 583 except formencode.Invalid as errors:
584 584 defaults = errors.value
585 585 c.user = user
586 586 return htmlfill.render(
587 587 render('admin/users/user_edit.html'),
588 588 defaults=defaults,
589 589 errors=errors.error_dict or {},
590 590 prefix_error=False,
591 591 encoding="UTF-8",
592 592 force_defaults=False)
593 593 except Exception:
594 594 log.exception("Exception during permissions saving")
595 595 h.flash(_('An error occurred during permissions saving'),
596 596 category='error')
597 597 return redirect(url('edit_user_global_perms', user_id=user_id))
598 598
599 599 @HasPermissionAllDecorator('hg.admin')
600 600 def edit_perms_summary(self, user_id):
601 601 user_id = safe_int(user_id)
602 602 c.user = User.get_or_404(user_id)
603 603 if c.user.username == User.DEFAULT_USER:
604 604 h.flash(_("You can't edit this user"), category='warning')
605 605 return redirect(url('users'))
606 606
607 607 c.active = 'perms_summary'
608 608 c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
609 609
610 610 return render('admin/users/user_edit.html')
611 611
612 612 @HasPermissionAllDecorator('hg.admin')
613 613 def edit_emails(self, user_id):
614 614 user_id = safe_int(user_id)
615 615 c.user = User.get_or_404(user_id)
616 616 if c.user.username == User.DEFAULT_USER:
617 617 h.flash(_("You can't edit this user"), category='warning')
618 618 return redirect(url('users'))
619 619
620 620 c.active = 'emails'
621 621 c.user_email_map = UserEmailMap.query() \
622 622 .filter(UserEmailMap.user == c.user).all()
623 623
624 624 defaults = c.user.get_dict()
625 625 return htmlfill.render(
626 626 render('admin/users/user_edit.html'),
627 627 defaults=defaults,
628 628 encoding="UTF-8",
629 629 force_defaults=False)
630 630
631 631 @HasPermissionAllDecorator('hg.admin')
632 632 @auth.CSRFRequired()
633 633 def add_email(self, user_id):
634 634 """POST /user_emails:Add an existing item"""
635 635 # url('user_emails', user_id=ID, method='put')
636 636 user_id = safe_int(user_id)
637 637 c.user = User.get_or_404(user_id)
638 638
639 639 email = request.POST.get('new_email')
640 640 user_model = UserModel()
641 641
642 642 try:
643 643 user_model.add_extra_email(user_id, email)
644 644 Session().commit()
645 645 h.flash(_("Added new email address `%s` for user account") % email,
646 646 category='success')
647 647 except formencode.Invalid as error:
648 648 msg = error.error_dict['email']
649 649 h.flash(msg, category='error')
650 650 except Exception:
651 651 log.exception("Exception during email saving")
652 652 h.flash(_('An error occurred during email saving'),
653 653 category='error')
654 654 return redirect(url('edit_user_emails', user_id=user_id))
655 655
656 656 @HasPermissionAllDecorator('hg.admin')
657 657 @auth.CSRFRequired()
658 658 def delete_email(self, user_id):
659 659 """DELETE /user_emails_delete/user_id: Delete an existing item"""
660 660 # url('user_emails_delete', user_id=ID, method='delete')
661 661 user_id = safe_int(user_id)
662 662 c.user = User.get_or_404(user_id)
663 663 email_id = request.POST.get('del_email_id')
664 664 user_model = UserModel()
665 665 user_model.delete_extra_email(user_id, email_id)
666 666 Session().commit()
667 667 h.flash(_("Removed email address from user account"), category='success')
668 668 return redirect(url('edit_user_emails', user_id=user_id))
669 669
670 670 @HasPermissionAllDecorator('hg.admin')
671 671 def edit_ips(self, user_id):
672 672 user_id = safe_int(user_id)
673 673 c.user = User.get_or_404(user_id)
674 674 if c.user.username == User.DEFAULT_USER:
675 675 h.flash(_("You can't edit this user"), category='warning')
676 676 return redirect(url('users'))
677 677
678 678 c.active = 'ips'
679 679 c.user_ip_map = UserIpMap.query() \
680 680 .filter(UserIpMap.user == c.user).all()
681 681
682 682 c.inherit_default_ips = c.user.inherit_default_permissions
683 683 c.default_user_ip_map = UserIpMap.query() \
684 684 .filter(UserIpMap.user == User.get_default_user()).all()
685 685
686 686 defaults = c.user.get_dict()
687 687 return htmlfill.render(
688 688 render('admin/users/user_edit.html'),
689 689 defaults=defaults,
690 690 encoding="UTF-8",
691 691 force_defaults=False)
692 692
693 693 @HasPermissionAllDecorator('hg.admin')
694 694 @auth.CSRFRequired()
695 695 def add_ip(self, user_id):
696 696 """POST /user_ips:Add an existing item"""
697 697 # url('user_ips', user_id=ID, method='put')
698 698
699 699 user_id = safe_int(user_id)
700 700 c.user = User.get_or_404(user_id)
701 701 user_model = UserModel()
702 702 try:
703 703 ip_list = user_model.parse_ip_range(request.POST.get('new_ip'))
704 704 except Exception as e:
705 705 ip_list = []
706 706 log.exception("Exception during ip saving")
707 707 h.flash(_('An error occurred during ip saving:%s' % (e,)),
708 708 category='error')
709 709
710 710 desc = request.POST.get('description')
711 711 added = []
712 712 for ip in ip_list:
713 713 try:
714 714 user_model.add_extra_ip(user_id, ip, desc)
715 715 Session().commit()
716 716 added.append(ip)
717 717 except formencode.Invalid as error:
718 718 msg = error.error_dict['ip']
719 719 h.flash(msg, category='error')
720 720 except Exception:
721 721 log.exception("Exception during ip saving")
722 722 h.flash(_('An error occurred during ip saving'),
723 723 category='error')
724 724 if added:
725 725 h.flash(
726 726 _("Added ips %s to user whitelist") % (', '.join(ip_list), ),
727 727 category='success')
728 728 if 'default_user' in request.POST:
729 729 return redirect(url('admin_permissions_ips'))
730 730 return redirect(url('edit_user_ips', user_id=user_id))
731 731
732 732 @HasPermissionAllDecorator('hg.admin')
733 733 @auth.CSRFRequired()
734 734 def delete_ip(self, user_id):
735 735 """DELETE /user_ips_delete/user_id: Delete an existing item"""
736 736 # url('user_ips_delete', user_id=ID, method='delete')
737 737 user_id = safe_int(user_id)
738 738 c.user = User.get_or_404(user_id)
739 739
740 740 ip_id = request.POST.get('del_ip_id')
741 741 user_model = UserModel()
742 742 user_model.delete_extra_ip(user_id, ip_id)
743 743 Session().commit()
744 744 h.flash(_("Removed ip address from user whitelist"), category='success')
745 745
746 746 if 'default_user' in request.POST:
747 747 return redirect(url('admin_permissions_ips'))
748 748 return redirect(url('edit_user_ips', user_id=user_id))
@@ -1,482 +1,483 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 permissions model for RhodeCode
23 23 """
24 24
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 from sqlalchemy.exc import DatabaseError
30 30
31 31 from rhodecode.model import BaseModel
32 32 from rhodecode.model.db import (
33 33 User, Permission, UserToPerm, UserRepoToPerm, UserRepoGroupToPerm,
34 34 UserUserGroupToPerm, UserGroup, UserGroupToPerm)
35 35 from rhodecode.lib.utils2 import str2bool, safe_int
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 class PermissionModel(BaseModel):
41 41 """
42 42 Permissions model for RhodeCode
43 43 """
44 44
45 45 cls = Permission
46 46 global_perms = {
47 47 'default_repo_create': None,
48 48 # special case for create repos on write access to group
49 49 'default_repo_create_on_write': None,
50 50 'default_repo_group_create': None,
51 51 'default_user_group_create': None,
52 52 'default_fork_create': None,
53 53 'default_inherit_default_permissions': None,
54 54 'default_register': None,
55 55 'default_password_reset': None,
56 56 'default_extern_activate': None,
57 57
58 58 # object permissions below
59 59 'default_repo_perm': None,
60 60 'default_group_perm': None,
61 61 'default_user_group_perm': None,
62 62 }
63 63
64 def set_global_permission_choices(self, c_obj, translator):
64 def set_global_permission_choices(self, c_obj, gettext_translator):
65
65 66 c_obj.repo_perms_choices = [
66 ('repository.none', translator('None'),),
67 ('repository.read', translator('Read'),),
68 ('repository.write', translator('Write'),),
69 ('repository.admin', translator('Admin'),)]
67 ('repository.none', gettext_translator('None'),),
68 ('repository.read', gettext_translator('Read'),),
69 ('repository.write', gettext_translator('Write'),),
70 ('repository.admin', gettext_translator('Admin'),)]
70 71
71 72 c_obj.group_perms_choices = [
72 ('group.none', translator('None'),),
73 ('group.read', translator('Read'),),
74 ('group.write', translator('Write'),),
75 ('group.admin', translator('Admin'),)]
73 ('group.none', gettext_translator('None'),),
74 ('group.read', gettext_translator('Read'),),
75 ('group.write', gettext_translator('Write'),),
76 ('group.admin', gettext_translator('Admin'),)]
76 77
77 78 c_obj.user_group_perms_choices = [
78 ('usergroup.none', translator('None'),),
79 ('usergroup.read', translator('Read'),),
80 ('usergroup.write', translator('Write'),),
81 ('usergroup.admin', translator('Admin'),)]
79 ('usergroup.none', gettext_translator('None'),),
80 ('usergroup.read', gettext_translator('Read'),),
81 ('usergroup.write', gettext_translator('Write'),),
82 ('usergroup.admin', gettext_translator('Admin'),)]
82 83
83 84 c_obj.register_choices = [
84 ('hg.register.none', translator('Disabled')),
85 ('hg.register.manual_activate', translator('Allowed with manual account activation')),
86 ('hg.register.auto_activate', translator('Allowed with automatic account activation')),]
85 ('hg.register.none', gettext_translator('Disabled')),
86 ('hg.register.manual_activate', gettext_translator('Allowed with manual account activation')),
87 ('hg.register.auto_activate', gettext_translator('Allowed with automatic account activation')),]
87 88
88 89 c_obj.password_reset_choices = [
89 ('hg.password_reset.enabled', translator('Allow password recovery')),
90 ('hg.password_reset.hidden', translator('Hide password recovery link')),
91 ('hg.password_reset.disabled', translator('Disable password recovery')),]
90 ('hg.password_reset.enabled', gettext_translator('Allow password recovery')),
91 ('hg.password_reset.hidden', gettext_translator('Hide password recovery link')),
92 ('hg.password_reset.disabled', gettext_translator('Disable password recovery')),]
92 93
93 94 c_obj.extern_activate_choices = [
94 ('hg.extern_activate.manual', translator('Manual activation of external account')),
95 ('hg.extern_activate.auto', translator('Automatic activation of external account')),]
95 ('hg.extern_activate.manual', gettext_translator('Manual activation of external account')),
96 ('hg.extern_activate.auto', gettext_translator('Automatic activation of external account')),]
96 97
97 98 c_obj.repo_create_choices = [
98 ('hg.create.none', translator('Disabled')),
99 ('hg.create.repository', translator('Enabled'))]
99 ('hg.create.none', gettext_translator('Disabled')),
100 ('hg.create.repository', gettext_translator('Enabled'))]
100 101
101 102 c_obj.repo_create_on_write_choices = [
102 ('hg.create.write_on_repogroup.false', translator('Disabled')),
103 ('hg.create.write_on_repogroup.true', translator('Enabled'))]
103 ('hg.create.write_on_repogroup.false', gettext_translator('Disabled')),
104 ('hg.create.write_on_repogroup.true', gettext_translator('Enabled'))]
104 105
105 106 c_obj.user_group_create_choices = [
106 ('hg.usergroup.create.false', translator('Disabled')),
107 ('hg.usergroup.create.true', translator('Enabled'))]
107 ('hg.usergroup.create.false', gettext_translator('Disabled')),
108 ('hg.usergroup.create.true', gettext_translator('Enabled'))]
108 109
109 110 c_obj.repo_group_create_choices = [
110 ('hg.repogroup.create.false', translator('Disabled')),
111 ('hg.repogroup.create.true', translator('Enabled'))]
111 ('hg.repogroup.create.false', gettext_translator('Disabled')),
112 ('hg.repogroup.create.true', gettext_translator('Enabled'))]
112 113
113 114 c_obj.fork_choices = [
114 ('hg.fork.none', translator('Disabled')),
115 ('hg.fork.repository', translator('Enabled'))]
115 ('hg.fork.none', gettext_translator('Disabled')),
116 ('hg.fork.repository', gettext_translator('Enabled'))]
116 117
117 118 c_obj.inherit_default_permission_choices = [
118 ('hg.inherit_default_perms.false', translator('Disabled')),
119 ('hg.inherit_default_perms.true', translator('Enabled'))]
119 ('hg.inherit_default_perms.false', gettext_translator('Disabled')),
120 ('hg.inherit_default_perms.true', gettext_translator('Enabled'))]
120 121
121 122 def get_default_perms(self, object_perms, suffix):
122 123 defaults = {}
123 124 for perm in object_perms:
124 125 # perms
125 126 if perm.permission.permission_name.startswith('repository.'):
126 127 defaults['default_repo_perm' + suffix] = perm.permission.permission_name
127 128
128 129 if perm.permission.permission_name.startswith('group.'):
129 130 defaults['default_group_perm' + suffix] = perm.permission.permission_name
130 131
131 132 if perm.permission.permission_name.startswith('usergroup.'):
132 133 defaults['default_user_group_perm' + suffix] = perm.permission.permission_name
133 134
134 135 # creation of objects
135 136 if perm.permission.permission_name.startswith('hg.create.write_on_repogroup'):
136 137 defaults['default_repo_create_on_write' + suffix] = perm.permission.permission_name
137 138
138 139 elif perm.permission.permission_name.startswith('hg.create.'):
139 140 defaults['default_repo_create' + suffix] = perm.permission.permission_name
140 141
141 142 if perm.permission.permission_name.startswith('hg.fork.'):
142 143 defaults['default_fork_create' + suffix] = perm.permission.permission_name
143 144
144 145 if perm.permission.permission_name.startswith('hg.inherit_default_perms.'):
145 146 defaults['default_inherit_default_permissions' + suffix] = perm.permission.permission_name
146 147
147 148 if perm.permission.permission_name.startswith('hg.repogroup.'):
148 149 defaults['default_repo_group_create' + suffix] = perm.permission.permission_name
149 150
150 151 if perm.permission.permission_name.startswith('hg.usergroup.'):
151 152 defaults['default_user_group_create' + suffix] = perm.permission.permission_name
152 153
153 154 # registration and external account activation
154 155 if perm.permission.permission_name.startswith('hg.register.'):
155 156 defaults['default_register' + suffix] = perm.permission.permission_name
156 157
157 158 if perm.permission.permission_name.startswith('hg.password_reset.'):
158 159 defaults['default_password_reset' + suffix] = perm.permission.permission_name
159 160
160 161 if perm.permission.permission_name.startswith('hg.extern_activate.'):
161 162 defaults['default_extern_activate' + suffix] = perm.permission.permission_name
162 163
163 164 return defaults
164 165
165 166 def _make_new_user_perm(self, user, perm_name):
166 167 log.debug('Creating new user permission:%s', perm_name)
167 168 new = UserToPerm()
168 169 new.user = user
169 170 new.permission = Permission.get_by_key(perm_name)
170 171 return new
171 172
172 173 def _make_new_user_group_perm(self, user_group, perm_name):
173 174 log.debug('Creating new user group permission:%s', perm_name)
174 175 new = UserGroupToPerm()
175 176 new.users_group = user_group
176 177 new.permission = Permission.get_by_key(perm_name)
177 178 return new
178 179
179 180 def _keep_perm(self, perm_name, keep_fields):
180 181 def get_pat(field_name):
181 182 return {
182 183 # global perms
183 184 'default_repo_create': 'hg.create.',
184 185 # special case for create repos on write access to group
185 186 'default_repo_create_on_write': 'hg.create.write_on_repogroup.',
186 187 'default_repo_group_create': 'hg.repogroup.create.',
187 188 'default_user_group_create': 'hg.usergroup.create.',
188 189 'default_fork_create': 'hg.fork.',
189 190 'default_inherit_default_permissions': 'hg.inherit_default_perms.',
190 191
191 192 # application perms
192 193 'default_register': 'hg.register.',
193 194 'default_password_reset': 'hg.password_reset.',
194 195 'default_extern_activate': 'hg.extern_activate.',
195 196
196 197 # object permissions below
197 198 'default_repo_perm': 'repository.',
198 199 'default_group_perm': 'group.',
199 200 'default_user_group_perm': 'usergroup.',
200 201 }[field_name]
201 202 for field in keep_fields:
202 203 pat = get_pat(field)
203 204 if perm_name.startswith(pat):
204 205 return True
205 206 return False
206 207
207 208 def _clear_object_perm(self, object_perms, preserve=None):
208 209 preserve = preserve or []
209 210 _deleted = []
210 211 for perm in object_perms:
211 212 perm_name = perm.permission.permission_name
212 213 if not self._keep_perm(perm_name, keep_fields=preserve):
213 214 _deleted.append(perm_name)
214 215 self.sa.delete(perm)
215 216 return _deleted
216 217
217 218 def _clear_user_perms(self, user_id, preserve=None):
218 219 perms = self.sa.query(UserToPerm)\
219 220 .filter(UserToPerm.user_id == user_id)\
220 221 .all()
221 222 return self._clear_object_perm(perms, preserve=preserve)
222 223
223 224 def _clear_user_group_perms(self, user_group_id, preserve=None):
224 225 perms = self.sa.query(UserGroupToPerm)\
225 226 .filter(UserGroupToPerm.users_group_id == user_group_id)\
226 227 .all()
227 228 return self._clear_object_perm(perms, preserve=preserve)
228 229
229 230 def _set_new_object_perms(self, obj_type, object, form_result, preserve=None):
230 231 # clear current entries, to make this function idempotent
231 232 # it will fix even if we define more permissions or permissions
232 233 # are somehow missing
233 234 preserve = preserve or []
234 235 _global_perms = self.global_perms.copy()
235 236 if obj_type not in ['user', 'user_group']:
236 237 raise ValueError("obj_type must be on of 'user' or 'user_group'")
237 238 if len(_global_perms) != len(Permission.DEFAULT_USER_PERMISSIONS):
238 239 raise Exception('Inconsistent permissions definition')
239 240
240 241 if obj_type == 'user':
241 242 self._clear_user_perms(object.user_id, preserve)
242 243 if obj_type == 'user_group':
243 244 self._clear_user_group_perms(object.users_group_id, preserve)
244 245
245 246 # now kill the keys that we want to preserve from the form.
246 247 for key in preserve:
247 248 del _global_perms[key]
248 249
249 250 for k in _global_perms.copy():
250 251 _global_perms[k] = form_result[k]
251 252
252 253 # at that stage we validate all are passed inside form_result
253 254 for _perm_key, perm_value in _global_perms.items():
254 255 if perm_value is None:
255 256 raise ValueError('Missing permission for %s' % (_perm_key,))
256 257
257 258 if obj_type == 'user':
258 259 p = self._make_new_user_perm(object, perm_value)
259 260 self.sa.add(p)
260 261 if obj_type == 'user_group':
261 262 p = self._make_new_user_group_perm(object, perm_value)
262 263 self.sa.add(p)
263 264
264 265 def _set_new_user_perms(self, user, form_result, preserve=None):
265 266 return self._set_new_object_perms(
266 267 'user', user, form_result, preserve)
267 268
268 269 def _set_new_user_group_perms(self, user_group, form_result, preserve=None):
269 270 return self._set_new_object_perms(
270 271 'user_group', user_group, form_result, preserve)
271 272
272 273 def set_new_user_perms(self, user, form_result):
273 274 # calculate what to preserve from what is given in form_result
274 275 preserve = set(self.global_perms.keys()).difference(set(form_result.keys()))
275 276 return self._set_new_user_perms(user, form_result, preserve)
276 277
277 278 def set_new_user_group_perms(self, user_group, form_result):
278 279 # calculate what to preserve from what is given in form_result
279 280 preserve = set(self.global_perms.keys()).difference(set(form_result.keys()))
280 281 return self._set_new_user_group_perms(user_group, form_result, preserve)
281 282
282 283 def create_permissions(self):
283 284 """
284 285 Create permissions for whole system
285 286 """
286 287 for p in Permission.PERMS:
287 288 if not Permission.get_by_key(p[0]):
288 289 new_perm = Permission()
289 290 new_perm.permission_name = p[0]
290 291 new_perm.permission_longname = p[0] # translation err with p[1]
291 292 self.sa.add(new_perm)
292 293
293 294 def _create_default_object_permission(self, obj_type, obj, obj_perms,
294 295 force=False):
295 296 if obj_type not in ['user', 'user_group']:
296 297 raise ValueError("obj_type must be on of 'user' or 'user_group'")
297 298
298 299 def _get_group(perm_name):
299 300 return '.'.join(perm_name.split('.')[:1])
300 301
301 302 defined_perms_groups = map(
302 303 _get_group, (x.permission.permission_name for x in obj_perms))
303 304 log.debug('GOT ALREADY DEFINED:%s', obj_perms)
304 305
305 306 if force:
306 307 self._clear_object_perm(obj_perms)
307 308 self.sa.commit()
308 309 defined_perms_groups = []
309 310 # for every default permission that needs to be created, we check if
310 311 # it's group is already defined, if it's not we create default perm
311 312 for perm_name in Permission.DEFAULT_USER_PERMISSIONS:
312 313 gr = _get_group(perm_name)
313 314 if gr not in defined_perms_groups:
314 315 log.debug('GR:%s not found, creating permission %s',
315 316 gr, perm_name)
316 317 if obj_type == 'user':
317 318 new_perm = self._make_new_user_perm(obj, perm_name)
318 319 self.sa.add(new_perm)
319 320 if obj_type == 'user_group':
320 321 new_perm = self._make_new_user_group_perm(obj, perm_name)
321 322 self.sa.add(new_perm)
322 323
323 324 def create_default_user_permissions(self, user, force=False):
324 325 """
325 326 Creates only missing default permissions for user, if force is set it
326 327 resets the default permissions for that user
327 328
328 329 :param user:
329 330 :param force:
330 331 """
331 332 user = self._get_user(user)
332 333 obj_perms = UserToPerm.query().filter(UserToPerm.user == user).all()
333 334 return self._create_default_object_permission(
334 335 'user', user, obj_perms, force)
335 336
336 337 def create_default_user_group_permissions(self, user_group, force=False):
337 338 """
338 339 Creates only missing default permissions for user group, if force is set it
339 340 resets the default permissions for that user group
340 341
341 342 :param user_group:
342 343 :param force:
343 344 """
344 345 user_group = self._get_user_group(user_group)
345 346 obj_perms = UserToPerm.query().filter(UserGroupToPerm.users_group == user_group).all()
346 347 return self._create_default_object_permission(
347 348 'user_group', user_group, obj_perms, force)
348 349
349 350 def update_application_permissions(self, form_result):
350 351 if 'perm_user_id' in form_result:
351 352 perm_user = User.get(safe_int(form_result['perm_user_id']))
352 353 else:
353 354 # used mostly to do lookup for default user
354 355 perm_user = User.get_by_username(form_result['perm_user_name'])
355 356
356 357 try:
357 358 # stage 1 set anonymous access
358 359 if perm_user.username == User.DEFAULT_USER:
359 360 perm_user.active = str2bool(form_result['anonymous'])
360 361 self.sa.add(perm_user)
361 362
362 363 # stage 2 reset defaults and set them from form data
363 364 self._set_new_user_perms(perm_user, form_result, preserve=[
364 365 'default_repo_perm',
365 366 'default_group_perm',
366 367 'default_user_group_perm',
367 368
368 369 'default_repo_group_create',
369 370 'default_user_group_create',
370 371 'default_repo_create_on_write',
371 372 'default_repo_create',
372 373 'default_fork_create',
373 374 'default_inherit_default_permissions',])
374 375
375 376 self.sa.commit()
376 377 except (DatabaseError,):
377 378 log.error(traceback.format_exc())
378 379 self.sa.rollback()
379 380 raise
380 381
381 382 def update_user_permissions(self, form_result):
382 383 if 'perm_user_id' in form_result:
383 384 perm_user = User.get(safe_int(form_result['perm_user_id']))
384 385 else:
385 386 # used mostly to do lookup for default user
386 387 perm_user = User.get_by_username(form_result['perm_user_name'])
387 388 try:
388 389 # stage 2 reset defaults and set them from form data
389 390 self._set_new_user_perms(perm_user, form_result, preserve=[
390 391 'default_repo_perm',
391 392 'default_group_perm',
392 393 'default_user_group_perm',
393 394
394 395 'default_register',
395 396 'default_password_reset',
396 397 'default_extern_activate'])
397 398 self.sa.commit()
398 399 except (DatabaseError,):
399 400 log.error(traceback.format_exc())
400 401 self.sa.rollback()
401 402 raise
402 403
403 404 def update_user_group_permissions(self, form_result):
404 405 if 'perm_user_group_id' in form_result:
405 406 perm_user_group = UserGroup.get(safe_int(form_result['perm_user_group_id']))
406 407 else:
407 408 # used mostly to do lookup for default user
408 409 perm_user_group = UserGroup.get_by_group_name(form_result['perm_user_group_name'])
409 410 try:
410 411 # stage 2 reset defaults and set them from form data
411 412 self._set_new_user_group_perms(perm_user_group, form_result, preserve=[
412 413 'default_repo_perm',
413 414 'default_group_perm',
414 415 'default_user_group_perm',
415 416
416 417 'default_register',
417 418 'default_password_reset',
418 419 'default_extern_activate'])
419 420 self.sa.commit()
420 421 except (DatabaseError,):
421 422 log.error(traceback.format_exc())
422 423 self.sa.rollback()
423 424 raise
424 425
425 426 def update_object_permissions(self, form_result):
426 427 if 'perm_user_id' in form_result:
427 428 perm_user = User.get(safe_int(form_result['perm_user_id']))
428 429 else:
429 430 # used mostly to do lookup for default user
430 431 perm_user = User.get_by_username(form_result['perm_user_name'])
431 432 try:
432 433
433 434 # stage 2 reset defaults and set them from form data
434 435 self._set_new_user_perms(perm_user, form_result, preserve=[
435 436 'default_repo_group_create',
436 437 'default_user_group_create',
437 438 'default_repo_create_on_write',
438 439 'default_repo_create',
439 440 'default_fork_create',
440 441 'default_inherit_default_permissions',
441 442
442 443 'default_register',
443 444 'default_password_reset',
444 445 'default_extern_activate'])
445 446
446 447 # overwrite default repo permissions
447 448 if form_result['overwrite_default_repo']:
448 449 _def_name = form_result['default_repo_perm'].split('repository.')[-1]
449 450 _def = Permission.get_by_key('repository.' + _def_name)
450 451 for r2p in self.sa.query(UserRepoToPerm)\
451 452 .filter(UserRepoToPerm.user == perm_user)\
452 453 .all():
453 454 # don't reset PRIVATE repositories
454 455 if not r2p.repository.private:
455 456 r2p.permission = _def
456 457 self.sa.add(r2p)
457 458
458 459 # overwrite default repo group permissions
459 460 if form_result['overwrite_default_group']:
460 461 _def_name = form_result['default_group_perm'].split('group.')[-1]
461 462 _def = Permission.get_by_key('group.' + _def_name)
462 463 for g2p in self.sa.query(UserRepoGroupToPerm)\
463 464 .filter(UserRepoGroupToPerm.user == perm_user)\
464 465 .all():
465 466 g2p.permission = _def
466 467 self.sa.add(g2p)
467 468
468 469 # overwrite default user group permissions
469 470 if form_result['overwrite_default_user_group']:
470 471 _def_name = form_result['default_user_group_perm'].split('usergroup.')[-1]
471 472 # user groups
472 473 _def = Permission.get_by_key('usergroup.' + _def_name)
473 474 for g2p in self.sa.query(UserUserGroupToPerm)\
474 475 .filter(UserUserGroupToPerm.user == perm_user)\
475 476 .all():
476 477 g2p.permission = _def
477 478 self.sa.add(g2p)
478 479 self.sa.commit()
479 480 except (DatabaseError,):
480 481 log.exception('Failed to set default object permissions')
481 482 self.sa.rollback()
482 483 raise
@@ -1,42 +1,43 b''
1 1 [aliases]
2 2 test = pytest
3 3
4 4 [egg_info]
5 5 tag_build =
6 6 tag_svn_revision = false
7 7
8 8 # Babel configuration
9 9 [compile_catalog]
10 10 domain = rhodecode
11 11 directory = rhodecode/i18n
12 12 statistics = true
13 13
14 14 [extract_messages]
15 15 add_comments = TRANSLATORS:
16 16 output_file = rhodecode/i18n/rhodecode.pot
17 17 msgid-bugs-address = marcin@rhodecode.com
18 18 copyright-holder = RhodeCode GmbH
19 19 no-wrap = true
20 20 keywords =
21 21 lazy_ugettext
22 22 _ngettext
23 23 _gettext
24 gettext_translator
24 25
25 26 [init_catalog]
26 27 domain = rhodecode
27 28 input_file = rhodecode/i18n/rhodecode.pot
28 29 output_dir = rhodecode/i18n
29 30
30 31 [update_catalog]
31 32 domain = rhodecode
32 33 input_file = rhodecode/i18n/rhodecode.pot
33 34 output_dir = rhodecode/i18n
34 35 previous = true
35 36
36 37 [build_sphinx]
37 38 source-dir = docs/
38 39 build-dir = docs/_build
39 40 all_files = 1
40 41
41 42 [upload_sphinx]
42 43 upload-dir = docs/_build/html
General Comments 0
You need to be logged in to leave comments. Login now