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