##// END OF EJS Templates
managing users groups enforce permissions checks....
marcink -
r3789:32f66c83 beta
parent child Browse files
Show More
@@ -1,737 +1,746 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.repo
3 rhodecode.model.repo
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 Repository model for rhodecode
6 Repository model for rhodecode
7
7
8 :created_on: Jun 5, 2010
8 :created_on: Jun 5, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 from __future__ import with_statement
25 from __future__ import with_statement
26 import os
26 import os
27 import shutil
27 import shutil
28 import logging
28 import logging
29 import traceback
29 import traceback
30 from datetime import datetime
30 from datetime import datetime
31
31
32 from rhodecode.lib.vcs.backends import get_backend
32 from rhodecode.lib.vcs.backends import get_backend
33 from rhodecode.lib.compat import json
33 from rhodecode.lib.compat import json
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
35 remove_prefix, obfuscate_url_pw
35 remove_prefix, obfuscate_url_pw
36 from rhodecode.lib.caching_query import FromCache
36 from rhodecode.lib.caching_query import FromCache
37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
38
38
39 from rhodecode.model import BaseModel
39 from rhodecode.model import BaseModel
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
41 Statistics, UserGroup, UserGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
41 Statistics, UserGroup, UserGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
42 RhodeCodeSetting, RepositoryField
42 RhodeCodeSetting, RepositoryField
43 from rhodecode.lib import helpers as h
43 from rhodecode.lib import helpers as h
44 from rhodecode.lib.auth import HasRepoPermissionAny
44 from rhodecode.lib.auth import HasRepoPermissionAny, HasUserGroupPermissionAny
45 from rhodecode.lib.exceptions import AttachedForksError
45 from rhodecode.lib.exceptions import AttachedForksError
46 from rhodecode.model.scm import UserGroupList
46
47
47 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
48
49
49
50
50 class RepoModel(BaseModel):
51 class RepoModel(BaseModel):
51
52
52 cls = Repository
53 cls = Repository
53 URL_SEPARATOR = Repository.url_sep()
54 URL_SEPARATOR = Repository.url_sep()
54
55
55 def _get_user_group(self, users_group):
56 def _get_user_group(self, users_group):
56 return self._get_instance(UserGroup, users_group,
57 return self._get_instance(UserGroup, users_group,
57 callback=UserGroup.get_by_group_name)
58 callback=UserGroup.get_by_group_name)
58
59
59 def _get_repo_group(self, repos_group):
60 def _get_repo_group(self, repos_group):
60 return self._get_instance(RepoGroup, repos_group,
61 return self._get_instance(RepoGroup, repos_group,
61 callback=RepoGroup.get_by_group_name)
62 callback=RepoGroup.get_by_group_name)
62
63
63 def _create_default_perms(self, repository, private):
64 def _create_default_perms(self, repository, private):
64 # create default permission
65 # create default permission
65 default = 'repository.read'
66 default = 'repository.read'
66 def_user = User.get_default_user()
67 def_user = User.get_default_user()
67 for p in def_user.user_perms:
68 for p in def_user.user_perms:
68 if p.permission.permission_name.startswith('repository.'):
69 if p.permission.permission_name.startswith('repository.'):
69 default = p.permission.permission_name
70 default = p.permission.permission_name
70 break
71 break
71
72
72 default_perm = 'repository.none' if private else default
73 default_perm = 'repository.none' if private else default
73
74
74 repo_to_perm = UserRepoToPerm()
75 repo_to_perm = UserRepoToPerm()
75 repo_to_perm.permission = Permission.get_by_key(default_perm)
76 repo_to_perm.permission = Permission.get_by_key(default_perm)
76
77
77 repo_to_perm.repository = repository
78 repo_to_perm.repository = repository
78 repo_to_perm.user_id = def_user.user_id
79 repo_to_perm.user_id = def_user.user_id
79
80
80 return repo_to_perm
81 return repo_to_perm
81
82
82 @LazyProperty
83 @LazyProperty
83 def repos_path(self):
84 def repos_path(self):
84 """
85 """
85 Get's the repositories root path from database
86 Get's the repositories root path from database
86 """
87 """
87
88
88 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
89 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
89 return q.ui_value
90 return q.ui_value
90
91
91 def get(self, repo_id, cache=False):
92 def get(self, repo_id, cache=False):
92 repo = self.sa.query(Repository)\
93 repo = self.sa.query(Repository)\
93 .filter(Repository.repo_id == repo_id)
94 .filter(Repository.repo_id == repo_id)
94
95
95 if cache:
96 if cache:
96 repo = repo.options(FromCache("sql_cache_short",
97 repo = repo.options(FromCache("sql_cache_short",
97 "get_repo_%s" % repo_id))
98 "get_repo_%s" % repo_id))
98 return repo.scalar()
99 return repo.scalar()
99
100
100 def get_repo(self, repository):
101 def get_repo(self, repository):
101 return self._get_repo(repository)
102 return self._get_repo(repository)
102
103
103 def get_by_repo_name(self, repo_name, cache=False):
104 def get_by_repo_name(self, repo_name, cache=False):
104 repo = self.sa.query(Repository)\
105 repo = self.sa.query(Repository)\
105 .filter(Repository.repo_name == repo_name)
106 .filter(Repository.repo_name == repo_name)
106
107
107 if cache:
108 if cache:
108 repo = repo.options(FromCache("sql_cache_short",
109 repo = repo.options(FromCache("sql_cache_short",
109 "get_repo_%s" % repo_name))
110 "get_repo_%s" % repo_name))
110 return repo.scalar()
111 return repo.scalar()
111
112
112 def get_all_user_repos(self, user):
113 def get_all_user_repos(self, user):
113 """
114 """
114 Get's all repositories that user have at least read access
115 Get's all repositories that user have at least read access
115
116
116 :param user:
117 :param user:
117 :type user:
118 :type user:
118 """
119 """
119 from rhodecode.lib.auth import AuthUser
120 from rhodecode.lib.auth import AuthUser
120 user = self._get_user(user)
121 user = self._get_user(user)
121 repos = AuthUser(user_id=user.user_id).permissions['repositories']
122 repos = AuthUser(user_id=user.user_id).permissions['repositories']
122 access_check = lambda r: r[1] in ['repository.read',
123 access_check = lambda r: r[1] in ['repository.read',
123 'repository.write',
124 'repository.write',
124 'repository.admin']
125 'repository.admin']
125 repos = [x[0] for x in filter(access_check, repos.items())]
126 repos = [x[0] for x in filter(access_check, repos.items())]
126 return Repository.query().filter(Repository.repo_name.in_(repos))
127 return Repository.query().filter(Repository.repo_name.in_(repos))
127
128
128 def get_users_js(self):
129 def get_users_js(self):
129 users = self.sa.query(User).filter(User.active == True).all()
130 users = self.sa.query(User).filter(User.active == True).all()
130 return json.dumps([
131 return json.dumps([
131 {
132 {
132 'id': u.user_id,
133 'id': u.user_id,
133 'fname': u.name,
134 'fname': u.name,
134 'lname': u.lastname,
135 'lname': u.lastname,
135 'nname': u.username,
136 'nname': u.username,
136 'gravatar_lnk': h.gravatar_url(u.email, 14)
137 'gravatar_lnk': h.gravatar_url(u.email, 14)
137 } for u in users]
138 } for u in users]
138 )
139 )
139
140
140 def get_users_groups_js(self):
141 def get_users_groups_js(self):
141 users_groups = self.sa.query(UserGroup)\
142 users_groups = self.sa.query(UserGroup)\
142 .filter(UserGroup.users_group_active == True).all()
143 .filter(UserGroup.users_group_active == True).all()
143
144 users_groups = UserGroupList(users_groups, perm_set=['usergroup.read',
145 'usergroup.write',
146 'usergroup.admin'])
144 return json.dumps([
147 return json.dumps([
145 {
148 {
146 'id': gr.users_group_id,
149 'id': gr.users_group_id,
147 'grname': gr.users_group_name,
150 'grname': gr.users_group_name,
148 'grmembers': len(gr.members),
151 'grmembers': len(gr.members),
149 } for gr in users_groups]
152 } for gr in users_groups]
150 )
153 )
151
154
152 @classmethod
155 @classmethod
153 def _render_datatable(cls, tmpl, *args, **kwargs):
156 def _render_datatable(cls, tmpl, *args, **kwargs):
154 import rhodecode
157 import rhodecode
155 from pylons import tmpl_context as c
158 from pylons import tmpl_context as c
156 from pylons.i18n.translation import _
159 from pylons.i18n.translation import _
157
160
158 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
161 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
159 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
162 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
160
163
161 tmpl = template.get_def(tmpl)
164 tmpl = template.get_def(tmpl)
162 kwargs.update(dict(_=_, h=h, c=c))
165 kwargs.update(dict(_=_, h=h, c=c))
163 return tmpl.render(*args, **kwargs)
166 return tmpl.render(*args, **kwargs)
164
167
165 @classmethod
168 @classmethod
166 def update_repoinfo(cls, repositories=None):
169 def update_repoinfo(cls, repositories=None):
167 if not repositories:
170 if not repositories:
168 repositories = Repository.getAll()
171 repositories = Repository.getAll()
169 for repo in repositories:
172 for repo in repositories:
170 repo.update_changeset_cache()
173 repo.update_changeset_cache()
171
174
172 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
175 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
173 super_user_actions=False):
176 super_user_actions=False):
174 _render = self._render_datatable
177 _render = self._render_datatable
175
178
176 def quick_menu(repo_name):
179 def quick_menu(repo_name):
177 return _render('quick_menu', repo_name)
180 return _render('quick_menu', repo_name)
178
181
179 def repo_lnk(name, rtype, private, fork_of):
182 def repo_lnk(name, rtype, private, fork_of):
180 return _render('repo_name', name, rtype, private, fork_of,
183 return _render('repo_name', name, rtype, private, fork_of,
181 short_name=not admin, admin=False)
184 short_name=not admin, admin=False)
182
185
183 def last_change(last_change):
186 def last_change(last_change):
184 return _render("last_change", last_change)
187 return _render("last_change", last_change)
185
188
186 def rss_lnk(repo_name):
189 def rss_lnk(repo_name):
187 return _render("rss", repo_name)
190 return _render("rss", repo_name)
188
191
189 def atom_lnk(repo_name):
192 def atom_lnk(repo_name):
190 return _render("atom", repo_name)
193 return _render("atom", repo_name)
191
194
192 def last_rev(repo_name, cs_cache):
195 def last_rev(repo_name, cs_cache):
193 return _render('revision', repo_name, cs_cache.get('revision'),
196 return _render('revision', repo_name, cs_cache.get('revision'),
194 cs_cache.get('raw_id'), cs_cache.get('author'),
197 cs_cache.get('raw_id'), cs_cache.get('author'),
195 cs_cache.get('message'))
198 cs_cache.get('message'))
196
199
197 def desc(desc):
200 def desc(desc):
198 from pylons import tmpl_context as c
201 from pylons import tmpl_context as c
199 if c.visual.stylify_metatags:
202 if c.visual.stylify_metatags:
200 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
203 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
201 else:
204 else:
202 return h.urlify_text(h.truncate(desc, 60))
205 return h.urlify_text(h.truncate(desc, 60))
203
206
204 def repo_actions(repo_name):
207 def repo_actions(repo_name):
205 return _render('repo_actions', repo_name, super_user_actions)
208 return _render('repo_actions', repo_name, super_user_actions)
206
209
207 def owner_actions(user_id, username):
210 def owner_actions(user_id, username):
208 return _render('user_name', user_id, username)
211 return _render('user_name', user_id, username)
209
212
210 repos_data = []
213 repos_data = []
211 for repo in repos_list:
214 for repo in repos_list:
212 if perm_check:
215 if perm_check:
213 # check permission at this level
216 # check permission at this level
214 if not HasRepoPermissionAny(
217 if not HasRepoPermissionAny(
215 'repository.read', 'repository.write', 'repository.admin'
218 'repository.read', 'repository.write', 'repository.admin'
216 )(repo.repo_name, 'get_repos_as_dict check'):
219 )(repo.repo_name, 'get_repos_as_dict check'):
217 continue
220 continue
218 cs_cache = repo.changeset_cache
221 cs_cache = repo.changeset_cache
219 row = {
222 row = {
220 "menu": quick_menu(repo.repo_name),
223 "menu": quick_menu(repo.repo_name),
221 "raw_name": repo.repo_name.lower(),
224 "raw_name": repo.repo_name.lower(),
222 "name": repo_lnk(repo.repo_name, repo.repo_type,
225 "name": repo_lnk(repo.repo_name, repo.repo_type,
223 repo.private, repo.fork),
226 repo.private, repo.fork),
224 "last_change": last_change(repo.last_db_change),
227 "last_change": last_change(repo.last_db_change),
225 "last_changeset": last_rev(repo.repo_name, cs_cache),
228 "last_changeset": last_rev(repo.repo_name, cs_cache),
226 "raw_tip": cs_cache.get('revision'),
229 "raw_tip": cs_cache.get('revision'),
227 "desc": desc(repo.description),
230 "desc": desc(repo.description),
228 "owner": h.person(repo.user.username),
231 "owner": h.person(repo.user.username),
229 "rss": rss_lnk(repo.repo_name),
232 "rss": rss_lnk(repo.repo_name),
230 "atom": atom_lnk(repo.repo_name),
233 "atom": atom_lnk(repo.repo_name),
231
234
232 }
235 }
233 if admin:
236 if admin:
234 row.update({
237 row.update({
235 "action": repo_actions(repo.repo_name),
238 "action": repo_actions(repo.repo_name),
236 "owner": owner_actions(repo.user.user_id,
239 "owner": owner_actions(repo.user.user_id,
237 h.person(repo.user.username))
240 h.person(repo.user.username))
238 })
241 })
239 repos_data.append(row)
242 repos_data.append(row)
240
243
241 return {
244 return {
242 "totalRecords": len(repos_list),
245 "totalRecords": len(repos_list),
243 "startIndex": 0,
246 "startIndex": 0,
244 "sort": "name",
247 "sort": "name",
245 "dir": "asc",
248 "dir": "asc",
246 "records": repos_data
249 "records": repos_data
247 }
250 }
248
251
249 def _get_defaults(self, repo_name):
252 def _get_defaults(self, repo_name):
250 """
253 """
251 Get's information about repository, and returns a dict for
254 Get's information about repository, and returns a dict for
252 usage in forms
255 usage in forms
253
256
254 :param repo_name:
257 :param repo_name:
255 """
258 """
256
259
257 repo_info = Repository.get_by_repo_name(repo_name)
260 repo_info = Repository.get_by_repo_name(repo_name)
258
261
259 if repo_info is None:
262 if repo_info is None:
260 return None
263 return None
261
264
262 defaults = repo_info.get_dict()
265 defaults = repo_info.get_dict()
263 group, repo_name, repo_name_full = repo_info.groups_and_repo
266 group, repo_name, repo_name_full = repo_info.groups_and_repo
264 defaults['repo_name'] = repo_name
267 defaults['repo_name'] = repo_name
265 defaults['repo_group'] = getattr(group[-1] if group else None,
268 defaults['repo_group'] = getattr(group[-1] if group else None,
266 'group_id', None)
269 'group_id', None)
267
270
268 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
271 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
269 (1, 'repo_description'), (1, 'repo_enable_locking'),
272 (1, 'repo_description'), (1, 'repo_enable_locking'),
270 (1, 'repo_landing_rev'), (0, 'clone_uri'),
273 (1, 'repo_landing_rev'), (0, 'clone_uri'),
271 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
274 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
272 attr = k
275 attr = k
273 if strip:
276 if strip:
274 attr = remove_prefix(k, 'repo_')
277 attr = remove_prefix(k, 'repo_')
275
278
276 defaults[k] = defaults[attr]
279 defaults[k] = defaults[attr]
277
280
278 # fill owner
281 # fill owner
279 if repo_info.user:
282 if repo_info.user:
280 defaults.update({'user': repo_info.user.username})
283 defaults.update({'user': repo_info.user.username})
281 else:
284 else:
282 replacement_user = User.query().filter(User.admin ==
285 replacement_user = User.query().filter(User.admin ==
283 True).first().username
286 True).first().username
284 defaults.update({'user': replacement_user})
287 defaults.update({'user': replacement_user})
285
288
286 # fill repository users
289 # fill repository users
287 for p in repo_info.repo_to_perm:
290 for p in repo_info.repo_to_perm:
288 defaults.update({'u_perm_%s' % p.user.username:
291 defaults.update({'u_perm_%s' % p.user.username:
289 p.permission.permission_name})
292 p.permission.permission_name})
290
293
291 # fill repository groups
294 # fill repository groups
292 for p in repo_info.users_group_to_perm:
295 for p in repo_info.users_group_to_perm:
293 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
296 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
294 p.permission.permission_name})
297 p.permission.permission_name})
295
298
296 return defaults
299 return defaults
297
300
298 def update(self, org_repo_name, **kwargs):
301 def update(self, org_repo_name, **kwargs):
299 try:
302 try:
300 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
303 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
301
304
302 if 'user' in kwargs:
305 if 'user' in kwargs:
303 cur_repo.user = User.get_by_username(kwargs['user'])
306 cur_repo.user = User.get_by_username(kwargs['user'])
304
307
305 if 'repo_group' in kwargs:
308 if 'repo_group' in kwargs:
306 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
309 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
307
310
308 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
311 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
309 (1, 'repo_description'), (1, 'repo_enable_locking'),
312 (1, 'repo_description'), (1, 'repo_enable_locking'),
310 (1, 'repo_landing_rev'), (0, 'clone_uri'),
313 (1, 'repo_landing_rev'), (0, 'clone_uri'),
311 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
314 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
312 if k in kwargs:
315 if k in kwargs:
313 val = kwargs[k]
316 val = kwargs[k]
314 if strip:
317 if strip:
315 k = remove_prefix(k, 'repo_')
318 k = remove_prefix(k, 'repo_')
316 setattr(cur_repo, k, val)
319 setattr(cur_repo, k, val)
317
320
318 new_name = cur_repo.get_new_name(kwargs['repo_name'])
321 new_name = cur_repo.get_new_name(kwargs['repo_name'])
319 cur_repo.repo_name = new_name
322 cur_repo.repo_name = new_name
320 #if private flag is set, reset default permission to NONE
323 #if private flag is set, reset default permission to NONE
321
324
322 if kwargs.get('repo_private'):
325 if kwargs.get('repo_private'):
323 EMPTY_PERM = 'repository.none'
326 EMPTY_PERM = 'repository.none'
324 RepoModel().grant_user_permission(
327 RepoModel().grant_user_permission(
325 repo=cur_repo, user='default', perm=EMPTY_PERM
328 repo=cur_repo, user='default', perm=EMPTY_PERM
326 )
329 )
327 #handle extra fields
330 #handle extra fields
328 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
331 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
329 k = RepositoryField.un_prefix_key(field)
332 k = RepositoryField.un_prefix_key(field)
330 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
333 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
331 if ex_field:
334 if ex_field:
332 ex_field.field_value = kwargs[field]
335 ex_field.field_value = kwargs[field]
333 self.sa.add(ex_field)
336 self.sa.add(ex_field)
334 self.sa.add(cur_repo)
337 self.sa.add(cur_repo)
335
338
336 if org_repo_name != new_name:
339 if org_repo_name != new_name:
337 # rename repository
340 # rename repository
338 self.__rename_repo(old=org_repo_name, new=new_name)
341 self.__rename_repo(old=org_repo_name, new=new_name)
339
342
340 return cur_repo
343 return cur_repo
341 except Exception:
344 except Exception:
342 log.error(traceback.format_exc())
345 log.error(traceback.format_exc())
343 raise
346 raise
344
347
345 def create_repo(self, repo_name, repo_type, description, owner,
348 def create_repo(self, repo_name, repo_type, description, owner,
346 private=False, clone_uri=None, repos_group=None,
349 private=False, clone_uri=None, repos_group=None,
347 landing_rev='tip', just_db=False, fork_of=None,
350 landing_rev='tip', just_db=False, fork_of=None,
348 copy_fork_permissions=False, enable_statistics=False,
351 copy_fork_permissions=False, enable_statistics=False,
349 enable_locking=False, enable_downloads=False):
352 enable_locking=False, enable_downloads=False):
350 """
353 """
351 Create repository
354 Create repository
352
355
353 """
356 """
354 from rhodecode.model.scm import ScmModel
357 from rhodecode.model.scm import ScmModel
355
358
356 owner = self._get_user(owner)
359 owner = self._get_user(owner)
357 fork_of = self._get_repo(fork_of)
360 fork_of = self._get_repo(fork_of)
358 repos_group = self._get_repo_group(repos_group)
361 repos_group = self._get_repo_group(repos_group)
359 try:
362 try:
360
363
361 # repo name is just a name of repository
364 # repo name is just a name of repository
362 # while repo_name_full is a full qualified name that is combined
365 # while repo_name_full is a full qualified name that is combined
363 # with name and path of group
366 # with name and path of group
364 repo_name_full = repo_name
367 repo_name_full = repo_name
365 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
368 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
366
369
367 new_repo = Repository()
370 new_repo = Repository()
368 new_repo.enable_statistics = False
371 new_repo.enable_statistics = False
369 new_repo.repo_name = repo_name_full
372 new_repo.repo_name = repo_name_full
370 new_repo.repo_type = repo_type
373 new_repo.repo_type = repo_type
371 new_repo.user = owner
374 new_repo.user = owner
372 new_repo.group = repos_group
375 new_repo.group = repos_group
373 new_repo.description = description or repo_name
376 new_repo.description = description or repo_name
374 new_repo.private = private
377 new_repo.private = private
375 new_repo.clone_uri = clone_uri
378 new_repo.clone_uri = clone_uri
376 new_repo.landing_rev = landing_rev
379 new_repo.landing_rev = landing_rev
377
380
378 new_repo.enable_statistics = enable_statistics
381 new_repo.enable_statistics = enable_statistics
379 new_repo.enable_locking = enable_locking
382 new_repo.enable_locking = enable_locking
380 new_repo.enable_downloads = enable_downloads
383 new_repo.enable_downloads = enable_downloads
381
384
382 if repos_group:
385 if repos_group:
383 new_repo.enable_locking = repos_group.enable_locking
386 new_repo.enable_locking = repos_group.enable_locking
384
387
385 if fork_of:
388 if fork_of:
386 parent_repo = fork_of
389 parent_repo = fork_of
387 new_repo.fork = parent_repo
390 new_repo.fork = parent_repo
388
391
389 self.sa.add(new_repo)
392 self.sa.add(new_repo)
390
393
391 if fork_of:
394 if fork_of:
392 if copy_fork_permissions:
395 if copy_fork_permissions:
393 repo = fork_of
396 repo = fork_of
394 user_perms = UserRepoToPerm.query()\
397 user_perms = UserRepoToPerm.query()\
395 .filter(UserRepoToPerm.repository == repo).all()
398 .filter(UserRepoToPerm.repository == repo).all()
396 group_perms = UserGroupRepoToPerm.query()\
399 group_perms = UserGroupRepoToPerm.query()\
397 .filter(UserGroupRepoToPerm.repository == repo).all()
400 .filter(UserGroupRepoToPerm.repository == repo).all()
398
401
399 for perm in user_perms:
402 for perm in user_perms:
400 UserRepoToPerm.create(perm.user, new_repo,
403 UserRepoToPerm.create(perm.user, new_repo,
401 perm.permission)
404 perm.permission)
402
405
403 for perm in group_perms:
406 for perm in group_perms:
404 UserGroupRepoToPerm.create(perm.users_group, new_repo,
407 UserGroupRepoToPerm.create(perm.users_group, new_repo,
405 perm.permission)
408 perm.permission)
406 else:
409 else:
407 perm_obj = self._create_default_perms(new_repo, private)
410 perm_obj = self._create_default_perms(new_repo, private)
408 self.sa.add(perm_obj)
411 self.sa.add(perm_obj)
409 else:
412 else:
410 perm_obj = self._create_default_perms(new_repo, private)
413 perm_obj = self._create_default_perms(new_repo, private)
411 self.sa.add(perm_obj)
414 self.sa.add(perm_obj)
412
415
413 if not just_db:
416 if not just_db:
414 self.__create_repo(repo_name, repo_type,
417 self.__create_repo(repo_name, repo_type,
415 repos_group,
418 repos_group,
416 clone_uri)
419 clone_uri)
417 log_create_repository(new_repo.get_dict(),
420 log_create_repository(new_repo.get_dict(),
418 created_by=owner.username)
421 created_by=owner.username)
419
422
420 # now automatically start following this repository as owner
423 # now automatically start following this repository as owner
421 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
424 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
422 owner.user_id)
425 owner.user_id)
423 return new_repo
426 return new_repo
424 except Exception:
427 except Exception:
425 log.error(traceback.format_exc())
428 log.error(traceback.format_exc())
426 raise
429 raise
427
430
428 def create(self, form_data, cur_user, just_db=False, fork=None):
431 def create(self, form_data, cur_user, just_db=False, fork=None):
429 """
432 """
430 Backward compatibility function, just a wrapper on top of create_repo
433 Backward compatibility function, just a wrapper on top of create_repo
431
434
432 :param form_data:
435 :param form_data:
433 :param cur_user:
436 :param cur_user:
434 :param just_db:
437 :param just_db:
435 :param fork:
438 :param fork:
436 """
439 """
437 owner = cur_user
440 owner = cur_user
438 repo_name = form_data['repo_name_full']
441 repo_name = form_data['repo_name_full']
439 repo_type = form_data['repo_type']
442 repo_type = form_data['repo_type']
440 description = form_data['repo_description']
443 description = form_data['repo_description']
441 private = form_data['repo_private']
444 private = form_data['repo_private']
442 clone_uri = form_data.get('clone_uri')
445 clone_uri = form_data.get('clone_uri')
443 repos_group = form_data['repo_group']
446 repos_group = form_data['repo_group']
444 landing_rev = form_data['repo_landing_rev']
447 landing_rev = form_data['repo_landing_rev']
445 copy_fork_permissions = form_data.get('copy_permissions')
448 copy_fork_permissions = form_data.get('copy_permissions')
446 fork_of = form_data.get('fork_parent_id')
449 fork_of = form_data.get('fork_parent_id')
447
450
448 ## repo creation defaults, private and repo_type are filled in form
451 ## repo creation defaults, private and repo_type are filled in form
449 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
452 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
450 enable_statistics = defs.get('repo_enable_statistics')
453 enable_statistics = defs.get('repo_enable_statistics')
451 enable_locking = defs.get('repo_enable_locking')
454 enable_locking = defs.get('repo_enable_locking')
452 enable_downloads = defs.get('repo_enable_downloads')
455 enable_downloads = defs.get('repo_enable_downloads')
453
456
454 return self.create_repo(
457 return self.create_repo(
455 repo_name, repo_type, description, owner, private, clone_uri,
458 repo_name, repo_type, description, owner, private, clone_uri,
456 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
459 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
457 enable_statistics, enable_locking, enable_downloads
460 enable_statistics, enable_locking, enable_downloads
458 )
461 )
459
462
460 def _update_permissions(self, repo, perms_new=None,
463 def _update_permissions(self, repo, perms_new=None,
461 perms_updates=None):
464 perms_updates=None):
462 if not perms_new:
465 if not perms_new:
463 perms_new = []
466 perms_new = []
464 if not perms_updates:
467 if not perms_updates:
465 perms_updates = []
468 perms_updates = []
466
469
467 # update permissions
470 # update permissions
468 for member, perm, member_type in perms_updates:
471 for member, perm, member_type in perms_updates:
469 if member_type == 'user':
472 if member_type == 'user':
470 # this updates existing one
473 # this updates existing one
471 self.grant_user_permission(
474 self.grant_user_permission(
472 repo=repo, user=member, perm=perm
475 repo=repo, user=member, perm=perm
473 )
476 )
474 else:
477 else:
478 #check if we have permissions to alter this usergroup
479 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
480 'usergroup.admin')(member):
475 self.grant_users_group_permission(
481 self.grant_users_group_permission(
476 repo=repo, group_name=member, perm=perm
482 repo=repo, group_name=member, perm=perm
477 )
483 )
478 # set new permissions
484 # set new permissions
479 for member, perm, member_type in perms_new:
485 for member, perm, member_type in perms_new:
480 if member_type == 'user':
486 if member_type == 'user':
481 self.grant_user_permission(
487 self.grant_user_permission(
482 repo=repo, user=member, perm=perm
488 repo=repo, user=member, perm=perm
483 )
489 )
484 else:
490 else:
491 #check if we have permissions to alter this usergroup
492 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
493 'usergroup.admin')(member):
485 self.grant_users_group_permission(
494 self.grant_users_group_permission(
486 repo=repo, group_name=member, perm=perm
495 repo=repo, group_name=member, perm=perm
487 )
496 )
488
497
489 def create_fork(self, form_data, cur_user):
498 def create_fork(self, form_data, cur_user):
490 """
499 """
491 Simple wrapper into executing celery task for fork creation
500 Simple wrapper into executing celery task for fork creation
492
501
493 :param form_data:
502 :param form_data:
494 :param cur_user:
503 :param cur_user:
495 """
504 """
496 from rhodecode.lib.celerylib import tasks, run_task
505 from rhodecode.lib.celerylib import tasks, run_task
497 run_task(tasks.create_repo_fork, form_data, cur_user)
506 run_task(tasks.create_repo_fork, form_data, cur_user)
498
507
499 def delete(self, repo, forks=None, fs_remove=True):
508 def delete(self, repo, forks=None, fs_remove=True):
500 """
509 """
501 Delete given repository, forks parameter defines what do do with
510 Delete given repository, forks parameter defines what do do with
502 attached forks. Throws AttachedForksError if deleted repo has attached
511 attached forks. Throws AttachedForksError if deleted repo has attached
503 forks
512 forks
504
513
505 :param repo:
514 :param repo:
506 :param forks: str 'delete' or 'detach'
515 :param forks: str 'delete' or 'detach'
507 :param fs_remove: remove(archive) repo from filesystem
516 :param fs_remove: remove(archive) repo from filesystem
508 """
517 """
509 repo = self._get_repo(repo)
518 repo = self._get_repo(repo)
510 if repo:
519 if repo:
511 if forks == 'detach':
520 if forks == 'detach':
512 for r in repo.forks:
521 for r in repo.forks:
513 r.fork = None
522 r.fork = None
514 self.sa.add(r)
523 self.sa.add(r)
515 elif forks == 'delete':
524 elif forks == 'delete':
516 for r in repo.forks:
525 for r in repo.forks:
517 self.delete(r, forks='delete')
526 self.delete(r, forks='delete')
518 elif [f for f in repo.forks]:
527 elif [f for f in repo.forks]:
519 raise AttachedForksError()
528 raise AttachedForksError()
520
529
521 old_repo_dict = repo.get_dict()
530 old_repo_dict = repo.get_dict()
522 owner = repo.user
531 owner = repo.user
523 try:
532 try:
524 self.sa.delete(repo)
533 self.sa.delete(repo)
525 if fs_remove:
534 if fs_remove:
526 self.__delete_repo(repo)
535 self.__delete_repo(repo)
527 else:
536 else:
528 log.debug('skipping removal from filesystem')
537 log.debug('skipping removal from filesystem')
529 log_delete_repository(old_repo_dict,
538 log_delete_repository(old_repo_dict,
530 deleted_by=owner.username)
539 deleted_by=owner.username)
531 except Exception:
540 except Exception:
532 log.error(traceback.format_exc())
541 log.error(traceback.format_exc())
533 raise
542 raise
534
543
535 def grant_user_permission(self, repo, user, perm):
544 def grant_user_permission(self, repo, user, perm):
536 """
545 """
537 Grant permission for user on given repository, or update existing one
546 Grant permission for user on given repository, or update existing one
538 if found
547 if found
539
548
540 :param repo: Instance of Repository, repository_id, or repository name
549 :param repo: Instance of Repository, repository_id, or repository name
541 :param user: Instance of User, user_id or username
550 :param user: Instance of User, user_id or username
542 :param perm: Instance of Permission, or permission_name
551 :param perm: Instance of Permission, or permission_name
543 """
552 """
544 user = self._get_user(user)
553 user = self._get_user(user)
545 repo = self._get_repo(repo)
554 repo = self._get_repo(repo)
546 permission = self._get_perm(perm)
555 permission = self._get_perm(perm)
547
556
548 # check if we have that permission already
557 # check if we have that permission already
549 obj = self.sa.query(UserRepoToPerm)\
558 obj = self.sa.query(UserRepoToPerm)\
550 .filter(UserRepoToPerm.user == user)\
559 .filter(UserRepoToPerm.user == user)\
551 .filter(UserRepoToPerm.repository == repo)\
560 .filter(UserRepoToPerm.repository == repo)\
552 .scalar()
561 .scalar()
553 if obj is None:
562 if obj is None:
554 # create new !
563 # create new !
555 obj = UserRepoToPerm()
564 obj = UserRepoToPerm()
556 obj.repository = repo
565 obj.repository = repo
557 obj.user = user
566 obj.user = user
558 obj.permission = permission
567 obj.permission = permission
559 self.sa.add(obj)
568 self.sa.add(obj)
560 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
569 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
561
570
562 def revoke_user_permission(self, repo, user):
571 def revoke_user_permission(self, repo, user):
563 """
572 """
564 Revoke permission for user on given repository
573 Revoke permission for user on given repository
565
574
566 :param repo: Instance of Repository, repository_id, or repository name
575 :param repo: Instance of Repository, repository_id, or repository name
567 :param user: Instance of User, user_id or username
576 :param user: Instance of User, user_id or username
568 """
577 """
569
578
570 user = self._get_user(user)
579 user = self._get_user(user)
571 repo = self._get_repo(repo)
580 repo = self._get_repo(repo)
572
581
573 obj = self.sa.query(UserRepoToPerm)\
582 obj = self.sa.query(UserRepoToPerm)\
574 .filter(UserRepoToPerm.repository == repo)\
583 .filter(UserRepoToPerm.repository == repo)\
575 .filter(UserRepoToPerm.user == user)\
584 .filter(UserRepoToPerm.user == user)\
576 .scalar()
585 .scalar()
577 if obj:
586 if obj:
578 self.sa.delete(obj)
587 self.sa.delete(obj)
579 log.debug('Revoked perm on %s on %s' % (repo, user))
588 log.debug('Revoked perm on %s on %s' % (repo, user))
580
589
581 def grant_users_group_permission(self, repo, group_name, perm):
590 def grant_users_group_permission(self, repo, group_name, perm):
582 """
591 """
583 Grant permission for user group on given repository, or update
592 Grant permission for user group on given repository, or update
584 existing one if found
593 existing one if found
585
594
586 :param repo: Instance of Repository, repository_id, or repository name
595 :param repo: Instance of Repository, repository_id, or repository name
587 :param group_name: Instance of UserGroup, users_group_id,
596 :param group_name: Instance of UserGroup, users_group_id,
588 or user group name
597 or user group name
589 :param perm: Instance of Permission, or permission_name
598 :param perm: Instance of Permission, or permission_name
590 """
599 """
591 repo = self._get_repo(repo)
600 repo = self._get_repo(repo)
592 group_name = self._get_user_group(group_name)
601 group_name = self._get_user_group(group_name)
593 permission = self._get_perm(perm)
602 permission = self._get_perm(perm)
594
603
595 # check if we have that permission already
604 # check if we have that permission already
596 obj = self.sa.query(UserGroupRepoToPerm)\
605 obj = self.sa.query(UserGroupRepoToPerm)\
597 .filter(UserGroupRepoToPerm.users_group == group_name)\
606 .filter(UserGroupRepoToPerm.users_group == group_name)\
598 .filter(UserGroupRepoToPerm.repository == repo)\
607 .filter(UserGroupRepoToPerm.repository == repo)\
599 .scalar()
608 .scalar()
600
609
601 if obj is None:
610 if obj is None:
602 # create new
611 # create new
603 obj = UserGroupRepoToPerm()
612 obj = UserGroupRepoToPerm()
604
613
605 obj.repository = repo
614 obj.repository = repo
606 obj.users_group = group_name
615 obj.users_group = group_name
607 obj.permission = permission
616 obj.permission = permission
608 self.sa.add(obj)
617 self.sa.add(obj)
609 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
618 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
610
619
611 def revoke_users_group_permission(self, repo, group_name):
620 def revoke_users_group_permission(self, repo, group_name):
612 """
621 """
613 Revoke permission for user group on given repository
622 Revoke permission for user group on given repository
614
623
615 :param repo: Instance of Repository, repository_id, or repository name
624 :param repo: Instance of Repository, repository_id, or repository name
616 :param group_name: Instance of UserGroup, users_group_id,
625 :param group_name: Instance of UserGroup, users_group_id,
617 or user group name
626 or user group name
618 """
627 """
619 repo = self._get_repo(repo)
628 repo = self._get_repo(repo)
620 group_name = self._get_user_group(group_name)
629 group_name = self._get_user_group(group_name)
621
630
622 obj = self.sa.query(UserGroupRepoToPerm)\
631 obj = self.sa.query(UserGroupRepoToPerm)\
623 .filter(UserGroupRepoToPerm.repository == repo)\
632 .filter(UserGroupRepoToPerm.repository == repo)\
624 .filter(UserGroupRepoToPerm.users_group == group_name)\
633 .filter(UserGroupRepoToPerm.users_group == group_name)\
625 .scalar()
634 .scalar()
626 if obj:
635 if obj:
627 self.sa.delete(obj)
636 self.sa.delete(obj)
628 log.debug('Revoked perm to %s on %s' % (repo, group_name))
637 log.debug('Revoked perm to %s on %s' % (repo, group_name))
629
638
630 def delete_stats(self, repo_name):
639 def delete_stats(self, repo_name):
631 """
640 """
632 removes stats for given repo
641 removes stats for given repo
633
642
634 :param repo_name:
643 :param repo_name:
635 """
644 """
636 repo = self._get_repo(repo_name)
645 repo = self._get_repo(repo_name)
637 try:
646 try:
638 obj = self.sa.query(Statistics)\
647 obj = self.sa.query(Statistics)\
639 .filter(Statistics.repository == repo).scalar()
648 .filter(Statistics.repository == repo).scalar()
640 if obj:
649 if obj:
641 self.sa.delete(obj)
650 self.sa.delete(obj)
642 except Exception:
651 except Exception:
643 log.error(traceback.format_exc())
652 log.error(traceback.format_exc())
644 raise
653 raise
645
654
646 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
655 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
647 """
656 """
648 makes repository on filesystem. It's group aware means it'll create
657 makes repository on filesystem. It's group aware means it'll create
649 a repository within a group, and alter the paths accordingly of
658 a repository within a group, and alter the paths accordingly of
650 group location
659 group location
651
660
652 :param repo_name:
661 :param repo_name:
653 :param alias:
662 :param alias:
654 :param parent_id:
663 :param parent_id:
655 :param clone_uri:
664 :param clone_uri:
656 """
665 """
657 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
666 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
658 from rhodecode.model.scm import ScmModel
667 from rhodecode.model.scm import ScmModel
659
668
660 if parent:
669 if parent:
661 new_parent_path = os.sep.join(parent.full_path_splitted)
670 new_parent_path = os.sep.join(parent.full_path_splitted)
662 else:
671 else:
663 new_parent_path = ''
672 new_parent_path = ''
664
673
665 # we need to make it str for mercurial
674 # we need to make it str for mercurial
666 repo_path = os.path.join(*map(lambda x: safe_str(x),
675 repo_path = os.path.join(*map(lambda x: safe_str(x),
667 [self.repos_path, new_parent_path, repo_name]))
676 [self.repos_path, new_parent_path, repo_name]))
668
677
669 # check if this path is not a repository
678 # check if this path is not a repository
670 if is_valid_repo(repo_path, self.repos_path):
679 if is_valid_repo(repo_path, self.repos_path):
671 raise Exception('This path %s is a valid repository' % repo_path)
680 raise Exception('This path %s is a valid repository' % repo_path)
672
681
673 # check if this path is a group
682 # check if this path is a group
674 if is_valid_repos_group(repo_path, self.repos_path):
683 if is_valid_repos_group(repo_path, self.repos_path):
675 raise Exception('This path %s is a valid group' % repo_path)
684 raise Exception('This path %s is a valid group' % repo_path)
676
685
677 log.info('creating repo %s in %s @ %s' % (
686 log.info('creating repo %s in %s @ %s' % (
678 repo_name, safe_unicode(repo_path),
687 repo_name, safe_unicode(repo_path),
679 obfuscate_url_pw(clone_uri)
688 obfuscate_url_pw(clone_uri)
680 )
689 )
681 )
690 )
682 backend = get_backend(alias)
691 backend = get_backend(alias)
683 if alias == 'hg':
692 if alias == 'hg':
684 backend(repo_path, create=True, src_url=clone_uri)
693 backend(repo_path, create=True, src_url=clone_uri)
685 elif alias == 'git':
694 elif alias == 'git':
686 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
695 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
687 # add rhodecode hook into this repo
696 # add rhodecode hook into this repo
688 ScmModel().install_git_hook(repo=r)
697 ScmModel().install_git_hook(repo=r)
689 else:
698 else:
690 raise Exception('Undefined alias %s' % alias)
699 raise Exception('Undefined alias %s' % alias)
691
700
692 def __rename_repo(self, old, new):
701 def __rename_repo(self, old, new):
693 """
702 """
694 renames repository on filesystem
703 renames repository on filesystem
695
704
696 :param old: old name
705 :param old: old name
697 :param new: new name
706 :param new: new name
698 """
707 """
699 log.info('renaming repo from %s to %s' % (old, new))
708 log.info('renaming repo from %s to %s' % (old, new))
700
709
701 old_path = os.path.join(self.repos_path, old)
710 old_path = os.path.join(self.repos_path, old)
702 new_path = os.path.join(self.repos_path, new)
711 new_path = os.path.join(self.repos_path, new)
703 if os.path.isdir(new_path):
712 if os.path.isdir(new_path):
704 raise Exception(
713 raise Exception(
705 'Was trying to rename to already existing dir %s' % new_path
714 'Was trying to rename to already existing dir %s' % new_path
706 )
715 )
707 shutil.move(old_path, new_path)
716 shutil.move(old_path, new_path)
708
717
709 def __delete_repo(self, repo):
718 def __delete_repo(self, repo):
710 """
719 """
711 removes repo from filesystem, the removal is acctually made by
720 removes repo from filesystem, the removal is acctually made by
712 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
721 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
713 repository is no longer valid for rhodecode, can be undeleted later on
722 repository is no longer valid for rhodecode, can be undeleted later on
714 by reverting the renames on this repository
723 by reverting the renames on this repository
715
724
716 :param repo: repo object
725 :param repo: repo object
717 """
726 """
718 rm_path = os.path.join(self.repos_path, repo.repo_name)
727 rm_path = os.path.join(self.repos_path, repo.repo_name)
719 log.info("Removing %s" % (rm_path))
728 log.info("Removing %s" % (rm_path))
720 # disable hg/git internal that it doesn't get detected as repo
729 # disable hg/git internal that it doesn't get detected as repo
721 alias = repo.repo_type
730 alias = repo.repo_type
722
731
723 bare = getattr(repo.scm_instance, 'bare', False)
732 bare = getattr(repo.scm_instance, 'bare', False)
724
733
725 if not bare:
734 if not bare:
726 # skip this for bare git repos
735 # skip this for bare git repos
727 shutil.move(os.path.join(rm_path, '.%s' % alias),
736 shutil.move(os.path.join(rm_path, '.%s' % alias),
728 os.path.join(rm_path, 'rm__.%s' % alias))
737 os.path.join(rm_path, 'rm__.%s' % alias))
729 # disable repo
738 # disable repo
730 _now = datetime.now()
739 _now = datetime.now()
731 _ms = str(_now.microsecond).rjust(6, '0')
740 _ms = str(_now.microsecond).rjust(6, '0')
732 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
741 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
733 repo.just_name)
742 repo.just_name)
734 if repo.group:
743 if repo.group:
735 args = repo.group.full_path_splitted + [_d]
744 args = repo.group.full_path_splitted + [_d]
736 _d = os.path.join(*args)
745 _d = os.path.join(*args)
737 shutil.move(rm_path, os.path.join(self.repos_path, _d))
746 shutil.move(rm_path, os.path.join(self.repos_path, _d))
@@ -1,429 +1,436 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user_group
3 rhodecode.model.user_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 repo group model for RhodeCode
6 repo group model for RhodeCode
7
7
8 :created_on: Jan 25, 2011
8 :created_on: Jan 25, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import traceback
28 import traceback
29 import shutil
29 import shutil
30 import datetime
30 import datetime
31
31
32 from rhodecode.lib.utils2 import LazyProperty
32 from rhodecode.lib.utils2 import LazyProperty
33
33
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
35 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
36 User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository
36 User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 class ReposGroupModel(BaseModel):
41 class ReposGroupModel(BaseModel):
42
42
43 cls = RepoGroup
43 cls = RepoGroup
44
44
45 def _get_user_group(self, users_group):
45 def _get_user_group(self, users_group):
46 return self._get_instance(UserGroup, users_group,
46 return self._get_instance(UserGroup, users_group,
47 callback=UserGroup.get_by_group_name)
47 callback=UserGroup.get_by_group_name)
48
48
49 def _get_repo_group(self, repos_group):
49 def _get_repo_group(self, repos_group):
50 return self._get_instance(RepoGroup, repos_group,
50 return self._get_instance(RepoGroup, repos_group,
51 callback=RepoGroup.get_by_group_name)
51 callback=RepoGroup.get_by_group_name)
52
52
53 @LazyProperty
53 @LazyProperty
54 def repos_path(self):
54 def repos_path(self):
55 """
55 """
56 Get's the repositories root path from database
56 Get's the repositories root path from database
57 """
57 """
58
58
59 q = RhodeCodeUi.get_by_key('/')
59 q = RhodeCodeUi.get_by_key('/')
60 return q.ui_value
60 return q.ui_value
61
61
62 def _create_default_perms(self, new_group):
62 def _create_default_perms(self, new_group):
63 # create default permission
63 # create default permission
64 default_perm = 'group.read'
64 default_perm = 'group.read'
65 def_user = User.get_default_user()
65 def_user = User.get_default_user()
66 for p in def_user.user_perms:
66 for p in def_user.user_perms:
67 if p.permission.permission_name.startswith('group.'):
67 if p.permission.permission_name.startswith('group.'):
68 default_perm = p.permission.permission_name
68 default_perm = p.permission.permission_name
69 break
69 break
70
70
71 repo_group_to_perm = UserRepoGroupToPerm()
71 repo_group_to_perm = UserRepoGroupToPerm()
72 repo_group_to_perm.permission = Permission.get_by_key(default_perm)
72 repo_group_to_perm.permission = Permission.get_by_key(default_perm)
73
73
74 repo_group_to_perm.group = new_group
74 repo_group_to_perm.group = new_group
75 repo_group_to_perm.user_id = def_user.user_id
75 repo_group_to_perm.user_id = def_user.user_id
76 return repo_group_to_perm
76 return repo_group_to_perm
77
77
78 def __create_group(self, group_name):
78 def __create_group(self, group_name):
79 """
79 """
80 makes repository group on filesystem
80 makes repository group on filesystem
81
81
82 :param repo_name:
82 :param repo_name:
83 :param parent_id:
83 :param parent_id:
84 """
84 """
85
85
86 create_path = os.path.join(self.repos_path, group_name)
86 create_path = os.path.join(self.repos_path, group_name)
87 log.debug('creating new group in %s' % create_path)
87 log.debug('creating new group in %s' % create_path)
88
88
89 if os.path.isdir(create_path):
89 if os.path.isdir(create_path):
90 raise Exception('That directory already exists !')
90 raise Exception('That directory already exists !')
91
91
92 os.makedirs(create_path)
92 os.makedirs(create_path)
93
93
94 def __rename_group(self, old, new):
94 def __rename_group(self, old, new):
95 """
95 """
96 Renames a group on filesystem
96 Renames a group on filesystem
97
97
98 :param group_name:
98 :param group_name:
99 """
99 """
100
100
101 if old == new:
101 if old == new:
102 log.debug('skipping group rename')
102 log.debug('skipping group rename')
103 return
103 return
104
104
105 log.debug('renaming repository group from %s to %s' % (old, new))
105 log.debug('renaming repository group from %s to %s' % (old, new))
106
106
107 old_path = os.path.join(self.repos_path, old)
107 old_path = os.path.join(self.repos_path, old)
108 new_path = os.path.join(self.repos_path, new)
108 new_path = os.path.join(self.repos_path, new)
109
109
110 log.debug('renaming repos paths from %s to %s' % (old_path, new_path))
110 log.debug('renaming repos paths from %s to %s' % (old_path, new_path))
111
111
112 if os.path.isdir(new_path):
112 if os.path.isdir(new_path):
113 raise Exception('Was trying to rename to already '
113 raise Exception('Was trying to rename to already '
114 'existing dir %s' % new_path)
114 'existing dir %s' % new_path)
115 shutil.move(old_path, new_path)
115 shutil.move(old_path, new_path)
116
116
117 def __delete_group(self, group, force_delete=False):
117 def __delete_group(self, group, force_delete=False):
118 """
118 """
119 Deletes a group from a filesystem
119 Deletes a group from a filesystem
120
120
121 :param group: instance of group from database
121 :param group: instance of group from database
122 :param force_delete: use shutil rmtree to remove all objects
122 :param force_delete: use shutil rmtree to remove all objects
123 """
123 """
124 paths = group.full_path.split(RepoGroup.url_sep())
124 paths = group.full_path.split(RepoGroup.url_sep())
125 paths = os.sep.join(paths)
125 paths = os.sep.join(paths)
126
126
127 rm_path = os.path.join(self.repos_path, paths)
127 rm_path = os.path.join(self.repos_path, paths)
128 log.info("Removing group %s" % (rm_path))
128 log.info("Removing group %s" % (rm_path))
129 # delete only if that path really exists
129 # delete only if that path really exists
130 if os.path.isdir(rm_path):
130 if os.path.isdir(rm_path):
131 if force_delete:
131 if force_delete:
132 shutil.rmtree(rm_path)
132 shutil.rmtree(rm_path)
133 else:
133 else:
134 #archive that group`
134 #archive that group`
135 _now = datetime.datetime.now()
135 _now = datetime.datetime.now()
136 _ms = str(_now.microsecond).rjust(6, '0')
136 _ms = str(_now.microsecond).rjust(6, '0')
137 _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
137 _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
138 group.name)
138 group.name)
139 shutil.move(rm_path, os.path.join(self.repos_path, _d))
139 shutil.move(rm_path, os.path.join(self.repos_path, _d))
140
140
141 def create(self, group_name, group_description, owner, parent=None, just_db=False):
141 def create(self, group_name, group_description, owner, parent=None, just_db=False):
142 try:
142 try:
143 new_repos_group = RepoGroup()
143 new_repos_group = RepoGroup()
144 new_repos_group.user = self._get_user(owner)
144 new_repos_group.user = self._get_user(owner)
145 new_repos_group.group_description = group_description or group_name
145 new_repos_group.group_description = group_description or group_name
146 new_repos_group.parent_group = self._get_repo_group(parent)
146 new_repos_group.parent_group = self._get_repo_group(parent)
147 new_repos_group.group_name = new_repos_group.get_new_name(group_name)
147 new_repos_group.group_name = new_repos_group.get_new_name(group_name)
148
148
149 self.sa.add(new_repos_group)
149 self.sa.add(new_repos_group)
150 perm_obj = self._create_default_perms(new_repos_group)
150 perm_obj = self._create_default_perms(new_repos_group)
151 self.sa.add(perm_obj)
151 self.sa.add(perm_obj)
152
152
153 #create an ADMIN permission for owner, later owner should go into
153 #create an ADMIN permission for owner, later owner should go into
154 #the owner field of groups
154 #the owner field of groups
155 self.grant_user_permission(repos_group=new_repos_group,
155 self.grant_user_permission(repos_group=new_repos_group,
156 user=owner, perm='group.admin')
156 user=owner, perm='group.admin')
157
157
158 if not just_db:
158 if not just_db:
159 # we need to flush here, in order to check if database won't
159 # we need to flush here, in order to check if database won't
160 # throw any exceptions, create filesystem dirs at the very end
160 # throw any exceptions, create filesystem dirs at the very end
161 self.sa.flush()
161 self.sa.flush()
162 self.__create_group(new_repos_group.group_name)
162 self.__create_group(new_repos_group.group_name)
163
163
164 return new_repos_group
164 return new_repos_group
165 except Exception:
165 except Exception:
166 log.error(traceback.format_exc())
166 log.error(traceback.format_exc())
167 raise
167 raise
168
168
169 def _update_permissions(self, repos_group, perms_new=None,
169 def _update_permissions(self, repos_group, perms_new=None,
170 perms_updates=None, recursive=False):
170 perms_updates=None, recursive=False):
171 from rhodecode.model.repo import RepoModel
171 from rhodecode.model.repo import RepoModel
172 from rhodecode.lib.auth import HasUserGroupPermissionAny
172 if not perms_new:
173 if not perms_new:
173 perms_new = []
174 perms_new = []
174 if not perms_updates:
175 if not perms_updates:
175 perms_updates = []
176 perms_updates = []
176
177
177 def _set_perm_user(obj, user, perm):
178 def _set_perm_user(obj, user, perm):
178 if isinstance(obj, RepoGroup):
179 if isinstance(obj, RepoGroup):
179 self.grant_user_permission(
180 self.grant_user_permission(
180 repos_group=obj, user=user, perm=perm
181 repos_group=obj, user=user, perm=perm
181 )
182 )
182 elif isinstance(obj, Repository):
183 elif isinstance(obj, Repository):
183 #we do this ONLY IF repository is non-private
184 #we do this ONLY IF repository is non-private
184 if obj.private:
185 if obj.private:
185 return
186 return
186
187
187 # we set group permission but we have to switch to repo
188 # we set group permission but we have to switch to repo
188 # permission
189 # permission
189 perm = perm.replace('group.', 'repository.')
190 perm = perm.replace('group.', 'repository.')
190 RepoModel().grant_user_permission(
191 RepoModel().grant_user_permission(
191 repo=obj, user=user, perm=perm
192 repo=obj, user=user, perm=perm
192 )
193 )
193
194
194 def _set_perm_group(obj, users_group, perm):
195 def _set_perm_group(obj, users_group, perm):
195 if isinstance(obj, RepoGroup):
196 if isinstance(obj, RepoGroup):
196 self.grant_users_group_permission(
197 self.grant_users_group_permission(
197 repos_group=obj, group_name=users_group, perm=perm
198 repos_group=obj, group_name=users_group, perm=perm
198 )
199 )
199 elif isinstance(obj, Repository):
200 elif isinstance(obj, Repository):
200 # we set group permission but we have to switch to repo
201 # we set group permission but we have to switch to repo
201 # permission
202 # permission
202 perm = perm.replace('group.', 'repository.')
203 perm = perm.replace('group.', 'repository.')
203 RepoModel().grant_users_group_permission(
204 RepoModel().grant_users_group_permission(
204 repo=obj, group_name=users_group, perm=perm
205 repo=obj, group_name=users_group, perm=perm
205 )
206 )
206 updates = []
207 updates = []
207 log.debug('Now updating permissions for %s in recursive mode:%s'
208 log.debug('Now updating permissions for %s in recursive mode:%s'
208 % (repos_group, recursive))
209 % (repos_group, recursive))
209
210
210 for obj in repos_group.recursive_groups_and_repos():
211 for obj in repos_group.recursive_groups_and_repos():
211 #obj is an instance of a group or repositories in that group
212 #obj is an instance of a group or repositories in that group
212 if not recursive:
213 if not recursive:
213 obj = repos_group
214 obj = repos_group
214
215
215 # update permissions
216 # update permissions
216 for member, perm, member_type in perms_updates:
217 for member, perm, member_type in perms_updates:
217 ## set for user
218 ## set for user
218 if member_type == 'user':
219 if member_type == 'user':
219 # this updates also current one if found
220 # this updates also current one if found
220 _set_perm_user(obj, user=member, perm=perm)
221 _set_perm_user(obj, user=member, perm=perm)
221 ## set for user group
222 ## set for user group
222 else:
223 else:
224 #check if we have permissions to alter this usergroup
225 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
226 'usergroup.admin')(member):
223 _set_perm_group(obj, users_group=member, perm=perm)
227 _set_perm_group(obj, users_group=member, perm=perm)
224 # set new permissions
228 # set new permissions
225 for member, perm, member_type in perms_new:
229 for member, perm, member_type in perms_new:
226 if member_type == 'user':
230 if member_type == 'user':
227 _set_perm_user(obj, user=member, perm=perm)
231 _set_perm_user(obj, user=member, perm=perm)
228 else:
232 else:
233 #check if we have permissions to alter this usergroup
234 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
235 'usergroup.admin')(member):
229 _set_perm_group(obj, users_group=member, perm=perm)
236 _set_perm_group(obj, users_group=member, perm=perm)
230 updates.append(obj)
237 updates.append(obj)
231 #if it's not recursive call
238 #if it's not recursive call
232 # break the loop and don't proceed with other changes
239 # break the loop and don't proceed with other changes
233 if not recursive:
240 if not recursive:
234 break
241 break
235 return updates
242 return updates
236
243
237 def update(self, repos_group, form_data):
244 def update(self, repos_group, form_data):
238
245
239 try:
246 try:
240 repos_group = self._get_repo_group(repos_group)
247 repos_group = self._get_repo_group(repos_group)
241 old_path = repos_group.full_path
248 old_path = repos_group.full_path
242
249
243 # change properties
250 # change properties
244 repos_group.group_description = form_data['group_description']
251 repos_group.group_description = form_data['group_description']
245 repos_group.group_parent_id = form_data['group_parent_id']
252 repos_group.group_parent_id = form_data['group_parent_id']
246 repos_group.enable_locking = form_data['enable_locking']
253 repos_group.enable_locking = form_data['enable_locking']
247
254
248 repos_group.parent_group = RepoGroup.get(form_data['group_parent_id'])
255 repos_group.parent_group = RepoGroup.get(form_data['group_parent_id'])
249 repos_group.group_name = repos_group.get_new_name(form_data['group_name'])
256 repos_group.group_name = repos_group.get_new_name(form_data['group_name'])
250 new_path = repos_group.full_path
257 new_path = repos_group.full_path
251 self.sa.add(repos_group)
258 self.sa.add(repos_group)
252
259
253 # iterate over all members of this groups and do fixes
260 # iterate over all members of this groups and do fixes
254 # set locking if given
261 # set locking if given
255 # if obj is a repoGroup also fix the name of the group according
262 # if obj is a repoGroup also fix the name of the group according
256 # to the parent
263 # to the parent
257 # if obj is a Repo fix it's name
264 # if obj is a Repo fix it's name
258 # this can be potentially heavy operation
265 # this can be potentially heavy operation
259 for obj in repos_group.recursive_groups_and_repos():
266 for obj in repos_group.recursive_groups_and_repos():
260 #set the value from it's parent
267 #set the value from it's parent
261 obj.enable_locking = repos_group.enable_locking
268 obj.enable_locking = repos_group.enable_locking
262 if isinstance(obj, RepoGroup):
269 if isinstance(obj, RepoGroup):
263 new_name = obj.get_new_name(obj.name)
270 new_name = obj.get_new_name(obj.name)
264 log.debug('Fixing group %s to new name %s' \
271 log.debug('Fixing group %s to new name %s' \
265 % (obj.group_name, new_name))
272 % (obj.group_name, new_name))
266 obj.group_name = new_name
273 obj.group_name = new_name
267 elif isinstance(obj, Repository):
274 elif isinstance(obj, Repository):
268 # we need to get all repositories from this new group and
275 # we need to get all repositories from this new group and
269 # rename them accordingly to new group path
276 # rename them accordingly to new group path
270 new_name = obj.get_new_name(obj.just_name)
277 new_name = obj.get_new_name(obj.just_name)
271 log.debug('Fixing repo %s to new name %s' \
278 log.debug('Fixing repo %s to new name %s' \
272 % (obj.repo_name, new_name))
279 % (obj.repo_name, new_name))
273 obj.repo_name = new_name
280 obj.repo_name = new_name
274 self.sa.add(obj)
281 self.sa.add(obj)
275
282
276 self.__rename_group(old_path, new_path)
283 self.__rename_group(old_path, new_path)
277
284
278 return repos_group
285 return repos_group
279 except Exception:
286 except Exception:
280 log.error(traceback.format_exc())
287 log.error(traceback.format_exc())
281 raise
288 raise
282
289
283 def delete(self, repos_group, force_delete=False):
290 def delete(self, repos_group, force_delete=False):
284 repos_group = self._get_repo_group(repos_group)
291 repos_group = self._get_repo_group(repos_group)
285 try:
292 try:
286 self.sa.delete(repos_group)
293 self.sa.delete(repos_group)
287 self.__delete_group(repos_group, force_delete)
294 self.__delete_group(repos_group, force_delete)
288 except Exception:
295 except Exception:
289 log.error('Error removing repos_group %s' % repos_group)
296 log.error('Error removing repos_group %s' % repos_group)
290 raise
297 raise
291
298
292 def delete_permission(self, repos_group, obj, obj_type, recursive):
299 def delete_permission(self, repos_group, obj, obj_type, recursive):
293 """
300 """
294 Revokes permission for repos_group for given obj(user or users_group),
301 Revokes permission for repos_group for given obj(user or users_group),
295 obj_type can be user or user group
302 obj_type can be user or user group
296
303
297 :param repos_group:
304 :param repos_group:
298 :param obj: user or user group id
305 :param obj: user or user group id
299 :param obj_type: user or user group type
306 :param obj_type: user or user group type
300 :param recursive: recurse to all children of group
307 :param recursive: recurse to all children of group
301 """
308 """
302 from rhodecode.model.repo import RepoModel
309 from rhodecode.model.repo import RepoModel
303 repos_group = self._get_repo_group(repos_group)
310 repos_group = self._get_repo_group(repos_group)
304
311
305 for el in repos_group.recursive_groups_and_repos():
312 for el in repos_group.recursive_groups_and_repos():
306 if not recursive:
313 if not recursive:
307 # if we don't recurse set the permission on only the top level
314 # if we don't recurse set the permission on only the top level
308 # object
315 # object
309 el = repos_group
316 el = repos_group
310
317
311 if isinstance(el, RepoGroup):
318 if isinstance(el, RepoGroup):
312 if obj_type == 'user':
319 if obj_type == 'user':
313 ReposGroupModel().revoke_user_permission(el, user=obj)
320 ReposGroupModel().revoke_user_permission(el, user=obj)
314 elif obj_type == 'users_group':
321 elif obj_type == 'users_group':
315 ReposGroupModel().revoke_users_group_permission(el, group_name=obj)
322 ReposGroupModel().revoke_users_group_permission(el, group_name=obj)
316 else:
323 else:
317 raise Exception('undefined object type %s' % obj_type)
324 raise Exception('undefined object type %s' % obj_type)
318 elif isinstance(el, Repository):
325 elif isinstance(el, Repository):
319 if obj_type == 'user':
326 if obj_type == 'user':
320 RepoModel().revoke_user_permission(el, user=obj)
327 RepoModel().revoke_user_permission(el, user=obj)
321 elif obj_type == 'users_group':
328 elif obj_type == 'users_group':
322 RepoModel().revoke_users_group_permission(el, group_name=obj)
329 RepoModel().revoke_users_group_permission(el, group_name=obj)
323 else:
330 else:
324 raise Exception('undefined object type %s' % obj_type)
331 raise Exception('undefined object type %s' % obj_type)
325
332
326 #if it's not recursive call
333 #if it's not recursive call
327 # break the loop and don't proceed with other changes
334 # break the loop and don't proceed with other changes
328 if not recursive:
335 if not recursive:
329 break
336 break
330
337
331 def grant_user_permission(self, repos_group, user, perm):
338 def grant_user_permission(self, repos_group, user, perm):
332 """
339 """
333 Grant permission for user on given repository group, or update
340 Grant permission for user on given repository group, or update
334 existing one if found
341 existing one if found
335
342
336 :param repos_group: Instance of ReposGroup, repositories_group_id,
343 :param repos_group: Instance of ReposGroup, repositories_group_id,
337 or repositories_group name
344 or repositories_group name
338 :param user: Instance of User, user_id or username
345 :param user: Instance of User, user_id or username
339 :param perm: Instance of Permission, or permission_name
346 :param perm: Instance of Permission, or permission_name
340 """
347 """
341
348
342 repos_group = self._get_repo_group(repos_group)
349 repos_group = self._get_repo_group(repos_group)
343 user = self._get_user(user)
350 user = self._get_user(user)
344 permission = self._get_perm(perm)
351 permission = self._get_perm(perm)
345
352
346 # check if we have that permission already
353 # check if we have that permission already
347 obj = self.sa.query(UserRepoGroupToPerm)\
354 obj = self.sa.query(UserRepoGroupToPerm)\
348 .filter(UserRepoGroupToPerm.user == user)\
355 .filter(UserRepoGroupToPerm.user == user)\
349 .filter(UserRepoGroupToPerm.group == repos_group)\
356 .filter(UserRepoGroupToPerm.group == repos_group)\
350 .scalar()
357 .scalar()
351 if obj is None:
358 if obj is None:
352 # create new !
359 # create new !
353 obj = UserRepoGroupToPerm()
360 obj = UserRepoGroupToPerm()
354 obj.group = repos_group
361 obj.group = repos_group
355 obj.user = user
362 obj.user = user
356 obj.permission = permission
363 obj.permission = permission
357 self.sa.add(obj)
364 self.sa.add(obj)
358 log.debug('Granted perm %s to %s on %s' % (perm, user, repos_group))
365 log.debug('Granted perm %s to %s on %s' % (perm, user, repos_group))
359
366
360 def revoke_user_permission(self, repos_group, user):
367 def revoke_user_permission(self, repos_group, user):
361 """
368 """
362 Revoke permission for user on given repository group
369 Revoke permission for user on given repository group
363
370
364 :param repos_group: Instance of ReposGroup, repositories_group_id,
371 :param repos_group: Instance of ReposGroup, repositories_group_id,
365 or repositories_group name
372 or repositories_group name
366 :param user: Instance of User, user_id or username
373 :param user: Instance of User, user_id or username
367 """
374 """
368
375
369 repos_group = self._get_repo_group(repos_group)
376 repos_group = self._get_repo_group(repos_group)
370 user = self._get_user(user)
377 user = self._get_user(user)
371
378
372 obj = self.sa.query(UserRepoGroupToPerm)\
379 obj = self.sa.query(UserRepoGroupToPerm)\
373 .filter(UserRepoGroupToPerm.user == user)\
380 .filter(UserRepoGroupToPerm.user == user)\
374 .filter(UserRepoGroupToPerm.group == repos_group)\
381 .filter(UserRepoGroupToPerm.group == repos_group)\
375 .scalar()
382 .scalar()
376 if obj:
383 if obj:
377 self.sa.delete(obj)
384 self.sa.delete(obj)
378 log.debug('Revoked perm on %s on %s' % (repos_group, user))
385 log.debug('Revoked perm on %s on %s' % (repos_group, user))
379
386
380 def grant_users_group_permission(self, repos_group, group_name, perm):
387 def grant_users_group_permission(self, repos_group, group_name, perm):
381 """
388 """
382 Grant permission for user group on given repository group, or update
389 Grant permission for user group on given repository group, or update
383 existing one if found
390 existing one if found
384
391
385 :param repos_group: Instance of ReposGroup, repositories_group_id,
392 :param repos_group: Instance of ReposGroup, repositories_group_id,
386 or repositories_group name
393 or repositories_group name
387 :param group_name: Instance of UserGroup, users_group_id,
394 :param group_name: Instance of UserGroup, users_group_id,
388 or user group name
395 or user group name
389 :param perm: Instance of Permission, or permission_name
396 :param perm: Instance of Permission, or permission_name
390 """
397 """
391 repos_group = self._get_repo_group(repos_group)
398 repos_group = self._get_repo_group(repos_group)
392 group_name = self._get_user_group(group_name)
399 group_name = self._get_user_group(group_name)
393 permission = self._get_perm(perm)
400 permission = self._get_perm(perm)
394
401
395 # check if we have that permission already
402 # check if we have that permission already
396 obj = self.sa.query(UserGroupRepoGroupToPerm)\
403 obj = self.sa.query(UserGroupRepoGroupToPerm)\
397 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
404 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
398 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
405 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
399 .scalar()
406 .scalar()
400
407
401 if obj is None:
408 if obj is None:
402 # create new
409 # create new
403 obj = UserGroupRepoGroupToPerm()
410 obj = UserGroupRepoGroupToPerm()
404
411
405 obj.group = repos_group
412 obj.group = repos_group
406 obj.users_group = group_name
413 obj.users_group = group_name
407 obj.permission = permission
414 obj.permission = permission
408 self.sa.add(obj)
415 self.sa.add(obj)
409 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repos_group))
416 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repos_group))
410
417
411 def revoke_users_group_permission(self, repos_group, group_name):
418 def revoke_users_group_permission(self, repos_group, group_name):
412 """
419 """
413 Revoke permission for user group on given repository group
420 Revoke permission for user group on given repository group
414
421
415 :param repos_group: Instance of ReposGroup, repositories_group_id,
422 :param repos_group: Instance of ReposGroup, repositories_group_id,
416 or repositories_group name
423 or repositories_group name
417 :param group_name: Instance of UserGroup, users_group_id,
424 :param group_name: Instance of UserGroup, users_group_id,
418 or user group name
425 or user group name
419 """
426 """
420 repos_group = self._get_repo_group(repos_group)
427 repos_group = self._get_repo_group(repos_group)
421 group_name = self._get_user_group(group_name)
428 group_name = self._get_user_group(group_name)
422
429
423 obj = self.sa.query(UserGroupRepoGroupToPerm)\
430 obj = self.sa.query(UserGroupRepoGroupToPerm)\
424 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
431 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
425 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
432 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
426 .scalar()
433 .scalar()
427 if obj:
434 if obj:
428 self.sa.delete(obj)
435 self.sa.delete(obj)
429 log.debug('Revoked perm to %s on %s' % (repos_group, group_name))
436 log.debug('Revoked perm to %s on %s' % (repos_group, group_name))
@@ -1,343 +1,350 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.users_group
3 rhodecode.model.users_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 user group model for RhodeCode
6 user group model for RhodeCode
7
7
8 :created_on: Oct 1, 2011
8 :created_on: Oct 1, 2011
9 :author: nvinot
9 :author: nvinot
10 :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
10 :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software: you can redistribute it and/or modify
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
17 # (at your option) any later version.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26
26
27 import logging
27 import logging
28 import traceback
28 import traceback
29
29
30 from rhodecode.model import BaseModel
30 from rhodecode.model import BaseModel
31 from rhodecode.model.db import UserGroupMember, UserGroup,\
31 from rhodecode.model.db import UserGroupMember, UserGroup,\
32 UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\
32 UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\
33 UserGroupUserGroupToPerm
33 UserGroupUserGroupToPerm
34 from rhodecode.lib.exceptions import UserGroupsAssignedException,\
34 from rhodecode.lib.exceptions import UserGroupsAssignedException,\
35 RepoGroupAssignmentError
35 RepoGroupAssignmentError
36
36
37 log = logging.getLogger(__name__)
37 log = logging.getLogger(__name__)
38
38
39
39
40 class UserGroupModel(BaseModel):
40 class UserGroupModel(BaseModel):
41
41
42 cls = UserGroup
42 cls = UserGroup
43
43
44 def _get_user_group(self, users_group):
44 def _get_user_group(self, users_group):
45 return self._get_instance(UserGroup, users_group,
45 return self._get_instance(UserGroup, users_group,
46 callback=UserGroup.get_by_group_name)
46 callback=UserGroup.get_by_group_name)
47
47
48 def _create_default_perms(self, user_group):
48 def _create_default_perms(self, user_group):
49 # create default permission
49 # create default permission
50 default_perm = 'usergroup.read'
50 default_perm = 'usergroup.read'
51 def_user = User.get_default_user()
51 def_user = User.get_default_user()
52 for p in def_user.user_perms:
52 for p in def_user.user_perms:
53 if p.permission.permission_name.startswith('usergroup.'):
53 if p.permission.permission_name.startswith('usergroup.'):
54 default_perm = p.permission.permission_name
54 default_perm = p.permission.permission_name
55 break
55 break
56
56
57 user_group_to_perm = UserUserGroupToPerm()
57 user_group_to_perm = UserUserGroupToPerm()
58 user_group_to_perm.permission = Permission.get_by_key(default_perm)
58 user_group_to_perm.permission = Permission.get_by_key(default_perm)
59
59
60 user_group_to_perm.user_group = user_group
60 user_group_to_perm.user_group = user_group
61 user_group_to_perm.user_id = def_user.user_id
61 user_group_to_perm.user_id = def_user.user_id
62 return user_group_to_perm
62 return user_group_to_perm
63
63
64 def _update_permissions(self, user_group, perms_new=None,
64 def _update_permissions(self, user_group, perms_new=None,
65 perms_updates=None):
65 perms_updates=None):
66 from rhodecode.lib.auth import HasUserGroupPermissionAny
66 if not perms_new:
67 if not perms_new:
67 perms_new = []
68 perms_new = []
68 if not perms_updates:
69 if not perms_updates:
69 perms_updates = []
70 perms_updates = []
70
71
71 # update permissions
72 # update permissions
72 for member, perm, member_type in perms_updates:
73 for member, perm, member_type in perms_updates:
73 if member_type == 'user':
74 if member_type == 'user':
74 # this updates existing one
75 # this updates existing one
75 self.grant_user_permission(
76 self.grant_user_permission(
76 user_group=user_group, user=member, perm=perm
77 user_group=user_group, user=member, perm=perm
77 )
78 )
78 else:
79 else:
80 #check if we have permissions to alter this usergroup
81 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
82 'usergroup.admin')(member):
79 self.grant_users_group_permission(
83 self.grant_users_group_permission(
80 target_user_group=user_group, user_group=member, perm=perm
84 target_user_group=user_group, user_group=member, perm=perm
81 )
85 )
82 # set new permissions
86 # set new permissions
83 for member, perm, member_type in perms_new:
87 for member, perm, member_type in perms_new:
84 if member_type == 'user':
88 if member_type == 'user':
85 self.grant_user_permission(
89 self.grant_user_permission(
86 user_group=user_group, user=member, perm=perm
90 user_group=user_group, user=member, perm=perm
87 )
91 )
88 else:
92 else:
93 #check if we have permissions to alter this usergroup
94 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
95 'usergroup.admin')(member):
89 self.grant_users_group_permission(
96 self.grant_users_group_permission(
90 target_user_group=user_group, user_group=member, perm=perm
97 target_user_group=user_group, user_group=member, perm=perm
91 )
98 )
92
99
93 def get(self, users_group_id, cache=False):
100 def get(self, users_group_id, cache=False):
94 return UserGroup.get(users_group_id)
101 return UserGroup.get(users_group_id)
95
102
96 def get_group(self, users_group):
103 def get_group(self, users_group):
97 return self._get_user_group(users_group)
104 return self._get_user_group(users_group)
98
105
99 def get_by_name(self, name, cache=False, case_insensitive=False):
106 def get_by_name(self, name, cache=False, case_insensitive=False):
100 return UserGroup.get_by_group_name(name, cache, case_insensitive)
107 return UserGroup.get_by_group_name(name, cache, case_insensitive)
101
108
102 def create(self, name, owner, active=True):
109 def create(self, name, owner, active=True):
103 try:
110 try:
104 new_user_group = UserGroup()
111 new_user_group = UserGroup()
105 new_user_group.user = self._get_user(owner)
112 new_user_group.user = self._get_user(owner)
106 new_user_group.users_group_name = name
113 new_user_group.users_group_name = name
107 new_user_group.users_group_active = active
114 new_user_group.users_group_active = active
108 self.sa.add(new_user_group)
115 self.sa.add(new_user_group)
109 perm_obj = self._create_default_perms(new_user_group)
116 perm_obj = self._create_default_perms(new_user_group)
110 self.sa.add(perm_obj)
117 self.sa.add(perm_obj)
111
118
112 self.grant_user_permission(user_group=new_user_group,
119 self.grant_user_permission(user_group=new_user_group,
113 user=owner, perm='usergroup.admin')
120 user=owner, perm='usergroup.admin')
114
121
115 return new_user_group
122 return new_user_group
116 except Exception:
123 except Exception:
117 log.error(traceback.format_exc())
124 log.error(traceback.format_exc())
118 raise
125 raise
119
126
120 def update(self, users_group, form_data):
127 def update(self, users_group, form_data):
121
128
122 try:
129 try:
123 users_group = self._get_user_group(users_group)
130 users_group = self._get_user_group(users_group)
124
131
125 for k, v in form_data.items():
132 for k, v in form_data.items():
126 if k == 'users_group_members':
133 if k == 'users_group_members':
127 users_group.members = []
134 users_group.members = []
128 self.sa.flush()
135 self.sa.flush()
129 members_list = []
136 members_list = []
130 if v:
137 if v:
131 v = [v] if isinstance(v, basestring) else v
138 v = [v] if isinstance(v, basestring) else v
132 for u_id in set(v):
139 for u_id in set(v):
133 member = UserGroupMember(users_group.users_group_id, u_id)
140 member = UserGroupMember(users_group.users_group_id, u_id)
134 members_list.append(member)
141 members_list.append(member)
135 setattr(users_group, 'members', members_list)
142 setattr(users_group, 'members', members_list)
136 setattr(users_group, k, v)
143 setattr(users_group, k, v)
137
144
138 self.sa.add(users_group)
145 self.sa.add(users_group)
139 except Exception:
146 except Exception:
140 log.error(traceback.format_exc())
147 log.error(traceback.format_exc())
141 raise
148 raise
142
149
143 def delete(self, users_group, force=False):
150 def delete(self, users_group, force=False):
144 """
151 """
145 Deletes repository group, unless force flag is used
152 Deletes repository group, unless force flag is used
146 raises exception if there are members in that group, else deletes
153 raises exception if there are members in that group, else deletes
147 group and users
154 group and users
148
155
149 :param users_group:
156 :param users_group:
150 :param force:
157 :param force:
151 """
158 """
152 try:
159 try:
153 users_group = self._get_user_group(users_group)
160 users_group = self._get_user_group(users_group)
154
161
155 # check if this group is not assigned to repo
162 # check if this group is not assigned to repo
156 assigned_groups = UserGroupRepoToPerm.query()\
163 assigned_groups = UserGroupRepoToPerm.query()\
157 .filter(UserGroupRepoToPerm.users_group == users_group).all()
164 .filter(UserGroupRepoToPerm.users_group == users_group).all()
158
165
159 if assigned_groups and not force:
166 if assigned_groups and not force:
160 raise UserGroupsAssignedException('RepoGroup assigned to %s' %
167 raise UserGroupsAssignedException('RepoGroup assigned to %s' %
161 assigned_groups)
168 assigned_groups)
162
169
163 self.sa.delete(users_group)
170 self.sa.delete(users_group)
164 except Exception:
171 except Exception:
165 log.error(traceback.format_exc())
172 log.error(traceback.format_exc())
166 raise
173 raise
167
174
168 def add_user_to_group(self, users_group, user):
175 def add_user_to_group(self, users_group, user):
169 users_group = self._get_user_group(users_group)
176 users_group = self._get_user_group(users_group)
170 user = self._get_user(user)
177 user = self._get_user(user)
171
178
172 for m in users_group.members:
179 for m in users_group.members:
173 u = m.user
180 u = m.user
174 if u.user_id == user.user_id:
181 if u.user_id == user.user_id:
175 return True
182 return True
176
183
177 try:
184 try:
178 users_group_member = UserGroupMember()
185 users_group_member = UserGroupMember()
179 users_group_member.user = user
186 users_group_member.user = user
180 users_group_member.users_group = users_group
187 users_group_member.users_group = users_group
181
188
182 users_group.members.append(users_group_member)
189 users_group.members.append(users_group_member)
183 user.group_member.append(users_group_member)
190 user.group_member.append(users_group_member)
184
191
185 self.sa.add(users_group_member)
192 self.sa.add(users_group_member)
186 return users_group_member
193 return users_group_member
187 except Exception:
194 except Exception:
188 log.error(traceback.format_exc())
195 log.error(traceback.format_exc())
189 raise
196 raise
190
197
191 def remove_user_from_group(self, users_group, user):
198 def remove_user_from_group(self, users_group, user):
192 users_group = self._get_user_group(users_group)
199 users_group = self._get_user_group(users_group)
193 user = self._get_user(user)
200 user = self._get_user(user)
194
201
195 users_group_member = None
202 users_group_member = None
196 for m in users_group.members:
203 for m in users_group.members:
197 if m.user.user_id == user.user_id:
204 if m.user.user_id == user.user_id:
198 # Found this user's membership row
205 # Found this user's membership row
199 users_group_member = m
206 users_group_member = m
200 break
207 break
201
208
202 if users_group_member:
209 if users_group_member:
203 try:
210 try:
204 self.sa.delete(users_group_member)
211 self.sa.delete(users_group_member)
205 return True
212 return True
206 except Exception:
213 except Exception:
207 log.error(traceback.format_exc())
214 log.error(traceback.format_exc())
208 raise
215 raise
209 else:
216 else:
210 # User isn't in that group
217 # User isn't in that group
211 return False
218 return False
212
219
213 def has_perm(self, users_group, perm):
220 def has_perm(self, users_group, perm):
214 users_group = self._get_user_group(users_group)
221 users_group = self._get_user_group(users_group)
215 perm = self._get_perm(perm)
222 perm = self._get_perm(perm)
216
223
217 return UserGroupToPerm.query()\
224 return UserGroupToPerm.query()\
218 .filter(UserGroupToPerm.users_group == users_group)\
225 .filter(UserGroupToPerm.users_group == users_group)\
219 .filter(UserGroupToPerm.permission == perm).scalar() is not None
226 .filter(UserGroupToPerm.permission == perm).scalar() is not None
220
227
221 def grant_perm(self, users_group, perm):
228 def grant_perm(self, users_group, perm):
222 users_group = self._get_user_group(users_group)
229 users_group = self._get_user_group(users_group)
223 perm = self._get_perm(perm)
230 perm = self._get_perm(perm)
224
231
225 # if this permission is already granted skip it
232 # if this permission is already granted skip it
226 _perm = UserGroupToPerm.query()\
233 _perm = UserGroupToPerm.query()\
227 .filter(UserGroupToPerm.users_group == users_group)\
234 .filter(UserGroupToPerm.users_group == users_group)\
228 .filter(UserGroupToPerm.permission == perm)\
235 .filter(UserGroupToPerm.permission == perm)\
229 .scalar()
236 .scalar()
230 if _perm:
237 if _perm:
231 return
238 return
232
239
233 new = UserGroupToPerm()
240 new = UserGroupToPerm()
234 new.users_group = users_group
241 new.users_group = users_group
235 new.permission = perm
242 new.permission = perm
236 self.sa.add(new)
243 self.sa.add(new)
237
244
238 def revoke_perm(self, users_group, perm):
245 def revoke_perm(self, users_group, perm):
239 users_group = self._get_user_group(users_group)
246 users_group = self._get_user_group(users_group)
240 perm = self._get_perm(perm)
247 perm = self._get_perm(perm)
241
248
242 obj = UserGroupToPerm.query()\
249 obj = UserGroupToPerm.query()\
243 .filter(UserGroupToPerm.users_group == users_group)\
250 .filter(UserGroupToPerm.users_group == users_group)\
244 .filter(UserGroupToPerm.permission == perm).scalar()
251 .filter(UserGroupToPerm.permission == perm).scalar()
245 if obj:
252 if obj:
246 self.sa.delete(obj)
253 self.sa.delete(obj)
247
254
248 def grant_user_permission(self, user_group, user, perm):
255 def grant_user_permission(self, user_group, user, perm):
249 """
256 """
250 Grant permission for user on given user group, or update
257 Grant permission for user on given user group, or update
251 existing one if found
258 existing one if found
252
259
253 :param user_group: Instance of UserGroup, users_group_id,
260 :param user_group: Instance of UserGroup, users_group_id,
254 or users_group_name
261 or users_group_name
255 :param user: Instance of User, user_id or username
262 :param user: Instance of User, user_id or username
256 :param perm: Instance of Permission, or permission_name
263 :param perm: Instance of Permission, or permission_name
257 """
264 """
258
265
259 user_group = self._get_user_group(user_group)
266 user_group = self._get_user_group(user_group)
260 user = self._get_user(user)
267 user = self._get_user(user)
261 permission = self._get_perm(perm)
268 permission = self._get_perm(perm)
262
269
263 # check if we have that permission already
270 # check if we have that permission already
264 obj = self.sa.query(UserUserGroupToPerm)\
271 obj = self.sa.query(UserUserGroupToPerm)\
265 .filter(UserUserGroupToPerm.user == user)\
272 .filter(UserUserGroupToPerm.user == user)\
266 .filter(UserUserGroupToPerm.user_group == user_group)\
273 .filter(UserUserGroupToPerm.user_group == user_group)\
267 .scalar()
274 .scalar()
268 if obj is None:
275 if obj is None:
269 # create new !
276 # create new !
270 obj = UserUserGroupToPerm()
277 obj = UserUserGroupToPerm()
271 obj.user_group = user_group
278 obj.user_group = user_group
272 obj.user = user
279 obj.user = user
273 obj.permission = permission
280 obj.permission = permission
274 self.sa.add(obj)
281 self.sa.add(obj)
275 log.debug('Granted perm %s to %s on %s' % (perm, user, user_group))
282 log.debug('Granted perm %s to %s on %s' % (perm, user, user_group))
276
283
277 def revoke_user_permission(self, user_group, user):
284 def revoke_user_permission(self, user_group, user):
278 """
285 """
279 Revoke permission for user on given repository group
286 Revoke permission for user on given repository group
280
287
281 :param user_group: Instance of ReposGroup, repositories_group_id,
288 :param user_group: Instance of ReposGroup, repositories_group_id,
282 or repositories_group name
289 or repositories_group name
283 :param user: Instance of User, user_id or username
290 :param user: Instance of User, user_id or username
284 """
291 """
285
292
286 user_group = self._get_user_group(user_group)
293 user_group = self._get_user_group(user_group)
287 user = self._get_user(user)
294 user = self._get_user(user)
288
295
289 obj = self.sa.query(UserUserGroupToPerm)\
296 obj = self.sa.query(UserUserGroupToPerm)\
290 .filter(UserUserGroupToPerm.user == user)\
297 .filter(UserUserGroupToPerm.user == user)\
291 .filter(UserUserGroupToPerm.user_group == user_group)\
298 .filter(UserUserGroupToPerm.user_group == user_group)\
292 .scalar()
299 .scalar()
293 if obj:
300 if obj:
294 self.sa.delete(obj)
301 self.sa.delete(obj)
295 log.debug('Revoked perm on %s on %s' % (user_group, user))
302 log.debug('Revoked perm on %s on %s' % (user_group, user))
296
303
297 def grant_users_group_permission(self, target_user_group, user_group, perm):
304 def grant_users_group_permission(self, target_user_group, user_group, perm):
298 """
305 """
299 Grant user group permission for given target_user_group
306 Grant user group permission for given target_user_group
300
307
301 :param target_user_group:
308 :param target_user_group:
302 :param user_group:
309 :param user_group:
303 :param perm:
310 :param perm:
304 """
311 """
305 target_user_group = self._get_user_group(target_user_group)
312 target_user_group = self._get_user_group(target_user_group)
306 user_group = self._get_user_group(user_group)
313 user_group = self._get_user_group(user_group)
307 permission = self._get_perm(perm)
314 permission = self._get_perm(perm)
308 # forbid assigning same user group to itself
315 # forbid assigning same user group to itself
309 if target_user_group == user_group:
316 if target_user_group == user_group:
310 raise RepoGroupAssignmentError('target repo:%s cannot be '
317 raise RepoGroupAssignmentError('target repo:%s cannot be '
311 'assigned to itself' % target_user_group)
318 'assigned to itself' % target_user_group)
312
319
313 # check if we have that permission already
320 # check if we have that permission already
314 obj = self.sa.query(UserGroupUserGroupToPerm)\
321 obj = self.sa.query(UserGroupUserGroupToPerm)\
315 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
322 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
316 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
323 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
317 .scalar()
324 .scalar()
318 if obj is None:
325 if obj is None:
319 # create new !
326 # create new !
320 obj = UserGroupUserGroupToPerm()
327 obj = UserGroupUserGroupToPerm()
321 obj.user_group = user_group
328 obj.user_group = user_group
322 obj.target_user_group = target_user_group
329 obj.target_user_group = target_user_group
323 obj.permission = permission
330 obj.permission = permission
324 self.sa.add(obj)
331 self.sa.add(obj)
325 log.debug('Granted perm %s to %s on %s' % (perm, target_user_group, user_group))
332 log.debug('Granted perm %s to %s on %s' % (perm, target_user_group, user_group))
326
333
327 def revoke_users_group_permission(self, target_user_group, user_group):
334 def revoke_users_group_permission(self, target_user_group, user_group):
328 """
335 """
329 Revoke user group permission for given target_user_group
336 Revoke user group permission for given target_user_group
330
337
331 :param target_user_group:
338 :param target_user_group:
332 :param user_group:
339 :param user_group:
333 """
340 """
334 target_user_group = self._get_user_group(target_user_group)
341 target_user_group = self._get_user_group(target_user_group)
335 user_group = self._get_user_group(user_group)
342 user_group = self._get_user_group(user_group)
336
343
337 obj = self.sa.query(UserGroupUserGroupToPerm)\
344 obj = self.sa.query(UserGroupUserGroupToPerm)\
338 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
345 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
339 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
346 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
340 .scalar()
347 .scalar()
341 if obj:
348 if obj:
342 self.sa.delete(obj)
349 self.sa.delete(obj)
343 log.debug('Revoked perm on %s on %s' % (target_user_group, user_group))
350 log.debug('Revoked perm on %s on %s' % (target_user_group, user_group))
General Comments 0
You need to be logged in to leave comments. Login now