##// END OF EJS Templates
Merge with upstream
Nicolas VINOT -
r1591:0b63a0d2 merge beta
parent child Browse files
Show More
@@ -0,0 +1,63 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.model.users_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 repository permission model for RhodeCode
7
8 :created_on: Oct 1, 2011
9 :author: nvinot
10 :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
11 :license: GPLv3, see COPYING for more details.
12 """
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
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
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/>.
25
26 import logging
27 from rhodecode.model.db import BaseModel, RepoToPerm, Permission
28 from rhodecode.model.meta import Session
29
30 log = logging.getLogger( __name__ )
31
32 class RepositoryPermissionModel( BaseModel ):
33 def getUserPermission( self, repository, user ):
34 return RepoToPerm.query() \
35 .filter( RepoToPerm.user == user ) \
36 .filter( RepoToPerm.repository == repository ) \
37 .scalar()
38
39 def updateUserPermission( self, repository, user, permission ):
40 permission = Permission.get_by_key( permission )
41 current = self.getUserPermission( repository, user )
42 if current:
43 if not current.permission is permission:
44 current.permission = permission
45 else:
46 p = RepoToPerm()
47 p.user = user
48 p.repository = repository
49 p.permission = permission
50 Session.add( p )
51 Session.commit()
52
53 def deleteUserPermission( self, repository, user ):
54 current = self.getUserPermission( repository, user )
55 if current:
56 Session.delete( current )
57 Session.commit()
58
59 def updateOrDeleteUserPermission( self, repository, user, permission ):
60 if permission:
61 self.updateUserPermission( repository, user, permission )
62 else:
63 self.deleteUserPermission( repository, user )
@@ -0,0 +1,89 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.model.users_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 users group model for RhodeCode
7
8 :created_on: Oct 1, 2011
9 :author: nvinot
10 :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
11 :license: GPLv3, see COPYING for more details.
12 """
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
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
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/>.
25
26 import logging
27 import traceback
28
29 from rhodecode.model import BaseModel
30 from rhodecode.model.caching_query import FromCache
31 from rhodecode.model.db import UsersGroupMember, UsersGroup
32
33 log = logging.getLogger( __name__ )
34
35 class UsersGroupModel( BaseModel ):
36
37 def get( self, users_group_id, cache = False ):
38 users_group = UsersGroup.query()
39 if cache:
40 users_group = users_group.options( FromCache( "sql_cache_short",
41 "get_users_group_%s" % users_group_id ) )
42 return users_group.get( users_group_id )
43
44 def get_by_name( self, name, cache = False, case_insensitive = False ):
45 users_group = UsersGroup.query()
46 if case_insensitive:
47 users_group = users_group.filter( UsersGroup.users_group_name.ilike( name ) )
48 else:
49 users_group = users_group.filter( UsersGroup.users_group_name == name )
50 if cache:
51 users_group = users_group.options( FromCache( "sql_cache_short",
52 "get_users_group_%s" % name ) )
53 return users_group.scalar()
54
55 def create( self, form_data ):
56 try:
57 new_users_group = UsersGroup()
58 for k, v in form_data.items():
59 setattr( new_users_group, k, v )
60
61 self.sa.add( new_users_group )
62 self.sa.commit()
63 return new_users_group
64 except:
65 log.error( traceback.format_exc() )
66 self.sa.rollback()
67 raise
68
69 def add_user_to_group( self, users_group, user ):
70 for m in users_group.members:
71 u = m.user
72 if u.user_id == user.user_id:
73 return m
74
75 try:
76 users_group_member = UsersGroupMember()
77 users_group_member.user = user
78 users_group_member.users_group = users_group
79
80 users_group.members.append( users_group_member )
81 user.group_member.append( users_group_member )
82
83 self.sa.add( users_group_member )
84 self.sa.commit()
85 return users_group_member
86 except:
87 log.error( traceback.format_exc() )
88 self.sa.rollback()
89 raise
@@ -1,98 +1,372 b''
1 import traceback
1 import traceback
2 import logging
2 import logging
3
3
4 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
4 from rhodecode.controllers.api import JSONRPCController, JSONRPCError
5 from rhodecode.lib.auth import HasPermissionAllDecorator
5 from rhodecode.lib.auth import HasPermissionAllDecorator, HasPermissionAnyDecorator
6 from rhodecode.model.scm import ScmModel
6 from rhodecode.model.scm import ScmModel
7
7
8 from rhodecode.model.db import User, UsersGroup, Repository
8 from rhodecode.model.db import User, UsersGroup, Group, Repository
9 from rhodecode.model.repo import RepoModel
10 from rhodecode.model.user import UserModel
11 from rhodecode.model.repo_permission import RepositoryPermissionModel
12 from rhodecode.model.users_group import UsersGroupModel
13 from rhodecode.model import users_group
14 from rhodecode.model.repos_group import ReposGroupModel
15 from sqlalchemy.orm.exc import NoResultFound
9
16
10 log = logging.getLogger(__name__)
17 log = logging.getLogger( __name__ )
11
18
12
19
13 class ApiController(JSONRPCController):
20 class ApiController( JSONRPCController ):
14 """
21 """
15 API Controller
22 API Controller
16
23
17
24
18 Each method needs to have USER as argument this is then based on given
25 Each method needs to have USER as argument this is then based on given
19 API_KEY propagated as instance of user object
26 API_KEY propagated as instance of user object
20
27
21 Preferably this should be first argument also
28 Preferably this should be first argument also
22
29
23
30
24 Each function should also **raise** JSONRPCError for any
31 Each function should also **raise** JSONRPCError for any
25 errors that happens
32 errors that happens
26
33
27 """
34 """
28
35
29 @HasPermissionAllDecorator('hg.admin')
36 @HasPermissionAllDecorator( 'hg.admin' )
30 def pull(self, apiuser, repo):
37 def pull( self, apiuser, repo ):
31 """
38 """
32 Dispatch pull action on given repo
39 Dispatch pull action on given repo
33
40
34
41
35 :param user:
42 :param user:
36 :param repo:
43 :param repo:
37 """
44 """
38
45
39 if Repository.is_valid(repo) is False:
46 if Repository.is_valid( repo ) is False:
40 raise JSONRPCError('Unknown repo "%s"' % repo)
47 raise JSONRPCError( 'Unknown repo "%s"' % repo )
41
48
42 try:
49 try:
43 ScmModel().pull_changes(repo, self.rhodecode_user.username)
50 ScmModel().pull_changes( repo, self.rhodecode_user.username )
44 return 'Pulled from %s' % repo
51 return 'Pulled from %s' % repo
45 except Exception:
52 except Exception:
46 raise JSONRPCError('Unable to pull changes from "%s"' % repo)
53 raise JSONRPCError( 'Unable to pull changes from "%s"' % repo )
54
55 @HasPermissionAllDecorator( 'hg.admin' )
56 def get_user( self, apiuser, username ):
57 """"
58 Get a user by username
59
60 :param apiuser
61 :param username
62 """
47
63
64 user = User.get_by_username( username )
65 if not user:
66 return None
67
68 return dict( id = user.user_id,
69 username = user.username,
70 firstname = user.name,
71 lastname = user.lastname,
72 email = user.email,
73 active = user.active,
74 admin = user.admin,
75 ldap = user.ldap_dn )
48
76
49 @HasPermissionAllDecorator('hg.admin')
77 @HasPermissionAllDecorator( 'hg.admin' )
50 def create_user(self, apiuser, username, password, active, admin, name,
78 def get_users( self, apiuser ):
51 lastname, email):
79 """"
80 Get all users
81
82 :param apiuser
52 """
83 """
53 Creates new user
84
54
85 result = []
86 for user in User.getAll():
87 result.append( dict( id = user.user_id,
88 username = user.username,
89 firstname = user.name,
90 lastname = user.lastname,
91 email = user.email,
92 active = user.active,
93 admin = user.admin,
94 ldap = user.ldap_dn ) )
95 return result
96
97 @HasPermissionAllDecorator( 'hg.admin' )
98 def create_user( self, apiuser, username, password, firstname,
99 lastname, email, active = True, admin = False, ldap_dn = None ):
100 """
101 Create new user
102
55 :param apiuser:
103 :param apiuser:
56 :param username:
104 :param username:
57 :param password:
105 :param password:
58 :param active:
59 :param admin:
60 :param name:
106 :param name:
61 :param lastname:
107 :param lastname:
62 :param email:
108 :param email:
109 :param active:
110 :param admin:
111 :param ldap_dn:
63 """
112 """
64
113
65 form_data = dict(username=username,
114 if self.get_user( apiuser, username ):
66 password=password,
115 raise JSONRPCError( "user %s already exist" % username )
67 active=active,
116
68 admin=admin,
69 name=name,
70 lastname=lastname,
71 email=email)
72 try:
117 try:
73 u = User.create(form_data)
118 form_data = dict( username = username,
74 return {'id':u.user_id,
119 password = password,
75 'msg':'created new user %s' % name}
120 active = active,
121 admin = admin,
122 name = firstname,
123 lastname = lastname,
124 email = email,
125 ldap_dn = ldap_dn )
126 UserModel().create_ldap( username, password, ldap_dn, form_data )
127 return dict( msg = 'created new user %s' % username )
76 except Exception:
128 except Exception:
77 log.error(traceback.format_exc())
129 log.error( traceback.format_exc() )
78 raise JSONRPCError('failed to create user %s' % name)
130 raise JSONRPCError( 'failed to create user %s' % username )
131
132 @HasPermissionAllDecorator( 'hg.admin' )
133 def get_users_group( self, apiuser, group_name ):
134 """"
135 Get users group by name
136
137 :param apiuser
138 :param group_name
139 """
140
141 users_group = UsersGroup.get_by_group_name( group_name )
142 if not users_group:
143 return None
144
145 members = []
146 for user in users_group.members:
147 user = user.user
148 members.append( dict( id = user.user_id,
149 username = user.username,
150 firstname = user.name,
151 lastname = user.lastname,
152 email = user.email,
153 active = user.active,
154 admin = user.admin,
155 ldap = user.ldap_dn ) )
79
156
157 return dict( id = users_group.users_group_id,
158 name = users_group.users_group_name,
159 active = users_group.users_group_active,
160 members = members )
80
161
81 @HasPermissionAllDecorator('hg.admin')
162 @HasPermissionAllDecorator( 'hg.admin' )
82 def create_users_group(self, apiuser, name, active):
163 def get_users_groups( self, apiuser ):
164 """"
165 Get all users groups
166
167 :param apiuser
168 """
169
170 result = []
171 for users_group in UsersGroup.getAll():
172 members = []
173 for user in users_group.members:
174 user = user.user
175 members.append( dict( id = user.user_id,
176 username = user.username,
177 firstname = user.name,
178 lastname = user.lastname,
179 email = user.email,
180 active = user.active,
181 admin = user.admin,
182 ldap = user.ldap_dn ) )
183
184 result.append( dict( id = users_group.users_group_id,
185 name = users_group.users_group_name,
186 active = users_group.users_group_active,
187 members = members ) )
188 return result
189
190 @HasPermissionAllDecorator( 'hg.admin' )
191 def create_users_group( self, apiuser, name, active = True ):
83 """
192 """
84 Creates an new usergroup
193 Creates an new usergroup
85
194
86 :param name:
195 :param name:
87 :param active:
196 :param active:
88 """
197 """
89 form_data = {'users_group_name':name,
198
90 'users_group_active':active}
199 if self.get_users_group( apiuser, name ):
200 raise JSONRPCError( "users group %s already exist" % name )
201
202 try:
203 form_data = dict( users_group_name = name,
204 users_group_active = active )
205 ug = UsersGroup.create( form_data )
206 return dict( id = ug.users_group_id,
207 msg = 'created new users group %s' % name )
208 except Exception:
209 log.error( traceback.format_exc() )
210 raise JSONRPCError( 'failed to create group %s' % name )
211
212 @HasPermissionAllDecorator( 'hg.admin' )
213 def add_user_to_users_group( self, apiuser, group_name, user_name ):
214 """"
215 Add a user to a group
216
217 :param apiuser
218 :param group_name
219 :param user_name
220 """
221
222 try:
223 users_group = UsersGroup.get_by_group_name( group_name )
224 if not users_group:
225 raise JSONRPCError( 'unknown users group %s' % group_name )
226
227 try:
228 user = User.get_by_username( user_name )
229 except NoResultFound:
230 raise JSONRPCError( 'unknown user %s' % user_name )
231
232 ugm = UsersGroupModel().add_user_to_group( users_group, user )
233
234 return dict( id = ugm.users_group_member_id,
235 msg = 'created new users group member' )
236 except Exception:
237 log.error( traceback.format_exc() )
238 raise JSONRPCError( 'failed to create users group member' )
239
240 @HasPermissionAnyDecorator( 'hg.admin' )
241 def get_repo( self, apiuser, repo_name ):
242 """"
243 Get repository by name
244
245 :param apiuser
246 :param repo_name
247 """
248
91 try:
249 try:
92 ug = UsersGroup.create(form_data)
250 repo = Repository.get_by_repo_name( repo_name )
93 return {'id':ug.users_group_id,
251 except NoResultFound:
94 'msg':'created new users group %s' % name}
252 return None
253
254 members = []
255 for user in repo.repo_to_perm:
256 perm = user.permission.permission_name
257 user = user.user
258 members.append( dict( type_ = "user",
259 id = user.user_id,
260 username = user.username,
261 firstname = user.name,
262 lastname = user.lastname,
263 email = user.email,
264 active = user.active,
265 admin = user.admin,
266 ldap = user.ldap_dn,
267 permission = perm ) )
268 for users_group in repo.users_group_to_perm:
269 perm = users_group.permission.permission_name
270 users_group = users_group.users_group
271 members.append( dict( type_ = "users_group",
272 id = users_group.users_group_id,
273 name = users_group.users_group_name,
274 active = users_group.users_group_active,
275 permission = perm ) )
276
277 return dict( id = repo.repo_id,
278 name = repo.repo_name,
279 type = repo.repo_type,
280 description = repo.description,
281 members = members )
282
283 @HasPermissionAnyDecorator( 'hg.admin' )
284 def get_repos( self, apiuser ):
285 """"
286 Get all repositories
287
288 :param apiuser
289 """
290
291 result = []
292 for repository in Repository.getAll():
293 result.append( dict( id = repository.repo_id,
294 name = repository.repo_name,
295 type = repository.repo_type,
296 description = repository.description ) )
297 return result
298
299 @HasPermissionAnyDecorator( 'hg.admin', 'hg.create.repository' )
300 def create_repo( self, apiuser, name, owner_name, description = '', repo_type = 'hg', \
301 private = False ):
302 """
303 Create a repository
304
305 :param apiuser
306 :param name
307 :param description
308 :param type
309 :param private
310 :param owner_name
311 """
312
313 try:
314 try:
315 owner = User.get_by_username( owner_name )
316 except NoResultFound:
317 raise JSONRPCError( 'unknown user %s' % owner )
318
319 if self.get_repo( apiuser, name ):
320 raise JSONRPCError( "repo %s already exist" % name )
321
322 groups = name.split( '/' )
323 real_name = groups[-1]
324 groups = groups[:-1]
325 parent_id = None
326 for g in groups:
327 group = Group.get_by_group_name( g )
328 if not group:
329 group = ReposGroupModel().create( dict( group_name = g,
330 group_description = '',
331 group_parent_id = parent_id ) )
332 parent_id = group.group_id
333
334 RepoModel().create( dict( repo_name = real_name,
335 repo_name_full = name,
336 description = description,
337 private = private,
338 repo_type = repo_type,
339 repo_group = parent_id,
340 clone_uri = None ), owner )
95 except Exception:
341 except Exception:
96 log.error(traceback.format_exc())
342 log.error( traceback.format_exc() )
97 raise JSONRPCError('failed to create group %s' % name)
343 raise JSONRPCError( 'failed to create repository %s' % name )
98 No newline at end of file
344
345 @HasPermissionAnyDecorator( 'hg.admin' )
346 def add_user_to_repo( self, apiuser, repo_name, user_name, perm ):
347 """
348 Add permission for a user to a repository
349
350 :param apiuser
351 :param repo_name
352 :param user_name
353 :param perm
354 """
355
356 try:
357 try:
358 repo = Repository.get_by_repo_name( repo_name )
359 except NoResultFound:
360 raise JSONRPCError( 'unknown repository %s' % repo )
361
362 try:
363 user = User.get_by_username( user_name )
364 except NoResultFound:
365 raise JSONRPCError( 'unknown user %s' % user )
366
367 RepositoryPermissionModel().updateOrDeleteUserPermission( repo, user, perm )
368 except Exception:
369 log.error( traceback.format_exc() )
370 raise JSONRPCError( 'failed to edit permission %(repo)s for %(user)s'
371 % dict( user = user_name, repo = repo_name ) )
372
This diff has been collapsed as it changes many lines, (903 lines changed) Show them Hide them
@@ -1,1050 +1,1069 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.db
3 rhodecode.model.db
4 ~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~
5
5
6 Database Models for RhodeCode
6 Database Models for RhodeCode
7
7
8 :created_on: Apr 08, 2010
8 :created_on: Apr 08, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import datetime
28 import datetime
29 import traceback
29 import traceback
30 from datetime import date
30 from datetime import date
31
31
32 from sqlalchemy import *
32 from sqlalchemy import *
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from sqlalchemy.ext.hybrid import hybrid_property
34 from sqlalchemy.ext.hybrid import hybrid_property
35 from sqlalchemy.orm import relationship, backref, joinedload, class_mapper, \
35 from sqlalchemy.orm import relationship, backref, joinedload, class_mapper, \
36 validates
36 validates
37 from sqlalchemy.orm.interfaces import MapperExtension
37 from sqlalchemy.orm.interfaces import MapperExtension
38 from beaker.cache import cache_region, region_invalidate
38 from beaker.cache import cache_region, region_invalidate
39
39
40 from vcs import get_backend
40 from vcs import get_backend
41 from vcs.utils.helpers import get_scm
41 from vcs.utils.helpers import get_scm
42 from vcs.exceptions import VCSError
42 from vcs.exceptions import VCSError
43 from vcs.utils.lazy import LazyProperty
43 from vcs.utils.lazy import LazyProperty
44
44
45 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
45 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
46 generate_api_key, safe_unicode
46 generate_api_key, safe_unicode
47 from rhodecode.lib.exceptions import UsersGroupsAssignedException
47 from rhodecode.lib.exceptions import UsersGroupsAssignedException
48 from rhodecode.lib.compat import json
48 from rhodecode.lib.compat import json
49
49
50 from rhodecode.model.meta import Base, Session
50 from rhodecode.model.meta import Base, Session
51 from rhodecode.model.caching_query import FromCache
51 from rhodecode.model.caching_query import FromCache
52
52
53
53
54 log = logging.getLogger(__name__)
54 log = logging.getLogger( __name__ )
55
55
56 #==============================================================================
56 #==============================================================================
57 # BASE CLASSES
57 # BASE CLASSES
58 #==============================================================================
58 #==============================================================================
59
59
60 class ModelSerializer(json.JSONEncoder):
60 class ModelSerializer( json.JSONEncoder ):
61 """
61 """
62 Simple Serializer for JSON,
62 Simple Serializer for JSON,
63
63
64 usage::
64 usage::
65
65
66 to make object customized for serialization implement a __json__
66 to make object customized for serialization implement a __json__
67 method that will return a dict for serialization into json
67 method that will return a dict for serialization into json
68
68
69 example::
69 example::
70
70
71 class Task(object):
71 class Task(object):
72
72
73 def __init__(self, name, value):
73 def __init__(self, name, value):
74 self.name = name
74 self.name = name
75 self.value = value
75 self.value = value
76
76
77 def __json__(self):
77 def __json__(self):
78 return dict(name=self.name,
78 return dict(name=self.name,
79 value=self.value)
79 value=self.value)
80
80
81 """
81 """
82
82
83 def default(self, obj):
83 def default( self, obj ):
84
84
85 if hasattr(obj, '__json__'):
85 if hasattr( obj, '__json__' ):
86 return obj.__json__()
86 return obj.__json__()
87 else:
87 else:
88 return json.JSONEncoder.default(self, obj)
88 return json.JSONEncoder.default( self, obj )
89
89
90 class BaseModel(object):
90 class BaseModel( object ):
91 """Base Model for all classess
91 """Base Model for all classess
92
92
93 """
93 """
94
94
95 @classmethod
95 @classmethod
96 def _get_keys(cls):
96 def _get_keys( cls ):
97 """return column names for this model """
97 """return column names for this model """
98 return class_mapper(cls).c.keys()
98 return class_mapper( cls ).c.keys()
99
99
100 def get_dict(self):
100 def get_dict( self ):
101 """return dict with keys and values corresponding
101 """return dict with keys and values corresponding
102 to this model data """
102 to this model data """
103
103
104 d = {}
104 d = {}
105 for k in self._get_keys():
105 for k in self._get_keys():
106 d[k] = getattr(self, k)
106 d[k] = getattr( self, k )
107 return d
107 return d
108
108
109 def get_appstruct(self):
109 def get_appstruct( self ):
110 """return list with keys and values tupples corresponding
110 """return list with keys and values tupples corresponding
111 to this model data """
111 to this model data """
112
112
113 l = []
113 l = []
114 for k in self._get_keys():
114 for k in self._get_keys():
115 l.append((k, getattr(self, k),))
115 l.append( ( k, getattr( self, k ), ) )
116 return l
116 return l
117
117
118 def populate_obj(self, populate_dict):
118 def populate_obj( self, populate_dict ):
119 """populate model with data from given populate_dict"""
119 """populate model with data from given populate_dict"""
120
120
121 for k in self._get_keys():
121 for k in self._get_keys():
122 if k in populate_dict:
122 if k in populate_dict:
123 setattr(self, k, populate_dict[k])
123 setattr( self, k, populate_dict[k] )
124
124
125 @classmethod
125 @classmethod
126 def query(cls):
126 def query( cls ):
127 return Session.query(cls)
127 return Session.query( cls )
128
128
129 @classmethod
129 @classmethod
130 def get(cls, id_):
130 def get( cls, id_ ):
131 if id_:
131 return cls.query().get( id_ )
132 return Session.query(cls).get(id_)
133
132
134 @classmethod
133 @classmethod
135 def delete(cls, id_):
134 def getAll( cls ):
136 obj = Session.query(cls).get(id_)
135 return cls.query().all()
137 Session.delete(obj)
136
137 @classmethod
138 def delete( cls, id_ ):
139 obj = cls.query().get( id_ )
140 Session.delete( obj )
138 Session.commit()
141 Session.commit()
139
142
140
143
141 class RhodeCodeSettings(Base, BaseModel):
144 class RhodeCodeSettings( Base, BaseModel ):
142 __tablename__ = 'rhodecode_settings'
145 __tablename__ = 'rhodecode_settings'
143 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
146 __table_args__ = ( UniqueConstraint( 'app_settings_name' ), {'extend_existing':True} )
144 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
147 app_settings_id = Column( "app_settings_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
145 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
148 app_settings_name = Column( "app_settings_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
146 _app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
149 _app_settings_value = Column( "app_settings_value", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
147
150
148 def __init__(self, k='', v=''):
151 def __init__( self, k = '', v = '' ):
149 self.app_settings_name = k
152 self.app_settings_name = k
150 self.app_settings_value = v
153 self.app_settings_value = v
151
154
152
155
153 @validates('_app_settings_value')
156 @validates( '_app_settings_value' )
154 def validate_settings_value(self, key, val):
157 def validate_settings_value( self, key, val ):
155 assert type(val) == unicode
158 assert type( val ) == unicode
156 return val
159 return val
157
160
158 @hybrid_property
161 @hybrid_property
159 def app_settings_value(self):
162 def app_settings_value( self ):
160 v = self._app_settings_value
163 v = self._app_settings_value
161 if v == 'ldap_active':
164 if v == 'ldap_active':
162 v = str2bool(v)
165 v = str2bool( v )
163 return v
166 return v
164
167
165 @app_settings_value.setter
168 @app_settings_value.setter
166 def app_settings_value(self,val):
169 def app_settings_value( self, val ):
167 """
170 """
168 Setter that will always make sure we use unicode in app_settings_value
171 Setter that will always make sure we use unicode in app_settings_value
169
172
170 :param val:
173 :param val:
171 """
174 """
172 self._app_settings_value = safe_unicode(val)
175 self._app_settings_value = safe_unicode( val )
173
176
174 def __repr__(self):
177 def __repr__( self ):
175 return "<%s('%s:%s')>" % (self.__class__.__name__,
178 return "<%s('%s:%s')>" % ( self.__class__.__name__,
176 self.app_settings_name, self.app_settings_value)
179 self.app_settings_name, self.app_settings_value )
177
180
178
181
179 @classmethod
182 @classmethod
180 def get_by_name(cls, ldap_key):
183 def get_by_name( cls, ldap_key ):
181 return Session.query(cls)\
184 return cls.query()\
182 .filter(cls.app_settings_name == ldap_key).scalar()
185 .filter( cls.app_settings_name == ldap_key ).scalar()
183
186
184 @classmethod
187 @classmethod
185 def get_app_settings(cls, cache=False):
188 def get_app_settings( cls, cache = False ):
186
189
187 ret = Session.query(cls)
190 ret = cls.query()
188
191
189 if cache:
192 if cache:
190 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
193 ret = ret.options( FromCache( "sql_cache_short", "get_hg_settings" ) )
191
194
192 if not ret:
195 if not ret:
193 raise Exception('Could not get application settings !')
196 raise Exception( 'Could not get application settings !' )
194 settings = {}
197 settings = {}
195 for each in ret:
198 for each in ret:
196 settings['rhodecode_' + each.app_settings_name] = \
199 settings['rhodecode_' + each.app_settings_name] = \
197 each.app_settings_value
200 each.app_settings_value
198
201
199 return settings
202 return settings
200
203
201 @classmethod
204 @classmethod
202 def get_ldap_settings(cls, cache=False):
205 def get_ldap_settings( cls, cache = False ):
203 ret = Session.query(cls)\
206 ret = cls.query()\
204 .filter(cls.app_settings_name.startswith('ldap_')).all()
207 .filter( cls.app_settings_name.startswith( 'ldap_' ) ).all()
205 fd = {}
208 fd = {}
206 for row in ret:
209 for row in ret:
207 fd.update({row.app_settings_name:row.app_settings_value})
210 fd.update( {row.app_settings_name:row.app_settings_value} )
208
211
209 return fd
212 return fd
210
213
211
214
212 class RhodeCodeUi(Base, BaseModel):
215 class RhodeCodeUi( Base, BaseModel ):
213 __tablename__ = 'rhodecode_ui'
216 __tablename__ = 'rhodecode_ui'
214 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
217 __table_args__ = ( UniqueConstraint( 'ui_key' ), {'extend_existing':True} )
215
218
216 HOOK_UPDATE = 'changegroup.update'
219 HOOK_UPDATE = 'changegroup.update'
217 HOOK_REPO_SIZE = 'changegroup.repo_size'
220 HOOK_REPO_SIZE = 'changegroup.repo_size'
218 HOOK_PUSH = 'pretxnchangegroup.push_logger'
221 HOOK_PUSH = 'pretxnchangegroup.push_logger'
219 HOOK_PULL = 'preoutgoing.pull_logger'
222 HOOK_PULL = 'preoutgoing.pull_logger'
220
223
221 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
224 ui_id = Column( "ui_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
222 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
225 ui_section = Column( "ui_section", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
223 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
226 ui_key = Column( "ui_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
224 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
227 ui_value = Column( "ui_value", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
225 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
228 ui_active = Column( "ui_active", Boolean(), nullable = True, unique = None, default = True )
226
229
227
230
228 @classmethod
231 @classmethod
229 def get_by_key(cls, key):
232 def get_by_key( cls, key ):
230 return Session.query(cls).filter(cls.ui_key == key)
233 return cls.query().filter( cls.ui_key == key )
231
234
232
235
233 @classmethod
236 @classmethod
234 def get_builtin_hooks(cls):
237 def get_builtin_hooks( cls ):
235 q = cls.query()
238 q = cls.query()
236 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
239 q = q.filter( cls.ui_key.in_( [cls.HOOK_UPDATE,
237 cls.HOOK_REPO_SIZE,
240 cls.HOOK_REPO_SIZE,
238 cls.HOOK_PUSH, cls.HOOK_PULL]))
241 cls.HOOK_PUSH, cls.HOOK_PULL] ) )
239 return q.all()
242 return q.all()
240
243
241 @classmethod
244 @classmethod
242 def get_custom_hooks(cls):
245 def get_custom_hooks( cls ):
243 q = cls.query()
246 q = cls.query()
244 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
247 q = q.filter( ~cls.ui_key.in_( [cls.HOOK_UPDATE,
245 cls.HOOK_REPO_SIZE,
248 cls.HOOK_REPO_SIZE,
246 cls.HOOK_PUSH, cls.HOOK_PULL]))
249 cls.HOOK_PUSH, cls.HOOK_PULL] ) )
247 q = q.filter(cls.ui_section == 'hooks')
250 q = q.filter( cls.ui_section == 'hooks' )
248 return q.all()
251 return q.all()
249
252
250 @classmethod
253 @classmethod
251 def create_or_update_hook(cls, key, val):
254 def create_or_update_hook( cls, key, val ):
252 new_ui = cls.get_by_key(key).scalar() or cls()
255 new_ui = cls.get_by_key( key ).scalar() or cls()
253 new_ui.ui_section = 'hooks'
256 new_ui.ui_section = 'hooks'
254 new_ui.ui_active = True
257 new_ui.ui_active = True
255 new_ui.ui_key = key
258 new_ui.ui_key = key
256 new_ui.ui_value = val
259 new_ui.ui_value = val
257
260
258 Session.add(new_ui)
261 Session.add( new_ui )
259 Session.commit()
262 Session.commit()
260
263
261
264
262 class User(Base, BaseModel):
265 class User( Base, BaseModel ):
263 __tablename__ = 'users'
266 __tablename__ = 'users'
264 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
267 __table_args__ = ( UniqueConstraint( 'username' ), UniqueConstraint( 'email' ), {'extend_existing':True} )
265 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
268 user_id = Column( "user_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
266 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
269 username = Column( "username", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
267 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
270 password = Column( "password", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
268 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
271 active = Column( "active", Boolean(), nullable = True, unique = None, default = None )
269 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
272 admin = Column( "admin", Boolean(), nullable = True, unique = None, default = False )
270 name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
273 name = Column( "name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
271 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
274 lastname = Column( "lastname", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
272 email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
275 email = Column( "email", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
273 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
276 last_login = Column( "last_login", DateTime( timezone = False ), nullable = True, unique = None, default = None )
274 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
277 ldap_dn = Column( "ldap_dn", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
275 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
278 api_key = Column( "api_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
276
279
277 user_log = relationship('UserLog', cascade='all')
280 user_log = relationship( 'UserLog', cascade = 'all' )
278 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
281 user_perms = relationship( 'UserToPerm', primaryjoin = "User.user_id==UserToPerm.user_id", cascade = 'all' )
279
282
280 repositories = relationship('Repository')
283 repositories = relationship( 'Repository' )
281 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
284 user_followers = relationship( 'UserFollowing', primaryjoin = 'UserFollowing.follows_user_id==User.user_id', cascade = 'all' )
282 repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all')
285 repo_to_perm = relationship( 'RepoToPerm', primaryjoin = 'RepoToPerm.user_id==User.user_id', cascade = 'all' )
283
286
284 group_member = relationship('UsersGroupMember', cascade='all')
287 group_member = relationship( 'UsersGroupMember', cascade = 'all' )
285
288
286 @property
289 @property
287 def full_contact(self):
290 def full_contact( self ):
288 return '%s %s <%s>' % (self.name, self.lastname, self.email)
291 return '%s %s <%s>' % ( self.name, self.lastname, self.email )
289
292
290 @property
293 @property
291 def short_contact(self):
294 def short_contact( self ):
292 return '%s %s' % (self.name, self.lastname)
295 return '%s %s' % ( self.name, self.lastname )
293
296
294 @property
297 @property
295 def is_admin(self):
298 def is_admin( self ):
296 return self.admin
299 return self.admin
297
300
298 def __repr__(self):
301 def __repr__( self ):
299 try:
302 try:
300 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
303 return "<%s('id:%s:%s')>" % ( self.__class__.__name__,
301 self.user_id, self.username)
304 self.user_id, self.username )
302 except:
305 except:
303 return self.__class__.__name__
306 return self.__class__.__name__
304
307
305 @classmethod
308 @classmethod
306 def get_by_username(cls, username, case_insensitive=False):
309 def get_by_username( cls, username, case_insensitive = False ):
307 if case_insensitive:
310 if case_insensitive:
308 return Session.query(cls).filter(cls.username.ilike(username)).scalar()
311 return Session.query( cls ).filter( cls.username.ilike( username ) ).scalar()
309 else:
312 else:
310 return Session.query(cls).filter(cls.username == username).scalar()
313 return Session.query( cls ).filter( cls.username == username ).scalar()
311
314
312 @classmethod
315 @classmethod
313 def get_by_api_key(cls, api_key):
316 def get_by_api_key( cls, api_key ):
314 return Session.query(cls).filter(cls.api_key == api_key).one()
317 return cls.query().filter( cls.api_key == api_key ).one()
315
318
316 def update_lastlogin(self):
319 def update_lastlogin( self ):
317 """Update user lastlogin"""
320 """Update user lastlogin"""
318
321
319 self.last_login = datetime.datetime.now()
322 self.last_login = datetime.datetime.now()
320 Session.add(self)
323 Session.add( self )
321 Session.commit()
324 Session.commit()
322 log.debug('updated user %s lastlogin', self.username)
325 log.debug( 'updated user %s lastlogin', self.username )
323
326
324 @classmethod
327 @classmethod
325 def create(cls, form_data):
328 def create( cls, form_data ):
326 from rhodecode.lib.auth import get_crypt_password
329 from rhodecode.lib.auth import get_crypt_password
327
330
328 try:
331 try:
329 new_user = cls()
332 new_user = cls()
330 for k, v in form_data.items():
333 for k, v in form_data.items():
331 if k == 'password':
334 if k == 'password':
332 v = get_crypt_password(v)
335 v = get_crypt_password( v )
333 setattr(new_user, k, v)
336 setattr( new_user, k, v )
334
337
335 new_user.api_key = generate_api_key(form_data['username'])
338 new_user.api_key = generate_api_key( form_data['username'] )
336 Session.add(new_user)
339 Session.add( new_user )
337 Session.commit()
340 Session.commit()
338 return new_user
341 return new_user
339 except:
342 except:
340 log.error(traceback.format_exc())
343 log.error( traceback.format_exc() )
341 Session.rollback()
344 Session.rollback()
342 raise
345 raise
343
346
344 class UserLog(Base, BaseModel):
347 class UserLog( Base, BaseModel ):
345 __tablename__ = 'user_logs'
348 __tablename__ = 'user_logs'
346 __table_args__ = {'extend_existing':True}
349 __table_args__ = {'extend_existing':True}
347 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
350 user_log_id = Column( "user_log_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
348 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
351 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
349 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
352 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None )
350 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
353 repository_name = Column( "repository_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
351 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
354 user_ip = Column( "user_ip", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
352 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
355 action = Column( "action", UnicodeText( length = 1200000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
353 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
356 action_date = Column( "action_date", DateTime( timezone = False ), nullable = True, unique = None, default = None )
354
357
355 @property
358 @property
356 def action_as_day(self):
359 def action_as_day( self ):
357 return date(*self.action_date.timetuple()[:3])
360 return date( *self.action_date.timetuple()[:3] )
358
361
359 user = relationship('User')
362 user = relationship( 'User' )
360 repository = relationship('Repository')
363 repository = relationship( 'Repository' )
361
364
362
365
363 class UsersGroup(Base, BaseModel):
366 class UsersGroup( Base, BaseModel ):
364 __tablename__ = 'users_groups'
367 __tablename__ = 'users_groups'
365 __table_args__ = {'extend_existing':True}
368 __table_args__ = {'extend_existing':True}
366
369
367 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
370 users_group_id = Column( "users_group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
368 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
371 users_group_name = Column( "users_group_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None )
369 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
372 users_group_active = Column( "users_group_active", Boolean(), nullable = True, unique = None, default = None )
370
373
371 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
374 members = relationship( 'UsersGroupMember', cascade = "all, delete, delete-orphan", lazy = "joined" )
372
375
373 def __repr__(self):
376 def __repr__( self ):
374 return '<userGroup(%s)>' % (self.users_group_name)
377 return '<userGroup(%s)>' % ( self.users_group_name )
375
378
376 @classmethod
379 @classmethod
377 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
380 def get_by_group_name( cls, group_name, cache = False, case_insensitive = False ):
378 if case_insensitive:
381 if case_insensitive:
379 gr = Session.query(cls)\
382 gr = cls.query()\
380 .filter(cls.users_group_name.ilike(group_name))
383 .filter( cls.users_group_name.ilike( group_name ) )
381 else:
384 else:
382 gr = Session.query(UsersGroup)\
385 gr = cls.query()\
383 .filter(UsersGroup.users_group_name == group_name)
386 .filter( cls.users_group_name == group_name )
384 if cache:
387 if cache:
385 gr = gr.options(FromCache("sql_cache_short",
388 gr = gr.options( FromCache( "sql_cache_short",
386 "get_user_%s" % group_name))
389 "get_user_%s" % group_name ) )
387 return gr.scalar()
390 return gr.scalar()
388
391
389
392
390 @classmethod
393 @classmethod
391 def get(cls, users_group_id, cache=False):
394 def get( cls, users_group_id, cache = False ):
392 users_group = Session.query(cls)
395 users_group = cls.query()
393 if cache:
396 if cache:
394 users_group = users_group.options(FromCache("sql_cache_short",
397 users_group = users_group.options( FromCache( "sql_cache_short",
395 "get_users_group_%s" % users_group_id))
398 "get_users_group_%s" % users_group_id ) )
396 return users_group.get(users_group_id)
399 return users_group.get( users_group_id )
397
400
398 @classmethod
401 @classmethod
399 def create(cls, form_data):
402 def create( cls, form_data ):
400 try:
403 try:
401 new_users_group = cls()
404 new_users_group = cls()
402 for k, v in form_data.items():
405 for k, v in form_data.items():
403 setattr(new_users_group, k, v)
406 setattr( new_users_group, k, v )
404
407
405 Session.add(new_users_group)
408 Session.add( new_users_group )
406 Session.commit()
409 Session.commit()
407 return new_users_group
410 return new_users_group
408 except:
411 except:
409 log.error(traceback.format_exc())
412 log.error( traceback.format_exc() )
410 Session.rollback()
413 Session.rollback()
411 raise
414 raise
412
415
413 @classmethod
416 @classmethod
414 def update(cls, users_group_id, form_data):
417 def update( cls, users_group_id, form_data ):
415
418
416 try:
419 try:
417 users_group = cls.get(users_group_id, cache=False)
420 users_group = cls.get( users_group_id, cache = False )
418
421
419 for k, v in form_data.items():
422 for k, v in form_data.items():
420 if k == 'users_group_members':
423 if k == 'users_group_members':
421 users_group.members = []
424 users_group.members = []
422 Session.flush()
425 Session.flush()
423 members_list = []
426 members_list = []
424 if v:
427 if v:
425 for u_id in set(list(v)):
428 for u_id in set( list( v ) ):
426 member = UsersGroupMember(users_group_id,u_id)
429 member = UsersGroupMember( users_group_id, u_id )
427 members_list.append(member)
430 members_list.append( member )
428 setattr(users_group, 'members', members_list)
431 setattr( users_group, 'members', members_list )
429 setattr(users_group, k, v)
432 setattr( users_group, k, v )
430
433
431 Session.add(users_group)
434 Session.add( users_group )
432 Session.commit()
435 Session.commit()
433 except:
436 except:
434 log.error(traceback.format_exc())
437 log.error( traceback.format_exc() )
435 Session.rollback()
438 Session.rollback()
436 raise
439 raise
437
440
438 @classmethod
441 @classmethod
439 def delete(cls, users_group_id):
442 def delete( cls, users_group_id ):
440 try:
443 try:
441
444
442 # check if this group is not assigned to repo
445 # check if this group is not assigned to repo
443 assigned_groups = UsersGroupRepoToPerm.query()\
446 assigned_groups = UsersGroupRepoToPerm.query()\
444 .filter(UsersGroupRepoToPerm.users_group_id ==
447 .filter( UsersGroupRepoToPerm.users_group_id ==
445 users_group_id).all()
448 users_group_id ).all()
446
449
447 if assigned_groups:
450 if assigned_groups:
448 raise UsersGroupsAssignedException('Group assigned to %s' %
451 raise UsersGroupsAssignedException( 'Group assigned to %s' %
449 assigned_groups)
452 assigned_groups )
450
453
451 users_group = cls.get(users_group_id, cache=False)
454 users_group = cls.get( users_group_id, cache = False )
452 Session.delete(users_group)
455 Session.delete( users_group )
453 Session.commit()
456 Session.commit()
454 except:
457 except:
455 log.error(traceback.format_exc())
458 log.error( traceback.format_exc() )
456 Session.rollback()
459 Session.rollback()
457 raise
460 raise
458
461
459
462 class UsersGroupMember( Base, BaseModel ):
460 class UsersGroupMember(Base, BaseModel):
461 __tablename__ = 'users_groups_members'
463 __tablename__ = 'users_groups_members'
462 __table_args__ = {'extend_existing':True}
464 __table_args__ = {'extend_existing':True}
463
465
464 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
466 users_group_member_id = Column( "users_group_member_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
465 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
467 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None )
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
468 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
467
469
468 user = relationship('User', lazy='joined')
470 user = relationship( 'User', lazy = 'joined' )
469 users_group = relationship('UsersGroup')
471 users_group = relationship( 'UsersGroup' )
470
472
471 def __init__(self, gr_id='', u_id=''):
473 def __init__( self, gr_id = '', u_id = '' ):
472 self.users_group_id = gr_id
474 self.users_group_id = gr_id
473 self.user_id = u_id
475 self.user_id = u_id
474
476
475 class Repository(Base, BaseModel):
477 @staticmethod
478 def add_user_to_group( group, user ):
479 ugm = UsersGroupMember()
480 ugm.users_group = group
481 ugm.user = user
482 Session.add( ugm )
483 Session.commit()
484 return ugm
485
486 class Repository( Base, BaseModel ):
476 __tablename__ = 'repositories'
487 __tablename__ = 'repositories'
477 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
488 __table_args__ = ( UniqueConstraint( 'repo_name' ), {'extend_existing':True}, )
478
489
479 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
490 repo_id = Column( "repo_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
480 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
491 repo_name = Column( "repo_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None )
481 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
492 clone_uri = Column( "clone_uri", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = False, default = None )
482 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
493 repo_type = Column( "repo_type", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = False, default = 'hg' )
483 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
494 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = False, default = None )
484 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
495 private = Column( "private", Boolean(), nullable = True, unique = None, default = None )
485 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
496 enable_statistics = Column( "statistics", Boolean(), nullable = True, unique = None, default = True )
486 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
497 enable_downloads = Column( "downloads", Boolean(), nullable = True, unique = None, default = True )
487 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
498 description = Column( "description", String( length = 10000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
488 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
499 created_on = Column( 'created_on', DateTime( timezone = False ), nullable = True, unique = None, default = datetime.datetime.now )
489
500
490 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
501 fork_id = Column( "fork_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = True, unique = False, default = None )
491 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
502 group_id = Column( "group_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = True, unique = False, default = None )
492
503
493
504
494 user = relationship('User')
505 user = relationship( 'User' )
495 fork = relationship('Repository', remote_side=repo_id)
506 fork = relationship( 'Repository', remote_side = repo_id )
496 group = relationship('Group')
507 group = relationship( 'Group' )
497 repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
508 repo_to_perm = relationship( 'RepoToPerm', cascade = 'all', order_by = 'RepoToPerm.repo_to_perm_id' )
498 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
509 users_group_to_perm = relationship( 'UsersGroupRepoToPerm', cascade = 'all' )
499 stats = relationship('Statistics', cascade='all', uselist=False)
510 stats = relationship( 'Statistics', cascade = 'all', uselist = False )
500
511
501 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
512 followers = relationship( 'UserFollowing', primaryjoin = 'UserFollowing.follows_repo_id==Repository.repo_id', cascade = 'all' )
502
513
503 logs = relationship('UserLog', cascade='all')
514 logs = relationship( 'UserLog', cascade = 'all' )
504
515
505 def __repr__(self):
516 def __repr__( self ):
506 return "<%s('%s:%s')>" % (self.__class__.__name__,
517 return "<%s('%s:%s')>" % ( self.__class__.__name__,
507 self.repo_id, self.repo_name)
518 self.repo_id, self.repo_name )
508
519
509 @classmethod
520 @classmethod
510 def url_sep(cls):
521 def url_sep( cls ):
511 return '/'
522 return '/'
512
523
513 @classmethod
524 @classmethod
514 def get_by_repo_name(cls, repo_name):
525 def get_by_repo_name( cls, repo_name ):
515 q = Session.query(cls).filter(cls.repo_name == repo_name)
526 q = Session.query( cls ).filter( cls.repo_name == repo_name )
516
527 q = q.options( joinedload( Repository.fork ) )\
517 q = q.options(joinedload(Repository.fork))\
528 .options( joinedload( Repository.user ) )\
518 .options(joinedload(Repository.user))\
529 .options( joinedload( Repository.group ) )
519 .options(joinedload(Repository.group))\
520
521 return q.one()
530 return q.one()
522
531
523 @classmethod
532 @classmethod
524 def get_repo_forks(cls, repo_id):
533 def get_repo_forks( cls, repo_id ):
525 return Session.query(cls).filter(Repository.fork_id == repo_id)
534 return cls.query().filter( Repository.fork_id == repo_id )
526
535
527 @classmethod
536 @classmethod
528 def base_path(cls):
537 def base_path( cls ):
529 """
538 """
530 Returns base path when all repos are stored
539 Returns base path when all repos are stored
531
540
532 :param cls:
541 :param cls:
533 """
542 """
534 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
543 q = Session.query( RhodeCodeUi ).filter( RhodeCodeUi.ui_key ==
535 cls.url_sep())
544 cls.url_sep() )
536 q.options(FromCache("sql_cache_short", "repository_repo_path"))
545 q.options( FromCache( "sql_cache_short", "repository_repo_path" ) )
537 return q.one().ui_value
546 return q.one().ui_value
538
547
539 @property
548 @property
540 def just_name(self):
549 def just_name( self ):
541 return self.repo_name.split(Repository.url_sep())[-1]
550 return self.repo_name.split( Repository.url_sep() )[-1]
542
551
543 @property
552 @property
544 def groups_with_parents(self):
553 def groups_with_parents( self ):
545 groups = []
554 groups = []
546 if self.group is None:
555 if self.group is None:
547 return groups
556 return groups
548
557
549 cur_gr = self.group
558 cur_gr = self.group
550 groups.insert(0, cur_gr)
559 groups.insert( 0, cur_gr )
551 while 1:
560 while 1:
552 gr = getattr(cur_gr, 'parent_group', None)
561 gr = getattr( cur_gr, 'parent_group', None )
553 cur_gr = cur_gr.parent_group
562 cur_gr = cur_gr.parent_group
554 if gr is None:
563 if gr is None:
555 break
564 break
556 groups.insert(0, gr)
565 groups.insert( 0, gr )
557
566
558 return groups
567 return groups
559
568
560 @property
569 @property
561 def groups_and_repo(self):
570 def groups_and_repo( self ):
562 return self.groups_with_parents, self.just_name
571 return self.groups_with_parents, self.just_name
563
572
564 @LazyProperty
573 @LazyProperty
565 def repo_path(self):
574 def repo_path( self ):
566 """
575 """
567 Returns base full path for that repository means where it actually
576 Returns base full path for that repository means where it actually
568 exists on a filesystem
577 exists on a filesystem
569 """
578 """
570 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
579 q = Session.query( RhodeCodeUi ).filter( RhodeCodeUi.ui_key ==
571 Repository.url_sep())
580 Repository.url_sep() )
572 q.options(FromCache("sql_cache_short", "repository_repo_path"))
581 q.options( FromCache( "sql_cache_short", "repository_repo_path" ) )
573 return q.one().ui_value
582 return q.one().ui_value
574
583
575 @property
584 @property
576 def repo_full_path(self):
585 def repo_full_path( self ):
577 p = [self.repo_path]
586 p = [self.repo_path]
578 # we need to split the name by / since this is how we store the
587 # we need to split the name by / since this is how we store the
579 # names in the database, but that eventually needs to be converted
588 # names in the database, but that eventually needs to be converted
580 # into a valid system path
589 # into a valid system path
581 p += self.repo_name.split(Repository.url_sep())
590 p += self.repo_name.split( Repository.url_sep() )
582 return os.path.join(*p)
591 return os.path.join( *p )
583
592
584 def get_new_name(self, repo_name):
593 def get_new_name( self, repo_name ):
585 """
594 """
586 returns new full repository name based on assigned group and new new
595 returns new full repository name based on assigned group and new new
587
596
588 :param group_name:
597 :param group_name:
589 """
598 """
590 path_prefix = self.group.full_path_splitted if self.group else []
599 path_prefix = self.group.full_path_splitted if self.group else []
591 return Repository.url_sep().join(path_prefix + [repo_name])
600 return Repository.url_sep().join( path_prefix + [repo_name] )
592
601
593 @property
602 @property
594 def _ui(self):
603 def _ui( self ):
595 """
604 """
596 Creates an db based ui object for this repository
605 Creates an db based ui object for this repository
597 """
606 """
598 from mercurial import ui
607 from mercurial import ui
599 from mercurial import config
608 from mercurial import config
600 baseui = ui.ui()
609 baseui = ui.ui()
601
610
602 #clean the baseui object
611 #clean the baseui object
603 baseui._ocfg = config.config()
612 baseui._ocfg = config.config()
604 baseui._ucfg = config.config()
613 baseui._ucfg = config.config()
605 baseui._tcfg = config.config()
614 baseui._tcfg = config.config()
606
615
607
616
608 ret = Session.query(RhodeCodeUi)\
617 ret = RhodeCodeUi.query()\
609 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
618 .options( FromCache( "sql_cache_short", "repository_repo_ui" ) ).all()
610
619
611 hg_ui = ret
620 hg_ui = ret
612 for ui_ in hg_ui:
621 for ui_ in hg_ui:
613 if ui_.ui_active:
622 if ui_.ui_active:
614 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
623 log.debug( 'settings ui from db[%s]%s:%s', ui_.ui_section,
615 ui_.ui_key, ui_.ui_value)
624 ui_.ui_key, ui_.ui_value )
616 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
625 baseui.setconfig( ui_.ui_section, ui_.ui_key, ui_.ui_value )
617
626
618 return baseui
627 return baseui
619
628
620 @classmethod
629 @classmethod
621 def is_valid(cls, repo_name):
630 def is_valid( cls, repo_name ):
622 """
631 """
623 returns True if given repo name is a valid filesystem repository
632 returns True if given repo name is a valid filesystem repository
624
633
625 @param cls:
634 @param cls:
626 @param repo_name:
635 @param repo_name:
627 """
636 """
628 from rhodecode.lib.utils import is_valid_repo
637 from rhodecode.lib.utils import is_valid_repo
629
638
630 return is_valid_repo(repo_name, cls.base_path())
639 return is_valid_repo( repo_name, cls.base_path() )
631
640
632
641
633 #==========================================================================
642 #==========================================================================
634 # SCM PROPERTIES
643 # SCM PROPERTIES
635 #==========================================================================
644 #==========================================================================
636
645
637 def get_changeset(self, rev):
646 def get_changeset( self, rev ):
638 return get_changeset_safe(self.scm_instance, rev)
647 return get_changeset_safe( self.scm_instance, rev )
639
648
640 @property
649 @property
641 def tip(self):
650 def tip( self ):
642 return self.get_changeset('tip')
651 return self.get_changeset( 'tip' )
643
652
644 @property
653 @property
645 def author(self):
654 def author( self ):
646 return self.tip.author
655 return self.tip.author
647
656
648 @property
657 @property
649 def last_change(self):
658 def last_change( self ):
650 return self.scm_instance.last_change
659 return self.scm_instance.last_change
651
660
652 #==========================================================================
661 #==========================================================================
653 # SCM CACHE INSTANCE
662 # SCM CACHE INSTANCE
654 #==========================================================================
663 #==========================================================================
655
664
656 @property
665 @property
657 def invalidate(self):
666 def invalidate( self ):
658 """
667 """
659 Returns Invalidation object if this repo should be invalidated
668 Returns Invalidation object if this repo should be invalidated
660 None otherwise. `cache_active = False` means that this cache
669 None otherwise. `cache_active = False` means that this cache
661 state is not valid and needs to be invalidated
670 state is not valid and needs to be invalidated
662 """
671 """
663 return Session.query(CacheInvalidation)\
672 return CacheInvalidation.query()\
664 .filter(CacheInvalidation.cache_key == self.repo_name)\
673 .filter( CacheInvalidation.cache_key == self.repo_name )\
665 .filter(CacheInvalidation.cache_active == False)\
674 .filter( CacheInvalidation.cache_active == False )\
666 .scalar()
675 .scalar()
667
676
668 def set_invalidate(self):
677 def set_invalidate( self ):
669 """
678 """
670 set a cache for invalidation for this instance
679 set a cache for invalidation for this instance
671 """
680 """
672 inv = Session.query(CacheInvalidation)\
681 inv = CacheInvalidation.query()\
673 .filter(CacheInvalidation.cache_key == self.repo_name)\
682 .filter( CacheInvalidation.cache_key == self.repo_name )\
674 .scalar()
683 .scalar()
675
684
676 if inv is None:
685 if inv is None:
677 inv = CacheInvalidation(self.repo_name)
686 inv = CacheInvalidation( self.repo_name )
678 inv.cache_active = True
687 inv.cache_active = True
679 Session.add(inv)
688 Session.add( inv )
680 Session.commit()
689 Session.commit()
681
690
682 @LazyProperty
691 @LazyProperty
683 def scm_instance(self):
692 def scm_instance( self ):
684 return self.__get_instance()
693 return self.__get_instance()
685
694
686 @property
695 @property
687 def scm_instance_cached(self):
696 def scm_instance_cached( self ):
688 @cache_region('long_term')
697 @cache_region( 'long_term' )
689 def _c(repo_name):
698 def _c( repo_name ):
690 return self.__get_instance()
699 return self.__get_instance()
691
700
692 # TODO: remove this trick when beaker 1.6 is released
701 # TODO: remove this trick when beaker 1.6 is released
693 # and have fixed this issue with not supporting unicode keys
702 # and have fixed this issue with not supporting unicode keys
694 rn = safe_str(self.repo_name)
703 rn = safe_str( self.repo_name )
695
704
696 inv = self.invalidate
705 inv = self.invalidate
697 if inv is not None:
706 if inv is not None:
698 region_invalidate(_c, None, rn)
707 region_invalidate( _c, None, rn )
699 # update our cache
708 # update our cache
700 inv.cache_active = True
709 inv.cache_active = True
701 Session.add(inv)
710 Session.add( inv )
702 Session.commit()
711 Session.commit()
703
712
704 return _c(rn)
713 return _c( rn )
705
714
706 def __get_instance(self):
715 def __get_instance( self ):
707
716
708 repo_full_path = self.repo_full_path
717 repo_full_path = self.repo_full_path
709
718
710 try:
719 try:
711 alias = get_scm(repo_full_path)[0]
720 alias = get_scm( repo_full_path )[0]
712 log.debug('Creating instance of %s repository', alias)
721 log.debug( 'Creating instance of %s repository', alias )
713 backend = get_backend(alias)
722 backend = get_backend( alias )
714 except VCSError:
723 except VCSError:
715 log.error(traceback.format_exc())
724 log.error( traceback.format_exc() )
716 log.error('Perhaps this repository is in db and not in '
725 log.error( 'Perhaps this repository is in db and not in '
717 'filesystem run rescan repositories with '
726 'filesystem run rescan repositories with '
718 '"destroy old data " option from admin panel')
727 '"destroy old data " option from admin panel' )
719 return
728 return
720
729
721 if alias == 'hg':
730 if alias == 'hg':
722
731
723 repo = backend(safe_str(repo_full_path), create=False,
732 repo = backend( safe_str( repo_full_path ), create = False,
724 baseui=self._ui)
733 baseui = self._ui )
725 #skip hidden web repository
734 #skip hidden web repository
726 if repo._get_hidden():
735 if repo._get_hidden():
727 return
736 return
728 else:
737 else:
729 repo = backend(repo_full_path, create=False)
738 repo = backend( repo_full_path, create = False )
730
739
731 return repo
740 return repo
732
741
733
742
734 class Group(Base, BaseModel):
743 class Group( Base, BaseModel ):
735 __tablename__ = 'groups'
744 __tablename__ = 'groups'
736 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
745 __table_args__ = ( UniqueConstraint( 'group_name', 'group_parent_id' ),
737 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
746 CheckConstraint( 'group_id != group_parent_id' ), {'extend_existing':True}, )
738 __mapper_args__ = {'order_by':'group_name'}
747 __mapper_args__ = {'order_by':'group_name'}
739
748
740 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
749 group_id = Column( "group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
741 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
750 group_name = Column( "group_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None )
742 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
751 group_parent_id = Column( "group_parent_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = True, unique = None, default = None )
743 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
752 group_description = Column( "group_description", String( length = 10000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
744
753
745 parent_group = relationship('Group', remote_side=group_id)
754 parent_group = relationship( 'Group', remote_side = group_id )
746
755
747
756
748 def __init__(self, group_name='', parent_group=None):
757 def __init__( self, group_name = '', parent_group = None ):
749 self.group_name = group_name
758 self.group_name = group_name
750 self.parent_group = parent_group
759 self.parent_group = parent_group
751
760
752 def __repr__(self):
761 def __repr__( self ):
753 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
762 return "<%s('%s:%s')>" % ( self.__class__.__name__, self.group_id,
754 self.group_name)
763 self.group_name )
755
764
756 @classmethod
765 @classmethod
757 def groups_choices(cls):
766 def groups_choices( cls ):
758 from webhelpers.html import literal as _literal
767 from webhelpers.html import literal as _literal
759 repo_groups = [('', '')]
768 repo_groups = [( '', '' )]
760 sep = ' &raquo; '
769 sep = ' &raquo; '
761 _name = lambda k: _literal(sep.join(k))
770 _name = lambda k: _literal( sep.join( k ) )
762
771
763 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
772 repo_groups.extend( [( x.group_id, _name( x.full_path_splitted ) )
764 for x in cls.query().all()])
773 for x in cls.query().all()] )
765
774
766 repo_groups = sorted(repo_groups,key=lambda t: t[1].split(sep)[0])
775 repo_groups = sorted( repo_groups, key = lambda t: t[1].split( sep )[0] )
767 return repo_groups
776 return repo_groups
768
777
769 @classmethod
778 @classmethod
770 def url_sep(cls):
779 def url_sep( cls ):
771 return '/'
780 return '/'
772
781
773 @classmethod
782 @classmethod
774 def get_by_group_name(cls, group_name):
783 def get_by_group_name( cls, group_name, cache = False, case_insensitive = False ):
775 return cls.query().filter(cls.group_name == group_name).scalar()
784 if case_insensitive:
785 gr = cls.query()\
786 .filter( cls.group_name.ilike( group_name ) )
787 else:
788 gr = cls.query()\
789 .filter( cls.group_name == group_name )
790 if cache:
791 gr = gr.options( FromCache( "sql_cache_short",
792 "get_group_%s" % group_name ) )
793 return gr.scalar()
776
794
777 @property
795 @property
778 def parents(self):
796 def parents( self ):
779 parents_recursion_limit = 5
797 parents_recursion_limit = 5
780 groups = []
798 groups = []
781 if self.parent_group is None:
799 if self.parent_group is None:
782 return groups
800 return groups
783 cur_gr = self.parent_group
801 cur_gr = self.parent_group
784 groups.insert(0, cur_gr)
802 groups.insert( 0, cur_gr )
785 cnt = 0
803 cnt = 0
786 while 1:
804 while 1:
787 cnt += 1
805 cnt += 1
788 gr = getattr(cur_gr, 'parent_group', None)
806 gr = getattr( cur_gr, 'parent_group', None )
789 cur_gr = cur_gr.parent_group
807 cur_gr = cur_gr.parent_group
790 if gr is None:
808 if gr is None:
791 break
809 break
792 if cnt == parents_recursion_limit:
810 if cnt == parents_recursion_limit:
793 # this will prevent accidental infinit loops
811 # this will prevent accidental infinit loops
794 log.error('group nested more than %s' %
812 log.error( 'group nested more than %s' %
795 parents_recursion_limit)
813 parents_recursion_limit )
796 break
814 break
797
815
798 groups.insert(0, gr)
816 groups.insert( 0, gr )
799 return groups
817 return groups
800
818
801 @property
819 @property
802 def children(self):
820 def children( self ):
803 return Session.query(Group).filter(Group.parent_group == self)
821 return Group.query().filter( Group.parent_group == self )
804
822
805 @property
823 @property
806 def name(self):
824 def name( self ):
807 return self.group_name.split(Group.url_sep())[-1]
825 return self.group_name.split( Group.url_sep() )[-1]
808
826
809 @property
827 @property
810 def full_path(self):
828 def full_path( self ):
811 return self.group_name
829 return Group.url_sep().join( [g.group_name for g in self.parents] +
830 [self.group_name] )
812
831
813 @property
832 @property
814 def full_path_splitted(self):
833 def full_path_splitted( self ):
815 return self.group_name.split(Group.url_sep())
834 return self.group_name.split( Group.url_sep() )
816
835
817 @property
836 @property
818 def repositories(self):
837 def repositories( self ):
819 return Session.query(Repository).filter(Repository.group == self)
838 return Repository.query().filter( Repository.group == self )
820
839
821 @property
840 @property
822 def repositories_recursive_count(self):
841 def repositories_recursive_count( self ):
823 cnt = self.repositories.count()
842 cnt = self.repositories.count()
824
843
825 def children_count(group):
844 def children_count( group ):
826 cnt = 0
845 cnt = 0
827 for child in group.children:
846 for child in group.children:
828 cnt += child.repositories.count()
847 cnt += child.repositories.count()
829 cnt += children_count(child)
848 cnt += children_count( child )
830 return cnt
849 return cnt
831
850
832 return cnt + children_count(self)
851 return cnt + children_count( self )
833
852
834
853
835 def get_new_name(self, group_name):
854 def get_new_name( self, group_name ):
836 """
855 """
837 returns new full group name based on parent and new name
856 returns new full group name based on parent and new name
838
857
839 :param group_name:
858 :param group_name:
840 """
859 """
841 path_prefix = self.parent_group.full_path_splitted if self.parent_group else []
860 path_prefix = self.parent_group.full_path_splitted if self.parent_group else []
842 return Group.url_sep().join(path_prefix + [group_name])
861 return Group.url_sep().join( path_prefix + [group_name] )
843
862
844
863
845 class Permission(Base, BaseModel):
864 class Permission( Base, BaseModel ):
846 __tablename__ = 'permissions'
865 __tablename__ = 'permissions'
847 __table_args__ = {'extend_existing':True}
866 __table_args__ = {'extend_existing':True}
848 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
867 permission_id = Column( "permission_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
849 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
868 permission_name = Column( "permission_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
850 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
869 permission_longname = Column( "permission_longname", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
851
870
852 def __repr__(self):
871 def __repr__( self ):
853 return "<%s('%s:%s')>" % (self.__class__.__name__,
872 return "<%s('%s:%s')>" % ( self.__class__.__name__,
854 self.permission_id, self.permission_name)
873 self.permission_id, self.permission_name )
855
874
856 @classmethod
875 @classmethod
857 def get_by_key(cls, key):
876 def get_by_key( cls, key ):
858 return Session.query(cls).filter(cls.permission_name == key).scalar()
877 return cls.query().filter( cls.permission_name == key ).scalar()
859
878
860 class RepoToPerm(Base, BaseModel):
879 class RepoToPerm( Base, BaseModel ):
861 __tablename__ = 'repo_to_perm'
880 __tablename__ = 'repo_to_perm'
862 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
881 __table_args__ = ( UniqueConstraint( 'user_id', 'repository_id' ), {'extend_existing':True} )
863 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
882 repo_to_perm_id = Column( "repo_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
864 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
883 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
865 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
884 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
866 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
885 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None )
867
886
868 user = relationship('User')
887 user = relationship( 'User' )
869 permission = relationship('Permission')
888 permission = relationship( 'Permission' )
870 repository = relationship('Repository')
889 repository = relationship( 'Repository' )
871
890
872 class UserToPerm(Base, BaseModel):
891 class UserToPerm( Base, BaseModel ):
873 __tablename__ = 'user_to_perm'
892 __tablename__ = 'user_to_perm'
874 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
893 __table_args__ = ( UniqueConstraint( 'user_id', 'permission_id' ), {'extend_existing':True} )
875 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
894 user_to_perm_id = Column( "user_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
876 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
895 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
877 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
896 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
878
897
879 user = relationship('User')
898 user = relationship( 'User' )
880 permission = relationship('Permission')
899 permission = relationship( 'Permission' )
881
900
882 @classmethod
901 @classmethod
883 def has_perm(cls, user_id, perm):
902 def has_perm( cls, user_id, perm ):
884 if not isinstance(perm, Permission):
903 if not isinstance( perm, Permission ):
885 raise Exception('perm needs to be an instance of Permission class')
904 raise Exception( 'perm needs to be an instance of Permission class' )
886
905
887 return Session.query(cls).filter(cls.user_id == user_id)\
906 return cls.query().filter( cls.user_id == user_id )\
888 .filter(cls.permission == perm).scalar() is not None
907 .filter( cls.permission == perm ).scalar() is not None
889
908
890 @classmethod
909 @classmethod
891 def grant_perm(cls, user_id, perm):
910 def grant_perm( cls, user_id, perm ):
892 if not isinstance(perm, Permission):
911 if not isinstance( perm, Permission ):
893 raise Exception('perm needs to be an instance of Permission class')
912 raise Exception( 'perm needs to be an instance of Permission class' )
894
913
895 new = cls()
914 new = cls()
896 new.user_id = user_id
915 new.user_id = user_id
897 new.permission = perm
916 new.permission = perm
898 try:
917 try:
899 Session.add(new)
918 Session.add( new )
900 Session.commit()
919 Session.commit()
901 except:
920 except:
902 Session.rollback()
921 Session.rollback()
903
922
904
923
905 @classmethod
924 @classmethod
906 def revoke_perm(cls, user_id, perm):
925 def revoke_perm( cls, user_id, perm ):
907 if not isinstance(perm, Permission):
926 if not isinstance( perm, Permission ):
908 raise Exception('perm needs to be an instance of Permission class')
927 raise Exception( 'perm needs to be an instance of Permission class' )
909
928
910 try:
929 try:
911 Session.query(cls).filter(cls.user_id == user_id)\
930 cls.query().filter( cls.user_id == user_id )\
912 .filter(cls.permission == perm).delete()
931 .filter( cls.permission == perm ).delete()
913 Session.commit()
932 Session.commit()
914 except:
933 except:
915 Session.rollback()
934 Session.rollback()
916
935
917 class UsersGroupRepoToPerm(Base, BaseModel):
936 class UsersGroupRepoToPerm( Base, BaseModel ):
918 __tablename__ = 'users_group_repo_to_perm'
937 __tablename__ = 'users_group_repo_to_perm'
919 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
938 __table_args__ = ( UniqueConstraint( 'repository_id', 'users_group_id', 'permission_id' ), {'extend_existing':True} )
920 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
939 users_group_to_perm_id = Column( "users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
921 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
940 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None )
922 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
941 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
923 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
942 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None )
924
943
925 users_group = relationship('UsersGroup')
944 users_group = relationship( 'UsersGroup' )
926 permission = relationship('Permission')
945 permission = relationship( 'Permission' )
927 repository = relationship('Repository')
946 repository = relationship( 'Repository' )
928
947
929 def __repr__(self):
948 def __repr__( self ):
930 return '<userGroup:%s => %s >' % (self.users_group, self.repository)
949 return '<userGroup:%s => %s >' % ( self.users_group, self.repository )
931
950
932 class UsersGroupToPerm(Base, BaseModel):
951 class UsersGroupToPerm( Base, BaseModel ):
933 __tablename__ = 'users_group_to_perm'
952 __tablename__ = 'users_group_to_perm'
934 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
953 users_group_to_perm_id = Column( "users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
935 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
954 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None )
936 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
955 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
937
956
938 users_group = relationship('UsersGroup')
957 users_group = relationship( 'UsersGroup' )
939 permission = relationship('Permission')
958 permission = relationship( 'Permission' )
940
959
941
960
942 @classmethod
961 @classmethod
943 def has_perm(cls, users_group_id, perm):
962 def has_perm( cls, users_group_id, perm ):
944 if not isinstance(perm, Permission):
963 if not isinstance( perm, Permission ):
945 raise Exception('perm needs to be an instance of Permission class')
964 raise Exception( 'perm needs to be an instance of Permission class' )
946
965
947 return Session.query(cls).filter(cls.users_group_id ==
966 return cls.query().filter( cls.users_group_id ==
948 users_group_id)\
967 users_group_id )\
949 .filter(cls.permission == perm)\
968 .filter( cls.permission == perm )\
950 .scalar() is not None
969 .scalar() is not None
951
970
952 @classmethod
971 @classmethod
953 def grant_perm(cls, users_group_id, perm):
972 def grant_perm( cls, users_group_id, perm ):
954 if not isinstance(perm, Permission):
973 if not isinstance( perm, Permission ):
955 raise Exception('perm needs to be an instance of Permission class')
974 raise Exception( 'perm needs to be an instance of Permission class' )
956
975
957 new = cls()
976 new = cls()
958 new.users_group_id = users_group_id
977 new.users_group_id = users_group_id
959 new.permission = perm
978 new.permission = perm
960 try:
979 try:
961 Session.add(new)
980 Session.add( new )
962 Session.commit()
981 Session.commit()
963 except:
982 except:
964 Session.rollback()
983 Session.rollback()
965
984
966
985
967 @classmethod
986 @classmethod
968 def revoke_perm(cls, users_group_id, perm):
987 def revoke_perm( cls, users_group_id, perm ):
969 if not isinstance(perm, Permission):
988 if not isinstance( perm, Permission ):
970 raise Exception('perm needs to be an instance of Permission class')
989 raise Exception( 'perm needs to be an instance of Permission class' )
971
990
972 try:
991 try:
973 Session.query(cls).filter(cls.users_group_id == users_group_id)\
992 cls.query().filter( cls.users_group_id == users_group_id )\
974 .filter(cls.permission == perm).delete()
993 .filter( cls.permission == perm ).delete()
975 Session.commit()
994 Session.commit()
976 except:
995 except:
977 Session.rollback()
996 Session.rollback()
978
997
979
998
980 class GroupToPerm(Base, BaseModel):
999 class GroupToPerm( Base, BaseModel ):
981 __tablename__ = 'group_to_perm'
1000 __tablename__ = 'group_to_perm'
982 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
1001 __table_args__ = ( UniqueConstraint( 'group_id', 'permission_id' ), {'extend_existing':True} )
983
1002
984 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1003 group_to_perm_id = Column( "group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
985 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1004 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
986 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1005 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
987 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1006 group_id = Column( "group_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = False, unique = None, default = None )
988
1007
989 user = relationship('User')
1008 user = relationship( 'User' )
990 permission = relationship('Permission')
1009 permission = relationship( 'Permission' )
991 group = relationship('Group')
1010 group = relationship( 'Group' )
992
1011
993 class Statistics(Base, BaseModel):
1012 class Statistics( Base, BaseModel ):
994 __tablename__ = 'statistics'
1013 __tablename__ = 'statistics'
995 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
1014 __table_args__ = ( UniqueConstraint( 'repository_id' ), {'extend_existing':True} )
996 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1015 stat_id = Column( "stat_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
997 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
1016 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = True, default = None )
998 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
1017 stat_on_revision = Column( "stat_on_revision", Integer(), nullable = False )
999 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1018 commit_activity = Column( "commit_activity", LargeBinary( 1000000 ), nullable = False )#JSON data
1000 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
1019 commit_activity_combined = Column( "commit_activity_combined", LargeBinary(), nullable = False )#JSON data
1001 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1020 languages = Column( "languages", LargeBinary( 1000000 ), nullable = False )#JSON data
1002
1021
1003 repository = relationship('Repository', single_parent=True)
1022 repository = relationship( 'Repository', single_parent = True )
1004
1023
1005 class UserFollowing(Base, BaseModel):
1024 class UserFollowing( Base, BaseModel ):
1006 __tablename__ = 'user_followings'
1025 __tablename__ = 'user_followings'
1007 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
1026 __table_args__ = ( UniqueConstraint( 'user_id', 'follows_repository_id' ),
1008 UniqueConstraint('user_id', 'follows_user_id')
1027 UniqueConstraint( 'user_id', 'follows_user_id' )
1009 , {'extend_existing':True})
1028 , {'extend_existing':True} )
1010
1029
1011 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1030 user_following_id = Column( "user_following_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
1012 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1031 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
1013 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1032 follows_repo_id = Column( "follows_repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = True, unique = None, default = None )
1014 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1033 follows_user_id = Column( "follows_user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = True, unique = None, default = None )
1015 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1034 follows_from = Column( 'follows_from', DateTime( timezone = False ), nullable = True, unique = None, default = datetime.datetime.now )
1016
1035
1017 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1036 user = relationship( 'User', primaryjoin = 'User.user_id==UserFollowing.user_id' )
1018
1037
1019 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1038 follows_user = relationship( 'User', primaryjoin = 'User.user_id==UserFollowing.follows_user_id' )
1020 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1039 follows_repository = relationship( 'Repository', order_by = 'Repository.repo_name' )
1021
1040
1022
1041
1023 @classmethod
1042 @classmethod
1024 def get_repo_followers(cls, repo_id):
1043 def get_repo_followers( cls, repo_id ):
1025 return Session.query(cls).filter(cls.follows_repo_id == repo_id)
1044 return cls.query().filter( cls.follows_repo_id == repo_id )
1026
1045
1027 class CacheInvalidation(Base, BaseModel):
1046 class CacheInvalidation( Base, BaseModel ):
1028 __tablename__ = 'cache_invalidation'
1047 __tablename__ = 'cache_invalidation'
1029 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
1048 __table_args__ = ( UniqueConstraint( 'cache_key' ), {'extend_existing':True} )
1030 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1049 cache_id = Column( "cache_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
1031 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1050 cache_key = Column( "cache_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
1032 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1051 cache_args = Column( "cache_args", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
1033 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1052 cache_active = Column( "cache_active", Boolean(), nullable = True, unique = None, default = False )
1034
1053
1035
1054
1036 def __init__(self, cache_key, cache_args=''):
1055 def __init__( self, cache_key, cache_args = '' ):
1037 self.cache_key = cache_key
1056 self.cache_key = cache_key
1038 self.cache_args = cache_args
1057 self.cache_args = cache_args
1039 self.cache_active = False
1058 self.cache_active = False
1040
1059
1041 def __repr__(self):
1060 def __repr__( self ):
1042 return "<%s('%s:%s')>" % (self.__class__.__name__,
1061 return "<%s('%s:%s')>" % ( self.__class__.__name__,
1043 self.cache_id, self.cache_key)
1062 self.cache_id, self.cache_key )
1044
1063
1045 class DbMigrateVersion(Base, BaseModel):
1064 class DbMigrateVersion( Base, BaseModel ):
1046 __tablename__ = 'db_migrate_version'
1065 __tablename__ = 'db_migrate_version'
1047 __table_args__ = {'extend_existing':True}
1066 __table_args__ = {'extend_existing':True}
1048 repository_id = Column('repository_id', String(250), primary_key=True)
1067 repository_id = Column( 'repository_id', String( 250 ), primary_key = True )
1049 repository_path = Column('repository_path', Text)
1068 repository_path = Column( 'repository_path', Text )
1050 version = Column('version', Integer)
1069 version = Column( 'version', Integer )
@@ -1,164 +1,174 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user_group
3 rhodecode.model.user_group
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 users groups model for RhodeCode
6 users groups model for RhodeCode
7
7
8 :created_on: Jan 25, 2011
8 :created_on: Jan 25, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import traceback
28 import traceback
29 import shutil
29 import shutil
30
30
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 from vcs.utils.lazy import LazyProperty
33 from vcs.utils.lazy import LazyProperty
34
34
35 from rhodecode.model import BaseModel
35 from rhodecode.model import BaseModel
36 from rhodecode.model.caching_query import FromCache
36 from rhodecode.model.caching_query import FromCache
37 from rhodecode.model.db import Group, RhodeCodeUi
37 from rhodecode.model.db import Group, RhodeCodeUi
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger( __name__ )
40
40
41
41
42 class ReposGroupModel(BaseModel):
42 class ReposGroupModel( BaseModel ):
43
43
44 @LazyProperty
44 @LazyProperty
45 def repos_path(self):
45 def repos_path( self ):
46 """
46 """
47 Get's the repositories root path from database
47 Get's the repositories root path from database
48 """
48 """
49
49
50 q = RhodeCodeUi.get_by_key('/').one()
50 q = RhodeCodeUi.get_by_key( '/' ).one()
51 return q.ui_value
51 return q.ui_value
52
52
53 def __create_group(self, group_name):
53 def __create_group( self, group_name, parent_id ):
54 """
54 """
55 makes repositories group on filesystem
55 makes repositories group on filesystem
56
56
57 :param repo_name:
57 :param repo_name:
58 :param parent_id:
58 :param parent_id:
59 """
59 """
60
60
61 create_path = os.path.join(self.repos_path, group_name)
61 if parent_id:
62 log.debug('creating new group in %s', create_path)
62 paths = Group.get( parent_id ).full_path.split( Group.url_sep() )
63 parent_path = os.sep.join( paths )
64 else:
65 parent_path = ''
66
67 create_path = os.path.join( self.repos_path, parent_path, group_name )
68 log.debug( 'creating new group in %s', create_path )
63
69
64 if os.path.isdir(create_path):
70 if os.path.isdir( create_path ):
65 raise Exception('That directory already exists !')
71 raise Exception( 'That directory already exists !' )
72
66
73
67 os.makedirs(create_path)
74 os.makedirs( create_path )
68
75
69 def __rename_group(self, old, new):
76
77 def __rename_group( self, old, old_parent_id, new, new_parent_id ):
70 """
78 """
71 Renames a group on filesystem
79 Renames a group on filesystem
72
80
73 :param group_name:
81 :param group_name:
74 """
82 """
83 log.debug( 'renaming repos group from %s to %s', old, new )
75
84
76 if old == new:
85 if new_parent_id:
77 log.debug('skipping group rename')
86 paths = Group.get( new_parent_id ).full_path.split( Group.url_sep() )
78 return
87 new_parent_path = os.sep.join( paths )
79
88 else:
80 log.debug('renaming repos group from %s to %s', old, new)
89 new_parent_path = ''
81
82
90
83 old_path = os.path.join(self.repos_path, old)
91 if old_parent_id:
84 new_path = os.path.join(self.repos_path, new)
92 paths = Group.get( old_parent_id ).full_path.split( Group.url_sep() )
93 old_parent_path = os.sep.join( paths )
94 else:
95 old_parent_path = ''
85
96
86 log.debug('renaming repos paths from %s to %s', old_path, new_path)
97 old_path = os.path.join( self.repos_path, old_parent_path, old )
98 new_path = os.path.join( self.repos_path, new_parent_path, new )
87
99
88 if os.path.isdir(new_path):
100 log.debug( 'renaming repos paths from %s to %s', old_path, new_path )
89 raise Exception('Was trying to rename to already '
90 'existing dir %s' % new_path)
91 shutil.move(old_path, new_path)
92
101
93 def __delete_group(self, group):
102 if os.path.isdir( new_path ):
103 raise Exception( 'Was trying to rename to already '
104 'existing dir %s' % new_path )
105 shutil.move( old_path, new_path )
106
107 def __delete_group( self, group ):
94 """
108 """
95 Deletes a group from a filesystem
109 Deletes a group from a filesystem
96
110
97 :param group: instance of group from database
111 :param group: instance of group from database
98 """
112 """
99 paths = group.full_path.split(Group.url_sep())
113 paths = group.full_path.split( Group.url_sep() )
100 paths = os.sep.join(paths)
114 paths = os.sep.join( paths )
101
115
102 rm_path = os.path.join(self.repos_path, paths)
116 rm_path = os.path.join( self.repos_path, paths )
103 if os.path.isdir(rm_path):
117 os.rmdir( rm_path )
104 # delete only if that path really exists
105 os.rmdir(rm_path)
106
118
107 def create(self, form_data):
119 def create( self, form_data ):
108 try:
120 try:
109 new_repos_group = Group()
121 new_repos_group = Group()
110 new_repos_group.group_description = form_data['group_description']
122 new_repos_group.group_name = form_data['group_name']
111 new_repos_group.parent_group = Group.get(form_data['group_parent_id'])
123 new_repos_group.group_description = \
112 new_repos_group.group_name = new_repos_group.get_new_name(form_data['group_name'])
124 form_data['group_description']
125 new_repos_group.group_parent_id = form_data['group_parent_id']
113
126
114 self.sa.add(new_repos_group)
127 self.sa.add( new_repos_group )
115
128
116 self.__create_group(new_repos_group.group_name)
129 self.__create_group( form_data['group_name'],
130 form_data['group_parent_id'] )
117
131
118 self.sa.commit()
132 self.sa.commit()
119 return new_repos_group
133 return new_repos_group
120 except:
134 except:
121 log.error(traceback.format_exc())
135 log.error( traceback.format_exc() )
122 self.sa.rollback()
136 self.sa.rollback()
123 raise
137 raise
124
138
125 def update(self, repos_group_id, form_data):
139 def update( self, repos_group_id, form_data ):
126
140
127 try:
141 try:
128 repos_group = Group.get(repos_group_id)
142 repos_group = Group.get( repos_group_id )
129 old_path = repos_group.full_path
143 old_name = repos_group.group_name
130
144 old_parent_id = repos_group.group_parent_id
131 #change properties
132 repos_group.group_description = form_data['group_description']
133 repos_group.parent_group = Group.get(form_data['group_parent_id'])
134 repos_group.group_name = repos_group.get_new_name(form_data['group_name'])
135
136 new_path = repos_group.full_path
137
145
138 self.sa.add(repos_group)
146 repos_group.group_name = form_data['group_name']
139
147 repos_group.group_description = \
140 self.__rename_group(old_path, new_path)
148 form_data['group_description']
149 repos_group.group_parent_id = form_data['group_parent_id']
141
150
142 # we need to get all repositories from this new group and
151 self.sa.add( repos_group )
143 # rename them accordingly to new group path
152
144 for r in repos_group.repositories:
153 if old_name != form_data['group_name'] or ( old_parent_id !=
145 r.repo_name = r.get_new_name(r.just_name)
154 form_data['group_parent_id'] ):
146 self.sa.add(r)
155 self.__rename_group( old = old_name, old_parent_id = old_parent_id,
156 new = form_data['group_name'],
157 new_parent_id = form_data['group_parent_id'] )
147
158
148 self.sa.commit()
159 self.sa.commit()
149 return repos_group
150 except:
160 except:
151 log.error(traceback.format_exc())
161 log.error( traceback.format_exc() )
152 self.sa.rollback()
162 self.sa.rollback()
153 raise
163 raise
154
164
155 def delete(self, users_group_id):
165 def delete( self, users_group_id ):
156 try:
166 try:
157 users_group = Group.get(users_group_id)
167 users_group = Group.get( users_group_id )
158 self.sa.delete(users_group)
168 self.sa.delete( users_group )
159 self.__delete_group(users_group)
169 self.__delete_group( users_group )
160 self.sa.commit()
170 self.sa.commit()
161 except:
171 except:
162 log.error(traceback.format_exc())
172 log.error( traceback.format_exc() )
163 self.sa.rollback()
173 self.sa.rollback()
164 raise
174 raise
@@ -1,388 +1,388 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) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 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
28
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from rhodecode.lib import safe_unicode
31 from rhodecode.lib import safe_unicode
32 from rhodecode.model import BaseModel
32 from rhodecode.model import BaseModel
33 from rhodecode.model.caching_query import FromCache
33 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
34 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
35 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember
35 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember
36 from rhodecode.lib.exceptions import DefaultUserException, \
36 from rhodecode.lib.exceptions import DefaultUserException, \
37 UserOwnsReposException
37 UserOwnsReposException
38
38
39 from sqlalchemy.exc import DatabaseError
39 from sqlalchemy.exc import DatabaseError
40 from rhodecode.lib import generate_api_key
40 from rhodecode.lib import generate_api_key
41 from sqlalchemy.orm import joinedload
41 from sqlalchemy.orm import joinedload
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45 PERM_WEIGHTS = {'repository.none': 0,
45 PERM_WEIGHTS = {'repository.none': 0,
46 'repository.read': 1,
46 'repository.read': 1,
47 'repository.write': 3,
47 'repository.write': 3,
48 'repository.admin': 3}
48 'repository.admin': 3}
49
49
50
50
51 class UserModel(BaseModel):
51 class UserModel(BaseModel):
52
53 def get(self, user_id, cache=False):
52 def get(self, user_id, cache=False):
54 user = self.sa.query(User)
53 user = self.sa.query(User)
55 if cache:
54 if cache:
56 user = user.options(FromCache("sql_cache_short",
55 user = user.options(FromCache("sql_cache_short",
57 "get_user_%s" % user_id))
56 "get_user_%s" % user_id))
58 return user.get(user_id)
57 return user.get(user_id)
59
58
60 def get_by_username(self, username, cache=False, case_insensitive=False):
59 def get_by_username(self, username, cache=False, case_insensitive=False):
61
60
62 if case_insensitive:
61 if case_insensitive:
63 user = self.sa.query(User).filter(User.username.ilike(username))
62 user = self.sa.query(User).filter(User.username.ilike(username))
64 else:
63 else:
65 user = self.sa.query(User)\
64 user = self.sa.query(User)\
66 .filter(User.username == username)
65 .filter(User.username == username)
67 if cache:
66 if cache:
68 user = user.options(FromCache("sql_cache_short",
67 user = user.options(FromCache("sql_cache_short",
69 "get_user_%s" % username))
68 "get_user_%s" % username))
70 return user.scalar()
69 return user.scalar()
71
70
72 def get_by_api_key(self, api_key, cache=False):
71 def get_by_api_key(self, api_key, cache=False):
73
72
74 user = self.sa.query(User)\
73 user = self.sa.query(User)\
75 .filter(User.api_key == api_key)
74 .filter(User.api_key == api_key)
76 if cache:
75 if cache:
77 user = user.options(FromCache("sql_cache_short",
76 user = user.options(FromCache("sql_cache_short",
78 "get_user_%s" % api_key))
77 "get_user_%s" % api_key))
79 return user.scalar()
78 return user.scalar()
80
79
81 def create(self, form_data):
80 def create(self, form_data):
82 try:
81 try:
83 new_user = User()
82 new_user = User()
84 for k, v in form_data.items():
83 for k, v in form_data.items():
85 setattr(new_user, k, v)
84 setattr(new_user, k, v)
86
85
87 new_user.api_key = generate_api_key(form_data['username'])
86 new_user.api_key = generate_api_key(form_data['username'])
88 self.sa.add(new_user)
87 self.sa.add(new_user)
89 self.sa.commit()
88 self.sa.commit()
89 return new_user
90 except:
90 except:
91 log.error(traceback.format_exc())
91 log.error(traceback.format_exc())
92 self.sa.rollback()
92 self.sa.rollback()
93 raise
93 raise
94
94
95 def create_ldap(self, username, password, user_dn, attrs):
95 def create_ldap(self, username, password, user_dn, attrs):
96 """
96 """
97 Checks if user is in database, if not creates this user marked
97 Checks if user is in database, if not creates this user marked
98 as ldap user
98 as ldap user
99 :param username:
99 :param username:
100 :param password:
100 :param password:
101 :param user_dn:
101 :param user_dn:
102 :param attrs:
102 :param attrs:
103 """
103 """
104 from rhodecode.lib.auth import get_crypt_password
104 from rhodecode.lib.auth import get_crypt_password
105 log.debug('Checking for such ldap account in RhodeCode database')
105 log.debug('Checking for such ldap account in RhodeCode database')
106 if self.get_by_username(username, case_insensitive=True) is None:
106 if self.get_by_username(username, case_insensitive=True) is None:
107 try:
107 try:
108 new_user = User()
108 new_user = User()
109 # add ldap account always lowercase
109 # add ldap account always lowercase
110 new_user.username = username.lower()
110 new_user.username = username.lower()
111 new_user.password = get_crypt_password(password)
111 new_user.password = get_crypt_password(password)
112 new_user.api_key = generate_api_key(username)
112 new_user.api_key = generate_api_key(username)
113 new_user.email = attrs['email']
113 new_user.email = attrs['email']
114 new_user.active = True
114 new_user.active = True
115 new_user.ldap_dn = safe_unicode(user_dn)
115 new_user.ldap_dn = safe_unicode(user_dn)
116 new_user.name = attrs['name']
116 new_user.name = attrs['name']
117 new_user.lastname = attrs['lastname']
117 new_user.lastname = attrs['lastname']
118
118
119 self.sa.add(new_user)
119 self.sa.add(new_user)
120 self.sa.commit()
120 self.sa.commit()
121 return True
121 return True
122 except (DatabaseError,):
122 except (DatabaseError,):
123 log.error(traceback.format_exc())
123 log.error(traceback.format_exc())
124 self.sa.rollback()
124 self.sa.rollback()
125 raise
125 raise
126 log.debug('this %s user exists skipping creation of ldap account',
126 log.debug('this %s user exists skipping creation of ldap account',
127 username)
127 username)
128 return False
128 return False
129
129
130 def create_registration(self, form_data):
130 def create_registration(self, form_data):
131 from rhodecode.lib.celerylib import tasks, run_task
131 from rhodecode.lib.celerylib import tasks, run_task
132 try:
132 try:
133 new_user = User()
133 new_user = User()
134 for k, v in form_data.items():
134 for k, v in form_data.items():
135 if k != 'admin':
135 if k != 'admin':
136 setattr(new_user, k, v)
136 setattr(new_user, k, v)
137
137
138 self.sa.add(new_user)
138 self.sa.add(new_user)
139 self.sa.commit()
139 self.sa.commit()
140 body = ('New user registration\n'
140 body = ('New user registration\n'
141 'username: %s\n'
141 'username: %s\n'
142 'email: %s\n')
142 'email: %s\n')
143 body = body % (form_data['username'], form_data['email'])
143 body = body % (form_data['username'], form_data['email'])
144
144
145 run_task(tasks.send_email, None,
145 run_task(tasks.send_email, None,
146 _('[RhodeCode] New User registration'),
146 _('[RhodeCode] New User registration'),
147 body)
147 body)
148 except:
148 except:
149 log.error(traceback.format_exc())
149 log.error(traceback.format_exc())
150 self.sa.rollback()
150 self.sa.rollback()
151 raise
151 raise
152
152
153 def update(self, user_id, form_data):
153 def update(self, user_id, form_data):
154 try:
154 try:
155 user = self.get(user_id, cache=False)
155 user = self.get(user_id, cache=False)
156 if user.username == 'default':
156 if user.username == 'default':
157 raise DefaultUserException(
157 raise DefaultUserException(
158 _("You can't Edit this user since it's"
158 _("You can't Edit this user since it's"
159 " crucial for entire application"))
159 " crucial for entire application"))
160
160
161 for k, v in form_data.items():
161 for k, v in form_data.items():
162 if k == 'new_password' and v != '':
162 if k == 'new_password' and v != '':
163 user.password = v
163 user.password = v
164 user.api_key = generate_api_key(user.username)
164 user.api_key = generate_api_key(user.username)
165 else:
165 else:
166 setattr(user, k, v)
166 setattr(user, k, v)
167
167
168 self.sa.add(user)
168 self.sa.add(user)
169 self.sa.commit()
169 self.sa.commit()
170 except:
170 except:
171 log.error(traceback.format_exc())
171 log.error(traceback.format_exc())
172 self.sa.rollback()
172 self.sa.rollback()
173 raise
173 raise
174
174
175 def update_my_account(self, user_id, form_data):
175 def update_my_account(self, user_id, form_data):
176 try:
176 try:
177 user = self.get(user_id, cache=False)
177 user = self.get(user_id, cache=False)
178 if user.username == 'default':
178 if user.username == 'default':
179 raise DefaultUserException(
179 raise DefaultUserException(
180 _("You can't Edit this user since it's"
180 _("You can't Edit this user since it's"
181 " crucial for entire application"))
181 " crucial for entire application"))
182 for k, v in form_data.items():
182 for k, v in form_data.items():
183 if k == 'new_password' and v != '':
183 if k == 'new_password' and v != '':
184 user.password = v
184 user.password = v
185 user.api_key = generate_api_key(user.username)
185 user.api_key = generate_api_key(user.username)
186 else:
186 else:
187 if k not in ['admin', 'active']:
187 if k not in ['admin', 'active']:
188 setattr(user, k, v)
188 setattr(user, k, v)
189
189
190 self.sa.add(user)
190 self.sa.add(user)
191 self.sa.commit()
191 self.sa.commit()
192 except:
192 except:
193 log.error(traceback.format_exc())
193 log.error(traceback.format_exc())
194 self.sa.rollback()
194 self.sa.rollback()
195 raise
195 raise
196
196
197 def delete(self, user_id):
197 def delete(self, user_id):
198 try:
198 try:
199 user = self.get(user_id, cache=False)
199 user = self.get(user_id, cache=False)
200 if user.username == 'default':
200 if user.username == 'default':
201 raise DefaultUserException(
201 raise DefaultUserException(
202 _("You can't remove this user since it's"
202 _("You can't remove this user since it's"
203 " crucial for entire application"))
203 " crucial for entire application"))
204 if user.repositories:
204 if user.repositories:
205 raise UserOwnsReposException(_('This user still owns %s '
205 raise UserOwnsReposException(_('This user still owns %s '
206 'repositories and cannot be '
206 'repositories and cannot be '
207 'removed. Switch owners or '
207 'removed. Switch owners or '
208 'remove those repositories') \
208 'remove those repositories') \
209 % user.repositories)
209 % user.repositories)
210 self.sa.delete(user)
210 self.sa.delete(user)
211 self.sa.commit()
211 self.sa.commit()
212 except:
212 except:
213 log.error(traceback.format_exc())
213 log.error(traceback.format_exc())
214 self.sa.rollback()
214 self.sa.rollback()
215 raise
215 raise
216
216
217 def reset_password_link(self, data):
217 def reset_password_link(self, data):
218 from rhodecode.lib.celerylib import tasks, run_task
218 from rhodecode.lib.celerylib import tasks, run_task
219 run_task(tasks.send_password_link, data['email'])
219 run_task(tasks.send_password_link, data['email'])
220
220
221 def reset_password(self, data):
221 def reset_password(self, data):
222 from rhodecode.lib.celerylib import tasks, run_task
222 from rhodecode.lib.celerylib import tasks, run_task
223 run_task(tasks.reset_user_password, data['email'])
223 run_task(tasks.reset_user_password, data['email'])
224
224
225 def fill_data(self, auth_user, user_id=None, api_key=None):
225 def fill_data(self, auth_user, user_id=None, api_key=None):
226 """
226 """
227 Fetches auth_user by user_id,or api_key if present.
227 Fetches auth_user by user_id,or api_key if present.
228 Fills auth_user attributes with those taken from database.
228 Fills auth_user attributes with those taken from database.
229 Additionally set's is_authenitated if lookup fails
229 Additionally set's is_authenitated if lookup fails
230 present in database
230 present in database
231
231
232 :param auth_user: instance of user to set attributes
232 :param auth_user: instance of user to set attributes
233 :param user_id: user id to fetch by
233 :param user_id: user id to fetch by
234 :param api_key: api key to fetch by
234 :param api_key: api key to fetch by
235 """
235 """
236 if user_id is None and api_key is None:
236 if user_id is None and api_key is None:
237 raise Exception('You need to pass user_id or api_key')
237 raise Exception('You need to pass user_id or api_key')
238
238
239 try:
239 try:
240 if api_key:
240 if api_key:
241 dbuser = self.get_by_api_key(api_key)
241 dbuser = self.get_by_api_key(api_key)
242 else:
242 else:
243 dbuser = self.get(user_id)
243 dbuser = self.get(user_id)
244
244
245 if dbuser is not None:
245 if dbuser is not None:
246 log.debug('filling %s data', dbuser)
246 log.debug('filling %s data', dbuser)
247 for k, v in dbuser.get_dict().items():
247 for k, v in dbuser.get_dict().items():
248 setattr(auth_user, k, v)
248 setattr(auth_user, k, v)
249
249
250 except:
250 except:
251 log.error(traceback.format_exc())
251 log.error(traceback.format_exc())
252 auth_user.is_authenticated = False
252 auth_user.is_authenticated = False
253
253
254 return auth_user
254 return auth_user
255
255
256 def fill_perms(self, user):
256 def fill_perms(self, user):
257 """
257 """
258 Fills user permission attribute with permissions taken from database
258 Fills user permission attribute with permissions taken from database
259 works for permissions given for repositories, and for permissions that
259 works for permissions given for repositories, and for permissions that
260 are granted to groups
260 are granted to groups
261
261
262 :param user: user instance to fill his perms
262 :param user: user instance to fill his perms
263 """
263 """
264
264
265 user.permissions['repositories'] = {}
265 user.permissions['repositories'] = {}
266 user.permissions['global'] = set()
266 user.permissions['global'] = set()
267
267
268 #======================================================================
268 #======================================================================
269 # fetch default permissions
269 # fetch default permissions
270 #======================================================================
270 #======================================================================
271 default_user = self.get_by_username('default', cache=True)
271 default_user = self.get_by_username('default', cache=True)
272
272
273 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
273 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
274 .join((Repository, RepoToPerm.repository_id ==
274 .join((Repository, RepoToPerm.repository_id ==
275 Repository.repo_id))\
275 Repository.repo_id))\
276 .join((Permission, RepoToPerm.permission_id ==
276 .join((Permission, RepoToPerm.permission_id ==
277 Permission.permission_id))\
277 Permission.permission_id))\
278 .filter(RepoToPerm.user == default_user).all()
278 .filter(RepoToPerm.user == default_user).all()
279
279
280 if user.is_admin:
280 if user.is_admin:
281 #==================================================================
281 #==================================================================
282 # #admin have all default rights set to admin
282 # #admin have all default rights set to admin
283 #==================================================================
283 #==================================================================
284 user.permissions['global'].add('hg.admin')
284 user.permissions['global'].add('hg.admin')
285
285
286 for perm in default_perms:
286 for perm in default_perms:
287 p = 'repository.admin'
287 p = 'repository.admin'
288 user.permissions['repositories'][perm.RepoToPerm.
288 user.permissions['repositories'][perm.RepoToPerm.
289 repository.repo_name] = p
289 repository.repo_name] = p
290
290
291 else:
291 else:
292 #==================================================================
292 #==================================================================
293 # set default permissions
293 # set default permissions
294 #==================================================================
294 #==================================================================
295 uid = user.user_id
295 uid = user.user_id
296
296
297 #default global
297 #default global
298 default_global_perms = self.sa.query(UserToPerm)\
298 default_global_perms = self.sa.query(UserToPerm)\
299 .filter(UserToPerm.user == default_user)
299 .filter(UserToPerm.user == default_user)
300
300
301 for perm in default_global_perms:
301 for perm in default_global_perms:
302 user.permissions['global'].add(perm.permission.permission_name)
302 user.permissions['global'].add(perm.permission.permission_name)
303
303
304 #default for repositories
304 #default for repositories
305 for perm in default_perms:
305 for perm in default_perms:
306 if perm.Repository.private and not (perm.Repository.user_id ==
306 if perm.Repository.private and not (perm.Repository.user_id ==
307 uid):
307 uid):
308 #diself.sable defaults for private repos,
308 #diself.sable defaults for private repos,
309 p = 'repository.none'
309 p = 'repository.none'
310 elif perm.Repository.user_id == uid:
310 elif perm.Repository.user_id == uid:
311 #set admin if owner
311 #set admin if owner
312 p = 'repository.admin'
312 p = 'repository.admin'
313 else:
313 else:
314 p = perm.Permission.permission_name
314 p = perm.Permission.permission_name
315
315
316 user.permissions['repositories'][perm.RepoToPerm.
316 user.permissions['repositories'][perm.RepoToPerm.
317 repository.repo_name] = p
317 repository.repo_name] = p
318
318
319 #==================================================================
319 #==================================================================
320 # overwrite default with user permissions if any
320 # overwrite default with user permissions if any
321 #==================================================================
321 #==================================================================
322
322
323 #user global
323 #user global
324 user_perms = self.sa.query(UserToPerm)\
324 user_perms = self.sa.query(UserToPerm)\
325 .options(joinedload(UserToPerm.permission))\
325 .options(joinedload(UserToPerm.permission))\
326 .filter(UserToPerm.user_id == uid).all()
326 .filter(UserToPerm.user_id == uid).all()
327
327
328 for perm in user_perms:
328 for perm in user_perms:
329 user.permissions['global'].add(perm.permission.
329 user.permissions['global'].add(perm.permission.
330 permission_name)
330 permission_name)
331
331
332 #user repositories
332 #user repositories
333 user_repo_perms = self.sa.query(RepoToPerm, Permission,
333 user_repo_perms = self.sa.query(RepoToPerm, Permission,
334 Repository)\
334 Repository)\
335 .join((Repository, RepoToPerm.repository_id ==
335 .join((Repository, RepoToPerm.repository_id ==
336 Repository.repo_id))\
336 Repository.repo_id))\
337 .join((Permission, RepoToPerm.permission_id ==
337 .join((Permission, RepoToPerm.permission_id ==
338 Permission.permission_id))\
338 Permission.permission_id))\
339 .filter(RepoToPerm.user_id == uid).all()
339 .filter(RepoToPerm.user_id == uid).all()
340
340
341 for perm in user_repo_perms:
341 for perm in user_repo_perms:
342 # set admin if owner
342 # set admin if owner
343 if perm.Repository.user_id == uid:
343 if perm.Repository.user_id == uid:
344 p = 'repository.admin'
344 p = 'repository.admin'
345 else:
345 else:
346 p = perm.Permission.permission_name
346 p = perm.Permission.permission_name
347 user.permissions['repositories'][perm.RepoToPerm.
347 user.permissions['repositories'][perm.RepoToPerm.
348 repository.repo_name] = p
348 repository.repo_name] = p
349
349
350 #==================================================================
350 #==================================================================
351 # check if user is part of groups for this repository and fill in
351 # check if user is part of groups for this repository and fill in
352 # (or replace with higher) permissions
352 # (or replace with higher) permissions
353 #==================================================================
353 #==================================================================
354
354
355 #users group global
355 #users group global
356 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
356 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
357 .options(joinedload(UsersGroupToPerm.permission))\
357 .options(joinedload(UsersGroupToPerm.permission))\
358 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
358 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
359 UsersGroupMember.users_group_id))\
359 UsersGroupMember.users_group_id))\
360 .filter(UsersGroupMember.user_id == uid).all()
360 .filter(UsersGroupMember.user_id == uid).all()
361
361
362 for perm in user_perms_from_users_groups:
362 for perm in user_perms_from_users_groups:
363 user.permissions['global'].add(perm.permission.permission_name)
363 user.permissions['global'].add(perm.permission.permission_name)
364
364
365 #users group repositories
365 #users group repositories
366 user_repo_perms_from_users_groups = self.sa.query(
366 user_repo_perms_from_users_groups = self.sa.query(
367 UsersGroupRepoToPerm,
367 UsersGroupRepoToPerm,
368 Permission, Repository,)\
368 Permission, Repository,)\
369 .join((Repository, UsersGroupRepoToPerm.repository_id ==
369 .join((Repository, UsersGroupRepoToPerm.repository_id ==
370 Repository.repo_id))\
370 Repository.repo_id))\
371 .join((Permission, UsersGroupRepoToPerm.permission_id ==
371 .join((Permission, UsersGroupRepoToPerm.permission_id ==
372 Permission.permission_id))\
372 Permission.permission_id))\
373 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
373 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
374 UsersGroupMember.users_group_id))\
374 UsersGroupMember.users_group_id))\
375 .filter(UsersGroupMember.user_id == uid).all()
375 .filter(UsersGroupMember.user_id == uid).all()
376
376
377 for perm in user_repo_perms_from_users_groups:
377 for perm in user_repo_perms_from_users_groups:
378 p = perm.Permission.permission_name
378 p = perm.Permission.permission_name
379 cur_perm = user.permissions['repositories'][perm.
379 cur_perm = user.permissions['repositories'][perm.
380 UsersGroupRepoToPerm.
380 UsersGroupRepoToPerm.
381 repository.repo_name]
381 repository.repo_name]
382 #overwrite permission only if it's greater than permission
382 #overwrite permission only if it's greater than permission
383 # given from other sources
383 # given from other sources
384 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
384 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
385 user.permissions['repositories'][perm.UsersGroupRepoToPerm.
385 user.permissions['repositories'][perm.UsersGroupRepoToPerm.
386 repository.repo_name] = p
386 repository.repo_name] = p
387
387
388 return user
388 return user
General Comments 0
You need to be logged in to leave comments. Login now