comparison rhodecode/model/db.py @ 1587:8898a79ac628 beta

Implement all CRUD API operation for repo
author Nicolas VINOT <aeris@imirhil.fr>
date Fri, 07 Oct 2011 01:53:59 +0200
parents 2ccb32ddcfd7
children 10d117545a7e
comparison
equal deleted inserted replaced
1586:2ccb32ddcfd7 1587:8898a79ac628
40 from vcs.utils.helpers import get_scm 40 from vcs.utils.helpers import get_scm
41 from vcs.exceptions import VCSError 41 from vcs.exceptions import VCSError
42 from vcs.utils.lazy import LazyProperty 42 from vcs.utils.lazy import LazyProperty
43 43
44 from rhodecode.lib.exceptions import UsersGroupsAssignedException 44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
45 from rhodecode.lib import str2bool, json, safe_str, get_changeset_safe,\ 45 from rhodecode.lib import str2bool, json, safe_str, get_changeset_safe, \
46 generate_api_key 46 generate_api_key
47 47
48 from rhodecode.model.meta import Base, Session 48 from rhodecode.model.meta import Base, Session
49 from rhodecode.model.caching_query import FromCache 49 from rhodecode.model.caching_query import FromCache
50 50
51 log = logging.getLogger(__name__) 51 log = logging.getLogger( __name__ )
52 52
53 #============================================================================== 53 #==============================================================================
54 # BASE CLASSES 54 # BASE CLASSES
55 #============================================================================== 55 #==============================================================================
56 56
57 class ModelSerializer(json.JSONEncoder): 57 class ModelSerializer( json.JSONEncoder ):
58 """ 58 """
59 Simple Serializer for JSON, 59 Simple Serializer for JSON,
60 60
61 usage:: 61 usage::
62 62
75 return dict(name=self.name, 75 return dict(name=self.name,
76 value=self.value) 76 value=self.value)
77 77
78 """ 78 """
79 79
80 def default(self, obj): 80 def default( self, obj ):
81 81
82 if hasattr(obj, '__json__'): 82 if hasattr( obj, '__json__' ):
83 return obj.__json__() 83 return obj.__json__()
84 else: 84 else:
85 return json.JSONEncoder.default(self, obj) 85 return json.JSONEncoder.default( self, obj )
86 86
87 class BaseModel(object): 87 class BaseModel( object ):
88 """Base Model for all classess 88 """Base Model for all classess
89 89
90 """ 90 """
91 91
92 @classmethod 92 @classmethod
93 def _get_keys(cls): 93 def _get_keys( cls ):
94 """return column names for this model """ 94 """return column names for this model """
95 return class_mapper(cls).c.keys() 95 return class_mapper( cls ).c.keys()
96 96
97 def get_dict(self): 97 def get_dict( self ):
98 """return dict with keys and values corresponding 98 """return dict with keys and values corresponding
99 to this model data """ 99 to this model data """
100 100
101 d = {} 101 d = {}
102 for k in self._get_keys(): 102 for k in self._get_keys():
103 d[k] = getattr(self, k) 103 d[k] = getattr( self, k )
104 return d 104 return d
105 105
106 def get_appstruct(self): 106 def get_appstruct( self ):
107 """return list with keys and values tupples corresponding 107 """return list with keys and values tupples corresponding
108 to this model data """ 108 to this model data """
109 109
110 l = [] 110 l = []
111 for k in self._get_keys(): 111 for k in self._get_keys():
112 l.append((k, getattr(self, k),)) 112 l.append( ( k, getattr( self, k ), ) )
113 return l 113 return l
114 114
115 def populate_obj(self, populate_dict): 115 def populate_obj( self, populate_dict ):
116 """populate model with data from given populate_dict""" 116 """populate model with data from given populate_dict"""
117 117
118 for k in self._get_keys(): 118 for k in self._get_keys():
119 if k in populate_dict: 119 if k in populate_dict:
120 setattr(self, k, populate_dict[k]) 120 setattr( self, k, populate_dict[k] )
121 121
122 @classmethod 122 @classmethod
123 def query(cls): 123 def query( cls ):
124 return Session.query(cls) 124 return Session.query( cls )
125 125
126 @classmethod 126 @classmethod
127 def get(cls, id_): 127 def get( cls, id_ ):
128 return cls.query().get(id_) 128 return cls.query().get( id_ )
129 129
130 @classmethod 130 @classmethod
131 def getAll(cls): 131 def getAll( cls ):
132 return cls.query().all() 132 return cls.query().all()
133 133
134 @classmethod 134 @classmethod
135 def delete(cls, id_): 135 def delete( cls, id_ ):
136 obj = cls.query().get(id_) 136 obj = cls.query().get( id_ )
137 Session.delete(obj) 137 Session.delete( obj )
138 Session.commit() 138 Session.commit()
139 139
140 140
141 class RhodeCodeSettings(Base, BaseModel): 141 class RhodeCodeSettings( Base, BaseModel ):
142 __tablename__ = 'rhodecode_settings' 142 __tablename__ = 'rhodecode_settings'
143 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True}) 143 __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) 144 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) 145 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) 146 app_settings_value = Column( "app_settings_value", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
147 147
148 def __init__(self, k='', v=''): 148 def __init__( self, k = '', v = '' ):
149 self.app_settings_name = k 149 self.app_settings_name = k
150 self.app_settings_value = v 150 self.app_settings_value = v
151 151
152 def __repr__(self): 152 def __repr__( self ):
153 return "<%s('%s:%s')>" % (self.__class__.__name__, 153 return "<%s('%s:%s')>" % ( self.__class__.__name__,
154 self.app_settings_name, self.app_settings_value) 154 self.app_settings_name, self.app_settings_value )
155 155
156 156
157 @classmethod 157 @classmethod
158 def get_by_name(cls, ldap_key): 158 def get_by_name( cls, ldap_key ):
159 return cls.query()\ 159 return cls.query()\
160 .filter(cls.app_settings_name == ldap_key).scalar() 160 .filter( cls.app_settings_name == ldap_key ).scalar()
161 161
162 @classmethod 162 @classmethod
163 def get_app_settings(cls, cache=False): 163 def get_app_settings( cls, cache = False ):
164 164
165 ret = cls.query() 165 ret = cls.query()
166 166
167 if cache: 167 if cache:
168 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) 168 ret = ret.options( FromCache( "sql_cache_short", "get_hg_settings" ) )
169 169
170 if not ret: 170 if not ret:
171 raise Exception('Could not get application settings !') 171 raise Exception( 'Could not get application settings !' )
172 settings = {} 172 settings = {}
173 for each in ret: 173 for each in ret:
174 settings['rhodecode_' + each.app_settings_name] = \ 174 settings['rhodecode_' + each.app_settings_name] = \
175 each.app_settings_value 175 each.app_settings_value
176 176
177 return settings 177 return settings
178 178
179 @classmethod 179 @classmethod
180 def get_ldap_settings(cls, cache=False): 180 def get_ldap_settings( cls, cache = False ):
181 ret = cls.query()\ 181 ret = cls.query()\
182 .filter(cls.app_settings_name.startswith('ldap_'))\ 182 .filter( cls.app_settings_name.startswith( 'ldap_' ) )\
183 .all() 183 .all()
184 fd = {} 184 fd = {}
185 for row in ret: 185 for row in ret:
186 fd.update({row.app_settings_name:row.app_settings_value}) 186 fd.update( {row.app_settings_name:row.app_settings_value} )
187 187
188 fd.update({'ldap_active':str2bool(fd.get('ldap_active'))}) 188 fd.update( {'ldap_active':str2bool( fd.get( 'ldap_active' ) )} )
189 189
190 return fd 190 return fd
191 191
192 192
193 class RhodeCodeUi(Base, BaseModel): 193 class RhodeCodeUi( Base, BaseModel ):
194 __tablename__ = 'rhodecode_ui' 194 __tablename__ = 'rhodecode_ui'
195 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True}) 195 __table_args__ = ( UniqueConstraint( 'ui_key' ), {'extend_existing':True} )
196 196
197 HOOK_UPDATE = 'changegroup.update' 197 HOOK_UPDATE = 'changegroup.update'
198 HOOK_REPO_SIZE = 'changegroup.repo_size' 198 HOOK_REPO_SIZE = 'changegroup.repo_size'
199 HOOK_PUSH = 'pretxnchangegroup.push_logger' 199 HOOK_PUSH = 'pretxnchangegroup.push_logger'
200 HOOK_PULL = 'preoutgoing.pull_logger' 200 HOOK_PULL = 'preoutgoing.pull_logger'
201 201
202 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 202 ui_id = Column( "ui_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
203 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 203 ui_section = Column( "ui_section", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
204 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 204 ui_key = Column( "ui_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
205 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 205 ui_value = Column( "ui_value", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
206 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True) 206 ui_active = Column( "ui_active", Boolean(), nullable = True, unique = None, default = True )
207 207
208 208
209 @classmethod 209 @classmethod
210 def get_by_key(cls, key): 210 def get_by_key( cls, key ):
211 return cls.query().filter(cls.ui_key == key) 211 return cls.query().filter( cls.ui_key == key )
212 212
213 213
214 @classmethod 214 @classmethod
215 def get_builtin_hooks(cls): 215 def get_builtin_hooks( cls ):
216 q = cls.query() 216 q = cls.query()
217 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, 217 q = q.filter( cls.ui_key.in_( [cls.HOOK_UPDATE,
218 cls.HOOK_REPO_SIZE, 218 cls.HOOK_REPO_SIZE,
219 cls.HOOK_PUSH, cls.HOOK_PULL])) 219 cls.HOOK_PUSH, cls.HOOK_PULL] ) )
220 return q.all() 220 return q.all()
221 221
222 @classmethod 222 @classmethod
223 def get_custom_hooks(cls): 223 def get_custom_hooks( cls ):
224 q = cls.query() 224 q = cls.query()
225 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, 225 q = q.filter( ~cls.ui_key.in_( [cls.HOOK_UPDATE,
226 cls.HOOK_REPO_SIZE, 226 cls.HOOK_REPO_SIZE,
227 cls.HOOK_PUSH, cls.HOOK_PULL])) 227 cls.HOOK_PUSH, cls.HOOK_PULL] ) )
228 q = q.filter(cls.ui_section == 'hooks') 228 q = q.filter( cls.ui_section == 'hooks' )
229 return q.all() 229 return q.all()
230 230
231 @classmethod 231 @classmethod
232 def create_or_update_hook(cls, key, val): 232 def create_or_update_hook( cls, key, val ):
233 new_ui = cls.get_by_key(key).scalar() or cls() 233 new_ui = cls.get_by_key( key ).scalar() or cls()
234 new_ui.ui_section = 'hooks' 234 new_ui.ui_section = 'hooks'
235 new_ui.ui_active = True 235 new_ui.ui_active = True
236 new_ui.ui_key = key 236 new_ui.ui_key = key
237 new_ui.ui_value = val 237 new_ui.ui_value = val
238 238
239 Session.add(new_ui) 239 Session.add( new_ui )
240 Session.commit() 240 Session.commit()
241 241
242 242
243 class User(Base, BaseModel): 243 class User( Base, BaseModel ):
244 __tablename__ = 'users' 244 __tablename__ = 'users'
245 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True}) 245 __table_args__ = ( UniqueConstraint( 'username' ), UniqueConstraint( 'email' ), {'extend_existing':True} )
246 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 246 user_id = Column( "user_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
247 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 247 username = Column( "username", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
248 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 248 password = Column( "password", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
249 active = Column("active", Boolean(), nullable=True, unique=None, default=None) 249 active = Column( "active", Boolean(), nullable = True, unique = None, default = None )
250 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False) 250 admin = Column( "admin", Boolean(), nullable = True, unique = None, default = False )
251 name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 251 name = Column( "name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
252 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 252 lastname = Column( "lastname", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
253 email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 253 email = Column( "email", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
254 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None) 254 last_login = Column( "last_login", DateTime( timezone = False ), nullable = True, unique = None, default = None )
255 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 255 ldap_dn = Column( "ldap_dn", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
256 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 256 api_key = Column( "api_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
257 257
258 user_log = relationship('UserLog', cascade='all') 258 user_log = relationship( 'UserLog', cascade = 'all' )
259 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all') 259 user_perms = relationship( 'UserToPerm', primaryjoin = "User.user_id==UserToPerm.user_id", cascade = 'all' )
260 260
261 repositories = relationship('Repository') 261 repositories = relationship( 'Repository' )
262 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all') 262 user_followers = relationship( 'UserFollowing', primaryjoin = 'UserFollowing.follows_user_id==User.user_id', cascade = 'all' )
263 repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all') 263 repo_to_perm = relationship( 'RepoToPerm', primaryjoin = 'RepoToPerm.user_id==User.user_id', cascade = 'all' )
264 264
265 group_member = relationship('UsersGroupMember', cascade='all') 265 group_member = relationship( 'UsersGroupMember', cascade = 'all' )
266 266
267 @property 267 @property
268 def full_contact(self): 268 def full_contact( self ):
269 return '%s %s <%s>' % (self.name, self.lastname, self.email) 269 return '%s %s <%s>' % ( self.name, self.lastname, self.email )
270 270
271 @property 271 @property
272 def short_contact(self): 272 def short_contact( self ):
273 return '%s %s' % (self.name, self.lastname) 273 return '%s %s' % ( self.name, self.lastname )
274 274
275 @property 275 @property
276 def is_admin(self): 276 def is_admin( self ):
277 return self.admin 277 return self.admin
278 278
279 def __repr__(self): 279 def __repr__( self ):
280 try: 280 try:
281 return "<%s('id:%s:%s')>" % (self.__class__.__name__, 281 return "<%s('id:%s:%s')>" % ( self.__class__.__name__,
282 self.user_id, self.username) 282 self.user_id, self.username )
283 except: 283 except:
284 return self.__class__.__name__ 284 return self.__class__.__name__
285 285
286 @classmethod 286 @classmethod
287 def by_username(cls, username, case_insensitive=False): 287 def by_username( cls, username, case_insensitive = False ):
288 if case_insensitive: 288 if case_insensitive:
289 return cls.query().filter(cls.username.like(username)).one() 289 return cls.query().filter( cls.username.like( username ) ).one()
290 else: 290 else:
291 return cls.query().filter(cls.username == username).one() 291 return cls.query().filter( cls.username == username ).one()
292 292
293 @classmethod 293 @classmethod
294 def get_by_api_key(cls, api_key): 294 def get_by_api_key( cls, api_key ):
295 return cls.query().filter(cls.api_key == api_key).one() 295 return cls.query().filter( cls.api_key == api_key ).one()
296 296
297 def update_lastlogin(self): 297 def update_lastlogin( self ):
298 """Update user lastlogin""" 298 """Update user lastlogin"""
299 299
300 self.last_login = datetime.datetime.now() 300 self.last_login = datetime.datetime.now()
301 Session.add(self) 301 Session.add( self )
302 Session.commit() 302 Session.commit()
303 log.debug('updated user %s lastlogin', self.username) 303 log.debug( 'updated user %s lastlogin', self.username )
304 304
305 @classmethod 305 @classmethod
306 def create(cls, form_data): 306 def create( cls, form_data ):
307 from rhodecode.lib.auth import get_crypt_password 307 from rhodecode.lib.auth import get_crypt_password
308 308
309 try: 309 try:
310 new_user = cls() 310 new_user = cls()
311 for k, v in form_data.items(): 311 for k, v in form_data.items():
312 if k == 'password': 312 if k == 'password':
313 v = get_crypt_password(v) 313 v = get_crypt_password( v )
314 setattr(new_user, k, v) 314 setattr( new_user, k, v )
315 315
316 new_user.api_key = generate_api_key(form_data['username']) 316 new_user.api_key = generate_api_key( form_data['username'] )
317 Session.add(new_user) 317 Session.add( new_user )
318 Session.commit() 318 Session.commit()
319 return new_user 319 return new_user
320 except: 320 except:
321 log.error(traceback.format_exc()) 321 log.error( traceback.format_exc() )
322 Session.rollback() 322 Session.rollback()
323 raise 323 raise
324 324
325 class UserLog(Base, BaseModel): 325 class UserLog( Base, BaseModel ):
326 __tablename__ = 'user_logs' 326 __tablename__ = 'user_logs'
327 __table_args__ = {'extend_existing':True} 327 __table_args__ = {'extend_existing':True}
328 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 328 user_log_id = Column( "user_log_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
329 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) 329 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
330 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) 330 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None )
331 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 331 repository_name = Column( "repository_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
332 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 332 user_ip = Column( "user_ip", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
333 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 333 action = Column( "action", UnicodeText( length = 1200000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
334 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None) 334 action_date = Column( "action_date", DateTime( timezone = False ), nullable = True, unique = None, default = None )
335 335
336 @property 336 @property
337 def action_as_day(self): 337 def action_as_day( self ):
338 return date(*self.action_date.timetuple()[:3]) 338 return date( *self.action_date.timetuple()[:3] )
339 339
340 user = relationship('User') 340 user = relationship( 'User' )
341 repository = relationship('Repository') 341 repository = relationship( 'Repository' )
342 342
343 343
344 class UsersGroup(Base, BaseModel): 344 class UsersGroup( Base, BaseModel ):
345 __tablename__ = 'users_groups' 345 __tablename__ = 'users_groups'
346 __table_args__ = {'extend_existing':True} 346 __table_args__ = {'extend_existing':True}
347 347
348 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 348 users_group_id = Column( "users_group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
349 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) 349 users_group_name = Column( "users_group_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None )
350 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None) 350 users_group_active = Column( "users_group_active", Boolean(), nullable = True, unique = None, default = None )
351 351
352 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined") 352 members = relationship( 'UsersGroupMember', cascade = "all, delete, delete-orphan", lazy = "joined" )
353 353
354 def __repr__(self): 354 def __repr__( self ):
355 return '<userGroup(%s)>' % (self.users_group_name) 355 return '<userGroup(%s)>' % ( self.users_group_name )
356 356
357 @classmethod 357 @classmethod
358 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): 358 def get_by_group_name( cls, group_name, cache = False, case_insensitive = False ):
359 if case_insensitive: 359 if case_insensitive:
360 gr = cls.query()\ 360 gr = cls.query()\
361 .filter(cls.users_group_name.ilike(group_name)) 361 .filter( cls.users_group_name.ilike( group_name ) )
362 else: 362 else:
363 gr = cls.query()\ 363 gr = cls.query()\
364 .filter(cls.users_group_name == group_name) 364 .filter( cls.users_group_name == group_name )
365 if cache: 365 if cache:
366 gr = gr.options(FromCache("sql_cache_short", 366 gr = gr.options( FromCache( "sql_cache_short",
367 "get_user_%s" % group_name)) 367 "get_user_%s" % group_name ) )
368 return gr.scalar() 368 return gr.scalar()
369 369
370 370
371 @classmethod 371 @classmethod
372 def get(cls, users_group_id, cache=False): 372 def get( cls, users_group_id, cache = False ):
373 users_group = cls.query() 373 users_group = cls.query()
374 if cache: 374 if cache:
375 users_group = users_group.options(FromCache("sql_cache_short", 375 users_group = users_group.options( FromCache( "sql_cache_short",
376 "get_users_group_%s" % users_group_id)) 376 "get_users_group_%s" % users_group_id ) )
377 return users_group.get(users_group_id) 377 return users_group.get( users_group_id )
378 378
379 @classmethod 379 @classmethod
380 def create(cls, form_data): 380 def create( cls, form_data ):
381 try: 381 try:
382 new_users_group = cls() 382 new_users_group = cls()
383 for k, v in form_data.items(): 383 for k, v in form_data.items():
384 setattr(new_users_group, k, v) 384 setattr( new_users_group, k, v )
385 385
386 Session.add(new_users_group) 386 Session.add( new_users_group )
387 Session.commit() 387 Session.commit()
388 return new_users_group 388 return new_users_group
389 except: 389 except:
390 log.error(traceback.format_exc()) 390 log.error( traceback.format_exc() )
391 Session.rollback() 391 Session.rollback()
392 raise 392 raise
393 393
394 @classmethod 394 @classmethod
395 def update(cls, users_group_id, form_data): 395 def update( cls, users_group_id, form_data ):
396 396
397 try: 397 try:
398 users_group = cls.get(users_group_id, cache=False) 398 users_group = cls.get( users_group_id, cache = False )
399 399
400 for k, v in form_data.items(): 400 for k, v in form_data.items():
401 if k == 'users_group_members': 401 if k == 'users_group_members':
402 users_group.members = [] 402 users_group.members = []
403 Session.flush() 403 Session.flush()
404 members_list = [] 404 members_list = []
405 if v: 405 if v:
406 for u_id in set(v): 406 for u_id in set( v ):
407 members_list.append(UsersGroupMember( 407 members_list.append( UsersGroupMember(
408 users_group_id, 408 users_group_id,
409 u_id)) 409 u_id ) )
410 setattr(users_group, 'members', members_list) 410 setattr( users_group, 'members', members_list )
411 setattr(users_group, k, v) 411 setattr( users_group, k, v )
412 412
413 Session.add(users_group) 413 Session.add( users_group )
414 Session.commit() 414 Session.commit()
415 except: 415 except:
416 log.error(traceback.format_exc()) 416 log.error( traceback.format_exc() )
417 Session.rollback() 417 Session.rollback()
418 raise 418 raise
419 419
420 @classmethod 420 @classmethod
421 def delete(cls, users_group_id): 421 def delete( cls, users_group_id ):
422 try: 422 try:
423 423
424 # check if this group is not assigned to repo 424 # check if this group is not assigned to repo
425 assigned_groups = UsersGroupRepoToPerm.query()\ 425 assigned_groups = UsersGroupRepoToPerm.query()\
426 .filter(UsersGroupRepoToPerm.users_group_id == 426 .filter( UsersGroupRepoToPerm.users_group_id ==
427 users_group_id).all() 427 users_group_id ).all()
428 428
429 if assigned_groups: 429 if assigned_groups:
430 raise UsersGroupsAssignedException('Group assigned to %s' % 430 raise UsersGroupsAssignedException( 'Group assigned to %s' %
431 assigned_groups) 431 assigned_groups )
432 432
433 users_group = cls.get(users_group_id, cache=False) 433 users_group = cls.get( users_group_id, cache = False )
434 Session.delete(users_group) 434 Session.delete( users_group )
435 Session.commit() 435 Session.commit()
436 except: 436 except:
437 log.error(traceback.format_exc()) 437 log.error( traceback.format_exc() )
438 Session.rollback() 438 Session.rollback()
439 raise 439 raise
440 440
441 441 class UsersGroupMember( Base, BaseModel ):
442 class UsersGroupMember(Base, BaseModel):
443 __tablename__ = 'users_groups_members' 442 __tablename__ = 'users_groups_members'
444 __table_args__ = {'extend_existing':True} 443 __table_args__ = {'extend_existing':True}
445 444
446 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 445 users_group_member_id = Column( "users_group_member_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
447 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) 446 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None )
448 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) 447 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
449 448
450 user = relationship('User', lazy='joined') 449 user = relationship( 'User', lazy = 'joined' )
451 users_group = relationship('UsersGroup') 450 users_group = relationship( 'UsersGroup' )
452 451
453 def __init__(self, gr_id='', u_id=''): 452 def __init__( self, gr_id = '', u_id = '' ):
454 self.users_group_id = gr_id 453 self.users_group_id = gr_id
455 self.user_id = u_id 454 self.user_id = u_id
456 455
457 class Repository(Base, BaseModel): 456 @staticmethod
457 def add_user_to_group( group, user ):
458 ugm = UsersGroupMember()
459 ugm.users_group = group
460 ugm.user = user
461 Session.add( ugm )
462 Session.commit()
463 return ugm
464
465 class Repository( Base, BaseModel ):
458 __tablename__ = 'repositories' 466 __tablename__ = 'repositories'
459 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},) 467 __table_args__ = ( UniqueConstraint( 'repo_name' ), {'extend_existing':True}, )
460 468
461 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 469 repo_id = Column( "repo_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
462 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) 470 repo_name = Column( "repo_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None )
463 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None) 471 clone_uri = Column( "clone_uri", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = False, default = None )
464 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg') 472 repo_type = Column( "repo_type", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = False, default = 'hg' )
465 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None) 473 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = False, default = None )
466 private = Column("private", Boolean(), nullable=True, unique=None, default=None) 474 private = Column( "private", Boolean(), nullable = True, unique = None, default = None )
467 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True) 475 enable_statistics = Column( "statistics", Boolean(), nullable = True, unique = None, default = True )
468 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True) 476 enable_downloads = Column( "downloads", Boolean(), nullable = True, unique = None, default = True )
469 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 477 description = Column( "description", String( length = 10000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
470 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) 478 created_on = Column( 'created_on', DateTime( timezone = False ), nullable = True, unique = None, default = datetime.datetime.now )
471 479
472 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None) 480 fork_id = Column( "fork_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = True, unique = False, default = None )
473 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None) 481 group_id = Column( "group_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = True, unique = False, default = None )
474 482
475 483
476 user = relationship('User') 484 user = relationship( 'User' )
477 fork = relationship('Repository', remote_side=repo_id) 485 fork = relationship( 'Repository', remote_side = repo_id )
478 group = relationship('Group') 486 group = relationship( 'Group' )
479 repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id') 487 repo_to_perm = relationship( 'RepoToPerm', cascade = 'all', order_by = 'RepoToPerm.repo_to_perm_id' )
480 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all') 488 users_group_to_perm = relationship( 'UsersGroupRepoToPerm', cascade = 'all' )
481 stats = relationship('Statistics', cascade='all', uselist=False) 489 stats = relationship( 'Statistics', cascade = 'all', uselist = False )
482 490
483 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all') 491 followers = relationship( 'UserFollowing', primaryjoin = 'UserFollowing.follows_repo_id==Repository.repo_id', cascade = 'all' )
484 492
485 logs = relationship('UserLog', cascade='all') 493 logs = relationship( 'UserLog', cascade = 'all' )
486 494
487 def __repr__(self): 495 def __repr__( self ):
488 return "<%s('%s:%s')>" % (self.__class__.__name__, 496 return "<%s('%s:%s')>" % ( self.__class__.__name__,
489 self.repo_id, self.repo_name) 497 self.repo_id, self.repo_name )
490 498
491 @classmethod 499 @classmethod
492 def by_repo_name(cls, repo_name): 500 def by_repo_name( cls, repo_name ):
493 q = cls.query().filter(cls.repo_name == repo_name) 501 q = cls.query().filter( cls.repo_name == repo_name )
494 502
495 q = q.options(joinedload(Repository.fork))\ 503 q = q.options( joinedload( Repository.fork ) )\
496 .options(joinedload(Repository.user))\ 504 .options( joinedload( Repository.user ) )\
497 .options(joinedload(Repository.group))\ 505 .options( joinedload( Repository.group ) )\
498 506
499 return q.one() 507 return q.one()
500 508
501 @classmethod 509 @classmethod
502 def get_repo_forks(cls, repo_id): 510 def get_repo_forks( cls, repo_id ):
503 return cls.query().filter(Repository.fork_id == repo_id) 511 return cls.query().filter( Repository.fork_id == repo_id )
504 512
505 @classmethod 513 @classmethod
506 def base_path(cls): 514 def base_path( cls ):
507 """ 515 """
508 Returns base path when all repos are stored 516 Returns base path when all repos are stored
509 517
510 :param cls: 518 :param cls:
511 """ 519 """
512 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/') 520 q = Session.query( RhodeCodeUi ).filter( RhodeCodeUi.ui_key == '/' )
513 q.options(FromCache("sql_cache_short", "repository_repo_path")) 521 q.options( FromCache( "sql_cache_short", "repository_repo_path" ) )
514 return q.one().ui_value 522 return q.one().ui_value
515 523
516 @property 524 @property
517 def just_name(self): 525 def just_name( self ):
518 return self.repo_name.split(os.sep)[-1] 526 return self.repo_name.split( os.sep )[-1]
519 527
520 @property 528 @property
521 def groups_with_parents(self): 529 def groups_with_parents( self ):
522 groups = [] 530 groups = []
523 if self.group is None: 531 if self.group is None:
524 return groups 532 return groups
525 533
526 cur_gr = self.group 534 cur_gr = self.group
527 groups.insert(0, cur_gr) 535 groups.insert( 0, cur_gr )
528 while 1: 536 while 1:
529 gr = getattr(cur_gr, 'parent_group', None) 537 gr = getattr( cur_gr, 'parent_group', None )
530 cur_gr = cur_gr.parent_group 538 cur_gr = cur_gr.parent_group
531 if gr is None: 539 if gr is None:
532 break 540 break
533 groups.insert(0, gr) 541 groups.insert( 0, gr )
534 542
535 return groups 543 return groups
536 544
537 @property 545 @property
538 def groups_and_repo(self): 546 def groups_and_repo( self ):
539 return self.groups_with_parents, self.just_name 547 return self.groups_with_parents, self.just_name
540 548
541 @LazyProperty 549 @LazyProperty
542 def repo_path(self): 550 def repo_path( self ):
543 """ 551 """
544 Returns base full path for that repository means where it actually 552 Returns base full path for that repository means where it actually
545 exists on a filesystem 553 exists on a filesystem
546 """ 554 """
547 q = RhodeCodeUi.query().filter(RhodeCodeUi.ui_key == '/') 555 q = RhodeCodeUi.query().filter( RhodeCodeUi.ui_key == '/' )
548 q.options(FromCache("sql_cache_short", "repository_repo_path")) 556 q.options( FromCache( "sql_cache_short", "repository_repo_path" ) )
549 return q.one().ui_value 557 return q.one().ui_value
550 558
551 @property 559 @property
552 def repo_full_path(self): 560 def repo_full_path( self ):
553 p = [self.repo_path] 561 p = [self.repo_path]
554 # we need to split the name by / since this is how we store the 562 # we need to split the name by / since this is how we store the
555 # names in the database, but that eventually needs to be converted 563 # names in the database, but that eventually needs to be converted
556 # into a valid system path 564 # into a valid system path
557 p += self.repo_name.split('/') 565 p += self.repo_name.split( '/' )
558 return os.path.join(*p) 566 return os.path.join( *p )
559 567
560 @property 568 @property
561 def _ui(self): 569 def _ui( self ):
562 """ 570 """
563 Creates an db based ui object for this repository 571 Creates an db based ui object for this repository
564 """ 572 """
565 from mercurial import ui 573 from mercurial import ui
566 from mercurial import config 574 from mercurial import config
571 baseui._ucfg = config.config() 579 baseui._ucfg = config.config()
572 baseui._tcfg = config.config() 580 baseui._tcfg = config.config()
573 581
574 582
575 ret = RhodeCodeUi.query()\ 583 ret = RhodeCodeUi.query()\
576 .options(FromCache("sql_cache_short", "repository_repo_ui")).all() 584 .options( FromCache( "sql_cache_short", "repository_repo_ui" ) ).all()
577 585
578 hg_ui = ret 586 hg_ui = ret
579 for ui_ in hg_ui: 587 for ui_ in hg_ui:
580 if ui_.ui_active: 588 if ui_.ui_active:
581 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, 589 log.debug( 'settings ui from db[%s]%s:%s', ui_.ui_section,
582 ui_.ui_key, ui_.ui_value) 590 ui_.ui_key, ui_.ui_value )
583 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value) 591 baseui.setconfig( ui_.ui_section, ui_.ui_key, ui_.ui_value )
584 592
585 return baseui 593 return baseui
586 594
587 @classmethod 595 @classmethod
588 def is_valid(cls, repo_name): 596 def is_valid( cls, repo_name ):
589 """ 597 """
590 returns True if given repo name is a valid filesystem repository 598 returns True if given repo name is a valid filesystem repository
591 599
592 @param cls: 600 @param cls:
593 @param repo_name: 601 @param repo_name:
594 """ 602 """
595 from rhodecode.lib.utils import is_valid_repo 603 from rhodecode.lib.utils import is_valid_repo
596 604
597 return is_valid_repo(repo_name, cls.base_path()) 605 return is_valid_repo( repo_name, cls.base_path() )
598 606
599 607
600 #========================================================================== 608 #==========================================================================
601 # SCM PROPERTIES 609 # SCM PROPERTIES
602 #========================================================================== 610 #==========================================================================
603 611
604 def get_changeset(self, rev): 612 def get_changeset( self, rev ):
605 return get_changeset_safe(self.scm_instance, rev) 613 return get_changeset_safe( self.scm_instance, rev )
606 614
607 @property 615 @property
608 def tip(self): 616 def tip( self ):
609 return self.get_changeset('tip') 617 return self.get_changeset( 'tip' )
610 618
611 @property 619 @property
612 def author(self): 620 def author( self ):
613 return self.tip.author 621 return self.tip.author
614 622
615 @property 623 @property
616 def last_change(self): 624 def last_change( self ):
617 return self.scm_instance.last_change 625 return self.scm_instance.last_change
618 626
619 #========================================================================== 627 #==========================================================================
620 # SCM CACHE INSTANCE 628 # SCM CACHE INSTANCE
621 #========================================================================== 629 #==========================================================================
622 630
623 @property 631 @property
624 def invalidate(self): 632 def invalidate( self ):
625 """ 633 """
626 Returns Invalidation object if this repo should be invalidated 634 Returns Invalidation object if this repo should be invalidated
627 None otherwise. `cache_active = False` means that this cache 635 None otherwise. `cache_active = False` means that this cache
628 state is not valid and needs to be invalidated 636 state is not valid and needs to be invalidated
629 """ 637 """
630 return CacheInvalidation.query()\ 638 return CacheInvalidation.query()\
631 .filter(CacheInvalidation.cache_key == self.repo_name)\ 639 .filter( CacheInvalidation.cache_key == self.repo_name )\
632 .filter(CacheInvalidation.cache_active == False)\ 640 .filter( CacheInvalidation.cache_active == False )\
633 .scalar() 641 .scalar()
634 642
635 def set_invalidate(self): 643 def set_invalidate( self ):
636 """ 644 """
637 set a cache for invalidation for this instance 645 set a cache for invalidation for this instance
638 """ 646 """
639 inv = CacheInvalidation.query()\ 647 inv = CacheInvalidation.query()\
640 .filter(CacheInvalidation.cache_key == self.repo_name)\ 648 .filter( CacheInvalidation.cache_key == self.repo_name )\
641 .scalar() 649 .scalar()
642 650
643 if inv is None: 651 if inv is None:
644 inv = CacheInvalidation(self.repo_name) 652 inv = CacheInvalidation( self.repo_name )
645 inv.cache_active = True 653 inv.cache_active = True
646 Session.add(inv) 654 Session.add( inv )
647 Session.commit() 655 Session.commit()
648 656
649 @LazyProperty 657 @LazyProperty
650 def scm_instance(self): 658 def scm_instance( self ):
651 return self.__get_instance() 659 return self.__get_instance()
652 660
653 @property 661 @property
654 def scm_instance_cached(self): 662 def scm_instance_cached( self ):
655 @cache_region('long_term') 663 @cache_region( 'long_term' )
656 def _c(repo_name): 664 def _c( repo_name ):
657 return self.__get_instance() 665 return self.__get_instance()
658 666
659 # TODO: remove this trick when beaker 1.6 is released 667 # TODO: remove this trick when beaker 1.6 is released
660 # and have fixed this issue with not supporting unicode keys 668 # and have fixed this issue with not supporting unicode keys
661 rn = safe_str(self.repo_name) 669 rn = safe_str( self.repo_name )
662 670
663 inv = self.invalidate 671 inv = self.invalidate
664 if inv is not None: 672 if inv is not None:
665 region_invalidate(_c, None, rn) 673 region_invalidate( _c, None, rn )
666 # update our cache 674 # update our cache
667 inv.cache_active = True 675 inv.cache_active = True
668 Session.add(inv) 676 Session.add( inv )
669 Session.commit() 677 Session.commit()
670 678
671 return _c(rn) 679 return _c( rn )
672 680
673 def __get_instance(self): 681 def __get_instance( self ):
674 682
675 repo_full_path = self.repo_full_path 683 repo_full_path = self.repo_full_path
676 684
677 try: 685 try:
678 alias = get_scm(repo_full_path)[0] 686 alias = get_scm( repo_full_path )[0]
679 log.debug('Creating instance of %s repository', alias) 687 log.debug( 'Creating instance of %s repository', alias )
680 backend = get_backend(alias) 688 backend = get_backend( alias )
681 except VCSError: 689 except VCSError:
682 log.error(traceback.format_exc()) 690 log.error( traceback.format_exc() )
683 log.error('Perhaps this repository is in db and not in ' 691 log.error( 'Perhaps this repository is in db and not in '
684 'filesystem run rescan repositories with ' 692 'filesystem run rescan repositories with '
685 '"destroy old data " option from admin panel') 693 '"destroy old data " option from admin panel' )
686 return 694 return
687 695
688 if alias == 'hg': 696 if alias == 'hg':
689 697
690 repo = backend(safe_str(repo_full_path), create=False, 698 repo = backend( safe_str( repo_full_path ), create = False,
691 baseui=self._ui) 699 baseui = self._ui )
692 #skip hidden web repository 700 #skip hidden web repository
693 if repo._get_hidden(): 701 if repo._get_hidden():
694 return 702 return
695 else: 703 else:
696 repo = backend(repo_full_path, create=False) 704 repo = backend( repo_full_path, create = False )
697 705
698 return repo 706 return repo
699 707
700 708
701 class Group(Base, BaseModel): 709 class Group( Base, BaseModel ):
702 __tablename__ = 'groups' 710 __tablename__ = 'groups'
703 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'), 711 __table_args__ = ( UniqueConstraint( 'group_name', 'group_parent_id' ),
704 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},) 712 CheckConstraint( 'group_id != group_parent_id' ), {'extend_existing':True}, )
705 __mapper_args__ = {'order_by':'group_name'} 713 __mapper_args__ = {'order_by':'group_name'}
706 714
707 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 715 group_id = Column( "group_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
708 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None) 716 group_name = Column( "group_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = False, unique = True, default = None )
709 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None) 717 group_parent_id = Column( "group_parent_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = True, unique = None, default = None )
710 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 718 group_description = Column( "group_description", String( length = 10000, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
711 719
712 parent_group = relationship('Group', remote_side=group_id) 720 parent_group = relationship( 'Group', remote_side = group_id )
713 721
714 722
715 def __init__(self, group_name='', parent_group=None): 723 def __init__( self, group_name = '', parent_group = None ):
716 self.group_name = group_name 724 self.group_name = group_name
717 self.parent_group = parent_group 725 self.parent_group = parent_group
718 726
719 def __repr__(self): 727 def __repr__( self ):
720 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id, 728 return "<%s('%s:%s')>" % ( self.__class__.__name__, self.group_id,
721 self.group_name) 729 self.group_name )
722 730
723 @classmethod 731 @classmethod
724 def url_sep(cls): 732 def url_sep( cls ):
725 return '/' 733 return '/'
726 734
727 @classmethod 735 @classmethod
728 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): 736 def get_by_group_name( cls, group_name, cache = False, case_insensitive = False ):
729 if case_insensitive: 737 if case_insensitive:
730 gr = cls.query()\ 738 gr = cls.query()\
731 .filter(cls.group_name.ilike(group_name)) 739 .filter( cls.group_name.ilike( group_name ) )
732 else: 740 else:
733 gr = cls.query()\ 741 gr = cls.query()\
734 .filter(cls.group_name == group_name) 742 .filter( cls.group_name == group_name )
735 if cache: 743 if cache:
736 gr = gr.options(FromCache("sql_cache_short", 744 gr = gr.options( FromCache( "sql_cache_short",
737 "get_group_%s" % group_name)) 745 "get_group_%s" % group_name ) )
738 return gr.scalar() 746 return gr.scalar()
739 747
740 @property 748 @property
741 def parents(self): 749 def parents( self ):
742 parents_recursion_limit = 5 750 parents_recursion_limit = 5
743 groups = [] 751 groups = []
744 if self.parent_group is None: 752 if self.parent_group is None:
745 return groups 753 return groups
746 cur_gr = self.parent_group 754 cur_gr = self.parent_group
747 groups.insert(0, cur_gr) 755 groups.insert( 0, cur_gr )
748 cnt = 0 756 cnt = 0
749 while 1: 757 while 1:
750 cnt += 1 758 cnt += 1
751 gr = getattr(cur_gr, 'parent_group', None) 759 gr = getattr( cur_gr, 'parent_group', None )
752 cur_gr = cur_gr.parent_group 760 cur_gr = cur_gr.parent_group
753 if gr is None: 761 if gr is None:
754 break 762 break
755 if cnt == parents_recursion_limit: 763 if cnt == parents_recursion_limit:
756 # this will prevent accidental infinit loops 764 # this will prevent accidental infinit loops
757 log.error('group nested more than %s' % 765 log.error( 'group nested more than %s' %
758 parents_recursion_limit) 766 parents_recursion_limit )
759 break 767 break
760 768
761 groups.insert(0, gr) 769 groups.insert( 0, gr )
762 return groups 770 return groups
763 771
764 @property 772 @property
765 def children(self): 773 def children( self ):
766 return Group.query().filter(Group.parent_group == self) 774 return Group.query().filter( Group.parent_group == self )
767 775
768 @property 776 @property
769 def full_path(self): 777 def full_path( self ):
770 return Group.url_sep().join([g.group_name for g in self.parents] + 778 return Group.url_sep().join( [g.group_name for g in self.parents] +
771 [self.group_name]) 779 [self.group_name] )
772 780
773 @property 781 @property
774 def repositories(self): 782 def repositories( self ):
775 return Repository.query().filter(Repository.group == self) 783 return Repository.query().filter( Repository.group == self )
776 784
777 @property 785 @property
778 def repositories_recursive_count(self): 786 def repositories_recursive_count( self ):
779 cnt = self.repositories.count() 787 cnt = self.repositories.count()
780 788
781 def children_count(group): 789 def children_count( group ):
782 cnt = 0 790 cnt = 0
783 for child in group.children: 791 for child in group.children:
784 cnt += child.repositories.count() 792 cnt += child.repositories.count()
785 cnt += children_count(child) 793 cnt += children_count( child )
786 return cnt 794 return cnt
787 795
788 return cnt + children_count(self) 796 return cnt + children_count( self )
789 797
790 class Permission(Base, BaseModel): 798 class Permission( Base, BaseModel ):
791 __tablename__ = 'permissions' 799 __tablename__ = 'permissions'
792 __table_args__ = {'extend_existing':True} 800 __table_args__ = {'extend_existing':True}
793 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 801 permission_id = Column( "permission_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
794 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 802 permission_name = Column( "permission_name", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
795 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 803 permission_longname = Column( "permission_longname", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
796 804
797 def __repr__(self): 805 def __repr__( self ):
798 return "<%s('%s:%s')>" % (self.__class__.__name__, 806 return "<%s('%s:%s')>" % ( self.__class__.__name__,
799 self.permission_id, self.permission_name) 807 self.permission_id, self.permission_name )
800 808
801 @classmethod 809 @classmethod
802 def get_by_key(cls, key): 810 def get_by_key( cls, key ):
803 return cls.query().filter(cls.permission_name == key).scalar() 811 return cls.query().filter( cls.permission_name == key ).scalar()
804 812
805 class RepoToPerm(Base, BaseModel): 813 class RepoToPerm( Base, BaseModel ):
806 __tablename__ = 'repo_to_perm' 814 __tablename__ = 'repo_to_perm'
807 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True}) 815 __table_args__ = ( UniqueConstraint( 'user_id', 'repository_id' ), {'extend_existing':True} )
808 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 816 repo_to_perm_id = Column( "repo_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
809 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) 817 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
810 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) 818 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
811 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) 819 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None )
812 820
813 user = relationship('User') 821 user = relationship( 'User' )
814 permission = relationship('Permission') 822 permission = relationship( 'Permission' )
815 repository = relationship('Repository') 823 repository = relationship( 'Repository' )
816 824
817 class UserToPerm(Base, BaseModel): 825 class UserToPerm( Base, BaseModel ):
818 __tablename__ = 'user_to_perm' 826 __tablename__ = 'user_to_perm'
819 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True}) 827 __table_args__ = ( UniqueConstraint( 'user_id', 'permission_id' ), {'extend_existing':True} )
820 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 828 user_to_perm_id = Column( "user_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
821 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) 829 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
822 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) 830 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
823 831
824 user = relationship('User') 832 user = relationship( 'User' )
825 permission = relationship('Permission') 833 permission = relationship( 'Permission' )
826 834
827 @classmethod 835 @classmethod
828 def has_perm(cls, user_id, perm): 836 def has_perm( cls, user_id, perm ):
829 if not isinstance(perm, Permission): 837 if not isinstance( perm, Permission ):
830 raise Exception('perm needs to be an instance of Permission class') 838 raise Exception( 'perm needs to be an instance of Permission class' )
831 839
832 return cls.query().filter(cls.user_id == user_id)\ 840 return cls.query().filter( cls.user_id == user_id )\
833 .filter(cls.permission == perm).scalar() is not None 841 .filter( cls.permission == perm ).scalar() is not None
834 842
835 @classmethod 843 @classmethod
836 def grant_perm(cls, user_id, perm): 844 def grant_perm( cls, user_id, perm ):
837 if not isinstance(perm, Permission): 845 if not isinstance( perm, Permission ):
838 raise Exception('perm needs to be an instance of Permission class') 846 raise Exception( 'perm needs to be an instance of Permission class' )
839 847
840 new = cls() 848 new = cls()
841 new.user_id = user_id 849 new.user_id = user_id
842 new.permission = perm 850 new.permission = perm
843 try: 851 try:
844 Session.add(new) 852 Session.add( new )
845 Session.commit() 853 Session.commit()
846 except: 854 except:
847 Session.rollback() 855 Session.rollback()
848 856
849 857
850 @classmethod 858 @classmethod
851 def revoke_perm(cls, user_id, perm): 859 def revoke_perm( cls, user_id, perm ):
852 if not isinstance(perm, Permission): 860 if not isinstance( perm, Permission ):
853 raise Exception('perm needs to be an instance of Permission class') 861 raise Exception( 'perm needs to be an instance of Permission class' )
854 862
855 try: 863 try:
856 cls.query().filter(cls.user_id == user_id)\ 864 cls.query().filter( cls.user_id == user_id )\
857 .filter(cls.permission == perm).delete() 865 .filter( cls.permission == perm ).delete()
858 Session.commit() 866 Session.commit()
859 except: 867 except:
860 Session.rollback() 868 Session.rollback()
861 869
862 class UsersGroupRepoToPerm(Base, BaseModel): 870 class UsersGroupRepoToPerm( Base, BaseModel ):
863 __tablename__ = 'users_group_repo_to_perm' 871 __tablename__ = 'users_group_repo_to_perm'
864 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True}) 872 __table_args__ = ( UniqueConstraint( 'repository_id', 'users_group_id', 'permission_id' ), {'extend_existing':True} )
865 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 873 users_group_to_perm_id = Column( "users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
866 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) 874 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None )
867 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) 875 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
868 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None) 876 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = None, default = None )
869 877
870 users_group = relationship('UsersGroup') 878 users_group = relationship( 'UsersGroup' )
871 permission = relationship('Permission') 879 permission = relationship( 'Permission' )
872 repository = relationship('Repository') 880 repository = relationship( 'Repository' )
873 881
874 def __repr__(self): 882 def __repr__( self ):
875 return '<userGroup:%s => %s >' % (self.users_group, self.repository) 883 return '<userGroup:%s => %s >' % ( self.users_group, self.repository )
876 884
877 class UsersGroupToPerm(Base, BaseModel): 885 class UsersGroupToPerm( Base, BaseModel ):
878 __tablename__ = 'users_group_to_perm' 886 __tablename__ = 'users_group_to_perm'
879 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 887 users_group_to_perm_id = Column( "users_group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
880 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None) 888 users_group_id = Column( "users_group_id", Integer(), ForeignKey( 'users_groups.users_group_id' ), nullable = False, unique = None, default = None )
881 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) 889 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
882 890
883 users_group = relationship('UsersGroup') 891 users_group = relationship( 'UsersGroup' )
884 permission = relationship('Permission') 892 permission = relationship( 'Permission' )
885 893
886 894
887 @classmethod 895 @classmethod
888 def has_perm(cls, users_group_id, perm): 896 def has_perm( cls, users_group_id, perm ):
889 if not isinstance(perm, Permission): 897 if not isinstance( perm, Permission ):
890 raise Exception('perm needs to be an instance of Permission class') 898 raise Exception( 'perm needs to be an instance of Permission class' )
891 899
892 return cls.query().filter(cls.users_group_id == 900 return cls.query().filter( cls.users_group_id ==
893 users_group_id)\ 901 users_group_id )\
894 .filter(cls.permission == perm)\ 902 .filter( cls.permission == perm )\
895 .scalar() is not None 903 .scalar() is not None
896 904
897 @classmethod 905 @classmethod
898 def grant_perm(cls, users_group_id, perm): 906 def grant_perm( cls, users_group_id, perm ):
899 if not isinstance(perm, Permission): 907 if not isinstance( perm, Permission ):
900 raise Exception('perm needs to be an instance of Permission class') 908 raise Exception( 'perm needs to be an instance of Permission class' )
901 909
902 new = cls() 910 new = cls()
903 new.users_group_id = users_group_id 911 new.users_group_id = users_group_id
904 new.permission = perm 912 new.permission = perm
905 try: 913 try:
906 Session.add(new) 914 Session.add( new )
907 Session.commit() 915 Session.commit()
908 except: 916 except:
909 Session.rollback() 917 Session.rollback()
910 918
911 919
912 @classmethod 920 @classmethod
913 def revoke_perm(cls, users_group_id, perm): 921 def revoke_perm( cls, users_group_id, perm ):
914 if not isinstance(perm, Permission): 922 if not isinstance( perm, Permission ):
915 raise Exception('perm needs to be an instance of Permission class') 923 raise Exception( 'perm needs to be an instance of Permission class' )
916 924
917 try: 925 try:
918 cls.query().filter(cls.users_group_id == users_group_id)\ 926 cls.query().filter( cls.users_group_id == users_group_id )\
919 .filter(cls.permission == perm).delete() 927 .filter( cls.permission == perm ).delete()
920 Session.commit() 928 Session.commit()
921 except: 929 except:
922 Session.rollback() 930 Session.rollback()
923 931
924 932
925 class GroupToPerm(Base, BaseModel): 933 class GroupToPerm( Base, BaseModel ):
926 __tablename__ = 'group_to_perm' 934 __tablename__ = 'group_to_perm'
927 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True}) 935 __table_args__ = ( UniqueConstraint( 'group_id', 'permission_id' ), {'extend_existing':True} )
928 936
929 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 937 group_to_perm_id = Column( "group_to_perm_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
930 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) 938 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
931 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None) 939 permission_id = Column( "permission_id", Integer(), ForeignKey( 'permissions.permission_id' ), nullable = False, unique = None, default = None )
932 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None) 940 group_id = Column( "group_id", Integer(), ForeignKey( 'groups.group_id' ), nullable = False, unique = None, default = None )
933 941
934 user = relationship('User') 942 user = relationship( 'User' )
935 permission = relationship('Permission') 943 permission = relationship( 'Permission' )
936 group = relationship('Group') 944 group = relationship( 'Group' )
937 945
938 class Statistics(Base, BaseModel): 946 class Statistics( Base, BaseModel ):
939 __tablename__ = 'statistics' 947 __tablename__ = 'statistics'
940 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True}) 948 __table_args__ = ( UniqueConstraint( 'repository_id' ), {'extend_existing':True} )
941 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 949 stat_id = Column( "stat_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
942 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None) 950 repository_id = Column( "repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = False, unique = True, default = None )
943 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False) 951 stat_on_revision = Column( "stat_on_revision", Integer(), nullable = False )
944 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data 952 commit_activity = Column( "commit_activity", LargeBinary( 1000000 ), nullable = False )#JSON data
945 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data 953 commit_activity_combined = Column( "commit_activity_combined", LargeBinary(), nullable = False )#JSON data
946 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data 954 languages = Column( "languages", LargeBinary( 1000000 ), nullable = False )#JSON data
947 955
948 repository = relationship('Repository', single_parent=True) 956 repository = relationship( 'Repository', single_parent = True )
949 957
950 class UserFollowing(Base, BaseModel): 958 class UserFollowing( Base, BaseModel ):
951 __tablename__ = 'user_followings' 959 __tablename__ = 'user_followings'
952 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'), 960 __table_args__ = ( UniqueConstraint( 'user_id', 'follows_repository_id' ),
953 UniqueConstraint('user_id', 'follows_user_id') 961 UniqueConstraint( 'user_id', 'follows_user_id' )
954 , {'extend_existing':True}) 962 , {'extend_existing':True} )
955 963
956 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 964 user_following_id = Column( "user_following_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
957 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None) 965 user_id = Column( "user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = False, unique = None, default = None )
958 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None) 966 follows_repo_id = Column( "follows_repository_id", Integer(), ForeignKey( 'repositories.repo_id' ), nullable = True, unique = None, default = None )
959 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None) 967 follows_user_id = Column( "follows_user_id", Integer(), ForeignKey( 'users.user_id' ), nullable = True, unique = None, default = None )
960 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now) 968 follows_from = Column( 'follows_from', DateTime( timezone = False ), nullable = True, unique = None, default = datetime.datetime.now )
961 969
962 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id') 970 user = relationship( 'User', primaryjoin = 'User.user_id==UserFollowing.user_id' )
963 971
964 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id') 972 follows_user = relationship( 'User', primaryjoin = 'User.user_id==UserFollowing.follows_user_id' )
965 follows_repository = relationship('Repository', order_by='Repository.repo_name') 973 follows_repository = relationship( 'Repository', order_by = 'Repository.repo_name' )
966 974
967 975
968 @classmethod 976 @classmethod
969 def get_repo_followers(cls, repo_id): 977 def get_repo_followers( cls, repo_id ):
970 return cls.query().filter(cls.follows_repo_id == repo_id) 978 return cls.query().filter( cls.follows_repo_id == repo_id )
971 979
972 class CacheInvalidation(Base, BaseModel): 980 class CacheInvalidation( Base, BaseModel ):
973 __tablename__ = 'cache_invalidation' 981 __tablename__ = 'cache_invalidation'
974 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True}) 982 __table_args__ = ( UniqueConstraint( 'cache_key' ), {'extend_existing':True} )
975 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True) 983 cache_id = Column( "cache_id", Integer(), nullable = False, unique = True, default = None, primary_key = True )
976 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 984 cache_key = Column( "cache_key", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
977 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None) 985 cache_args = Column( "cache_args", String( length = 255, convert_unicode = False, assert_unicode = None ), nullable = True, unique = None, default = None )
978 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False) 986 cache_active = Column( "cache_active", Boolean(), nullable = True, unique = None, default = False )
979 987
980 988
981 def __init__(self, cache_key, cache_args=''): 989 def __init__( self, cache_key, cache_args = '' ):
982 self.cache_key = cache_key 990 self.cache_key = cache_key
983 self.cache_args = cache_args 991 self.cache_args = cache_args
984 self.cache_active = False 992 self.cache_active = False
985 993
986 def __repr__(self): 994 def __repr__( self ):
987 return "<%s('%s:%s')>" % (self.__class__.__name__, 995 return "<%s('%s:%s')>" % ( self.__class__.__name__,
988 self.cache_id, self.cache_key) 996 self.cache_id, self.cache_key )
989 997
990 class DbMigrateVersion(Base, BaseModel): 998 class DbMigrateVersion( Base, BaseModel ):
991 __tablename__ = 'db_migrate_version' 999 __tablename__ = 'db_migrate_version'
992 __table_args__ = {'extend_existing':True} 1000 __table_args__ = {'extend_existing':True}
993 repository_id = Column('repository_id', String(250), primary_key=True) 1001 repository_id = Column( 'repository_id', String( 250 ), primary_key = True )
994 repository_path = Column('repository_path', Text) 1002 repository_path = Column( 'repository_path', Text )
995 version = Column('version', Integer) 1003 version = Column( 'version', Integer )