##// END OF EJS Templates
repo-group-model: add flag to return proper object along the exported names.
marcink -
r1151:8ddcff9d default
parent child Browse files
Show More
@@ -1,705 +1,710 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 """
22 """
23 repo group model for RhodeCode
23 repo group model for RhodeCode
24 """
24 """
25
25
26 import os
26 import os
27 import datetime
27 import datetime
28 import itertools
28 import itertools
29 import logging
29 import logging
30 import shutil
30 import shutil
31 import traceback
31 import traceback
32 import string
32 import string
33
33
34 from zope.cachedescriptors.property import Lazy as LazyProperty
34 from zope.cachedescriptors.property import Lazy as LazyProperty
35
35
36 from rhodecode import events
36 from rhodecode import events
37 from rhodecode.model import BaseModel
37 from rhodecode.model import BaseModel
38 from rhodecode.model.db import (
38 from rhodecode.model.db import (
39 RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm,
39 RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm,
40 UserGroup, Repository)
40 UserGroup, Repository)
41 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
41 from rhodecode.model.settings import VcsSettingsModel, SettingsModel
42 from rhodecode.lib.caching_query import FromCache
42 from rhodecode.lib.caching_query import FromCache
43 from rhodecode.lib.utils2 import action_logger_generic
43 from rhodecode.lib.utils2 import action_logger_generic
44
44
45 log = logging.getLogger(__name__)
45 log = logging.getLogger(__name__)
46
46
47
47
48 class RepoGroupModel(BaseModel):
48 class RepoGroupModel(BaseModel):
49
49
50 cls = RepoGroup
50 cls = RepoGroup
51 PERSONAL_GROUP_DESC = 'personal repo group of user `%(username)s`'
51 PERSONAL_GROUP_DESC = 'personal repo group of user `%(username)s`'
52 PERSONAL_GROUP_PATTERN = '${username}' # default
52 PERSONAL_GROUP_PATTERN = '${username}' # default
53
53
54 def _get_user_group(self, users_group):
54 def _get_user_group(self, users_group):
55 return self._get_instance(UserGroup, users_group,
55 return self._get_instance(UserGroup, users_group,
56 callback=UserGroup.get_by_group_name)
56 callback=UserGroup.get_by_group_name)
57
57
58 def _get_repo_group(self, repo_group):
58 def _get_repo_group(self, repo_group):
59 return self._get_instance(RepoGroup, repo_group,
59 return self._get_instance(RepoGroup, repo_group,
60 callback=RepoGroup.get_by_group_name)
60 callback=RepoGroup.get_by_group_name)
61
61
62 @LazyProperty
62 @LazyProperty
63 def repos_path(self):
63 def repos_path(self):
64 """
64 """
65 Gets the repositories root path from database
65 Gets the repositories root path from database
66 """
66 """
67
67
68 settings_model = VcsSettingsModel(sa=self.sa)
68 settings_model = VcsSettingsModel(sa=self.sa)
69 return settings_model.get_repos_location()
69 return settings_model.get_repos_location()
70
70
71 def get_by_group_name(self, repo_group_name, cache=None):
71 def get_by_group_name(self, repo_group_name, cache=None):
72 repo = self.sa.query(RepoGroup) \
72 repo = self.sa.query(RepoGroup) \
73 .filter(RepoGroup.group_name == repo_group_name)
73 .filter(RepoGroup.group_name == repo_group_name)
74
74
75 if cache:
75 if cache:
76 repo = repo.options(FromCache(
76 repo = repo.options(FromCache(
77 "sql_cache_short", "get_repo_group_%s" % repo_group_name))
77 "sql_cache_short", "get_repo_group_%s" % repo_group_name))
78 return repo.scalar()
78 return repo.scalar()
79
79
80 def get_default_create_personal_repo_group(self):
80 def get_default_create_personal_repo_group(self):
81 value = SettingsModel().get_setting_by_name(
81 value = SettingsModel().get_setting_by_name(
82 'create_personal_repo_group')
82 'create_personal_repo_group')
83 return value.app_settings_value if value else None or False
83 return value.app_settings_value if value else None or False
84
84
85 def get_personal_group_name_pattern(self):
85 def get_personal_group_name_pattern(self):
86 value = SettingsModel().get_setting_by_name(
86 value = SettingsModel().get_setting_by_name(
87 'personal_repo_group_pattern')
87 'personal_repo_group_pattern')
88 val = value.app_settings_value if value else None
88 val = value.app_settings_value if value else None
89 group_template = val or self.PERSONAL_GROUP_PATTERN
89 group_template = val or self.PERSONAL_GROUP_PATTERN
90
90
91 group_template = group_template.lstrip('/')
91 group_template = group_template.lstrip('/')
92 return group_template
92 return group_template
93
93
94 def get_personal_group_name(self, user):
94 def get_personal_group_name(self, user):
95 template = self.get_personal_group_name_pattern()
95 template = self.get_personal_group_name_pattern()
96 return string.Template(template).safe_substitute(
96 return string.Template(template).safe_substitute(
97 username=user.username,
97 username=user.username,
98 user_id=user.user_id,
98 user_id=user.user_id,
99 )
99 )
100
100
101 def create_personal_repo_group(self, user, commit_early=True):
101 def create_personal_repo_group(self, user, commit_early=True):
102 desc = self.PERSONAL_GROUP_DESC % {'username': user.username}
102 desc = self.PERSONAL_GROUP_DESC % {'username': user.username}
103 personal_repo_group_name = self.get_personal_group_name(user)
103 personal_repo_group_name = self.get_personal_group_name(user)
104
104
105 # create a new one
105 # create a new one
106 RepoGroupModel().create(
106 RepoGroupModel().create(
107 group_name=personal_repo_group_name,
107 group_name=personal_repo_group_name,
108 group_description=desc,
108 group_description=desc,
109 owner=user.username,
109 owner=user.username,
110 personal=True,
110 personal=True,
111 commit_early=commit_early)
111 commit_early=commit_early)
112
112
113 def _create_default_perms(self, new_group):
113 def _create_default_perms(self, new_group):
114 # create default permission
114 # create default permission
115 default_perm = 'group.read'
115 default_perm = 'group.read'
116 def_user = User.get_default_user()
116 def_user = User.get_default_user()
117 for p in def_user.user_perms:
117 for p in def_user.user_perms:
118 if p.permission.permission_name.startswith('group.'):
118 if p.permission.permission_name.startswith('group.'):
119 default_perm = p.permission.permission_name
119 default_perm = p.permission.permission_name
120 break
120 break
121
121
122 repo_group_to_perm = UserRepoGroupToPerm()
122 repo_group_to_perm = UserRepoGroupToPerm()
123 repo_group_to_perm.permission = Permission.get_by_key(default_perm)
123 repo_group_to_perm.permission = Permission.get_by_key(default_perm)
124
124
125 repo_group_to_perm.group = new_group
125 repo_group_to_perm.group = new_group
126 repo_group_to_perm.user_id = def_user.user_id
126 repo_group_to_perm.user_id = def_user.user_id
127 return repo_group_to_perm
127 return repo_group_to_perm
128
128
129 def _get_group_name_and_parent(self, group_name_full, repo_in_path=False):
129 def _get_group_name_and_parent(self, group_name_full, repo_in_path=False,
130 get_object=False):
130 """
131 """
131 Get's the group name and a parent group name from given group name.
132 Get's the group name and a parent group name from given group name.
132 If repo_in_path is set to truth, we asume the full path also includes
133 If repo_in_path is set to truth, we asume the full path also includes
133 repo name, in such case we clean the last element.
134 repo name, in such case we clean the last element.
134
135
135 :param group_name_full:
136 :param group_name_full:
136 """
137 """
137 split_paths = 1
138 split_paths = 1
138 if repo_in_path:
139 if repo_in_path:
139 split_paths = 2
140 split_paths = 2
140 _parts = group_name_full.rsplit(RepoGroup.url_sep(), split_paths)
141 _parts = group_name_full.rsplit(RepoGroup.url_sep(), split_paths)
141
142
142 if repo_in_path and len(_parts) > 1:
143 if repo_in_path and len(_parts) > 1:
143 # such case last element is the repo_name
144 # such case last element is the repo_name
144 _parts.pop(-1)
145 _parts.pop(-1)
145 group_name_cleaned = _parts[-1] # just the group name
146 group_name_cleaned = _parts[-1] # just the group name
146 parent_repo_group_name = None
147 parent_repo_group_name = None
147
148
148 if len(_parts) > 1:
149 if len(_parts) > 1:
149 parent_repo_group_name = _parts[0]
150 parent_repo_group_name = _parts[0]
150
151
152 parent_group = None
151 if parent_repo_group_name:
153 if parent_repo_group_name:
152 parent_group = RepoGroup.get_by_group_name(parent_repo_group_name)
154 parent_group = RepoGroup.get_by_group_name(parent_repo_group_name)
153
155
156 if get_object:
157 return group_name_cleaned, parent_repo_group_name, parent_group
158
154 return group_name_cleaned, parent_repo_group_name
159 return group_name_cleaned, parent_repo_group_name
155
160
156 def check_exist_filesystem(self, group_name, exc_on_failure=True):
161 def check_exist_filesystem(self, group_name, exc_on_failure=True):
157 create_path = os.path.join(self.repos_path, group_name)
162 create_path = os.path.join(self.repos_path, group_name)
158 log.debug('creating new group in %s', create_path)
163 log.debug('creating new group in %s', create_path)
159
164
160 if os.path.isdir(create_path):
165 if os.path.isdir(create_path):
161 if exc_on_failure:
166 if exc_on_failure:
162 raise Exception('That directory already exists !')
167 raise Exception('That directory already exists !')
163 return False
168 return False
164 return True
169 return True
165
170
166 def _create_group(self, group_name):
171 def _create_group(self, group_name):
167 """
172 """
168 makes repository group on filesystem
173 makes repository group on filesystem
169
174
170 :param repo_name:
175 :param repo_name:
171 :param parent_id:
176 :param parent_id:
172 """
177 """
173
178
174 self.check_exist_filesystem(group_name)
179 self.check_exist_filesystem(group_name)
175 create_path = os.path.join(self.repos_path, group_name)
180 create_path = os.path.join(self.repos_path, group_name)
176 log.debug('creating new group in %s', create_path)
181 log.debug('creating new group in %s', create_path)
177 os.makedirs(create_path, mode=0755)
182 os.makedirs(create_path, mode=0755)
178 log.debug('created group in %s', create_path)
183 log.debug('created group in %s', create_path)
179
184
180 def _rename_group(self, old, new):
185 def _rename_group(self, old, new):
181 """
186 """
182 Renames a group on filesystem
187 Renames a group on filesystem
183
188
184 :param group_name:
189 :param group_name:
185 """
190 """
186
191
187 if old == new:
192 if old == new:
188 log.debug('skipping group rename')
193 log.debug('skipping group rename')
189 return
194 return
190
195
191 log.debug('renaming repository group from %s to %s', old, new)
196 log.debug('renaming repository group from %s to %s', old, new)
192
197
193 old_path = os.path.join(self.repos_path, old)
198 old_path = os.path.join(self.repos_path, old)
194 new_path = os.path.join(self.repos_path, new)
199 new_path = os.path.join(self.repos_path, new)
195
200
196 log.debug('renaming repos paths from %s to %s', old_path, new_path)
201 log.debug('renaming repos paths from %s to %s', old_path, new_path)
197
202
198 if os.path.isdir(new_path):
203 if os.path.isdir(new_path):
199 raise Exception('Was trying to rename to already '
204 raise Exception('Was trying to rename to already '
200 'existing dir %s' % new_path)
205 'existing dir %s' % new_path)
201 shutil.move(old_path, new_path)
206 shutil.move(old_path, new_path)
202
207
203 def _delete_filesystem_group(self, group, force_delete=False):
208 def _delete_filesystem_group(self, group, force_delete=False):
204 """
209 """
205 Deletes a group from a filesystem
210 Deletes a group from a filesystem
206
211
207 :param group: instance of group from database
212 :param group: instance of group from database
208 :param force_delete: use shutil rmtree to remove all objects
213 :param force_delete: use shutil rmtree to remove all objects
209 """
214 """
210 paths = group.full_path.split(RepoGroup.url_sep())
215 paths = group.full_path.split(RepoGroup.url_sep())
211 paths = os.sep.join(paths)
216 paths = os.sep.join(paths)
212
217
213 rm_path = os.path.join(self.repos_path, paths)
218 rm_path = os.path.join(self.repos_path, paths)
214 log.info("Removing group %s", rm_path)
219 log.info("Removing group %s", rm_path)
215 # delete only if that path really exists
220 # delete only if that path really exists
216 if os.path.isdir(rm_path):
221 if os.path.isdir(rm_path):
217 if force_delete:
222 if force_delete:
218 shutil.rmtree(rm_path)
223 shutil.rmtree(rm_path)
219 else:
224 else:
220 # archive that group`
225 # archive that group`
221 _now = datetime.datetime.now()
226 _now = datetime.datetime.now()
222 _ms = str(_now.microsecond).rjust(6, '0')
227 _ms = str(_now.microsecond).rjust(6, '0')
223 _d = 'rm__%s_GROUP_%s' % (
228 _d = 'rm__%s_GROUP_%s' % (
224 _now.strftime('%Y%m%d_%H%M%S_' + _ms), group.name)
229 _now.strftime('%Y%m%d_%H%M%S_' + _ms), group.name)
225 shutil.move(rm_path, os.path.join(self.repos_path, _d))
230 shutil.move(rm_path, os.path.join(self.repos_path, _d))
226
231
227 def create(self, group_name, group_description, owner, just_db=False,
232 def create(self, group_name, group_description, owner, just_db=False,
228 copy_permissions=False, personal=None, commit_early=True):
233 copy_permissions=False, personal=None, commit_early=True):
229
234
230 (group_name_cleaned,
235 (group_name_cleaned,
231 parent_group_name) = RepoGroupModel()._get_group_name_and_parent(group_name)
236 parent_group_name) = RepoGroupModel()._get_group_name_and_parent(group_name)
232
237
233 parent_group = None
238 parent_group = None
234 if parent_group_name:
239 if parent_group_name:
235 parent_group = self._get_repo_group(parent_group_name)
240 parent_group = self._get_repo_group(parent_group_name)
236 if not parent_group:
241 if not parent_group:
237 # we tried to create a nested group, but the parent is not
242 # we tried to create a nested group, but the parent is not
238 # existing
243 # existing
239 raise ValueError(
244 raise ValueError(
240 'Parent group `%s` given in `%s` group name '
245 'Parent group `%s` given in `%s` group name '
241 'is not yet existing.' % (parent_group_name, group_name))
246 'is not yet existing.' % (parent_group_name, group_name))
242
247
243 # because we are doing a cleanup, we need to check if such directory
248 # because we are doing a cleanup, we need to check if such directory
244 # already exists. If we don't do that we can accidentally delete
249 # already exists. If we don't do that we can accidentally delete
245 # existing directory via cleanup that can cause data issues, since
250 # existing directory via cleanup that can cause data issues, since
246 # delete does a folder rename to special syntax later cleanup
251 # delete does a folder rename to special syntax later cleanup
247 # functions can delete this
252 # functions can delete this
248 cleanup_group = self.check_exist_filesystem(group_name,
253 cleanup_group = self.check_exist_filesystem(group_name,
249 exc_on_failure=False)
254 exc_on_failure=False)
250 try:
255 try:
251 user = self._get_user(owner)
256 user = self._get_user(owner)
252 new_repo_group = RepoGroup()
257 new_repo_group = RepoGroup()
253 new_repo_group.user = user
258 new_repo_group.user = user
254 new_repo_group.group_description = group_description or group_name
259 new_repo_group.group_description = group_description or group_name
255 new_repo_group.parent_group = parent_group
260 new_repo_group.parent_group = parent_group
256 new_repo_group.group_name = group_name
261 new_repo_group.group_name = group_name
257 new_repo_group.personal = personal
262 new_repo_group.personal = personal
258
263
259 self.sa.add(new_repo_group)
264 self.sa.add(new_repo_group)
260
265
261 # create an ADMIN permission for owner except if we're super admin,
266 # create an ADMIN permission for owner except if we're super admin,
262 # later owner should go into the owner field of groups
267 # later owner should go into the owner field of groups
263 if not user.is_admin:
268 if not user.is_admin:
264 self.grant_user_permission(repo_group=new_repo_group,
269 self.grant_user_permission(repo_group=new_repo_group,
265 user=owner, perm='group.admin')
270 user=owner, perm='group.admin')
266
271
267 if parent_group and copy_permissions:
272 if parent_group and copy_permissions:
268 # copy permissions from parent
273 # copy permissions from parent
269 user_perms = UserRepoGroupToPerm.query() \
274 user_perms = UserRepoGroupToPerm.query() \
270 .filter(UserRepoGroupToPerm.group == parent_group).all()
275 .filter(UserRepoGroupToPerm.group == parent_group).all()
271
276
272 group_perms = UserGroupRepoGroupToPerm.query() \
277 group_perms = UserGroupRepoGroupToPerm.query() \
273 .filter(UserGroupRepoGroupToPerm.group == parent_group).all()
278 .filter(UserGroupRepoGroupToPerm.group == parent_group).all()
274
279
275 for perm in user_perms:
280 for perm in user_perms:
276 # don't copy over the permission for user who is creating
281 # don't copy over the permission for user who is creating
277 # this group, if he is not super admin he get's admin
282 # this group, if he is not super admin he get's admin
278 # permission set above
283 # permission set above
279 if perm.user != user or user.is_admin:
284 if perm.user != user or user.is_admin:
280 UserRepoGroupToPerm.create(
285 UserRepoGroupToPerm.create(
281 perm.user, new_repo_group, perm.permission)
286 perm.user, new_repo_group, perm.permission)
282
287
283 for perm in group_perms:
288 for perm in group_perms:
284 UserGroupRepoGroupToPerm.create(
289 UserGroupRepoGroupToPerm.create(
285 perm.users_group, new_repo_group, perm.permission)
290 perm.users_group, new_repo_group, perm.permission)
286 else:
291 else:
287 perm_obj = self._create_default_perms(new_repo_group)
292 perm_obj = self._create_default_perms(new_repo_group)
288 self.sa.add(perm_obj)
293 self.sa.add(perm_obj)
289
294
290 # now commit the changes, earlier so we are sure everything is in
295 # now commit the changes, earlier so we are sure everything is in
291 # the database.
296 # the database.
292 if commit_early:
297 if commit_early:
293 self.sa.commit()
298 self.sa.commit()
294 if not just_db:
299 if not just_db:
295 self._create_group(new_repo_group.group_name)
300 self._create_group(new_repo_group.group_name)
296
301
297 # trigger the post hook
302 # trigger the post hook
298 from rhodecode.lib.hooks_base import log_create_repository_group
303 from rhodecode.lib.hooks_base import log_create_repository_group
299 repo_group = RepoGroup.get_by_group_name(group_name)
304 repo_group = RepoGroup.get_by_group_name(group_name)
300 log_create_repository_group(
305 log_create_repository_group(
301 created_by=user.username, **repo_group.get_dict())
306 created_by=user.username, **repo_group.get_dict())
302
307
303 # Trigger create event.
308 # Trigger create event.
304 events.trigger(events.RepoGroupCreateEvent(repo_group))
309 events.trigger(events.RepoGroupCreateEvent(repo_group))
305
310
306 return new_repo_group
311 return new_repo_group
307 except Exception:
312 except Exception:
308 self.sa.rollback()
313 self.sa.rollback()
309 log.exception('Exception occurred when creating repository group, '
314 log.exception('Exception occurred when creating repository group, '
310 'doing cleanup...')
315 'doing cleanup...')
311 # rollback things manually !
316 # rollback things manually !
312 repo_group = RepoGroup.get_by_group_name(group_name)
317 repo_group = RepoGroup.get_by_group_name(group_name)
313 if repo_group:
318 if repo_group:
314 RepoGroup.delete(repo_group.group_id)
319 RepoGroup.delete(repo_group.group_id)
315 self.sa.commit()
320 self.sa.commit()
316 if cleanup_group:
321 if cleanup_group:
317 RepoGroupModel()._delete_filesystem_group(repo_group)
322 RepoGroupModel()._delete_filesystem_group(repo_group)
318 raise
323 raise
319
324
320 def update_permissions(
325 def update_permissions(
321 self, repo_group, perm_additions=None, perm_updates=None,
326 self, repo_group, perm_additions=None, perm_updates=None,
322 perm_deletions=None, recursive=None, check_perms=True,
327 perm_deletions=None, recursive=None, check_perms=True,
323 cur_user=None):
328 cur_user=None):
324 from rhodecode.model.repo import RepoModel
329 from rhodecode.model.repo import RepoModel
325 from rhodecode.lib.auth import HasUserGroupPermissionAny
330 from rhodecode.lib.auth import HasUserGroupPermissionAny
326
331
327 if not perm_additions:
332 if not perm_additions:
328 perm_additions = []
333 perm_additions = []
329 if not perm_updates:
334 if not perm_updates:
330 perm_updates = []
335 perm_updates = []
331 if not perm_deletions:
336 if not perm_deletions:
332 perm_deletions = []
337 perm_deletions = []
333
338
334 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
339 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
335
340
336 def _set_perm_user(obj, user, perm):
341 def _set_perm_user(obj, user, perm):
337 if isinstance(obj, RepoGroup):
342 if isinstance(obj, RepoGroup):
338 self.grant_user_permission(
343 self.grant_user_permission(
339 repo_group=obj, user=user, perm=perm)
344 repo_group=obj, user=user, perm=perm)
340 elif isinstance(obj, Repository):
345 elif isinstance(obj, Repository):
341 # private repos will not allow to change the default
346 # private repos will not allow to change the default
342 # permissions using recursive mode
347 # permissions using recursive mode
343 if obj.private and user == User.DEFAULT_USER:
348 if obj.private and user == User.DEFAULT_USER:
344 return
349 return
345
350
346 # we set group permission but we have to switch to repo
351 # we set group permission but we have to switch to repo
347 # permission
352 # permission
348 perm = perm.replace('group.', 'repository.')
353 perm = perm.replace('group.', 'repository.')
349 RepoModel().grant_user_permission(
354 RepoModel().grant_user_permission(
350 repo=obj, user=user, perm=perm)
355 repo=obj, user=user, perm=perm)
351
356
352 def _set_perm_group(obj, users_group, perm):
357 def _set_perm_group(obj, users_group, perm):
353 if isinstance(obj, RepoGroup):
358 if isinstance(obj, RepoGroup):
354 self.grant_user_group_permission(
359 self.grant_user_group_permission(
355 repo_group=obj, group_name=users_group, perm=perm)
360 repo_group=obj, group_name=users_group, perm=perm)
356 elif isinstance(obj, Repository):
361 elif isinstance(obj, Repository):
357 # we set group permission but we have to switch to repo
362 # we set group permission but we have to switch to repo
358 # permission
363 # permission
359 perm = perm.replace('group.', 'repository.')
364 perm = perm.replace('group.', 'repository.')
360 RepoModel().grant_user_group_permission(
365 RepoModel().grant_user_group_permission(
361 repo=obj, group_name=users_group, perm=perm)
366 repo=obj, group_name=users_group, perm=perm)
362
367
363 def _revoke_perm_user(obj, user):
368 def _revoke_perm_user(obj, user):
364 if isinstance(obj, RepoGroup):
369 if isinstance(obj, RepoGroup):
365 self.revoke_user_permission(repo_group=obj, user=user)
370 self.revoke_user_permission(repo_group=obj, user=user)
366 elif isinstance(obj, Repository):
371 elif isinstance(obj, Repository):
367 RepoModel().revoke_user_permission(repo=obj, user=user)
372 RepoModel().revoke_user_permission(repo=obj, user=user)
368
373
369 def _revoke_perm_group(obj, user_group):
374 def _revoke_perm_group(obj, user_group):
370 if isinstance(obj, RepoGroup):
375 if isinstance(obj, RepoGroup):
371 self.revoke_user_group_permission(
376 self.revoke_user_group_permission(
372 repo_group=obj, group_name=user_group)
377 repo_group=obj, group_name=user_group)
373 elif isinstance(obj, Repository):
378 elif isinstance(obj, Repository):
374 RepoModel().revoke_user_group_permission(
379 RepoModel().revoke_user_group_permission(
375 repo=obj, group_name=user_group)
380 repo=obj, group_name=user_group)
376
381
377 # start updates
382 # start updates
378 updates = []
383 updates = []
379 log.debug('Now updating permissions for %s in recursive mode:%s',
384 log.debug('Now updating permissions for %s in recursive mode:%s',
380 repo_group, recursive)
385 repo_group, recursive)
381
386
382 # initialize check function, we'll call that multiple times
387 # initialize check function, we'll call that multiple times
383 has_group_perm = HasUserGroupPermissionAny(*req_perms)
388 has_group_perm = HasUserGroupPermissionAny(*req_perms)
384
389
385 for obj in repo_group.recursive_groups_and_repos():
390 for obj in repo_group.recursive_groups_and_repos():
386 # iterated obj is an instance of a repos group or repository in
391 # iterated obj is an instance of a repos group or repository in
387 # that group, recursive option can be: none, repos, groups, all
392 # that group, recursive option can be: none, repos, groups, all
388 if recursive == 'all':
393 if recursive == 'all':
389 obj = obj
394 obj = obj
390 elif recursive == 'repos':
395 elif recursive == 'repos':
391 # skip groups, other than this one
396 # skip groups, other than this one
392 if isinstance(obj, RepoGroup) and not obj == repo_group:
397 if isinstance(obj, RepoGroup) and not obj == repo_group:
393 continue
398 continue
394 elif recursive == 'groups':
399 elif recursive == 'groups':
395 # skip repos
400 # skip repos
396 if isinstance(obj, Repository):
401 if isinstance(obj, Repository):
397 continue
402 continue
398 else: # recursive == 'none':
403 else: # recursive == 'none':
399 # DEFAULT option - don't apply to iterated objects
404 # DEFAULT option - don't apply to iterated objects
400 # also we do a break at the end of this loop. if we are not
405 # also we do a break at the end of this loop. if we are not
401 # in recursive mode
406 # in recursive mode
402 obj = repo_group
407 obj = repo_group
403
408
404 # update permissions
409 # update permissions
405 for member_id, perm, member_type in perm_updates:
410 for member_id, perm, member_type in perm_updates:
406 member_id = int(member_id)
411 member_id = int(member_id)
407 if member_type == 'user':
412 if member_type == 'user':
408 # this updates also current one if found
413 # this updates also current one if found
409 _set_perm_user(obj, user=member_id, perm=perm)
414 _set_perm_user(obj, user=member_id, perm=perm)
410 else: # set for user group
415 else: # set for user group
411 member_name = UserGroup.get(member_id).users_group_name
416 member_name = UserGroup.get(member_id).users_group_name
412 if not check_perms or has_group_perm(member_name,
417 if not check_perms or has_group_perm(member_name,
413 user=cur_user):
418 user=cur_user):
414 _set_perm_group(obj, users_group=member_id, perm=perm)
419 _set_perm_group(obj, users_group=member_id, perm=perm)
415
420
416 # set new permissions
421 # set new permissions
417 for member_id, perm, member_type in perm_additions:
422 for member_id, perm, member_type in perm_additions:
418 member_id = int(member_id)
423 member_id = int(member_id)
419 if member_type == 'user':
424 if member_type == 'user':
420 _set_perm_user(obj, user=member_id, perm=perm)
425 _set_perm_user(obj, user=member_id, perm=perm)
421 else: # set for user group
426 else: # set for user group
422 # check if we have permissions to alter this usergroup
427 # check if we have permissions to alter this usergroup
423 member_name = UserGroup.get(member_id).users_group_name
428 member_name = UserGroup.get(member_id).users_group_name
424 if not check_perms or has_group_perm(member_name,
429 if not check_perms or has_group_perm(member_name,
425 user=cur_user):
430 user=cur_user):
426 _set_perm_group(obj, users_group=member_id, perm=perm)
431 _set_perm_group(obj, users_group=member_id, perm=perm)
427
432
428 # delete permissions
433 # delete permissions
429 for member_id, perm, member_type in perm_deletions:
434 for member_id, perm, member_type in perm_deletions:
430 member_id = int(member_id)
435 member_id = int(member_id)
431 if member_type == 'user':
436 if member_type == 'user':
432 _revoke_perm_user(obj, user=member_id)
437 _revoke_perm_user(obj, user=member_id)
433 else: # set for user group
438 else: # set for user group
434 # check if we have permissions to alter this usergroup
439 # check if we have permissions to alter this usergroup
435 member_name = UserGroup.get(member_id).users_group_name
440 member_name = UserGroup.get(member_id).users_group_name
436 if not check_perms or has_group_perm(member_name,
441 if not check_perms or has_group_perm(member_name,
437 user=cur_user):
442 user=cur_user):
438 _revoke_perm_group(obj, user_group=member_id)
443 _revoke_perm_group(obj, user_group=member_id)
439
444
440 updates.append(obj)
445 updates.append(obj)
441 # if it's not recursive call for all,repos,groups
446 # if it's not recursive call for all,repos,groups
442 # break the loop and don't proceed with other changes
447 # break the loop and don't proceed with other changes
443 if recursive not in ['all', 'repos', 'groups']:
448 if recursive not in ['all', 'repos', 'groups']:
444 break
449 break
445
450
446 return updates
451 return updates
447
452
448 def update(self, repo_group, form_data):
453 def update(self, repo_group, form_data):
449 try:
454 try:
450 repo_group = self._get_repo_group(repo_group)
455 repo_group = self._get_repo_group(repo_group)
451 old_path = repo_group.full_path
456 old_path = repo_group.full_path
452
457
453 # change properties
458 # change properties
454 if 'group_description' in form_data:
459 if 'group_description' in form_data:
455 repo_group.group_description = form_data['group_description']
460 repo_group.group_description = form_data['group_description']
456
461
457 if 'enable_locking' in form_data:
462 if 'enable_locking' in form_data:
458 repo_group.enable_locking = form_data['enable_locking']
463 repo_group.enable_locking = form_data['enable_locking']
459
464
460 if 'group_parent_id' in form_data:
465 if 'group_parent_id' in form_data:
461 parent_group = (
466 parent_group = (
462 self._get_repo_group(form_data['group_parent_id']))
467 self._get_repo_group(form_data['group_parent_id']))
463 repo_group.group_parent_id = (
468 repo_group.group_parent_id = (
464 parent_group.group_id if parent_group else None)
469 parent_group.group_id if parent_group else None)
465 repo_group.parent_group = parent_group
470 repo_group.parent_group = parent_group
466
471
467 # mikhail: to update the full_path, we have to explicitly
472 # mikhail: to update the full_path, we have to explicitly
468 # update group_name
473 # update group_name
469 group_name = form_data.get('group_name', repo_group.name)
474 group_name = form_data.get('group_name', repo_group.name)
470 repo_group.group_name = repo_group.get_new_name(group_name)
475 repo_group.group_name = repo_group.get_new_name(group_name)
471
476
472 new_path = repo_group.full_path
477 new_path = repo_group.full_path
473
478
474 if 'user' in form_data:
479 if 'user' in form_data:
475 repo_group.user = User.get_by_username(form_data['user'])
480 repo_group.user = User.get_by_username(form_data['user'])
476
481
477 self.sa.add(repo_group)
482 self.sa.add(repo_group)
478
483
479 # iterate over all members of this groups and do fixes
484 # iterate over all members of this groups and do fixes
480 # set locking if given
485 # set locking if given
481 # if obj is a repoGroup also fix the name of the group according
486 # if obj is a repoGroup also fix the name of the group according
482 # to the parent
487 # to the parent
483 # if obj is a Repo fix it's name
488 # if obj is a Repo fix it's name
484 # this can be potentially heavy operation
489 # this can be potentially heavy operation
485 for obj in repo_group.recursive_groups_and_repos():
490 for obj in repo_group.recursive_groups_and_repos():
486 # set the value from it's parent
491 # set the value from it's parent
487 obj.enable_locking = repo_group.enable_locking
492 obj.enable_locking = repo_group.enable_locking
488 if isinstance(obj, RepoGroup):
493 if isinstance(obj, RepoGroup):
489 new_name = obj.get_new_name(obj.name)
494 new_name = obj.get_new_name(obj.name)
490 log.debug('Fixing group %s to new name %s',
495 log.debug('Fixing group %s to new name %s',
491 obj.group_name, new_name)
496 obj.group_name, new_name)
492 obj.group_name = new_name
497 obj.group_name = new_name
493 elif isinstance(obj, Repository):
498 elif isinstance(obj, Repository):
494 # we need to get all repositories from this new group and
499 # we need to get all repositories from this new group and
495 # rename them accordingly to new group path
500 # rename them accordingly to new group path
496 new_name = obj.get_new_name(obj.just_name)
501 new_name = obj.get_new_name(obj.just_name)
497 log.debug('Fixing repo %s to new name %s',
502 log.debug('Fixing repo %s to new name %s',
498 obj.repo_name, new_name)
503 obj.repo_name, new_name)
499 obj.repo_name = new_name
504 obj.repo_name = new_name
500 self.sa.add(obj)
505 self.sa.add(obj)
501
506
502 self._rename_group(old_path, new_path)
507 self._rename_group(old_path, new_path)
503
508
504 # Trigger update event.
509 # Trigger update event.
505 events.trigger(events.RepoGroupUpdateEvent(repo_group))
510 events.trigger(events.RepoGroupUpdateEvent(repo_group))
506
511
507 return repo_group
512 return repo_group
508 except Exception:
513 except Exception:
509 log.error(traceback.format_exc())
514 log.error(traceback.format_exc())
510 raise
515 raise
511
516
512 def delete(self, repo_group, force_delete=False, fs_remove=True):
517 def delete(self, repo_group, force_delete=False, fs_remove=True):
513 repo_group = self._get_repo_group(repo_group)
518 repo_group = self._get_repo_group(repo_group)
514 if not repo_group:
519 if not repo_group:
515 return False
520 return False
516 try:
521 try:
517 self.sa.delete(repo_group)
522 self.sa.delete(repo_group)
518 if fs_remove:
523 if fs_remove:
519 self._delete_filesystem_group(repo_group, force_delete)
524 self._delete_filesystem_group(repo_group, force_delete)
520 else:
525 else:
521 log.debug('skipping removal from filesystem')
526 log.debug('skipping removal from filesystem')
522
527
523 # Trigger delete event.
528 # Trigger delete event.
524 events.trigger(events.RepoGroupDeleteEvent(repo_group))
529 events.trigger(events.RepoGroupDeleteEvent(repo_group))
525 return True
530 return True
526
531
527 except Exception:
532 except Exception:
528 log.error('Error removing repo_group %s', repo_group)
533 log.error('Error removing repo_group %s', repo_group)
529 raise
534 raise
530
535
531 def grant_user_permission(self, repo_group, user, perm):
536 def grant_user_permission(self, repo_group, user, perm):
532 """
537 """
533 Grant permission for user on given repository group, or update
538 Grant permission for user on given repository group, or update
534 existing one if found
539 existing one if found
535
540
536 :param repo_group: Instance of RepoGroup, repositories_group_id,
541 :param repo_group: Instance of RepoGroup, repositories_group_id,
537 or repositories_group name
542 or repositories_group name
538 :param user: Instance of User, user_id or username
543 :param user: Instance of User, user_id or username
539 :param perm: Instance of Permission, or permission_name
544 :param perm: Instance of Permission, or permission_name
540 """
545 """
541
546
542 repo_group = self._get_repo_group(repo_group)
547 repo_group = self._get_repo_group(repo_group)
543 user = self._get_user(user)
548 user = self._get_user(user)
544 permission = self._get_perm(perm)
549 permission = self._get_perm(perm)
545
550
546 # check if we have that permission already
551 # check if we have that permission already
547 obj = self.sa.query(UserRepoGroupToPerm)\
552 obj = self.sa.query(UserRepoGroupToPerm)\
548 .filter(UserRepoGroupToPerm.user == user)\
553 .filter(UserRepoGroupToPerm.user == user)\
549 .filter(UserRepoGroupToPerm.group == repo_group)\
554 .filter(UserRepoGroupToPerm.group == repo_group)\
550 .scalar()
555 .scalar()
551 if obj is None:
556 if obj is None:
552 # create new !
557 # create new !
553 obj = UserRepoGroupToPerm()
558 obj = UserRepoGroupToPerm()
554 obj.group = repo_group
559 obj.group = repo_group
555 obj.user = user
560 obj.user = user
556 obj.permission = permission
561 obj.permission = permission
557 self.sa.add(obj)
562 self.sa.add(obj)
558 log.debug('Granted perm %s to %s on %s', perm, user, repo_group)
563 log.debug('Granted perm %s to %s on %s', perm, user, repo_group)
559 action_logger_generic(
564 action_logger_generic(
560 'granted permission: {} to user: {} on repogroup: {}'.format(
565 'granted permission: {} to user: {} on repogroup: {}'.format(
561 perm, user, repo_group), namespace='security.repogroup')
566 perm, user, repo_group), namespace='security.repogroup')
562 return obj
567 return obj
563
568
564 def revoke_user_permission(self, repo_group, user):
569 def revoke_user_permission(self, repo_group, user):
565 """
570 """
566 Revoke permission for user on given repository group
571 Revoke permission for user on given repository group
567
572
568 :param repo_group: Instance of RepoGroup, repositories_group_id,
573 :param repo_group: Instance of RepoGroup, repositories_group_id,
569 or repositories_group name
574 or repositories_group name
570 :param user: Instance of User, user_id or username
575 :param user: Instance of User, user_id or username
571 """
576 """
572
577
573 repo_group = self._get_repo_group(repo_group)
578 repo_group = self._get_repo_group(repo_group)
574 user = self._get_user(user)
579 user = self._get_user(user)
575
580
576 obj = self.sa.query(UserRepoGroupToPerm)\
581 obj = self.sa.query(UserRepoGroupToPerm)\
577 .filter(UserRepoGroupToPerm.user == user)\
582 .filter(UserRepoGroupToPerm.user == user)\
578 .filter(UserRepoGroupToPerm.group == repo_group)\
583 .filter(UserRepoGroupToPerm.group == repo_group)\
579 .scalar()
584 .scalar()
580 if obj:
585 if obj:
581 self.sa.delete(obj)
586 self.sa.delete(obj)
582 log.debug('Revoked perm on %s on %s', repo_group, user)
587 log.debug('Revoked perm on %s on %s', repo_group, user)
583 action_logger_generic(
588 action_logger_generic(
584 'revoked permission from user: {} on repogroup: {}'.format(
589 'revoked permission from user: {} on repogroup: {}'.format(
585 user, repo_group), namespace='security.repogroup')
590 user, repo_group), namespace='security.repogroup')
586
591
587 def grant_user_group_permission(self, repo_group, group_name, perm):
592 def grant_user_group_permission(self, repo_group, group_name, perm):
588 """
593 """
589 Grant permission for user group on given repository group, or update
594 Grant permission for user group on given repository group, or update
590 existing one if found
595 existing one if found
591
596
592 :param repo_group: Instance of RepoGroup, repositories_group_id,
597 :param repo_group: Instance of RepoGroup, repositories_group_id,
593 or repositories_group name
598 or repositories_group name
594 :param group_name: Instance of UserGroup, users_group_id,
599 :param group_name: Instance of UserGroup, users_group_id,
595 or user group name
600 or user group name
596 :param perm: Instance of Permission, or permission_name
601 :param perm: Instance of Permission, or permission_name
597 """
602 """
598 repo_group = self._get_repo_group(repo_group)
603 repo_group = self._get_repo_group(repo_group)
599 group_name = self._get_user_group(group_name)
604 group_name = self._get_user_group(group_name)
600 permission = self._get_perm(perm)
605 permission = self._get_perm(perm)
601
606
602 # check if we have that permission already
607 # check if we have that permission already
603 obj = self.sa.query(UserGroupRepoGroupToPerm)\
608 obj = self.sa.query(UserGroupRepoGroupToPerm)\
604 .filter(UserGroupRepoGroupToPerm.group == repo_group)\
609 .filter(UserGroupRepoGroupToPerm.group == repo_group)\
605 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
610 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
606 .scalar()
611 .scalar()
607
612
608 if obj is None:
613 if obj is None:
609 # create new
614 # create new
610 obj = UserGroupRepoGroupToPerm()
615 obj = UserGroupRepoGroupToPerm()
611
616
612 obj.group = repo_group
617 obj.group = repo_group
613 obj.users_group = group_name
618 obj.users_group = group_name
614 obj.permission = permission
619 obj.permission = permission
615 self.sa.add(obj)
620 self.sa.add(obj)
616 log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group)
621 log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group)
617 action_logger_generic(
622 action_logger_generic(
618 'granted permission: {} to usergroup: {} on repogroup: {}'.format(
623 'granted permission: {} to usergroup: {} on repogroup: {}'.format(
619 perm, group_name, repo_group), namespace='security.repogroup')
624 perm, group_name, repo_group), namespace='security.repogroup')
620 return obj
625 return obj
621
626
622 def revoke_user_group_permission(self, repo_group, group_name):
627 def revoke_user_group_permission(self, repo_group, group_name):
623 """
628 """
624 Revoke permission for user group on given repository group
629 Revoke permission for user group on given repository group
625
630
626 :param repo_group: Instance of RepoGroup, repositories_group_id,
631 :param repo_group: Instance of RepoGroup, repositories_group_id,
627 or repositories_group name
632 or repositories_group name
628 :param group_name: Instance of UserGroup, users_group_id,
633 :param group_name: Instance of UserGroup, users_group_id,
629 or user group name
634 or user group name
630 """
635 """
631 repo_group = self._get_repo_group(repo_group)
636 repo_group = self._get_repo_group(repo_group)
632 group_name = self._get_user_group(group_name)
637 group_name = self._get_user_group(group_name)
633
638
634 obj = self.sa.query(UserGroupRepoGroupToPerm)\
639 obj = self.sa.query(UserGroupRepoGroupToPerm)\
635 .filter(UserGroupRepoGroupToPerm.group == repo_group)\
640 .filter(UserGroupRepoGroupToPerm.group == repo_group)\
636 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
641 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
637 .scalar()
642 .scalar()
638 if obj:
643 if obj:
639 self.sa.delete(obj)
644 self.sa.delete(obj)
640 log.debug('Revoked perm to %s on %s', repo_group, group_name)
645 log.debug('Revoked perm to %s on %s', repo_group, group_name)
641 action_logger_generic(
646 action_logger_generic(
642 'revoked permission from usergroup: {} on repogroup: {}'.format(
647 'revoked permission from usergroup: {} on repogroup: {}'.format(
643 group_name, repo_group), namespace='security.repogroup')
648 group_name, repo_group), namespace='security.repogroup')
644
649
645 def get_repo_groups_as_dict(self, repo_group_list=None, admin=False,
650 def get_repo_groups_as_dict(self, repo_group_list=None, admin=False,
646 super_user_actions=False):
651 super_user_actions=False):
647
652
648 from rhodecode.lib.utils import PartialRenderer
653 from rhodecode.lib.utils import PartialRenderer
649 _render = PartialRenderer('data_table/_dt_elements.html')
654 _render = PartialRenderer('data_table/_dt_elements.html')
650 c = _render.c
655 c = _render.c
651 h = _render.h
656 h = _render.h
652
657
653 def quick_menu(repo_group_name):
658 def quick_menu(repo_group_name):
654 return _render('quick_repo_group_menu', repo_group_name)
659 return _render('quick_repo_group_menu', repo_group_name)
655
660
656 def repo_group_lnk(repo_group_name):
661 def repo_group_lnk(repo_group_name):
657 return _render('repo_group_name', repo_group_name)
662 return _render('repo_group_name', repo_group_name)
658
663
659 def desc(desc, personal):
664 def desc(desc, personal):
660 prefix = h.escaped_stylize(u'[personal] ') if personal else ''
665 prefix = h.escaped_stylize(u'[personal] ') if personal else ''
661
666
662 if c.visual.stylify_metatags:
667 if c.visual.stylify_metatags:
663 desc = h.urlify_text(prefix + h.escaped_stylize(desc))
668 desc = h.urlify_text(prefix + h.escaped_stylize(desc))
664 else:
669 else:
665 desc = h.urlify_text(prefix + h.html_escape(desc))
670 desc = h.urlify_text(prefix + h.html_escape(desc))
666
671
667 return _render('repo_group_desc', desc)
672 return _render('repo_group_desc', desc)
668
673
669 def repo_group_actions(repo_group_id, repo_group_name, gr_count):
674 def repo_group_actions(repo_group_id, repo_group_name, gr_count):
670 return _render(
675 return _render(
671 'repo_group_actions', repo_group_id, repo_group_name, gr_count)
676 'repo_group_actions', repo_group_id, repo_group_name, gr_count)
672
677
673 def repo_group_name(repo_group_name, children_groups):
678 def repo_group_name(repo_group_name, children_groups):
674 return _render("repo_group_name", repo_group_name, children_groups)
679 return _render("repo_group_name", repo_group_name, children_groups)
675
680
676 def user_profile(username):
681 def user_profile(username):
677 return _render('user_profile', username)
682 return _render('user_profile', username)
678
683
679 repo_group_data = []
684 repo_group_data = []
680 for group in repo_group_list:
685 for group in repo_group_list:
681
686
682 row = {
687 row = {
683 "menu": quick_menu(group.group_name),
688 "menu": quick_menu(group.group_name),
684 "name": repo_group_lnk(group.group_name),
689 "name": repo_group_lnk(group.group_name),
685 "name_raw": group.group_name,
690 "name_raw": group.group_name,
686 "desc": desc(group.group_description, group.personal),
691 "desc": desc(group.group_description, group.personal),
687 "top_level_repos": 0,
692 "top_level_repos": 0,
688 "owner": user_profile(group.user.username)
693 "owner": user_profile(group.user.username)
689 }
694 }
690 if admin:
695 if admin:
691 repo_count = group.repositories.count()
696 repo_count = group.repositories.count()
692 children_groups = map(
697 children_groups = map(
693 h.safe_unicode,
698 h.safe_unicode,
694 itertools.chain((g.name for g in group.parents),
699 itertools.chain((g.name for g in group.parents),
695 (x.name for x in [group])))
700 (x.name for x in [group])))
696 row.update({
701 row.update({
697 "action": repo_group_actions(
702 "action": repo_group_actions(
698 group.group_id, group.group_name, repo_count),
703 group.group_id, group.group_name, repo_count),
699 "top_level_repos": repo_count,
704 "top_level_repos": repo_count,
700 "name": repo_group_name(group.group_name, children_groups),
705 "name": repo_group_name(group.group_name, children_groups),
701
706
702 })
707 })
703 repo_group_data.append(row)
708 repo_group_data.append(row)
704
709
705 return repo_group_data
710 return repo_group_data
General Comments 0
You need to be logged in to leave comments. Login now