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