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