##// END OF EJS Templates
Replaced fallback username from ? to None in hook loggers
marcink -
r4018:727d2a45 default
parent child Browse files
Show More
@@ -1,757 +1,757 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, get_current_rhodecode_user
35 remove_prefix, obfuscate_url_pw, get_current_rhodecode_user
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, HasUserGroupPermissionAny
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 from rhodecode.model.scm import UserGroupList
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class RepoModel(BaseModel):
51 class RepoModel(BaseModel):
52
52
53 cls = Repository
53 cls = Repository
54 URL_SEPARATOR = Repository.url_sep()
54 URL_SEPARATOR = Repository.url_sep()
55
55
56 def _get_user_group(self, users_group):
56 def _get_user_group(self, users_group):
57 return self._get_instance(UserGroup, users_group,
57 return self._get_instance(UserGroup, users_group,
58 callback=UserGroup.get_by_group_name)
58 callback=UserGroup.get_by_group_name)
59
59
60 def _get_repo_group(self, repos_group):
60 def _get_repo_group(self, repos_group):
61 return self._get_instance(RepoGroup, repos_group,
61 return self._get_instance(RepoGroup, repos_group,
62 callback=RepoGroup.get_by_group_name)
62 callback=RepoGroup.get_by_group_name)
63
63
64 def _create_default_perms(self, repository, private):
64 def _create_default_perms(self, repository, private):
65 # create default permission
65 # create default permission
66 default = 'repository.read'
66 default = 'repository.read'
67 def_user = User.get_default_user()
67 def_user = User.get_default_user()
68 for p in def_user.user_perms:
68 for p in def_user.user_perms:
69 if p.permission.permission_name.startswith('repository.'):
69 if p.permission.permission_name.startswith('repository.'):
70 default = p.permission.permission_name
70 default = p.permission.permission_name
71 break
71 break
72
72
73 default_perm = 'repository.none' if private else default
73 default_perm = 'repository.none' if private else default
74
74
75 repo_to_perm = UserRepoToPerm()
75 repo_to_perm = UserRepoToPerm()
76 repo_to_perm.permission = Permission.get_by_key(default_perm)
76 repo_to_perm.permission = Permission.get_by_key(default_perm)
77
77
78 repo_to_perm.repository = repository
78 repo_to_perm.repository = repository
79 repo_to_perm.user_id = def_user.user_id
79 repo_to_perm.user_id = def_user.user_id
80
80
81 return repo_to_perm
81 return repo_to_perm
82
82
83 @LazyProperty
83 @LazyProperty
84 def repos_path(self):
84 def repos_path(self):
85 """
85 """
86 Get's the repositories root path from database
86 Get's the repositories root path from database
87 """
87 """
88
88
89 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
89 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
90 return q.ui_value
90 return q.ui_value
91
91
92 def get(self, repo_id, cache=False):
92 def get(self, repo_id, cache=False):
93 repo = self.sa.query(Repository)\
93 repo = self.sa.query(Repository)\
94 .filter(Repository.repo_id == repo_id)
94 .filter(Repository.repo_id == repo_id)
95
95
96 if cache:
96 if cache:
97 repo = repo.options(FromCache("sql_cache_short",
97 repo = repo.options(FromCache("sql_cache_short",
98 "get_repo_%s" % repo_id))
98 "get_repo_%s" % repo_id))
99 return repo.scalar()
99 return repo.scalar()
100
100
101 def get_repo(self, repository):
101 def get_repo(self, repository):
102 return self._get_repo(repository)
102 return self._get_repo(repository)
103
103
104 def get_by_repo_name(self, repo_name, cache=False):
104 def get_by_repo_name(self, repo_name, cache=False):
105 repo = self.sa.query(Repository)\
105 repo = self.sa.query(Repository)\
106 .filter(Repository.repo_name == repo_name)
106 .filter(Repository.repo_name == repo_name)
107
107
108 if cache:
108 if cache:
109 repo = repo.options(FromCache("sql_cache_short",
109 repo = repo.options(FromCache("sql_cache_short",
110 "get_repo_%s" % repo_name))
110 "get_repo_%s" % repo_name))
111 return repo.scalar()
111 return repo.scalar()
112
112
113 def get_all_user_repos(self, user):
113 def get_all_user_repos(self, user):
114 """
114 """
115 Get's all repositories that user have at least read access
115 Get's all repositories that user have at least read access
116
116
117 :param user:
117 :param user:
118 """
118 """
119 from rhodecode.lib.auth import AuthUser
119 from rhodecode.lib.auth import AuthUser
120 user = self._get_user(user)
120 user = self._get_user(user)
121 repos = AuthUser(user_id=user.user_id).permissions['repositories']
121 repos = AuthUser(user_id=user.user_id).permissions['repositories']
122 access_check = lambda r: r[1] in ['repository.read',
122 access_check = lambda r: r[1] in ['repository.read',
123 'repository.write',
123 'repository.write',
124 'repository.admin']
124 'repository.admin']
125 repos = [x[0] for x in filter(access_check, repos.items())]
125 repos = [x[0] for x in filter(access_check, repos.items())]
126 return Repository.query().filter(Repository.repo_name.in_(repos))
126 return Repository.query().filter(Repository.repo_name.in_(repos))
127
127
128 def get_users_js(self):
128 def get_users_js(self):
129 users = self.sa.query(User).filter(User.active == True).all()
129 users = self.sa.query(User).filter(User.active == True).all()
130 return json.dumps([
130 return json.dumps([
131 {
131 {
132 'id': u.user_id,
132 'id': u.user_id,
133 'fname': u.name,
133 'fname': u.name,
134 'lname': u.lastname,
134 'lname': u.lastname,
135 'nname': u.username,
135 'nname': u.username,
136 'gravatar_lnk': h.gravatar_url(u.email, 14)
136 'gravatar_lnk': h.gravatar_url(u.email, 14)
137 } for u in users]
137 } for u in users]
138 )
138 )
139
139
140 def get_users_groups_js(self):
140 def get_users_groups_js(self):
141 users_groups = self.sa.query(UserGroup)\
141 users_groups = self.sa.query(UserGroup)\
142 .filter(UserGroup.users_group_active == True).all()
142 .filter(UserGroup.users_group_active == True).all()
143 users_groups = UserGroupList(users_groups, perm_set=['usergroup.read',
143 users_groups = UserGroupList(users_groups, perm_set=['usergroup.read',
144 'usergroup.write',
144 'usergroup.write',
145 'usergroup.admin'])
145 'usergroup.admin'])
146 return json.dumps([
146 return json.dumps([
147 {
147 {
148 'id': gr.users_group_id,
148 'id': gr.users_group_id,
149 'grname': gr.users_group_name,
149 'grname': gr.users_group_name,
150 'grmembers': len(gr.members),
150 'grmembers': len(gr.members),
151 } for gr in users_groups]
151 } for gr in users_groups]
152 )
152 )
153
153
154 @classmethod
154 @classmethod
155 def _render_datatable(cls, tmpl, *args, **kwargs):
155 def _render_datatable(cls, tmpl, *args, **kwargs):
156 import rhodecode
156 import rhodecode
157 from pylons import tmpl_context as c
157 from pylons import tmpl_context as c
158 from pylons.i18n.translation import _
158 from pylons.i18n.translation import _
159
159
160 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
160 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
161 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
161 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
162
162
163 tmpl = template.get_def(tmpl)
163 tmpl = template.get_def(tmpl)
164 kwargs.update(dict(_=_, h=h, c=c))
164 kwargs.update(dict(_=_, h=h, c=c))
165 return tmpl.render(*args, **kwargs)
165 return tmpl.render(*args, **kwargs)
166
166
167 @classmethod
167 @classmethod
168 def update_repoinfo(cls, repositories=None):
168 def update_repoinfo(cls, repositories=None):
169 if not repositories:
169 if not repositories:
170 repositories = Repository.getAll()
170 repositories = Repository.getAll()
171 for repo in repositories:
171 for repo in repositories:
172 repo.update_changeset_cache()
172 repo.update_changeset_cache()
173
173
174 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
174 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
175 super_user_actions=False):
175 super_user_actions=False):
176 _render = self._render_datatable
176 _render = self._render_datatable
177 from pylons import tmpl_context as c
177 from pylons import tmpl_context as c
178
178
179 def quick_menu(repo_name):
179 def quick_menu(repo_name):
180 return _render('quick_menu', repo_name)
180 return _render('quick_menu', repo_name)
181
181
182 def repo_lnk(name, rtype, private, fork_of):
182 def repo_lnk(name, rtype, private, fork_of):
183 return _render('repo_name', name, rtype, private, fork_of,
183 return _render('repo_name', name, rtype, private, fork_of,
184 short_name=not admin, admin=False)
184 short_name=not admin, admin=False)
185
185
186 def last_change(last_change):
186 def last_change(last_change):
187 return _render("last_change", last_change)
187 return _render("last_change", last_change)
188
188
189 def rss_lnk(repo_name):
189 def rss_lnk(repo_name):
190 return _render("rss", repo_name)
190 return _render("rss", repo_name)
191
191
192 def atom_lnk(repo_name):
192 def atom_lnk(repo_name):
193 return _render("atom", repo_name)
193 return _render("atom", repo_name)
194
194
195 def last_rev(repo_name, cs_cache):
195 def last_rev(repo_name, cs_cache):
196 return _render('revision', repo_name, cs_cache.get('revision'),
196 return _render('revision', repo_name, cs_cache.get('revision'),
197 cs_cache.get('raw_id'), cs_cache.get('author'),
197 cs_cache.get('raw_id'), cs_cache.get('author'),
198 cs_cache.get('message'))
198 cs_cache.get('message'))
199
199
200 def desc(desc):
200 def desc(desc):
201 if c.visual.stylify_metatags:
201 if c.visual.stylify_metatags:
202 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
202 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
203 else:
203 else:
204 return h.urlify_text(h.truncate(desc, 60))
204 return h.urlify_text(h.truncate(desc, 60))
205
205
206 def repo_actions(repo_name):
206 def repo_actions(repo_name):
207 return _render('repo_actions', repo_name, super_user_actions)
207 return _render('repo_actions', repo_name, super_user_actions)
208
208
209 def owner_actions(user_id, username):
209 def owner_actions(user_id, username):
210 return _render('user_name', user_id, username)
210 return _render('user_name', user_id, username)
211
211
212 repos_data = []
212 repos_data = []
213 for repo in repos_list:
213 for repo in repos_list:
214 if perm_check:
214 if perm_check:
215 # check permission at this level
215 # check permission at this level
216 if not HasRepoPermissionAny(
216 if not HasRepoPermissionAny(
217 'repository.read', 'repository.write', 'repository.admin'
217 'repository.read', 'repository.write', 'repository.admin'
218 )(repo.repo_name, 'get_repos_as_dict check'):
218 )(repo.repo_name, 'get_repos_as_dict check'):
219 continue
219 continue
220 cs_cache = repo.changeset_cache
220 cs_cache = repo.changeset_cache
221 row = {
221 row = {
222 "menu": quick_menu(repo.repo_name),
222 "menu": quick_menu(repo.repo_name),
223 "raw_name": repo.repo_name.lower(),
223 "raw_name": repo.repo_name.lower(),
224 "name": repo_lnk(repo.repo_name, repo.repo_type,
224 "name": repo_lnk(repo.repo_name, repo.repo_type,
225 repo.private, repo.fork),
225 repo.private, repo.fork),
226 "last_change": last_change(repo.last_db_change),
226 "last_change": last_change(repo.last_db_change),
227 "last_changeset": last_rev(repo.repo_name, cs_cache),
227 "last_changeset": last_rev(repo.repo_name, cs_cache),
228 "raw_tip": cs_cache.get('revision'),
228 "raw_tip": cs_cache.get('revision'),
229 "desc": desc(repo.description),
229 "desc": desc(repo.description),
230 "owner": h.person(repo.user.username),
230 "owner": h.person(repo.user.username),
231 "rss": rss_lnk(repo.repo_name),
231 "rss": rss_lnk(repo.repo_name),
232 "atom": atom_lnk(repo.repo_name),
232 "atom": atom_lnk(repo.repo_name),
233
233
234 }
234 }
235 if admin:
235 if admin:
236 row.update({
236 row.update({
237 "action": repo_actions(repo.repo_name),
237 "action": repo_actions(repo.repo_name),
238 "owner": owner_actions(repo.user.user_id,
238 "owner": owner_actions(repo.user.user_id,
239 h.person(repo.user.username))
239 h.person(repo.user.username))
240 })
240 })
241 repos_data.append(row)
241 repos_data.append(row)
242
242
243 return {
243 return {
244 "totalRecords": len(repos_list),
244 "totalRecords": len(repos_list),
245 "startIndex": 0,
245 "startIndex": 0,
246 "sort": "name",
246 "sort": "name",
247 "dir": "asc",
247 "dir": "asc",
248 "records": repos_data
248 "records": repos_data
249 }
249 }
250
250
251 def _get_defaults(self, repo_name):
251 def _get_defaults(self, repo_name):
252 """
252 """
253 Get's information about repository, and returns a dict for
253 Get's information about repository, and returns a dict for
254 usage in forms
254 usage in forms
255
255
256 :param repo_name:
256 :param repo_name:
257 """
257 """
258
258
259 repo_info = Repository.get_by_repo_name(repo_name)
259 repo_info = Repository.get_by_repo_name(repo_name)
260
260
261 if repo_info is None:
261 if repo_info is None:
262 return None
262 return None
263
263
264 defaults = repo_info.get_dict()
264 defaults = repo_info.get_dict()
265 group, repo_name, repo_name_full = repo_info.groups_and_repo
265 group, repo_name, repo_name_full = repo_info.groups_and_repo
266 defaults['repo_name'] = repo_name
266 defaults['repo_name'] = repo_name
267 defaults['repo_group'] = getattr(group[-1] if group else None,
267 defaults['repo_group'] = getattr(group[-1] if group else None,
268 'group_id', None)
268 'group_id', None)
269
269
270 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
270 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
271 (1, 'repo_description'), (1, 'repo_enable_locking'),
271 (1, 'repo_description'), (1, 'repo_enable_locking'),
272 (1, 'repo_landing_rev'), (0, 'clone_uri'),
272 (1, 'repo_landing_rev'), (0, 'clone_uri'),
273 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
273 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
274 attr = k
274 attr = k
275 if strip:
275 if strip:
276 attr = remove_prefix(k, 'repo_')
276 attr = remove_prefix(k, 'repo_')
277
277
278 defaults[k] = defaults[attr]
278 defaults[k] = defaults[attr]
279
279
280 # fill owner
280 # fill owner
281 if repo_info.user:
281 if repo_info.user:
282 defaults.update({'user': repo_info.user.username})
282 defaults.update({'user': repo_info.user.username})
283 else:
283 else:
284 replacement_user = User.query().filter(User.admin ==
284 replacement_user = User.query().filter(User.admin ==
285 True).first().username
285 True).first().username
286 defaults.update({'user': replacement_user})
286 defaults.update({'user': replacement_user})
287
287
288 # fill repository users
288 # fill repository users
289 for p in repo_info.repo_to_perm:
289 for p in repo_info.repo_to_perm:
290 defaults.update({'u_perm_%s' % p.user.username:
290 defaults.update({'u_perm_%s' % p.user.username:
291 p.permission.permission_name})
291 p.permission.permission_name})
292
292
293 # fill repository groups
293 # fill repository groups
294 for p in repo_info.users_group_to_perm:
294 for p in repo_info.users_group_to_perm:
295 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
295 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
296 p.permission.permission_name})
296 p.permission.permission_name})
297
297
298 return defaults
298 return defaults
299
299
300 def update(self, org_repo_name, **kwargs):
300 def update(self, org_repo_name, **kwargs):
301 try:
301 try:
302 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
302 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
303
303
304 if 'user' in kwargs:
304 if 'user' in kwargs:
305 cur_repo.user = User.get_by_username(kwargs['user'])
305 cur_repo.user = User.get_by_username(kwargs['user'])
306
306
307 if 'repo_group' in kwargs:
307 if 'repo_group' in kwargs:
308 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
308 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
309
309
310 for strip, k in [(1, 'repo_enable_downloads'),
310 for strip, k in [(1, 'repo_enable_downloads'),
311 (1, 'repo_description'), (1, 'repo_enable_locking'),
311 (1, 'repo_description'), (1, 'repo_enable_locking'),
312 (1, 'repo_landing_rev'), (0, 'clone_uri'),
312 (1, 'repo_landing_rev'), (0, 'clone_uri'),
313 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
313 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
314 if k in kwargs:
314 if k in kwargs:
315 val = kwargs[k]
315 val = kwargs[k]
316 if strip:
316 if strip:
317 k = remove_prefix(k, 'repo_')
317 k = remove_prefix(k, 'repo_')
318 setattr(cur_repo, k, val)
318 setattr(cur_repo, k, val)
319
319
320 new_name = cur_repo.get_new_name(kwargs['repo_name'])
320 new_name = cur_repo.get_new_name(kwargs['repo_name'])
321 cur_repo.repo_name = new_name
321 cur_repo.repo_name = new_name
322 #if private flag is set, reset default permission to NONE
322 #if private flag is set, reset default permission to NONE
323
323
324 if kwargs.get('repo_private'):
324 if kwargs.get('repo_private'):
325 EMPTY_PERM = 'repository.none'
325 EMPTY_PERM = 'repository.none'
326 RepoModel().grant_user_permission(
326 RepoModel().grant_user_permission(
327 repo=cur_repo, user='default', perm=EMPTY_PERM
327 repo=cur_repo, user='default', perm=EMPTY_PERM
328 )
328 )
329 #handle extra fields
329 #handle extra fields
330 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
330 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
331 k = RepositoryField.un_prefix_key(field)
331 k = RepositoryField.un_prefix_key(field)
332 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
332 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
333 if ex_field:
333 if ex_field:
334 ex_field.field_value = kwargs[field]
334 ex_field.field_value = kwargs[field]
335 self.sa.add(ex_field)
335 self.sa.add(ex_field)
336 self.sa.add(cur_repo)
336 self.sa.add(cur_repo)
337
337
338 if org_repo_name != new_name:
338 if org_repo_name != new_name:
339 # rename repository
339 # rename repository
340 self.__rename_repo(old=org_repo_name, new=new_name)
340 self.__rename_repo(old=org_repo_name, new=new_name)
341
341
342 return cur_repo
342 return cur_repo
343 except Exception:
343 except Exception:
344 log.error(traceback.format_exc())
344 log.error(traceback.format_exc())
345 raise
345 raise
346
346
347 def create_repo(self, repo_name, repo_type, description, owner,
347 def create_repo(self, repo_name, repo_type, description, owner,
348 private=False, clone_uri=None, repos_group=None,
348 private=False, clone_uri=None, repos_group=None,
349 landing_rev='tip', just_db=False, fork_of=None,
349 landing_rev='tip', just_db=False, fork_of=None,
350 copy_fork_permissions=False, enable_statistics=False,
350 copy_fork_permissions=False, enable_statistics=False,
351 enable_locking=False, enable_downloads=False):
351 enable_locking=False, enable_downloads=False):
352 """
352 """
353 Create repository
353 Create repository
354
354
355 """
355 """
356 from rhodecode.model.scm import ScmModel
356 from rhodecode.model.scm import ScmModel
357
357
358 owner = self._get_user(owner)
358 owner = self._get_user(owner)
359 fork_of = self._get_repo(fork_of)
359 fork_of = self._get_repo(fork_of)
360 repos_group = self._get_repo_group(repos_group)
360 repos_group = self._get_repo_group(repos_group)
361 try:
361 try:
362
362
363 # repo name is just a name of repository
363 # repo name is just a name of repository
364 # while repo_name_full is a full qualified name that is combined
364 # while repo_name_full is a full qualified name that is combined
365 # with name and path of group
365 # with name and path of group
366 repo_name_full = repo_name
366 repo_name_full = repo_name
367 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
367 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
368
368
369 new_repo = Repository()
369 new_repo = Repository()
370 new_repo.enable_statistics = False
370 new_repo.enable_statistics = False
371 new_repo.repo_name = repo_name_full
371 new_repo.repo_name = repo_name_full
372 new_repo.repo_type = repo_type
372 new_repo.repo_type = repo_type
373 new_repo.user = owner
373 new_repo.user = owner
374 new_repo.group = repos_group
374 new_repo.group = repos_group
375 new_repo.description = description or repo_name
375 new_repo.description = description or repo_name
376 new_repo.private = private
376 new_repo.private = private
377 new_repo.clone_uri = clone_uri
377 new_repo.clone_uri = clone_uri
378 new_repo.landing_rev = landing_rev
378 new_repo.landing_rev = landing_rev
379
379
380 new_repo.enable_statistics = enable_statistics
380 new_repo.enable_statistics = enable_statistics
381 new_repo.enable_locking = enable_locking
381 new_repo.enable_locking = enable_locking
382 new_repo.enable_downloads = enable_downloads
382 new_repo.enable_downloads = enable_downloads
383
383
384 if repos_group:
384 if repos_group:
385 new_repo.enable_locking = repos_group.enable_locking
385 new_repo.enable_locking = repos_group.enable_locking
386
386
387 if fork_of:
387 if fork_of:
388 parent_repo = fork_of
388 parent_repo = fork_of
389 new_repo.fork = parent_repo
389 new_repo.fork = parent_repo
390
390
391 self.sa.add(new_repo)
391 self.sa.add(new_repo)
392
392
393 if fork_of:
393 if fork_of:
394 if copy_fork_permissions:
394 if copy_fork_permissions:
395 repo = fork_of
395 repo = fork_of
396 user_perms = UserRepoToPerm.query()\
396 user_perms = UserRepoToPerm.query()\
397 .filter(UserRepoToPerm.repository == repo).all()
397 .filter(UserRepoToPerm.repository == repo).all()
398 group_perms = UserGroupRepoToPerm.query()\
398 group_perms = UserGroupRepoToPerm.query()\
399 .filter(UserGroupRepoToPerm.repository == repo).all()
399 .filter(UserGroupRepoToPerm.repository == repo).all()
400
400
401 for perm in user_perms:
401 for perm in user_perms:
402 UserRepoToPerm.create(perm.user, new_repo,
402 UserRepoToPerm.create(perm.user, new_repo,
403 perm.permission)
403 perm.permission)
404
404
405 for perm in group_perms:
405 for perm in group_perms:
406 UserGroupRepoToPerm.create(perm.users_group, new_repo,
406 UserGroupRepoToPerm.create(perm.users_group, new_repo,
407 perm.permission)
407 perm.permission)
408 else:
408 else:
409 perm_obj = self._create_default_perms(new_repo, private)
409 perm_obj = self._create_default_perms(new_repo, private)
410 self.sa.add(perm_obj)
410 self.sa.add(perm_obj)
411 else:
411 else:
412 perm_obj = self._create_default_perms(new_repo, private)
412 perm_obj = self._create_default_perms(new_repo, private)
413 self.sa.add(perm_obj)
413 self.sa.add(perm_obj)
414
414
415 if not just_db:
415 if not just_db:
416 self.__create_repo(repo_name, repo_type,
416 self.__create_repo(repo_name, repo_type,
417 repos_group,
417 repos_group,
418 clone_uri)
418 clone_uri)
419 log_create_repository(new_repo.get_dict(),
419 log_create_repository(new_repo.get_dict(),
420 created_by=owner.username)
420 created_by=owner.username)
421
421
422 # now automatically start following this repository as owner
422 # now automatically start following this repository as owner
423 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
423 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
424 owner.user_id)
424 owner.user_id)
425 return new_repo
425 return new_repo
426 except Exception:
426 except Exception:
427 log.error(traceback.format_exc())
427 log.error(traceback.format_exc())
428 raise
428 raise
429
429
430 def create(self, form_data, cur_user, just_db=False, fork=None):
430 def create(self, form_data, cur_user, just_db=False, fork=None):
431 """
431 """
432 Backward compatibility function, just a wrapper on top of create_repo
432 Backward compatibility function, just a wrapper on top of create_repo
433
433
434 :param form_data:
434 :param form_data:
435 :param cur_user:
435 :param cur_user:
436 :param just_db:
436 :param just_db:
437 :param fork:
437 :param fork:
438 """
438 """
439 owner = cur_user
439 owner = cur_user
440 repo_name = form_data['repo_name_full']
440 repo_name = form_data['repo_name_full']
441 repo_type = form_data['repo_type']
441 repo_type = form_data['repo_type']
442 description = form_data['repo_description']
442 description = form_data['repo_description']
443 private = form_data['repo_private']
443 private = form_data['repo_private']
444 clone_uri = form_data.get('clone_uri')
444 clone_uri = form_data.get('clone_uri')
445 repos_group = form_data['repo_group']
445 repos_group = form_data['repo_group']
446 landing_rev = form_data['repo_landing_rev']
446 landing_rev = form_data['repo_landing_rev']
447 copy_fork_permissions = form_data.get('copy_permissions')
447 copy_fork_permissions = form_data.get('copy_permissions')
448 fork_of = form_data.get('fork_parent_id')
448 fork_of = form_data.get('fork_parent_id')
449
449
450 ## repo creation defaults, private and repo_type are filled in form
450 ## repo creation defaults, private and repo_type are filled in form
451 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
451 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
452 enable_statistics = defs.get('repo_enable_statistics')
452 enable_statistics = defs.get('repo_enable_statistics')
453 enable_locking = defs.get('repo_enable_locking')
453 enable_locking = defs.get('repo_enable_locking')
454 enable_downloads = defs.get('repo_enable_downloads')
454 enable_downloads = defs.get('repo_enable_downloads')
455
455
456 return self.create_repo(
456 return self.create_repo(
457 repo_name, repo_type, description, owner, private, clone_uri,
457 repo_name, repo_type, description, owner, private, clone_uri,
458 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
458 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
459 enable_statistics, enable_locking, enable_downloads
459 enable_statistics, enable_locking, enable_downloads
460 )
460 )
461
461
462 def _update_permissions(self, repo, perms_new=None, perms_updates=None,
462 def _update_permissions(self, repo, perms_new=None, perms_updates=None,
463 check_perms=True):
463 check_perms=True):
464 if not perms_new:
464 if not perms_new:
465 perms_new = []
465 perms_new = []
466 if not perms_updates:
466 if not perms_updates:
467 perms_updates = []
467 perms_updates = []
468
468
469 # update permissions
469 # update permissions
470 for member, perm, member_type in perms_updates:
470 for member, perm, member_type in perms_updates:
471 if member_type == 'user':
471 if member_type == 'user':
472 # this updates existing one
472 # this updates existing one
473 self.grant_user_permission(
473 self.grant_user_permission(
474 repo=repo, user=member, perm=perm
474 repo=repo, user=member, perm=perm
475 )
475 )
476 else:
476 else:
477 #check if we have permissions to alter this usergroup
477 #check if we have permissions to alter this usergroup
478 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
478 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
479 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member):
479 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member):
480 self.grant_users_group_permission(
480 self.grant_users_group_permission(
481 repo=repo, group_name=member, perm=perm
481 repo=repo, group_name=member, perm=perm
482 )
482 )
483 # set new permissions
483 # set new permissions
484 for member, perm, member_type in perms_new:
484 for member, perm, member_type in perms_new:
485 if member_type == 'user':
485 if member_type == 'user':
486 self.grant_user_permission(
486 self.grant_user_permission(
487 repo=repo, user=member, perm=perm
487 repo=repo, user=member, perm=perm
488 )
488 )
489 else:
489 else:
490 #check if we have permissions to alter this usergroup
490 #check if we have permissions to alter this usergroup
491 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
491 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
492 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member):
492 if not check_perms or HasUserGroupPermissionAny(*req_perms)(member):
493 self.grant_users_group_permission(
493 self.grant_users_group_permission(
494 repo=repo, group_name=member, perm=perm
494 repo=repo, group_name=member, perm=perm
495 )
495 )
496
496
497 def create_fork(self, form_data, cur_user):
497 def create_fork(self, form_data, cur_user):
498 """
498 """
499 Simple wrapper into executing celery task for fork creation
499 Simple wrapper into executing celery task for fork creation
500
500
501 :param form_data:
501 :param form_data:
502 :param cur_user:
502 :param cur_user:
503 """
503 """
504 from rhodecode.lib.celerylib import tasks, run_task
504 from rhodecode.lib.celerylib import tasks, run_task
505 run_task(tasks.create_repo_fork, form_data, cur_user)
505 run_task(tasks.create_repo_fork, form_data, cur_user)
506
506
507 def delete(self, repo, forks=None, fs_remove=True, cur_user=None):
507 def delete(self, repo, forks=None, fs_remove=True, cur_user=None):
508 """
508 """
509 Delete given repository, forks parameter defines what do do with
509 Delete given repository, forks parameter defines what do do with
510 attached forks. Throws AttachedForksError if deleted repo has attached
510 attached forks. Throws AttachedForksError if deleted repo has attached
511 forks
511 forks
512
512
513 :param repo:
513 :param repo:
514 :param forks: str 'delete' or 'detach'
514 :param forks: str 'delete' or 'detach'
515 :param fs_remove: remove(archive) repo from filesystem
515 :param fs_remove: remove(archive) repo from filesystem
516 """
516 """
517 if not cur_user:
517 if not cur_user:
518 cur_user = getattr(get_current_rhodecode_user(), 'username', '?')
518 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
519 repo = self._get_repo(repo)
519 repo = self._get_repo(repo)
520 if repo:
520 if repo:
521 if forks == 'detach':
521 if forks == 'detach':
522 for r in repo.forks:
522 for r in repo.forks:
523 r.fork = None
523 r.fork = None
524 self.sa.add(r)
524 self.sa.add(r)
525 elif forks == 'delete':
525 elif forks == 'delete':
526 for r in repo.forks:
526 for r in repo.forks:
527 self.delete(r, forks='delete')
527 self.delete(r, forks='delete')
528 elif [f for f in repo.forks]:
528 elif [f for f in repo.forks]:
529 raise AttachedForksError()
529 raise AttachedForksError()
530
530
531 old_repo_dict = repo.get_dict()
531 old_repo_dict = repo.get_dict()
532 owner = repo.user
532 owner = repo.user
533 try:
533 try:
534 self.sa.delete(repo)
534 self.sa.delete(repo)
535 if fs_remove:
535 if fs_remove:
536 self.__delete_repo(repo)
536 self.__delete_repo(repo)
537 else:
537 else:
538 log.debug('skipping removal from filesystem')
538 log.debug('skipping removal from filesystem')
539 log_delete_repository(old_repo_dict,
539 log_delete_repository(old_repo_dict,
540 deleted_by=cur_user)
540 deleted_by=cur_user)
541 except Exception:
541 except Exception:
542 log.error(traceback.format_exc())
542 log.error(traceback.format_exc())
543 raise
543 raise
544
544
545 def grant_user_permission(self, repo, user, perm):
545 def grant_user_permission(self, repo, user, perm):
546 """
546 """
547 Grant permission for user on given repository, or update existing one
547 Grant permission for user on given repository, or update existing one
548 if found
548 if found
549
549
550 :param repo: Instance of Repository, repository_id, or repository name
550 :param repo: Instance of Repository, repository_id, or repository name
551 :param user: Instance of User, user_id or username
551 :param user: Instance of User, user_id or username
552 :param perm: Instance of Permission, or permission_name
552 :param perm: Instance of Permission, or permission_name
553 """
553 """
554 user = self._get_user(user)
554 user = self._get_user(user)
555 repo = self._get_repo(repo)
555 repo = self._get_repo(repo)
556 permission = self._get_perm(perm)
556 permission = self._get_perm(perm)
557
557
558 # check if we have that permission already
558 # check if we have that permission already
559 obj = self.sa.query(UserRepoToPerm)\
559 obj = self.sa.query(UserRepoToPerm)\
560 .filter(UserRepoToPerm.user == user)\
560 .filter(UserRepoToPerm.user == user)\
561 .filter(UserRepoToPerm.repository == repo)\
561 .filter(UserRepoToPerm.repository == repo)\
562 .scalar()
562 .scalar()
563 if obj is None:
563 if obj is None:
564 # create new !
564 # create new !
565 obj = UserRepoToPerm()
565 obj = UserRepoToPerm()
566 obj.repository = repo
566 obj.repository = repo
567 obj.user = user
567 obj.user = user
568 obj.permission = permission
568 obj.permission = permission
569 self.sa.add(obj)
569 self.sa.add(obj)
570 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
570 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
571
571
572 def revoke_user_permission(self, repo, user):
572 def revoke_user_permission(self, repo, user):
573 """
573 """
574 Revoke permission for user on given repository
574 Revoke permission for user on given repository
575
575
576 :param repo: Instance of Repository, repository_id, or repository name
576 :param repo: Instance of Repository, repository_id, or repository name
577 :param user: Instance of User, user_id or username
577 :param user: Instance of User, user_id or username
578 """
578 """
579
579
580 user = self._get_user(user)
580 user = self._get_user(user)
581 repo = self._get_repo(repo)
581 repo = self._get_repo(repo)
582
582
583 obj = self.sa.query(UserRepoToPerm)\
583 obj = self.sa.query(UserRepoToPerm)\
584 .filter(UserRepoToPerm.repository == repo)\
584 .filter(UserRepoToPerm.repository == repo)\
585 .filter(UserRepoToPerm.user == user)\
585 .filter(UserRepoToPerm.user == user)\
586 .scalar()
586 .scalar()
587 if obj:
587 if obj:
588 self.sa.delete(obj)
588 self.sa.delete(obj)
589 log.debug('Revoked perm on %s on %s' % (repo, user))
589 log.debug('Revoked perm on %s on %s' % (repo, user))
590
590
591 def grant_users_group_permission(self, repo, group_name, perm):
591 def grant_users_group_permission(self, repo, group_name, perm):
592 """
592 """
593 Grant permission for user group on given repository, or update
593 Grant permission for user group on given repository, or update
594 existing one if found
594 existing one if found
595
595
596 :param repo: Instance of Repository, repository_id, or repository name
596 :param repo: Instance of Repository, repository_id, or repository name
597 :param group_name: Instance of UserGroup, users_group_id,
597 :param group_name: Instance of UserGroup, users_group_id,
598 or user group name
598 or user group name
599 :param perm: Instance of Permission, or permission_name
599 :param perm: Instance of Permission, or permission_name
600 """
600 """
601 repo = self._get_repo(repo)
601 repo = self._get_repo(repo)
602 group_name = self._get_user_group(group_name)
602 group_name = self._get_user_group(group_name)
603 permission = self._get_perm(perm)
603 permission = self._get_perm(perm)
604
604
605 # check if we have that permission already
605 # check if we have that permission already
606 obj = self.sa.query(UserGroupRepoToPerm)\
606 obj = self.sa.query(UserGroupRepoToPerm)\
607 .filter(UserGroupRepoToPerm.users_group == group_name)\
607 .filter(UserGroupRepoToPerm.users_group == group_name)\
608 .filter(UserGroupRepoToPerm.repository == repo)\
608 .filter(UserGroupRepoToPerm.repository == repo)\
609 .scalar()
609 .scalar()
610
610
611 if obj is None:
611 if obj is None:
612 # create new
612 # create new
613 obj = UserGroupRepoToPerm()
613 obj = UserGroupRepoToPerm()
614
614
615 obj.repository = repo
615 obj.repository = repo
616 obj.users_group = group_name
616 obj.users_group = group_name
617 obj.permission = permission
617 obj.permission = permission
618 self.sa.add(obj)
618 self.sa.add(obj)
619 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
619 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
620
620
621 def revoke_users_group_permission(self, repo, group_name):
621 def revoke_users_group_permission(self, repo, group_name):
622 """
622 """
623 Revoke permission for user group on given repository
623 Revoke permission for user group on given repository
624
624
625 :param repo: Instance of Repository, repository_id, or repository name
625 :param repo: Instance of Repository, repository_id, or repository name
626 :param group_name: Instance of UserGroup, users_group_id,
626 :param group_name: Instance of UserGroup, users_group_id,
627 or user group name
627 or user group name
628 """
628 """
629 repo = self._get_repo(repo)
629 repo = self._get_repo(repo)
630 group_name = self._get_user_group(group_name)
630 group_name = self._get_user_group(group_name)
631
631
632 obj = self.sa.query(UserGroupRepoToPerm)\
632 obj = self.sa.query(UserGroupRepoToPerm)\
633 .filter(UserGroupRepoToPerm.repository == repo)\
633 .filter(UserGroupRepoToPerm.repository == repo)\
634 .filter(UserGroupRepoToPerm.users_group == group_name)\
634 .filter(UserGroupRepoToPerm.users_group == group_name)\
635 .scalar()
635 .scalar()
636 if obj:
636 if obj:
637 self.sa.delete(obj)
637 self.sa.delete(obj)
638 log.debug('Revoked perm to %s on %s' % (repo, group_name))
638 log.debug('Revoked perm to %s on %s' % (repo, group_name))
639
639
640 def delete_stats(self, repo_name):
640 def delete_stats(self, repo_name):
641 """
641 """
642 removes stats for given repo
642 removes stats for given repo
643
643
644 :param repo_name:
644 :param repo_name:
645 """
645 """
646 repo = self._get_repo(repo_name)
646 repo = self._get_repo(repo_name)
647 try:
647 try:
648 obj = self.sa.query(Statistics)\
648 obj = self.sa.query(Statistics)\
649 .filter(Statistics.repository == repo).scalar()
649 .filter(Statistics.repository == repo).scalar()
650 if obj:
650 if obj:
651 self.sa.delete(obj)
651 self.sa.delete(obj)
652 except Exception:
652 except Exception:
653 log.error(traceback.format_exc())
653 log.error(traceback.format_exc())
654 raise
654 raise
655
655
656 def _create_repo(self, repo_name, alias, parent, clone_uri=False,
656 def _create_repo(self, repo_name, alias, parent, clone_uri=False,
657 repo_store_location=None):
657 repo_store_location=None):
658 return self.__create_repo(repo_name, alias, parent, clone_uri,
658 return self.__create_repo(repo_name, alias, parent, clone_uri,
659 repo_store_location)
659 repo_store_location)
660
660
661 def __create_repo(self, repo_name, alias, parent, clone_uri=False,
661 def __create_repo(self, repo_name, alias, parent, clone_uri=False,
662 repo_store_location=None):
662 repo_store_location=None):
663 """
663 """
664 makes repository on filesystem. It's group aware means it'll create
664 makes repository on filesystem. It's group aware means it'll create
665 a repository within a group, and alter the paths accordingly of
665 a repository within a group, and alter the paths accordingly of
666 group location
666 group location
667
667
668 :param repo_name:
668 :param repo_name:
669 :param alias:
669 :param alias:
670 :param parent_id:
670 :param parent_id:
671 :param clone_uri:
671 :param clone_uri:
672 :param repo_path:
672 :param repo_path:
673 """
673 """
674 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
674 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
675 from rhodecode.model.scm import ScmModel
675 from rhodecode.model.scm import ScmModel
676
676
677 if parent:
677 if parent:
678 new_parent_path = os.sep.join(parent.full_path_splitted)
678 new_parent_path = os.sep.join(parent.full_path_splitted)
679 else:
679 else:
680 new_parent_path = ''
680 new_parent_path = ''
681 if repo_store_location:
681 if repo_store_location:
682 _paths = [repo_store_location]
682 _paths = [repo_store_location]
683 else:
683 else:
684 _paths = [self.repos_path, new_parent_path, repo_name]
684 _paths = [self.repos_path, new_parent_path, repo_name]
685 # we need to make it str for mercurial
685 # we need to make it str for mercurial
686 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
686 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
687
687
688 # check if this path is not a repository
688 # check if this path is not a repository
689 if is_valid_repo(repo_path, self.repos_path):
689 if is_valid_repo(repo_path, self.repos_path):
690 raise Exception('This path %s is a valid repository' % repo_path)
690 raise Exception('This path %s is a valid repository' % repo_path)
691
691
692 # check if this path is a group
692 # check if this path is a group
693 if is_valid_repos_group(repo_path, self.repos_path):
693 if is_valid_repos_group(repo_path, self.repos_path):
694 raise Exception('This path %s is a valid group' % repo_path)
694 raise Exception('This path %s is a valid group' % repo_path)
695
695
696 log.info('creating repo %s in %s @ %s' % (
696 log.info('creating repo %s in %s @ %s' % (
697 repo_name, safe_unicode(repo_path),
697 repo_name, safe_unicode(repo_path),
698 obfuscate_url_pw(clone_uri)
698 obfuscate_url_pw(clone_uri)
699 )
699 )
700 )
700 )
701 backend = get_backend(alias)
701 backend = get_backend(alias)
702 if alias == 'hg':
702 if alias == 'hg':
703 repo = backend(repo_path, create=True, src_url=clone_uri)
703 repo = backend(repo_path, create=True, src_url=clone_uri)
704 elif alias == 'git':
704 elif alias == 'git':
705 repo = backend(repo_path, create=True, src_url=clone_uri, bare=True)
705 repo = backend(repo_path, create=True, src_url=clone_uri, bare=True)
706 # add rhodecode hook into this repo
706 # add rhodecode hook into this repo
707 ScmModel().install_git_hook(repo=repo)
707 ScmModel().install_git_hook(repo=repo)
708 else:
708 else:
709 raise Exception('Undefined alias %s' % alias)
709 raise Exception('Undefined alias %s' % alias)
710 return repo
710 return repo
711
711
712 def __rename_repo(self, old, new):
712 def __rename_repo(self, old, new):
713 """
713 """
714 renames repository on filesystem
714 renames repository on filesystem
715
715
716 :param old: old name
716 :param old: old name
717 :param new: new name
717 :param new: new name
718 """
718 """
719 log.info('renaming repo from %s to %s' % (old, new))
719 log.info('renaming repo from %s to %s' % (old, new))
720
720
721 old_path = os.path.join(self.repos_path, old)
721 old_path = os.path.join(self.repos_path, old)
722 new_path = os.path.join(self.repos_path, new)
722 new_path = os.path.join(self.repos_path, new)
723 if os.path.isdir(new_path):
723 if os.path.isdir(new_path):
724 raise Exception(
724 raise Exception(
725 'Was trying to rename to already existing dir %s' % new_path
725 'Was trying to rename to already existing dir %s' % new_path
726 )
726 )
727 shutil.move(old_path, new_path)
727 shutil.move(old_path, new_path)
728
728
729 def __delete_repo(self, repo):
729 def __delete_repo(self, repo):
730 """
730 """
731 removes repo from filesystem, the removal is acctually made by
731 removes repo from filesystem, the removal is acctually made by
732 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
732 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
733 repository is no longer valid for rhodecode, can be undeleted later on
733 repository is no longer valid for rhodecode, can be undeleted later on
734 by reverting the renames on this repository
734 by reverting the renames on this repository
735
735
736 :param repo: repo object
736 :param repo: repo object
737 """
737 """
738 rm_path = os.path.join(self.repos_path, repo.repo_name)
738 rm_path = os.path.join(self.repos_path, repo.repo_name)
739 log.info("Removing %s" % (rm_path))
739 log.info("Removing %s" % (rm_path))
740 # disable hg/git internal that it doesn't get detected as repo
740 # disable hg/git internal that it doesn't get detected as repo
741 alias = repo.repo_type
741 alias = repo.repo_type
742
742
743 bare = getattr(repo.scm_instance, 'bare', False)
743 bare = getattr(repo.scm_instance, 'bare', False)
744
744
745 if not bare:
745 if not bare:
746 # skip this for bare git repos
746 # skip this for bare git repos
747 shutil.move(os.path.join(rm_path, '.%s' % alias),
747 shutil.move(os.path.join(rm_path, '.%s' % alias),
748 os.path.join(rm_path, 'rm__.%s' % alias))
748 os.path.join(rm_path, 'rm__.%s' % alias))
749 # disable repo
749 # disable repo
750 _now = datetime.now()
750 _now = datetime.now()
751 _ms = str(_now.microsecond).rjust(6, '0')
751 _ms = str(_now.microsecond).rjust(6, '0')
752 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
752 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
753 repo.just_name)
753 repo.just_name)
754 if repo.group:
754 if repo.group:
755 args = repo.group.full_path_splitted + [_d]
755 args = repo.group.full_path_splitted + [_d]
756 _d = os.path.join(*args)
756 _d = os.path.join(*args)
757 shutil.move(rm_path, os.path.join(self.repos_path, _d))
757 shutil.move(rm_path, os.path.join(self.repos_path, _d))
@@ -1,829 +1,829 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user
3 rhodecode.model.user
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 users model for RhodeCode
6 users model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 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
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import itertools
28 import itertools
29 import collections
29 import collections
30 from pylons import url
30 from pylons import url
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from sqlalchemy.orm import joinedload
34 from sqlalchemy.orm import joinedload
35
35
36 from rhodecode.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user
36 from rhodecode.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user
37 from rhodecode.lib.caching_query import FromCache
37 from rhodecode.lib.caching_query import FromCache
38 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
39 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
39 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
40 UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
40 UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
41 Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
41 Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
42 UserEmailMap, UserIpMap, UserGroupUserGroupToPerm, UserGroup
42 UserEmailMap, UserIpMap, UserGroupUserGroupToPerm, UserGroup
43 from rhodecode.lib.exceptions import DefaultUserException, \
43 from rhodecode.lib.exceptions import DefaultUserException, \
44 UserOwnsReposException
44 UserOwnsReposException
45 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
46
46
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50 PERM_WEIGHTS = Permission.PERM_WEIGHTS
50 PERM_WEIGHTS = Permission.PERM_WEIGHTS
51
51
52
52
53 class UserModel(BaseModel):
53 class UserModel(BaseModel):
54 cls = User
54 cls = User
55
55
56 def get(self, user_id, cache=False):
56 def get(self, user_id, cache=False):
57 user = self.sa.query(User)
57 user = self.sa.query(User)
58 if cache:
58 if cache:
59 user = user.options(FromCache("sql_cache_short",
59 user = user.options(FromCache("sql_cache_short",
60 "get_user_%s" % user_id))
60 "get_user_%s" % user_id))
61 return user.get(user_id)
61 return user.get(user_id)
62
62
63 def get_user(self, user):
63 def get_user(self, user):
64 return self._get_user(user)
64 return self._get_user(user)
65
65
66 def get_by_username(self, username, cache=False, case_insensitive=False):
66 def get_by_username(self, username, cache=False, case_insensitive=False):
67
67
68 if case_insensitive:
68 if case_insensitive:
69 user = self.sa.query(User).filter(User.username.ilike(username))
69 user = self.sa.query(User).filter(User.username.ilike(username))
70 else:
70 else:
71 user = self.sa.query(User)\
71 user = self.sa.query(User)\
72 .filter(User.username == username)
72 .filter(User.username == username)
73 if cache:
73 if cache:
74 user = user.options(FromCache("sql_cache_short",
74 user = user.options(FromCache("sql_cache_short",
75 "get_user_%s" % username))
75 "get_user_%s" % username))
76 return user.scalar()
76 return user.scalar()
77
77
78 def get_by_email(self, email, cache=False, case_insensitive=False):
78 def get_by_email(self, email, cache=False, case_insensitive=False):
79 return User.get_by_email(email, case_insensitive, cache)
79 return User.get_by_email(email, case_insensitive, cache)
80
80
81 def get_by_api_key(self, api_key, cache=False):
81 def get_by_api_key(self, api_key, cache=False):
82 return User.get_by_api_key(api_key, cache)
82 return User.get_by_api_key(api_key, cache)
83
83
84 def create(self, form_data, cur_user=None):
84 def create(self, form_data, cur_user=None):
85 if not cur_user:
85 if not cur_user:
86 cur_user = getattr(get_current_rhodecode_user(), 'username', '?')
86 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
87 from rhodecode.lib.auth import get_crypt_password
87 from rhodecode.lib.auth import get_crypt_password
88 try:
88 try:
89 new_user = User()
89 new_user = User()
90 for k, v in form_data.items():
90 for k, v in form_data.items():
91 if k == 'password':
91 if k == 'password':
92 v = get_crypt_password(v)
92 v = get_crypt_password(v)
93 if k == 'firstname':
93 if k == 'firstname':
94 k = 'name'
94 k = 'name'
95 setattr(new_user, k, v)
95 setattr(new_user, k, v)
96
96
97 new_user.api_key = generate_api_key(form_data['username'])
97 new_user.api_key = generate_api_key(form_data['username'])
98 self.sa.add(new_user)
98 self.sa.add(new_user)
99
99
100 from rhodecode.lib.hooks import log_create_user
100 from rhodecode.lib.hooks import log_create_user
101 log_create_user(new_user.get_dict(), cur_user)
101 log_create_user(new_user.get_dict(), cur_user)
102 return new_user
102 return new_user
103 except Exception:
103 except Exception:
104 log.error(traceback.format_exc())
104 log.error(traceback.format_exc())
105 raise
105 raise
106
106
107 def create_or_update(self, username, password, email, firstname='',
107 def create_or_update(self, username, password, email, firstname='',
108 lastname='', active=True, admin=False, ldap_dn=None, cur_user=None):
108 lastname='', active=True, admin=False, ldap_dn=None, cur_user=None):
109 """
109 """
110 Creates a new instance if not found, or updates current one
110 Creates a new instance if not found, or updates current one
111
111
112 :param username:
112 :param username:
113 :param password:
113 :param password:
114 :param email:
114 :param email:
115 :param active:
115 :param active:
116 :param firstname:
116 :param firstname:
117 :param lastname:
117 :param lastname:
118 :param active:
118 :param active:
119 :param admin:
119 :param admin:
120 :param ldap_dn:
120 :param ldap_dn:
121 """
121 """
122 if not cur_user:
122 if not cur_user:
123 cur_user = getattr(get_current_rhodecode_user(), 'username', '?')
123 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
124
124
125 from rhodecode.lib.auth import get_crypt_password
125 from rhodecode.lib.auth import get_crypt_password
126
126
127 log.debug('Checking for %s account in RhodeCode database' % username)
127 log.debug('Checking for %s account in RhodeCode database' % username)
128 user = User.get_by_username(username, case_insensitive=True)
128 user = User.get_by_username(username, case_insensitive=True)
129 if user is None:
129 if user is None:
130 log.debug('creating new user %s' % username)
130 log.debug('creating new user %s' % username)
131 new_user = User()
131 new_user = User()
132 edit = False
132 edit = False
133 else:
133 else:
134 log.debug('updating user %s' % username)
134 log.debug('updating user %s' % username)
135 new_user = user
135 new_user = user
136 edit = True
136 edit = True
137
137
138 try:
138 try:
139 new_user.username = username
139 new_user.username = username
140 new_user.admin = admin
140 new_user.admin = admin
141 # set password only if creating an user or password is changed
141 # set password only if creating an user or password is changed
142 if not edit or user.password != password:
142 if not edit or user.password != password:
143 new_user.password = get_crypt_password(password) if password else None
143 new_user.password = get_crypt_password(password) if password else None
144 new_user.api_key = generate_api_key(username)
144 new_user.api_key = generate_api_key(username)
145 new_user.email = email
145 new_user.email = email
146 new_user.active = active
146 new_user.active = active
147 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
147 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
148 new_user.name = firstname
148 new_user.name = firstname
149 new_user.lastname = lastname
149 new_user.lastname = lastname
150 self.sa.add(new_user)
150 self.sa.add(new_user)
151
151
152 if not edit:
152 if not edit:
153 from rhodecode.lib.hooks import log_create_user
153 from rhodecode.lib.hooks import log_create_user
154 log_create_user(new_user.get_dict(), cur_user)
154 log_create_user(new_user.get_dict(), cur_user)
155 return new_user
155 return new_user
156 except (DatabaseError,):
156 except (DatabaseError,):
157 log.error(traceback.format_exc())
157 log.error(traceback.format_exc())
158 raise
158 raise
159
159
160 def create_for_container_auth(self, username, attrs, cur_user=None):
160 def create_for_container_auth(self, username, attrs, cur_user=None):
161 """
161 """
162 Creates the given user if it's not already in the database
162 Creates the given user if it's not already in the database
163
163
164 :param username:
164 :param username:
165 :param attrs:
165 :param attrs:
166 """
166 """
167 if not cur_user:
167 if not cur_user:
168 cur_user = getattr(get_current_rhodecode_user(), 'username', '?')
168 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
169 if self.get_by_username(username, case_insensitive=True) is None:
169 if self.get_by_username(username, case_insensitive=True) is None:
170
170
171 # autogenerate email for container account without one
171 # autogenerate email for container account without one
172 generate_email = lambda usr: '%s@container_auth.account' % usr
172 generate_email = lambda usr: '%s@container_auth.account' % usr
173
173
174 try:
174 try:
175 new_user = User()
175 new_user = User()
176 new_user.username = username
176 new_user.username = username
177 new_user.password = None
177 new_user.password = None
178 new_user.api_key = generate_api_key(username)
178 new_user.api_key = generate_api_key(username)
179 new_user.email = attrs['email']
179 new_user.email = attrs['email']
180 new_user.active = attrs.get('active', True)
180 new_user.active = attrs.get('active', True)
181 new_user.name = attrs['name'] or generate_email(username)
181 new_user.name = attrs['name'] or generate_email(username)
182 new_user.lastname = attrs['lastname']
182 new_user.lastname = attrs['lastname']
183
183
184 self.sa.add(new_user)
184 self.sa.add(new_user)
185
185
186 from rhodecode.lib.hooks import log_create_user
186 from rhodecode.lib.hooks import log_create_user
187 log_create_user(new_user.get_dict(), cur_user)
187 log_create_user(new_user.get_dict(), cur_user)
188 return new_user
188 return new_user
189 except (DatabaseError,):
189 except (DatabaseError,):
190 log.error(traceback.format_exc())
190 log.error(traceback.format_exc())
191 self.sa.rollback()
191 self.sa.rollback()
192 raise
192 raise
193 log.debug('User %s already exists. Skipping creation of account'
193 log.debug('User %s already exists. Skipping creation of account'
194 ' for container auth.', username)
194 ' for container auth.', username)
195 return None
195 return None
196
196
197 def create_ldap(self, username, password, user_dn, attrs, cur_user=None):
197 def create_ldap(self, username, password, user_dn, attrs, cur_user=None):
198 """
198 """
199 Checks if user is in database, if not creates this user marked
199 Checks if user is in database, if not creates this user marked
200 as ldap user
200 as ldap user
201
201
202 :param username:
202 :param username:
203 :param password:
203 :param password:
204 :param user_dn:
204 :param user_dn:
205 :param attrs:
205 :param attrs:
206 """
206 """
207 if not cur_user:
207 if not cur_user:
208 cur_user = getattr(get_current_rhodecode_user(), 'username', '?')
208 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
209 from rhodecode.lib.auth import get_crypt_password
209 from rhodecode.lib.auth import get_crypt_password
210 log.debug('Checking for such ldap account in RhodeCode database')
210 log.debug('Checking for such ldap account in RhodeCode database')
211 if self.get_by_username(username, case_insensitive=True) is None:
211 if self.get_by_username(username, case_insensitive=True) is None:
212
212
213 # autogenerate email for ldap account without one
213 # autogenerate email for ldap account without one
214 generate_email = lambda usr: '%s@ldap.account' % usr
214 generate_email = lambda usr: '%s@ldap.account' % usr
215
215
216 try:
216 try:
217 new_user = User()
217 new_user = User()
218 username = username.lower()
218 username = username.lower()
219 # add ldap account always lowercase
219 # add ldap account always lowercase
220 new_user.username = username
220 new_user.username = username
221 new_user.password = get_crypt_password(password)
221 new_user.password = get_crypt_password(password)
222 new_user.api_key = generate_api_key(username)
222 new_user.api_key = generate_api_key(username)
223 new_user.email = attrs['email'] or generate_email(username)
223 new_user.email = attrs['email'] or generate_email(username)
224 new_user.active = attrs.get('active', True)
224 new_user.active = attrs.get('active', True)
225 new_user.ldap_dn = safe_unicode(user_dn)
225 new_user.ldap_dn = safe_unicode(user_dn)
226 new_user.name = attrs['name']
226 new_user.name = attrs['name']
227 new_user.lastname = attrs['lastname']
227 new_user.lastname = attrs['lastname']
228
228
229 self.sa.add(new_user)
229 self.sa.add(new_user)
230
230
231 from rhodecode.lib.hooks import log_create_user
231 from rhodecode.lib.hooks import log_create_user
232 log_create_user(new_user.get_dict(), cur_user)
232 log_create_user(new_user.get_dict(), cur_user)
233 return new_user
233 return new_user
234 except (DatabaseError,):
234 except (DatabaseError,):
235 log.error(traceback.format_exc())
235 log.error(traceback.format_exc())
236 self.sa.rollback()
236 self.sa.rollback()
237 raise
237 raise
238 log.debug('this %s user exists skipping creation of ldap account',
238 log.debug('this %s user exists skipping creation of ldap account',
239 username)
239 username)
240 return None
240 return None
241
241
242 def create_registration(self, form_data):
242 def create_registration(self, form_data):
243 from rhodecode.model.notification import NotificationModel
243 from rhodecode.model.notification import NotificationModel
244
244
245 try:
245 try:
246 form_data['admin'] = False
246 form_data['admin'] = False
247 new_user = self.create(form_data)
247 new_user = self.create(form_data)
248
248
249 self.sa.add(new_user)
249 self.sa.add(new_user)
250 self.sa.flush()
250 self.sa.flush()
251
251
252 # notification to admins
252 # notification to admins
253 subject = _('New user registration')
253 subject = _('New user registration')
254 body = ('New user registration\n'
254 body = ('New user registration\n'
255 '---------------------\n'
255 '---------------------\n'
256 '- Username: %s\n'
256 '- Username: %s\n'
257 '- Full Name: %s\n'
257 '- Full Name: %s\n'
258 '- Email: %s\n')
258 '- Email: %s\n')
259 body = body % (new_user.username, new_user.full_name,
259 body = body % (new_user.username, new_user.full_name,
260 new_user.email)
260 new_user.email)
261 edit_url = url('edit_user', id=new_user.user_id, qualified=True)
261 edit_url = url('edit_user', id=new_user.user_id, qualified=True)
262 kw = {'registered_user_url': edit_url}
262 kw = {'registered_user_url': edit_url}
263 NotificationModel().create(created_by=new_user, subject=subject,
263 NotificationModel().create(created_by=new_user, subject=subject,
264 body=body, recipients=None,
264 body=body, recipients=None,
265 type_=Notification.TYPE_REGISTRATION,
265 type_=Notification.TYPE_REGISTRATION,
266 email_kwargs=kw)
266 email_kwargs=kw)
267
267
268 except Exception:
268 except Exception:
269 log.error(traceback.format_exc())
269 log.error(traceback.format_exc())
270 raise
270 raise
271
271
272 def update(self, user_id, form_data, skip_attrs=[]):
272 def update(self, user_id, form_data, skip_attrs=[]):
273 from rhodecode.lib.auth import get_crypt_password
273 from rhodecode.lib.auth import get_crypt_password
274 try:
274 try:
275 user = self.get(user_id, cache=False)
275 user = self.get(user_id, cache=False)
276 if user.username == 'default':
276 if user.username == 'default':
277 raise DefaultUserException(
277 raise DefaultUserException(
278 _("You can't Edit this user since it's"
278 _("You can't Edit this user since it's"
279 " crucial for entire application"))
279 " crucial for entire application"))
280
280
281 for k, v in form_data.items():
281 for k, v in form_data.items():
282 if k in skip_attrs:
282 if k in skip_attrs:
283 continue
283 continue
284 if k == 'new_password' and v:
284 if k == 'new_password' and v:
285 user.password = get_crypt_password(v)
285 user.password = get_crypt_password(v)
286 user.api_key = generate_api_key(user.username)
286 user.api_key = generate_api_key(user.username)
287 else:
287 else:
288 if k == 'firstname':
288 if k == 'firstname':
289 k = 'name'
289 k = 'name'
290 setattr(user, k, v)
290 setattr(user, k, v)
291 self.sa.add(user)
291 self.sa.add(user)
292 except Exception:
292 except Exception:
293 log.error(traceback.format_exc())
293 log.error(traceback.format_exc())
294 raise
294 raise
295
295
296 def update_user(self, user, **kwargs):
296 def update_user(self, user, **kwargs):
297 from rhodecode.lib.auth import get_crypt_password
297 from rhodecode.lib.auth import get_crypt_password
298 try:
298 try:
299 user = self._get_user(user)
299 user = self._get_user(user)
300 if user.username == 'default':
300 if user.username == 'default':
301 raise DefaultUserException(
301 raise DefaultUserException(
302 _("You can't Edit this user since it's"
302 _("You can't Edit this user since it's"
303 " crucial for entire application")
303 " crucial for entire application")
304 )
304 )
305
305
306 for k, v in kwargs.items():
306 for k, v in kwargs.items():
307 if k == 'password' and v:
307 if k == 'password' and v:
308 v = get_crypt_password(v)
308 v = get_crypt_password(v)
309 user.api_key = generate_api_key(user.username)
309 user.api_key = generate_api_key(user.username)
310
310
311 setattr(user, k, v)
311 setattr(user, k, v)
312 self.sa.add(user)
312 self.sa.add(user)
313 return user
313 return user
314 except Exception:
314 except Exception:
315 log.error(traceback.format_exc())
315 log.error(traceback.format_exc())
316 raise
316 raise
317
317
318 def delete(self, user, cur_user=None):
318 def delete(self, user, cur_user=None):
319 if not cur_user:
319 if not cur_user:
320 cur_user = getattr(get_current_rhodecode_user(), 'username', '?')
320 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
321 user = self._get_user(user)
321 user = self._get_user(user)
322
322
323 try:
323 try:
324 if user.username == 'default':
324 if user.username == 'default':
325 raise DefaultUserException(
325 raise DefaultUserException(
326 _(u"You can't remove this user since it's"
326 _(u"You can't remove this user since it's"
327 " crucial for entire application")
327 " crucial for entire application")
328 )
328 )
329 if user.repositories:
329 if user.repositories:
330 repos = [x.repo_name for x in user.repositories]
330 repos = [x.repo_name for x in user.repositories]
331 raise UserOwnsReposException(
331 raise UserOwnsReposException(
332 _(u'user "%s" still owns %s repositories and cannot be '
332 _(u'user "%s" still owns %s repositories and cannot be '
333 'removed. Switch owners or remove those repositories. %s')
333 'removed. Switch owners or remove those repositories. %s')
334 % (user.username, len(repos), ', '.join(repos))
334 % (user.username, len(repos), ', '.join(repos))
335 )
335 )
336 self.sa.delete(user)
336 self.sa.delete(user)
337
337
338 from rhodecode.lib.hooks import log_delete_user
338 from rhodecode.lib.hooks import log_delete_user
339 log_delete_user(user.get_dict(), cur_user)
339 log_delete_user(user.get_dict(), cur_user)
340 except Exception:
340 except Exception:
341 log.error(traceback.format_exc())
341 log.error(traceback.format_exc())
342 raise
342 raise
343
343
344 def reset_password_link(self, data):
344 def reset_password_link(self, data):
345 from rhodecode.lib.celerylib import tasks, run_task
345 from rhodecode.lib.celerylib import tasks, run_task
346 from rhodecode.model.notification import EmailNotificationModel
346 from rhodecode.model.notification import EmailNotificationModel
347 user_email = data['email']
347 user_email = data['email']
348 try:
348 try:
349 user = User.get_by_email(user_email)
349 user = User.get_by_email(user_email)
350 if user:
350 if user:
351 log.debug('password reset user found %s' % user)
351 log.debug('password reset user found %s' % user)
352 link = url('reset_password_confirmation', key=user.api_key,
352 link = url('reset_password_confirmation', key=user.api_key,
353 qualified=True)
353 qualified=True)
354 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
354 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
355 body = EmailNotificationModel().get_email_tmpl(reg_type,
355 body = EmailNotificationModel().get_email_tmpl(reg_type,
356 **{'user': user.short_contact,
356 **{'user': user.short_contact,
357 'reset_url': link})
357 'reset_url': link})
358 log.debug('sending email')
358 log.debug('sending email')
359 run_task(tasks.send_email, user_email,
359 run_task(tasks.send_email, user_email,
360 _("Password reset link"), body, body)
360 _("Password reset link"), body, body)
361 log.info('send new password mail to %s' % user_email)
361 log.info('send new password mail to %s' % user_email)
362 else:
362 else:
363 log.debug("password reset email %s not found" % user_email)
363 log.debug("password reset email %s not found" % user_email)
364 except Exception:
364 except Exception:
365 log.error(traceback.format_exc())
365 log.error(traceback.format_exc())
366 return False
366 return False
367
367
368 return True
368 return True
369
369
370 def reset_password(self, data):
370 def reset_password(self, data):
371 from rhodecode.lib.celerylib import tasks, run_task
371 from rhodecode.lib.celerylib import tasks, run_task
372 from rhodecode.lib import auth
372 from rhodecode.lib import auth
373 user_email = data['email']
373 user_email = data['email']
374 try:
374 try:
375 try:
375 try:
376 user = User.get_by_email(user_email)
376 user = User.get_by_email(user_email)
377 new_passwd = auth.PasswordGenerator().gen_password(8,
377 new_passwd = auth.PasswordGenerator().gen_password(8,
378 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
378 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
379 if user:
379 if user:
380 user.password = auth.get_crypt_password(new_passwd)
380 user.password = auth.get_crypt_password(new_passwd)
381 user.api_key = auth.generate_api_key(user.username)
381 user.api_key = auth.generate_api_key(user.username)
382 Session().add(user)
382 Session().add(user)
383 Session().commit()
383 Session().commit()
384 log.info('change password for %s' % user_email)
384 log.info('change password for %s' % user_email)
385 if new_passwd is None:
385 if new_passwd is None:
386 raise Exception('unable to generate new password')
386 raise Exception('unable to generate new password')
387 except Exception:
387 except Exception:
388 log.error(traceback.format_exc())
388 log.error(traceback.format_exc())
389 Session().rollback()
389 Session().rollback()
390
390
391 run_task(tasks.send_email, user_email,
391 run_task(tasks.send_email, user_email,
392 _('Your new password'),
392 _('Your new password'),
393 _('Your new RhodeCode password:%s') % (new_passwd))
393 _('Your new RhodeCode password:%s') % (new_passwd))
394 log.info('send new password mail to %s' % user_email)
394 log.info('send new password mail to %s' % user_email)
395
395
396 except Exception:
396 except Exception:
397 log.error('Failed to update user password')
397 log.error('Failed to update user password')
398 log.error(traceback.format_exc())
398 log.error(traceback.format_exc())
399
399
400 return True
400 return True
401
401
402 def fill_data(self, auth_user, user_id=None, api_key=None):
402 def fill_data(self, auth_user, user_id=None, api_key=None):
403 """
403 """
404 Fetches auth_user by user_id,or api_key if present.
404 Fetches auth_user by user_id,or api_key if present.
405 Fills auth_user attributes with those taken from database.
405 Fills auth_user attributes with those taken from database.
406 Additionally set's is_authenitated if lookup fails
406 Additionally set's is_authenitated if lookup fails
407 present in database
407 present in database
408
408
409 :param auth_user: instance of user to set attributes
409 :param auth_user: instance of user to set attributes
410 :param user_id: user id to fetch by
410 :param user_id: user id to fetch by
411 :param api_key: api key to fetch by
411 :param api_key: api key to fetch by
412 """
412 """
413 if user_id is None and api_key is None:
413 if user_id is None and api_key is None:
414 raise Exception('You need to pass user_id or api_key')
414 raise Exception('You need to pass user_id or api_key')
415
415
416 try:
416 try:
417 if api_key:
417 if api_key:
418 dbuser = self.get_by_api_key(api_key)
418 dbuser = self.get_by_api_key(api_key)
419 else:
419 else:
420 dbuser = self.get(user_id)
420 dbuser = self.get(user_id)
421
421
422 if dbuser is not None and dbuser.active:
422 if dbuser is not None and dbuser.active:
423 log.debug('filling %s data' % dbuser)
423 log.debug('filling %s data' % dbuser)
424 for k, v in dbuser.get_dict().items():
424 for k, v in dbuser.get_dict().items():
425 setattr(auth_user, k, v)
425 setattr(auth_user, k, v)
426 else:
426 else:
427 return False
427 return False
428
428
429 except Exception:
429 except Exception:
430 log.error(traceback.format_exc())
430 log.error(traceback.format_exc())
431 auth_user.is_authenticated = False
431 auth_user.is_authenticated = False
432 return False
432 return False
433
433
434 return True
434 return True
435
435
436 def fill_perms(self, user, explicit=True, algo='higherwin'):
436 def fill_perms(self, user, explicit=True, algo='higherwin'):
437 """
437 """
438 Fills user permission attribute with permissions taken from database
438 Fills user permission attribute with permissions taken from database
439 works for permissions given for repositories, and for permissions that
439 works for permissions given for repositories, and for permissions that
440 are granted to groups
440 are granted to groups
441
441
442 :param user: user instance to fill his perms
442 :param user: user instance to fill his perms
443 :param explicit: In case there are permissions both for user and a group
443 :param explicit: In case there are permissions both for user and a group
444 that user is part of, explicit flag will defiine if user will
444 that user is part of, explicit flag will defiine if user will
445 explicitly override permissions from group, if it's False it will
445 explicitly override permissions from group, if it's False it will
446 make decision based on the algo
446 make decision based on the algo
447 :param algo: algorithm to decide what permission should be choose if
447 :param algo: algorithm to decide what permission should be choose if
448 it's multiple defined, eg user in two different groups. It also
448 it's multiple defined, eg user in two different groups. It also
449 decides if explicit flag is turned off how to specify the permission
449 decides if explicit flag is turned off how to specify the permission
450 for case when user is in a group + have defined separate permission
450 for case when user is in a group + have defined separate permission
451 """
451 """
452 RK = 'repositories'
452 RK = 'repositories'
453 GK = 'repositories_groups'
453 GK = 'repositories_groups'
454 UK = 'user_groups'
454 UK = 'user_groups'
455 GLOBAL = 'global'
455 GLOBAL = 'global'
456 user.permissions[RK] = {}
456 user.permissions[RK] = {}
457 user.permissions[GK] = {}
457 user.permissions[GK] = {}
458 user.permissions[UK] = {}
458 user.permissions[UK] = {}
459 user.permissions[GLOBAL] = set()
459 user.permissions[GLOBAL] = set()
460
460
461 def _choose_perm(new_perm, cur_perm):
461 def _choose_perm(new_perm, cur_perm):
462 new_perm_val = PERM_WEIGHTS[new_perm]
462 new_perm_val = PERM_WEIGHTS[new_perm]
463 cur_perm_val = PERM_WEIGHTS[cur_perm]
463 cur_perm_val = PERM_WEIGHTS[cur_perm]
464 if algo == 'higherwin':
464 if algo == 'higherwin':
465 if new_perm_val > cur_perm_val:
465 if new_perm_val > cur_perm_val:
466 return new_perm
466 return new_perm
467 return cur_perm
467 return cur_perm
468 elif algo == 'lowerwin':
468 elif algo == 'lowerwin':
469 if new_perm_val < cur_perm_val:
469 if new_perm_val < cur_perm_val:
470 return new_perm
470 return new_perm
471 return cur_perm
471 return cur_perm
472
472
473 #======================================================================
473 #======================================================================
474 # fetch default permissions
474 # fetch default permissions
475 #======================================================================
475 #======================================================================
476 default_user = User.get_by_username('default', cache=True)
476 default_user = User.get_by_username('default', cache=True)
477 default_user_id = default_user.user_id
477 default_user_id = default_user.user_id
478
478
479 default_repo_perms = Permission.get_default_perms(default_user_id)
479 default_repo_perms = Permission.get_default_perms(default_user_id)
480 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
480 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
481 default_user_group_perms = Permission.get_default_user_group_perms(default_user_id)
481 default_user_group_perms = Permission.get_default_user_group_perms(default_user_id)
482
482
483 if user.is_admin:
483 if user.is_admin:
484 #==================================================================
484 #==================================================================
485 # admin user have all default rights for repositories
485 # admin user have all default rights for repositories
486 # and groups set to admin
486 # and groups set to admin
487 #==================================================================
487 #==================================================================
488 user.permissions[GLOBAL].add('hg.admin')
488 user.permissions[GLOBAL].add('hg.admin')
489
489
490 # repositories
490 # repositories
491 for perm in default_repo_perms:
491 for perm in default_repo_perms:
492 r_k = perm.UserRepoToPerm.repository.repo_name
492 r_k = perm.UserRepoToPerm.repository.repo_name
493 p = 'repository.admin'
493 p = 'repository.admin'
494 user.permissions[RK][r_k] = p
494 user.permissions[RK][r_k] = p
495
495
496 # repository groups
496 # repository groups
497 for perm in default_repo_groups_perms:
497 for perm in default_repo_groups_perms:
498 rg_k = perm.UserRepoGroupToPerm.group.group_name
498 rg_k = perm.UserRepoGroupToPerm.group.group_name
499 p = 'group.admin'
499 p = 'group.admin'
500 user.permissions[GK][rg_k] = p
500 user.permissions[GK][rg_k] = p
501
501
502 # user groups
502 # user groups
503 for perm in default_user_group_perms:
503 for perm in default_user_group_perms:
504 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
504 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
505 p = 'usergroup.admin'
505 p = 'usergroup.admin'
506 user.permissions[UK][u_k] = p
506 user.permissions[UK][u_k] = p
507 return user
507 return user
508
508
509 #==================================================================
509 #==================================================================
510 # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS
510 # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS
511 #==================================================================
511 #==================================================================
512 uid = user.user_id
512 uid = user.user_id
513
513
514 # default global permissions taken fron the default user
514 # default global permissions taken fron the default user
515 default_global_perms = self.sa.query(UserToPerm)\
515 default_global_perms = self.sa.query(UserToPerm)\
516 .filter(UserToPerm.user_id == default_user_id)
516 .filter(UserToPerm.user_id == default_user_id)
517
517
518 for perm in default_global_perms:
518 for perm in default_global_perms:
519 user.permissions[GLOBAL].add(perm.permission.permission_name)
519 user.permissions[GLOBAL].add(perm.permission.permission_name)
520
520
521 # defaults for repositories, taken from default user
521 # defaults for repositories, taken from default user
522 for perm in default_repo_perms:
522 for perm in default_repo_perms:
523 r_k = perm.UserRepoToPerm.repository.repo_name
523 r_k = perm.UserRepoToPerm.repository.repo_name
524 if perm.Repository.private and not (perm.Repository.user_id == uid):
524 if perm.Repository.private and not (perm.Repository.user_id == uid):
525 # disable defaults for private repos,
525 # disable defaults for private repos,
526 p = 'repository.none'
526 p = 'repository.none'
527 elif perm.Repository.user_id == uid:
527 elif perm.Repository.user_id == uid:
528 # set admin if owner
528 # set admin if owner
529 p = 'repository.admin'
529 p = 'repository.admin'
530 else:
530 else:
531 p = perm.Permission.permission_name
531 p = perm.Permission.permission_name
532
532
533 user.permissions[RK][r_k] = p
533 user.permissions[RK][r_k] = p
534
534
535 # defaults for repository groups taken from default user permission
535 # defaults for repository groups taken from default user permission
536 # on given group
536 # on given group
537 for perm in default_repo_groups_perms:
537 for perm in default_repo_groups_perms:
538 rg_k = perm.UserRepoGroupToPerm.group.group_name
538 rg_k = perm.UserRepoGroupToPerm.group.group_name
539 p = perm.Permission.permission_name
539 p = perm.Permission.permission_name
540 user.permissions[GK][rg_k] = p
540 user.permissions[GK][rg_k] = p
541
541
542 # defaults for user groups taken from default user permission
542 # defaults for user groups taken from default user permission
543 # on given user group
543 # on given user group
544 for perm in default_user_group_perms:
544 for perm in default_user_group_perms:
545 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
545 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
546 p = perm.Permission.permission_name
546 p = perm.Permission.permission_name
547 user.permissions[UK][u_k] = p
547 user.permissions[UK][u_k] = p
548
548
549 #======================================================================
549 #======================================================================
550 # !! OVERRIDE GLOBALS !! with user permissions if any found
550 # !! OVERRIDE GLOBALS !! with user permissions if any found
551 #======================================================================
551 #======================================================================
552 # those can be configured from groups or users explicitly
552 # those can be configured from groups or users explicitly
553 _configurable = set([
553 _configurable = set([
554 'hg.fork.none', 'hg.fork.repository',
554 'hg.fork.none', 'hg.fork.repository',
555 'hg.create.none', 'hg.create.repository',
555 'hg.create.none', 'hg.create.repository',
556 'hg.usergroup.create.false', 'hg.usergroup.create.true'
556 'hg.usergroup.create.false', 'hg.usergroup.create.true'
557 ])
557 ])
558
558
559 # USER GROUPS comes first
559 # USER GROUPS comes first
560 # user group global permissions
560 # user group global permissions
561 user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\
561 user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\
562 .options(joinedload(UserGroupToPerm.permission))\
562 .options(joinedload(UserGroupToPerm.permission))\
563 .join((UserGroupMember, UserGroupToPerm.users_group_id ==
563 .join((UserGroupMember, UserGroupToPerm.users_group_id ==
564 UserGroupMember.users_group_id))\
564 UserGroupMember.users_group_id))\
565 .filter(UserGroupMember.user_id == uid)\
565 .filter(UserGroupMember.user_id == uid)\
566 .order_by(UserGroupToPerm.users_group_id)\
566 .order_by(UserGroupToPerm.users_group_id)\
567 .all()
567 .all()
568 #need to group here by groups since user can be in more than one group
568 #need to group here by groups since user can be in more than one group
569 _grouped = [[x, list(y)] for x, y in
569 _grouped = [[x, list(y)] for x, y in
570 itertools.groupby(user_perms_from_users_groups,
570 itertools.groupby(user_perms_from_users_groups,
571 lambda x:x.users_group)]
571 lambda x:x.users_group)]
572 for gr, perms in _grouped:
572 for gr, perms in _grouped:
573 # since user can be in multiple groups iterate over them and
573 # since user can be in multiple groups iterate over them and
574 # select the lowest permissions first (more explicit)
574 # select the lowest permissions first (more explicit)
575 ##TODO: do this^^
575 ##TODO: do this^^
576 if not gr.inherit_default_permissions:
576 if not gr.inherit_default_permissions:
577 # NEED TO IGNORE all configurable permissions and
577 # NEED TO IGNORE all configurable permissions and
578 # replace them with explicitly set
578 # replace them with explicitly set
579 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
579 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
580 .difference(_configurable)
580 .difference(_configurable)
581 for perm in perms:
581 for perm in perms:
582 user.permissions[GLOBAL].add(perm.permission.permission_name)
582 user.permissions[GLOBAL].add(perm.permission.permission_name)
583
583
584 # user specific global permissions
584 # user specific global permissions
585 user_perms = self.sa.query(UserToPerm)\
585 user_perms = self.sa.query(UserToPerm)\
586 .options(joinedload(UserToPerm.permission))\
586 .options(joinedload(UserToPerm.permission))\
587 .filter(UserToPerm.user_id == uid).all()
587 .filter(UserToPerm.user_id == uid).all()
588
588
589 if not user.inherit_default_permissions:
589 if not user.inherit_default_permissions:
590 # NEED TO IGNORE all configurable permissions and
590 # NEED TO IGNORE all configurable permissions and
591 # replace them with explicitly set
591 # replace them with explicitly set
592 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
592 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
593 .difference(_configurable)
593 .difference(_configurable)
594
594
595 for perm in user_perms:
595 for perm in user_perms:
596 user.permissions[GLOBAL].add(perm.permission.permission_name)
596 user.permissions[GLOBAL].add(perm.permission.permission_name)
597 ## END GLOBAL PERMISSIONS
597 ## END GLOBAL PERMISSIONS
598
598
599 #======================================================================
599 #======================================================================
600 # !! PERMISSIONS FOR REPOSITORIES !!
600 # !! PERMISSIONS FOR REPOSITORIES !!
601 #======================================================================
601 #======================================================================
602 #======================================================================
602 #======================================================================
603 # check if user is part of user groups for this repository and
603 # check if user is part of user groups for this repository and
604 # fill in his permission from it. _choose_perm decides of which
604 # fill in his permission from it. _choose_perm decides of which
605 # permission should be selected based on selected method
605 # permission should be selected based on selected method
606 #======================================================================
606 #======================================================================
607
607
608 # user group for repositories permissions
608 # user group for repositories permissions
609 user_repo_perms_from_users_groups = \
609 user_repo_perms_from_users_groups = \
610 self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\
610 self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\
611 .join((Repository, UserGroupRepoToPerm.repository_id ==
611 .join((Repository, UserGroupRepoToPerm.repository_id ==
612 Repository.repo_id))\
612 Repository.repo_id))\
613 .join((Permission, UserGroupRepoToPerm.permission_id ==
613 .join((Permission, UserGroupRepoToPerm.permission_id ==
614 Permission.permission_id))\
614 Permission.permission_id))\
615 .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
615 .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
616 UserGroupMember.users_group_id))\
616 UserGroupMember.users_group_id))\
617 .filter(UserGroupMember.user_id == uid)\
617 .filter(UserGroupMember.user_id == uid)\
618 .all()
618 .all()
619
619
620 multiple_counter = collections.defaultdict(int)
620 multiple_counter = collections.defaultdict(int)
621 for perm in user_repo_perms_from_users_groups:
621 for perm in user_repo_perms_from_users_groups:
622 r_k = perm.UserGroupRepoToPerm.repository.repo_name
622 r_k = perm.UserGroupRepoToPerm.repository.repo_name
623 multiple_counter[r_k] += 1
623 multiple_counter[r_k] += 1
624 p = perm.Permission.permission_name
624 p = perm.Permission.permission_name
625 cur_perm = user.permissions[RK][r_k]
625 cur_perm = user.permissions[RK][r_k]
626
626
627 if perm.Repository.user_id == uid:
627 if perm.Repository.user_id == uid:
628 # set admin if owner
628 # set admin if owner
629 p = 'repository.admin'
629 p = 'repository.admin'
630 else:
630 else:
631 if multiple_counter[r_k] > 1:
631 if multiple_counter[r_k] > 1:
632 p = _choose_perm(p, cur_perm)
632 p = _choose_perm(p, cur_perm)
633 user.permissions[RK][r_k] = p
633 user.permissions[RK][r_k] = p
634
634
635 # user explicit permissions for repositories, overrides any specified
635 # user explicit permissions for repositories, overrides any specified
636 # by the group permission
636 # by the group permission
637 user_repo_perms = Permission.get_default_perms(uid)
637 user_repo_perms = Permission.get_default_perms(uid)
638 for perm in user_repo_perms:
638 for perm in user_repo_perms:
639 r_k = perm.UserRepoToPerm.repository.repo_name
639 r_k = perm.UserRepoToPerm.repository.repo_name
640 cur_perm = user.permissions[RK][r_k]
640 cur_perm = user.permissions[RK][r_k]
641 # set admin if owner
641 # set admin if owner
642 if perm.Repository.user_id == uid:
642 if perm.Repository.user_id == uid:
643 p = 'repository.admin'
643 p = 'repository.admin'
644 else:
644 else:
645 p = perm.Permission.permission_name
645 p = perm.Permission.permission_name
646 if not explicit:
646 if not explicit:
647 p = _choose_perm(p, cur_perm)
647 p = _choose_perm(p, cur_perm)
648 user.permissions[RK][r_k] = p
648 user.permissions[RK][r_k] = p
649
649
650 #======================================================================
650 #======================================================================
651 # !! PERMISSIONS FOR REPOSITORY GROUPS !!
651 # !! PERMISSIONS FOR REPOSITORY GROUPS !!
652 #======================================================================
652 #======================================================================
653 #======================================================================
653 #======================================================================
654 # check if user is part of user groups for this repository groups and
654 # check if user is part of user groups for this repository groups and
655 # fill in his permission from it. _choose_perm decides of which
655 # fill in his permission from it. _choose_perm decides of which
656 # permission should be selected based on selected method
656 # permission should be selected based on selected method
657 #======================================================================
657 #======================================================================
658 # user group for repo groups permissions
658 # user group for repo groups permissions
659 user_repo_group_perms_from_users_groups = \
659 user_repo_group_perms_from_users_groups = \
660 self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
660 self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
661 .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
661 .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
662 .join((Permission, UserGroupRepoGroupToPerm.permission_id
662 .join((Permission, UserGroupRepoGroupToPerm.permission_id
663 == Permission.permission_id))\
663 == Permission.permission_id))\
664 .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
664 .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
665 == UserGroupMember.users_group_id))\
665 == UserGroupMember.users_group_id))\
666 .filter(UserGroupMember.user_id == uid)\
666 .filter(UserGroupMember.user_id == uid)\
667 .all()
667 .all()
668
668
669 multiple_counter = collections.defaultdict(int)
669 multiple_counter = collections.defaultdict(int)
670 for perm in user_repo_group_perms_from_users_groups:
670 for perm in user_repo_group_perms_from_users_groups:
671 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
671 g_k = perm.UserGroupRepoGroupToPerm.group.group_name
672 multiple_counter[g_k] += 1
672 multiple_counter[g_k] += 1
673 p = perm.Permission.permission_name
673 p = perm.Permission.permission_name
674 cur_perm = user.permissions[GK][g_k]
674 cur_perm = user.permissions[GK][g_k]
675 if multiple_counter[g_k] > 1:
675 if multiple_counter[g_k] > 1:
676 p = _choose_perm(p, cur_perm)
676 p = _choose_perm(p, cur_perm)
677 user.permissions[GK][g_k] = p
677 user.permissions[GK][g_k] = p
678
678
679 # user explicit permissions for repository groups
679 # user explicit permissions for repository groups
680 user_repo_groups_perms = Permission.get_default_group_perms(uid)
680 user_repo_groups_perms = Permission.get_default_group_perms(uid)
681 for perm in user_repo_groups_perms:
681 for perm in user_repo_groups_perms:
682 rg_k = perm.UserRepoGroupToPerm.group.group_name
682 rg_k = perm.UserRepoGroupToPerm.group.group_name
683 p = perm.Permission.permission_name
683 p = perm.Permission.permission_name
684 cur_perm = user.permissions[GK][rg_k]
684 cur_perm = user.permissions[GK][rg_k]
685 if not explicit:
685 if not explicit:
686 p = _choose_perm(p, cur_perm)
686 p = _choose_perm(p, cur_perm)
687 user.permissions[GK][rg_k] = p
687 user.permissions[GK][rg_k] = p
688
688
689 #======================================================================
689 #======================================================================
690 # !! PERMISSIONS FOR USER GROUPS !!
690 # !! PERMISSIONS FOR USER GROUPS !!
691 #======================================================================
691 #======================================================================
692 # user group for user group permissions
692 # user group for user group permissions
693 user_group_user_groups_perms = \
693 user_group_user_groups_perms = \
694 self.sa.query(UserGroupUserGroupToPerm, Permission, UserGroup)\
694 self.sa.query(UserGroupUserGroupToPerm, Permission, UserGroup)\
695 .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id
695 .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id
696 == UserGroup.users_group_id))\
696 == UserGroup.users_group_id))\
697 .join((Permission, UserGroupUserGroupToPerm.permission_id
697 .join((Permission, UserGroupUserGroupToPerm.permission_id
698 == Permission.permission_id))\
698 == Permission.permission_id))\
699 .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id
699 .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id
700 == UserGroupMember.users_group_id))\
700 == UserGroupMember.users_group_id))\
701 .filter(UserGroupMember.user_id == uid)\
701 .filter(UserGroupMember.user_id == uid)\
702 .all()
702 .all()
703
703
704 multiple_counter = collections.defaultdict(int)
704 multiple_counter = collections.defaultdict(int)
705 for perm in user_group_user_groups_perms:
705 for perm in user_group_user_groups_perms:
706 g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name
706 g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name
707 multiple_counter[g_k] += 1
707 multiple_counter[g_k] += 1
708 p = perm.Permission.permission_name
708 p = perm.Permission.permission_name
709 cur_perm = user.permissions[UK][g_k]
709 cur_perm = user.permissions[UK][g_k]
710 if multiple_counter[g_k] > 1:
710 if multiple_counter[g_k] > 1:
711 p = _choose_perm(p, cur_perm)
711 p = _choose_perm(p, cur_perm)
712 user.permissions[UK][g_k] = p
712 user.permissions[UK][g_k] = p
713
713
714 #user explicit permission for user groups
714 #user explicit permission for user groups
715 user_user_groups_perms = Permission.get_default_user_group_perms(uid)
715 user_user_groups_perms = Permission.get_default_user_group_perms(uid)
716 for perm in user_user_groups_perms:
716 for perm in user_user_groups_perms:
717 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
717 u_k = perm.UserUserGroupToPerm.user_group.users_group_name
718 p = perm.Permission.permission_name
718 p = perm.Permission.permission_name
719 cur_perm = user.permissions[UK][u_k]
719 cur_perm = user.permissions[UK][u_k]
720 if not explicit:
720 if not explicit:
721 p = _choose_perm(p, cur_perm)
721 p = _choose_perm(p, cur_perm)
722 user.permissions[UK][u_k] = p
722 user.permissions[UK][u_k] = p
723
723
724 return user
724 return user
725
725
726 def has_perm(self, user, perm):
726 def has_perm(self, user, perm):
727 perm = self._get_perm(perm)
727 perm = self._get_perm(perm)
728 user = self._get_user(user)
728 user = self._get_user(user)
729
729
730 return UserToPerm.query().filter(UserToPerm.user == user)\
730 return UserToPerm.query().filter(UserToPerm.user == user)\
731 .filter(UserToPerm.permission == perm).scalar() is not None
731 .filter(UserToPerm.permission == perm).scalar() is not None
732
732
733 def grant_perm(self, user, perm):
733 def grant_perm(self, user, perm):
734 """
734 """
735 Grant user global permissions
735 Grant user global permissions
736
736
737 :param user:
737 :param user:
738 :param perm:
738 :param perm:
739 """
739 """
740 user = self._get_user(user)
740 user = self._get_user(user)
741 perm = self._get_perm(perm)
741 perm = self._get_perm(perm)
742 # if this permission is already granted skip it
742 # if this permission is already granted skip it
743 _perm = UserToPerm.query()\
743 _perm = UserToPerm.query()\
744 .filter(UserToPerm.user == user)\
744 .filter(UserToPerm.user == user)\
745 .filter(UserToPerm.permission == perm)\
745 .filter(UserToPerm.permission == perm)\
746 .scalar()
746 .scalar()
747 if _perm:
747 if _perm:
748 return
748 return
749 new = UserToPerm()
749 new = UserToPerm()
750 new.user = user
750 new.user = user
751 new.permission = perm
751 new.permission = perm
752 self.sa.add(new)
752 self.sa.add(new)
753
753
754 def revoke_perm(self, user, perm):
754 def revoke_perm(self, user, perm):
755 """
755 """
756 Revoke users global permissions
756 Revoke users global permissions
757
757
758 :param user:
758 :param user:
759 :param perm:
759 :param perm:
760 """
760 """
761 user = self._get_user(user)
761 user = self._get_user(user)
762 perm = self._get_perm(perm)
762 perm = self._get_perm(perm)
763
763
764 obj = UserToPerm.query()\
764 obj = UserToPerm.query()\
765 .filter(UserToPerm.user == user)\
765 .filter(UserToPerm.user == user)\
766 .filter(UserToPerm.permission == perm)\
766 .filter(UserToPerm.permission == perm)\
767 .scalar()
767 .scalar()
768 if obj:
768 if obj:
769 self.sa.delete(obj)
769 self.sa.delete(obj)
770
770
771 def add_extra_email(self, user, email):
771 def add_extra_email(self, user, email):
772 """
772 """
773 Adds email address to UserEmailMap
773 Adds email address to UserEmailMap
774
774
775 :param user:
775 :param user:
776 :param email:
776 :param email:
777 """
777 """
778 from rhodecode.model import forms
778 from rhodecode.model import forms
779 form = forms.UserExtraEmailForm()()
779 form = forms.UserExtraEmailForm()()
780 data = form.to_python(dict(email=email))
780 data = form.to_python(dict(email=email))
781 user = self._get_user(user)
781 user = self._get_user(user)
782
782
783 obj = UserEmailMap()
783 obj = UserEmailMap()
784 obj.user = user
784 obj.user = user
785 obj.email = data['email']
785 obj.email = data['email']
786 self.sa.add(obj)
786 self.sa.add(obj)
787 return obj
787 return obj
788
788
789 def delete_extra_email(self, user, email_id):
789 def delete_extra_email(self, user, email_id):
790 """
790 """
791 Removes email address from UserEmailMap
791 Removes email address from UserEmailMap
792
792
793 :param user:
793 :param user:
794 :param email_id:
794 :param email_id:
795 """
795 """
796 user = self._get_user(user)
796 user = self._get_user(user)
797 obj = UserEmailMap.query().get(email_id)
797 obj = UserEmailMap.query().get(email_id)
798 if obj:
798 if obj:
799 self.sa.delete(obj)
799 self.sa.delete(obj)
800
800
801 def add_extra_ip(self, user, ip):
801 def add_extra_ip(self, user, ip):
802 """
802 """
803 Adds ip address to UserIpMap
803 Adds ip address to UserIpMap
804
804
805 :param user:
805 :param user:
806 :param ip:
806 :param ip:
807 """
807 """
808 from rhodecode.model import forms
808 from rhodecode.model import forms
809 form = forms.UserExtraIpForm()()
809 form = forms.UserExtraIpForm()()
810 data = form.to_python(dict(ip=ip))
810 data = form.to_python(dict(ip=ip))
811 user = self._get_user(user)
811 user = self._get_user(user)
812
812
813 obj = UserIpMap()
813 obj = UserIpMap()
814 obj.user = user
814 obj.user = user
815 obj.ip_addr = data['ip']
815 obj.ip_addr = data['ip']
816 self.sa.add(obj)
816 self.sa.add(obj)
817 return obj
817 return obj
818
818
819 def delete_extra_ip(self, user, ip_id):
819 def delete_extra_ip(self, user, ip_id):
820 """
820 """
821 Removes ip address from UserIpMap
821 Removes ip address from UserIpMap
822
822
823 :param user:
823 :param user:
824 :param ip_id:
824 :param ip_id:
825 """
825 """
826 user = self._get_user(user)
826 user = self._get_user(user)
827 obj = UserIpMap.query().get(ip_id)
827 obj = UserIpMap.query().get(ip_id)
828 if obj:
828 if obj:
829 self.sa.delete(obj)
829 self.sa.delete(obj)
General Comments 0
You need to be logged in to leave comments. Login now