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