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