##// END OF EJS Templates
dbmigrate: fixed migration problems
super-admin -
r5166:f519a80b default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,1144 +1,1144 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27
27
28 from sqlalchemy import *
28 from sqlalchemy import *
29 from sqlalchemy.ext.hybrid import hybrid_property
29 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
30 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.exc import DatabaseError
31 from sqlalchemy.exc import DatabaseError
32 from beaker.cache import cache_region, region_invalidate
32 from beaker.cache import cache_region, region_invalidate
33 from webob.exc import HTTPNotFound
33 from webob.exc import HTTPNotFound
34
34
35 from rhodecode.translation import _
35 from rhodecode.translation import _
36
36
37 from rhodecode.lib.vcs import get_backend
37 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs.utils.helpers import get_scm
38 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.exceptions import VCSError
39 from rhodecode.lib.vcs.exceptions import VCSError
40 from zope.cachedescriptors.property import Lazy as LazyProperty
40 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from rhodecode.lib.vcs.backends.base import EmptyCommit
41 from rhodecode.lib.vcs.backends.base import EmptyCommit
42
42
43 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
43 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 remove_suffix, remove_prefix, time_to_datetime
44 remove_suffix, remove_prefix, time_to_datetime
45 from rhodecode.lib.ext_json import json
45 from rhodecode.lib.ext_json import json
46 from rhodecode.lib.caching_query import FromCache
46 from rhodecode.lib.caching_query import FromCache
47
47
48 from rhodecode.model.meta import Base, Session
48 from rhodecode.model.meta import Base, Session
49
49
50 URL_SEP = '/'
50 URL_SEP = '/'
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 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
57 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
58
58
59
59
60 class BaseModel(object):
60 class BaseModel(object):
61 """
61 """
62 Base Model for all classes
62 Base Model for all classes
63 """
63 """
64
64
65 @classmethod
65 @classmethod
66 def _get_keys(cls):
66 def _get_keys(cls):
67 """return column names for this model """
67 """return column names for this model """
68 return class_mapper(cls).c.keys()
68 return class_mapper(cls).c.keys()
69
69
70 def get_dict(self):
70 def get_dict(self):
71 """
71 """
72 return dict with keys and values corresponding
72 return dict with keys and values corresponding
73 to this model data """
73 to this model data """
74
74
75 d = {}
75 d = {}
76 for k in self._get_keys():
76 for k in self._get_keys():
77 d[k] = getattr(self, k)
77 d[k] = getattr(self, k)
78
78
79 # also use __json__() if present to get additional fields
79 # also use __json__() if present to get additional fields
80 _json_attr = getattr(self, '__json__', None)
80 _json_attr = getattr(self, '__json__', None)
81 if _json_attr:
81 if _json_attr:
82 # update with attributes from __json__
82 # update with attributes from __json__
83 if callable(_json_attr):
83 if callable(_json_attr):
84 _json_attr = _json_attr()
84 _json_attr = _json_attr()
85 for k, val in _json_attr.items():
85 for k, val in _json_attr.items():
86 d[k] = val
86 d[k] = val
87 return d
87 return d
88
88
89 def get_appstruct(self):
89 def get_appstruct(self):
90 """return list with keys and values tupples corresponding
90 """return list with keys and values tupples corresponding
91 to this model data """
91 to this model data """
92
92
93 l = []
93 l = []
94 for k in self._get_keys():
94 for k in self._get_keys():
95 l.append((k, getattr(self, k),))
95 l.append((k, getattr(self, k),))
96 return l
96 return l
97
97
98 def populate_obj(self, populate_dict):
98 def populate_obj(self, populate_dict):
99 """populate model with data from given populate_dict"""
99 """populate model with data from given populate_dict"""
100
100
101 for k in self._get_keys():
101 for k in self._get_keys():
102 if k in populate_dict:
102 if k in populate_dict:
103 setattr(self, k, populate_dict[k])
103 setattr(self, k, populate_dict[k])
104
104
105 @classmethod
105 @classmethod
106 def query(cls):
106 def query(cls):
107 return Session().query(cls)
107 return Session().query(cls)
108
108
109 @classmethod
109 @classmethod
110 def get(cls, id_):
110 def get(cls, id_):
111 if id_:
111 if id_:
112 return cls.query().get(id_)
112 return cls.query().get(id_)
113
113
114 @classmethod
114 @classmethod
115 def get_or_404(cls, id_):
115 def get_or_404(cls, id_):
116 try:
116 try:
117 id_ = int(id_)
117 id_ = int(id_)
118 except (TypeError, ValueError):
118 except (TypeError, ValueError):
119 raise HTTPNotFound
119 raise HTTPNotFound
120
120
121 res = cls.query().get(id_)
121 res = cls.query().get(id_)
122 if not res:
122 if not res:
123 raise HTTPNotFound
123 raise HTTPNotFound
124 return res
124 return res
125
125
126 @classmethod
126 @classmethod
127 def getAll(cls):
127 def getAll(cls):
128 # deprecated and left for backward compatibility
128 # deprecated and left for backward compatibility
129 return cls.get_all()
129 return cls.get_all()
130
130
131 @classmethod
131 @classmethod
132 def get_all(cls):
132 def get_all(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
139
140 def __repr__(self):
140 def __repr__(self):
141 if hasattr(self, '__unicode__'):
141 if hasattr(self, '__unicode__'):
142 # python repr needs to return str
142 # python repr needs to return str
143 return safe_str(self.__unicode__())
143 return safe_str(self.__unicode__())
144 return '<DB:%s>' % (self.__class__.__name__)
144 return '<DB:%s>' % (self.__class__.__name__)
145
145
146
146
147 class RhodeCodeSetting(Base, BaseModel):
147 class RhodeCodeSetting(Base, BaseModel):
148 __tablename__ = 'rhodecode_settings'
148 __tablename__ = 'rhodecode_settings'
149 __table_args__ = (
149 __table_args__ = (
150 UniqueConstraint('app_settings_name'),
150 UniqueConstraint('app_settings_name'),
151 {'extend_existing': True, 'mysql_engine': 'InnoDB',
151 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 'mysql_charset': 'utf8'}
152 'mysql_charset': 'utf8'}
153 )
153 )
154 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
154 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
155 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
156 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157
157
158 def __init__(self, k='', v=''):
158 def __init__(self, k='', v=''):
159 self.app_settings_name = k
159 self.app_settings_name = k
160 self.app_settings_value = v
160 self.app_settings_value = v
161
161
162 @validates('_app_settings_value')
162 @validates('_app_settings_value')
163 def validate_settings_value(self, key, val):
163 def validate_settings_value(self, key, val):
164 assert type(val) == str
164 assert type(val) == str
165 return val
165 return val
166
166
167 @hybrid_property
167 @hybrid_property
168 def app_settings_value(self):
168 def app_settings_value(self):
169 v = self._app_settings_value
169 v = self._app_settings_value
170 if self.app_settings_name in ["ldap_active",
170 if self.app_settings_name in ["ldap_active",
171 "default_repo_enable_statistics",
171 "default_repo_enable_statistics",
172 "default_repo_enable_locking",
172 "default_repo_enable_locking",
173 "default_repo_private",
173 "default_repo_private",
174 "default_repo_enable_downloads"]:
174 "default_repo_enable_downloads"]:
175 v = str2bool(v)
175 v = str2bool(v)
176 return v
176 return v
177
177
178 @app_settings_value.setter
178 @app_settings_value.setter
179 def app_settings_value(self, val):
179 def app_settings_value(self, val):
180 """
180 """
181 Setter that will always make sure we use unicode in app_settings_value
181 Setter that will always make sure we use unicode in app_settings_value
182
182
183 :param val:
183 :param val:
184 """
184 """
185 self._app_settings_value = safe_str(val)
185 self._app_settings_value = safe_str(val)
186
186
187 def __unicode__(self):
187 def __unicode__(self):
188 return u"<%s('%s:%s')>" % (
188 return u"<%s('%s:%s')>" % (
189 self.__class__.__name__,
189 self.__class__.__name__,
190 self.app_settings_name, self.app_settings_value
190 self.app_settings_name, self.app_settings_value
191 )
191 )
192
192
193
193
194 class RhodeCodeUi(Base, BaseModel):
194 class RhodeCodeUi(Base, BaseModel):
195 __tablename__ = 'rhodecode_ui'
195 __tablename__ = 'rhodecode_ui'
196 __table_args__ = (
196 __table_args__ = (
197 UniqueConstraint('ui_key'),
197 UniqueConstraint('ui_key'),
198 {'extend_existing': True, 'mysql_engine': 'InnoDB',
198 {'extend_existing': True, 'mysql_engine': 'InnoDB',
199 'mysql_charset': 'utf8'}
199 'mysql_charset': 'utf8'}
200 )
200 )
201
201
202 HOOK_REPO_SIZE = 'changegroup.repo_size'
202 HOOK_REPO_SIZE = 'changegroup.repo_size'
203 HOOK_PUSH = 'changegroup.push_logger'
203 HOOK_PUSH = 'changegroup.push_logger'
204 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
204 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
205 HOOK_PULL = 'outgoing.pull_logger'
205 HOOK_PULL = 'outgoing.pull_logger'
206 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
206 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
207
207
208 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
208 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
209 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
209 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
210 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
210 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
211 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
211 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
212 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
212 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
213
213
214
214
215
215
216 class User(Base, BaseModel):
216 class User(Base, BaseModel):
217 __tablename__ = 'users'
217 __tablename__ = 'users'
218 __table_args__ = (
218 __table_args__ = (
219 UniqueConstraint('username'), UniqueConstraint('email'),
219 UniqueConstraint('username'), UniqueConstraint('email'),
220 Index('u_username_idx', 'username'),
220 Index('u_username_idx', 'username'),
221 Index('u_email_idx', 'email'),
221 Index('u_email_idx', 'email'),
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 'mysql_charset': 'utf8'}
223 'mysql_charset': 'utf8'}
224 )
224 )
225 DEFAULT_USER = 'default'
225 DEFAULT_USER = 'default'
226
226
227 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
227 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
228 username = Column("username", String(255), nullable=True, unique=None, default=None)
228 username = Column("username", String(255), nullable=True, unique=None, default=None)
229 password = Column("password", String(255), nullable=True, unique=None, default=None)
229 password = Column("password", String(255), nullable=True, unique=None, default=None)
230 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
230 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
231 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
231 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
232 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
232 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
233 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
233 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
234 _email = Column("email", String(255), nullable=True, unique=None, default=None)
234 _email = Column("email", String(255), nullable=True, unique=None, default=None)
235 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
235 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
236 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
236 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
237 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
237 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
238 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
238 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
239
239
240 user_log = relationship('UserLog')
240 user_log = relationship('UserLog')
241 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
241 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
242
242
243 repositories = relationship('Repository')
243 repositories = relationship('Repository')
244 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
244 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
245 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
245 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
246
246
247 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
247 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
248 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
248 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
249
249
250 group_member = relationship('UserGroupMember', cascade='all')
250 group_member = relationship('UserGroupMember', cascade='all')
251
251
252 notifications = relationship('UserNotification', cascade='all')
252 notifications = relationship('UserNotification', cascade='all')
253 # notifications assigned to this user
253 # notifications assigned to this user
254 user_created_notifications = relationship('Notification', cascade='all')
254 user_created_notifications = relationship('Notification', cascade='all')
255 # comments created by this user
255 # comments created by this user
256 user_comments = relationship('ChangesetComment', cascade='all')
256 user_comments = relationship('ChangesetComment', cascade='all')
257 user_emails = relationship('UserEmailMap', cascade='all')
257 user_emails = relationship('UserEmailMap', cascade='all')
258
258
259 @hybrid_property
259 @hybrid_property
260 def email(self):
260 def email(self):
261 return self._email
261 return self._email
262
262
263 @email.setter
263 @email.setter
264 def email(self, val):
264 def email(self, val):
265 self._email = val.lower() if val else None
265 self._email = val.lower() if val else None
266
266
267 @property
267 @property
268 def firstname(self):
268 def firstname(self):
269 # alias for future
269 # alias for future
270 return self.name
270 return self.name
271
271
272 @property
272 @property
273 def username_and_name(self):
273 def username_and_name(self):
274 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
274 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
275
275
276 @property
276 @property
277 def full_name(self):
277 def full_name(self):
278 return '%s %s' % (self.firstname, self.lastname)
278 return '%s %s' % (self.firstname, self.lastname)
279
279
280 @property
280 @property
281 def full_contact(self):
281 def full_contact(self):
282 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
282 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
283
283
284 @property
284 @property
285 def short_contact(self):
285 def short_contact(self):
286 return '%s %s' % (self.firstname, self.lastname)
286 return '%s %s' % (self.firstname, self.lastname)
287
287
288 @property
288 @property
289 def is_admin(self):
289 def is_admin(self):
290 return self.admin
290 return self.admin
291
291
292 @classmethod
292 @classmethod
293 def get_by_username(cls, username, case_insensitive=False, cache=False):
293 def get_by_username(cls, username, case_insensitive=False, cache=False):
294 if case_insensitive:
294 if case_insensitive:
295 q = cls.query().filter(cls.username.ilike(username))
295 q = cls.query().filter(cls.username.ilike(username))
296 else:
296 else:
297 q = cls.query().filter(cls.username == username)
297 q = cls.query().filter(cls.username == username)
298
298
299 if cache:
299 if cache:
300 q = q.options(FromCache(
300 q = q.options(FromCache(
301 "sql_cache_short",
301 "sql_cache_short",
302 "get_user_%s" % _hash_key(username)
302 "get_user_%s" % _hash_key(username)
303 )
303 )
304 )
304 )
305 return q.scalar()
305 return q.scalar()
306
306
307 @classmethod
307 @classmethod
308 def get_by_auth_token(cls, auth_token, cache=False):
308 def get_by_auth_token(cls, auth_token, cache=False):
309 q = cls.query().filter(cls.api_key == auth_token)
309 q = cls.query().filter(cls.api_key == auth_token)
310
310
311 if cache:
311 if cache:
312 q = q.options(FromCache("sql_cache_short",
312 q = q.options(FromCache("sql_cache_short",
313 "get_auth_token_%s" % auth_token))
313 "get_auth_token_%s" % auth_token))
314 return q.scalar()
314 return q.scalar()
315
315
316 @classmethod
316 @classmethod
317 def get_by_email(cls, email, case_insensitive=False, cache=False):
317 def get_by_email(cls, email, case_insensitive=False, cache=False):
318 if case_insensitive:
318 if case_insensitive:
319 q = cls.query().filter(cls.email.ilike(email))
319 q = cls.query().filter(cls.email.ilike(email))
320 else:
320 else:
321 q = cls.query().filter(cls.email == email)
321 q = cls.query().filter(cls.email == email)
322
322
323 if cache:
323 if cache:
324 q = q.options(FromCache("sql_cache_short",
324 q = q.options(FromCache("sql_cache_short",
325 "get_email_key_%s" % email))
325 "get_email_key_%s" % email))
326
326
327 ret = q.scalar()
327 ret = q.scalar()
328 if ret is None:
328 if ret is None:
329 q = UserEmailMap.query()
329 q = UserEmailMap.query()
330 # try fetching in alternate email map
330 # try fetching in alternate email map
331 if case_insensitive:
331 if case_insensitive:
332 q = q.filter(UserEmailMap.email.ilike(email))
332 q = q.filter(UserEmailMap.email.ilike(email))
333 else:
333 else:
334 q = q.filter(UserEmailMap.email == email)
334 q = q.filter(UserEmailMap.email == email)
335 q = q.options(joinedload(UserEmailMap.user))
335 q = q.options(joinedload(UserEmailMap.user))
336 if cache:
336 if cache:
337 q = q.options(FromCache("sql_cache_short",
337 q = q.options(FromCache("sql_cache_short",
338 "get_email_map_key_%s" % email))
338 "get_email_map_key_%s" % email))
339 ret = getattr(q.scalar(), 'user', None)
339 ret = getattr(q.scalar(), 'user', None)
340
340
341 return ret
341 return ret
342
342
343 @classmethod
343 @classmethod
344 def get_first_admin(cls):
344 def get_first_admin(cls):
345 user = User.query().filter(User.admin == True).first()
345 user = User.query().filter(User.admin == True).first()
346 if user is None:
346 if user is None:
347 raise Exception('Missing administrative account!')
347 raise Exception('Missing administrative account!')
348 return user
348 return user
349
349
350 @classmethod
350 @classmethod
351 def get_default_user(cls, cache=False):
351 def get_default_user(cls, cache=False):
352 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
352 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
353 if user is None:
353 if user is None:
354 raise Exception('Missing default account!')
354 raise Exception('Missing default account!')
355 return user
355 return user
356
356
357
357
358
358
359
359
360 class UserEmailMap(Base, BaseModel):
360 class UserEmailMap(Base, BaseModel):
361 __tablename__ = 'user_email_map'
361 __tablename__ = 'user_email_map'
362 __table_args__ = (
362 __table_args__ = (
363 Index('uem_email_idx', 'email'),
363 Index('uem_email_idx', 'email'),
364 UniqueConstraint('email'),
364 UniqueConstraint('email'),
365 {'extend_existing': True, 'mysql_engine': 'InnoDB',
365 {'extend_existing': True, 'mysql_engine': 'InnoDB',
366 'mysql_charset': 'utf8'}
366 'mysql_charset': 'utf8'}
367 )
367 )
368
368
369
369
370 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
370 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
371 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
371 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
372 _email = Column("email", String(255), nullable=True, unique=False, default=None)
372 _email = Column("email", String(255), nullable=True, unique=False, default=None)
373 user = relationship('User', lazy='joined')
373 user = relationship('User', lazy='joined')
374
374
375 @validates('_email')
375 @validates('_email')
376 def validate_email(self, key, email):
376 def validate_email(self, key, email):
377 # check if this email is not main one
377 # check if this email is not main one
378 main_email = Session().query(User).filter(User.email == email).scalar()
378 main_email = Session().query(User).filter(User.email == email).scalar()
379 if main_email is not None:
379 if main_email is not None:
380 raise AttributeError('email %s is present is user table' % email)
380 raise AttributeError('email %s is present is user table' % email)
381 return email
381 return email
382
382
383 @hybrid_property
383 @hybrid_property
384 def email(self):
384 def email(self):
385 return self._email
385 return self._email
386
386
387 @email.setter
387 @email.setter
388 def email(self, val):
388 def email(self, val):
389 self._email = val.lower() if val else None
389 self._email = val.lower() if val else None
390
390
391
391
392 class UserIpMap(Base, BaseModel):
392 class UserIpMap(Base, BaseModel):
393 __tablename__ = 'user_ip_map'
393 __tablename__ = 'user_ip_map'
394 __table_args__ = (
394 __table_args__ = (
395 UniqueConstraint('user_id', 'ip_addr'),
395 UniqueConstraint('user_id', 'ip_addr'),
396 {'extend_existing': True, 'mysql_engine': 'InnoDB',
396 {'extend_existing': True, 'mysql_engine': 'InnoDB',
397 'mysql_charset': 'utf8'}
397 'mysql_charset': 'utf8'}
398 )
398 )
399
399
400
400
401 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
401 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
402 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
402 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
403 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
403 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
404 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
404 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
405 user = relationship('User', lazy='joined')
405 user = relationship('User', lazy='joined')
406
406
407
407
408 class UserLog(Base, BaseModel):
408 class UserLog(Base, BaseModel):
409 __tablename__ = 'user_logs'
409 __tablename__ = 'user_logs'
410 __table_args__ = (
410 __table_args__ = (
411 {'extend_existing': True, 'mysql_engine': 'InnoDB',
411 {'extend_existing': True, 'mysql_engine': 'InnoDB',
412 'mysql_charset': 'utf8'},
412 'mysql_charset': 'utf8'},
413 )
413 )
414 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
414 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
415 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
415 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
416 username = Column("username", String(255), nullable=True, unique=None, default=None)
416 username = Column("username", String(255), nullable=True, unique=None, default=None)
417 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
417 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
418 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
418 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
419 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
419 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
420 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
420 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
421 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
421 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
422
422
423 def __unicode__(self):
423 def __unicode__(self):
424 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
424 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
425 self.repository_name,
425 self.repository_name,
426 self.action)
426 self.action)
427
427
428 user = relationship('User')
428 user = relationship('User')
429 repository = relationship('Repository', cascade='')
429 repository = relationship('Repository', cascade='')
430
430
431
431
432 class UserGroup(Base, BaseModel):
432 class UserGroup(Base, BaseModel):
433 __tablename__ = 'users_groups'
433 __tablename__ = 'users_groups'
434 __table_args__ = (
434 __table_args__ = (
435 {'extend_existing': True, 'mysql_engine': 'InnoDB',
435 {'extend_existing': True, 'mysql_engine': 'InnoDB',
436 'mysql_charset': 'utf8'},
436 'mysql_charset': 'utf8'},
437 )
437 )
438
438
439 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
439 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
440 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
440 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
441 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
441 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
442 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
442 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
443 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
443 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
444
444
445 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
445 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
446 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
446 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
447 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
447 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
448 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
448 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
449 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
449 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
450 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
450 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
451
451
452 user = relationship('User')
452 user = relationship('User')
453
453
454 def __unicode__(self):
454 def __unicode__(self):
455 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
455 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
456 self.users_group_id,
456 self.users_group_id,
457 self.users_group_name)
457 self.users_group_name)
458
458
459 @classmethod
459 @classmethod
460 def get_by_group_name(cls, group_name, cache=False,
460 def get_by_group_name(cls, group_name, cache=False,
461 case_insensitive=False):
461 case_insensitive=False):
462 if case_insensitive:
462 if case_insensitive:
463 q = cls.query().filter(cls.users_group_name.ilike(group_name))
463 q = cls.query().filter(cls.users_group_name.ilike(group_name))
464 else:
464 else:
465 q = cls.query().filter(cls.users_group_name == group_name)
465 q = cls.query().filter(cls.users_group_name == group_name)
466 if cache:
466 if cache:
467 q = q.options(FromCache(
467 q = q.options(FromCache(
468 "sql_cache_short",
468 "sql_cache_short",
469 "get_user_%s" % _hash_key(group_name)
469 "get_user_%s" % _hash_key(group_name)
470 )
470 )
471 )
471 )
472 return q.scalar()
472 return q.scalar()
473
473
474 @classmethod
474 @classmethod
475 def get(cls, users_group_id, cache=False):
475 def get(cls, users_group_id, cache=False):
476 user_group = cls.query()
476 user_group = cls.query()
477 if cache:
477 if cache:
478 user_group = user_group.options(FromCache("sql_cache_short",
478 user_group = user_group.options(FromCache("sql_cache_short",
479 "get_users_group_%s" % users_group_id))
479 "get_users_group_%s" % users_group_id))
480 return user_group.get(users_group_id)
480 return user_group.get(users_group_id)
481
481
482
482
483 class UserGroupMember(Base, BaseModel):
483 class UserGroupMember(Base, BaseModel):
484 __tablename__ = 'users_groups_members'
484 __tablename__ = 'users_groups_members'
485 __table_args__ = (
485 __table_args__ = (
486 {'extend_existing': True, 'mysql_engine': 'InnoDB',
486 {'extend_existing': True, 'mysql_engine': 'InnoDB',
487 'mysql_charset': 'utf8'},
487 'mysql_charset': 'utf8'},
488 )
488 )
489
489
490 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
490 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
491 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
491 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
492 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
492 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
493
493
494 user = relationship('User', lazy='joined')
494 user = relationship('User', lazy='joined')
495 users_group = relationship('UserGroup')
495 users_group = relationship('UserGroup')
496
496
497 def __init__(self, gr_id='', u_id=''):
497 def __init__(self, gr_id='', u_id=''):
498 self.users_group_id = gr_id
498 self.users_group_id = gr_id
499 self.user_id = u_id
499 self.user_id = u_id
500
500
501
501
502 class RepositoryField(Base, BaseModel):
502 class RepositoryField(Base, BaseModel):
503 __tablename__ = 'repositories_fields'
503 __tablename__ = 'repositories_fields'
504 __table_args__ = (
504 __table_args__ = (
505 UniqueConstraint('repository_id', 'field_key'), # no-multi field
505 UniqueConstraint('repository_id', 'field_key'), # no-multi field
506 {'extend_existing': True, 'mysql_engine': 'InnoDB',
506 {'extend_existing': True, 'mysql_engine': 'InnoDB',
507 'mysql_charset': 'utf8'},
507 'mysql_charset': 'utf8'},
508 )
508 )
509 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
509 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
510
510
511 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
511 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
512 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
512 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
513 field_key = Column("field_key", String(250))
513 field_key = Column("field_key", String(250))
514 field_label = Column("field_label", String(1024), nullable=False)
514 field_label = Column("field_label", String(1024), nullable=False)
515 field_value = Column("field_value", String(10000), nullable=False)
515 field_value = Column("field_value", String(10000), nullable=False)
516 field_desc = Column("field_desc", String(1024), nullable=False)
516 field_desc = Column("field_desc", String(1024), nullable=False)
517 field_type = Column("field_type", String(256), nullable=False, unique=None)
517 field_type = Column("field_type", String(256), nullable=False, unique=None)
518 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
518 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
519
519
520 repository = relationship('Repository')
520 repository = relationship('Repository')
521
521
522 @classmethod
522 @classmethod
523 def get_by_key_name(cls, key, repo):
523 def get_by_key_name(cls, key, repo):
524 row = cls.query()\
524 row = cls.query()\
525 .filter(cls.repository == repo)\
525 .filter(cls.repository == repo)\
526 .filter(cls.field_key == key).scalar()
526 .filter(cls.field_key == key).scalar()
527 return row
527 return row
528
528
529
529
530 class Repository(Base, BaseModel):
530 class Repository(Base, BaseModel):
531 __tablename__ = 'repositories'
531 __tablename__ = 'repositories'
532 __table_args__ = (
532 __table_args__ = (
533 UniqueConstraint('repo_name'),
533 UniqueConstraint('repo_name'),
534 Index('r_repo_name_idx', 'repo_name'),
534 Index('r_repo_name_idx', 'repo_name'),
535 {'extend_existing': True, 'mysql_engine': 'InnoDB',
535 {'extend_existing': True, 'mysql_engine': 'InnoDB',
536 'mysql_charset': 'utf8'},
536 'mysql_charset': 'utf8'},
537 )
537 )
538
538
539 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
539 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
540 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
540 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
541 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
541 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
542 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
542 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
543 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
543 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
544 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
544 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
545 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
545 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
546 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
546 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
547 description = Column("description", String(10000), nullable=True, unique=None, default=None)
547 description = Column("description", String(10000), nullable=True, unique=None, default=None)
548 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
548 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
549 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
549 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
550 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
550 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
551 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
551 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
552 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
552 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
553 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
553 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
554
554
555 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
555 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
556 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
556 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
557
557
558 user = relationship('User')
558 user = relationship('User')
559 fork = relationship('Repository', remote_side=repo_id)
559 fork = relationship('Repository', remote_side=repo_id)
560 group = relationship('RepoGroup')
560 group = relationship('RepoGroup')
561 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
561 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
562 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
562 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
563 stats = relationship('Statistics', cascade='all', uselist=False)
563 stats = relationship('Statistics', cascade='all', uselist=False)
564
564
565 followers = relationship('UserFollowing',
565 followers = relationship('UserFollowing',
566 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
566 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
567 cascade='all')
567 cascade='all')
568 extra_fields = relationship('RepositoryField',
568 extra_fields = relationship('RepositoryField',
569 cascade="all, delete, delete-orphan")
569 cascade="all, delete, delete-orphan")
570
570
571 logs = relationship('UserLog')
571 logs = relationship('UserLog')
572 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
572 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
573
573
574 pull_requests_org = relationship('PullRequest',
574 pull_requests_org = relationship('PullRequest',
575 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
575 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
576 cascade="all, delete, delete-orphan")
576 cascade="all, delete, delete-orphan")
577
577
578 pull_requests_other = relationship('PullRequest',
578 pull_requests_other = relationship('PullRequest',
579 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
579 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
580 cascade="all, delete, delete-orphan")
580 cascade="all, delete, delete-orphan")
581
581
582 def __unicode__(self):
582 def __unicode__(self):
583 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
583 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
584 safe_str(self.repo_name))
584 safe_str(self.repo_name))
585
585
586 @classmethod
586 @classmethod
587 def get_by_repo_name(cls, repo_name):
587 def get_by_repo_name(cls, repo_name):
588 q = Session().query(cls).filter(cls.repo_name == repo_name)
588 q = Session().query(cls).filter(cls.repo_name == repo_name)
589 q = q.options(joinedload(Repository.fork))\
589 q = q.options(joinedload(Repository.fork))\
590 .options(joinedload(Repository.user))\
590 .options(joinedload(Repository.user))\
591 .options(joinedload(Repository.group))
591 .options(joinedload(Repository.group))
592 return q.scalar()
592 return q.scalar()
593
593
594
594
595 class RepoGroup(Base, BaseModel):
595 class RepoGroup(Base, BaseModel):
596 __tablename__ = 'groups'
596 __tablename__ = 'groups'
597 __table_args__ = (
597 __table_args__ = (
598 UniqueConstraint('group_name', 'group_parent_id'),
598 UniqueConstraint('group_name', 'group_parent_id'),
599 {'extend_existing': True, 'mysql_engine': 'InnoDB',
599 {'extend_existing': True, 'mysql_engine': 'InnoDB',
600 'mysql_charset': 'utf8'},
600 'mysql_charset': 'utf8'},
601 )
601 )
602
602
603
603
604 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
604 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
605 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
605 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
606 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
606 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
607 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
607 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
608 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
608 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
609 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
609 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
610
610
611 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
611 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
612 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
612 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
613 parent_group = relationship('RepoGroup', remote_side=group_id)
613 parent_group = relationship('RepoGroup', remote_side=group_id)
614 user = relationship('User')
614 user = relationship('User')
615
615
616 def __init__(self, group_name='', parent_group=None):
616 def __init__(self, group_name='', parent_group=None):
617 self.group_name = group_name
617 self.group_name = group_name
618 self.parent_group = parent_group
618 self.parent_group = parent_group
619
619
620 def __unicode__(self):
620 def __unicode__(self):
621 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
621 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
622 self.group_name)
622 self.group_name)
623
623
624 @classmethod
624 @classmethod
625 def url_sep(cls):
625 def url_sep(cls):
626 return URL_SEP
626 return URL_SEP
627
627
628 @classmethod
628 @classmethod
629 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
629 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
630 if case_insensitive:
630 if case_insensitive:
631 gr = cls.query()\
631 gr = cls.query()\
632 .filter(cls.group_name.ilike(group_name))
632 .filter(cls.group_name.ilike(group_name))
633 else:
633 else:
634 gr = cls.query()\
634 gr = cls.query()\
635 .filter(cls.group_name == group_name)
635 .filter(cls.group_name == group_name)
636 if cache:
636 if cache:
637 gr = gr.options(FromCache(
637 gr = gr.options(FromCache(
638 "sql_cache_short",
638 "sql_cache_short",
639 "get_group_%s" % _hash_key(group_name)
639 "get_group_%s" % _hash_key(group_name)
640 )
640 )
641 )
641 )
642 return gr.scalar()
642 return gr.scalar()
643
643
644
644
645 class Permission(Base, BaseModel):
645 class Permission(Base, BaseModel):
646 __tablename__ = 'permissions'
646 __tablename__ = 'permissions'
647 __table_args__ = (
647 __table_args__ = (
648 Index('p_perm_name_idx', 'permission_name'),
648 Index('p_perm_name_idx', 'permission_name'),
649 {'extend_existing': True, 'mysql_engine': 'InnoDB',
649 {'extend_existing': True, 'mysql_engine': 'InnoDB',
650 'mysql_charset': 'utf8'},
650 'mysql_charset': 'utf8'},
651 )
651 )
652 PERMS = [
652 PERMS = [
653 ('hg.admin', _('RhodeCode Administrator')),
653 ('hg.admin', _('RhodeCode Administrator')),
654
654
655 ('repository.none', _('Repository no access')),
655 ('repository.none', _('Repository no access')),
656 ('repository.read', _('Repository read access')),
656 ('repository.read', _('Repository read access')),
657 ('repository.write', _('Repository write access')),
657 ('repository.write', _('Repository write access')),
658 ('repository.admin', _('Repository admin access')),
658 ('repository.admin', _('Repository admin access')),
659
659
660 ('group.none', _('Repository group no access')),
660 ('group.none', _('Repository group no access')),
661 ('group.read', _('Repository group read access')),
661 ('group.read', _('Repository group read access')),
662 ('group.write', _('Repository group write access')),
662 ('group.write', _('Repository group write access')),
663 ('group.admin', _('Repository group admin access')),
663 ('group.admin', _('Repository group admin access')),
664
664
665 ('usergroup.none', _('User group no access')),
665 ('usergroup.none', _('User group no access')),
666 ('usergroup.read', _('User group read access')),
666 ('usergroup.read', _('User group read access')),
667 ('usergroup.write', _('User group write access')),
667 ('usergroup.write', _('User group write access')),
668 ('usergroup.admin', _('User group admin access')),
668 ('usergroup.admin', _('User group admin access')),
669
669
670 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
670 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
671 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
671 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
672
672
673 ('hg.usergroup.create.false', _('User Group creation disabled')),
673 ('hg.usergroup.create.false', _('User Group creation disabled')),
674 ('hg.usergroup.create.true', _('User Group creation enabled')),
674 ('hg.usergroup.create.true', _('User Group creation enabled')),
675
675
676 ('hg.create.none', _('Repository creation disabled')),
676 ('hg.create.none', _('Repository creation disabled')),
677 ('hg.create.repository', _('Repository creation enabled')),
677 ('hg.create.repository', _('Repository creation enabled')),
678
678
679 ('hg.fork.none', _('Repository forking disabled')),
679 ('hg.fork.none', _('Repository forking disabled')),
680 ('hg.fork.repository', _('Repository forking enabled')),
680 ('hg.fork.repository', _('Repository forking enabled')),
681
681
682 ('hg.register.none', _('Registration disabled')),
682 ('hg.register.none', _('Registration disabled')),
683 ('hg.register.manual_activate', _('User Registration with manual account activation')),
683 ('hg.register.manual_activate', _('User Registration with manual account activation')),
684 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
684 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
685
685
686 ('hg.extern_activate.manual', _('Manual activation of external account')),
686 ('hg.extern_activate.manual', _('Manual activation of external account')),
687 ('hg.extern_activate.auto', _('Automatic activation of external account')),
687 ('hg.extern_activate.auto', _('Automatic activation of external account')),
688
688
689 ]
689 ]
690
690
691 #definition of system default permissions for DEFAULT user
691 #definition of system default permissions for DEFAULT user
692 DEFAULT_USER_PERMISSIONS = [
692 DEFAULT_USER_PERMISSIONS = [
693 'repository.read',
693 'repository.read',
694 'group.read',
694 'group.read',
695 'usergroup.read',
695 'usergroup.read',
696 'hg.create.repository',
696 'hg.create.repository',
697 'hg.fork.repository',
697 'hg.fork.repository',
698 'hg.register.manual_activate',
698 'hg.register.manual_activate',
699 'hg.extern_activate.auto',
699 'hg.extern_activate.auto',
700 ]
700 ]
701
701
702 # defines which permissions are more important higher the more important
702 # defines which permissions are more important higher the more important
703 # Weight defines which permissions are more important.
703 # Weight defines which permissions are more important.
704 # The higher number the more important.
704 # The higher number the more important.
705 PERM_WEIGHTS = {
705 PERM_WEIGHTS = {
706 'repository.none': 0,
706 'repository.none': 0,
707 'repository.read': 1,
707 'repository.read': 1,
708 'repository.write': 3,
708 'repository.write': 3,
709 'repository.admin': 4,
709 'repository.admin': 4,
710
710
711 'group.none': 0,
711 'group.none': 0,
712 'group.read': 1,
712 'group.read': 1,
713 'group.write': 3,
713 'group.write': 3,
714 'group.admin': 4,
714 'group.admin': 4,
715
715
716 'usergroup.none': 0,
716 'usergroup.none': 0,
717 'usergroup.read': 1,
717 'usergroup.read': 1,
718 'usergroup.write': 3,
718 'usergroup.write': 3,
719 'usergroup.admin': 4,
719 'usergroup.admin': 4,
720 'hg.repogroup.create.false': 0,
720 'hg.repogroup.create.false': 0,
721 'hg.repogroup.create.true': 1,
721 'hg.repogroup.create.true': 1,
722
722
723 'hg.usergroup.create.false': 0,
723 'hg.usergroup.create.false': 0,
724 'hg.usergroup.create.true': 1,
724 'hg.usergroup.create.true': 1,
725
725
726 'hg.fork.none': 0,
726 'hg.fork.none': 0,
727 'hg.fork.repository': 1,
727 'hg.fork.repository': 1,
728 'hg.create.none': 0,
728 'hg.create.none': 0,
729 'hg.create.repository': 1
729 'hg.create.repository': 1
730 }
730 }
731
731
732 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
732 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
733 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
733 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
734 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
734 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
735
735
736 def __unicode__(self):
736 def __unicode__(self):
737 return u"<%s('%s:%s')>" % (
737 return u"<%s('%s:%s')>" % (
738 self.__class__.__name__, self.permission_id, self.permission_name
738 self.__class__.__name__, self.permission_id, self.permission_name
739 )
739 )
740
740
741 @classmethod
741 @classmethod
742 def get_by_key(cls, key):
742 def get_by_key(cls, key):
743 return cls.query().filter(cls.permission_name == key).scalar()
743 return cls.query().filter(cls.permission_name == key).scalar()
744
744
745
745
746 class UserRepoToPerm(Base, BaseModel):
746 class UserRepoToPerm(Base, BaseModel):
747 __tablename__ = 'repo_to_perm'
747 __tablename__ = 'repo_to_perm'
748 __table_args__ = (
748 __table_args__ = (
749 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
749 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
750 {'extend_existing': True, 'mysql_engine': 'InnoDB',
750 {'extend_existing': True, 'mysql_engine': 'InnoDB',
751 'mysql_charset': 'utf8'}
751 'mysql_charset': 'utf8'}
752 )
752 )
753 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
753 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
754 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
754 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
755 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
755 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
756 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
756 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
757
757
758 user = relationship('User')
758 user = relationship('User')
759 repository = relationship('Repository')
759 repository = relationship('Repository')
760 permission = relationship('Permission')
760 permission = relationship('Permission')
761
761
762 def __unicode__(self):
762 def __unicode__(self):
763 return u'<%s => %s >' % (self.user, self.repository)
763 return u'<%s => %s >' % (self.user, self.repository)
764
764
765
765
766 class UserUserGroupToPerm(Base, BaseModel):
766 class UserUserGroupToPerm(Base, BaseModel):
767 __tablename__ = 'user_user_group_to_perm'
767 __tablename__ = 'user_user_group_to_perm'
768 __table_args__ = (
768 __table_args__ = (
769 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
769 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
770 {'extend_existing': True, 'mysql_engine': 'InnoDB',
770 {'extend_existing': True, 'mysql_engine': 'InnoDB',
771 'mysql_charset': 'utf8'}
771 'mysql_charset': 'utf8'}
772 )
772 )
773 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
773 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
774 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
774 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
775 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
775 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
776 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
776 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
777
777
778 user = relationship('User')
778 user = relationship('User')
779 user_group = relationship('UserGroup')
779 user_group = relationship('UserGroup')
780 permission = relationship('Permission')
780 permission = relationship('Permission')
781
781
782 def __unicode__(self):
782 def __unicode__(self):
783 return u'<%s => %s >' % (self.user, self.user_group)
783 return u'<%s => %s >' % (self.user, self.user_group)
784
784
785
785
786 class UserToPerm(Base, BaseModel):
786 class UserToPerm(Base, BaseModel):
787 __tablename__ = 'user_to_perm'
787 __tablename__ = 'user_to_perm'
788 __table_args__ = (
788 __table_args__ = (
789 UniqueConstraint('user_id', 'permission_id'),
789 UniqueConstraint('user_id', 'permission_id'),
790 {'extend_existing': True, 'mysql_engine': 'InnoDB',
790 {'extend_existing': True, 'mysql_engine': 'InnoDB',
791 'mysql_charset': 'utf8'}
791 'mysql_charset': 'utf8'}
792 )
792 )
793 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
793 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
794 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
794 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
795 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
795 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
796
796
797 user = relationship('User')
797 user = relationship('User')
798 permission = relationship('Permission', lazy='joined')
798 permission = relationship('Permission', lazy='joined')
799
799
800 def __unicode__(self):
800 def __unicode__(self):
801 return u'<%s => %s >' % (self.user, self.permission)
801 return u'<%s => %s >' % (self.user, self.permission)
802
802
803
803
804 class UserGroupRepoToPerm(Base, BaseModel):
804 class UserGroupRepoToPerm(Base, BaseModel):
805 __tablename__ = 'users_group_repo_to_perm'
805 __tablename__ = 'users_group_repo_to_perm'
806 __table_args__ = (
806 __table_args__ = (
807 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
807 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
808 {'extend_existing': True, 'mysql_engine': 'InnoDB',
808 {'extend_existing': True, 'mysql_engine': 'InnoDB',
809 'mysql_charset': 'utf8'}
809 'mysql_charset': 'utf8'}
810 )
810 )
811 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
811 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
812 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
812 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
813 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
813 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
814 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
814 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
815
815
816 users_group = relationship('UserGroup')
816 users_group = relationship('UserGroup')
817 permission = relationship('Permission')
817 permission = relationship('Permission')
818 repository = relationship('Repository')
818 repository = relationship('Repository')
819
819
820 def __unicode__(self):
820 def __unicode__(self):
821 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
821 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
822
822
823
823
824 class UserGroupUserGroupToPerm(Base, BaseModel):
824 class UserGroupUserGroupToPerm(Base, BaseModel):
825 __tablename__ = 'user_group_user_group_to_perm'
825 __tablename__ = 'user_group_user_group_to_perm'
826 __table_args__ = (
826 __table_args__ = (
827 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
827 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
828 CheckConstraint('target_user_group_id != user_group_id'),
828 CheckConstraint('target_user_group_id != user_group_id'),
829 {'extend_existing': True, 'mysql_engine': 'InnoDB',
829 {'extend_existing': True, 'mysql_engine': 'InnoDB',
830 'mysql_charset': 'utf8'}
830 'mysql_charset': 'utf8'}
831 )
831 )
832 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
832 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
833 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
833 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
834 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
834 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
835 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
835 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
836
836
837 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
837 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
838 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
838 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
839 permission = relationship('Permission')
839 permission = relationship('Permission')
840
840
841 def __unicode__(self):
841 def __unicode__(self):
842 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
842 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
843
843
844
844
845 class UserGroupToPerm(Base, BaseModel):
845 class UserGroupToPerm(Base, BaseModel):
846 __tablename__ = 'users_group_to_perm'
846 __tablename__ = 'users_group_to_perm'
847 __table_args__ = (
847 __table_args__ = (
848 UniqueConstraint('users_group_id', 'permission_id',),
848 UniqueConstraint('users_group_id', 'permission_id',),
849 {'extend_existing': True, 'mysql_engine': 'InnoDB',
849 {'extend_existing': True, 'mysql_engine': 'InnoDB',
850 'mysql_charset': 'utf8'}
850 'mysql_charset': 'utf8'}
851 )
851 )
852 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
852 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
853 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
853 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
854 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
854 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
855
855
856 users_group = relationship('UserGroup')
856 users_group = relationship('UserGroup')
857 permission = relationship('Permission')
857 permission = relationship('Permission')
858
858
859
859
860 class UserRepoGroupToPerm(Base, BaseModel):
860 class UserRepoGroupToPerm(Base, BaseModel):
861 __tablename__ = 'user_repo_group_to_perm'
861 __tablename__ = 'user_repo_group_to_perm'
862 __table_args__ = (
862 __table_args__ = (
863 UniqueConstraint('user_id', 'group_id', 'permission_id'),
863 UniqueConstraint('user_id', 'group_id', 'permission_id'),
864 {'extend_existing': True, 'mysql_engine': 'InnoDB',
864 {'extend_existing': True, 'mysql_engine': 'InnoDB',
865 'mysql_charset': 'utf8'}
865 'mysql_charset': 'utf8'}
866 )
866 )
867
867
868 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
868 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
869 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
869 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
870 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
870 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
871 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
871 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
872
872
873 user = relationship('User')
873 user = relationship('User')
874 group = relationship('RepoGroup')
874 group = relationship('RepoGroup')
875 permission = relationship('Permission')
875 permission = relationship('Permission')
876
876
877
877
878 class UserGroupRepoGroupToPerm(Base, BaseModel):
878 class UserGroupRepoGroupToPerm(Base, BaseModel):
879 __tablename__ = 'users_group_repo_group_to_perm'
879 __tablename__ = 'users_group_repo_group_to_perm'
880 __table_args__ = (
880 __table_args__ = (
881 UniqueConstraint('users_group_id', 'group_id'),
881 UniqueConstraint('users_group_id', 'group_id'),
882 {'extend_existing': True, 'mysql_engine': 'InnoDB',
882 {'extend_existing': True, 'mysql_engine': 'InnoDB',
883 'mysql_charset': 'utf8'}
883 'mysql_charset': 'utf8'}
884 )
884 )
885
885
886 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)
886 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)
887 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
887 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
888 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
888 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
889 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
889 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
890
890
891 users_group = relationship('UserGroup')
891 users_group = relationship('UserGroup')
892 permission = relationship('Permission')
892 permission = relationship('Permission')
893 group = relationship('RepoGroup')
893 group = relationship('RepoGroup')
894
894
895
895
896 class Statistics(Base, BaseModel):
896 class Statistics(Base, BaseModel):
897 __tablename__ = 'statistics'
897 __tablename__ = 'statistics'
898 __table_args__ = (
898 __table_args__ = (
899 UniqueConstraint('repository_id'),
899 UniqueConstraint('repository_id'),
900 {'extend_existing': True, 'mysql_engine': 'InnoDB',
900 {'extend_existing': True, 'mysql_engine': 'InnoDB',
901 'mysql_charset': 'utf8'}
901 'mysql_charset': 'utf8'}
902 )
902 )
903 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
903 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
904 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
904 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
905 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
905 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
906 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
906 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
907 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
907 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
908 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
908 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
909
909
910 repository = relationship('Repository', single_parent=True)
910 repository = relationship('Repository', single_parent=True)
911
911
912
912
913 class UserFollowing(Base, BaseModel):
913 class UserFollowing(Base, BaseModel):
914 __tablename__ = 'user_followings'
914 __tablename__ = 'user_followings'
915 __table_args__ = (
915 __table_args__ = (
916 UniqueConstraint('user_id', 'follows_repository_id'),
916 UniqueConstraint('user_id', 'follows_repository_id'),
917 UniqueConstraint('user_id', 'follows_user_id'),
917 UniqueConstraint('user_id', 'follows_user_id'),
918 {'extend_existing': True, 'mysql_engine': 'InnoDB',
918 {'extend_existing': True, 'mysql_engine': 'InnoDB',
919 'mysql_charset': 'utf8'}
919 'mysql_charset': 'utf8'}
920 )
920 )
921
921
922 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
922 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
923 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
923 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
924 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
924 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
925 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
925 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
926 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
926 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
927
927
928 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
928 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
929
929
930 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
930 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
931 follows_repository = relationship('Repository', order_by='Repository.repo_name')
931 follows_repository = relationship('Repository', order_by='Repository.repo_name')
932
932
933
933
934 class CacheInvalidation(Base, BaseModel):
934 class CacheInvalidation(Base, BaseModel):
935 __tablename__ = 'cache_invalidation'
935 __tablename__ = 'cache_invalidation'
936 __table_args__ = (
936 __table_args__ = (
937 UniqueConstraint('cache_key'),
937 UniqueConstraint('cache_key'),
938 Index('key_idx', 'cache_key'),
938 Index('key_idx', 'cache_key'),
939 {'extend_existing': True, 'mysql_engine': 'InnoDB',
939 {'extend_existing': True, 'mysql_engine': 'InnoDB',
940 'mysql_charset': 'utf8'},
940 'mysql_charset': 'utf8'},
941 )
941 )
942 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
942 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
943 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
943 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
944 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
944 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
945 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
945 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
946
946
947 def __init__(self, cache_key, cache_args=''):
947 def __init__(self, cache_key, cache_args=''):
948 self.cache_key = cache_key
948 self.cache_key = cache_key
949 self.cache_args = cache_args
949 self.cache_args = cache_args
950 self.cache_active = False
950 self.cache_active = False
951
951
952
952
953 class ChangesetComment(Base, BaseModel):
953 class ChangesetComment(Base, BaseModel):
954 __tablename__ = 'changeset_comments'
954 __tablename__ = 'changeset_comments'
955 __table_args__ = (
955 __table_args__ = (
956 Index('cc_revision_idx', 'revision'),
956 Index('cc_revision_idx', 'revision'),
957 {'extend_existing': True, 'mysql_engine': 'InnoDB',
957 {'extend_existing': True, 'mysql_engine': 'InnoDB',
958 'mysql_charset': 'utf8'},
958 'mysql_charset': 'utf8'},
959 )
959 )
960 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
960 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
961 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
961 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
962 revision = Column('revision', String(40), nullable=True)
962 revision = Column('revision', String(40), nullable=True)
963 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
963 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
964 line_no = Column('line_no', Unicode(10), nullable=True)
964 line_no = Column('line_no', Unicode(10), nullable=True)
965 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
965 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
966 f_path = Column('f_path', Unicode(1000), nullable=True)
966 f_path = Column('f_path', Unicode(1000), nullable=True)
967 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
967 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
968 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
968 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
969 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
969 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
970 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
970 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
971
971
972 author = relationship('User', lazy='joined')
972 author = relationship('User', lazy='joined')
973 repo = relationship('Repository')
973 repo = relationship('Repository')
974 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
974 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
975 pull_request = relationship('PullRequest', lazy='joined')
975 pull_request = relationship('PullRequest', lazy='joined')
976
976
977
977
978 class ChangesetStatus(Base, BaseModel):
978 class ChangesetStatus(Base, BaseModel):
979 __tablename__ = 'changeset_statuses'
979 __tablename__ = 'changeset_statuses'
980 __table_args__ = (
980 __table_args__ = (
981 Index('cs_revision_idx', 'revision'),
981 Index('cs_revision_idx', 'revision'),
982 Index('cs_version_idx', 'version'),
982 Index('cs_version_idx', 'version'),
983 UniqueConstraint('repo_id', 'revision', 'version'),
983 UniqueConstraint('repo_id', 'revision', 'version'),
984 {'extend_existing': True, 'mysql_engine': 'InnoDB',
984 {'extend_existing': True, 'mysql_engine': 'InnoDB',
985 'mysql_charset': 'utf8'}
985 'mysql_charset': 'utf8'}
986 )
986 )
987 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
987 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
988 STATUS_APPROVED = 'approved'
988 STATUS_APPROVED = 'approved'
989 STATUS_REJECTED = 'rejected'
989 STATUS_REJECTED = 'rejected'
990 STATUS_UNDER_REVIEW = 'under_review'
990 STATUS_UNDER_REVIEW = 'under_review'
991
991
992 STATUSES = [
992 STATUSES = [
993 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
993 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
994 (STATUS_APPROVED, _("Approved")),
994 (STATUS_APPROVED, _("Approved")),
995 (STATUS_REJECTED, _("Rejected")),
995 (STATUS_REJECTED, _("Rejected")),
996 (STATUS_UNDER_REVIEW, _("Under Review")),
996 (STATUS_UNDER_REVIEW, _("Under Review")),
997 ]
997 ]
998
998
999 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
999 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1000 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1000 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1001 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1001 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1002 revision = Column('revision', String(40), nullable=False)
1002 revision = Column('revision', String(40), nullable=False)
1003 status = Column('status', String(128), nullable=False, default=DEFAULT)
1003 status = Column('status', String(128), nullable=False, default=DEFAULT)
1004 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1004 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1005 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1005 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1006 version = Column('version', Integer(), nullable=False, default=0)
1006 version = Column('version', Integer(), nullable=False, default=0)
1007 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1007 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1008
1008
1009 author = relationship('User', lazy='joined')
1009 author = relationship('User', lazy='joined')
1010 repo = relationship('Repository')
1010 repo = relationship('Repository')
1011 comment = relationship('ChangesetComment', lazy='joined')
1011 comment = relationship('ChangesetComment', lazy='joined')
1012 pull_request = relationship('PullRequest', lazy='joined')
1012 pull_request = relationship('PullRequest', lazy='joined')
1013
1013
1014
1014
1015
1015
1016 class PullRequest(Base, BaseModel):
1016 class PullRequest(Base, BaseModel):
1017 __tablename__ = 'pull_requests'
1017 __tablename__ = 'pull_requests'
1018 __table_args__ = (
1018 __table_args__ = (
1019 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1019 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1020 'mysql_charset': 'utf8'},
1020 'mysql_charset': 'utf8'},
1021 )
1021 )
1022
1022
1023 STATUS_NEW = u'new'
1023 STATUS_NEW = u'new'
1024 STATUS_OPEN = u'open'
1024 STATUS_OPEN = u'open'
1025 STATUS_CLOSED = u'closed'
1025 STATUS_CLOSED = u'closed'
1026
1026
1027 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1027 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1028 title = Column('title', Unicode(256), nullable=True)
1028 title = Column('title', Unicode(256), nullable=True)
1029 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1029 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1030 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1030 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1031 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1031 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1032 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1032 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1033 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1033 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1034 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1034 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1035 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1035 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1036 org_ref = Column('org_ref', Unicode(256), nullable=False)
1036 org_ref = Column('org_ref', Unicode(256), nullable=False)
1037 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1037 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1038 other_ref = Column('other_ref', Unicode(256), nullable=False)
1038 other_ref = Column('other_ref', Unicode(256), nullable=False)
1039
1039
1040 author = relationship('User', lazy='joined')
1040 author = relationship('User', lazy='joined')
1041 reviewers = relationship('PullRequestReviewers',
1041 reviewers = relationship('PullRequestReviewers',
1042 cascade="all, delete, delete-orphan")
1042 cascade="all, delete, delete-orphan")
1043 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1043 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1044 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1044 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1045 statuses = relationship('ChangesetStatus')
1045 statuses = relationship('ChangesetStatus')
1046 comments = relationship('ChangesetComment',
1046 comments = relationship('ChangesetComment',
1047 cascade="all, delete, delete-orphan")
1047 cascade="all, delete, delete-orphan")
1048
1048
1049
1049
1050 class PullRequestReviewers(Base, BaseModel):
1050 class PullRequestReviewers(Base, BaseModel):
1051 __tablename__ = 'pull_request_reviewers'
1051 __tablename__ = 'pull_request_reviewers'
1052 __table_args__ = (
1052 __table_args__ = (
1053 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1053 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1054 'mysql_charset': 'utf8'},
1054 'mysql_charset': 'utf8'},
1055 )
1055 )
1056
1056
1057 def __init__(self, user=None, pull_request=None):
1057 def __init__(self, user=None, pull_request=None):
1058 self.user = user
1058 self.user = user
1059 self.pull_request = pull_request
1059 self.pull_request = pull_request
1060
1060
1061 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1061 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1062 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1062 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1063 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1063 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1064
1064
1065 user = relationship('User')
1065 user = relationship('User')
1066 pull_request = relationship('PullRequest')
1066 pull_request = relationship('PullRequest')
1067
1067
1068
1068
1069 class Notification(Base, BaseModel):
1069 class Notification(Base, BaseModel):
1070 __tablename__ = 'notifications'
1070 __tablename__ = 'notifications'
1071 __table_args__ = (
1071 __table_args__ = (
1072 Index('notification_type_idx', 'type'),
1072 Index('notification_type_idx', 'type'),
1073 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1073 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1074 'mysql_charset': 'utf8'},
1074 'mysql_charset': 'utf8'},
1075 )
1075 )
1076
1076
1077 TYPE_CHANGESET_COMMENT = u'cs_comment'
1077 TYPE_CHANGESET_COMMENT = u'cs_comment'
1078 TYPE_MESSAGE = u'message'
1078 TYPE_MESSAGE = u'message'
1079 TYPE_MENTION = u'mention'
1079 TYPE_MENTION = u'mention'
1080 TYPE_REGISTRATION = u'registration'
1080 TYPE_REGISTRATION = u'registration'
1081 TYPE_PULL_REQUEST = u'pull_request'
1081 TYPE_PULL_REQUEST = u'pull_request'
1082 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1082 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1083
1083
1084 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1084 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1085 subject = Column('subject', Unicode(512), nullable=True)
1085 subject = Column('subject', Unicode(512), nullable=True)
1086 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1086 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1087 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1087 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1088 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1088 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1089 type_ = Column('type', Unicode(256))
1089 type_ = Column('type', Unicode(256))
1090
1090
1091 created_by_user = relationship('User')
1091 created_by_user = relationship('User')
1092 notifications_to_users = relationship('UserNotification', lazy='joined',
1092 notifications_to_users = relationship('UserNotification', lazy='joined',
1093 cascade="all, delete, delete-orphan")
1093 cascade="all, delete, delete-orphan")
1094
1094
1095
1095
1096 class UserNotification(Base, BaseModel):
1096 class UserNotification(Base, BaseModel):
1097 __tablename__ = 'user_to_notification'
1097 __tablename__ = 'user_to_notification'
1098 __table_args__ = (
1098 __table_args__ = (
1099 UniqueConstraint('user_id', 'notification_id'),
1099 UniqueConstraint('user_id', 'notification_id'),
1100 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1100 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1101 'mysql_charset': 'utf8'}
1101 'mysql_charset': 'utf8'}
1102 )
1102 )
1103 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1103 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1104 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1104 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1105 read = Column('read', Boolean, default=False)
1105 read = Column('read', Boolean, default=False)
1106 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1106 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1107
1107
1108 user = relationship('User', lazy="joined")
1108 user = relationship('User', lazy="joined")
1109 notification = relationship('Notification', lazy="joined",
1109 notification = relationship('Notification', lazy="joined",
1110 order_by=lambda: Notification.created_on.desc(),)
1110 order_by=lambda: Notification.created_on.desc(),)
1111
1111
1112
1112
1113 class Gist(Base, BaseModel):
1113 class Gist(Base, BaseModel):
1114 __tablename__ = 'gists'
1114 __tablename__ = 'gists'
1115 __table_args__ = (
1115 __table_args__ = (
1116 Index('g_gist_access_id_idx', 'gist_access_id'),
1116 Index('g_gist_access_id_idx', 'gist_access_id'),
1117 Index('g_created_on_idx', 'created_on'),
1117 Index('g_created_on_idx', 'created_on'),
1118 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1118 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1119 'mysql_charset': 'utf8'}
1119 'mysql_charset': 'utf8'}
1120 )
1120 )
1121 GIST_PUBLIC = u'public'
1121 GIST_PUBLIC = u'public'
1122 GIST_PRIVATE = u'private'
1122 GIST_PRIVATE = u'private'
1123
1123
1124 gist_id = Column('gist_id', Integer(), primary_key=True)
1124 gist_id = Column('gist_id', Integer(), primary_key=True)
1125 gist_access_id = Column('gist_access_id', Unicode(250))
1125 gist_access_id = Column('gist_access_id', Unicode(250))
1126 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1126 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1127 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1127 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1128 gist_expires = Column('gist_expires', Float(), nullable=False)
1128 gist_expires = Column('gist_expires', Float(), nullable=False)
1129 gist_type = Column('gist_type', Unicode(128), nullable=False)
1129 gist_type = Column('gist_type', Unicode(128), nullable=False)
1130 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1130 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1131 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1131 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1132
1132
1133 owner = relationship('User')
1133 owner = relationship('User')
1134
1134
1135
1135
1136 class DbMigrateVersion(Base, BaseModel):
1136 class DbMigrateVersion(Base, BaseModel):
1137 __tablename__ = 'db_migrate_version'
1137 __tablename__ = 'db_migrate_version'
1138 __table_args__ = (
1138 __table_args__ = (
1139 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1139 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1140 'mysql_charset': 'utf8'},
1140 'mysql_charset': 'utf8'},
1141 )
1141 )
1142 repository_id = Column('repository_id', String(250), primary_key=True)
1142 repository_id = Column('repository_id', String(250), primary_key=True)
1143 repository_path = Column('repository_path', Text)
1143 repository_path = Column('repository_path', Text)
1144 version = Column('version', Integer)
1144 version = Column('version', Integer)
@@ -1,1146 +1,1146 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27
27
28 from sqlalchemy import *
28 from sqlalchemy import *
29 from sqlalchemy.ext.hybrid import hybrid_property
29 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
30 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.exc import DatabaseError
31 from sqlalchemy.exc import DatabaseError
32 from beaker.cache import cache_region, region_invalidate
32 from beaker.cache import cache_region, region_invalidate
33 from webob.exc import HTTPNotFound
33 from webob.exc import HTTPNotFound
34
34
35 from rhodecode.translation import _
35 from rhodecode.translation import _
36
36
37 from rhodecode.lib.vcs import get_backend
37 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs.utils.helpers import get_scm
38 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.exceptions import VCSError
39 from rhodecode.lib.vcs.exceptions import VCSError
40 from zope.cachedescriptors.property import Lazy as LazyProperty
40 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from rhodecode.lib.vcs.backends.base import EmptyCommit
41 from rhodecode.lib.vcs.backends.base import EmptyCommit
42
42
43 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
43 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 remove_suffix, remove_prefix, time_to_datetime
44 remove_suffix, remove_prefix, time_to_datetime
45 from rhodecode.lib.ext_json import json
45 from rhodecode.lib.ext_json import json
46 from rhodecode.lib.caching_query import FromCache
46 from rhodecode.lib.caching_query import FromCache
47
47
48 from rhodecode.model.meta import Base, Session
48 from rhodecode.model.meta import Base, Session
49
49
50 URL_SEP = '/'
50 URL_SEP = '/'
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 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
57 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
58
58
59
59
60 class BaseModel(object):
60 class BaseModel(object):
61 """
61 """
62 Base Model for all classes
62 Base Model for all classes
63 """
63 """
64
64
65 @classmethod
65 @classmethod
66 def _get_keys(cls):
66 def _get_keys(cls):
67 """return column names for this model """
67 """return column names for this model """
68 return class_mapper(cls).c.keys()
68 return class_mapper(cls).c.keys()
69
69
70 def get_dict(self):
70 def get_dict(self):
71 """
71 """
72 return dict with keys and values corresponding
72 return dict with keys and values corresponding
73 to this model data """
73 to this model data """
74
74
75 d = {}
75 d = {}
76 for k in self._get_keys():
76 for k in self._get_keys():
77 d[k] = getattr(self, k)
77 d[k] = getattr(self, k)
78
78
79 # also use __json__() if present to get additional fields
79 # also use __json__() if present to get additional fields
80 _json_attr = getattr(self, '__json__', None)
80 _json_attr = getattr(self, '__json__', None)
81 if _json_attr:
81 if _json_attr:
82 # update with attributes from __json__
82 # update with attributes from __json__
83 if callable(_json_attr):
83 if callable(_json_attr):
84 _json_attr = _json_attr()
84 _json_attr = _json_attr()
85 for k, val in _json_attr.items():
85 for k, val in _json_attr.items():
86 d[k] = val
86 d[k] = val
87 return d
87 return d
88
88
89 def get_appstruct(self):
89 def get_appstruct(self):
90 """return list with keys and values tupples corresponding
90 """return list with keys and values tupples corresponding
91 to this model data """
91 to this model data """
92
92
93 l = []
93 l = []
94 for k in self._get_keys():
94 for k in self._get_keys():
95 l.append((k, getattr(self, k),))
95 l.append((k, getattr(self, k),))
96 return l
96 return l
97
97
98 def populate_obj(self, populate_dict):
98 def populate_obj(self, populate_dict):
99 """populate model with data from given populate_dict"""
99 """populate model with data from given populate_dict"""
100
100
101 for k in self._get_keys():
101 for k in self._get_keys():
102 if k in populate_dict:
102 if k in populate_dict:
103 setattr(self, k, populate_dict[k])
103 setattr(self, k, populate_dict[k])
104
104
105 @classmethod
105 @classmethod
106 def query(cls):
106 def query(cls):
107 return Session().query(cls)
107 return Session().query(cls)
108
108
109 @classmethod
109 @classmethod
110 def get(cls, id_):
110 def get(cls, id_):
111 if id_:
111 if id_:
112 return cls.query().get(id_)
112 return cls.query().get(id_)
113
113
114 @classmethod
114 @classmethod
115 def get_or_404(cls, id_):
115 def get_or_404(cls, id_):
116 try:
116 try:
117 id_ = int(id_)
117 id_ = int(id_)
118 except (TypeError, ValueError):
118 except (TypeError, ValueError):
119 raise HTTPNotFound
119 raise HTTPNotFound
120
120
121 res = cls.query().get(id_)
121 res = cls.query().get(id_)
122 if not res:
122 if not res:
123 raise HTTPNotFound
123 raise HTTPNotFound
124 return res
124 return res
125
125
126 @classmethod
126 @classmethod
127 def getAll(cls):
127 def getAll(cls):
128 # deprecated and left for backward compatibility
128 # deprecated and left for backward compatibility
129 return cls.get_all()
129 return cls.get_all()
130
130
131 @classmethod
131 @classmethod
132 def get_all(cls):
132 def get_all(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
139
140 def __repr__(self):
140 def __repr__(self):
141 if hasattr(self, '__unicode__'):
141 if hasattr(self, '__unicode__'):
142 # python repr needs to return str
142 # python repr needs to return str
143 return safe_str(self.__unicode__())
143 return safe_str(self.__unicode__())
144 return '<DB:%s>' % (self.__class__.__name__)
144 return '<DB:%s>' % (self.__class__.__name__)
145
145
146
146
147 class RhodeCodeSetting(Base, BaseModel):
147 class RhodeCodeSetting(Base, BaseModel):
148 __tablename__ = 'rhodecode_settings'
148 __tablename__ = 'rhodecode_settings'
149 __table_args__ = (
149 __table_args__ = (
150 UniqueConstraint('app_settings_name'),
150 UniqueConstraint('app_settings_name'),
151 {'extend_existing': True, 'mysql_engine': 'InnoDB',
151 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
152 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
153 )
153 )
154 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
154 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
155 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
156 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
157 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
158
158
159 def __init__(self, key='', val='', type='unicode'):
159 def __init__(self, key='', val='', type='unicode'):
160 self.app_settings_name = key
160 self.app_settings_name = key
161 self.app_settings_value = val
161 self.app_settings_value = val
162 self.app_settings_type = type
162 self.app_settings_type = type
163
163
164 @validates('_app_settings_value')
164 @validates('_app_settings_value')
165 def validate_settings_value(self, key, val):
165 def validate_settings_value(self, key, val):
166 assert type(val) == str
166 assert type(val) == str
167 return val
167 return val
168
168
169 @hybrid_property
169 @hybrid_property
170 def app_settings_value(self):
170 def app_settings_value(self):
171 v = self._app_settings_value
171 v = self._app_settings_value
172 if self.app_settings_name in ["ldap_active",
172 if self.app_settings_name in ["ldap_active",
173 "default_repo_enable_statistics",
173 "default_repo_enable_statistics",
174 "default_repo_enable_locking",
174 "default_repo_enable_locking",
175 "default_repo_private",
175 "default_repo_private",
176 "default_repo_enable_downloads"]:
176 "default_repo_enable_downloads"]:
177 v = str2bool(v)
177 v = str2bool(v)
178 return v
178 return v
179
179
180 @app_settings_value.setter
180 @app_settings_value.setter
181 def app_settings_value(self, val):
181 def app_settings_value(self, val):
182 """
182 """
183 Setter that will always make sure we use unicode in app_settings_value
183 Setter that will always make sure we use unicode in app_settings_value
184
184
185 :param val:
185 :param val:
186 """
186 """
187 self._app_settings_value = safe_str(val)
187 self._app_settings_value = safe_str(val)
188
188
189 def __unicode__(self):
189 def __unicode__(self):
190 return u"<%s('%s:%s')>" % (
190 return u"<%s('%s:%s')>" % (
191 self.__class__.__name__,
191 self.__class__.__name__,
192 self.app_settings_name, self.app_settings_value
192 self.app_settings_name, self.app_settings_value
193 )
193 )
194
194
195
195
196 class RhodeCodeUi(Base, BaseModel):
196 class RhodeCodeUi(Base, BaseModel):
197 __tablename__ = 'rhodecode_ui'
197 __tablename__ = 'rhodecode_ui'
198 __table_args__ = (
198 __table_args__ = (
199 UniqueConstraint('ui_key'),
199 UniqueConstraint('ui_key'),
200 {'extend_existing': True, 'mysql_engine': 'InnoDB',
200 {'extend_existing': True, 'mysql_engine': 'InnoDB',
201 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
201 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
202 )
202 )
203
203
204 HOOK_REPO_SIZE = 'changegroup.repo_size'
204 HOOK_REPO_SIZE = 'changegroup.repo_size'
205 HOOK_PUSH = 'changegroup.push_logger'
205 HOOK_PUSH = 'changegroup.push_logger'
206 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
206 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
207 HOOK_PULL = 'outgoing.pull_logger'
207 HOOK_PULL = 'outgoing.pull_logger'
208 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
208 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
209
209
210 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
210 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
211 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
211 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
212 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
212 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
213 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
213 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
214 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
214 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
215
215
216
216
217
217
218 class User(Base, BaseModel):
218 class User(Base, BaseModel):
219 __tablename__ = 'users'
219 __tablename__ = 'users'
220 __table_args__ = (
220 __table_args__ = (
221 UniqueConstraint('username'), UniqueConstraint('email'),
221 UniqueConstraint('username'), UniqueConstraint('email'),
222 Index('u_username_idx', 'username'),
222 Index('u_username_idx', 'username'),
223 Index('u_email_idx', 'email'),
223 Index('u_email_idx', 'email'),
224 {'extend_existing': True, 'mysql_engine': 'InnoDB',
224 {'extend_existing': True, 'mysql_engine': 'InnoDB',
225 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
225 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
226 )
226 )
227 DEFAULT_USER = 'default'
227 DEFAULT_USER = 'default'
228
228
229 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
229 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
230 username = Column("username", String(255), nullable=True, unique=None, default=None)
230 username = Column("username", String(255), nullable=True, unique=None, default=None)
231 password = Column("password", String(255), nullable=True, unique=None, default=None)
231 password = Column("password", String(255), nullable=True, unique=None, default=None)
232 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
232 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
233 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
233 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
234 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
234 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
235 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
235 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
236 _email = Column("email", String(255), nullable=True, unique=None, default=None)
236 _email = Column("email", String(255), nullable=True, unique=None, default=None)
237 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
237 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
238 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
238 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
239 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
239 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
240 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
240 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
241
241
242 user_log = relationship('UserLog')
242 user_log = relationship('UserLog')
243 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
243 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
244
244
245 repositories = relationship('Repository')
245 repositories = relationship('Repository')
246 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
246 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
247 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
247 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
248
248
249 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
249 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
250 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
250 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
251
251
252 group_member = relationship('UserGroupMember', cascade='all')
252 group_member = relationship('UserGroupMember', cascade='all')
253
253
254 notifications = relationship('UserNotification', cascade='all')
254 notifications = relationship('UserNotification', cascade='all')
255 # notifications assigned to this user
255 # notifications assigned to this user
256 user_created_notifications = relationship('Notification', cascade='all')
256 user_created_notifications = relationship('Notification', cascade='all')
257 # comments created by this user
257 # comments created by this user
258 user_comments = relationship('ChangesetComment', cascade='all')
258 user_comments = relationship('ChangesetComment', cascade='all')
259 user_emails = relationship('UserEmailMap', cascade='all')
259 user_emails = relationship('UserEmailMap', cascade='all')
260
260
261 @hybrid_property
261 @hybrid_property
262 def email(self):
262 def email(self):
263 return self._email
263 return self._email
264
264
265 @email.setter
265 @email.setter
266 def email(self, val):
266 def email(self, val):
267 self._email = val.lower() if val else None
267 self._email = val.lower() if val else None
268
268
269 @property
269 @property
270 def firstname(self):
270 def firstname(self):
271 # alias for future
271 # alias for future
272 return self.name
272 return self.name
273
273
274 @property
274 @property
275 def username_and_name(self):
275 def username_and_name(self):
276 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
276 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
277
277
278 @property
278 @property
279 def full_name(self):
279 def full_name(self):
280 return '%s %s' % (self.firstname, self.lastname)
280 return '%s %s' % (self.firstname, self.lastname)
281
281
282 @property
282 @property
283 def full_contact(self):
283 def full_contact(self):
284 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
284 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
285
285
286 @property
286 @property
287 def short_contact(self):
287 def short_contact(self):
288 return '%s %s' % (self.firstname, self.lastname)
288 return '%s %s' % (self.firstname, self.lastname)
289
289
290 @property
290 @property
291 def is_admin(self):
291 def is_admin(self):
292 return self.admin
292 return self.admin
293
293
294 @classmethod
294 @classmethod
295 def get_by_username(cls, username, case_insensitive=False, cache=False):
295 def get_by_username(cls, username, case_insensitive=False, cache=False):
296 if case_insensitive:
296 if case_insensitive:
297 q = cls.query().filter(cls.username.ilike(username))
297 q = cls.query().filter(cls.username.ilike(username))
298 else:
298 else:
299 q = cls.query().filter(cls.username == username)
299 q = cls.query().filter(cls.username == username)
300
300
301 if cache:
301 if cache:
302 q = q.options(FromCache(
302 q = q.options(FromCache(
303 "sql_cache_short",
303 "sql_cache_short",
304 "get_user_%s" % _hash_key(username)
304 "get_user_%s" % _hash_key(username)
305 )
305 )
306 )
306 )
307 return q.scalar()
307 return q.scalar()
308
308
309 @classmethod
309 @classmethod
310 def get_by_auth_token(cls, auth_token, cache=False):
310 def get_by_auth_token(cls, auth_token, cache=False):
311 q = cls.query().filter(cls.api_key == auth_token)
311 q = cls.query().filter(cls.api_key == auth_token)
312
312
313 if cache:
313 if cache:
314 q = q.options(FromCache("sql_cache_short",
314 q = q.options(FromCache("sql_cache_short",
315 "get_auth_token_%s" % auth_token))
315 "get_auth_token_%s" % auth_token))
316 return q.scalar()
316 return q.scalar()
317
317
318 @classmethod
318 @classmethod
319 def get_by_email(cls, email, case_insensitive=False, cache=False):
319 def get_by_email(cls, email, case_insensitive=False, cache=False):
320 if case_insensitive:
320 if case_insensitive:
321 q = cls.query().filter(cls.email.ilike(email))
321 q = cls.query().filter(cls.email.ilike(email))
322 else:
322 else:
323 q = cls.query().filter(cls.email == email)
323 q = cls.query().filter(cls.email == email)
324
324
325 if cache:
325 if cache:
326 q = q.options(FromCache("sql_cache_short",
326 q = q.options(FromCache("sql_cache_short",
327 "get_email_key_%s" % email))
327 "get_email_key_%s" % email))
328
328
329 ret = q.scalar()
329 ret = q.scalar()
330 if ret is None:
330 if ret is None:
331 q = UserEmailMap.query()
331 q = UserEmailMap.query()
332 # try fetching in alternate email map
332 # try fetching in alternate email map
333 if case_insensitive:
333 if case_insensitive:
334 q = q.filter(UserEmailMap.email.ilike(email))
334 q = q.filter(UserEmailMap.email.ilike(email))
335 else:
335 else:
336 q = q.filter(UserEmailMap.email == email)
336 q = q.filter(UserEmailMap.email == email)
337 q = q.options(joinedload(UserEmailMap.user))
337 q = q.options(joinedload(UserEmailMap.user))
338 if cache:
338 if cache:
339 q = q.options(FromCache("sql_cache_short",
339 q = q.options(FromCache("sql_cache_short",
340 "get_email_map_key_%s" % email))
340 "get_email_map_key_%s" % email))
341 ret = getattr(q.scalar(), 'user', None)
341 ret = getattr(q.scalar(), 'user', None)
342
342
343 return ret
343 return ret
344
344
345 @classmethod
345 @classmethod
346 def get_first_admin(cls):
346 def get_first_admin(cls):
347 user = User.query().filter(User.admin == True).first()
347 user = User.query().filter(User.admin == True).first()
348 if user is None:
348 if user is None:
349 raise Exception('Missing administrative account!')
349 raise Exception('Missing administrative account!')
350 return user
350 return user
351
351
352 @classmethod
352 @classmethod
353 def get_default_user(cls, cache=False):
353 def get_default_user(cls, cache=False):
354 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
354 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
355 if user is None:
355 if user is None:
356 raise Exception('Missing default account!')
356 raise Exception('Missing default account!')
357 return user
357 return user
358
358
359
359
360
360
361
361
362 class UserEmailMap(Base, BaseModel):
362 class UserEmailMap(Base, BaseModel):
363 __tablename__ = 'user_email_map'
363 __tablename__ = 'user_email_map'
364 __table_args__ = (
364 __table_args__ = (
365 Index('uem_email_idx', 'email'),
365 Index('uem_email_idx', 'email'),
366 UniqueConstraint('email'),
366 UniqueConstraint('email'),
367 {'extend_existing': True, 'mysql_engine': 'InnoDB',
367 {'extend_existing': True, 'mysql_engine': 'InnoDB',
368 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
368 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
369 )
369 )
370
370
371
371
372 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
372 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
373 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
373 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
374 _email = Column("email", String(255), nullable=True, unique=False, default=None)
374 _email = Column("email", String(255), nullable=True, unique=False, default=None)
375 user = relationship('User', lazy='joined')
375 user = relationship('User', lazy='joined')
376
376
377 @validates('_email')
377 @validates('_email')
378 def validate_email(self, key, email):
378 def validate_email(self, key, email):
379 # check if this email is not main one
379 # check if this email is not main one
380 main_email = Session().query(User).filter(User.email == email).scalar()
380 main_email = Session().query(User).filter(User.email == email).scalar()
381 if main_email is not None:
381 if main_email is not None:
382 raise AttributeError('email %s is present is user table' % email)
382 raise AttributeError('email %s is present is user table' % email)
383 return email
383 return email
384
384
385 @hybrid_property
385 @hybrid_property
386 def email(self):
386 def email(self):
387 return self._email
387 return self._email
388
388
389 @email.setter
389 @email.setter
390 def email(self, val):
390 def email(self, val):
391 self._email = val.lower() if val else None
391 self._email = val.lower() if val else None
392
392
393
393
394 class UserIpMap(Base, BaseModel):
394 class UserIpMap(Base, BaseModel):
395 __tablename__ = 'user_ip_map'
395 __tablename__ = 'user_ip_map'
396 __table_args__ = (
396 __table_args__ = (
397 UniqueConstraint('user_id', 'ip_addr'),
397 UniqueConstraint('user_id', 'ip_addr'),
398 {'extend_existing': True, 'mysql_engine': 'InnoDB',
398 {'extend_existing': True, 'mysql_engine': 'InnoDB',
399 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
399 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
400 )
400 )
401
401
402
402
403 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
403 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
404 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
404 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
405 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
405 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
406 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
406 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
407 user = relationship('User', lazy='joined')
407 user = relationship('User', lazy='joined')
408
408
409
409
410 class UserLog(Base, BaseModel):
410 class UserLog(Base, BaseModel):
411 __tablename__ = 'user_logs'
411 __tablename__ = 'user_logs'
412 __table_args__ = (
412 __table_args__ = (
413 {'extend_existing': True, 'mysql_engine': 'InnoDB',
413 {'extend_existing': True, 'mysql_engine': 'InnoDB',
414 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
414 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
415 )
415 )
416 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
416 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
417 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
417 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
418 username = Column("username", String(255), nullable=True, unique=None, default=None)
418 username = Column("username", String(255), nullable=True, unique=None, default=None)
419 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
419 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
420 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
420 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
421 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
421 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
422 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
422 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
423 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
423 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
424
424
425 def __unicode__(self):
425 def __unicode__(self):
426 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
426 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
427 self.repository_name,
427 self.repository_name,
428 self.action)
428 self.action)
429
429
430 user = relationship('User')
430 user = relationship('User')
431 repository = relationship('Repository', cascade='')
431 repository = relationship('Repository', cascade='')
432
432
433
433
434 class UserGroup(Base, BaseModel):
434 class UserGroup(Base, BaseModel):
435 __tablename__ = 'users_groups'
435 __tablename__ = 'users_groups'
436 __table_args__ = (
436 __table_args__ = (
437 {'extend_existing': True, 'mysql_engine': 'InnoDB',
437 {'extend_existing': True, 'mysql_engine': 'InnoDB',
438 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
438 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
439 )
439 )
440
440
441 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
441 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
442 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
442 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
443 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
443 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
444 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
444 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
445 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
445 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
446
446
447 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
447 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
448 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
448 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
449 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
449 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
450 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
450 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
451 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
451 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
452 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
452 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
453
453
454 user = relationship('User')
454 user = relationship('User')
455
455
456 def __unicode__(self):
456 def __unicode__(self):
457 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
457 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
458 self.users_group_id,
458 self.users_group_id,
459 self.users_group_name)
459 self.users_group_name)
460
460
461 @classmethod
461 @classmethod
462 def get_by_group_name(cls, group_name, cache=False,
462 def get_by_group_name(cls, group_name, cache=False,
463 case_insensitive=False):
463 case_insensitive=False):
464 if case_insensitive:
464 if case_insensitive:
465 q = cls.query().filter(cls.users_group_name.ilike(group_name))
465 q = cls.query().filter(cls.users_group_name.ilike(group_name))
466 else:
466 else:
467 q = cls.query().filter(cls.users_group_name == group_name)
467 q = cls.query().filter(cls.users_group_name == group_name)
468 if cache:
468 if cache:
469 q = q.options(FromCache(
469 q = q.options(FromCache(
470 "sql_cache_short",
470 "sql_cache_short",
471 "get_user_%s" % _hash_key(group_name)
471 "get_user_%s" % _hash_key(group_name)
472 )
472 )
473 )
473 )
474 return q.scalar()
474 return q.scalar()
475
475
476 @classmethod
476 @classmethod
477 def get(cls, user_group_id, cache=False):
477 def get(cls, user_group_id, cache=False):
478 user_group = cls.query()
478 user_group = cls.query()
479 if cache:
479 if cache:
480 user_group = user_group.options(FromCache("sql_cache_short",
480 user_group = user_group.options(FromCache("sql_cache_short",
481 "get_users_group_%s" % user_group_id))
481 "get_users_group_%s" % user_group_id))
482 return user_group.get(user_group_id)
482 return user_group.get(user_group_id)
483
483
484
484
485 class UserGroupMember(Base, BaseModel):
485 class UserGroupMember(Base, BaseModel):
486 __tablename__ = 'users_groups_members'
486 __tablename__ = 'users_groups_members'
487 __table_args__ = (
487 __table_args__ = (
488 {'extend_existing': True, 'mysql_engine': 'InnoDB',
488 {'extend_existing': True, 'mysql_engine': 'InnoDB',
489 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
489 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
490 )
490 )
491
491
492 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
492 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
493 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
493 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
494 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
494 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
495
495
496 user = relationship('User', lazy='joined')
496 user = relationship('User', lazy='joined')
497 users_group = relationship('UserGroup')
497 users_group = relationship('UserGroup')
498
498
499 def __init__(self, gr_id='', u_id=''):
499 def __init__(self, gr_id='', u_id=''):
500 self.users_group_id = gr_id
500 self.users_group_id = gr_id
501 self.user_id = u_id
501 self.user_id = u_id
502
502
503
503
504 class RepositoryField(Base, BaseModel):
504 class RepositoryField(Base, BaseModel):
505 __tablename__ = 'repositories_fields'
505 __tablename__ = 'repositories_fields'
506 __table_args__ = (
506 __table_args__ = (
507 UniqueConstraint('repository_id', 'field_key'), # no-multi field
507 UniqueConstraint('repository_id', 'field_key'), # no-multi field
508 {'extend_existing': True, 'mysql_engine': 'InnoDB',
508 {'extend_existing': True, 'mysql_engine': 'InnoDB',
509 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
509 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
510 )
510 )
511 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
511 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
512
512
513 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
513 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
514 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
514 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
515 field_key = Column("field_key", String(250))
515 field_key = Column("field_key", String(250))
516 field_label = Column("field_label", String(1024), nullable=False)
516 field_label = Column("field_label", String(1024), nullable=False)
517 field_value = Column("field_value", String(10000), nullable=False)
517 field_value = Column("field_value", String(10000), nullable=False)
518 field_desc = Column("field_desc", String(1024), nullable=False)
518 field_desc = Column("field_desc", String(1024), nullable=False)
519 field_type = Column("field_type", String(256), nullable=False, unique=None)
519 field_type = Column("field_type", String(256), nullable=False, unique=None)
520 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
520 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
521
521
522 repository = relationship('Repository')
522 repository = relationship('Repository')
523
523
524 @classmethod
524 @classmethod
525 def get_by_key_name(cls, key, repo):
525 def get_by_key_name(cls, key, repo):
526 row = cls.query()\
526 row = cls.query()\
527 .filter(cls.repository == repo)\
527 .filter(cls.repository == repo)\
528 .filter(cls.field_key == key).scalar()
528 .filter(cls.field_key == key).scalar()
529 return row
529 return row
530
530
531
531
532 class Repository(Base, BaseModel):
532 class Repository(Base, BaseModel):
533 __tablename__ = 'repositories'
533 __tablename__ = 'repositories'
534 __table_args__ = (
534 __table_args__ = (
535 UniqueConstraint('repo_name'),
535 UniqueConstraint('repo_name'),
536 Index('r_repo_name_idx', 'repo_name'),
536 Index('r_repo_name_idx', 'repo_name'),
537 {'extend_existing': True, 'mysql_engine': 'InnoDB',
537 {'extend_existing': True, 'mysql_engine': 'InnoDB',
538 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
538 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
539 )
539 )
540
540
541 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
541 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
542 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
542 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
543 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
543 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
544 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
544 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
545 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
545 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
546 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
546 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
547 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
547 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
548 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
548 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
549 description = Column("description", String(10000), nullable=True, unique=None, default=None)
549 description = Column("description", String(10000), nullable=True, unique=None, default=None)
550 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
550 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
551 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
551 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
552 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
552 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
553 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
553 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
554 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
554 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
555 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
555 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
556
556
557 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
557 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
558 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
558 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
559
559
560 user = relationship('User')
560 user = relationship('User')
561 fork = relationship('Repository', remote_side=repo_id)
561 fork = relationship('Repository', remote_side=repo_id)
562 group = relationship('RepoGroup')
562 group = relationship('RepoGroup')
563 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
563 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
564 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
564 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
565 stats = relationship('Statistics', cascade='all', uselist=False)
565 stats = relationship('Statistics', cascade='all', uselist=False)
566
566
567 followers = relationship('UserFollowing',
567 followers = relationship('UserFollowing',
568 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
568 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
569 cascade='all')
569 cascade='all')
570 extra_fields = relationship('RepositoryField',
570 extra_fields = relationship('RepositoryField',
571 cascade="all, delete, delete-orphan")
571 cascade="all, delete, delete-orphan")
572
572
573 logs = relationship('UserLog')
573 logs = relationship('UserLog')
574 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
574 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
575
575
576 pull_requests_org = relationship('PullRequest',
576 pull_requests_org = relationship('PullRequest',
577 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
577 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
578 cascade="all, delete, delete-orphan")
578 cascade="all, delete, delete-orphan")
579
579
580 pull_requests_other = relationship('PullRequest',
580 pull_requests_other = relationship('PullRequest',
581 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
581 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
582 cascade="all, delete, delete-orphan")
582 cascade="all, delete, delete-orphan")
583
583
584 def __unicode__(self):
584 def __unicode__(self):
585 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
585 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
586 safe_str(self.repo_name))
586 safe_str(self.repo_name))
587
587
588 @classmethod
588 @classmethod
589 def get_by_repo_name(cls, repo_name):
589 def get_by_repo_name(cls, repo_name):
590 q = Session().query(cls).filter(cls.repo_name == repo_name)
590 q = Session().query(cls).filter(cls.repo_name == repo_name)
591 q = q.options(joinedload(Repository.fork))\
591 q = q.options(joinedload(Repository.fork))\
592 .options(joinedload(Repository.user))\
592 .options(joinedload(Repository.user))\
593 .options(joinedload(Repository.group))
593 .options(joinedload(Repository.group))
594 return q.scalar()
594 return q.scalar()
595
595
596
596
597 class RepoGroup(Base, BaseModel):
597 class RepoGroup(Base, BaseModel):
598 __tablename__ = 'groups'
598 __tablename__ = 'groups'
599 __table_args__ = (
599 __table_args__ = (
600 UniqueConstraint('group_name', 'group_parent_id'),
600 UniqueConstraint('group_name', 'group_parent_id'),
601 {'extend_existing': True, 'mysql_engine': 'InnoDB',
601 {'extend_existing': True, 'mysql_engine': 'InnoDB',
602 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
602 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
603 )
603 )
604
604
605
605
606 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
606 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
607 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
607 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
608 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
608 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
609 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
609 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
610 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
610 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
611 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
611 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
612
612
613 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
613 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
614 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
614 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
615 parent_group = relationship('RepoGroup', remote_side=group_id)
615 parent_group = relationship('RepoGroup', remote_side=group_id)
616 user = relationship('User')
616 user = relationship('User')
617
617
618 def __init__(self, group_name='', parent_group=None):
618 def __init__(self, group_name='', parent_group=None):
619 self.group_name = group_name
619 self.group_name = group_name
620 self.parent_group = parent_group
620 self.parent_group = parent_group
621
621
622 def __unicode__(self):
622 def __unicode__(self):
623 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
623 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
624 self.group_name)
624 self.group_name)
625
625
626 @classmethod
626 @classmethod
627 def url_sep(cls):
627 def url_sep(cls):
628 return URL_SEP
628 return URL_SEP
629
629
630 @classmethod
630 @classmethod
631 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
631 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
632 if case_insensitive:
632 if case_insensitive:
633 gr = cls.query()\
633 gr = cls.query()\
634 .filter(cls.group_name.ilike(group_name))
634 .filter(cls.group_name.ilike(group_name))
635 else:
635 else:
636 gr = cls.query()\
636 gr = cls.query()\
637 .filter(cls.group_name == group_name)
637 .filter(cls.group_name == group_name)
638 if cache:
638 if cache:
639 gr = gr.options(FromCache(
639 gr = gr.options(FromCache(
640 "sql_cache_short",
640 "sql_cache_short",
641 "get_group_%s" % _hash_key(group_name)
641 "get_group_%s" % _hash_key(group_name)
642 )
642 )
643 )
643 )
644 return gr.scalar()
644 return gr.scalar()
645
645
646
646
647 class Permission(Base, BaseModel):
647 class Permission(Base, BaseModel):
648 __tablename__ = 'permissions'
648 __tablename__ = 'permissions'
649 __table_args__ = (
649 __table_args__ = (
650 Index('p_perm_name_idx', 'permission_name'),
650 Index('p_perm_name_idx', 'permission_name'),
651 {'extend_existing': True, 'mysql_engine': 'InnoDB',
651 {'extend_existing': True, 'mysql_engine': 'InnoDB',
652 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
652 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
653 )
653 )
654 PERMS = [
654 PERMS = [
655 ('hg.admin', _('RhodeCode Administrator')),
655 ('hg.admin', _('RhodeCode Administrator')),
656
656
657 ('repository.none', _('Repository no access')),
657 ('repository.none', _('Repository no access')),
658 ('repository.read', _('Repository read access')),
658 ('repository.read', _('Repository read access')),
659 ('repository.write', _('Repository write access')),
659 ('repository.write', _('Repository write access')),
660 ('repository.admin', _('Repository admin access')),
660 ('repository.admin', _('Repository admin access')),
661
661
662 ('group.none', _('Repository group no access')),
662 ('group.none', _('Repository group no access')),
663 ('group.read', _('Repository group read access')),
663 ('group.read', _('Repository group read access')),
664 ('group.write', _('Repository group write access')),
664 ('group.write', _('Repository group write access')),
665 ('group.admin', _('Repository group admin access')),
665 ('group.admin', _('Repository group admin access')),
666
666
667 ('usergroup.none', _('User group no access')),
667 ('usergroup.none', _('User group no access')),
668 ('usergroup.read', _('User group read access')),
668 ('usergroup.read', _('User group read access')),
669 ('usergroup.write', _('User group write access')),
669 ('usergroup.write', _('User group write access')),
670 ('usergroup.admin', _('User group admin access')),
670 ('usergroup.admin', _('User group admin access')),
671
671
672 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
672 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
673 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
673 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
674
674
675 ('hg.usergroup.create.false', _('User Group creation disabled')),
675 ('hg.usergroup.create.false', _('User Group creation disabled')),
676 ('hg.usergroup.create.true', _('User Group creation enabled')),
676 ('hg.usergroup.create.true', _('User Group creation enabled')),
677
677
678 ('hg.create.none', _('Repository creation disabled')),
678 ('hg.create.none', _('Repository creation disabled')),
679 ('hg.create.repository', _('Repository creation enabled')),
679 ('hg.create.repository', _('Repository creation enabled')),
680
680
681 ('hg.fork.none', _('Repository forking disabled')),
681 ('hg.fork.none', _('Repository forking disabled')),
682 ('hg.fork.repository', _('Repository forking enabled')),
682 ('hg.fork.repository', _('Repository forking enabled')),
683
683
684 ('hg.register.none', _('Registration disabled')),
684 ('hg.register.none', _('Registration disabled')),
685 ('hg.register.manual_activate', _('User Registration with manual account activation')),
685 ('hg.register.manual_activate', _('User Registration with manual account activation')),
686 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
686 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
687
687
688 ('hg.extern_activate.manual', _('Manual activation of external account')),
688 ('hg.extern_activate.manual', _('Manual activation of external account')),
689 ('hg.extern_activate.auto', _('Automatic activation of external account')),
689 ('hg.extern_activate.auto', _('Automatic activation of external account')),
690
690
691 ]
691 ]
692
692
693 #definition of system default permissions for DEFAULT user
693 #definition of system default permissions for DEFAULT user
694 DEFAULT_USER_PERMISSIONS = [
694 DEFAULT_USER_PERMISSIONS = [
695 'repository.read',
695 'repository.read',
696 'group.read',
696 'group.read',
697 'usergroup.read',
697 'usergroup.read',
698 'hg.create.repository',
698 'hg.create.repository',
699 'hg.fork.repository',
699 'hg.fork.repository',
700 'hg.register.manual_activate',
700 'hg.register.manual_activate',
701 'hg.extern_activate.auto',
701 'hg.extern_activate.auto',
702 ]
702 ]
703
703
704 # defines which permissions are more important higher the more important
704 # defines which permissions are more important higher the more important
705 # Weight defines which permissions are more important.
705 # Weight defines which permissions are more important.
706 # The higher number the more important.
706 # The higher number the more important.
707 PERM_WEIGHTS = {
707 PERM_WEIGHTS = {
708 'repository.none': 0,
708 'repository.none': 0,
709 'repository.read': 1,
709 'repository.read': 1,
710 'repository.write': 3,
710 'repository.write': 3,
711 'repository.admin': 4,
711 'repository.admin': 4,
712
712
713 'group.none': 0,
713 'group.none': 0,
714 'group.read': 1,
714 'group.read': 1,
715 'group.write': 3,
715 'group.write': 3,
716 'group.admin': 4,
716 'group.admin': 4,
717
717
718 'usergroup.none': 0,
718 'usergroup.none': 0,
719 'usergroup.read': 1,
719 'usergroup.read': 1,
720 'usergroup.write': 3,
720 'usergroup.write': 3,
721 'usergroup.admin': 4,
721 'usergroup.admin': 4,
722 'hg.repogroup.create.false': 0,
722 'hg.repogroup.create.false': 0,
723 'hg.repogroup.create.true': 1,
723 'hg.repogroup.create.true': 1,
724
724
725 'hg.usergroup.create.false': 0,
725 'hg.usergroup.create.false': 0,
726 'hg.usergroup.create.true': 1,
726 'hg.usergroup.create.true': 1,
727
727
728 'hg.fork.none': 0,
728 'hg.fork.none': 0,
729 'hg.fork.repository': 1,
729 'hg.fork.repository': 1,
730 'hg.create.none': 0,
730 'hg.create.none': 0,
731 'hg.create.repository': 1
731 'hg.create.repository': 1
732 }
732 }
733
733
734 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
734 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
735 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
735 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
736 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
736 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
737
737
738 def __unicode__(self):
738 def __unicode__(self):
739 return u"<%s('%s:%s')>" % (
739 return u"<%s('%s:%s')>" % (
740 self.__class__.__name__, self.permission_id, self.permission_name
740 self.__class__.__name__, self.permission_id, self.permission_name
741 )
741 )
742
742
743 @classmethod
743 @classmethod
744 def get_by_key(cls, key):
744 def get_by_key(cls, key):
745 return cls.query().filter(cls.permission_name == key).scalar()
745 return cls.query().filter(cls.permission_name == key).scalar()
746
746
747
747
748 class UserRepoToPerm(Base, BaseModel):
748 class UserRepoToPerm(Base, BaseModel):
749 __tablename__ = 'repo_to_perm'
749 __tablename__ = 'repo_to_perm'
750 __table_args__ = (
750 __table_args__ = (
751 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
751 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
752 {'extend_existing': True, 'mysql_engine': 'InnoDB',
752 {'extend_existing': True, 'mysql_engine': 'InnoDB',
753 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
753 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
754 )
754 )
755 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
755 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
756 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
756 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
757 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
757 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
758 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
758 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
759
759
760 user = relationship('User')
760 user = relationship('User')
761 repository = relationship('Repository')
761 repository = relationship('Repository')
762 permission = relationship('Permission')
762 permission = relationship('Permission')
763
763
764 def __unicode__(self):
764 def __unicode__(self):
765 return u'<%s => %s >' % (self.user, self.repository)
765 return u'<%s => %s >' % (self.user, self.repository)
766
766
767
767
768 class UserUserGroupToPerm(Base, BaseModel):
768 class UserUserGroupToPerm(Base, BaseModel):
769 __tablename__ = 'user_user_group_to_perm'
769 __tablename__ = 'user_user_group_to_perm'
770 __table_args__ = (
770 __table_args__ = (
771 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
771 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
772 {'extend_existing': True, 'mysql_engine': 'InnoDB',
772 {'extend_existing': True, 'mysql_engine': 'InnoDB',
773 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
773 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
774 )
774 )
775 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
775 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
776 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
776 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
777 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
777 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
778 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
778 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
779
779
780 user = relationship('User')
780 user = relationship('User')
781 user_group = relationship('UserGroup')
781 user_group = relationship('UserGroup')
782 permission = relationship('Permission')
782 permission = relationship('Permission')
783
783
784 def __unicode__(self):
784 def __unicode__(self):
785 return u'<%s => %s >' % (self.user, self.user_group)
785 return u'<%s => %s >' % (self.user, self.user_group)
786
786
787
787
788 class UserToPerm(Base, BaseModel):
788 class UserToPerm(Base, BaseModel):
789 __tablename__ = 'user_to_perm'
789 __tablename__ = 'user_to_perm'
790 __table_args__ = (
790 __table_args__ = (
791 UniqueConstraint('user_id', 'permission_id'),
791 UniqueConstraint('user_id', 'permission_id'),
792 {'extend_existing': True, 'mysql_engine': 'InnoDB',
792 {'extend_existing': True, 'mysql_engine': 'InnoDB',
793 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
793 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
794 )
794 )
795 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
795 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
796 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
796 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
797 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
797 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
798
798
799 user = relationship('User')
799 user = relationship('User')
800 permission = relationship('Permission', lazy='joined')
800 permission = relationship('Permission', lazy='joined')
801
801
802 def __unicode__(self):
802 def __unicode__(self):
803 return u'<%s => %s >' % (self.user, self.permission)
803 return u'<%s => %s >' % (self.user, self.permission)
804
804
805
805
806 class UserGroupRepoToPerm(Base, BaseModel):
806 class UserGroupRepoToPerm(Base, BaseModel):
807 __tablename__ = 'users_group_repo_to_perm'
807 __tablename__ = 'users_group_repo_to_perm'
808 __table_args__ = (
808 __table_args__ = (
809 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
809 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
810 {'extend_existing': True, 'mysql_engine': 'InnoDB',
810 {'extend_existing': True, 'mysql_engine': 'InnoDB',
811 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
811 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
812 )
812 )
813 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
813 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
814 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
814 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
815 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
815 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
816 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
816 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
817
817
818 users_group = relationship('UserGroup')
818 users_group = relationship('UserGroup')
819 permission = relationship('Permission')
819 permission = relationship('Permission')
820 repository = relationship('Repository')
820 repository = relationship('Repository')
821
821
822 def __unicode__(self):
822 def __unicode__(self):
823 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
823 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
824
824
825
825
826 class UserGroupUserGroupToPerm(Base, BaseModel):
826 class UserGroupUserGroupToPerm(Base, BaseModel):
827 __tablename__ = 'user_group_user_group_to_perm'
827 __tablename__ = 'user_group_user_group_to_perm'
828 __table_args__ = (
828 __table_args__ = (
829 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
829 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
830 CheckConstraint('target_user_group_id != user_group_id'),
830 CheckConstraint('target_user_group_id != user_group_id'),
831 {'extend_existing': True, 'mysql_engine': 'InnoDB',
831 {'extend_existing': True, 'mysql_engine': 'InnoDB',
832 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
832 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
833 )
833 )
834 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
834 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
835 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
835 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
836 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
836 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
837 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
837 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
838
838
839 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
839 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
840 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
840 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
841 permission = relationship('Permission')
841 permission = relationship('Permission')
842
842
843 def __unicode__(self):
843 def __unicode__(self):
844 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
844 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
845
845
846
846
847 class UserGroupToPerm(Base, BaseModel):
847 class UserGroupToPerm(Base, BaseModel):
848 __tablename__ = 'users_group_to_perm'
848 __tablename__ = 'users_group_to_perm'
849 __table_args__ = (
849 __table_args__ = (
850 UniqueConstraint('users_group_id', 'permission_id',),
850 UniqueConstraint('users_group_id', 'permission_id',),
851 {'extend_existing': True, 'mysql_engine': 'InnoDB',
851 {'extend_existing': True, 'mysql_engine': 'InnoDB',
852 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
852 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
853 )
853 )
854 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
854 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
855 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
855 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
856 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
856 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
857
857
858 users_group = relationship('UserGroup')
858 users_group = relationship('UserGroup')
859 permission = relationship('Permission')
859 permission = relationship('Permission')
860
860
861
861
862 class UserRepoGroupToPerm(Base, BaseModel):
862 class UserRepoGroupToPerm(Base, BaseModel):
863 __tablename__ = 'user_repo_group_to_perm'
863 __tablename__ = 'user_repo_group_to_perm'
864 __table_args__ = (
864 __table_args__ = (
865 UniqueConstraint('user_id', 'group_id', 'permission_id'),
865 UniqueConstraint('user_id', 'group_id', 'permission_id'),
866 {'extend_existing': True, 'mysql_engine': 'InnoDB',
866 {'extend_existing': True, 'mysql_engine': 'InnoDB',
867 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
867 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
868 )
868 )
869
869
870 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
870 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
871 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
871 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
872 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
872 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
873 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
873 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
874
874
875 user = relationship('User')
875 user = relationship('User')
876 group = relationship('RepoGroup')
876 group = relationship('RepoGroup')
877 permission = relationship('Permission')
877 permission = relationship('Permission')
878
878
879
879
880 class UserGroupRepoGroupToPerm(Base, BaseModel):
880 class UserGroupRepoGroupToPerm(Base, BaseModel):
881 __tablename__ = 'users_group_repo_group_to_perm'
881 __tablename__ = 'users_group_repo_group_to_perm'
882 __table_args__ = (
882 __table_args__ = (
883 UniqueConstraint('users_group_id', 'group_id'),
883 UniqueConstraint('users_group_id', 'group_id'),
884 {'extend_existing': True, 'mysql_engine': 'InnoDB',
884 {'extend_existing': True, 'mysql_engine': 'InnoDB',
885 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
885 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
886 )
886 )
887
887
888 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)
888 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)
889 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
889 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
890 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
890 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
891 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
891 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
892
892
893 users_group = relationship('UserGroup')
893 users_group = relationship('UserGroup')
894 permission = relationship('Permission')
894 permission = relationship('Permission')
895 group = relationship('RepoGroup')
895 group = relationship('RepoGroup')
896
896
897
897
898 class Statistics(Base, BaseModel):
898 class Statistics(Base, BaseModel):
899 __tablename__ = 'statistics'
899 __tablename__ = 'statistics'
900 __table_args__ = (
900 __table_args__ = (
901 UniqueConstraint('repository_id'),
901 UniqueConstraint('repository_id'),
902 {'extend_existing': True, 'mysql_engine': 'InnoDB',
902 {'extend_existing': True, 'mysql_engine': 'InnoDB',
903 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
903 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
904 )
904 )
905 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
905 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
906 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
906 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
907 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
907 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
908 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
908 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
909 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
909 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
910 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
910 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
911
911
912 repository = relationship('Repository', single_parent=True)
912 repository = relationship('Repository', single_parent=True)
913
913
914
914
915 class UserFollowing(Base, BaseModel):
915 class UserFollowing(Base, BaseModel):
916 __tablename__ = 'user_followings'
916 __tablename__ = 'user_followings'
917 __table_args__ = (
917 __table_args__ = (
918 UniqueConstraint('user_id', 'follows_repository_id'),
918 UniqueConstraint('user_id', 'follows_repository_id'),
919 UniqueConstraint('user_id', 'follows_user_id'),
919 UniqueConstraint('user_id', 'follows_user_id'),
920 {'extend_existing': True, 'mysql_engine': 'InnoDB',
920 {'extend_existing': True, 'mysql_engine': 'InnoDB',
921 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
921 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
922 )
922 )
923
923
924 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
924 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
925 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
925 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
926 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
926 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
927 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
927 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
928 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
928 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
929
929
930 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
930 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
931
931
932 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
932 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
933 follows_repository = relationship('Repository', order_by='Repository.repo_name')
933 follows_repository = relationship('Repository', order_by='Repository.repo_name')
934
934
935
935
936 class CacheInvalidation(Base, BaseModel):
936 class CacheInvalidation(Base, BaseModel):
937 __tablename__ = 'cache_invalidation'
937 __tablename__ = 'cache_invalidation'
938 __table_args__ = (
938 __table_args__ = (
939 UniqueConstraint('cache_key'),
939 UniqueConstraint('cache_key'),
940 Index('key_idx', 'cache_key'),
940 Index('key_idx', 'cache_key'),
941 {'extend_existing': True, 'mysql_engine': 'InnoDB',
941 {'extend_existing': True, 'mysql_engine': 'InnoDB',
942 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
942 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
943 )
943 )
944 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
944 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
945 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
945 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
946 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
946 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
947 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
947 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
948
948
949 def __init__(self, cache_key, cache_args=''):
949 def __init__(self, cache_key, cache_args=''):
950 self.cache_key = cache_key
950 self.cache_key = cache_key
951 self.cache_args = cache_args
951 self.cache_args = cache_args
952 self.cache_active = False
952 self.cache_active = False
953
953
954
954
955 class ChangesetComment(Base, BaseModel):
955 class ChangesetComment(Base, BaseModel):
956 __tablename__ = 'changeset_comments'
956 __tablename__ = 'changeset_comments'
957 __table_args__ = (
957 __table_args__ = (
958 Index('cc_revision_idx', 'revision'),
958 Index('cc_revision_idx', 'revision'),
959 {'extend_existing': True, 'mysql_engine': 'InnoDB',
959 {'extend_existing': True, 'mysql_engine': 'InnoDB',
960 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
960 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
961 )
961 )
962 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
962 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
963 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
963 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
964 revision = Column('revision', String(40), nullable=True)
964 revision = Column('revision', String(40), nullable=True)
965 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
965 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
966 line_no = Column('line_no', Unicode(10), nullable=True)
966 line_no = Column('line_no', Unicode(10), nullable=True)
967 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
967 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
968 f_path = Column('f_path', Unicode(1000), nullable=True)
968 f_path = Column('f_path', Unicode(1000), nullable=True)
969 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
969 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
970 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
970 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
971 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
971 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
972 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
972 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
973
973
974 author = relationship('User', lazy='joined')
974 author = relationship('User', lazy='joined')
975 repo = relationship('Repository')
975 repo = relationship('Repository')
976 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
976 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
977 pull_request = relationship('PullRequest', lazy='joined')
977 pull_request = relationship('PullRequest', lazy='joined')
978
978
979
979
980 class ChangesetStatus(Base, BaseModel):
980 class ChangesetStatus(Base, BaseModel):
981 __tablename__ = 'changeset_statuses'
981 __tablename__ = 'changeset_statuses'
982 __table_args__ = (
982 __table_args__ = (
983 Index('cs_revision_idx', 'revision'),
983 Index('cs_revision_idx', 'revision'),
984 Index('cs_version_idx', 'version'),
984 Index('cs_version_idx', 'version'),
985 UniqueConstraint('repo_id', 'revision', 'version'),
985 UniqueConstraint('repo_id', 'revision', 'version'),
986 {'extend_existing': True, 'mysql_engine': 'InnoDB',
986 {'extend_existing': True, 'mysql_engine': 'InnoDB',
987 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
987 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
988 )
988 )
989 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
989 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
990 STATUS_APPROVED = 'approved'
990 STATUS_APPROVED = 'approved'
991 STATUS_REJECTED = 'rejected'
991 STATUS_REJECTED = 'rejected'
992 STATUS_UNDER_REVIEW = 'under_review'
992 STATUS_UNDER_REVIEW = 'under_review'
993
993
994 STATUSES = [
994 STATUSES = [
995 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
995 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
996 (STATUS_APPROVED, _("Approved")),
996 (STATUS_APPROVED, _("Approved")),
997 (STATUS_REJECTED, _("Rejected")),
997 (STATUS_REJECTED, _("Rejected")),
998 (STATUS_UNDER_REVIEW, _("Under Review")),
998 (STATUS_UNDER_REVIEW, _("Under Review")),
999 ]
999 ]
1000
1000
1001 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1001 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1002 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1002 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1003 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1003 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1004 revision = Column('revision', String(40), nullable=False)
1004 revision = Column('revision', String(40), nullable=False)
1005 status = Column('status', String(128), nullable=False, default=DEFAULT)
1005 status = Column('status', String(128), nullable=False, default=DEFAULT)
1006 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1006 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1007 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1007 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1008 version = Column('version', Integer(), nullable=False, default=0)
1008 version = Column('version', Integer(), nullable=False, default=0)
1009 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1009 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1010
1010
1011 author = relationship('User', lazy='joined')
1011 author = relationship('User', lazy='joined')
1012 repo = relationship('Repository')
1012 repo = relationship('Repository')
1013 comment = relationship('ChangesetComment', lazy='joined')
1013 comment = relationship('ChangesetComment', lazy='joined')
1014 pull_request = relationship('PullRequest', lazy='joined')
1014 pull_request = relationship('PullRequest', lazy='joined')
1015
1015
1016
1016
1017
1017
1018 class PullRequest(Base, BaseModel):
1018 class PullRequest(Base, BaseModel):
1019 __tablename__ = 'pull_requests'
1019 __tablename__ = 'pull_requests'
1020 __table_args__ = (
1020 __table_args__ = (
1021 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1021 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1022 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1022 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1023 )
1023 )
1024
1024
1025 STATUS_NEW = u'new'
1025 STATUS_NEW = u'new'
1026 STATUS_OPEN = u'open'
1026 STATUS_OPEN = u'open'
1027 STATUS_CLOSED = u'closed'
1027 STATUS_CLOSED = u'closed'
1028
1028
1029 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1029 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1030 title = Column('title', Unicode(256), nullable=True)
1030 title = Column('title', Unicode(256), nullable=True)
1031 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1031 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1032 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1032 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1033 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1033 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1034 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1034 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1035 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1035 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1036 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1036 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1037 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1037 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1038 org_ref = Column('org_ref', Unicode(256), nullable=False)
1038 org_ref = Column('org_ref', Unicode(256), nullable=False)
1039 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1039 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1040 other_ref = Column('other_ref', Unicode(256), nullable=False)
1040 other_ref = Column('other_ref', Unicode(256), nullable=False)
1041
1041
1042 author = relationship('User', lazy='joined')
1042 author = relationship('User', lazy='joined')
1043 reviewers = relationship('PullRequestReviewers',
1043 reviewers = relationship('PullRequestReviewers',
1044 cascade="all, delete, delete-orphan")
1044 cascade="all, delete, delete-orphan")
1045 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1045 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1046 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1046 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1047 statuses = relationship('ChangesetStatus')
1047 statuses = relationship('ChangesetStatus')
1048 comments = relationship('ChangesetComment',
1048 comments = relationship('ChangesetComment',
1049 cascade="all, delete, delete-orphan")
1049 cascade="all, delete, delete-orphan")
1050
1050
1051
1051
1052 class PullRequestReviewers(Base, BaseModel):
1052 class PullRequestReviewers(Base, BaseModel):
1053 __tablename__ = 'pull_request_reviewers'
1053 __tablename__ = 'pull_request_reviewers'
1054 __table_args__ = (
1054 __table_args__ = (
1055 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1055 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1056 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1056 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1057 )
1057 )
1058
1058
1059 def __init__(self, user=None, pull_request=None):
1059 def __init__(self, user=None, pull_request=None):
1060 self.user = user
1060 self.user = user
1061 self.pull_request = pull_request
1061 self.pull_request = pull_request
1062
1062
1063 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1063 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1064 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1064 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1065 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1065 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1066
1066
1067 user = relationship('User')
1067 user = relationship('User')
1068 pull_request = relationship('PullRequest')
1068 pull_request = relationship('PullRequest')
1069
1069
1070
1070
1071 class Notification(Base, BaseModel):
1071 class Notification(Base, BaseModel):
1072 __tablename__ = 'notifications'
1072 __tablename__ = 'notifications'
1073 __table_args__ = (
1073 __table_args__ = (
1074 Index('notification_type_idx', 'type'),
1074 Index('notification_type_idx', 'type'),
1075 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1075 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1076 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1076 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1077 )
1077 )
1078
1078
1079 TYPE_CHANGESET_COMMENT = u'cs_comment'
1079 TYPE_CHANGESET_COMMENT = u'cs_comment'
1080 TYPE_MESSAGE = u'message'
1080 TYPE_MESSAGE = u'message'
1081 TYPE_MENTION = u'mention'
1081 TYPE_MENTION = u'mention'
1082 TYPE_REGISTRATION = u'registration'
1082 TYPE_REGISTRATION = u'registration'
1083 TYPE_PULL_REQUEST = u'pull_request'
1083 TYPE_PULL_REQUEST = u'pull_request'
1084 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1084 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1085
1085
1086 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1086 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1087 subject = Column('subject', Unicode(512), nullable=True)
1087 subject = Column('subject', Unicode(512), nullable=True)
1088 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1088 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1089 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1089 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1090 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1090 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1091 type_ = Column('type', Unicode(256))
1091 type_ = Column('type', Unicode(256))
1092
1092
1093 created_by_user = relationship('User')
1093 created_by_user = relationship('User')
1094 notifications_to_users = relationship('UserNotification', lazy='joined',
1094 notifications_to_users = relationship('UserNotification', lazy='joined',
1095 cascade="all, delete, delete-orphan")
1095 cascade="all, delete, delete-orphan")
1096
1096
1097
1097
1098 class UserNotification(Base, BaseModel):
1098 class UserNotification(Base, BaseModel):
1099 __tablename__ = 'user_to_notification'
1099 __tablename__ = 'user_to_notification'
1100 __table_args__ = (
1100 __table_args__ = (
1101 UniqueConstraint('user_id', 'notification_id'),
1101 UniqueConstraint('user_id', 'notification_id'),
1102 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1102 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1103 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1103 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1104 )
1104 )
1105 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1105 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1106 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1106 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1107 read = Column('read', Boolean, default=False)
1107 read = Column('read', Boolean, default=False)
1108 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1108 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1109
1109
1110 user = relationship('User', lazy="joined")
1110 user = relationship('User', lazy="joined")
1111 notification = relationship('Notification', lazy="joined",
1111 notification = relationship('Notification', lazy="joined",
1112 order_by=lambda: Notification.created_on.desc(),)
1112 order_by=lambda: Notification.created_on.desc(),)
1113
1113
1114
1114
1115 class Gist(Base, BaseModel):
1115 class Gist(Base, BaseModel):
1116 __tablename__ = 'gists'
1116 __tablename__ = 'gists'
1117 __table_args__ = (
1117 __table_args__ = (
1118 Index('g_gist_access_id_idx', 'gist_access_id'),
1118 Index('g_gist_access_id_idx', 'gist_access_id'),
1119 Index('g_created_on_idx', 'created_on'),
1119 Index('g_created_on_idx', 'created_on'),
1120 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1120 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1121 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1121 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1122 )
1122 )
1123 GIST_PUBLIC = u'public'
1123 GIST_PUBLIC = u'public'
1124 GIST_PRIVATE = u'private'
1124 GIST_PRIVATE = u'private'
1125
1125
1126 gist_id = Column('gist_id', Integer(), primary_key=True)
1126 gist_id = Column('gist_id', Integer(), primary_key=True)
1127 gist_access_id = Column('gist_access_id', Unicode(250))
1127 gist_access_id = Column('gist_access_id', Unicode(250))
1128 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1128 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1129 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1129 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1130 gist_expires = Column('gist_expires', Float(53), nullable=False)
1130 gist_expires = Column('gist_expires', Float(53), nullable=False)
1131 gist_type = Column('gist_type', Unicode(128), nullable=False)
1131 gist_type = Column('gist_type', Unicode(128), nullable=False)
1132 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1132 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1133 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1133 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1134
1134
1135 owner = relationship('User')
1135 owner = relationship('User')
1136
1136
1137
1137
1138 class DbMigrateVersion(Base, BaseModel):
1138 class DbMigrateVersion(Base, BaseModel):
1139 __tablename__ = 'db_migrate_version'
1139 __tablename__ = 'db_migrate_version'
1140 __table_args__ = (
1140 __table_args__ = (
1141 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1141 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1142 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1142 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1143 )
1143 )
1144 repository_id = Column('repository_id', String(250), primary_key=True)
1144 repository_id = Column('repository_id', String(250), primary_key=True)
1145 repository_path = Column('repository_path', Text)
1145 repository_path = Column('repository_path', Text)
1146 version = Column('version', Integer)
1146 version = Column('version', Integer)
@@ -1,1169 +1,1169 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 from rhodecode.lib.ext_json import json
46 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.caching_query import FromCache
47 from rhodecode.lib.caching_query import FromCache
48
48
49 from rhodecode.model.meta import Base, Session
49 from rhodecode.model.meta import Base, Session
50
50
51 URL_SEP = '/'
51 URL_SEP = '/'
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 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
58 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59
59
60
60
61 class BaseModel(object):
61 class BaseModel(object):
62 """
62 """
63 Base Model for all classes
63 Base Model for all classes
64 """
64 """
65
65
66 @classmethod
66 @classmethod
67 def _get_keys(cls):
67 def _get_keys(cls):
68 """return column names for this model """
68 """return column names for this model """
69 return class_mapper(cls).c.keys()
69 return class_mapper(cls).c.keys()
70
70
71 def get_dict(self):
71 def get_dict(self):
72 """
72 """
73 return dict with keys and values corresponding
73 return dict with keys and values corresponding
74 to this model data """
74 to this model data """
75
75
76 d = {}
76 d = {}
77 for k in self._get_keys():
77 for k in self._get_keys():
78 d[k] = getattr(self, k)
78 d[k] = getattr(self, k)
79
79
80 # also use __json__() if present to get additional fields
80 # also use __json__() if present to get additional fields
81 _json_attr = getattr(self, '__json__', None)
81 _json_attr = getattr(self, '__json__', None)
82 if _json_attr:
82 if _json_attr:
83 # update with attributes from __json__
83 # update with attributes from __json__
84 if callable(_json_attr):
84 if callable(_json_attr):
85 _json_attr = _json_attr()
85 _json_attr = _json_attr()
86 for k, val in _json_attr.items():
86 for k, val in _json_attr.items():
87 d[k] = val
87 d[k] = val
88 return d
88 return d
89
89
90 def get_appstruct(self):
90 def get_appstruct(self):
91 """return list with keys and values tupples corresponding
91 """return list with keys and values tupples corresponding
92 to this model data """
92 to this model data """
93
93
94 l = []
94 l = []
95 for k in self._get_keys():
95 for k in self._get_keys():
96 l.append((k, getattr(self, k),))
96 l.append((k, getattr(self, k),))
97 return l
97 return l
98
98
99 def populate_obj(self, populate_dict):
99 def populate_obj(self, populate_dict):
100 """populate model with data from given populate_dict"""
100 """populate model with data from given populate_dict"""
101
101
102 for k in self._get_keys():
102 for k in self._get_keys():
103 if k in populate_dict:
103 if k in populate_dict:
104 setattr(self, k, populate_dict[k])
104 setattr(self, k, populate_dict[k])
105
105
106 @classmethod
106 @classmethod
107 def query(cls):
107 def query(cls):
108 return Session().query(cls)
108 return Session().query(cls)
109
109
110 @classmethod
110 @classmethod
111 def get(cls, id_):
111 def get(cls, id_):
112 if id_:
112 if id_:
113 return cls.query().get(id_)
113 return cls.query().get(id_)
114
114
115 @classmethod
115 @classmethod
116 def get_or_404(cls, id_):
116 def get_or_404(cls, id_):
117 try:
117 try:
118 id_ = int(id_)
118 id_ = int(id_)
119 except (TypeError, ValueError):
119 except (TypeError, ValueError):
120 raise HTTPNotFound
120 raise HTTPNotFound
121
121
122 res = cls.query().get(id_)
122 res = cls.query().get(id_)
123 if not res:
123 if not res:
124 raise HTTPNotFound
124 raise HTTPNotFound
125 return res
125 return res
126
126
127 @classmethod
127 @classmethod
128 def getAll(cls):
128 def getAll(cls):
129 # deprecated and left for backward compatibility
129 # deprecated and left for backward compatibility
130 return cls.get_all()
130 return cls.get_all()
131
131
132 @classmethod
132 @classmethod
133 def get_all(cls):
133 def get_all(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
140
141 def __repr__(self):
141 def __repr__(self):
142 if hasattr(self, '__unicode__'):
142 if hasattr(self, '__unicode__'):
143 # python repr needs to return str
143 # python repr needs to return str
144 return safe_str(self.__unicode__())
144 return safe_str(self.__unicode__())
145 return '<DB:%s>' % (self.__class__.__name__)
145 return '<DB:%s>' % (self.__class__.__name__)
146
146
147
147
148 class RhodeCodeSetting(Base, BaseModel):
148 class RhodeCodeSetting(Base, BaseModel):
149 SETTINGS_TYPES = {
149 SETTINGS_TYPES = {
150 'str': safe_str,
150 'str': safe_str,
151 'int': safe_int,
151 'int': safe_int,
152 'unicode': safe_str,
152 'unicode': safe_str,
153 'bool': str2bool,
153 'bool': str2bool,
154 'list': functools.partial(aslist, sep=',')
154 'list': functools.partial(aslist, sep=',')
155 }
155 }
156 __tablename__ = 'rhodecode_settings'
156 __tablename__ = 'rhodecode_settings'
157 __table_args__ = (
157 __table_args__ = (
158 UniqueConstraint('app_settings_name'),
158 UniqueConstraint('app_settings_name'),
159 {'extend_existing': True, 'mysql_engine': 'InnoDB',
159 {'extend_existing': True, 'mysql_engine': 'InnoDB',
160 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
160 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
161 )
161 )
162 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
162 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
163 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
163 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
164 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
164 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
165 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
165 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
166
166
167 def __init__(self, key='', val='', type='unicode'):
167 def __init__(self, key='', val='', type='unicode'):
168 self.app_settings_name = key
168 self.app_settings_name = key
169 self.app_settings_value = val
169 self.app_settings_value = val
170 self.app_settings_type = type
170 self.app_settings_type = type
171
171
172 @validates('_app_settings_value')
172 @validates('_app_settings_value')
173 def validate_settings_value(self, key, val):
173 def validate_settings_value(self, key, val):
174 assert type(val) == str
174 assert type(val) == str
175 return val
175 return val
176
176
177 @hybrid_property
177 @hybrid_property
178 def app_settings_value(self):
178 def app_settings_value(self):
179 v = self._app_settings_value
179 v = self._app_settings_value
180 _type = self.app_settings_type
180 _type = self.app_settings_type
181 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
181 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
182 return converter(v)
182 return converter(v)
183
183
184 @app_settings_value.setter
184 @app_settings_value.setter
185 def app_settings_value(self, val):
185 def app_settings_value(self, val):
186 """
186 """
187 Setter that will always make sure we use unicode in app_settings_value
187 Setter that will always make sure we use unicode in app_settings_value
188
188
189 :param val:
189 :param val:
190 """
190 """
191 self._app_settings_value = safe_str(val)
191 self._app_settings_value = safe_str(val)
192
192
193 @hybrid_property
193 @hybrid_property
194 def app_settings_type(self):
194 def app_settings_type(self):
195 return self._app_settings_type
195 return self._app_settings_type
196
196
197 @app_settings_type.setter
197 @app_settings_type.setter
198 def app_settings_type(self, val):
198 def app_settings_type(self, val):
199 if val not in self.SETTINGS_TYPES:
199 if val not in self.SETTINGS_TYPES:
200 raise Exception('type must be one of %s got %s'
200 raise Exception('type must be one of %s got %s'
201 % (self.SETTINGS_TYPES.keys(), val))
201 % (self.SETTINGS_TYPES.keys(), val))
202 self._app_settings_type = val
202 self._app_settings_type = val
203
203
204 def __unicode__(self):
204 def __unicode__(self):
205 return u"<%s('%s:%s[%s]')>" % (
205 return u"<%s('%s:%s[%s]')>" % (
206 self.__class__.__name__,
206 self.__class__.__name__,
207 self.app_settings_name, self.app_settings_value, self.app_settings_type
207 self.app_settings_name, self.app_settings_value, self.app_settings_type
208 )
208 )
209
209
210
210
211 class RhodeCodeUi(Base, BaseModel):
211 class RhodeCodeUi(Base, BaseModel):
212 __tablename__ = 'rhodecode_ui'
212 __tablename__ = 'rhodecode_ui'
213 __table_args__ = (
213 __table_args__ = (
214 UniqueConstraint('ui_key'),
214 UniqueConstraint('ui_key'),
215 {'extend_existing': True, 'mysql_engine': 'InnoDB',
215 {'extend_existing': True, 'mysql_engine': 'InnoDB',
216 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
216 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
217 )
217 )
218
218
219 HOOK_REPO_SIZE = 'changegroup.repo_size'
219 HOOK_REPO_SIZE = 'changegroup.repo_size'
220 HOOK_PUSH = 'changegroup.push_logger'
220 HOOK_PUSH = 'changegroup.push_logger'
221 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
221 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
222 HOOK_PULL = 'outgoing.pull_logger'
222 HOOK_PULL = 'outgoing.pull_logger'
223 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
223 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
224
224
225 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
225 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
226 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
226 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
227 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
227 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
228 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
228 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
229 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
229 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
230
230
231
231
232
232
233 class User(Base, BaseModel):
233 class User(Base, BaseModel):
234 __tablename__ = 'users'
234 __tablename__ = 'users'
235 __table_args__ = (
235 __table_args__ = (
236 UniqueConstraint('username'), UniqueConstraint('email'),
236 UniqueConstraint('username'), UniqueConstraint('email'),
237 Index('u_username_idx', 'username'),
237 Index('u_username_idx', 'username'),
238 Index('u_email_idx', 'email'),
238 Index('u_email_idx', 'email'),
239 {'extend_existing': True, 'mysql_engine': 'InnoDB',
239 {'extend_existing': True, 'mysql_engine': 'InnoDB',
240 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
240 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
241 )
241 )
242 DEFAULT_USER = 'default'
242 DEFAULT_USER = 'default'
243
243
244 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
244 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
245 username = Column("username", String(255), nullable=True, unique=None, default=None)
245 username = Column("username", String(255), nullable=True, unique=None, default=None)
246 password = Column("password", String(255), nullable=True, unique=None, default=None)
246 password = Column("password", String(255), nullable=True, unique=None, default=None)
247 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
247 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
248 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
248 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
249 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
249 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
250 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
250 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
251 _email = Column("email", String(255), nullable=True, unique=None, default=None)
251 _email = Column("email", String(255), nullable=True, unique=None, default=None)
252 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
252 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
253 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
253 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
254 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
254 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
255 #for migration reasons, this is going to be later deleted
255 #for migration reasons, this is going to be later deleted
256 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
256 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
257
257
258 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
258 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
259 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
259 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
260 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
260 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
261
261
262 user_log = relationship('UserLog')
262 user_log = relationship('UserLog')
263 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
263 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
264
264
265 repositories = relationship('Repository')
265 repositories = relationship('Repository')
266 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
266 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
267 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
267 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
268
268
269 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
269 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
270 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
270 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
271
271
272 group_member = relationship('UserGroupMember', cascade='all')
272 group_member = relationship('UserGroupMember', cascade='all')
273
273
274 notifications = relationship('UserNotification', cascade='all')
274 notifications = relationship('UserNotification', cascade='all')
275 # notifications assigned to this user
275 # notifications assigned to this user
276 user_created_notifications = relationship('Notification', cascade='all')
276 user_created_notifications = relationship('Notification', cascade='all')
277 # comments created by this user
277 # comments created by this user
278 user_comments = relationship('ChangesetComment', cascade='all')
278 user_comments = relationship('ChangesetComment', cascade='all')
279 user_emails = relationship('UserEmailMap', cascade='all')
279 user_emails = relationship('UserEmailMap', cascade='all')
280
280
281 @hybrid_property
281 @hybrid_property
282 def email(self):
282 def email(self):
283 return self._email
283 return self._email
284
284
285 @email.setter
285 @email.setter
286 def email(self, val):
286 def email(self, val):
287 self._email = val.lower() if val else None
287 self._email = val.lower() if val else None
288
288
289 @property
289 @property
290 def firstname(self):
290 def firstname(self):
291 # alias for future
291 # alias for future
292 return self.name
292 return self.name
293
293
294 @property
294 @property
295 def username_and_name(self):
295 def username_and_name(self):
296 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
296 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
297
297
298 @property
298 @property
299 def full_name(self):
299 def full_name(self):
300 return '%s %s' % (self.firstname, self.lastname)
300 return '%s %s' % (self.firstname, self.lastname)
301
301
302 @property
302 @property
303 def full_contact(self):
303 def full_contact(self):
304 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
304 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
305
305
306 @property
306 @property
307 def short_contact(self):
307 def short_contact(self):
308 return '%s %s' % (self.firstname, self.lastname)
308 return '%s %s' % (self.firstname, self.lastname)
309
309
310 @property
310 @property
311 def is_admin(self):
311 def is_admin(self):
312 return self.admin
312 return self.admin
313
313
314 @classmethod
314 @classmethod
315 def get_by_username(cls, username, case_insensitive=False, cache=False):
315 def get_by_username(cls, username, case_insensitive=False, cache=False):
316 if case_insensitive:
316 if case_insensitive:
317 q = cls.query().filter(cls.username.ilike(username))
317 q = cls.query().filter(cls.username.ilike(username))
318 else:
318 else:
319 q = cls.query().filter(cls.username == username)
319 q = cls.query().filter(cls.username == username)
320
320
321 if cache:
321 if cache:
322 q = q.options(FromCache(
322 q = q.options(FromCache(
323 "sql_cache_short",
323 "sql_cache_short",
324 "get_user_%s" % _hash_key(username)
324 "get_user_%s" % _hash_key(username)
325 )
325 )
326 )
326 )
327 return q.scalar()
327 return q.scalar()
328
328
329 @classmethod
329 @classmethod
330 def get_by_auth_token(cls, auth_token, cache=False):
330 def get_by_auth_token(cls, auth_token, cache=False):
331 q = cls.query().filter(cls.api_key == auth_token)
331 q = cls.query().filter(cls.api_key == auth_token)
332
332
333 if cache:
333 if cache:
334 q = q.options(FromCache("sql_cache_short",
334 q = q.options(FromCache("sql_cache_short",
335 "get_auth_token_%s" % auth_token))
335 "get_auth_token_%s" % auth_token))
336 return q.scalar()
336 return q.scalar()
337
337
338 @classmethod
338 @classmethod
339 def get_by_email(cls, email, case_insensitive=False, cache=False):
339 def get_by_email(cls, email, case_insensitive=False, cache=False):
340 if case_insensitive:
340 if case_insensitive:
341 q = cls.query().filter(cls.email.ilike(email))
341 q = cls.query().filter(cls.email.ilike(email))
342 else:
342 else:
343 q = cls.query().filter(cls.email == email)
343 q = cls.query().filter(cls.email == email)
344
344
345 if cache:
345 if cache:
346 q = q.options(FromCache("sql_cache_short",
346 q = q.options(FromCache("sql_cache_short",
347 "get_email_key_%s" % email))
347 "get_email_key_%s" % email))
348
348
349 ret = q.scalar()
349 ret = q.scalar()
350 if ret is None:
350 if ret is None:
351 q = UserEmailMap.query()
351 q = UserEmailMap.query()
352 # try fetching in alternate email map
352 # try fetching in alternate email map
353 if case_insensitive:
353 if case_insensitive:
354 q = q.filter(UserEmailMap.email.ilike(email))
354 q = q.filter(UserEmailMap.email.ilike(email))
355 else:
355 else:
356 q = q.filter(UserEmailMap.email == email)
356 q = q.filter(UserEmailMap.email == email)
357 q = q.options(joinedload(UserEmailMap.user))
357 q = q.options(joinedload(UserEmailMap.user))
358 if cache:
358 if cache:
359 q = q.options(FromCache("sql_cache_short",
359 q = q.options(FromCache("sql_cache_short",
360 "get_email_map_key_%s" % email))
360 "get_email_map_key_%s" % email))
361 ret = getattr(q.scalar(), 'user', None)
361 ret = getattr(q.scalar(), 'user', None)
362
362
363 return ret
363 return ret
364
364
365 @classmethod
365 @classmethod
366 def get_first_admin(cls):
366 def get_first_admin(cls):
367 user = User.query().filter(User.admin == True).first()
367 user = User.query().filter(User.admin == True).first()
368 if user is None:
368 if user is None:
369 raise Exception('Missing administrative account!')
369 raise Exception('Missing administrative account!')
370 return user
370 return user
371
371
372 @classmethod
372 @classmethod
373 def get_default_user(cls, cache=False):
373 def get_default_user(cls, cache=False):
374 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
374 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
375 if user is None:
375 if user is None:
376 raise Exception('Missing default account!')
376 raise Exception('Missing default account!')
377 return user
377 return user
378
378
379
379
380
380
381
381
382 class UserEmailMap(Base, BaseModel):
382 class UserEmailMap(Base, BaseModel):
383 __tablename__ = 'user_email_map'
383 __tablename__ = 'user_email_map'
384 __table_args__ = (
384 __table_args__ = (
385 Index('uem_email_idx', 'email'),
385 Index('uem_email_idx', 'email'),
386 UniqueConstraint('email'),
386 UniqueConstraint('email'),
387 {'extend_existing': True, 'mysql_engine': 'InnoDB',
387 {'extend_existing': True, 'mysql_engine': 'InnoDB',
388 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
388 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
389 )
389 )
390
390
391
391
392 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
392 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
393 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
393 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
394 _email = Column("email", String(255), nullable=True, unique=False, default=None)
394 _email = Column("email", String(255), nullable=True, unique=False, default=None)
395 user = relationship('User', lazy='joined')
395 user = relationship('User', lazy='joined')
396
396
397 @validates('_email')
397 @validates('_email')
398 def validate_email(self, key, email):
398 def validate_email(self, key, email):
399 # check if this email is not main one
399 # check if this email is not main one
400 main_email = Session().query(User).filter(User.email == email).scalar()
400 main_email = Session().query(User).filter(User.email == email).scalar()
401 if main_email is not None:
401 if main_email is not None:
402 raise AttributeError('email %s is present is user table' % email)
402 raise AttributeError('email %s is present is user table' % email)
403 return email
403 return email
404
404
405 @hybrid_property
405 @hybrid_property
406 def email(self):
406 def email(self):
407 return self._email
407 return self._email
408
408
409 @email.setter
409 @email.setter
410 def email(self, val):
410 def email(self, val):
411 self._email = val.lower() if val else None
411 self._email = val.lower() if val else None
412
412
413
413
414 class UserIpMap(Base, BaseModel):
414 class UserIpMap(Base, BaseModel):
415 __tablename__ = 'user_ip_map'
415 __tablename__ = 'user_ip_map'
416 __table_args__ = (
416 __table_args__ = (
417 UniqueConstraint('user_id', 'ip_addr'),
417 UniqueConstraint('user_id', 'ip_addr'),
418 {'extend_existing': True, 'mysql_engine': 'InnoDB',
418 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
419 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
420 )
420 )
421
421
422
422
423 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
423 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
424 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
425 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
425 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
426 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
426 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
427 user = relationship('User', lazy='joined')
427 user = relationship('User', lazy='joined')
428
428
429
429
430 class UserLog(Base, BaseModel):
430 class UserLog(Base, BaseModel):
431 __tablename__ = 'user_logs'
431 __tablename__ = 'user_logs'
432 __table_args__ = (
432 __table_args__ = (
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
434 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
434 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
435 )
435 )
436 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
436 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
438 username = Column("username", String(255), nullable=True, unique=None, default=None)
438 username = Column("username", String(255), nullable=True, unique=None, default=None)
439 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
439 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
440 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
440 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
441 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
441 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
442 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
442 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
443 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
443 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
444
444
445 def __unicode__(self):
445 def __unicode__(self):
446 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
446 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
447 self.repository_name,
447 self.repository_name,
448 self.action)
448 self.action)
449
449
450 user = relationship('User')
450 user = relationship('User')
451 repository = relationship('Repository', cascade='')
451 repository = relationship('Repository', cascade='')
452
452
453
453
454 class UserGroup(Base, BaseModel):
454 class UserGroup(Base, BaseModel):
455 __tablename__ = 'users_groups'
455 __tablename__ = 'users_groups'
456 __table_args__ = (
456 __table_args__ = (
457 {'extend_existing': True, 'mysql_engine': 'InnoDB',
457 {'extend_existing': True, 'mysql_engine': 'InnoDB',
458 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
458 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
459 )
459 )
460
460
461 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
461 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
462 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
462 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
463 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
463 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
464 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
464 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
465 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
465 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
468
468
469 # don't trigger lazy load for migrations
469 # don't trigger lazy load for migrations
470 #members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
470 #members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
471 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
471 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
472 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
472 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
473 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
473 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
474 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
474 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
475 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
475 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
476
476
477 user = relationship('User')
477 user = relationship('User')
478
478
479 def __unicode__(self):
479 def __unicode__(self):
480 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
480 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
481 self.users_group_id,
481 self.users_group_id,
482 self.users_group_name)
482 self.users_group_name)
483
483
484 @classmethod
484 @classmethod
485 def get_by_group_name(cls, group_name, cache=False,
485 def get_by_group_name(cls, group_name, cache=False,
486 case_insensitive=False):
486 case_insensitive=False):
487 if case_insensitive:
487 if case_insensitive:
488 q = cls.query().filter(cls.users_group_name.ilike(group_name))
488 q = cls.query().filter(cls.users_group_name.ilike(group_name))
489 else:
489 else:
490 q = cls.query().filter(cls.users_group_name == group_name)
490 q = cls.query().filter(cls.users_group_name == group_name)
491 if cache:
491 if cache:
492 q = q.options(FromCache(
492 q = q.options(FromCache(
493 "sql_cache_short",
493 "sql_cache_short",
494 "get_user_%s" % _hash_key(group_name)
494 "get_user_%s" % _hash_key(group_name)
495 )
495 )
496 )
496 )
497 return q.scalar()
497 return q.scalar()
498
498
499 @classmethod
499 @classmethod
500 def get(cls, user_group_id, cache=False):
500 def get(cls, user_group_id, cache=False):
501 user_group = cls.query()
501 user_group = cls.query()
502 if cache:
502 if cache:
503 user_group = user_group.options(FromCache("sql_cache_short",
503 user_group = user_group.options(FromCache("sql_cache_short",
504 "get_users_group_%s" % user_group_id))
504 "get_users_group_%s" % user_group_id))
505 return user_group.get(user_group_id)
505 return user_group.get(user_group_id)
506
506
507
507
508 class UserGroupMember(Base, BaseModel):
508 class UserGroupMember(Base, BaseModel):
509 __tablename__ = 'users_groups_members'
509 __tablename__ = 'users_groups_members'
510 __table_args__ = (
510 __table_args__ = (
511 {'extend_existing': True, 'mysql_engine': 'InnoDB',
511 {'extend_existing': True, 'mysql_engine': 'InnoDB',
512 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
512 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
513 )
513 )
514
514
515 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
515 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
516 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
516 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
517 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
517 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
518
518
519 user = relationship('User', lazy='joined')
519 user = relationship('User', lazy='joined')
520 users_group = relationship('UserGroup')
520 users_group = relationship('UserGroup')
521
521
522 def __init__(self, gr_id='', u_id=''):
522 def __init__(self, gr_id='', u_id=''):
523 self.users_group_id = gr_id
523 self.users_group_id = gr_id
524 self.user_id = u_id
524 self.user_id = u_id
525
525
526
526
527 class RepositoryField(Base, BaseModel):
527 class RepositoryField(Base, BaseModel):
528 __tablename__ = 'repositories_fields'
528 __tablename__ = 'repositories_fields'
529 __table_args__ = (
529 __table_args__ = (
530 UniqueConstraint('repository_id', 'field_key'), # no-multi field
530 UniqueConstraint('repository_id', 'field_key'), # no-multi field
531 {'extend_existing': True, 'mysql_engine': 'InnoDB',
531 {'extend_existing': True, 'mysql_engine': 'InnoDB',
532 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
532 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
533 )
533 )
534 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
534 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
535
535
536 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
536 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
537 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
537 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
538 field_key = Column("field_key", String(250))
538 field_key = Column("field_key", String(250))
539 field_label = Column("field_label", String(1024), nullable=False)
539 field_label = Column("field_label", String(1024), nullable=False)
540 field_value = Column("field_value", String(10000), nullable=False)
540 field_value = Column("field_value", String(10000), nullable=False)
541 field_desc = Column("field_desc", String(1024), nullable=False)
541 field_desc = Column("field_desc", String(1024), nullable=False)
542 field_type = Column("field_type", String(256), nullable=False, unique=None)
542 field_type = Column("field_type", String(256), nullable=False, unique=None)
543 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
543 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
544
544
545 repository = relationship('Repository')
545 repository = relationship('Repository')
546
546
547 @classmethod
547 @classmethod
548 def get_by_key_name(cls, key, repo):
548 def get_by_key_name(cls, key, repo):
549 row = cls.query()\
549 row = cls.query()\
550 .filter(cls.repository == repo)\
550 .filter(cls.repository == repo)\
551 .filter(cls.field_key == key).scalar()
551 .filter(cls.field_key == key).scalar()
552 return row
552 return row
553
553
554
554
555 class Repository(Base, BaseModel):
555 class Repository(Base, BaseModel):
556 __tablename__ = 'repositories'
556 __tablename__ = 'repositories'
557 __table_args__ = (
557 __table_args__ = (
558 UniqueConstraint('repo_name'),
558 UniqueConstraint('repo_name'),
559 Index('r_repo_name_idx', 'repo_name'),
559 Index('r_repo_name_idx', 'repo_name'),
560 {'extend_existing': True, 'mysql_engine': 'InnoDB',
560 {'extend_existing': True, 'mysql_engine': 'InnoDB',
561 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
561 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
562 )
562 )
563
563
564 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
564 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
565 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
565 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
566 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
566 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
567 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
567 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
568 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
568 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
569 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
569 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
570 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
570 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
571 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
571 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
572 description = Column("description", String(10000), nullable=True, unique=None, default=None)
572 description = Column("description", String(10000), nullable=True, unique=None, default=None)
573 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
573 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
574 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
574 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
575 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
575 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
576 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
576 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
577 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
577 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
578 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
578 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
579
579
580 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
580 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
581 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
581 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
582
582
583 user = relationship('User')
583 user = relationship('User')
584 fork = relationship('Repository', remote_side=repo_id)
584 fork = relationship('Repository', remote_side=repo_id)
585 group = relationship('RepoGroup')
585 group = relationship('RepoGroup')
586 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
586 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
587 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
587 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
588 stats = relationship('Statistics', cascade='all', uselist=False)
588 stats = relationship('Statistics', cascade='all', uselist=False)
589
589
590 followers = relationship('UserFollowing',
590 followers = relationship('UserFollowing',
591 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
591 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
592 cascade='all')
592 cascade='all')
593 extra_fields = relationship('RepositoryField',
593 extra_fields = relationship('RepositoryField',
594 cascade="all, delete, delete-orphan")
594 cascade="all, delete, delete-orphan")
595
595
596 logs = relationship('UserLog')
596 logs = relationship('UserLog')
597 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
597 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
598
598
599 pull_requests_org = relationship('PullRequest',
599 pull_requests_org = relationship('PullRequest',
600 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
600 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
601 cascade="all, delete, delete-orphan")
601 cascade="all, delete, delete-orphan")
602
602
603 pull_requests_other = relationship('PullRequest',
603 pull_requests_other = relationship('PullRequest',
604 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
604 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
605 cascade="all, delete, delete-orphan")
605 cascade="all, delete, delete-orphan")
606
606
607 def __unicode__(self):
607 def __unicode__(self):
608 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
608 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
609 safe_str(self.repo_name))
609 safe_str(self.repo_name))
610
610
611 @classmethod
611 @classmethod
612 def get_by_repo_name(cls, repo_name):
612 def get_by_repo_name(cls, repo_name):
613 q = Session().query(cls).filter(cls.repo_name == repo_name)
613 q = Session().query(cls).filter(cls.repo_name == repo_name)
614 q = q.options(joinedload(Repository.fork))\
614 q = q.options(joinedload(Repository.fork))\
615 .options(joinedload(Repository.user))\
615 .options(joinedload(Repository.user))\
616 .options(joinedload(Repository.group))
616 .options(joinedload(Repository.group))
617 return q.scalar()
617 return q.scalar()
618
618
619
619
620 class RepoGroup(Base, BaseModel):
620 class RepoGroup(Base, BaseModel):
621 __tablename__ = 'groups'
621 __tablename__ = 'groups'
622 __table_args__ = (
622 __table_args__ = (
623 UniqueConstraint('group_name', 'group_parent_id'),
623 UniqueConstraint('group_name', 'group_parent_id'),
624 {'extend_existing': True, 'mysql_engine': 'InnoDB',
624 {'extend_existing': True, 'mysql_engine': 'InnoDB',
625 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
625 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
626 )
626 )
627
627
628
628
629 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
629 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
630 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
630 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
631 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
631 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
632 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
632 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
633 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
633 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
634 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
634 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
635
635
636 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
636 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
637 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
637 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
638 parent_group = relationship('RepoGroup', remote_side=group_id)
638 parent_group = relationship('RepoGroup', remote_side=group_id)
639 user = relationship('User')
639 user = relationship('User')
640
640
641 def __init__(self, group_name='', parent_group=None):
641 def __init__(self, group_name='', parent_group=None):
642 self.group_name = group_name
642 self.group_name = group_name
643 self.parent_group = parent_group
643 self.parent_group = parent_group
644
644
645 def __unicode__(self):
645 def __unicode__(self):
646 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
646 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
647 self.group_name)
647 self.group_name)
648
648
649 @classmethod
649 @classmethod
650 def url_sep(cls):
650 def url_sep(cls):
651 return URL_SEP
651 return URL_SEP
652
652
653 @classmethod
653 @classmethod
654 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
654 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
655 if case_insensitive:
655 if case_insensitive:
656 gr = cls.query()\
656 gr = cls.query()\
657 .filter(cls.group_name.ilike(group_name))
657 .filter(cls.group_name.ilike(group_name))
658 else:
658 else:
659 gr = cls.query()\
659 gr = cls.query()\
660 .filter(cls.group_name == group_name)
660 .filter(cls.group_name == group_name)
661 if cache:
661 if cache:
662 gr = gr.options(FromCache(
662 gr = gr.options(FromCache(
663 "sql_cache_short",
663 "sql_cache_short",
664 "get_group_%s" % _hash_key(group_name)
664 "get_group_%s" % _hash_key(group_name)
665 )
665 )
666 )
666 )
667 return gr.scalar()
667 return gr.scalar()
668
668
669
669
670 class Permission(Base, BaseModel):
670 class Permission(Base, BaseModel):
671 __tablename__ = 'permissions'
671 __tablename__ = 'permissions'
672 __table_args__ = (
672 __table_args__ = (
673 Index('p_perm_name_idx', 'permission_name'),
673 Index('p_perm_name_idx', 'permission_name'),
674 {'extend_existing': True, 'mysql_engine': 'InnoDB',
674 {'extend_existing': True, 'mysql_engine': 'InnoDB',
675 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
675 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
676 )
676 )
677 PERMS = [
677 PERMS = [
678 ('hg.admin', _('RhodeCode Administrator')),
678 ('hg.admin', _('RhodeCode Administrator')),
679
679
680 ('repository.none', _('Repository no access')),
680 ('repository.none', _('Repository no access')),
681 ('repository.read', _('Repository read access')),
681 ('repository.read', _('Repository read access')),
682 ('repository.write', _('Repository write access')),
682 ('repository.write', _('Repository write access')),
683 ('repository.admin', _('Repository admin access')),
683 ('repository.admin', _('Repository admin access')),
684
684
685 ('group.none', _('Repository group no access')),
685 ('group.none', _('Repository group no access')),
686 ('group.read', _('Repository group read access')),
686 ('group.read', _('Repository group read access')),
687 ('group.write', _('Repository group write access')),
687 ('group.write', _('Repository group write access')),
688 ('group.admin', _('Repository group admin access')),
688 ('group.admin', _('Repository group admin access')),
689
689
690 ('usergroup.none', _('User group no access')),
690 ('usergroup.none', _('User group no access')),
691 ('usergroup.read', _('User group read access')),
691 ('usergroup.read', _('User group read access')),
692 ('usergroup.write', _('User group write access')),
692 ('usergroup.write', _('User group write access')),
693 ('usergroup.admin', _('User group admin access')),
693 ('usergroup.admin', _('User group admin access')),
694
694
695 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
695 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
696 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
696 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
697
697
698 ('hg.usergroup.create.false', _('User Group creation disabled')),
698 ('hg.usergroup.create.false', _('User Group creation disabled')),
699 ('hg.usergroup.create.true', _('User Group creation enabled')),
699 ('hg.usergroup.create.true', _('User Group creation enabled')),
700
700
701 ('hg.create.none', _('Repository creation disabled')),
701 ('hg.create.none', _('Repository creation disabled')),
702 ('hg.create.repository', _('Repository creation enabled')),
702 ('hg.create.repository', _('Repository creation enabled')),
703
703
704 ('hg.fork.none', _('Repository forking disabled')),
704 ('hg.fork.none', _('Repository forking disabled')),
705 ('hg.fork.repository', _('Repository forking enabled')),
705 ('hg.fork.repository', _('Repository forking enabled')),
706
706
707 ('hg.register.none', _('Registration disabled')),
707 ('hg.register.none', _('Registration disabled')),
708 ('hg.register.manual_activate', _('User Registration with manual account activation')),
708 ('hg.register.manual_activate', _('User Registration with manual account activation')),
709 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
709 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
710
710
711 ('hg.extern_activate.manual', _('Manual activation of external account')),
711 ('hg.extern_activate.manual', _('Manual activation of external account')),
712 ('hg.extern_activate.auto', _('Automatic activation of external account')),
712 ('hg.extern_activate.auto', _('Automatic activation of external account')),
713
713
714 ]
714 ]
715
715
716 #definition of system default permissions for DEFAULT user
716 #definition of system default permissions for DEFAULT user
717 DEFAULT_USER_PERMISSIONS = [
717 DEFAULT_USER_PERMISSIONS = [
718 'repository.read',
718 'repository.read',
719 'group.read',
719 'group.read',
720 'usergroup.read',
720 'usergroup.read',
721 'hg.create.repository',
721 'hg.create.repository',
722 'hg.fork.repository',
722 'hg.fork.repository',
723 'hg.register.manual_activate',
723 'hg.register.manual_activate',
724 'hg.extern_activate.auto',
724 'hg.extern_activate.auto',
725 ]
725 ]
726
726
727 # defines which permissions are more important higher the more important
727 # defines which permissions are more important higher the more important
728 # Weight defines which permissions are more important.
728 # Weight defines which permissions are more important.
729 # The higher number the more important.
729 # The higher number the more important.
730 PERM_WEIGHTS = {
730 PERM_WEIGHTS = {
731 'repository.none': 0,
731 'repository.none': 0,
732 'repository.read': 1,
732 'repository.read': 1,
733 'repository.write': 3,
733 'repository.write': 3,
734 'repository.admin': 4,
734 'repository.admin': 4,
735
735
736 'group.none': 0,
736 'group.none': 0,
737 'group.read': 1,
737 'group.read': 1,
738 'group.write': 3,
738 'group.write': 3,
739 'group.admin': 4,
739 'group.admin': 4,
740
740
741 'usergroup.none': 0,
741 'usergroup.none': 0,
742 'usergroup.read': 1,
742 'usergroup.read': 1,
743 'usergroup.write': 3,
743 'usergroup.write': 3,
744 'usergroup.admin': 4,
744 'usergroup.admin': 4,
745 'hg.repogroup.create.false': 0,
745 'hg.repogroup.create.false': 0,
746 'hg.repogroup.create.true': 1,
746 'hg.repogroup.create.true': 1,
747
747
748 'hg.usergroup.create.false': 0,
748 'hg.usergroup.create.false': 0,
749 'hg.usergroup.create.true': 1,
749 'hg.usergroup.create.true': 1,
750
750
751 'hg.fork.none': 0,
751 'hg.fork.none': 0,
752 'hg.fork.repository': 1,
752 'hg.fork.repository': 1,
753 'hg.create.none': 0,
753 'hg.create.none': 0,
754 'hg.create.repository': 1
754 'hg.create.repository': 1
755 }
755 }
756
756
757 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
757 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
758 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
758 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
759 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
759 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
760
760
761 def __unicode__(self):
761 def __unicode__(self):
762 return u"<%s('%s:%s')>" % (
762 return u"<%s('%s:%s')>" % (
763 self.__class__.__name__, self.permission_id, self.permission_name
763 self.__class__.__name__, self.permission_id, self.permission_name
764 )
764 )
765
765
766 @classmethod
766 @classmethod
767 def get_by_key(cls, key):
767 def get_by_key(cls, key):
768 return cls.query().filter(cls.permission_name == key).scalar()
768 return cls.query().filter(cls.permission_name == key).scalar()
769
769
770
770
771 class UserRepoToPerm(Base, BaseModel):
771 class UserRepoToPerm(Base, BaseModel):
772 __tablename__ = 'repo_to_perm'
772 __tablename__ = 'repo_to_perm'
773 __table_args__ = (
773 __table_args__ = (
774 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
774 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
775 {'extend_existing': True, 'mysql_engine': 'InnoDB',
775 {'extend_existing': True, 'mysql_engine': 'InnoDB',
776 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
776 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
777 )
777 )
778 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
778 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
779 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
779 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
780 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
780 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
781 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
781 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
782
782
783 user = relationship('User')
783 user = relationship('User')
784 repository = relationship('Repository')
784 repository = relationship('Repository')
785 permission = relationship('Permission')
785 permission = relationship('Permission')
786
786
787 def __unicode__(self):
787 def __unicode__(self):
788 return u'<%s => %s >' % (self.user, self.repository)
788 return u'<%s => %s >' % (self.user, self.repository)
789
789
790
790
791 class UserUserGroupToPerm(Base, BaseModel):
791 class UserUserGroupToPerm(Base, BaseModel):
792 __tablename__ = 'user_user_group_to_perm'
792 __tablename__ = 'user_user_group_to_perm'
793 __table_args__ = (
793 __table_args__ = (
794 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
794 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
795 {'extend_existing': True, 'mysql_engine': 'InnoDB',
795 {'extend_existing': True, 'mysql_engine': 'InnoDB',
796 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
796 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
797 )
797 )
798 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
798 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
799 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
799 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
800 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
800 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
801 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
801 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
802
802
803 user = relationship('User')
803 user = relationship('User')
804 user_group = relationship('UserGroup')
804 user_group = relationship('UserGroup')
805 permission = relationship('Permission')
805 permission = relationship('Permission')
806
806
807 def __unicode__(self):
807 def __unicode__(self):
808 return u'<%s => %s >' % (self.user, self.user_group)
808 return u'<%s => %s >' % (self.user, self.user_group)
809
809
810
810
811 class UserToPerm(Base, BaseModel):
811 class UserToPerm(Base, BaseModel):
812 __tablename__ = 'user_to_perm'
812 __tablename__ = 'user_to_perm'
813 __table_args__ = (
813 __table_args__ = (
814 UniqueConstraint('user_id', 'permission_id'),
814 UniqueConstraint('user_id', 'permission_id'),
815 {'extend_existing': True, 'mysql_engine': 'InnoDB',
815 {'extend_existing': True, 'mysql_engine': 'InnoDB',
816 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
816 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
817 )
817 )
818 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
818 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
819 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
819 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
820 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
820 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
821
821
822 user = relationship('User')
822 user = relationship('User')
823 permission = relationship('Permission', lazy='joined')
823 permission = relationship('Permission', lazy='joined')
824
824
825 def __unicode__(self):
825 def __unicode__(self):
826 return u'<%s => %s >' % (self.user, self.permission)
826 return u'<%s => %s >' % (self.user, self.permission)
827
827
828
828
829 class UserGroupRepoToPerm(Base, BaseModel):
829 class UserGroupRepoToPerm(Base, BaseModel):
830 __tablename__ = 'users_group_repo_to_perm'
830 __tablename__ = 'users_group_repo_to_perm'
831 __table_args__ = (
831 __table_args__ = (
832 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
832 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
833 {'extend_existing': True, 'mysql_engine': 'InnoDB',
833 {'extend_existing': True, 'mysql_engine': 'InnoDB',
834 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
834 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
835 )
835 )
836 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
836 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
837 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
837 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
838 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
838 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
839 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
839 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
840
840
841 users_group = relationship('UserGroup')
841 users_group = relationship('UserGroup')
842 permission = relationship('Permission')
842 permission = relationship('Permission')
843 repository = relationship('Repository')
843 repository = relationship('Repository')
844
844
845 def __unicode__(self):
845 def __unicode__(self):
846 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
846 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
847
847
848
848
849 class UserGroupUserGroupToPerm(Base, BaseModel):
849 class UserGroupUserGroupToPerm(Base, BaseModel):
850 __tablename__ = 'user_group_user_group_to_perm'
850 __tablename__ = 'user_group_user_group_to_perm'
851 __table_args__ = (
851 __table_args__ = (
852 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
852 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
853 CheckConstraint('target_user_group_id != user_group_id'),
853 CheckConstraint('target_user_group_id != user_group_id'),
854 {'extend_existing': True, 'mysql_engine': 'InnoDB',
854 {'extend_existing': True, 'mysql_engine': 'InnoDB',
855 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
855 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
856 )
856 )
857 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
857 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
858 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
858 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
859 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
859 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
860 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
860 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
861
861
862 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
862 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
863 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
863 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
864 permission = relationship('Permission')
864 permission = relationship('Permission')
865
865
866 def __unicode__(self):
866 def __unicode__(self):
867 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
867 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
868
868
869
869
870 class UserGroupToPerm(Base, BaseModel):
870 class UserGroupToPerm(Base, BaseModel):
871 __tablename__ = 'users_group_to_perm'
871 __tablename__ = 'users_group_to_perm'
872 __table_args__ = (
872 __table_args__ = (
873 UniqueConstraint('users_group_id', 'permission_id',),
873 UniqueConstraint('users_group_id', 'permission_id',),
874 {'extend_existing': True, 'mysql_engine': 'InnoDB',
874 {'extend_existing': True, 'mysql_engine': 'InnoDB',
875 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
875 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
876 )
876 )
877 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
877 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
878 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
878 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
879 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
879 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
880
880
881 users_group = relationship('UserGroup')
881 users_group = relationship('UserGroup')
882 permission = relationship('Permission')
882 permission = relationship('Permission')
883
883
884
884
885 class UserRepoGroupToPerm(Base, BaseModel):
885 class UserRepoGroupToPerm(Base, BaseModel):
886 __tablename__ = 'user_repo_group_to_perm'
886 __tablename__ = 'user_repo_group_to_perm'
887 __table_args__ = (
887 __table_args__ = (
888 UniqueConstraint('user_id', 'group_id', 'permission_id'),
888 UniqueConstraint('user_id', 'group_id', 'permission_id'),
889 {'extend_existing': True, 'mysql_engine': 'InnoDB',
889 {'extend_existing': True, 'mysql_engine': 'InnoDB',
890 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
890 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
891 )
891 )
892
892
893 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
893 group_to_perm_id = Column("group_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)
894 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
895 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
895 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
896 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
896 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
897
897
898 user = relationship('User')
898 user = relationship('User')
899 group = relationship('RepoGroup')
899 group = relationship('RepoGroup')
900 permission = relationship('Permission')
900 permission = relationship('Permission')
901
901
902
902
903 class UserGroupRepoGroupToPerm(Base, BaseModel):
903 class UserGroupRepoGroupToPerm(Base, BaseModel):
904 __tablename__ = 'users_group_repo_group_to_perm'
904 __tablename__ = 'users_group_repo_group_to_perm'
905 __table_args__ = (
905 __table_args__ = (
906 UniqueConstraint('users_group_id', 'group_id'),
906 UniqueConstraint('users_group_id', 'group_id'),
907 {'extend_existing': True, 'mysql_engine': 'InnoDB',
907 {'extend_existing': True, 'mysql_engine': 'InnoDB',
908 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
908 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
909 )
909 )
910
910
911 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)
911 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)
912 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
912 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
913 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
913 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
914 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
914 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
915
915
916 users_group = relationship('UserGroup')
916 users_group = relationship('UserGroup')
917 permission = relationship('Permission')
917 permission = relationship('Permission')
918 group = relationship('RepoGroup')
918 group = relationship('RepoGroup')
919
919
920
920
921 class Statistics(Base, BaseModel):
921 class Statistics(Base, BaseModel):
922 __tablename__ = 'statistics'
922 __tablename__ = 'statistics'
923 __table_args__ = (
923 __table_args__ = (
924 UniqueConstraint('repository_id'),
924 UniqueConstraint('repository_id'),
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
926 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
926 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
927 )
927 )
928 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
928 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
929 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
929 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
930 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
930 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
931 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
931 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
932 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
932 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
933 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
933 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
934
934
935 repository = relationship('Repository', single_parent=True)
935 repository = relationship('Repository', single_parent=True)
936
936
937
937
938 class UserFollowing(Base, BaseModel):
938 class UserFollowing(Base, BaseModel):
939 __tablename__ = 'user_followings'
939 __tablename__ = 'user_followings'
940 __table_args__ = (
940 __table_args__ = (
941 UniqueConstraint('user_id', 'follows_repository_id'),
941 UniqueConstraint('user_id', 'follows_repository_id'),
942 UniqueConstraint('user_id', 'follows_user_id'),
942 UniqueConstraint('user_id', 'follows_user_id'),
943 {'extend_existing': True, 'mysql_engine': 'InnoDB',
943 {'extend_existing': True, 'mysql_engine': 'InnoDB',
944 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
944 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
945 )
945 )
946
946
947 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
947 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
948 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
948 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
949 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
949 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
950 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
950 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
951 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
951 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
952
952
953 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
953 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
954
954
955 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
955 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
956 follows_repository = relationship('Repository', order_by='Repository.repo_name')
956 follows_repository = relationship('Repository', order_by='Repository.repo_name')
957
957
958
958
959 class CacheInvalidation(Base, BaseModel):
959 class CacheInvalidation(Base, BaseModel):
960 __tablename__ = 'cache_invalidation'
960 __tablename__ = 'cache_invalidation'
961 __table_args__ = (
961 __table_args__ = (
962 UniqueConstraint('cache_key'),
962 UniqueConstraint('cache_key'),
963 Index('key_idx', 'cache_key'),
963 Index('key_idx', 'cache_key'),
964 {'extend_existing': True, 'mysql_engine': 'InnoDB',
964 {'extend_existing': True, 'mysql_engine': 'InnoDB',
965 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
965 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
966 )
966 )
967 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
967 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
968 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
968 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
969 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
969 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
970 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
970 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
971
971
972 def __init__(self, cache_key, cache_args=''):
972 def __init__(self, cache_key, cache_args=''):
973 self.cache_key = cache_key
973 self.cache_key = cache_key
974 self.cache_args = cache_args
974 self.cache_args = cache_args
975 self.cache_active = False
975 self.cache_active = False
976
976
977
977
978 class ChangesetComment(Base, BaseModel):
978 class ChangesetComment(Base, BaseModel):
979 __tablename__ = 'changeset_comments'
979 __tablename__ = 'changeset_comments'
980 __table_args__ = (
980 __table_args__ = (
981 Index('cc_revision_idx', 'revision'),
981 Index('cc_revision_idx', 'revision'),
982 {'extend_existing': True, 'mysql_engine': 'InnoDB',
982 {'extend_existing': True, 'mysql_engine': 'InnoDB',
983 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
983 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
984 )
984 )
985 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
985 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
986 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
986 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
987 revision = Column('revision', String(40), nullable=True)
987 revision = Column('revision', String(40), nullable=True)
988 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
988 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
989 line_no = Column('line_no', Unicode(10), nullable=True)
989 line_no = Column('line_no', Unicode(10), nullable=True)
990 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
990 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
991 f_path = Column('f_path', Unicode(1000), nullable=True)
991 f_path = Column('f_path', Unicode(1000), nullable=True)
992 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
992 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
993 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
993 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
994 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
994 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
995 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
995 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
996
996
997 author = relationship('User', lazy='joined')
997 author = relationship('User', lazy='joined')
998 repo = relationship('Repository')
998 repo = relationship('Repository')
999 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
999 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1000 pull_request = relationship('PullRequest', lazy='joined')
1000 pull_request = relationship('PullRequest', lazy='joined')
1001
1001
1002
1002
1003 class ChangesetStatus(Base, BaseModel):
1003 class ChangesetStatus(Base, BaseModel):
1004 __tablename__ = 'changeset_statuses'
1004 __tablename__ = 'changeset_statuses'
1005 __table_args__ = (
1005 __table_args__ = (
1006 Index('cs_revision_idx', 'revision'),
1006 Index('cs_revision_idx', 'revision'),
1007 Index('cs_version_idx', 'version'),
1007 Index('cs_version_idx', 'version'),
1008 UniqueConstraint('repo_id', 'revision', 'version'),
1008 UniqueConstraint('repo_id', 'revision', 'version'),
1009 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1009 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1010 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1010 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1011 )
1011 )
1012 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1012 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1013 STATUS_APPROVED = 'approved'
1013 STATUS_APPROVED = 'approved'
1014 STATUS_REJECTED = 'rejected'
1014 STATUS_REJECTED = 'rejected'
1015 STATUS_UNDER_REVIEW = 'under_review'
1015 STATUS_UNDER_REVIEW = 'under_review'
1016
1016
1017 STATUSES = [
1017 STATUSES = [
1018 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1018 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1019 (STATUS_APPROVED, _("Approved")),
1019 (STATUS_APPROVED, _("Approved")),
1020 (STATUS_REJECTED, _("Rejected")),
1020 (STATUS_REJECTED, _("Rejected")),
1021 (STATUS_UNDER_REVIEW, _("Under Review")),
1021 (STATUS_UNDER_REVIEW, _("Under Review")),
1022 ]
1022 ]
1023
1023
1024 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1024 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1025 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1025 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1026 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1026 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1027 revision = Column('revision', String(40), nullable=False)
1027 revision = Column('revision', String(40), nullable=False)
1028 status = Column('status', String(128), nullable=False, default=DEFAULT)
1028 status = Column('status', String(128), nullable=False, default=DEFAULT)
1029 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1029 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1030 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1030 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1031 version = Column('version', Integer(), nullable=False, default=0)
1031 version = Column('version', Integer(), nullable=False, default=0)
1032 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1032 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1033
1033
1034 author = relationship('User', lazy='joined')
1034 author = relationship('User', lazy='joined')
1035 repo = relationship('Repository')
1035 repo = relationship('Repository')
1036 comment = relationship('ChangesetComment', lazy='joined')
1036 comment = relationship('ChangesetComment', lazy='joined')
1037 pull_request = relationship('PullRequest', lazy='joined')
1037 pull_request = relationship('PullRequest', lazy='joined')
1038
1038
1039
1039
1040
1040
1041 class PullRequest(Base, BaseModel):
1041 class PullRequest(Base, BaseModel):
1042 __tablename__ = 'pull_requests'
1042 __tablename__ = 'pull_requests'
1043 __table_args__ = (
1043 __table_args__ = (
1044 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1044 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1045 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1045 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1046 )
1046 )
1047
1047
1048 STATUS_NEW = u'new'
1048 STATUS_NEW = u'new'
1049 STATUS_OPEN = u'open'
1049 STATUS_OPEN = u'open'
1050 STATUS_CLOSED = u'closed'
1050 STATUS_CLOSED = u'closed'
1051
1051
1052 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1052 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1053 title = Column('title', Unicode(256), nullable=True)
1053 title = Column('title', Unicode(256), nullable=True)
1054 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1054 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1055 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1055 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1056 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1056 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1057 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1057 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1058 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1058 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1059 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1059 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1060 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1060 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1061 org_ref = Column('org_ref', Unicode(256), nullable=False)
1061 org_ref = Column('org_ref', Unicode(256), nullable=False)
1062 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1062 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1063 other_ref = Column('other_ref', Unicode(256), nullable=False)
1063 other_ref = Column('other_ref', Unicode(256), nullable=False)
1064
1064
1065 author = relationship('User', lazy='joined')
1065 author = relationship('User', lazy='joined')
1066 reviewers = relationship('PullRequestReviewers',
1066 reviewers = relationship('PullRequestReviewers',
1067 cascade="all, delete, delete-orphan")
1067 cascade="all, delete, delete-orphan")
1068 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1068 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1069 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1069 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1070 statuses = relationship('ChangesetStatus')
1070 statuses = relationship('ChangesetStatus')
1071 comments = relationship('ChangesetComment',
1071 comments = relationship('ChangesetComment',
1072 cascade="all, delete, delete-orphan")
1072 cascade="all, delete, delete-orphan")
1073
1073
1074
1074
1075 class PullRequestReviewers(Base, BaseModel):
1075 class PullRequestReviewers(Base, BaseModel):
1076 __tablename__ = 'pull_request_reviewers'
1076 __tablename__ = 'pull_request_reviewers'
1077 __table_args__ = (
1077 __table_args__ = (
1078 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1078 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1079 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1079 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1080 )
1080 )
1081
1081
1082 def __init__(self, user=None, pull_request=None):
1082 def __init__(self, user=None, pull_request=None):
1083 self.user = user
1083 self.user = user
1084 self.pull_request = pull_request
1084 self.pull_request = pull_request
1085
1085
1086 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1086 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1087 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1087 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1088 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1088 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1089
1089
1090 user = relationship('User')
1090 user = relationship('User')
1091 pull_request = relationship('PullRequest')
1091 pull_request = relationship('PullRequest')
1092
1092
1093
1093
1094 class Notification(Base, BaseModel):
1094 class Notification(Base, BaseModel):
1095 __tablename__ = 'notifications'
1095 __tablename__ = 'notifications'
1096 __table_args__ = (
1096 __table_args__ = (
1097 Index('notification_type_idx', 'type'),
1097 Index('notification_type_idx', 'type'),
1098 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1098 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1099 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1099 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1100 )
1100 )
1101
1101
1102 TYPE_CHANGESET_COMMENT = u'cs_comment'
1102 TYPE_CHANGESET_COMMENT = u'cs_comment'
1103 TYPE_MESSAGE = u'message'
1103 TYPE_MESSAGE = u'message'
1104 TYPE_MENTION = u'mention'
1104 TYPE_MENTION = u'mention'
1105 TYPE_REGISTRATION = u'registration'
1105 TYPE_REGISTRATION = u'registration'
1106 TYPE_PULL_REQUEST = u'pull_request'
1106 TYPE_PULL_REQUEST = u'pull_request'
1107 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1107 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1108
1108
1109 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1109 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1110 subject = Column('subject', Unicode(512), nullable=True)
1110 subject = Column('subject', Unicode(512), nullable=True)
1111 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1111 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1112 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1112 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1113 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1113 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1114 type_ = Column('type', Unicode(256))
1114 type_ = Column('type', Unicode(256))
1115
1115
1116 created_by_user = relationship('User')
1116 created_by_user = relationship('User')
1117 notifications_to_users = relationship('UserNotification', lazy='joined',
1117 notifications_to_users = relationship('UserNotification', lazy='joined',
1118 cascade="all, delete, delete-orphan")
1118 cascade="all, delete, delete-orphan")
1119
1119
1120
1120
1121 class UserNotification(Base, BaseModel):
1121 class UserNotification(Base, BaseModel):
1122 __tablename__ = 'user_to_notification'
1122 __tablename__ = 'user_to_notification'
1123 __table_args__ = (
1123 __table_args__ = (
1124 UniqueConstraint('user_id', 'notification_id'),
1124 UniqueConstraint('user_id', 'notification_id'),
1125 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1125 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1126 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1126 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1127 )
1127 )
1128 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1128 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1129 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1129 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1130 read = Column('read', Boolean, default=False)
1130 read = Column('read', Boolean, default=False)
1131 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1131 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1132
1132
1133 user = relationship('User', lazy="joined")
1133 user = relationship('User', lazy="joined")
1134 notification = relationship('Notification', lazy="joined",
1134 notification = relationship('Notification', lazy="joined",
1135 order_by=lambda: Notification.created_on.desc(),)
1135 order_by=lambda: Notification.created_on.desc(),)
1136
1136
1137
1137
1138 class Gist(Base, BaseModel):
1138 class Gist(Base, BaseModel):
1139 __tablename__ = 'gists'
1139 __tablename__ = 'gists'
1140 __table_args__ = (
1140 __table_args__ = (
1141 Index('g_gist_access_id_idx', 'gist_access_id'),
1141 Index('g_gist_access_id_idx', 'gist_access_id'),
1142 Index('g_created_on_idx', 'created_on'),
1142 Index('g_created_on_idx', 'created_on'),
1143 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1143 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1144 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1144 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1145 )
1145 )
1146 GIST_PUBLIC = u'public'
1146 GIST_PUBLIC = u'public'
1147 GIST_PRIVATE = u'private'
1147 GIST_PRIVATE = u'private'
1148
1148
1149 gist_id = Column('gist_id', Integer(), primary_key=True)
1149 gist_id = Column('gist_id', Integer(), primary_key=True)
1150 gist_access_id = Column('gist_access_id', Unicode(250))
1150 gist_access_id = Column('gist_access_id', Unicode(250))
1151 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1151 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1152 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1152 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1153 gist_expires = Column('gist_expires', Float(53), nullable=False)
1153 gist_expires = Column('gist_expires', Float(53), nullable=False)
1154 gist_type = Column('gist_type', Unicode(128), nullable=False)
1154 gist_type = Column('gist_type', Unicode(128), nullable=False)
1155 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1155 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1156 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1156 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1157
1157
1158 owner = relationship('User')
1158 owner = relationship('User')
1159
1159
1160
1160
1161 class DbMigrateVersion(Base, BaseModel):
1161 class DbMigrateVersion(Base, BaseModel):
1162 __tablename__ = 'db_migrate_version'
1162 __tablename__ = 'db_migrate_version'
1163 __table_args__ = (
1163 __table_args__ = (
1164 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1164 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1165 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1165 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1166 )
1166 )
1167 repository_id = Column('repository_id', String(250), primary_key=True)
1167 repository_id = Column('repository_id', String(250), primary_key=True)
1168 repository_path = Column('repository_path', Text)
1168 repository_path = Column('repository_path', Text)
1169 version = Column('version', Integer)
1169 version = Column('version', Integer)
@@ -1,1170 +1,1170 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 from rhodecode.lib.ext_json import json
46 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.caching_query import FromCache
47 from rhodecode.lib.caching_query import FromCache
48
48
49 from rhodecode.model.meta import Base, Session
49 from rhodecode.model.meta import Base, Session
50
50
51 URL_SEP = '/'
51 URL_SEP = '/'
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 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
58 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59
59
60
60
61 class BaseModel(object):
61 class BaseModel(object):
62 """
62 """
63 Base Model for all classes
63 Base Model for all classes
64 """
64 """
65
65
66 @classmethod
66 @classmethod
67 def _get_keys(cls):
67 def _get_keys(cls):
68 """return column names for this model """
68 """return column names for this model """
69 return class_mapper(cls).c.keys()
69 return class_mapper(cls).c.keys()
70
70
71 def get_dict(self):
71 def get_dict(self):
72 """
72 """
73 return dict with keys and values corresponding
73 return dict with keys and values corresponding
74 to this model data """
74 to this model data """
75
75
76 d = {}
76 d = {}
77 for k in self._get_keys():
77 for k in self._get_keys():
78 d[k] = getattr(self, k)
78 d[k] = getattr(self, k)
79
79
80 # also use __json__() if present to get additional fields
80 # also use __json__() if present to get additional fields
81 _json_attr = getattr(self, '__json__', None)
81 _json_attr = getattr(self, '__json__', None)
82 if _json_attr:
82 if _json_attr:
83 # update with attributes from __json__
83 # update with attributes from __json__
84 if callable(_json_attr):
84 if callable(_json_attr):
85 _json_attr = _json_attr()
85 _json_attr = _json_attr()
86 for k, val in _json_attr.items():
86 for k, val in _json_attr.items():
87 d[k] = val
87 d[k] = val
88 return d
88 return d
89
89
90 def get_appstruct(self):
90 def get_appstruct(self):
91 """return list with keys and values tupples corresponding
91 """return list with keys and values tupples corresponding
92 to this model data """
92 to this model data """
93
93
94 l = []
94 l = []
95 for k in self._get_keys():
95 for k in self._get_keys():
96 l.append((k, getattr(self, k),))
96 l.append((k, getattr(self, k),))
97 return l
97 return l
98
98
99 def populate_obj(self, populate_dict):
99 def populate_obj(self, populate_dict):
100 """populate model with data from given populate_dict"""
100 """populate model with data from given populate_dict"""
101
101
102 for k in self._get_keys():
102 for k in self._get_keys():
103 if k in populate_dict:
103 if k in populate_dict:
104 setattr(self, k, populate_dict[k])
104 setattr(self, k, populate_dict[k])
105
105
106 @classmethod
106 @classmethod
107 def query(cls):
107 def query(cls):
108 return Session().query(cls)
108 return Session().query(cls)
109
109
110 @classmethod
110 @classmethod
111 def get(cls, id_):
111 def get(cls, id_):
112 if id_:
112 if id_:
113 return cls.query().get(id_)
113 return cls.query().get(id_)
114
114
115 @classmethod
115 @classmethod
116 def get_or_404(cls, id_):
116 def get_or_404(cls, id_):
117 try:
117 try:
118 id_ = int(id_)
118 id_ = int(id_)
119 except (TypeError, ValueError):
119 except (TypeError, ValueError):
120 raise HTTPNotFound
120 raise HTTPNotFound
121
121
122 res = cls.query().get(id_)
122 res = cls.query().get(id_)
123 if not res:
123 if not res:
124 raise HTTPNotFound
124 raise HTTPNotFound
125 return res
125 return res
126
126
127 @classmethod
127 @classmethod
128 def getAll(cls):
128 def getAll(cls):
129 # deprecated and left for backward compatibility
129 # deprecated and left for backward compatibility
130 return cls.get_all()
130 return cls.get_all()
131
131
132 @classmethod
132 @classmethod
133 def get_all(cls):
133 def get_all(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
140
141 def __repr__(self):
141 def __repr__(self):
142 if hasattr(self, '__unicode__'):
142 if hasattr(self, '__unicode__'):
143 # python repr needs to return str
143 # python repr needs to return str
144 try:
144 try:
145 return safe_str(self.__unicode__())
145 return safe_str(self.__unicode__())
146 except UnicodeDecodeError:
146 except UnicodeDecodeError:
147 pass
147 pass
148 return '<DB:%s>' % (self.__class__.__name__)
148 return '<DB:%s>' % (self.__class__.__name__)
149
149
150
150
151 class RhodeCodeSetting(Base, BaseModel):
151 class RhodeCodeSetting(Base, BaseModel):
152 SETTINGS_TYPES = {
152 SETTINGS_TYPES = {
153 'str': safe_str,
153 'str': safe_str,
154 'int': safe_int,
154 'int': safe_int,
155 'unicode': safe_str,
155 'unicode': safe_str,
156 'bool': str2bool,
156 'bool': str2bool,
157 'list': functools.partial(aslist, sep=',')
157 'list': functools.partial(aslist, sep=',')
158 }
158 }
159 __tablename__ = 'rhodecode_settings'
159 __tablename__ = 'rhodecode_settings'
160 __table_args__ = (
160 __table_args__ = (
161 UniqueConstraint('app_settings_name'),
161 UniqueConstraint('app_settings_name'),
162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
163 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
163 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
164 )
164 )
165 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
165 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
166 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
166 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
167 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
167 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
168 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
168 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
169
169
170 def __init__(self, key='', val='', type='unicode'):
170 def __init__(self, key='', val='', type='unicode'):
171 self.app_settings_name = key
171 self.app_settings_name = key
172 self.app_settings_value = val
172 self.app_settings_value = val
173 self.app_settings_type = type
173 self.app_settings_type = type
174
174
175 @validates('_app_settings_value')
175 @validates('_app_settings_value')
176 def validate_settings_value(self, key, val):
176 def validate_settings_value(self, key, val):
177 assert type(val) == str
177 assert type(val) == str
178 return val
178 return val
179
179
180 @hybrid_property
180 @hybrid_property
181 def app_settings_value(self):
181 def app_settings_value(self):
182 v = self._app_settings_value
182 v = self._app_settings_value
183 _type = self.app_settings_type
183 _type = self.app_settings_type
184 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
184 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
185 return converter(v)
185 return converter(v)
186
186
187 @app_settings_value.setter
187 @app_settings_value.setter
188 def app_settings_value(self, val):
188 def app_settings_value(self, val):
189 """
189 """
190 Setter that will always make sure we use unicode in app_settings_value
190 Setter that will always make sure we use unicode in app_settings_value
191
191
192 :param val:
192 :param val:
193 """
193 """
194 self._app_settings_value = safe_str(val)
194 self._app_settings_value = safe_str(val)
195
195
196 @hybrid_property
196 @hybrid_property
197 def app_settings_type(self):
197 def app_settings_type(self):
198 return self._app_settings_type
198 return self._app_settings_type
199
199
200 @app_settings_type.setter
200 @app_settings_type.setter
201 def app_settings_type(self, val):
201 def app_settings_type(self, val):
202 if val not in self.SETTINGS_TYPES:
202 if val not in self.SETTINGS_TYPES:
203 raise Exception('type must be one of %s got %s'
203 raise Exception('type must be one of %s got %s'
204 % (self.SETTINGS_TYPES.keys(), val))
204 % (self.SETTINGS_TYPES.keys(), val))
205 self._app_settings_type = val
205 self._app_settings_type = val
206
206
207 def __unicode__(self):
207 def __unicode__(self):
208 return u"<%s('%s:%s[%s]')>" % (
208 return u"<%s('%s:%s[%s]')>" % (
209 self.__class__.__name__,
209 self.__class__.__name__,
210 self.app_settings_name, self.app_settings_value, self.app_settings_type
210 self.app_settings_name, self.app_settings_value, self.app_settings_type
211 )
211 )
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__ = (
216 __table_args__ = (
217 UniqueConstraint('ui_key'),
217 UniqueConstraint('ui_key'),
218 {'extend_existing': True, 'mysql_engine': 'InnoDB',
218 {'extend_existing': True, 'mysql_engine': 'InnoDB',
219 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
219 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
220 )
220 )
221
221
222 HOOK_REPO_SIZE = 'changegroup.repo_size'
222 HOOK_REPO_SIZE = 'changegroup.repo_size'
223 HOOK_PUSH = 'changegroup.push_logger'
223 HOOK_PUSH = 'changegroup.push_logger'
224 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
224 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
225 HOOK_PULL = 'outgoing.pull_logger'
225 HOOK_PULL = 'outgoing.pull_logger'
226 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
226 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
227
227
228 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
228 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
229 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
229 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
230 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
230 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
231 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
231 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
232 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
232 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
233
233
234
234
235
235
236 class User(Base, BaseModel):
236 class User(Base, BaseModel):
237 __tablename__ = 'users'
237 __tablename__ = 'users'
238 __table_args__ = (
238 __table_args__ = (
239 UniqueConstraint('username'), UniqueConstraint('email'),
239 UniqueConstraint('username'), UniqueConstraint('email'),
240 Index('u_username_idx', 'username'),
240 Index('u_username_idx', 'username'),
241 Index('u_email_idx', 'email'),
241 Index('u_email_idx', 'email'),
242 {'extend_existing': True, 'mysql_engine': 'InnoDB',
242 {'extend_existing': True, 'mysql_engine': 'InnoDB',
243 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
243 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
244 )
244 )
245 DEFAULT_USER = 'default'
245 DEFAULT_USER = 'default'
246
246
247 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
247 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
248 username = Column("username", String(255), nullable=True, unique=None, default=None)
248 username = Column("username", String(255), nullable=True, unique=None, default=None)
249 password = Column("password", String(255), nullable=True, unique=None, default=None)
249 password = Column("password", String(255), nullable=True, unique=None, default=None)
250 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
250 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
251 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
251 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
252 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
252 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
253 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
253 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
254 _email = Column("email", String(255), nullable=True, unique=None, default=None)
254 _email = Column("email", String(255), nullable=True, unique=None, default=None)
255 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
255 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
256 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
256 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
257 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
257 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
258 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
258 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
259 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
259 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
260 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
260 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
261
261
262 user_log = relationship('UserLog')
262 user_log = relationship('UserLog')
263 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
263 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
264
264
265 repositories = relationship('Repository')
265 repositories = relationship('Repository')
266 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
266 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
267 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
267 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
268
268
269 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
269 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
270 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
270 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
271
271
272 group_member = relationship('UserGroupMember', cascade='all')
272 group_member = relationship('UserGroupMember', cascade='all')
273
273
274 notifications = relationship('UserNotification', cascade='all')
274 notifications = relationship('UserNotification', cascade='all')
275 # notifications assigned to this user
275 # notifications assigned to this user
276 user_created_notifications = relationship('Notification', cascade='all')
276 user_created_notifications = relationship('Notification', cascade='all')
277 # comments created by this user
277 # comments created by this user
278 user_comments = relationship('ChangesetComment', cascade='all')
278 user_comments = relationship('ChangesetComment', cascade='all')
279 user_emails = relationship('UserEmailMap', cascade='all')
279 user_emails = relationship('UserEmailMap', cascade='all')
280
280
281 @hybrid_property
281 @hybrid_property
282 def email(self):
282 def email(self):
283 return self._email
283 return self._email
284
284
285 @email.setter
285 @email.setter
286 def email(self, val):
286 def email(self, val):
287 self._email = val.lower() if val else None
287 self._email = val.lower() if val else None
288
288
289 @property
289 @property
290 def firstname(self):
290 def firstname(self):
291 # alias for future
291 # alias for future
292 return self.name
292 return self.name
293
293
294 @property
294 @property
295 def username_and_name(self):
295 def username_and_name(self):
296 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
296 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
297
297
298 @property
298 @property
299 def full_name(self):
299 def full_name(self):
300 return '%s %s' % (self.firstname, self.lastname)
300 return '%s %s' % (self.firstname, self.lastname)
301
301
302 @property
302 @property
303 def full_contact(self):
303 def full_contact(self):
304 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
304 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
305
305
306 @property
306 @property
307 def short_contact(self):
307 def short_contact(self):
308 return '%s %s' % (self.firstname, self.lastname)
308 return '%s %s' % (self.firstname, self.lastname)
309
309
310 @property
310 @property
311 def is_admin(self):
311 def is_admin(self):
312 return self.admin
312 return self.admin
313
313
314 @classmethod
314 @classmethod
315 def get_by_username(cls, username, case_insensitive=False, cache=False):
315 def get_by_username(cls, username, case_insensitive=False, cache=False):
316 if case_insensitive:
316 if case_insensitive:
317 q = cls.query().filter(cls.username.ilike(username))
317 q = cls.query().filter(cls.username.ilike(username))
318 else:
318 else:
319 q = cls.query().filter(cls.username == username)
319 q = cls.query().filter(cls.username == username)
320
320
321 if cache:
321 if cache:
322 q = q.options(FromCache(
322 q = q.options(FromCache(
323 "sql_cache_short",
323 "sql_cache_short",
324 "get_user_%s" % _hash_key(username)
324 "get_user_%s" % _hash_key(username)
325 )
325 )
326 )
326 )
327 return q.scalar()
327 return q.scalar()
328
328
329 @classmethod
329 @classmethod
330 def get_by_auth_token(cls, auth_token, cache=False):
330 def get_by_auth_token(cls, auth_token, cache=False):
331 q = cls.query().filter(cls.api_key == auth_token)
331 q = cls.query().filter(cls.api_key == auth_token)
332
332
333 if cache:
333 if cache:
334 q = q.options(FromCache("sql_cache_short",
334 q = q.options(FromCache("sql_cache_short",
335 "get_auth_token_%s" % auth_token))
335 "get_auth_token_%s" % auth_token))
336 return q.scalar()
336 return q.scalar()
337
337
338 @classmethod
338 @classmethod
339 def get_by_email(cls, email, case_insensitive=False, cache=False):
339 def get_by_email(cls, email, case_insensitive=False, cache=False):
340 if case_insensitive:
340 if case_insensitive:
341 q = cls.query().filter(cls.email.ilike(email))
341 q = cls.query().filter(cls.email.ilike(email))
342 else:
342 else:
343 q = cls.query().filter(cls.email == email)
343 q = cls.query().filter(cls.email == email)
344
344
345 if cache:
345 if cache:
346 q = q.options(FromCache("sql_cache_short",
346 q = q.options(FromCache("sql_cache_short",
347 "get_email_key_%s" % email))
347 "get_email_key_%s" % email))
348
348
349 ret = q.scalar()
349 ret = q.scalar()
350 if ret is None:
350 if ret is None:
351 q = UserEmailMap.query()
351 q = UserEmailMap.query()
352 # try fetching in alternate email map
352 # try fetching in alternate email map
353 if case_insensitive:
353 if case_insensitive:
354 q = q.filter(UserEmailMap.email.ilike(email))
354 q = q.filter(UserEmailMap.email.ilike(email))
355 else:
355 else:
356 q = q.filter(UserEmailMap.email == email)
356 q = q.filter(UserEmailMap.email == email)
357 q = q.options(joinedload(UserEmailMap.user))
357 q = q.options(joinedload(UserEmailMap.user))
358 if cache:
358 if cache:
359 q = q.options(FromCache("sql_cache_short",
359 q = q.options(FromCache("sql_cache_short",
360 "get_email_map_key_%s" % email))
360 "get_email_map_key_%s" % email))
361 ret = getattr(q.scalar(), 'user', None)
361 ret = getattr(q.scalar(), 'user', None)
362
362
363 return ret
363 return ret
364
364
365 @classmethod
365 @classmethod
366 def get_first_admin(cls):
366 def get_first_admin(cls):
367 user = User.query().filter(User.admin == True).first()
367 user = User.query().filter(User.admin == True).first()
368 if user is None:
368 if user is None:
369 raise Exception('Missing administrative account!')
369 raise Exception('Missing administrative account!')
370 return user
370 return user
371
371
372 @classmethod
372 @classmethod
373 def get_default_user(cls, cache=False):
373 def get_default_user(cls, cache=False):
374 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
374 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
375 if user is None:
375 if user is None:
376 raise Exception('Missing default account!')
376 raise Exception('Missing default account!')
377 return user
377 return user
378
378
379
379
380
380
381
381
382 class UserEmailMap(Base, BaseModel):
382 class UserEmailMap(Base, BaseModel):
383 __tablename__ = 'user_email_map'
383 __tablename__ = 'user_email_map'
384 __table_args__ = (
384 __table_args__ = (
385 Index('uem_email_idx', 'email'),
385 Index('uem_email_idx', 'email'),
386 UniqueConstraint('email'),
386 UniqueConstraint('email'),
387 {'extend_existing': True, 'mysql_engine': 'InnoDB',
387 {'extend_existing': True, 'mysql_engine': 'InnoDB',
388 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
388 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
389 )
389 )
390
390
391
391
392 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
392 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
393 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
393 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
394 _email = Column("email", String(255), nullable=True, unique=False, default=None)
394 _email = Column("email", String(255), nullable=True, unique=False, default=None)
395 user = relationship('User', lazy='joined')
395 user = relationship('User', lazy='joined')
396
396
397 @validates('_email')
397 @validates('_email')
398 def validate_email(self, key, email):
398 def validate_email(self, key, email):
399 # check if this email is not main one
399 # check if this email is not main one
400 main_email = Session().query(User).filter(User.email == email).scalar()
400 main_email = Session().query(User).filter(User.email == email).scalar()
401 if main_email is not None:
401 if main_email is not None:
402 raise AttributeError('email %s is present is user table' % email)
402 raise AttributeError('email %s is present is user table' % email)
403 return email
403 return email
404
404
405 @hybrid_property
405 @hybrid_property
406 def email(self):
406 def email(self):
407 return self._email
407 return self._email
408
408
409 @email.setter
409 @email.setter
410 def email(self, val):
410 def email(self, val):
411 self._email = val.lower() if val else None
411 self._email = val.lower() if val else None
412
412
413
413
414 class UserIpMap(Base, BaseModel):
414 class UserIpMap(Base, BaseModel):
415 __tablename__ = 'user_ip_map'
415 __tablename__ = 'user_ip_map'
416 __table_args__ = (
416 __table_args__ = (
417 UniqueConstraint('user_id', 'ip_addr'),
417 UniqueConstraint('user_id', 'ip_addr'),
418 {'extend_existing': True, 'mysql_engine': 'InnoDB',
418 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
419 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
420 )
420 )
421
421
422
422
423 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
423 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
424 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
425 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
425 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
426 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
426 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
427 user = relationship('User', lazy='joined')
427 user = relationship('User', lazy='joined')
428
428
429
429
430 class UserLog(Base, BaseModel):
430 class UserLog(Base, BaseModel):
431 __tablename__ = 'user_logs'
431 __tablename__ = 'user_logs'
432 __table_args__ = (
432 __table_args__ = (
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
434 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
434 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
435 )
435 )
436 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
436 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
438 username = Column("username", String(255), nullable=True, unique=None, default=None)
438 username = Column("username", String(255), nullable=True, unique=None, default=None)
439 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
439 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
440 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
440 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
441 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
441 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
442 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
442 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
443 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
443 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
444
444
445 def __unicode__(self):
445 def __unicode__(self):
446 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
446 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
447 self.repository_name,
447 self.repository_name,
448 self.action)
448 self.action)
449
449
450 user = relationship('User')
450 user = relationship('User')
451 repository = relationship('Repository', cascade='')
451 repository = relationship('Repository', cascade='')
452
452
453
453
454 class UserGroup(Base, BaseModel):
454 class UserGroup(Base, BaseModel):
455 __tablename__ = 'users_groups'
455 __tablename__ = 'users_groups'
456 __table_args__ = (
456 __table_args__ = (
457 {'extend_existing': True, 'mysql_engine': 'InnoDB',
457 {'extend_existing': True, 'mysql_engine': 'InnoDB',
458 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
458 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
459 )
459 )
460
460
461 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
461 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
462 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
462 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
463 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
463 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
464 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
464 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
465 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
465 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
468
468
469 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
469 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
470 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
470 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
471 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
471 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
472 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
472 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
473 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
473 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
474 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
474 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
475
475
476 user = relationship('User')
476 user = relationship('User')
477
477
478 def __unicode__(self):
478 def __unicode__(self):
479 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
479 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
480 self.users_group_id,
480 self.users_group_id,
481 self.users_group_name)
481 self.users_group_name)
482
482
483 @classmethod
483 @classmethod
484 def get_by_group_name(cls, group_name, cache=False,
484 def get_by_group_name(cls, group_name, cache=False,
485 case_insensitive=False):
485 case_insensitive=False):
486 if case_insensitive:
486 if case_insensitive:
487 q = cls.query().filter(cls.users_group_name.ilike(group_name))
487 q = cls.query().filter(cls.users_group_name.ilike(group_name))
488 else:
488 else:
489 q = cls.query().filter(cls.users_group_name == group_name)
489 q = cls.query().filter(cls.users_group_name == group_name)
490 if cache:
490 if cache:
491 q = q.options(FromCache(
491 q = q.options(FromCache(
492 "sql_cache_short",
492 "sql_cache_short",
493 "get_user_%s" % _hash_key(group_name)
493 "get_user_%s" % _hash_key(group_name)
494 )
494 )
495 )
495 )
496 return q.scalar()
496 return q.scalar()
497
497
498 @classmethod
498 @classmethod
499 def get(cls, user_group_id, cache=False):
499 def get(cls, user_group_id, cache=False):
500 user_group = cls.query()
500 user_group = cls.query()
501 if cache:
501 if cache:
502 user_group = user_group.options(FromCache("sql_cache_short",
502 user_group = user_group.options(FromCache("sql_cache_short",
503 "get_users_group_%s" % user_group_id))
503 "get_users_group_%s" % user_group_id))
504 return user_group.get(user_group_id)
504 return user_group.get(user_group_id)
505
505
506
506
507 class UserGroupMember(Base, BaseModel):
507 class UserGroupMember(Base, BaseModel):
508 __tablename__ = 'users_groups_members'
508 __tablename__ = 'users_groups_members'
509 __table_args__ = (
509 __table_args__ = (
510 {'extend_existing': True, 'mysql_engine': 'InnoDB',
510 {'extend_existing': True, 'mysql_engine': 'InnoDB',
511 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
511 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
512 )
512 )
513
513
514 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
514 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
515 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
515 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
516 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
516 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
517
517
518 user = relationship('User', lazy='joined')
518 user = relationship('User', lazy='joined')
519 users_group = relationship('UserGroup')
519 users_group = relationship('UserGroup')
520
520
521 def __init__(self, gr_id='', u_id=''):
521 def __init__(self, gr_id='', u_id=''):
522 self.users_group_id = gr_id
522 self.users_group_id = gr_id
523 self.user_id = u_id
523 self.user_id = u_id
524
524
525
525
526 class RepositoryField(Base, BaseModel):
526 class RepositoryField(Base, BaseModel):
527 __tablename__ = 'repositories_fields'
527 __tablename__ = 'repositories_fields'
528 __table_args__ = (
528 __table_args__ = (
529 UniqueConstraint('repository_id', 'field_key'), # no-multi field
529 UniqueConstraint('repository_id', 'field_key'), # no-multi field
530 {'extend_existing': True, 'mysql_engine': 'InnoDB',
530 {'extend_existing': True, 'mysql_engine': 'InnoDB',
531 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
531 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
532 )
532 )
533 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
533 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
534
534
535 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
535 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
536 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
536 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
537 field_key = Column("field_key", String(250))
537 field_key = Column("field_key", String(250))
538 field_label = Column("field_label", String(1024), nullable=False)
538 field_label = Column("field_label", String(1024), nullable=False)
539 field_value = Column("field_value", String(10000), nullable=False)
539 field_value = Column("field_value", String(10000), nullable=False)
540 field_desc = Column("field_desc", String(1024), nullable=False)
540 field_desc = Column("field_desc", String(1024), nullable=False)
541 field_type = Column("field_type", String(256), nullable=False, unique=None)
541 field_type = Column("field_type", String(256), nullable=False, unique=None)
542 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
542 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
543
543
544 repository = relationship('Repository')
544 repository = relationship('Repository')
545
545
546 @classmethod
546 @classmethod
547 def get_by_key_name(cls, key, repo):
547 def get_by_key_name(cls, key, repo):
548 row = cls.query()\
548 row = cls.query()\
549 .filter(cls.repository == repo)\
549 .filter(cls.repository == repo)\
550 .filter(cls.field_key == key).scalar()
550 .filter(cls.field_key == key).scalar()
551 return row
551 return row
552
552
553
553
554 class Repository(Base, BaseModel):
554 class Repository(Base, BaseModel):
555 __tablename__ = 'repositories'
555 __tablename__ = 'repositories'
556 __table_args__ = (
556 __table_args__ = (
557 UniqueConstraint('repo_name'),
557 UniqueConstraint('repo_name'),
558 Index('r_repo_name_idx', 'repo_name'),
558 Index('r_repo_name_idx', 'repo_name'),
559 {'extend_existing': True, 'mysql_engine': 'InnoDB',
559 {'extend_existing': True, 'mysql_engine': 'InnoDB',
560 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
560 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
561 )
561 )
562
562
563 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
563 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
564 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
564 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
565 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
565 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
566 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
566 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
567 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
567 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
568 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
568 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
569 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
569 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
570 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
570 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
571 description = Column("description", String(10000), nullable=True, unique=None, default=None)
571 description = Column("description", String(10000), nullable=True, unique=None, default=None)
572 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
572 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
573 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
573 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
574 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
574 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
575 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
575 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
576 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
576 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
577 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
577 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
578
578
579 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
579 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
580 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
580 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
581
581
582 user = relationship('User')
582 user = relationship('User')
583 fork = relationship('Repository', remote_side=repo_id)
583 fork = relationship('Repository', remote_side=repo_id)
584 group = relationship('RepoGroup')
584 group = relationship('RepoGroup')
585 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
585 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
586 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
586 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
587 stats = relationship('Statistics', cascade='all', uselist=False)
587 stats = relationship('Statistics', cascade='all', uselist=False)
588
588
589 followers = relationship('UserFollowing',
589 followers = relationship('UserFollowing',
590 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
590 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
591 cascade='all')
591 cascade='all')
592 extra_fields = relationship('RepositoryField',
592 extra_fields = relationship('RepositoryField',
593 cascade="all, delete, delete-orphan")
593 cascade="all, delete, delete-orphan")
594
594
595 logs = relationship('UserLog')
595 logs = relationship('UserLog')
596 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
596 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
597
597
598 pull_requests_org = relationship('PullRequest',
598 pull_requests_org = relationship('PullRequest',
599 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
599 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
600 cascade="all, delete, delete-orphan")
600 cascade="all, delete, delete-orphan")
601
601
602 pull_requests_other = relationship('PullRequest',
602 pull_requests_other = relationship('PullRequest',
603 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
603 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
604 cascade="all, delete, delete-orphan")
604 cascade="all, delete, delete-orphan")
605
605
606 def __unicode__(self):
606 def __unicode__(self):
607 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
607 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
608 safe_str(self.repo_name))
608 safe_str(self.repo_name))
609
609
610 @classmethod
610 @classmethod
611 def get_by_repo_name(cls, repo_name):
611 def get_by_repo_name(cls, repo_name):
612 q = Session().query(cls).filter(cls.repo_name == repo_name)
612 q = Session().query(cls).filter(cls.repo_name == repo_name)
613 q = q.options(joinedload(Repository.fork))\
613 q = q.options(joinedload(Repository.fork))\
614 .options(joinedload(Repository.user))\
614 .options(joinedload(Repository.user))\
615 .options(joinedload(Repository.group))
615 .options(joinedload(Repository.group))
616 return q.scalar()
616 return q.scalar()
617
617
618
618
619 class RepoGroup(Base, BaseModel):
619 class RepoGroup(Base, BaseModel):
620 __tablename__ = 'groups'
620 __tablename__ = 'groups'
621 __table_args__ = (
621 __table_args__ = (
622 UniqueConstraint('group_name', 'group_parent_id'),
622 UniqueConstraint('group_name', 'group_parent_id'),
623 {'extend_existing': True, 'mysql_engine': 'InnoDB',
623 {'extend_existing': True, 'mysql_engine': 'InnoDB',
624 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
624 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
625 )
625 )
626
626
627
627
628 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
628 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
629 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
629 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
630 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
630 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
631 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
631 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
632 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
632 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
633 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
633 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
634 #TODO: create this field in migrations
634 #TODO: create this field in migrations
635 #created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
635 #created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
636
636
637 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
637 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
638 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
638 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
639 parent_group = relationship('RepoGroup', remote_side=group_id)
639 parent_group = relationship('RepoGroup', remote_side=group_id)
640 user = relationship('User')
640 user = relationship('User')
641
641
642 def __init__(self, group_name='', parent_group=None):
642 def __init__(self, group_name='', parent_group=None):
643 self.group_name = group_name
643 self.group_name = group_name
644 self.parent_group = parent_group
644 self.parent_group = parent_group
645
645
646 def __unicode__(self):
646 def __unicode__(self):
647 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
647 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
648 self.group_name)
648 self.group_name)
649
649
650 @classmethod
650 @classmethod
651 def url_sep(cls):
651 def url_sep(cls):
652 return URL_SEP
652 return URL_SEP
653
653
654 @classmethod
654 @classmethod
655 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
655 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
656 if case_insensitive:
656 if case_insensitive:
657 gr = cls.query()\
657 gr = cls.query()\
658 .filter(cls.group_name.ilike(group_name))
658 .filter(cls.group_name.ilike(group_name))
659 else:
659 else:
660 gr = cls.query()\
660 gr = cls.query()\
661 .filter(cls.group_name == group_name)
661 .filter(cls.group_name == group_name)
662 if cache:
662 if cache:
663 gr = gr.options(FromCache(
663 gr = gr.options(FromCache(
664 "sql_cache_short",
664 "sql_cache_short",
665 "get_group_%s" % _hash_key(group_name)
665 "get_group_%s" % _hash_key(group_name)
666 )
666 )
667 )
667 )
668 return gr.scalar()
668 return gr.scalar()
669
669
670
670
671 class Permission(Base, BaseModel):
671 class Permission(Base, BaseModel):
672 __tablename__ = 'permissions'
672 __tablename__ = 'permissions'
673 __table_args__ = (
673 __table_args__ = (
674 Index('p_perm_name_idx', 'permission_name'),
674 Index('p_perm_name_idx', 'permission_name'),
675 {'extend_existing': True, 'mysql_engine': 'InnoDB',
675 {'extend_existing': True, 'mysql_engine': 'InnoDB',
676 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
676 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
677 )
677 )
678 PERMS = [
678 PERMS = [
679 ('hg.admin', _('RhodeCode Administrator')),
679 ('hg.admin', _('RhodeCode Administrator')),
680
680
681 ('repository.none', _('Repository no access')),
681 ('repository.none', _('Repository no access')),
682 ('repository.read', _('Repository read access')),
682 ('repository.read', _('Repository read access')),
683 ('repository.write', _('Repository write access')),
683 ('repository.write', _('Repository write access')),
684 ('repository.admin', _('Repository admin access')),
684 ('repository.admin', _('Repository admin access')),
685
685
686 ('group.none', _('Repository group no access')),
686 ('group.none', _('Repository group no access')),
687 ('group.read', _('Repository group read access')),
687 ('group.read', _('Repository group read access')),
688 ('group.write', _('Repository group write access')),
688 ('group.write', _('Repository group write access')),
689 ('group.admin', _('Repository group admin access')),
689 ('group.admin', _('Repository group admin access')),
690
690
691 ('usergroup.none', _('User group no access')),
691 ('usergroup.none', _('User group no access')),
692 ('usergroup.read', _('User group read access')),
692 ('usergroup.read', _('User group read access')),
693 ('usergroup.write', _('User group write access')),
693 ('usergroup.write', _('User group write access')),
694 ('usergroup.admin', _('User group admin access')),
694 ('usergroup.admin', _('User group admin access')),
695
695
696 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
696 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
697 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
697 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
698
698
699 ('hg.usergroup.create.false', _('User Group creation disabled')),
699 ('hg.usergroup.create.false', _('User Group creation disabled')),
700 ('hg.usergroup.create.true', _('User Group creation enabled')),
700 ('hg.usergroup.create.true', _('User Group creation enabled')),
701
701
702 ('hg.create.none', _('Repository creation disabled')),
702 ('hg.create.none', _('Repository creation disabled')),
703 ('hg.create.repository', _('Repository creation enabled')),
703 ('hg.create.repository', _('Repository creation enabled')),
704
704
705 ('hg.fork.none', _('Repository forking disabled')),
705 ('hg.fork.none', _('Repository forking disabled')),
706 ('hg.fork.repository', _('Repository forking enabled')),
706 ('hg.fork.repository', _('Repository forking enabled')),
707
707
708 ('hg.register.none', _('Registration disabled')),
708 ('hg.register.none', _('Registration disabled')),
709 ('hg.register.manual_activate', _('User Registration with manual account activation')),
709 ('hg.register.manual_activate', _('User Registration with manual account activation')),
710 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
710 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
711
711
712 ('hg.extern_activate.manual', _('Manual activation of external account')),
712 ('hg.extern_activate.manual', _('Manual activation of external account')),
713 ('hg.extern_activate.auto', _('Automatic activation of external account')),
713 ('hg.extern_activate.auto', _('Automatic activation of external account')),
714
714
715 ]
715 ]
716
716
717 #definition of system default permissions for DEFAULT user
717 #definition of system default permissions for DEFAULT user
718 DEFAULT_USER_PERMISSIONS = [
718 DEFAULT_USER_PERMISSIONS = [
719 'repository.read',
719 'repository.read',
720 'group.read',
720 'group.read',
721 'usergroup.read',
721 'usergroup.read',
722 'hg.create.repository',
722 'hg.create.repository',
723 'hg.fork.repository',
723 'hg.fork.repository',
724 'hg.register.manual_activate',
724 'hg.register.manual_activate',
725 'hg.extern_activate.auto',
725 'hg.extern_activate.auto',
726 ]
726 ]
727
727
728 # defines which permissions are more important higher the more important
728 # defines which permissions are more important higher the more important
729 # Weight defines which permissions are more important.
729 # Weight defines which permissions are more important.
730 # The higher number the more important.
730 # The higher number the more important.
731 PERM_WEIGHTS = {
731 PERM_WEIGHTS = {
732 'repository.none': 0,
732 'repository.none': 0,
733 'repository.read': 1,
733 'repository.read': 1,
734 'repository.write': 3,
734 'repository.write': 3,
735 'repository.admin': 4,
735 'repository.admin': 4,
736
736
737 'group.none': 0,
737 'group.none': 0,
738 'group.read': 1,
738 'group.read': 1,
739 'group.write': 3,
739 'group.write': 3,
740 'group.admin': 4,
740 'group.admin': 4,
741
741
742 'usergroup.none': 0,
742 'usergroup.none': 0,
743 'usergroup.read': 1,
743 'usergroup.read': 1,
744 'usergroup.write': 3,
744 'usergroup.write': 3,
745 'usergroup.admin': 4,
745 'usergroup.admin': 4,
746 'hg.repogroup.create.false': 0,
746 'hg.repogroup.create.false': 0,
747 'hg.repogroup.create.true': 1,
747 'hg.repogroup.create.true': 1,
748
748
749 'hg.usergroup.create.false': 0,
749 'hg.usergroup.create.false': 0,
750 'hg.usergroup.create.true': 1,
750 'hg.usergroup.create.true': 1,
751
751
752 'hg.fork.none': 0,
752 'hg.fork.none': 0,
753 'hg.fork.repository': 1,
753 'hg.fork.repository': 1,
754 'hg.create.none': 0,
754 'hg.create.none': 0,
755 'hg.create.repository': 1
755 'hg.create.repository': 1
756 }
756 }
757
757
758 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
758 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
759 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
759 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
760 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
760 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
761
761
762 def __unicode__(self):
762 def __unicode__(self):
763 return u"<%s('%s:%s')>" % (
763 return u"<%s('%s:%s')>" % (
764 self.__class__.__name__, self.permission_id, self.permission_name
764 self.__class__.__name__, self.permission_id, self.permission_name
765 )
765 )
766
766
767 @classmethod
767 @classmethod
768 def get_by_key(cls, key):
768 def get_by_key(cls, key):
769 return cls.query().filter(cls.permission_name == key).scalar()
769 return cls.query().filter(cls.permission_name == key).scalar()
770
770
771
771
772 class UserRepoToPerm(Base, BaseModel):
772 class UserRepoToPerm(Base, BaseModel):
773 __tablename__ = 'repo_to_perm'
773 __tablename__ = 'repo_to_perm'
774 __table_args__ = (
774 __table_args__ = (
775 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
775 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
776 {'extend_existing': True, 'mysql_engine': 'InnoDB',
776 {'extend_existing': True, 'mysql_engine': 'InnoDB',
777 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
777 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
778 )
778 )
779 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
779 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
780 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
780 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
781 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
781 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
782 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
782 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
783
783
784 user = relationship('User')
784 user = relationship('User')
785 repository = relationship('Repository')
785 repository = relationship('Repository')
786 permission = relationship('Permission')
786 permission = relationship('Permission')
787
787
788 def __unicode__(self):
788 def __unicode__(self):
789 return u'<%s => %s >' % (self.user, self.repository)
789 return u'<%s => %s >' % (self.user, self.repository)
790
790
791
791
792 class UserUserGroupToPerm(Base, BaseModel):
792 class UserUserGroupToPerm(Base, BaseModel):
793 __tablename__ = 'user_user_group_to_perm'
793 __tablename__ = 'user_user_group_to_perm'
794 __table_args__ = (
794 __table_args__ = (
795 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
795 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
796 {'extend_existing': True, 'mysql_engine': 'InnoDB',
796 {'extend_existing': True, 'mysql_engine': 'InnoDB',
797 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
797 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
798 )
798 )
799 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
799 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
800 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
800 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
801 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
801 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
802 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
802 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
803
803
804 user = relationship('User')
804 user = relationship('User')
805 user_group = relationship('UserGroup')
805 user_group = relationship('UserGroup')
806 permission = relationship('Permission')
806 permission = relationship('Permission')
807
807
808 def __unicode__(self):
808 def __unicode__(self):
809 return u'<%s => %s >' % (self.user, self.user_group)
809 return u'<%s => %s >' % (self.user, self.user_group)
810
810
811
811
812 class UserToPerm(Base, BaseModel):
812 class UserToPerm(Base, BaseModel):
813 __tablename__ = 'user_to_perm'
813 __tablename__ = 'user_to_perm'
814 __table_args__ = (
814 __table_args__ = (
815 UniqueConstraint('user_id', 'permission_id'),
815 UniqueConstraint('user_id', 'permission_id'),
816 {'extend_existing': True, 'mysql_engine': 'InnoDB',
816 {'extend_existing': True, 'mysql_engine': 'InnoDB',
817 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
817 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
818 )
818 )
819 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
819 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
820 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
820 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
821 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
821 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
822
822
823 user = relationship('User')
823 user = relationship('User')
824 permission = relationship('Permission', lazy='joined')
824 permission = relationship('Permission', lazy='joined')
825
825
826 def __unicode__(self):
826 def __unicode__(self):
827 return u'<%s => %s >' % (self.user, self.permission)
827 return u'<%s => %s >' % (self.user, self.permission)
828
828
829
829
830 class UserGroupRepoToPerm(Base, BaseModel):
830 class UserGroupRepoToPerm(Base, BaseModel):
831 __tablename__ = 'users_group_repo_to_perm'
831 __tablename__ = 'users_group_repo_to_perm'
832 __table_args__ = (
832 __table_args__ = (
833 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
833 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
834 {'extend_existing': True, 'mysql_engine': 'InnoDB',
834 {'extend_existing': True, 'mysql_engine': 'InnoDB',
835 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
835 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
836 )
836 )
837 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
837 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
838 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
838 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
839 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
839 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
840 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
840 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
841
841
842 users_group = relationship('UserGroup')
842 users_group = relationship('UserGroup')
843 permission = relationship('Permission')
843 permission = relationship('Permission')
844 repository = relationship('Repository')
844 repository = relationship('Repository')
845
845
846 def __unicode__(self):
846 def __unicode__(self):
847 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
847 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
848
848
849
849
850 class UserGroupUserGroupToPerm(Base, BaseModel):
850 class UserGroupUserGroupToPerm(Base, BaseModel):
851 __tablename__ = 'user_group_user_group_to_perm'
851 __tablename__ = 'user_group_user_group_to_perm'
852 __table_args__ = (
852 __table_args__ = (
853 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
853 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
854 CheckConstraint('target_user_group_id != user_group_id'),
854 CheckConstraint('target_user_group_id != user_group_id'),
855 {'extend_existing': True, 'mysql_engine': 'InnoDB',
855 {'extend_existing': True, 'mysql_engine': 'InnoDB',
856 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
856 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
857 )
857 )
858 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
858 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
859 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
859 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
860 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
860 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
861 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
861 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
862
862
863 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
863 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
864 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
864 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
865 permission = relationship('Permission')
865 permission = relationship('Permission')
866
866
867 def __unicode__(self):
867 def __unicode__(self):
868 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
868 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
869
869
870
870
871 class UserGroupToPerm(Base, BaseModel):
871 class UserGroupToPerm(Base, BaseModel):
872 __tablename__ = 'users_group_to_perm'
872 __tablename__ = 'users_group_to_perm'
873 __table_args__ = (
873 __table_args__ = (
874 UniqueConstraint('users_group_id', 'permission_id',),
874 UniqueConstraint('users_group_id', 'permission_id',),
875 {'extend_existing': True, 'mysql_engine': 'InnoDB',
875 {'extend_existing': True, 'mysql_engine': 'InnoDB',
876 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
876 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
877 )
877 )
878 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
878 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
879 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
879 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
880 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
880 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
881
881
882 users_group = relationship('UserGroup')
882 users_group = relationship('UserGroup')
883 permission = relationship('Permission')
883 permission = relationship('Permission')
884
884
885
885
886 class UserRepoGroupToPerm(Base, BaseModel):
886 class UserRepoGroupToPerm(Base, BaseModel):
887 __tablename__ = 'user_repo_group_to_perm'
887 __tablename__ = 'user_repo_group_to_perm'
888 __table_args__ = (
888 __table_args__ = (
889 UniqueConstraint('user_id', 'group_id', 'permission_id'),
889 UniqueConstraint('user_id', 'group_id', 'permission_id'),
890 {'extend_existing': True, 'mysql_engine': 'InnoDB',
890 {'extend_existing': True, 'mysql_engine': 'InnoDB',
891 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
891 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
892 )
892 )
893
893
894 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
894 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
895 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
895 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
896 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
896 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
898
898
899 user = relationship('User')
899 user = relationship('User')
900 group = relationship('RepoGroup')
900 group = relationship('RepoGroup')
901 permission = relationship('Permission')
901 permission = relationship('Permission')
902
902
903
903
904 class UserGroupRepoGroupToPerm(Base, BaseModel):
904 class UserGroupRepoGroupToPerm(Base, BaseModel):
905 __tablename__ = 'users_group_repo_group_to_perm'
905 __tablename__ = 'users_group_repo_group_to_perm'
906 __table_args__ = (
906 __table_args__ = (
907 UniqueConstraint('users_group_id', 'group_id'),
907 UniqueConstraint('users_group_id', 'group_id'),
908 {'extend_existing': True, 'mysql_engine': 'InnoDB',
908 {'extend_existing': True, 'mysql_engine': 'InnoDB',
909 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
909 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
910 )
910 )
911
911
912 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)
912 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)
913 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
913 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
914 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
914 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
915 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
915 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
916
916
917 users_group = relationship('UserGroup')
917 users_group = relationship('UserGroup')
918 permission = relationship('Permission')
918 permission = relationship('Permission')
919 group = relationship('RepoGroup')
919 group = relationship('RepoGroup')
920
920
921
921
922 class Statistics(Base, BaseModel):
922 class Statistics(Base, BaseModel):
923 __tablename__ = 'statistics'
923 __tablename__ = 'statistics'
924 __table_args__ = (
924 __table_args__ = (
925 UniqueConstraint('repository_id'),
925 UniqueConstraint('repository_id'),
926 {'extend_existing': True, 'mysql_engine': 'InnoDB',
926 {'extend_existing': True, 'mysql_engine': 'InnoDB',
927 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
927 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
928 )
928 )
929 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
929 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
930 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
930 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
931 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
931 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
932 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
932 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
933 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
933 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
934 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
934 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
935
935
936 repository = relationship('Repository', single_parent=True)
936 repository = relationship('Repository', single_parent=True)
937
937
938
938
939 class UserFollowing(Base, BaseModel):
939 class UserFollowing(Base, BaseModel):
940 __tablename__ = 'user_followings'
940 __tablename__ = 'user_followings'
941 __table_args__ = (
941 __table_args__ = (
942 UniqueConstraint('user_id', 'follows_repository_id'),
942 UniqueConstraint('user_id', 'follows_repository_id'),
943 UniqueConstraint('user_id', 'follows_user_id'),
943 UniqueConstraint('user_id', 'follows_user_id'),
944 {'extend_existing': True, 'mysql_engine': 'InnoDB',
944 {'extend_existing': True, 'mysql_engine': 'InnoDB',
945 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
945 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
946 )
946 )
947
947
948 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
948 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
949 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
949 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
950 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
950 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
951 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
951 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
952 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
952 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
953
953
954 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
954 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
955
955
956 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
956 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
957 follows_repository = relationship('Repository', order_by='Repository.repo_name')
957 follows_repository = relationship('Repository', order_by='Repository.repo_name')
958
958
959
959
960 class CacheInvalidation(Base, BaseModel):
960 class CacheInvalidation(Base, BaseModel):
961 __tablename__ = 'cache_invalidation'
961 __tablename__ = 'cache_invalidation'
962 __table_args__ = (
962 __table_args__ = (
963 UniqueConstraint('cache_key'),
963 UniqueConstraint('cache_key'),
964 Index('key_idx', 'cache_key'),
964 Index('key_idx', 'cache_key'),
965 {'extend_existing': True, 'mysql_engine': 'InnoDB',
965 {'extend_existing': True, 'mysql_engine': 'InnoDB',
966 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
966 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
967 )
967 )
968 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
968 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
969 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
969 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
970 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
970 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
971 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
971 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
972
972
973 def __init__(self, cache_key, cache_args=''):
973 def __init__(self, cache_key, cache_args=''):
974 self.cache_key = cache_key
974 self.cache_key = cache_key
975 self.cache_args = cache_args
975 self.cache_args = cache_args
976 self.cache_active = False
976 self.cache_active = False
977
977
978
978
979 class ChangesetComment(Base, BaseModel):
979 class ChangesetComment(Base, BaseModel):
980 __tablename__ = 'changeset_comments'
980 __tablename__ = 'changeset_comments'
981 __table_args__ = (
981 __table_args__ = (
982 Index('cc_revision_idx', 'revision'),
982 Index('cc_revision_idx', 'revision'),
983 {'extend_existing': True, 'mysql_engine': 'InnoDB',
983 {'extend_existing': True, 'mysql_engine': 'InnoDB',
984 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
984 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
985 )
985 )
986 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
986 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
987 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
987 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
988 revision = Column('revision', String(40), nullable=True)
988 revision = Column('revision', String(40), nullable=True)
989 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
989 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
990 line_no = Column('line_no', Unicode(10), nullable=True)
990 line_no = Column('line_no', Unicode(10), nullable=True)
991 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
991 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
992 f_path = Column('f_path', Unicode(1000), nullable=True)
992 f_path = Column('f_path', Unicode(1000), nullable=True)
993 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
993 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
994 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
994 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
995 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
995 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
996 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
996 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
997
997
998 author = relationship('User', lazy='joined')
998 author = relationship('User', lazy='joined')
999 repo = relationship('Repository')
999 repo = relationship('Repository')
1000 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1000 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1001 pull_request = relationship('PullRequest', lazy='joined')
1001 pull_request = relationship('PullRequest', lazy='joined')
1002
1002
1003
1003
1004 class ChangesetStatus(Base, BaseModel):
1004 class ChangesetStatus(Base, BaseModel):
1005 __tablename__ = 'changeset_statuses'
1005 __tablename__ = 'changeset_statuses'
1006 __table_args__ = (
1006 __table_args__ = (
1007 Index('cs_revision_idx', 'revision'),
1007 Index('cs_revision_idx', 'revision'),
1008 Index('cs_version_idx', 'version'),
1008 Index('cs_version_idx', 'version'),
1009 UniqueConstraint('repo_id', 'revision', 'version'),
1009 UniqueConstraint('repo_id', 'revision', 'version'),
1010 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1010 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1011 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1011 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1012 )
1012 )
1013 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1013 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1014 STATUS_APPROVED = 'approved'
1014 STATUS_APPROVED = 'approved'
1015 STATUS_REJECTED = 'rejected'
1015 STATUS_REJECTED = 'rejected'
1016 STATUS_UNDER_REVIEW = 'under_review'
1016 STATUS_UNDER_REVIEW = 'under_review'
1017
1017
1018 STATUSES = [
1018 STATUSES = [
1019 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1019 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1020 (STATUS_APPROVED, _("Approved")),
1020 (STATUS_APPROVED, _("Approved")),
1021 (STATUS_REJECTED, _("Rejected")),
1021 (STATUS_REJECTED, _("Rejected")),
1022 (STATUS_UNDER_REVIEW, _("Under Review")),
1022 (STATUS_UNDER_REVIEW, _("Under Review")),
1023 ]
1023 ]
1024
1024
1025 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1025 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1026 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1026 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1027 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1027 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1028 revision = Column('revision', String(40), nullable=False)
1028 revision = Column('revision', String(40), nullable=False)
1029 status = Column('status', String(128), nullable=False, default=DEFAULT)
1029 status = Column('status', String(128), nullable=False, default=DEFAULT)
1030 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1030 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1031 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1031 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1032 version = Column('version', Integer(), nullable=False, default=0)
1032 version = Column('version', Integer(), nullable=False, default=0)
1033 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1033 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1034
1034
1035 author = relationship('User', lazy='joined')
1035 author = relationship('User', lazy='joined')
1036 repo = relationship('Repository')
1036 repo = relationship('Repository')
1037 comment = relationship('ChangesetComment', lazy='joined')
1037 comment = relationship('ChangesetComment', lazy='joined')
1038 pull_request = relationship('PullRequest', lazy='joined')
1038 pull_request = relationship('PullRequest', lazy='joined')
1039
1039
1040
1040
1041
1041
1042 class PullRequest(Base, BaseModel):
1042 class PullRequest(Base, BaseModel):
1043 __tablename__ = 'pull_requests'
1043 __tablename__ = 'pull_requests'
1044 __table_args__ = (
1044 __table_args__ = (
1045 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1045 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1046 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1046 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1047 )
1047 )
1048
1048
1049 STATUS_NEW = u'new'
1049 STATUS_NEW = u'new'
1050 STATUS_OPEN = u'open'
1050 STATUS_OPEN = u'open'
1051 STATUS_CLOSED = u'closed'
1051 STATUS_CLOSED = u'closed'
1052
1052
1053 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1053 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1054 title = Column('title', Unicode(256), nullable=True)
1054 title = Column('title', Unicode(256), nullable=True)
1055 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1055 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1056 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1056 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1057 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1057 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1058 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1058 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1059 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1059 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1060 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1060 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1061 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1061 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1062 org_ref = Column('org_ref', Unicode(256), nullable=False)
1062 org_ref = Column('org_ref', Unicode(256), nullable=False)
1063 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1063 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1064 other_ref = Column('other_ref', Unicode(256), nullable=False)
1064 other_ref = Column('other_ref', Unicode(256), nullable=False)
1065
1065
1066 author = relationship('User', lazy='joined')
1066 author = relationship('User', lazy='joined')
1067 reviewers = relationship('PullRequestReviewers',
1067 reviewers = relationship('PullRequestReviewers',
1068 cascade="all, delete, delete-orphan")
1068 cascade="all, delete, delete-orphan")
1069 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1069 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1070 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1070 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1071 statuses = relationship('ChangesetStatus')
1071 statuses = relationship('ChangesetStatus')
1072 comments = relationship('ChangesetComment',
1072 comments = relationship('ChangesetComment',
1073 cascade="all, delete, delete-orphan")
1073 cascade="all, delete, delete-orphan")
1074
1074
1075
1075
1076 class PullRequestReviewers(Base, BaseModel):
1076 class PullRequestReviewers(Base, BaseModel):
1077 __tablename__ = 'pull_request_reviewers'
1077 __tablename__ = 'pull_request_reviewers'
1078 __table_args__ = (
1078 __table_args__ = (
1079 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1079 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1080 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1080 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1081 )
1081 )
1082
1082
1083 def __init__(self, user=None, pull_request=None):
1083 def __init__(self, user=None, pull_request=None):
1084 self.user = user
1084 self.user = user
1085 self.pull_request = pull_request
1085 self.pull_request = pull_request
1086
1086
1087 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1087 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1088 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1088 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1089 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1089 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1090
1090
1091 user = relationship('User')
1091 user = relationship('User')
1092 pull_request = relationship('PullRequest')
1092 pull_request = relationship('PullRequest')
1093
1093
1094
1094
1095 class Notification(Base, BaseModel):
1095 class Notification(Base, BaseModel):
1096 __tablename__ = 'notifications'
1096 __tablename__ = 'notifications'
1097 __table_args__ = (
1097 __table_args__ = (
1098 Index('notification_type_idx', 'type'),
1098 Index('notification_type_idx', 'type'),
1099 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1099 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1100 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1100 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1101 )
1101 )
1102
1102
1103 TYPE_CHANGESET_COMMENT = u'cs_comment'
1103 TYPE_CHANGESET_COMMENT = u'cs_comment'
1104 TYPE_MESSAGE = u'message'
1104 TYPE_MESSAGE = u'message'
1105 TYPE_MENTION = u'mention'
1105 TYPE_MENTION = u'mention'
1106 TYPE_REGISTRATION = u'registration'
1106 TYPE_REGISTRATION = u'registration'
1107 TYPE_PULL_REQUEST = u'pull_request'
1107 TYPE_PULL_REQUEST = u'pull_request'
1108 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1108 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1109
1109
1110 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1110 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1111 subject = Column('subject', Unicode(512), nullable=True)
1111 subject = Column('subject', Unicode(512), nullable=True)
1112 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1112 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1113 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1113 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1114 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1114 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1115 type_ = Column('type', Unicode(256))
1115 type_ = Column('type', Unicode(256))
1116
1116
1117 created_by_user = relationship('User')
1117 created_by_user = relationship('User')
1118 notifications_to_users = relationship('UserNotification', lazy='joined',
1118 notifications_to_users = relationship('UserNotification', lazy='joined',
1119 cascade="all, delete, delete-orphan")
1119 cascade="all, delete, delete-orphan")
1120
1120
1121
1121
1122 class UserNotification(Base, BaseModel):
1122 class UserNotification(Base, BaseModel):
1123 __tablename__ = 'user_to_notification'
1123 __tablename__ = 'user_to_notification'
1124 __table_args__ = (
1124 __table_args__ = (
1125 UniqueConstraint('user_id', 'notification_id'),
1125 UniqueConstraint('user_id', 'notification_id'),
1126 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1126 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1127 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1127 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1128 )
1128 )
1129 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1129 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1130 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1130 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1131 read = Column('read', Boolean, default=False)
1131 read = Column('read', Boolean, default=False)
1132 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1132 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1133
1133
1134 user = relationship('User', lazy="joined")
1134 user = relationship('User', lazy="joined")
1135 notification = relationship('Notification', lazy="joined",
1135 notification = relationship('Notification', lazy="joined",
1136 order_by=lambda: Notification.created_on.desc(),)
1136 order_by=lambda: Notification.created_on.desc(),)
1137
1137
1138
1138
1139 class Gist(Base, BaseModel):
1139 class Gist(Base, BaseModel):
1140 __tablename__ = 'gists'
1140 __tablename__ = 'gists'
1141 __table_args__ = (
1141 __table_args__ = (
1142 Index('g_gist_access_id_idx', 'gist_access_id'),
1142 Index('g_gist_access_id_idx', 'gist_access_id'),
1143 Index('g_created_on_idx', 'created_on'),
1143 Index('g_created_on_idx', 'created_on'),
1144 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1144 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1145 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1145 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1146 )
1146 )
1147 GIST_PUBLIC = u'public'
1147 GIST_PUBLIC = u'public'
1148 GIST_PRIVATE = u'private'
1148 GIST_PRIVATE = u'private'
1149
1149
1150 gist_id = Column('gist_id', Integer(), primary_key=True)
1150 gist_id = Column('gist_id', Integer(), primary_key=True)
1151 gist_access_id = Column('gist_access_id', Unicode(250))
1151 gist_access_id = Column('gist_access_id', Unicode(250))
1152 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1152 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1153 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1153 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1154 gist_expires = Column('gist_expires', Float(53), nullable=False)
1154 gist_expires = Column('gist_expires', Float(53), nullable=False)
1155 gist_type = Column('gist_type', Unicode(128), nullable=False)
1155 gist_type = Column('gist_type', Unicode(128), nullable=False)
1156 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1156 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1157 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1157 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1158
1158
1159 owner = relationship('User')
1159 owner = relationship('User')
1160
1160
1161
1161
1162 class DbMigrateVersion(Base, BaseModel):
1162 class DbMigrateVersion(Base, BaseModel):
1163 __tablename__ = 'db_migrate_version'
1163 __tablename__ = 'db_migrate_version'
1164 __table_args__ = (
1164 __table_args__ = (
1165 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1165 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1166 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1166 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1167 )
1167 )
1168 repository_id = Column('repository_id', String(250), primary_key=True)
1168 repository_id = Column('repository_id', String(250), primary_key=True)
1169 repository_path = Column('repository_path', Text)
1169 repository_path = Column('repository_path', Text)
1170 version = Column('version', Integer)
1170 version = Column('version', Integer)
@@ -1,1187 +1,1187 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 from rhodecode.lib.ext_json import json
46 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.caching_query import FromCache
47 from rhodecode.lib.caching_query import FromCache
48
48
49 from rhodecode.model.meta import Base, Session
49 from rhodecode.model.meta import Base, Session
50
50
51 URL_SEP = '/'
51 URL_SEP = '/'
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 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
58 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59
59
60
60
61 class BaseModel(object):
61 class BaseModel(object):
62 """
62 """
63 Base Model for all classes
63 Base Model for all classes
64 """
64 """
65
65
66 @classmethod
66 @classmethod
67 def _get_keys(cls):
67 def _get_keys(cls):
68 """return column names for this model """
68 """return column names for this model """
69 return class_mapper(cls).c.keys()
69 return class_mapper(cls).c.keys()
70
70
71 def get_dict(self):
71 def get_dict(self):
72 """
72 """
73 return dict with keys and values corresponding
73 return dict with keys and values corresponding
74 to this model data """
74 to this model data """
75
75
76 d = {}
76 d = {}
77 for k in self._get_keys():
77 for k in self._get_keys():
78 d[k] = getattr(self, k)
78 d[k] = getattr(self, k)
79
79
80 # also use __json__() if present to get additional fields
80 # also use __json__() if present to get additional fields
81 _json_attr = getattr(self, '__json__', None)
81 _json_attr = getattr(self, '__json__', None)
82 if _json_attr:
82 if _json_attr:
83 # update with attributes from __json__
83 # update with attributes from __json__
84 if callable(_json_attr):
84 if callable(_json_attr):
85 _json_attr = _json_attr()
85 _json_attr = _json_attr()
86 for k, val in _json_attr.items():
86 for k, val in _json_attr.items():
87 d[k] = val
87 d[k] = val
88 return d
88 return d
89
89
90 def get_appstruct(self):
90 def get_appstruct(self):
91 """return list with keys and values tupples corresponding
91 """return list with keys and values tupples corresponding
92 to this model data """
92 to this model data """
93
93
94 l = []
94 l = []
95 for k in self._get_keys():
95 for k in self._get_keys():
96 l.append((k, getattr(self, k),))
96 l.append((k, getattr(self, k),))
97 return l
97 return l
98
98
99 def populate_obj(self, populate_dict):
99 def populate_obj(self, populate_dict):
100 """populate model with data from given populate_dict"""
100 """populate model with data from given populate_dict"""
101
101
102 for k in self._get_keys():
102 for k in self._get_keys():
103 if k in populate_dict:
103 if k in populate_dict:
104 setattr(self, k, populate_dict[k])
104 setattr(self, k, populate_dict[k])
105
105
106 @classmethod
106 @classmethod
107 def query(cls):
107 def query(cls):
108 return Session().query(cls)
108 return Session().query(cls)
109
109
110 @classmethod
110 @classmethod
111 def get(cls, id_):
111 def get(cls, id_):
112 if id_:
112 if id_:
113 return cls.query().get(id_)
113 return cls.query().get(id_)
114
114
115 @classmethod
115 @classmethod
116 def get_or_404(cls, id_):
116 def get_or_404(cls, id_):
117 try:
117 try:
118 id_ = int(id_)
118 id_ = int(id_)
119 except (TypeError, ValueError):
119 except (TypeError, ValueError):
120 raise HTTPNotFound
120 raise HTTPNotFound
121
121
122 res = cls.query().get(id_)
122 res = cls.query().get(id_)
123 if not res:
123 if not res:
124 raise HTTPNotFound
124 raise HTTPNotFound
125 return res
125 return res
126
126
127 @classmethod
127 @classmethod
128 def getAll(cls):
128 def getAll(cls):
129 # deprecated and left for backward compatibility
129 # deprecated and left for backward compatibility
130 return cls.get_all()
130 return cls.get_all()
131
131
132 @classmethod
132 @classmethod
133 def get_all(cls):
133 def get_all(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
140
141 def __repr__(self):
141 def __repr__(self):
142 if hasattr(self, '__unicode__'):
142 if hasattr(self, '__unicode__'):
143 # python repr needs to return str
143 # python repr needs to return str
144 try:
144 try:
145 return safe_str(self.__unicode__())
145 return safe_str(self.__unicode__())
146 except UnicodeDecodeError:
146 except UnicodeDecodeError:
147 pass
147 pass
148 return '<DB:%s>' % (self.__class__.__name__)
148 return '<DB:%s>' % (self.__class__.__name__)
149
149
150
150
151 class RhodeCodeSetting(Base, BaseModel):
151 class RhodeCodeSetting(Base, BaseModel):
152 SETTINGS_TYPES = {
152 SETTINGS_TYPES = {
153 'str': safe_str,
153 'str': safe_str,
154 'int': safe_int,
154 'int': safe_int,
155 'unicode': safe_str,
155 'unicode': safe_str,
156 'bool': str2bool,
156 'bool': str2bool,
157 'list': functools.partial(aslist, sep=',')
157 'list': functools.partial(aslist, sep=',')
158 }
158 }
159 __tablename__ = 'rhodecode_settings'
159 __tablename__ = 'rhodecode_settings'
160 __table_args__ = (
160 __table_args__ = (
161 UniqueConstraint('app_settings_name'),
161 UniqueConstraint('app_settings_name'),
162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
163 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
163 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
164 )
164 )
165 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
165 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
166 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
166 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
167 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
167 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
168 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
168 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
169
169
170 def __init__(self, key='', val='', type='unicode'):
170 def __init__(self, key='', val='', type='unicode'):
171 self.app_settings_name = key
171 self.app_settings_name = key
172 self.app_settings_value = val
172 self.app_settings_value = val
173 self.app_settings_type = type
173 self.app_settings_type = type
174
174
175 @validates('_app_settings_value')
175 @validates('_app_settings_value')
176 def validate_settings_value(self, key, val):
176 def validate_settings_value(self, key, val):
177 assert type(val) == str
177 assert type(val) == str
178 return val
178 return val
179
179
180 @hybrid_property
180 @hybrid_property
181 def app_settings_value(self):
181 def app_settings_value(self):
182 v = self._app_settings_value
182 v = self._app_settings_value
183 _type = self.app_settings_type
183 _type = self.app_settings_type
184 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
184 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
185 return converter(v)
185 return converter(v)
186
186
187 @app_settings_value.setter
187 @app_settings_value.setter
188 def app_settings_value(self, val):
188 def app_settings_value(self, val):
189 """
189 """
190 Setter that will always make sure we use unicode in app_settings_value
190 Setter that will always make sure we use unicode in app_settings_value
191
191
192 :param val:
192 :param val:
193 """
193 """
194 self._app_settings_value = safe_str(val)
194 self._app_settings_value = safe_str(val)
195
195
196 @hybrid_property
196 @hybrid_property
197 def app_settings_type(self):
197 def app_settings_type(self):
198 return self._app_settings_type
198 return self._app_settings_type
199
199
200 @app_settings_type.setter
200 @app_settings_type.setter
201 def app_settings_type(self, val):
201 def app_settings_type(self, val):
202 if val not in self.SETTINGS_TYPES:
202 if val not in self.SETTINGS_TYPES:
203 raise Exception('type must be one of %s got %s'
203 raise Exception('type must be one of %s got %s'
204 % (self.SETTINGS_TYPES.keys(), val))
204 % (self.SETTINGS_TYPES.keys(), val))
205 self._app_settings_type = val
205 self._app_settings_type = val
206
206
207 def __unicode__(self):
207 def __unicode__(self):
208 return u"<%s('%s:%s[%s]')>" % (
208 return u"<%s('%s:%s[%s]')>" % (
209 self.__class__.__name__,
209 self.__class__.__name__,
210 self.app_settings_name, self.app_settings_value, self.app_settings_type
210 self.app_settings_name, self.app_settings_value, self.app_settings_type
211 )
211 )
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__ = (
216 __table_args__ = (
217 UniqueConstraint('ui_key'),
217 UniqueConstraint('ui_key'),
218 {'extend_existing': True, 'mysql_engine': 'InnoDB',
218 {'extend_existing': True, 'mysql_engine': 'InnoDB',
219 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
219 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
220 )
220 )
221
221
222 HOOK_REPO_SIZE = 'changegroup.repo_size'
222 HOOK_REPO_SIZE = 'changegroup.repo_size'
223 HOOK_PUSH = 'changegroup.push_logger'
223 HOOK_PUSH = 'changegroup.push_logger'
224 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
224 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
225 HOOK_PULL = 'outgoing.pull_logger'
225 HOOK_PULL = 'outgoing.pull_logger'
226 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
226 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
227
227
228 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
228 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
229 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
229 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
230 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
230 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
231 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
231 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
232 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
232 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
233
233
234
234
235
235
236 class User(Base, BaseModel):
236 class User(Base, BaseModel):
237 __tablename__ = 'users'
237 __tablename__ = 'users'
238 __table_args__ = (
238 __table_args__ = (
239 UniqueConstraint('username'), UniqueConstraint('email'),
239 UniqueConstraint('username'), UniqueConstraint('email'),
240 Index('u_username_idx', 'username'),
240 Index('u_username_idx', 'username'),
241 Index('u_email_idx', 'email'),
241 Index('u_email_idx', 'email'),
242 {'extend_existing': True, 'mysql_engine': 'InnoDB',
242 {'extend_existing': True, 'mysql_engine': 'InnoDB',
243 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
243 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
244 )
244 )
245 DEFAULT_USER = 'default'
245 DEFAULT_USER = 'default'
246
246
247 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
247 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
248 username = Column("username", String(255), nullable=True, unique=None, default=None)
248 username = Column("username", String(255), nullable=True, unique=None, default=None)
249 password = Column("password", String(255), nullable=True, unique=None, default=None)
249 password = Column("password", String(255), nullable=True, unique=None, default=None)
250 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
250 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
251 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
251 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
252 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
252 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
253 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
253 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
254 _email = Column("email", String(255), nullable=True, unique=None, default=None)
254 _email = Column("email", String(255), nullable=True, unique=None, default=None)
255 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
255 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
256 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
256 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
257 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
257 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
258 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
258 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
259 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
259 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
260 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
260 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
261
261
262 user_log = relationship('UserLog')
262 user_log = relationship('UserLog')
263 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
263 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
264
264
265 repositories = relationship('Repository')
265 repositories = relationship('Repository')
266 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
266 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
267 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
267 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
268
268
269 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
269 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
270 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
270 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
271
271
272 group_member = relationship('UserGroupMember', cascade='all')
272 group_member = relationship('UserGroupMember', cascade='all')
273
273
274 notifications = relationship('UserNotification', cascade='all')
274 notifications = relationship('UserNotification', cascade='all')
275 # notifications assigned to this user
275 # notifications assigned to this user
276 user_created_notifications = relationship('Notification', cascade='all')
276 user_created_notifications = relationship('Notification', cascade='all')
277 # comments created by this user
277 # comments created by this user
278 user_comments = relationship('ChangesetComment', cascade='all')
278 user_comments = relationship('ChangesetComment', cascade='all')
279 user_emails = relationship('UserEmailMap', cascade='all')
279 user_emails = relationship('UserEmailMap', cascade='all')
280
280
281 @hybrid_property
281 @hybrid_property
282 def email(self):
282 def email(self):
283 return self._email
283 return self._email
284
284
285 @email.setter
285 @email.setter
286 def email(self, val):
286 def email(self, val):
287 self._email = val.lower() if val else None
287 self._email = val.lower() if val else None
288
288
289 @property
289 @property
290 def firstname(self):
290 def firstname(self):
291 # alias for future
291 # alias for future
292 return self.name
292 return self.name
293
293
294 @property
294 @property
295 def username_and_name(self):
295 def username_and_name(self):
296 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
296 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
297
297
298 @property
298 @property
299 def full_name(self):
299 def full_name(self):
300 return '%s %s' % (self.firstname, self.lastname)
300 return '%s %s' % (self.firstname, self.lastname)
301
301
302 @property
302 @property
303 def full_contact(self):
303 def full_contact(self):
304 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
304 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
305
305
306 @property
306 @property
307 def short_contact(self):
307 def short_contact(self):
308 return '%s %s' % (self.firstname, self.lastname)
308 return '%s %s' % (self.firstname, self.lastname)
309
309
310 @property
310 @property
311 def is_admin(self):
311 def is_admin(self):
312 return self.admin
312 return self.admin
313
313
314 @classmethod
314 @classmethod
315 def get_by_username(cls, username, case_insensitive=False, cache=False):
315 def get_by_username(cls, username, case_insensitive=False, cache=False):
316 if case_insensitive:
316 if case_insensitive:
317 q = cls.query().filter(cls.username.ilike(username))
317 q = cls.query().filter(cls.username.ilike(username))
318 else:
318 else:
319 q = cls.query().filter(cls.username == username)
319 q = cls.query().filter(cls.username == username)
320
320
321 if cache:
321 if cache:
322 q = q.options(FromCache(
322 q = q.options(FromCache(
323 "sql_cache_short",
323 "sql_cache_short",
324 "get_user_%s" % _hash_key(username)
324 "get_user_%s" % _hash_key(username)
325 )
325 )
326 )
326 )
327 return q.scalar()
327 return q.scalar()
328
328
329 @classmethod
329 @classmethod
330 def get_by_auth_token(cls, auth_token, cache=False):
330 def get_by_auth_token(cls, auth_token, cache=False):
331 q = cls.query().filter(cls.api_key == auth_token)
331 q = cls.query().filter(cls.api_key == auth_token)
332
332
333 if cache:
333 if cache:
334 q = q.options(FromCache("sql_cache_short",
334 q = q.options(FromCache("sql_cache_short",
335 "get_auth_token_%s" % auth_token))
335 "get_auth_token_%s" % auth_token))
336 return q.scalar()
336 return q.scalar()
337
337
338 @classmethod
338 @classmethod
339 def get_by_email(cls, email, case_insensitive=False, cache=False):
339 def get_by_email(cls, email, case_insensitive=False, cache=False):
340 if case_insensitive:
340 if case_insensitive:
341 q = cls.query().filter(cls.email.ilike(email))
341 q = cls.query().filter(cls.email.ilike(email))
342 else:
342 else:
343 q = cls.query().filter(cls.email == email)
343 q = cls.query().filter(cls.email == email)
344
344
345 if cache:
345 if cache:
346 q = q.options(FromCache("sql_cache_short",
346 q = q.options(FromCache("sql_cache_short",
347 "get_email_key_%s" % email))
347 "get_email_key_%s" % email))
348
348
349 ret = q.scalar()
349 ret = q.scalar()
350 if ret is None:
350 if ret is None:
351 q = UserEmailMap.query()
351 q = UserEmailMap.query()
352 # try fetching in alternate email map
352 # try fetching in alternate email map
353 if case_insensitive:
353 if case_insensitive:
354 q = q.filter(UserEmailMap.email.ilike(email))
354 q = q.filter(UserEmailMap.email.ilike(email))
355 else:
355 else:
356 q = q.filter(UserEmailMap.email == email)
356 q = q.filter(UserEmailMap.email == email)
357 q = q.options(joinedload(UserEmailMap.user))
357 q = q.options(joinedload(UserEmailMap.user))
358 if cache:
358 if cache:
359 q = q.options(FromCache("sql_cache_short",
359 q = q.options(FromCache("sql_cache_short",
360 "get_email_map_key_%s" % email))
360 "get_email_map_key_%s" % email))
361 ret = getattr(q.scalar(), 'user', None)
361 ret = getattr(q.scalar(), 'user', None)
362
362
363 return ret
363 return ret
364
364
365 @classmethod
365 @classmethod
366 def get_first_admin(cls):
366 def get_first_admin(cls):
367 user = User.query().filter(User.admin == True).first()
367 user = User.query().filter(User.admin == True).first()
368 if user is None:
368 if user is None:
369 raise Exception('Missing administrative account!')
369 raise Exception('Missing administrative account!')
370 return user
370 return user
371
371
372 @classmethod
372 @classmethod
373 def get_default_user(cls, cache=False):
373 def get_default_user(cls, cache=False):
374 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
374 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
375 if user is None:
375 if user is None:
376 raise Exception('Missing default account!')
376 raise Exception('Missing default account!')
377 return user
377 return user
378
378
379
379
380
380
381
381
382 class UserEmailMap(Base, BaseModel):
382 class UserEmailMap(Base, BaseModel):
383 __tablename__ = 'user_email_map'
383 __tablename__ = 'user_email_map'
384 __table_args__ = (
384 __table_args__ = (
385 Index('uem_email_idx', 'email'),
385 Index('uem_email_idx', 'email'),
386 UniqueConstraint('email'),
386 UniqueConstraint('email'),
387 {'extend_existing': True, 'mysql_engine': 'InnoDB',
387 {'extend_existing': True, 'mysql_engine': 'InnoDB',
388 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
388 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
389 )
389 )
390
390
391
391
392 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
392 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
393 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
393 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
394 _email = Column("email", String(255), nullable=True, unique=False, default=None)
394 _email = Column("email", String(255), nullable=True, unique=False, default=None)
395 user = relationship('User', lazy='joined')
395 user = relationship('User', lazy='joined')
396
396
397 @validates('_email')
397 @validates('_email')
398 def validate_email(self, key, email):
398 def validate_email(self, key, email):
399 # check if this email is not main one
399 # check if this email is not main one
400 main_email = Session().query(User).filter(User.email == email).scalar()
400 main_email = Session().query(User).filter(User.email == email).scalar()
401 if main_email is not None:
401 if main_email is not None:
402 raise AttributeError('email %s is present is user table' % email)
402 raise AttributeError('email %s is present is user table' % email)
403 return email
403 return email
404
404
405 @hybrid_property
405 @hybrid_property
406 def email(self):
406 def email(self):
407 return self._email
407 return self._email
408
408
409 @email.setter
409 @email.setter
410 def email(self, val):
410 def email(self, val):
411 self._email = val.lower() if val else None
411 self._email = val.lower() if val else None
412
412
413
413
414 class UserIpMap(Base, BaseModel):
414 class UserIpMap(Base, BaseModel):
415 __tablename__ = 'user_ip_map'
415 __tablename__ = 'user_ip_map'
416 __table_args__ = (
416 __table_args__ = (
417 UniqueConstraint('user_id', 'ip_addr'),
417 UniqueConstraint('user_id', 'ip_addr'),
418 {'extend_existing': True, 'mysql_engine': 'InnoDB',
418 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
419 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
420 )
420 )
421
421
422
422
423 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
423 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
424 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
425 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
425 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
426 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
426 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
427 user = relationship('User', lazy='joined')
427 user = relationship('User', lazy='joined')
428
428
429
429
430 class UserLog(Base, BaseModel):
430 class UserLog(Base, BaseModel):
431 __tablename__ = 'user_logs'
431 __tablename__ = 'user_logs'
432 __table_args__ = (
432 __table_args__ = (
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
434 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
434 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
435 )
435 )
436 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
436 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
438 username = Column("username", String(255), nullable=True, unique=None, default=None)
438 username = Column("username", String(255), nullable=True, unique=None, default=None)
439 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
439 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
440 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
440 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
441 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
441 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
442 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
442 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
443 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
443 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
444
444
445 def __unicode__(self):
445 def __unicode__(self):
446 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
446 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
447 self.repository_name,
447 self.repository_name,
448 self.action)
448 self.action)
449
449
450 user = relationship('User')
450 user = relationship('User')
451 repository = relationship('Repository', cascade='')
451 repository = relationship('Repository', cascade='')
452
452
453
453
454 class UserGroup(Base, BaseModel):
454 class UserGroup(Base, BaseModel):
455 __tablename__ = 'users_groups'
455 __tablename__ = 'users_groups'
456 __table_args__ = (
456 __table_args__ = (
457 {'extend_existing': True, 'mysql_engine': 'InnoDB',
457 {'extend_existing': True, 'mysql_engine': 'InnoDB',
458 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
458 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
459 )
459 )
460
460
461 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
461 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
462 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
462 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
463 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
463 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
464 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
464 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
465 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
465 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
466 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
468
468
469 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
469 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
470 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
470 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
471 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
471 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
472 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
472 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
473 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
473 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
474 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
474 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
475
475
476 user = relationship('User')
476 user = relationship('User')
477
477
478 def __unicode__(self):
478 def __unicode__(self):
479 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
479 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
480 self.users_group_id,
480 self.users_group_id,
481 self.users_group_name)
481 self.users_group_name)
482
482
483 @classmethod
483 @classmethod
484 def get_by_group_name(cls, group_name, cache=False,
484 def get_by_group_name(cls, group_name, cache=False,
485 case_insensitive=False):
485 case_insensitive=False):
486 if case_insensitive:
486 if case_insensitive:
487 q = cls.query().filter(cls.users_group_name.ilike(group_name))
487 q = cls.query().filter(cls.users_group_name.ilike(group_name))
488 else:
488 else:
489 q = cls.query().filter(cls.users_group_name == group_name)
489 q = cls.query().filter(cls.users_group_name == group_name)
490 if cache:
490 if cache:
491 q = q.options(FromCache(
491 q = q.options(FromCache(
492 "sql_cache_short",
492 "sql_cache_short",
493 "get_user_%s" % _hash_key(group_name)
493 "get_user_%s" % _hash_key(group_name)
494 )
494 )
495 )
495 )
496 return q.scalar()
496 return q.scalar()
497
497
498 @classmethod
498 @classmethod
499 def get(cls, user_group_id, cache=False):
499 def get(cls, user_group_id, cache=False):
500 user_group = cls.query()
500 user_group = cls.query()
501 if cache:
501 if cache:
502 user_group = user_group.options(FromCache("sql_cache_short",
502 user_group = user_group.options(FromCache("sql_cache_short",
503 "get_users_group_%s" % user_group_id))
503 "get_users_group_%s" % user_group_id))
504 return user_group.get(user_group_id)
504 return user_group.get(user_group_id)
505
505
506
506
507 class UserGroupMember(Base, BaseModel):
507 class UserGroupMember(Base, BaseModel):
508 __tablename__ = 'users_groups_members'
508 __tablename__ = 'users_groups_members'
509 __table_args__ = (
509 __table_args__ = (
510 {'extend_existing': True, 'mysql_engine': 'InnoDB',
510 {'extend_existing': True, 'mysql_engine': 'InnoDB',
511 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
511 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
512 )
512 )
513
513
514 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
514 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
515 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
515 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
516 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
516 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
517
517
518 user = relationship('User', lazy='joined')
518 user = relationship('User', lazy='joined')
519 users_group = relationship('UserGroup')
519 users_group = relationship('UserGroup')
520
520
521 def __init__(self, gr_id='', u_id=''):
521 def __init__(self, gr_id='', u_id=''):
522 self.users_group_id = gr_id
522 self.users_group_id = gr_id
523 self.user_id = u_id
523 self.user_id = u_id
524
524
525
525
526 class RepositoryField(Base, BaseModel):
526 class RepositoryField(Base, BaseModel):
527 __tablename__ = 'repositories_fields'
527 __tablename__ = 'repositories_fields'
528 __table_args__ = (
528 __table_args__ = (
529 UniqueConstraint('repository_id', 'field_key'), # no-multi field
529 UniqueConstraint('repository_id', 'field_key'), # no-multi field
530 {'extend_existing': True, 'mysql_engine': 'InnoDB',
530 {'extend_existing': True, 'mysql_engine': 'InnoDB',
531 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
531 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
532 )
532 )
533 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
533 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
534
534
535 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
535 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
536 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
536 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
537 field_key = Column("field_key", String(250))
537 field_key = Column("field_key", String(250))
538 field_label = Column("field_label", String(1024), nullable=False)
538 field_label = Column("field_label", String(1024), nullable=False)
539 field_value = Column("field_value", String(10000), nullable=False)
539 field_value = Column("field_value", String(10000), nullable=False)
540 field_desc = Column("field_desc", String(1024), nullable=False)
540 field_desc = Column("field_desc", String(1024), nullable=False)
541 field_type = Column("field_type", String(256), nullable=False, unique=None)
541 field_type = Column("field_type", String(256), nullable=False, unique=None)
542 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
542 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
543
543
544 repository = relationship('Repository')
544 repository = relationship('Repository')
545
545
546 @classmethod
546 @classmethod
547 def get_by_key_name(cls, key, repo):
547 def get_by_key_name(cls, key, repo):
548 row = cls.query()\
548 row = cls.query()\
549 .filter(cls.repository == repo)\
549 .filter(cls.repository == repo)\
550 .filter(cls.field_key == key).scalar()
550 .filter(cls.field_key == key).scalar()
551 return row
551 return row
552
552
553
553
554 class Repository(Base, BaseModel):
554 class Repository(Base, BaseModel):
555 __tablename__ = 'repositories'
555 __tablename__ = 'repositories'
556 __table_args__ = (
556 __table_args__ = (
557 UniqueConstraint('repo_name'),
557 UniqueConstraint('repo_name'),
558 Index('r_repo_name_idx', 'repo_name'),
558 Index('r_repo_name_idx', 'repo_name'),
559 {'extend_existing': True, 'mysql_engine': 'InnoDB',
559 {'extend_existing': True, 'mysql_engine': 'InnoDB',
560 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
560 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
561 )
561 )
562
562
563 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
563 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
564 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
564 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
565 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
565 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
566 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
566 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
567 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
567 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
568 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
568 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
569 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
569 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
570 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
570 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
571 description = Column("description", String(10000), nullable=True, unique=None, default=None)
571 description = Column("description", String(10000), nullable=True, unique=None, default=None)
572 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
572 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
573 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
573 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
574 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
574 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
575 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
575 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
576 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
576 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
577 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
577 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
578
578
579 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
579 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
580 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
580 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
581
581
582 user = relationship('User')
582 user = relationship('User')
583 fork = relationship('Repository', remote_side=repo_id)
583 fork = relationship('Repository', remote_side=repo_id)
584 group = relationship('RepoGroup')
584 group = relationship('RepoGroup')
585 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
585 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
586 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
586 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
587 stats = relationship('Statistics', cascade='all', uselist=False)
587 stats = relationship('Statistics', cascade='all', uselist=False)
588
588
589 followers = relationship('UserFollowing',
589 followers = relationship('UserFollowing',
590 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
590 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
591 cascade='all')
591 cascade='all')
592 extra_fields = relationship('RepositoryField',
592 extra_fields = relationship('RepositoryField',
593 cascade="all, delete, delete-orphan")
593 cascade="all, delete, delete-orphan")
594
594
595 logs = relationship('UserLog')
595 logs = relationship('UserLog')
596 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
596 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
597
597
598 pull_requests_org = relationship('PullRequest',
598 pull_requests_org = relationship('PullRequest',
599 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
599 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
600 cascade="all, delete, delete-orphan")
600 cascade="all, delete, delete-orphan")
601
601
602 pull_requests_other = relationship('PullRequest',
602 pull_requests_other = relationship('PullRequest',
603 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
603 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
604 cascade="all, delete, delete-orphan")
604 cascade="all, delete, delete-orphan")
605
605
606 #NOTE: marcink, DO NOT REMOVE THOSE
606 #NOTE: marcink, DO NOT REMOVE THOSE
607 @hybrid_property
607 @hybrid_property
608 def landing_rev(self):
608 def landing_rev(self):
609 # always should return [rev_type, rev]
609 # always should return [rev_type, rev]
610 if self._landing_revision:
610 if self._landing_revision:
611 _rev_info = self._landing_revision.split(':')
611 _rev_info = self._landing_revision.split(':')
612 if len(_rev_info) < 2:
612 if len(_rev_info) < 2:
613 _rev_info.insert(0, 'rev')
613 _rev_info.insert(0, 'rev')
614 return [_rev_info[0], _rev_info[1]]
614 return [_rev_info[0], _rev_info[1]]
615 return [None, None]
615 return [None, None]
616
616
617 @landing_rev.setter
617 @landing_rev.setter
618 def landing_rev(self, val):
618 def landing_rev(self, val):
619 if ':' not in val:
619 if ':' not in val:
620 raise ValueError('value must be delimited with `:` and consist '
620 raise ValueError('value must be delimited with `:` and consist '
621 'of <rev_type>:<rev>, got %s instead' % val)
621 'of <rev_type>:<rev>, got %s instead' % val)
622 self._landing_revision = val
622 self._landing_revision = val
623
623
624 def __unicode__(self):
624 def __unicode__(self):
625 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
625 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
626 safe_str(self.repo_name))
626 safe_str(self.repo_name))
627
627
628 @classmethod
628 @classmethod
629 def get_by_repo_name(cls, repo_name):
629 def get_by_repo_name(cls, repo_name):
630 q = Session().query(cls).filter(cls.repo_name == repo_name)
630 q = Session().query(cls).filter(cls.repo_name == repo_name)
631 q = q.options(joinedload(Repository.fork))\
631 q = q.options(joinedload(Repository.fork))\
632 .options(joinedload(Repository.user))\
632 .options(joinedload(Repository.user))\
633 .options(joinedload(Repository.group))
633 .options(joinedload(Repository.group))
634 return q.scalar()
634 return q.scalar()
635
635
636
636
637 class RepoGroup(Base, BaseModel):
637 class RepoGroup(Base, BaseModel):
638 __tablename__ = 'groups'
638 __tablename__ = 'groups'
639 __table_args__ = (
639 __table_args__ = (
640 UniqueConstraint('group_name', 'group_parent_id'),
640 UniqueConstraint('group_name', 'group_parent_id'),
641 {'extend_existing': True, 'mysql_engine': 'InnoDB',
641 {'extend_existing': True, 'mysql_engine': 'InnoDB',
642 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
642 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
643 )
643 )
644
644
645
645
646 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
646 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
647 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
647 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
648 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
648 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
649 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
649 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
650 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
650 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
651 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
651 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
652 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
652 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
653
653
654 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
654 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
655 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
655 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
656 parent_group = relationship('RepoGroup', remote_side=group_id)
656 parent_group = relationship('RepoGroup', remote_side=group_id)
657 user = relationship('User')
657 user = relationship('User')
658
658
659 def __init__(self, group_name='', parent_group=None):
659 def __init__(self, group_name='', parent_group=None):
660 self.group_name = group_name
660 self.group_name = group_name
661 self.parent_group = parent_group
661 self.parent_group = parent_group
662
662
663 def __unicode__(self):
663 def __unicode__(self):
664 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
664 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
665 self.group_name)
665 self.group_name)
666
666
667 @classmethod
667 @classmethod
668 def url_sep(cls):
668 def url_sep(cls):
669 return URL_SEP
669 return URL_SEP
670
670
671 @classmethod
671 @classmethod
672 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
672 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
673 if case_insensitive:
673 if case_insensitive:
674 gr = cls.query()\
674 gr = cls.query()\
675 .filter(cls.group_name.ilike(group_name))
675 .filter(cls.group_name.ilike(group_name))
676 else:
676 else:
677 gr = cls.query()\
677 gr = cls.query()\
678 .filter(cls.group_name == group_name)
678 .filter(cls.group_name == group_name)
679 if cache:
679 if cache:
680 gr = gr.options(FromCache(
680 gr = gr.options(FromCache(
681 "sql_cache_short",
681 "sql_cache_short",
682 "get_group_%s" % _hash_key(group_name)
682 "get_group_%s" % _hash_key(group_name)
683 )
683 )
684 )
684 )
685 return gr.scalar()
685 return gr.scalar()
686
686
687
687
688 class Permission(Base, BaseModel):
688 class Permission(Base, BaseModel):
689 __tablename__ = 'permissions'
689 __tablename__ = 'permissions'
690 __table_args__ = (
690 __table_args__ = (
691 Index('p_perm_name_idx', 'permission_name'),
691 Index('p_perm_name_idx', 'permission_name'),
692 {'extend_existing': True, 'mysql_engine': 'InnoDB',
692 {'extend_existing': True, 'mysql_engine': 'InnoDB',
693 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
693 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
694 )
694 )
695 PERMS = [
695 PERMS = [
696 ('hg.admin', _('RhodeCode Administrator')),
696 ('hg.admin', _('RhodeCode Administrator')),
697
697
698 ('repository.none', _('Repository no access')),
698 ('repository.none', _('Repository no access')),
699 ('repository.read', _('Repository read access')),
699 ('repository.read', _('Repository read access')),
700 ('repository.write', _('Repository write access')),
700 ('repository.write', _('Repository write access')),
701 ('repository.admin', _('Repository admin access')),
701 ('repository.admin', _('Repository admin access')),
702
702
703 ('group.none', _('Repository group no access')),
703 ('group.none', _('Repository group no access')),
704 ('group.read', _('Repository group read access')),
704 ('group.read', _('Repository group read access')),
705 ('group.write', _('Repository group write access')),
705 ('group.write', _('Repository group write access')),
706 ('group.admin', _('Repository group admin access')),
706 ('group.admin', _('Repository group admin access')),
707
707
708 ('usergroup.none', _('User group no access')),
708 ('usergroup.none', _('User group no access')),
709 ('usergroup.read', _('User group read access')),
709 ('usergroup.read', _('User group read access')),
710 ('usergroup.write', _('User group write access')),
710 ('usergroup.write', _('User group write access')),
711 ('usergroup.admin', _('User group admin access')),
711 ('usergroup.admin', _('User group admin access')),
712
712
713 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
713 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
714 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
714 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
715
715
716 ('hg.usergroup.create.false', _('User Group creation disabled')),
716 ('hg.usergroup.create.false', _('User Group creation disabled')),
717 ('hg.usergroup.create.true', _('User Group creation enabled')),
717 ('hg.usergroup.create.true', _('User Group creation enabled')),
718
718
719 ('hg.create.none', _('Repository creation disabled')),
719 ('hg.create.none', _('Repository creation disabled')),
720 ('hg.create.repository', _('Repository creation enabled')),
720 ('hg.create.repository', _('Repository creation enabled')),
721
721
722 ('hg.fork.none', _('Repository forking disabled')),
722 ('hg.fork.none', _('Repository forking disabled')),
723 ('hg.fork.repository', _('Repository forking enabled')),
723 ('hg.fork.repository', _('Repository forking enabled')),
724
724
725 ('hg.register.none', _('Registration disabled')),
725 ('hg.register.none', _('Registration disabled')),
726 ('hg.register.manual_activate', _('User Registration with manual account activation')),
726 ('hg.register.manual_activate', _('User Registration with manual account activation')),
727 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
727 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
728
728
729 ('hg.extern_activate.manual', _('Manual activation of external account')),
729 ('hg.extern_activate.manual', _('Manual activation of external account')),
730 ('hg.extern_activate.auto', _('Automatic activation of external account')),
730 ('hg.extern_activate.auto', _('Automatic activation of external account')),
731
731
732 ]
732 ]
733
733
734 #definition of system default permissions for DEFAULT user
734 #definition of system default permissions for DEFAULT user
735 DEFAULT_USER_PERMISSIONS = [
735 DEFAULT_USER_PERMISSIONS = [
736 'repository.read',
736 'repository.read',
737 'group.read',
737 'group.read',
738 'usergroup.read',
738 'usergroup.read',
739 'hg.create.repository',
739 'hg.create.repository',
740 'hg.fork.repository',
740 'hg.fork.repository',
741 'hg.register.manual_activate',
741 'hg.register.manual_activate',
742 'hg.extern_activate.auto',
742 'hg.extern_activate.auto',
743 ]
743 ]
744
744
745 # defines which permissions are more important higher the more important
745 # defines which permissions are more important higher the more important
746 # Weight defines which permissions are more important.
746 # Weight defines which permissions are more important.
747 # The higher number the more important.
747 # The higher number the more important.
748 PERM_WEIGHTS = {
748 PERM_WEIGHTS = {
749 'repository.none': 0,
749 'repository.none': 0,
750 'repository.read': 1,
750 'repository.read': 1,
751 'repository.write': 3,
751 'repository.write': 3,
752 'repository.admin': 4,
752 'repository.admin': 4,
753
753
754 'group.none': 0,
754 'group.none': 0,
755 'group.read': 1,
755 'group.read': 1,
756 'group.write': 3,
756 'group.write': 3,
757 'group.admin': 4,
757 'group.admin': 4,
758
758
759 'usergroup.none': 0,
759 'usergroup.none': 0,
760 'usergroup.read': 1,
760 'usergroup.read': 1,
761 'usergroup.write': 3,
761 'usergroup.write': 3,
762 'usergroup.admin': 4,
762 'usergroup.admin': 4,
763 'hg.repogroup.create.false': 0,
763 'hg.repogroup.create.false': 0,
764 'hg.repogroup.create.true': 1,
764 'hg.repogroup.create.true': 1,
765
765
766 'hg.usergroup.create.false': 0,
766 'hg.usergroup.create.false': 0,
767 'hg.usergroup.create.true': 1,
767 'hg.usergroup.create.true': 1,
768
768
769 'hg.fork.none': 0,
769 'hg.fork.none': 0,
770 'hg.fork.repository': 1,
770 'hg.fork.repository': 1,
771 'hg.create.none': 0,
771 'hg.create.none': 0,
772 'hg.create.repository': 1
772 'hg.create.repository': 1
773 }
773 }
774
774
775 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
775 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
776 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
776 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
777 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
777 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
778
778
779 def __unicode__(self):
779 def __unicode__(self):
780 return u"<%s('%s:%s')>" % (
780 return u"<%s('%s:%s')>" % (
781 self.__class__.__name__, self.permission_id, self.permission_name
781 self.__class__.__name__, self.permission_id, self.permission_name
782 )
782 )
783
783
784 @classmethod
784 @classmethod
785 def get_by_key(cls, key):
785 def get_by_key(cls, key):
786 return cls.query().filter(cls.permission_name == key).scalar()
786 return cls.query().filter(cls.permission_name == key).scalar()
787
787
788
788
789 class UserRepoToPerm(Base, BaseModel):
789 class UserRepoToPerm(Base, BaseModel):
790 __tablename__ = 'repo_to_perm'
790 __tablename__ = 'repo_to_perm'
791 __table_args__ = (
791 __table_args__ = (
792 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
792 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
793 {'extend_existing': True, 'mysql_engine': 'InnoDB',
793 {'extend_existing': True, 'mysql_engine': 'InnoDB',
794 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
794 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
795 )
795 )
796 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
796 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
797 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
797 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
798 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
798 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
799 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
799 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
800
800
801 user = relationship('User')
801 user = relationship('User')
802 repository = relationship('Repository')
802 repository = relationship('Repository')
803 permission = relationship('Permission')
803 permission = relationship('Permission')
804
804
805 def __unicode__(self):
805 def __unicode__(self):
806 return u'<%s => %s >' % (self.user, self.repository)
806 return u'<%s => %s >' % (self.user, self.repository)
807
807
808
808
809 class UserUserGroupToPerm(Base, BaseModel):
809 class UserUserGroupToPerm(Base, BaseModel):
810 __tablename__ = 'user_user_group_to_perm'
810 __tablename__ = 'user_user_group_to_perm'
811 __table_args__ = (
811 __table_args__ = (
812 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
812 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
813 {'extend_existing': True, 'mysql_engine': 'InnoDB',
813 {'extend_existing': True, 'mysql_engine': 'InnoDB',
814 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
814 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
815 )
815 )
816 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
816 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
817 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
817 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
818 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
818 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
819 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
819 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
820
820
821 user = relationship('User')
821 user = relationship('User')
822 user_group = relationship('UserGroup')
822 user_group = relationship('UserGroup')
823 permission = relationship('Permission')
823 permission = relationship('Permission')
824
824
825 def __unicode__(self):
825 def __unicode__(self):
826 return u'<%s => %s >' % (self.user, self.user_group)
826 return u'<%s => %s >' % (self.user, self.user_group)
827
827
828
828
829 class UserToPerm(Base, BaseModel):
829 class UserToPerm(Base, BaseModel):
830 __tablename__ = 'user_to_perm'
830 __tablename__ = 'user_to_perm'
831 __table_args__ = (
831 __table_args__ = (
832 UniqueConstraint('user_id', 'permission_id'),
832 UniqueConstraint('user_id', 'permission_id'),
833 {'extend_existing': True, 'mysql_engine': 'InnoDB',
833 {'extend_existing': True, 'mysql_engine': 'InnoDB',
834 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
834 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
835 )
835 )
836 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
836 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
837 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
837 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
838 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
838 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
839
839
840 user = relationship('User')
840 user = relationship('User')
841 permission = relationship('Permission', lazy='joined')
841 permission = relationship('Permission', lazy='joined')
842
842
843 def __unicode__(self):
843 def __unicode__(self):
844 return u'<%s => %s >' % (self.user, self.permission)
844 return u'<%s => %s >' % (self.user, self.permission)
845
845
846
846
847 class UserGroupRepoToPerm(Base, BaseModel):
847 class UserGroupRepoToPerm(Base, BaseModel):
848 __tablename__ = 'users_group_repo_to_perm'
848 __tablename__ = 'users_group_repo_to_perm'
849 __table_args__ = (
849 __table_args__ = (
850 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
850 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
851 {'extend_existing': True, 'mysql_engine': 'InnoDB',
851 {'extend_existing': True, 'mysql_engine': 'InnoDB',
852 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
852 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
853 )
853 )
854 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
854 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
855 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
855 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
856 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
856 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
857 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
857 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
858
858
859 users_group = relationship('UserGroup')
859 users_group = relationship('UserGroup')
860 permission = relationship('Permission')
860 permission = relationship('Permission')
861 repository = relationship('Repository')
861 repository = relationship('Repository')
862
862
863 def __unicode__(self):
863 def __unicode__(self):
864 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
864 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
865
865
866
866
867 class UserGroupUserGroupToPerm(Base, BaseModel):
867 class UserGroupUserGroupToPerm(Base, BaseModel):
868 __tablename__ = 'user_group_user_group_to_perm'
868 __tablename__ = 'user_group_user_group_to_perm'
869 __table_args__ = (
869 __table_args__ = (
870 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
870 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
871 CheckConstraint('target_user_group_id != user_group_id'),
871 CheckConstraint('target_user_group_id != user_group_id'),
872 {'extend_existing': True, 'mysql_engine': 'InnoDB',
872 {'extend_existing': True, 'mysql_engine': 'InnoDB',
873 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
873 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
874 )
874 )
875 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
875 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
876 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
876 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
877 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
877 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
878 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
878 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
879
879
880 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
880 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
881 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
881 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
882 permission = relationship('Permission')
882 permission = relationship('Permission')
883
883
884 def __unicode__(self):
884 def __unicode__(self):
885 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
885 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
886
886
887
887
888 class UserGroupToPerm(Base, BaseModel):
888 class UserGroupToPerm(Base, BaseModel):
889 __tablename__ = 'users_group_to_perm'
889 __tablename__ = 'users_group_to_perm'
890 __table_args__ = (
890 __table_args__ = (
891 UniqueConstraint('users_group_id', 'permission_id',),
891 UniqueConstraint('users_group_id', 'permission_id',),
892 {'extend_existing': True, 'mysql_engine': 'InnoDB',
892 {'extend_existing': True, 'mysql_engine': 'InnoDB',
893 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
893 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
894 )
894 )
895 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
895 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
896 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
896 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
898
898
899 users_group = relationship('UserGroup')
899 users_group = relationship('UserGroup')
900 permission = relationship('Permission')
900 permission = relationship('Permission')
901
901
902
902
903 class UserRepoGroupToPerm(Base, BaseModel):
903 class UserRepoGroupToPerm(Base, BaseModel):
904 __tablename__ = 'user_repo_group_to_perm'
904 __tablename__ = 'user_repo_group_to_perm'
905 __table_args__ = (
905 __table_args__ = (
906 UniqueConstraint('user_id', 'group_id', 'permission_id'),
906 UniqueConstraint('user_id', 'group_id', 'permission_id'),
907 {'extend_existing': True, 'mysql_engine': 'InnoDB',
907 {'extend_existing': True, 'mysql_engine': 'InnoDB',
908 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
908 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
909 )
909 )
910
910
911 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
911 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
912 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
912 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
913 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
913 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
914 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
914 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
915
915
916 user = relationship('User')
916 user = relationship('User')
917 group = relationship('RepoGroup')
917 group = relationship('RepoGroup')
918 permission = relationship('Permission')
918 permission = relationship('Permission')
919
919
920
920
921 class UserGroupRepoGroupToPerm(Base, BaseModel):
921 class UserGroupRepoGroupToPerm(Base, BaseModel):
922 __tablename__ = 'users_group_repo_group_to_perm'
922 __tablename__ = 'users_group_repo_group_to_perm'
923 __table_args__ = (
923 __table_args__ = (
924 UniqueConstraint('users_group_id', 'group_id'),
924 UniqueConstraint('users_group_id', 'group_id'),
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
926 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
926 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
927 )
927 )
928
928
929 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)
929 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)
930 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
930 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
931 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
931 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
932 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
932 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
933
933
934 users_group = relationship('UserGroup')
934 users_group = relationship('UserGroup')
935 permission = relationship('Permission')
935 permission = relationship('Permission')
936 group = relationship('RepoGroup')
936 group = relationship('RepoGroup')
937
937
938
938
939 class Statistics(Base, BaseModel):
939 class Statistics(Base, BaseModel):
940 __tablename__ = 'statistics'
940 __tablename__ = 'statistics'
941 __table_args__ = (
941 __table_args__ = (
942 UniqueConstraint('repository_id'),
942 UniqueConstraint('repository_id'),
943 {'extend_existing': True, 'mysql_engine': 'InnoDB',
943 {'extend_existing': True, 'mysql_engine': 'InnoDB',
944 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
944 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
945 )
945 )
946 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
946 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
947 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
947 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
948 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
948 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
949 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
949 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
950 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
950 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
951 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
951 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
952
952
953 repository = relationship('Repository', single_parent=True)
953 repository = relationship('Repository', single_parent=True)
954
954
955
955
956 class UserFollowing(Base, BaseModel):
956 class UserFollowing(Base, BaseModel):
957 __tablename__ = 'user_followings'
957 __tablename__ = 'user_followings'
958 __table_args__ = (
958 __table_args__ = (
959 UniqueConstraint('user_id', 'follows_repository_id'),
959 UniqueConstraint('user_id', 'follows_repository_id'),
960 UniqueConstraint('user_id', 'follows_user_id'),
960 UniqueConstraint('user_id', 'follows_user_id'),
961 {'extend_existing': True, 'mysql_engine': 'InnoDB',
961 {'extend_existing': True, 'mysql_engine': 'InnoDB',
962 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
962 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
963 )
963 )
964
964
965 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
965 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
966 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
966 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
967 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
967 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
968 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
968 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
969 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
969 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
970
970
971 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
971 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
972
972
973 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
973 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
974 follows_repository = relationship('Repository', order_by='Repository.repo_name')
974 follows_repository = relationship('Repository', order_by='Repository.repo_name')
975
975
976
976
977 class CacheInvalidation(Base, BaseModel):
977 class CacheInvalidation(Base, BaseModel):
978 __tablename__ = 'cache_invalidation'
978 __tablename__ = 'cache_invalidation'
979 __table_args__ = (
979 __table_args__ = (
980 UniqueConstraint('cache_key'),
980 UniqueConstraint('cache_key'),
981 Index('key_idx', 'cache_key'),
981 Index('key_idx', 'cache_key'),
982 {'extend_existing': True, 'mysql_engine': 'InnoDB',
982 {'extend_existing': True, 'mysql_engine': 'InnoDB',
983 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
983 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
984 )
984 )
985 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
985 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
986 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
986 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
987 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
987 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
988 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
988 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
989
989
990 def __init__(self, cache_key, cache_args=''):
990 def __init__(self, cache_key, cache_args=''):
991 self.cache_key = cache_key
991 self.cache_key = cache_key
992 self.cache_args = cache_args
992 self.cache_args = cache_args
993 self.cache_active = False
993 self.cache_active = False
994
994
995
995
996 class ChangesetComment(Base, BaseModel):
996 class ChangesetComment(Base, BaseModel):
997 __tablename__ = 'changeset_comments'
997 __tablename__ = 'changeset_comments'
998 __table_args__ = (
998 __table_args__ = (
999 Index('cc_revision_idx', 'revision'),
999 Index('cc_revision_idx', 'revision'),
1000 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1000 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1001 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1001 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1002 )
1002 )
1003 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1003 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1004 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1004 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1005 revision = Column('revision', String(40), nullable=True)
1005 revision = Column('revision', String(40), nullable=True)
1006 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1006 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1007 line_no = Column('line_no', Unicode(10), nullable=True)
1007 line_no = Column('line_no', Unicode(10), nullable=True)
1008 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1008 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1009 f_path = Column('f_path', Unicode(1000), nullable=True)
1009 f_path = Column('f_path', Unicode(1000), nullable=True)
1010 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1010 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1011 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1011 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1012 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1012 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1013 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1013 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1014
1014
1015 author = relationship('User', lazy='joined')
1015 author = relationship('User', lazy='joined')
1016 repo = relationship('Repository')
1016 repo = relationship('Repository')
1017 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1017 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1018 pull_request = relationship('PullRequest', lazy='joined')
1018 pull_request = relationship('PullRequest', lazy='joined')
1019
1019
1020
1020
1021 class ChangesetStatus(Base, BaseModel):
1021 class ChangesetStatus(Base, BaseModel):
1022 __tablename__ = 'changeset_statuses'
1022 __tablename__ = 'changeset_statuses'
1023 __table_args__ = (
1023 __table_args__ = (
1024 Index('cs_revision_idx', 'revision'),
1024 Index('cs_revision_idx', 'revision'),
1025 Index('cs_version_idx', 'version'),
1025 Index('cs_version_idx', 'version'),
1026 UniqueConstraint('repo_id', 'revision', 'version'),
1026 UniqueConstraint('repo_id', 'revision', 'version'),
1027 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1027 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1028 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1028 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1029 )
1029 )
1030 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1030 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1031 STATUS_APPROVED = 'approved'
1031 STATUS_APPROVED = 'approved'
1032 STATUS_REJECTED = 'rejected'
1032 STATUS_REJECTED = 'rejected'
1033 STATUS_UNDER_REVIEW = 'under_review'
1033 STATUS_UNDER_REVIEW = 'under_review'
1034
1034
1035 STATUSES = [
1035 STATUSES = [
1036 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1036 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1037 (STATUS_APPROVED, _("Approved")),
1037 (STATUS_APPROVED, _("Approved")),
1038 (STATUS_REJECTED, _("Rejected")),
1038 (STATUS_REJECTED, _("Rejected")),
1039 (STATUS_UNDER_REVIEW, _("Under Review")),
1039 (STATUS_UNDER_REVIEW, _("Under Review")),
1040 ]
1040 ]
1041
1041
1042 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1042 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1043 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1043 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1044 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1044 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1045 revision = Column('revision', String(40), nullable=False)
1045 revision = Column('revision', String(40), nullable=False)
1046 status = Column('status', String(128), nullable=False, default=DEFAULT)
1046 status = Column('status', String(128), nullable=False, default=DEFAULT)
1047 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1047 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1048 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1048 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1049 version = Column('version', Integer(), nullable=False, default=0)
1049 version = Column('version', Integer(), nullable=False, default=0)
1050 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1050 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1051
1051
1052 author = relationship('User', lazy='joined')
1052 author = relationship('User', lazy='joined')
1053 repo = relationship('Repository')
1053 repo = relationship('Repository')
1054 comment = relationship('ChangesetComment', lazy='joined')
1054 comment = relationship('ChangesetComment', lazy='joined')
1055 pull_request = relationship('PullRequest', lazy='joined')
1055 pull_request = relationship('PullRequest', lazy='joined')
1056
1056
1057
1057
1058
1058
1059 class PullRequest(Base, BaseModel):
1059 class PullRequest(Base, BaseModel):
1060 __tablename__ = 'pull_requests'
1060 __tablename__ = 'pull_requests'
1061 __table_args__ = (
1061 __table_args__ = (
1062 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1062 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1063 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1063 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1064 )
1064 )
1065
1065
1066 STATUS_NEW = u'new'
1066 STATUS_NEW = u'new'
1067 STATUS_OPEN = u'open'
1067 STATUS_OPEN = u'open'
1068 STATUS_CLOSED = u'closed'
1068 STATUS_CLOSED = u'closed'
1069
1069
1070 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1070 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1071 title = Column('title', Unicode(256), nullable=True)
1071 title = Column('title', Unicode(256), nullable=True)
1072 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1072 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1073 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1073 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1074 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1074 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1075 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1075 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1076 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1076 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1077 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1077 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1078 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1078 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1079 org_ref = Column('org_ref', Unicode(256), nullable=False)
1079 org_ref = Column('org_ref', Unicode(256), nullable=False)
1080 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1080 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1081 other_ref = Column('other_ref', Unicode(256), nullable=False)
1081 other_ref = Column('other_ref', Unicode(256), nullable=False)
1082
1082
1083 author = relationship('User', lazy='joined')
1083 author = relationship('User', lazy='joined')
1084 reviewers = relationship('PullRequestReviewers',
1084 reviewers = relationship('PullRequestReviewers',
1085 cascade="all, delete, delete-orphan")
1085 cascade="all, delete, delete-orphan")
1086 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1086 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1087 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1087 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1088 statuses = relationship('ChangesetStatus')
1088 statuses = relationship('ChangesetStatus')
1089 comments = relationship('ChangesetComment',
1089 comments = relationship('ChangesetComment',
1090 cascade="all, delete, delete-orphan")
1090 cascade="all, delete, delete-orphan")
1091
1091
1092
1092
1093 class PullRequestReviewers(Base, BaseModel):
1093 class PullRequestReviewers(Base, BaseModel):
1094 __tablename__ = 'pull_request_reviewers'
1094 __tablename__ = 'pull_request_reviewers'
1095 __table_args__ = (
1095 __table_args__ = (
1096 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1096 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1097 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1097 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1098 )
1098 )
1099
1099
1100 def __init__(self, user=None, pull_request=None):
1100 def __init__(self, user=None, pull_request=None):
1101 self.user = user
1101 self.user = user
1102 self.pull_request = pull_request
1102 self.pull_request = pull_request
1103
1103
1104 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1104 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1105 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1105 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1106 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1106 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1107
1107
1108 user = relationship('User')
1108 user = relationship('User')
1109 pull_request = relationship('PullRequest')
1109 pull_request = relationship('PullRequest')
1110
1110
1111
1111
1112 class Notification(Base, BaseModel):
1112 class Notification(Base, BaseModel):
1113 __tablename__ = 'notifications'
1113 __tablename__ = 'notifications'
1114 __table_args__ = (
1114 __table_args__ = (
1115 Index('notification_type_idx', 'type'),
1115 Index('notification_type_idx', 'type'),
1116 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1116 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1117 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1117 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1118 )
1118 )
1119
1119
1120 TYPE_CHANGESET_COMMENT = u'cs_comment'
1120 TYPE_CHANGESET_COMMENT = u'cs_comment'
1121 TYPE_MESSAGE = u'message'
1121 TYPE_MESSAGE = u'message'
1122 TYPE_MENTION = u'mention'
1122 TYPE_MENTION = u'mention'
1123 TYPE_REGISTRATION = u'registration'
1123 TYPE_REGISTRATION = u'registration'
1124 TYPE_PULL_REQUEST = u'pull_request'
1124 TYPE_PULL_REQUEST = u'pull_request'
1125 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1125 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1126
1126
1127 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1127 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1128 subject = Column('subject', Unicode(512), nullable=True)
1128 subject = Column('subject', Unicode(512), nullable=True)
1129 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1129 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1130 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1130 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1131 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1131 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1132 type_ = Column('type', Unicode(256))
1132 type_ = Column('type', Unicode(256))
1133
1133
1134 created_by_user = relationship('User')
1134 created_by_user = relationship('User')
1135 notifications_to_users = relationship('UserNotification', lazy='joined',
1135 notifications_to_users = relationship('UserNotification', lazy='joined',
1136 cascade="all, delete, delete-orphan")
1136 cascade="all, delete, delete-orphan")
1137
1137
1138
1138
1139 class UserNotification(Base, BaseModel):
1139 class UserNotification(Base, BaseModel):
1140 __tablename__ = 'user_to_notification'
1140 __tablename__ = 'user_to_notification'
1141 __table_args__ = (
1141 __table_args__ = (
1142 UniqueConstraint('user_id', 'notification_id'),
1142 UniqueConstraint('user_id', 'notification_id'),
1143 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1143 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1144 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1144 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1145 )
1145 )
1146 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1146 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1147 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1147 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1148 read = Column('read', Boolean, default=False)
1148 read = Column('read', Boolean, default=False)
1149 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1149 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1150
1150
1151 user = relationship('User', lazy="joined")
1151 user = relationship('User', lazy="joined")
1152 notification = relationship('Notification', lazy="joined",
1152 notification = relationship('Notification', lazy="joined",
1153 order_by=lambda: Notification.created_on.desc(),)
1153 order_by=lambda: Notification.created_on.desc(),)
1154
1154
1155
1155
1156 class Gist(Base, BaseModel):
1156 class Gist(Base, BaseModel):
1157 __tablename__ = 'gists'
1157 __tablename__ = 'gists'
1158 __table_args__ = (
1158 __table_args__ = (
1159 Index('g_gist_access_id_idx', 'gist_access_id'),
1159 Index('g_gist_access_id_idx', 'gist_access_id'),
1160 Index('g_created_on_idx', 'created_on'),
1160 Index('g_created_on_idx', 'created_on'),
1161 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1161 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1162 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1162 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1163 )
1163 )
1164 GIST_PUBLIC = u'public'
1164 GIST_PUBLIC = u'public'
1165 GIST_PRIVATE = u'private'
1165 GIST_PRIVATE = u'private'
1166
1166
1167 gist_id = Column('gist_id', Integer(), primary_key=True)
1167 gist_id = Column('gist_id', Integer(), primary_key=True)
1168 gist_access_id = Column('gist_access_id', Unicode(250))
1168 gist_access_id = Column('gist_access_id', Unicode(250))
1169 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1169 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1170 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1170 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1171 gist_expires = Column('gist_expires', Float(53), nullable=False)
1171 gist_expires = Column('gist_expires', Float(53), nullable=False)
1172 gist_type = Column('gist_type', Unicode(128), nullable=False)
1172 gist_type = Column('gist_type', Unicode(128), nullable=False)
1173 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1173 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1174 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1174 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1175
1175
1176 owner = relationship('User')
1176 owner = relationship('User')
1177
1177
1178
1178
1179 class DbMigrateVersion(Base, BaseModel):
1179 class DbMigrateVersion(Base, BaseModel):
1180 __tablename__ = 'db_migrate_version'
1180 __tablename__ = 'db_migrate_version'
1181 __table_args__ = (
1181 __table_args__ = (
1182 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1182 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1183 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1183 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1184 )
1184 )
1185 repository_id = Column('repository_id', String(250), primary_key=True)
1185 repository_id = Column('repository_id', String(250), primary_key=True)
1186 repository_path = Column('repository_path', Text)
1186 repository_path = Column('repository_path', Text)
1187 version = Column('version', Integer)
1187 version = Column('version', Integer)
@@ -1,1204 +1,1204 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 from rhodecode.lib.ext_json import json
46 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.caching_query import FromCache
47 from rhodecode.lib.caching_query import FromCache
48
48
49 from rhodecode.model.meta import Base, Session
49 from rhodecode.model.meta import Base, Session
50
50
51 URL_SEP = '/'
51 URL_SEP = '/'
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 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
58 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59
59
60
60
61 class BaseModel(object):
61 class BaseModel(object):
62 """
62 """
63 Base Model for all classes
63 Base Model for all classes
64 """
64 """
65
65
66 @classmethod
66 @classmethod
67 def _get_keys(cls):
67 def _get_keys(cls):
68 """return column names for this model """
68 """return column names for this model """
69 return class_mapper(cls).c.keys()
69 return class_mapper(cls).c.keys()
70
70
71 def get_dict(self):
71 def get_dict(self):
72 """
72 """
73 return dict with keys and values corresponding
73 return dict with keys and values corresponding
74 to this model data """
74 to this model data """
75
75
76 d = {}
76 d = {}
77 for k in self._get_keys():
77 for k in self._get_keys():
78 d[k] = getattr(self, k)
78 d[k] = getattr(self, k)
79
79
80 # also use __json__() if present to get additional fields
80 # also use __json__() if present to get additional fields
81 _json_attr = getattr(self, '__json__', None)
81 _json_attr = getattr(self, '__json__', None)
82 if _json_attr:
82 if _json_attr:
83 # update with attributes from __json__
83 # update with attributes from __json__
84 if callable(_json_attr):
84 if callable(_json_attr):
85 _json_attr = _json_attr()
85 _json_attr = _json_attr()
86 for k, val in _json_attr.items():
86 for k, val in _json_attr.items():
87 d[k] = val
87 d[k] = val
88 return d
88 return d
89
89
90 def get_appstruct(self):
90 def get_appstruct(self):
91 """return list with keys and values tupples corresponding
91 """return list with keys and values tupples corresponding
92 to this model data """
92 to this model data """
93
93
94 l = []
94 l = []
95 for k in self._get_keys():
95 for k in self._get_keys():
96 l.append((k, getattr(self, k),))
96 l.append((k, getattr(self, k),))
97 return l
97 return l
98
98
99 def populate_obj(self, populate_dict):
99 def populate_obj(self, populate_dict):
100 """populate model with data from given populate_dict"""
100 """populate model with data from given populate_dict"""
101
101
102 for k in self._get_keys():
102 for k in self._get_keys():
103 if k in populate_dict:
103 if k in populate_dict:
104 setattr(self, k, populate_dict[k])
104 setattr(self, k, populate_dict[k])
105
105
106 @classmethod
106 @classmethod
107 def query(cls):
107 def query(cls):
108 return Session().query(cls)
108 return Session().query(cls)
109
109
110 @classmethod
110 @classmethod
111 def get(cls, id_):
111 def get(cls, id_):
112 if id_:
112 if id_:
113 return cls.query().get(id_)
113 return cls.query().get(id_)
114
114
115 @classmethod
115 @classmethod
116 def get_or_404(cls, id_):
116 def get_or_404(cls, id_):
117 try:
117 try:
118 id_ = int(id_)
118 id_ = int(id_)
119 except (TypeError, ValueError):
119 except (TypeError, ValueError):
120 raise HTTPNotFound
120 raise HTTPNotFound
121
121
122 res = cls.query().get(id_)
122 res = cls.query().get(id_)
123 if not res:
123 if not res:
124 raise HTTPNotFound
124 raise HTTPNotFound
125 return res
125 return res
126
126
127 @classmethod
127 @classmethod
128 def getAll(cls):
128 def getAll(cls):
129 # deprecated and left for backward compatibility
129 # deprecated and left for backward compatibility
130 return cls.get_all()
130 return cls.get_all()
131
131
132 @classmethod
132 @classmethod
133 def get_all(cls):
133 def get_all(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
140
141 def __repr__(self):
141 def __repr__(self):
142 if hasattr(self, '__unicode__'):
142 if hasattr(self, '__unicode__'):
143 # python repr needs to return str
143 # python repr needs to return str
144 try:
144 try:
145 return safe_str(self.__unicode__())
145 return safe_str(self.__unicode__())
146 except UnicodeDecodeError:
146 except UnicodeDecodeError:
147 pass
147 pass
148 return '<DB:%s>' % (self.__class__.__name__)
148 return '<DB:%s>' % (self.__class__.__name__)
149
149
150
150
151 class RhodeCodeSetting(Base, BaseModel):
151 class RhodeCodeSetting(Base, BaseModel):
152 __tablename__ = 'rhodecode_settings'
152 __tablename__ = 'rhodecode_settings'
153 __table_args__ = (
153 __table_args__ = (
154 UniqueConstraint('app_settings_name'),
154 UniqueConstraint('app_settings_name'),
155 {'extend_existing': True, 'mysql_engine': 'InnoDB',
155 {'extend_existing': True, 'mysql_engine': 'InnoDB',
156 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
156 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
157 )
157 )
158
158
159 SETTINGS_TYPES = {
159 SETTINGS_TYPES = {
160 'str': safe_str,
160 'str': safe_str,
161 'int': safe_int,
161 'int': safe_int,
162 'unicode': safe_str,
162 'unicode': safe_str,
163 'bool': str2bool,
163 'bool': str2bool,
164 'list': functools.partial(aslist, sep=',')
164 'list': functools.partial(aslist, sep=',')
165 }
165 }
166 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
166 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
167
167
168 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
168 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
169 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
169 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
170 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
170 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
171 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
171 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
172
172
173 def __init__(self, key='', val='', type='unicode'):
173 def __init__(self, key='', val='', type='unicode'):
174 self.app_settings_name = key
174 self.app_settings_name = key
175 self.app_settings_value = val
175 self.app_settings_value = val
176 self.app_settings_type = type
176 self.app_settings_type = type
177
177
178 @validates('_app_settings_value')
178 @validates('_app_settings_value')
179 def validate_settings_value(self, key, val):
179 def validate_settings_value(self, key, val):
180 assert type(val) == str
180 assert type(val) == str
181 return val
181 return val
182
182
183 @hybrid_property
183 @hybrid_property
184 def app_settings_value(self):
184 def app_settings_value(self):
185 v = self._app_settings_value
185 v = self._app_settings_value
186 _type = self.app_settings_type
186 _type = self.app_settings_type
187 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
187 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
188 return converter(v)
188 return converter(v)
189
189
190 @app_settings_value.setter
190 @app_settings_value.setter
191 def app_settings_value(self, val):
191 def app_settings_value(self, val):
192 """
192 """
193 Setter that will always make sure we use unicode in app_settings_value
193 Setter that will always make sure we use unicode in app_settings_value
194
194
195 :param val:
195 :param val:
196 """
196 """
197 self._app_settings_value = safe_str(val)
197 self._app_settings_value = safe_str(val)
198
198
199 @hybrid_property
199 @hybrid_property
200 def app_settings_type(self):
200 def app_settings_type(self):
201 return self._app_settings_type
201 return self._app_settings_type
202
202
203 @app_settings_type.setter
203 @app_settings_type.setter
204 def app_settings_type(self, val):
204 def app_settings_type(self, val):
205 if val not in self.SETTINGS_TYPES:
205 if val not in self.SETTINGS_TYPES:
206 raise Exception('type must be one of %s got %s'
206 raise Exception('type must be one of %s got %s'
207 % (self.SETTINGS_TYPES.keys(), val))
207 % (self.SETTINGS_TYPES.keys(), val))
208 self._app_settings_type = val
208 self._app_settings_type = val
209
209
210 def __unicode__(self):
210 def __unicode__(self):
211 return u"<%s('%s:%s[%s]')>" % (
211 return u"<%s('%s:%s[%s]')>" % (
212 self.__class__.__name__,
212 self.__class__.__name__,
213 self.app_settings_name, self.app_settings_value, self.app_settings_type
213 self.app_settings_name, self.app_settings_value, self.app_settings_type
214 )
214 )
215
215
216
216
217 class RhodeCodeUi(Base, BaseModel):
217 class RhodeCodeUi(Base, BaseModel):
218 __tablename__ = 'rhodecode_ui'
218 __tablename__ = 'rhodecode_ui'
219 __table_args__ = (
219 __table_args__ = (
220 UniqueConstraint('ui_key'),
220 UniqueConstraint('ui_key'),
221 {'extend_existing': True, 'mysql_engine': 'InnoDB',
221 {'extend_existing': True, 'mysql_engine': 'InnoDB',
222 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
222 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
223 )
223 )
224
224
225 HOOK_REPO_SIZE = 'changegroup.repo_size'
225 HOOK_REPO_SIZE = 'changegroup.repo_size'
226 HOOK_PUSH = 'changegroup.push_logger'
226 HOOK_PUSH = 'changegroup.push_logger'
227 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
227 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
228 HOOK_PULL = 'outgoing.pull_logger'
228 HOOK_PULL = 'outgoing.pull_logger'
229 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
229 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
230
230
231 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
231 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
232 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
233 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
233 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
234 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
234 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
235 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
235 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
236
236
237
237
238
238
239 class User(Base, BaseModel):
239 class User(Base, BaseModel):
240 __tablename__ = 'users'
240 __tablename__ = 'users'
241 __table_args__ = (
241 __table_args__ = (
242 UniqueConstraint('username'), UniqueConstraint('email'),
242 UniqueConstraint('username'), UniqueConstraint('email'),
243 Index('u_username_idx', 'username'),
243 Index('u_username_idx', 'username'),
244 Index('u_email_idx', 'email'),
244 Index('u_email_idx', 'email'),
245 {'extend_existing': True, 'mysql_engine': 'InnoDB',
245 {'extend_existing': True, 'mysql_engine': 'InnoDB',
246 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
246 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
247 )
247 )
248 DEFAULT_USER = 'default'
248 DEFAULT_USER = 'default'
249 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
249 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
250
250
251 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
251 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
252 username = Column("username", String(255), nullable=True, unique=None, default=None)
252 username = Column("username", String(255), nullable=True, unique=None, default=None)
253 password = Column("password", String(255), nullable=True, unique=None, default=None)
253 password = Column("password", String(255), nullable=True, unique=None, default=None)
254 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
254 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
255 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
255 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
256 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
256 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
257 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
257 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
258 _email = Column("email", String(255), nullable=True, unique=None, default=None)
258 _email = Column("email", String(255), nullable=True, unique=None, default=None)
259 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
259 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
260 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
260 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
261 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
261 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
262 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
262 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
263 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
263 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
264 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
264 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
265
265
266 user_log = relationship('UserLog')
266 user_log = relationship('UserLog')
267 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
267 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
268
268
269 repositories = relationship('Repository')
269 repositories = relationship('Repository')
270 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
270 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
271 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
271 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
272
272
273 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
273 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
274 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
274 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
275
275
276 group_member = relationship('UserGroupMember', cascade='all')
276 group_member = relationship('UserGroupMember', cascade='all')
277
277
278 notifications = relationship('UserNotification', cascade='all')
278 notifications = relationship('UserNotification', cascade='all')
279 # notifications assigned to this user
279 # notifications assigned to this user
280 user_created_notifications = relationship('Notification', cascade='all')
280 user_created_notifications = relationship('Notification', cascade='all')
281 # comments created by this user
281 # comments created by this user
282 user_comments = relationship('ChangesetComment', cascade='all')
282 user_comments = relationship('ChangesetComment', cascade='all')
283 user_emails = relationship('UserEmailMap', cascade='all')
283 user_emails = relationship('UserEmailMap', cascade='all')
284
284
285 @hybrid_property
285 @hybrid_property
286 def email(self):
286 def email(self):
287 return self._email
287 return self._email
288
288
289 @email.setter
289 @email.setter
290 def email(self, val):
290 def email(self, val):
291 self._email = val.lower() if val else None
291 self._email = val.lower() if val else None
292
292
293 @property
293 @property
294 def firstname(self):
294 def firstname(self):
295 # alias for future
295 # alias for future
296 return self.name
296 return self.name
297
297
298 @property
298 @property
299 def username_and_name(self):
299 def username_and_name(self):
300 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
300 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
301
301
302 @property
302 @property
303 def full_name(self):
303 def full_name(self):
304 return '%s %s' % (self.firstname, self.lastname)
304 return '%s %s' % (self.firstname, self.lastname)
305
305
306 @property
306 @property
307 def full_contact(self):
307 def full_contact(self):
308 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
308 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
309
309
310 @property
310 @property
311 def short_contact(self):
311 def short_contact(self):
312 return '%s %s' % (self.firstname, self.lastname)
312 return '%s %s' % (self.firstname, self.lastname)
313
313
314 @property
314 @property
315 def is_admin(self):
315 def is_admin(self):
316 return self.admin
316 return self.admin
317
317
318 @classmethod
318 @classmethod
319 def get_by_username(cls, username, case_insensitive=False, cache=False):
319 def get_by_username(cls, username, case_insensitive=False, cache=False):
320 if case_insensitive:
320 if case_insensitive:
321 q = cls.query().filter(cls.username.ilike(username))
321 q = cls.query().filter(cls.username.ilike(username))
322 else:
322 else:
323 q = cls.query().filter(cls.username == username)
323 q = cls.query().filter(cls.username == username)
324
324
325 if cache:
325 if cache:
326 q = q.options(FromCache(
326 q = q.options(FromCache(
327 "sql_cache_short",
327 "sql_cache_short",
328 "get_user_%s" % _hash_key(username)
328 "get_user_%s" % _hash_key(username)
329 )
329 )
330 )
330 )
331 return q.scalar()
331 return q.scalar()
332
332
333 @classmethod
333 @classmethod
334 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
334 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
335 q = cls.query().filter(cls.api_key == auth_token)
335 q = cls.query().filter(cls.api_key == auth_token)
336
336
337 if cache:
337 if cache:
338 q = q.options(FromCache("sql_cache_short",
338 q = q.options(FromCache("sql_cache_short",
339 "get_auth_token_%s" % auth_token))
339 "get_auth_token_%s" % auth_token))
340 res = q.scalar()
340 res = q.scalar()
341
341
342 if fallback and not res:
342 if fallback and not res:
343 #fallback to additional keys
343 #fallback to additional keys
344 _res = UserApiKeys.query()\
344 _res = UserApiKeys.query()\
345 .filter(UserApiKeys.api_key == auth_token)\
345 .filter(UserApiKeys.api_key == auth_token)\
346 .filter(or_(UserApiKeys.expires == -1,
346 .filter(or_(UserApiKeys.expires == -1,
347 UserApiKeys.expires >= time.time()))\
347 UserApiKeys.expires >= time.time()))\
348 .first()
348 .first()
349 if _res:
349 if _res:
350 res = _res.user
350 res = _res.user
351 return res
351 return res
352
352
353 @classmethod
353 @classmethod
354 def get_by_email(cls, email, case_insensitive=False, cache=False):
354 def get_by_email(cls, email, case_insensitive=False, cache=False):
355
355
356 if case_insensitive:
356 if case_insensitive:
357 q = cls.query().filter(cls.email.ilike(email))
357 q = cls.query().filter(cls.email.ilike(email))
358 else:
358 else:
359 q = cls.query().filter(cls.email == email)
359 q = cls.query().filter(cls.email == email)
360
360
361 if cache:
361 if cache:
362 q = q.options(FromCache("sql_cache_short",
362 q = q.options(FromCache("sql_cache_short",
363 "get_email_key_%s" % email))
363 "get_email_key_%s" % email))
364
364
365 ret = q.scalar()
365 ret = q.scalar()
366 if ret is None:
366 if ret is None:
367 q = UserEmailMap.query()
367 q = UserEmailMap.query()
368 # try fetching in alternate email map
368 # try fetching in alternate email map
369 if case_insensitive:
369 if case_insensitive:
370 q = q.filter(UserEmailMap.email.ilike(email))
370 q = q.filter(UserEmailMap.email.ilike(email))
371 else:
371 else:
372 q = q.filter(UserEmailMap.email == email)
372 q = q.filter(UserEmailMap.email == email)
373 q = q.options(joinedload(UserEmailMap.user))
373 q = q.options(joinedload(UserEmailMap.user))
374 if cache:
374 if cache:
375 q = q.options(FromCache("sql_cache_short",
375 q = q.options(FromCache("sql_cache_short",
376 "get_email_map_key_%s" % email))
376 "get_email_map_key_%s" % email))
377 ret = getattr(q.scalar(), 'user', None)
377 ret = getattr(q.scalar(), 'user', None)
378
378
379 return ret
379 return ret
380
380
381 @classmethod
381 @classmethod
382 def get_first_admin(cls):
382 def get_first_admin(cls):
383 user = User.query().filter(User.admin == True).first()
383 user = User.query().filter(User.admin == True).first()
384 if user is None:
384 if user is None:
385 raise Exception('Missing administrative account!')
385 raise Exception('Missing administrative account!')
386 return user
386 return user
387
387
388 @classmethod
388 @classmethod
389 def get_default_user(cls, cache=False):
389 def get_default_user(cls, cache=False):
390 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
390 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
391 if user is None:
391 if user is None:
392 raise Exception('Missing default account!')
392 raise Exception('Missing default account!')
393 return user
393 return user
394
394
395
395
396 class UserApiKeys(Base, BaseModel):
396 class UserApiKeys(Base, BaseModel):
397 __tablename__ = 'user_api_keys'
397 __tablename__ = 'user_api_keys'
398 __table_args__ = (
398 __table_args__ = (
399 Index('uak_api_key_idx', 'api_key'),
399 Index('uak_api_key_idx', 'api_key'),
400 UniqueConstraint('api_key'),
400 UniqueConstraint('api_key'),
401 {'extend_existing': True, 'mysql_engine': 'InnoDB',
401 {'extend_existing': True, 'mysql_engine': 'InnoDB',
402 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
402 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
403 )
403 )
404
404
405
405
406 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
406 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
407 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
407 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
408 api_key = Column("api_key", String(255), nullable=False, unique=True)
408 api_key = Column("api_key", String(255), nullable=False, unique=True)
409 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
409 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
410 expires = Column('expires', Float(53), nullable=False)
410 expires = Column('expires', Float(53), nullable=False)
411 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
411 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
412
412
413 user = relationship('User', lazy='joined')
413 user = relationship('User', lazy='joined')
414
414
415
415
416 class UserEmailMap(Base, BaseModel):
416 class UserEmailMap(Base, BaseModel):
417 __tablename__ = 'user_email_map'
417 __tablename__ = 'user_email_map'
418 __table_args__ = (
418 __table_args__ = (
419 Index('uem_email_idx', 'email'),
419 Index('uem_email_idx', 'email'),
420 UniqueConstraint('email'),
420 UniqueConstraint('email'),
421 {'extend_existing': True, 'mysql_engine': 'InnoDB',
421 {'extend_existing': True, 'mysql_engine': 'InnoDB',
422 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
422 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
423 )
423 )
424
424
425
425
426 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
426 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
427 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
427 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
428 _email = Column("email", String(255), nullable=True, unique=False, default=None)
428 _email = Column("email", String(255), nullable=True, unique=False, default=None)
429 user = relationship('User', lazy='joined')
429 user = relationship('User', lazy='joined')
430
430
431 @validates('_email')
431 @validates('_email')
432 def validate_email(self, key, email):
432 def validate_email(self, key, email):
433 # check if this email is not main one
433 # check if this email is not main one
434 main_email = Session().query(User).filter(User.email == email).scalar()
434 main_email = Session().query(User).filter(User.email == email).scalar()
435 if main_email is not None:
435 if main_email is not None:
436 raise AttributeError('email %s is present is user table' % email)
436 raise AttributeError('email %s is present is user table' % email)
437 return email
437 return email
438
438
439 @hybrid_property
439 @hybrid_property
440 def email(self):
440 def email(self):
441 return self._email
441 return self._email
442
442
443 @email.setter
443 @email.setter
444 def email(self, val):
444 def email(self, val):
445 self._email = val.lower() if val else None
445 self._email = val.lower() if val else None
446
446
447
447
448 class UserIpMap(Base, BaseModel):
448 class UserIpMap(Base, BaseModel):
449 __tablename__ = 'user_ip_map'
449 __tablename__ = 'user_ip_map'
450 __table_args__ = (
450 __table_args__ = (
451 UniqueConstraint('user_id', 'ip_addr'),
451 UniqueConstraint('user_id', 'ip_addr'),
452 {'extend_existing': True, 'mysql_engine': 'InnoDB',
452 {'extend_existing': True, 'mysql_engine': 'InnoDB',
453 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
453 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
454 )
454 )
455
455
456
456
457 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
457 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
458 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
458 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
459 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
459 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
460 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
460 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
461 user = relationship('User', lazy='joined')
461 user = relationship('User', lazy='joined')
462
462
463
463
464 class UserLog(Base, BaseModel):
464 class UserLog(Base, BaseModel):
465 __tablename__ = 'user_logs'
465 __tablename__ = 'user_logs'
466 __table_args__ = (
466 __table_args__ = (
467 {'extend_existing': True, 'mysql_engine': 'InnoDB',
467 {'extend_existing': True, 'mysql_engine': 'InnoDB',
468 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
468 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
469 )
469 )
470 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
470 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
471 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
471 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
472 username = Column("username", String(255), nullable=True, unique=None, default=None)
472 username = Column("username", String(255), nullable=True, unique=None, default=None)
473 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
473 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
474 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
474 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
475 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
475 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
476 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
476 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
477 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
477 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
478
478
479 def __unicode__(self):
479 def __unicode__(self):
480 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
480 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
481 self.repository_name,
481 self.repository_name,
482 self.action)
482 self.action)
483
483
484 user = relationship('User')
484 user = relationship('User')
485 repository = relationship('Repository', cascade='')
485 repository = relationship('Repository', cascade='')
486
486
487
487
488 class UserGroup(Base, BaseModel):
488 class UserGroup(Base, BaseModel):
489 __tablename__ = 'users_groups'
489 __tablename__ = 'users_groups'
490 __table_args__ = (
490 __table_args__ = (
491 {'extend_existing': True, 'mysql_engine': 'InnoDB',
491 {'extend_existing': True, 'mysql_engine': 'InnoDB',
492 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
492 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
493 )
493 )
494
494
495 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
495 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
496 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
496 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
497 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
497 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
498 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
498 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
499 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
499 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
500 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
500 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
501 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
501 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
502
502
503 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
503 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
504 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
504 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
505 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
505 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
506 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
506 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
507 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
507 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
508 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
508 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
509
509
510 user = relationship('User')
510 user = relationship('User')
511
511
512 def __unicode__(self):
512 def __unicode__(self):
513 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
513 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
514 self.users_group_id,
514 self.users_group_id,
515 self.users_group_name)
515 self.users_group_name)
516
516
517 @classmethod
517 @classmethod
518 def get_by_group_name(cls, group_name, cache=False,
518 def get_by_group_name(cls, group_name, cache=False,
519 case_insensitive=False):
519 case_insensitive=False):
520 if case_insensitive:
520 if case_insensitive:
521 q = cls.query().filter(cls.users_group_name.ilike(group_name))
521 q = cls.query().filter(cls.users_group_name.ilike(group_name))
522 else:
522 else:
523 q = cls.query().filter(cls.users_group_name == group_name)
523 q = cls.query().filter(cls.users_group_name == group_name)
524 if cache:
524 if cache:
525 q = q.options(FromCache(
525 q = q.options(FromCache(
526 "sql_cache_short",
526 "sql_cache_short",
527 "get_user_%s" % _hash_key(group_name)
527 "get_user_%s" % _hash_key(group_name)
528 )
528 )
529 )
529 )
530 return q.scalar()
530 return q.scalar()
531
531
532 @classmethod
532 @classmethod
533 def get(cls, user_group_id, cache=False):
533 def get(cls, user_group_id, cache=False):
534 user_group = cls.query()
534 user_group = cls.query()
535 if cache:
535 if cache:
536 user_group = user_group.options(FromCache("sql_cache_short",
536 user_group = user_group.options(FromCache("sql_cache_short",
537 "get_users_group_%s" % user_group_id))
537 "get_users_group_%s" % user_group_id))
538 return user_group.get(user_group_id)
538 return user_group.get(user_group_id)
539
539
540
540
541 class UserGroupMember(Base, BaseModel):
541 class UserGroupMember(Base, BaseModel):
542 __tablename__ = 'users_groups_members'
542 __tablename__ = 'users_groups_members'
543 __table_args__ = (
543 __table_args__ = (
544 {'extend_existing': True, 'mysql_engine': 'InnoDB',
544 {'extend_existing': True, 'mysql_engine': 'InnoDB',
545 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
545 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
546 )
546 )
547
547
548 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
548 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
549 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
549 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
550 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
550 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
551
551
552 user = relationship('User', lazy='joined')
552 user = relationship('User', lazy='joined')
553 users_group = relationship('UserGroup')
553 users_group = relationship('UserGroup')
554
554
555 def __init__(self, gr_id='', u_id=''):
555 def __init__(self, gr_id='', u_id=''):
556 self.users_group_id = gr_id
556 self.users_group_id = gr_id
557 self.user_id = u_id
557 self.user_id = u_id
558
558
559
559
560 class RepositoryField(Base, BaseModel):
560 class RepositoryField(Base, BaseModel):
561 __tablename__ = 'repositories_fields'
561 __tablename__ = 'repositories_fields'
562 __table_args__ = (
562 __table_args__ = (
563 UniqueConstraint('repository_id', 'field_key'), # no-multi field
563 UniqueConstraint('repository_id', 'field_key'), # no-multi field
564 {'extend_existing': True, 'mysql_engine': 'InnoDB',
564 {'extend_existing': True, 'mysql_engine': 'InnoDB',
565 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
565 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
566 )
566 )
567 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
567 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
568
568
569 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
569 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
570 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
570 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
571 field_key = Column("field_key", String(250))
571 field_key = Column("field_key", String(250))
572 field_label = Column("field_label", String(1024), nullable=False)
572 field_label = Column("field_label", String(1024), nullable=False)
573 field_value = Column("field_value", String(10000), nullable=False)
573 field_value = Column("field_value", String(10000), nullable=False)
574 field_desc = Column("field_desc", String(1024), nullable=False)
574 field_desc = Column("field_desc", String(1024), nullable=False)
575 field_type = Column("field_type", String(256), nullable=False, unique=None)
575 field_type = Column("field_type", String(256), nullable=False, unique=None)
576 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
576 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
577
577
578 repository = relationship('Repository')
578 repository = relationship('Repository')
579
579
580 @classmethod
580 @classmethod
581 def get_by_key_name(cls, key, repo):
581 def get_by_key_name(cls, key, repo):
582 row = cls.query()\
582 row = cls.query()\
583 .filter(cls.repository == repo)\
583 .filter(cls.repository == repo)\
584 .filter(cls.field_key == key).scalar()
584 .filter(cls.field_key == key).scalar()
585 return row
585 return row
586
586
587
587
588 class Repository(Base, BaseModel):
588 class Repository(Base, BaseModel):
589 __tablename__ = 'repositories'
589 __tablename__ = 'repositories'
590 __table_args__ = (
590 __table_args__ = (
591 UniqueConstraint('repo_name'),
591 UniqueConstraint('repo_name'),
592 Index('r_repo_name_idx', 'repo_name'),
592 Index('r_repo_name_idx', 'repo_name'),
593 {'extend_existing': True, 'mysql_engine': 'InnoDB',
593 {'extend_existing': True, 'mysql_engine': 'InnoDB',
594 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
594 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
595 )
595 )
596 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
596 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
597
597
598 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
598 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
599 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
599 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
600 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
600 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
601 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
601 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
602 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
602 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
603 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
603 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
604 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
604 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
605 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
605 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
606 description = Column("description", String(10000), nullable=True, unique=None, default=None)
606 description = Column("description", String(10000), nullable=True, unique=None, default=None)
607 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
607 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
608 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
608 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
609 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
609 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
610 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
610 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
611 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
611 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
612 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
612 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
613
613
614 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
614 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
615 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
615 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
616
616
617 user = relationship('User')
617 user = relationship('User')
618 fork = relationship('Repository', remote_side=repo_id)
618 fork = relationship('Repository', remote_side=repo_id)
619 group = relationship('RepoGroup')
619 group = relationship('RepoGroup')
620 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
620 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
621 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
621 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
622 stats = relationship('Statistics', cascade='all', uselist=False)
622 stats = relationship('Statistics', cascade='all', uselist=False)
623
623
624 followers = relationship('UserFollowing',
624 followers = relationship('UserFollowing',
625 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
625 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
626 cascade='all')
626 cascade='all')
627 extra_fields = relationship('RepositoryField',
627 extra_fields = relationship('RepositoryField',
628 cascade="all, delete, delete-orphan")
628 cascade="all, delete, delete-orphan")
629
629
630 logs = relationship('UserLog')
630 logs = relationship('UserLog')
631 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
631 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
632
632
633 pull_requests_org = relationship('PullRequest',
633 pull_requests_org = relationship('PullRequest',
634 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
634 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
635 cascade="all, delete, delete-orphan")
635 cascade="all, delete, delete-orphan")
636
636
637 pull_requests_other = relationship('PullRequest',
637 pull_requests_other = relationship('PullRequest',
638 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
638 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
639 cascade="all, delete, delete-orphan")
639 cascade="all, delete, delete-orphan")
640
640
641 def __unicode__(self):
641 def __unicode__(self):
642 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
642 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
643 safe_str(self.repo_name))
643 safe_str(self.repo_name))
644
644
645 @classmethod
645 @classmethod
646 def get_by_repo_name(cls, repo_name):
646 def get_by_repo_name(cls, repo_name):
647 q = Session().query(cls).filter(cls.repo_name == repo_name)
647 q = Session().query(cls).filter(cls.repo_name == repo_name)
648 q = q.options(joinedload(Repository.fork))\
648 q = q.options(joinedload(Repository.fork))\
649 .options(joinedload(Repository.user))\
649 .options(joinedload(Repository.user))\
650 .options(joinedload(Repository.group))
650 .options(joinedload(Repository.group))
651 return q.scalar()
651 return q.scalar()
652
652
653
653
654 class RepoGroup(Base, BaseModel):
654 class RepoGroup(Base, BaseModel):
655 __tablename__ = 'groups'
655 __tablename__ = 'groups'
656 __table_args__ = (
656 __table_args__ = (
657 UniqueConstraint('group_name', 'group_parent_id'),
657 UniqueConstraint('group_name', 'group_parent_id'),
658 {'extend_existing': True, 'mysql_engine': 'InnoDB',
658 {'extend_existing': True, 'mysql_engine': 'InnoDB',
659 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
659 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
660 )
660 )
661
661
662
662
663 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
663 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
664 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
664 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
665 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
665 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
666 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
666 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
667 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
667 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
668 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
668 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
669 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
669 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
670
670
671 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
671 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
672 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
672 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
673 parent_group = relationship('RepoGroup', remote_side=group_id)
673 parent_group = relationship('RepoGroup', remote_side=group_id)
674 user = relationship('User')
674 user = relationship('User')
675
675
676 def __init__(self, group_name='', parent_group=None):
676 def __init__(self, group_name='', parent_group=None):
677 self.group_name = group_name
677 self.group_name = group_name
678 self.parent_group = parent_group
678 self.parent_group = parent_group
679
679
680 def __unicode__(self):
680 def __unicode__(self):
681 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
681 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
682 self.group_name)
682 self.group_name)
683
683
684 @classmethod
684 @classmethod
685 def url_sep(cls):
685 def url_sep(cls):
686 return URL_SEP
686 return URL_SEP
687
687
688 @classmethod
688 @classmethod
689 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
689 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
690 if case_insensitive:
690 if case_insensitive:
691 gr = cls.query()\
691 gr = cls.query()\
692 .filter(cls.group_name.ilike(group_name))
692 .filter(cls.group_name.ilike(group_name))
693 else:
693 else:
694 gr = cls.query()\
694 gr = cls.query()\
695 .filter(cls.group_name == group_name)
695 .filter(cls.group_name == group_name)
696 if cache:
696 if cache:
697 gr = gr.options(FromCache(
697 gr = gr.options(FromCache(
698 "sql_cache_short",
698 "sql_cache_short",
699 "get_group_%s" % _hash_key(group_name)
699 "get_group_%s" % _hash_key(group_name)
700 )
700 )
701 )
701 )
702 return gr.scalar()
702 return gr.scalar()
703
703
704
704
705 class Permission(Base, BaseModel):
705 class Permission(Base, BaseModel):
706 __tablename__ = 'permissions'
706 __tablename__ = 'permissions'
707 __table_args__ = (
707 __table_args__ = (
708 Index('p_perm_name_idx', 'permission_name'),
708 Index('p_perm_name_idx', 'permission_name'),
709 {'extend_existing': True, 'mysql_engine': 'InnoDB',
709 {'extend_existing': True, 'mysql_engine': 'InnoDB',
710 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
710 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
711 )
711 )
712 PERMS = [
712 PERMS = [
713 ('hg.admin', _('RhodeCode Administrator')),
713 ('hg.admin', _('RhodeCode Administrator')),
714
714
715 ('repository.none', _('Repository no access')),
715 ('repository.none', _('Repository no access')),
716 ('repository.read', _('Repository read access')),
716 ('repository.read', _('Repository read access')),
717 ('repository.write', _('Repository write access')),
717 ('repository.write', _('Repository write access')),
718 ('repository.admin', _('Repository admin access')),
718 ('repository.admin', _('Repository admin access')),
719
719
720 ('group.none', _('Repository group no access')),
720 ('group.none', _('Repository group no access')),
721 ('group.read', _('Repository group read access')),
721 ('group.read', _('Repository group read access')),
722 ('group.write', _('Repository group write access')),
722 ('group.write', _('Repository group write access')),
723 ('group.admin', _('Repository group admin access')),
723 ('group.admin', _('Repository group admin access')),
724
724
725 ('usergroup.none', _('User group no access')),
725 ('usergroup.none', _('User group no access')),
726 ('usergroup.read', _('User group read access')),
726 ('usergroup.read', _('User group read access')),
727 ('usergroup.write', _('User group write access')),
727 ('usergroup.write', _('User group write access')),
728 ('usergroup.admin', _('User group admin access')),
728 ('usergroup.admin', _('User group admin access')),
729
729
730 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
730 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
731 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
731 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
732
732
733 ('hg.usergroup.create.false', _('User Group creation disabled')),
733 ('hg.usergroup.create.false', _('User Group creation disabled')),
734 ('hg.usergroup.create.true', _('User Group creation enabled')),
734 ('hg.usergroup.create.true', _('User Group creation enabled')),
735
735
736 ('hg.create.none', _('Repository creation disabled')),
736 ('hg.create.none', _('Repository creation disabled')),
737 ('hg.create.repository', _('Repository creation enabled')),
737 ('hg.create.repository', _('Repository creation enabled')),
738
738
739 ('hg.fork.none', _('Repository forking disabled')),
739 ('hg.fork.none', _('Repository forking disabled')),
740 ('hg.fork.repository', _('Repository forking enabled')),
740 ('hg.fork.repository', _('Repository forking enabled')),
741
741
742 ('hg.register.none', _('Registration disabled')),
742 ('hg.register.none', _('Registration disabled')),
743 ('hg.register.manual_activate', _('User Registration with manual account activation')),
743 ('hg.register.manual_activate', _('User Registration with manual account activation')),
744 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
744 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
745
745
746 ('hg.extern_activate.manual', _('Manual activation of external account')),
746 ('hg.extern_activate.manual', _('Manual activation of external account')),
747 ('hg.extern_activate.auto', _('Automatic activation of external account')),
747 ('hg.extern_activate.auto', _('Automatic activation of external account')),
748
748
749 ]
749 ]
750
750
751 #definition of system default permissions for DEFAULT user
751 #definition of system default permissions for DEFAULT user
752 DEFAULT_USER_PERMISSIONS = [
752 DEFAULT_USER_PERMISSIONS = [
753 'repository.read',
753 'repository.read',
754 'group.read',
754 'group.read',
755 'usergroup.read',
755 'usergroup.read',
756 'hg.create.repository',
756 'hg.create.repository',
757 'hg.fork.repository',
757 'hg.fork.repository',
758 'hg.register.manual_activate',
758 'hg.register.manual_activate',
759 'hg.extern_activate.auto',
759 'hg.extern_activate.auto',
760 ]
760 ]
761
761
762 # defines which permissions are more important higher the more important
762 # defines which permissions are more important higher the more important
763 # Weight defines which permissions are more important.
763 # Weight defines which permissions are more important.
764 # The higher number the more important.
764 # The higher number the more important.
765 PERM_WEIGHTS = {
765 PERM_WEIGHTS = {
766 'repository.none': 0,
766 'repository.none': 0,
767 'repository.read': 1,
767 'repository.read': 1,
768 'repository.write': 3,
768 'repository.write': 3,
769 'repository.admin': 4,
769 'repository.admin': 4,
770
770
771 'group.none': 0,
771 'group.none': 0,
772 'group.read': 1,
772 'group.read': 1,
773 'group.write': 3,
773 'group.write': 3,
774 'group.admin': 4,
774 'group.admin': 4,
775
775
776 'usergroup.none': 0,
776 'usergroup.none': 0,
777 'usergroup.read': 1,
777 'usergroup.read': 1,
778 'usergroup.write': 3,
778 'usergroup.write': 3,
779 'usergroup.admin': 4,
779 'usergroup.admin': 4,
780 'hg.repogroup.create.false': 0,
780 'hg.repogroup.create.false': 0,
781 'hg.repogroup.create.true': 1,
781 'hg.repogroup.create.true': 1,
782
782
783 'hg.usergroup.create.false': 0,
783 'hg.usergroup.create.false': 0,
784 'hg.usergroup.create.true': 1,
784 'hg.usergroup.create.true': 1,
785
785
786 'hg.fork.none': 0,
786 'hg.fork.none': 0,
787 'hg.fork.repository': 1,
787 'hg.fork.repository': 1,
788 'hg.create.none': 0,
788 'hg.create.none': 0,
789 'hg.create.repository': 1
789 'hg.create.repository': 1
790 }
790 }
791
791
792 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
792 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
793 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
793 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
794 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
794 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
795
795
796 def __unicode__(self):
796 def __unicode__(self):
797 return u"<%s('%s:%s')>" % (
797 return u"<%s('%s:%s')>" % (
798 self.__class__.__name__, self.permission_id, self.permission_name
798 self.__class__.__name__, self.permission_id, self.permission_name
799 )
799 )
800
800
801 @classmethod
801 @classmethod
802 def get_by_key(cls, key):
802 def get_by_key(cls, key):
803 return cls.query().filter(cls.permission_name == key).scalar()
803 return cls.query().filter(cls.permission_name == key).scalar()
804
804
805
805
806 class UserRepoToPerm(Base, BaseModel):
806 class UserRepoToPerm(Base, BaseModel):
807 __tablename__ = 'repo_to_perm'
807 __tablename__ = 'repo_to_perm'
808 __table_args__ = (
808 __table_args__ = (
809 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
809 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
810 {'extend_existing': True, 'mysql_engine': 'InnoDB',
810 {'extend_existing': True, 'mysql_engine': 'InnoDB',
811 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
811 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
812 )
812 )
813 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
813 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
814 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
814 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
815 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
815 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
816 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
816 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
817
817
818 user = relationship('User')
818 user = relationship('User')
819 repository = relationship('Repository')
819 repository = relationship('Repository')
820 permission = relationship('Permission')
820 permission = relationship('Permission')
821
821
822 def __unicode__(self):
822 def __unicode__(self):
823 return u'<%s => %s >' % (self.user, self.repository)
823 return u'<%s => %s >' % (self.user, self.repository)
824
824
825
825
826 class UserUserGroupToPerm(Base, BaseModel):
826 class UserUserGroupToPerm(Base, BaseModel):
827 __tablename__ = 'user_user_group_to_perm'
827 __tablename__ = 'user_user_group_to_perm'
828 __table_args__ = (
828 __table_args__ = (
829 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
829 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
830 {'extend_existing': True, 'mysql_engine': 'InnoDB',
830 {'extend_existing': True, 'mysql_engine': 'InnoDB',
831 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
831 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
832 )
832 )
833 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
833 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
834 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
834 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
835 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
835 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
836 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
836 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
837
837
838 user = relationship('User')
838 user = relationship('User')
839 user_group = relationship('UserGroup')
839 user_group = relationship('UserGroup')
840 permission = relationship('Permission')
840 permission = relationship('Permission')
841
841
842 def __unicode__(self):
842 def __unicode__(self):
843 return u'<%s => %s >' % (self.user, self.user_group)
843 return u'<%s => %s >' % (self.user, self.user_group)
844
844
845
845
846 class UserToPerm(Base, BaseModel):
846 class UserToPerm(Base, BaseModel):
847 __tablename__ = 'user_to_perm'
847 __tablename__ = 'user_to_perm'
848 __table_args__ = (
848 __table_args__ = (
849 UniqueConstraint('user_id', 'permission_id'),
849 UniqueConstraint('user_id', 'permission_id'),
850 {'extend_existing': True, 'mysql_engine': 'InnoDB',
850 {'extend_existing': True, 'mysql_engine': 'InnoDB',
851 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
851 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
852 )
852 )
853 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
853 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
854 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
854 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
855 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
855 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
856
856
857 user = relationship('User')
857 user = relationship('User')
858 permission = relationship('Permission', lazy='joined')
858 permission = relationship('Permission', lazy='joined')
859
859
860 def __unicode__(self):
860 def __unicode__(self):
861 return u'<%s => %s >' % (self.user, self.permission)
861 return u'<%s => %s >' % (self.user, self.permission)
862
862
863
863
864 class UserGroupRepoToPerm(Base, BaseModel):
864 class UserGroupRepoToPerm(Base, BaseModel):
865 __tablename__ = 'users_group_repo_to_perm'
865 __tablename__ = 'users_group_repo_to_perm'
866 __table_args__ = (
866 __table_args__ = (
867 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
867 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
868 {'extend_existing': True, 'mysql_engine': 'InnoDB',
868 {'extend_existing': True, 'mysql_engine': 'InnoDB',
869 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
869 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
870 )
870 )
871 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
871 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
872 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
872 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
873 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
873 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
874 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
874 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
875
875
876 users_group = relationship('UserGroup')
876 users_group = relationship('UserGroup')
877 permission = relationship('Permission')
877 permission = relationship('Permission')
878 repository = relationship('Repository')
878 repository = relationship('Repository')
879
879
880 def __unicode__(self):
880 def __unicode__(self):
881 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
881 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
882
882
883
883
884 class UserGroupUserGroupToPerm(Base, BaseModel):
884 class UserGroupUserGroupToPerm(Base, BaseModel):
885 __tablename__ = 'user_group_user_group_to_perm'
885 __tablename__ = 'user_group_user_group_to_perm'
886 __table_args__ = (
886 __table_args__ = (
887 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
887 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
888 CheckConstraint('target_user_group_id != user_group_id'),
888 CheckConstraint('target_user_group_id != user_group_id'),
889 {'extend_existing': True, 'mysql_engine': 'InnoDB',
889 {'extend_existing': True, 'mysql_engine': 'InnoDB',
890 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
890 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
891 )
891 )
892 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
892 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
893 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
893 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
894 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
894 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
895 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
895 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
896
896
897 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
897 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
898 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
898 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
899 permission = relationship('Permission')
899 permission = relationship('Permission')
900
900
901 def __unicode__(self):
901 def __unicode__(self):
902 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
902 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
903
903
904
904
905 class UserGroupToPerm(Base, BaseModel):
905 class UserGroupToPerm(Base, BaseModel):
906 __tablename__ = 'users_group_to_perm'
906 __tablename__ = 'users_group_to_perm'
907 __table_args__ = (
907 __table_args__ = (
908 UniqueConstraint('users_group_id', 'permission_id',),
908 UniqueConstraint('users_group_id', 'permission_id',),
909 {'extend_existing': True, 'mysql_engine': 'InnoDB',
909 {'extend_existing': True, 'mysql_engine': 'InnoDB',
910 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
910 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
911 )
911 )
912 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
912 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
913 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
913 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
914 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
914 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
915
915
916 users_group = relationship('UserGroup')
916 users_group = relationship('UserGroup')
917 permission = relationship('Permission')
917 permission = relationship('Permission')
918
918
919
919
920 class UserRepoGroupToPerm(Base, BaseModel):
920 class UserRepoGroupToPerm(Base, BaseModel):
921 __tablename__ = 'user_repo_group_to_perm'
921 __tablename__ = 'user_repo_group_to_perm'
922 __table_args__ = (
922 __table_args__ = (
923 UniqueConstraint('user_id', 'group_id', 'permission_id'),
923 UniqueConstraint('user_id', 'group_id', 'permission_id'),
924 {'extend_existing': True, 'mysql_engine': 'InnoDB',
924 {'extend_existing': True, 'mysql_engine': 'InnoDB',
925 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
925 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
926 )
926 )
927
927
928 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
928 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
929 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
929 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
930 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
930 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
931 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
931 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
932
932
933 user = relationship('User')
933 user = relationship('User')
934 group = relationship('RepoGroup')
934 group = relationship('RepoGroup')
935 permission = relationship('Permission')
935 permission = relationship('Permission')
936
936
937
937
938 class UserGroupRepoGroupToPerm(Base, BaseModel):
938 class UserGroupRepoGroupToPerm(Base, BaseModel):
939 __tablename__ = 'users_group_repo_group_to_perm'
939 __tablename__ = 'users_group_repo_group_to_perm'
940 __table_args__ = (
940 __table_args__ = (
941 UniqueConstraint('users_group_id', 'group_id'),
941 UniqueConstraint('users_group_id', 'group_id'),
942 {'extend_existing': True, 'mysql_engine': 'InnoDB',
942 {'extend_existing': True, 'mysql_engine': 'InnoDB',
943 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
943 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
944 )
944 )
945
945
946 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)
946 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)
947 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
947 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
948 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
948 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
949 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
949 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
950
950
951 users_group = relationship('UserGroup')
951 users_group = relationship('UserGroup')
952 permission = relationship('Permission')
952 permission = relationship('Permission')
953 group = relationship('RepoGroup')
953 group = relationship('RepoGroup')
954
954
955
955
956 class Statistics(Base, BaseModel):
956 class Statistics(Base, BaseModel):
957 __tablename__ = 'statistics'
957 __tablename__ = 'statistics'
958 __table_args__ = (
958 __table_args__ = (
959 UniqueConstraint('repository_id'),
959 UniqueConstraint('repository_id'),
960 {'extend_existing': True, 'mysql_engine': 'InnoDB',
960 {'extend_existing': True, 'mysql_engine': 'InnoDB',
961 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
961 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
962 )
962 )
963 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
963 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
964 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
964 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
965 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
965 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
966 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
966 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
967 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
967 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
968 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
968 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
969
969
970 repository = relationship('Repository', single_parent=True)
970 repository = relationship('Repository', single_parent=True)
971
971
972
972
973 class UserFollowing(Base, BaseModel):
973 class UserFollowing(Base, BaseModel):
974 __tablename__ = 'user_followings'
974 __tablename__ = 'user_followings'
975 __table_args__ = (
975 __table_args__ = (
976 UniqueConstraint('user_id', 'follows_repository_id'),
976 UniqueConstraint('user_id', 'follows_repository_id'),
977 UniqueConstraint('user_id', 'follows_user_id'),
977 UniqueConstraint('user_id', 'follows_user_id'),
978 {'extend_existing': True, 'mysql_engine': 'InnoDB',
978 {'extend_existing': True, 'mysql_engine': 'InnoDB',
979 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
979 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
980 )
980 )
981
981
982 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
982 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
983 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
983 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
984 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
984 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
985 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
985 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
986 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
986 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
987
987
988 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
988 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
989
989
990 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
990 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
991 follows_repository = relationship('Repository', order_by='Repository.repo_name')
991 follows_repository = relationship('Repository', order_by='Repository.repo_name')
992
992
993
993
994 class CacheInvalidation(Base, BaseModel):
994 class CacheInvalidation(Base, BaseModel):
995 __tablename__ = 'cache_invalidation'
995 __tablename__ = 'cache_invalidation'
996 __table_args__ = (
996 __table_args__ = (
997 UniqueConstraint('cache_key'),
997 UniqueConstraint('cache_key'),
998 Index('key_idx', 'cache_key'),
998 Index('key_idx', 'cache_key'),
999 {'extend_existing': True, 'mysql_engine': 'InnoDB',
999 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1000 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1000 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1001 )
1001 )
1002 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1002 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1003 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1003 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1004 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1004 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1005 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1005 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1006
1006
1007 def __init__(self, cache_key, cache_args=''):
1007 def __init__(self, cache_key, cache_args=''):
1008 self.cache_key = cache_key
1008 self.cache_key = cache_key
1009 self.cache_args = cache_args
1009 self.cache_args = cache_args
1010 self.cache_active = False
1010 self.cache_active = False
1011
1011
1012
1012
1013 class ChangesetComment(Base, BaseModel):
1013 class ChangesetComment(Base, BaseModel):
1014 __tablename__ = 'changeset_comments'
1014 __tablename__ = 'changeset_comments'
1015 __table_args__ = (
1015 __table_args__ = (
1016 Index('cc_revision_idx', 'revision'),
1016 Index('cc_revision_idx', 'revision'),
1017 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1017 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1018 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1018 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1019 )
1019 )
1020 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1020 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1021 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1021 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1022 revision = Column('revision', String(40), nullable=True)
1022 revision = Column('revision', String(40), nullable=True)
1023 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1023 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1024 line_no = Column('line_no', Unicode(10), nullable=True)
1024 line_no = Column('line_no', Unicode(10), nullable=True)
1025 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1025 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1026 f_path = Column('f_path', Unicode(1000), nullable=True)
1026 f_path = Column('f_path', Unicode(1000), nullable=True)
1027 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1027 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1028 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1028 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1029 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1029 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1030 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1030 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1031
1031
1032 author = relationship('User', lazy='joined')
1032 author = relationship('User', lazy='joined')
1033 repo = relationship('Repository')
1033 repo = relationship('Repository')
1034 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1034 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1035 pull_request = relationship('PullRequest', lazy='joined')
1035 pull_request = relationship('PullRequest', lazy='joined')
1036
1036
1037
1037
1038 class ChangesetStatus(Base, BaseModel):
1038 class ChangesetStatus(Base, BaseModel):
1039 __tablename__ = 'changeset_statuses'
1039 __tablename__ = 'changeset_statuses'
1040 __table_args__ = (
1040 __table_args__ = (
1041 Index('cs_revision_idx', 'revision'),
1041 Index('cs_revision_idx', 'revision'),
1042 Index('cs_version_idx', 'version'),
1042 Index('cs_version_idx', 'version'),
1043 UniqueConstraint('repo_id', 'revision', 'version'),
1043 UniqueConstraint('repo_id', 'revision', 'version'),
1044 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1044 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1045 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1045 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1046 )
1046 )
1047 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1047 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1048 STATUS_APPROVED = 'approved'
1048 STATUS_APPROVED = 'approved'
1049 STATUS_REJECTED = 'rejected'
1049 STATUS_REJECTED = 'rejected'
1050 STATUS_UNDER_REVIEW = 'under_review'
1050 STATUS_UNDER_REVIEW = 'under_review'
1051
1051
1052 STATUSES = [
1052 STATUSES = [
1053 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1053 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1054 (STATUS_APPROVED, _("Approved")),
1054 (STATUS_APPROVED, _("Approved")),
1055 (STATUS_REJECTED, _("Rejected")),
1055 (STATUS_REJECTED, _("Rejected")),
1056 (STATUS_UNDER_REVIEW, _("Under Review")),
1056 (STATUS_UNDER_REVIEW, _("Under Review")),
1057 ]
1057 ]
1058
1058
1059 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1059 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1060 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1060 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1061 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1061 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1062 revision = Column('revision', String(40), nullable=False)
1062 revision = Column('revision', String(40), nullable=False)
1063 status = Column('status', String(128), nullable=False, default=DEFAULT)
1063 status = Column('status', String(128), nullable=False, default=DEFAULT)
1064 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1064 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1065 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1065 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1066 version = Column('version', Integer(), nullable=False, default=0)
1066 version = Column('version', Integer(), nullable=False, default=0)
1067 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1067 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1068
1068
1069 author = relationship('User', lazy='joined')
1069 author = relationship('User', lazy='joined')
1070 repo = relationship('Repository')
1070 repo = relationship('Repository')
1071 comment = relationship('ChangesetComment', lazy='joined')
1071 comment = relationship('ChangesetComment', lazy='joined')
1072 pull_request = relationship('PullRequest', lazy='joined')
1072 pull_request = relationship('PullRequest', lazy='joined')
1073
1073
1074
1074
1075
1075
1076 class PullRequest(Base, BaseModel):
1076 class PullRequest(Base, BaseModel):
1077 __tablename__ = 'pull_requests'
1077 __tablename__ = 'pull_requests'
1078 __table_args__ = (
1078 __table_args__ = (
1079 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1079 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1080 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1080 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1081 )
1081 )
1082
1082
1083 STATUS_NEW = u'new'
1083 STATUS_NEW = u'new'
1084 STATUS_OPEN = u'open'
1084 STATUS_OPEN = u'open'
1085 STATUS_CLOSED = u'closed'
1085 STATUS_CLOSED = u'closed'
1086
1086
1087 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1087 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1088 title = Column('title', Unicode(256), nullable=True)
1088 title = Column('title', Unicode(256), nullable=True)
1089 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1089 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1090 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1090 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1091 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1091 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1092 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1092 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1093 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1093 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1094 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1094 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1095 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1095 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1096 org_ref = Column('org_ref', Unicode(256), nullable=False)
1096 org_ref = Column('org_ref', Unicode(256), nullable=False)
1097 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1097 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1098 other_ref = Column('other_ref', Unicode(256), nullable=False)
1098 other_ref = Column('other_ref', Unicode(256), nullable=False)
1099
1099
1100 author = relationship('User', lazy='joined')
1100 author = relationship('User', lazy='joined')
1101 reviewers = relationship('PullRequestReviewers',
1101 reviewers = relationship('PullRequestReviewers',
1102 cascade="all, delete, delete-orphan")
1102 cascade="all, delete, delete-orphan")
1103 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1103 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1104 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1104 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1105 statuses = relationship('ChangesetStatus')
1105 statuses = relationship('ChangesetStatus')
1106 comments = relationship('ChangesetComment',
1106 comments = relationship('ChangesetComment',
1107 cascade="all, delete, delete-orphan")
1107 cascade="all, delete, delete-orphan")
1108
1108
1109
1109
1110 class PullRequestReviewers(Base, BaseModel):
1110 class PullRequestReviewers(Base, BaseModel):
1111 __tablename__ = 'pull_request_reviewers'
1111 __tablename__ = 'pull_request_reviewers'
1112 __table_args__ = (
1112 __table_args__ = (
1113 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1113 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1114 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1114 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1115 )
1115 )
1116
1116
1117 def __init__(self, user=None, pull_request=None):
1117 def __init__(self, user=None, pull_request=None):
1118 self.user = user
1118 self.user = user
1119 self.pull_request = pull_request
1119 self.pull_request = pull_request
1120
1120
1121 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1121 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1122 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1122 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1123 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1123 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1124
1124
1125 user = relationship('User')
1125 user = relationship('User')
1126 pull_request = relationship('PullRequest')
1126 pull_request = relationship('PullRequest')
1127
1127
1128
1128
1129 class Notification(Base, BaseModel):
1129 class Notification(Base, BaseModel):
1130 __tablename__ = 'notifications'
1130 __tablename__ = 'notifications'
1131 __table_args__ = (
1131 __table_args__ = (
1132 Index('notification_type_idx', 'type'),
1132 Index('notification_type_idx', 'type'),
1133 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1133 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1134 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1134 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1135 )
1135 )
1136
1136
1137 TYPE_CHANGESET_COMMENT = u'cs_comment'
1137 TYPE_CHANGESET_COMMENT = u'cs_comment'
1138 TYPE_MESSAGE = u'message'
1138 TYPE_MESSAGE = u'message'
1139 TYPE_MENTION = u'mention'
1139 TYPE_MENTION = u'mention'
1140 TYPE_REGISTRATION = u'registration'
1140 TYPE_REGISTRATION = u'registration'
1141 TYPE_PULL_REQUEST = u'pull_request'
1141 TYPE_PULL_REQUEST = u'pull_request'
1142 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1142 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1143
1143
1144 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1144 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1145 subject = Column('subject', Unicode(512), nullable=True)
1145 subject = Column('subject', Unicode(512), nullable=True)
1146 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1146 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1147 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1147 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1148 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1148 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1149 type_ = Column('type', Unicode(256))
1149 type_ = Column('type', Unicode(256))
1150
1150
1151 created_by_user = relationship('User')
1151 created_by_user = relationship('User')
1152 notifications_to_users = relationship('UserNotification', lazy='joined',
1152 notifications_to_users = relationship('UserNotification', lazy='joined',
1153 cascade="all, delete, delete-orphan")
1153 cascade="all, delete, delete-orphan")
1154
1154
1155
1155
1156 class UserNotification(Base, BaseModel):
1156 class UserNotification(Base, BaseModel):
1157 __tablename__ = 'user_to_notification'
1157 __tablename__ = 'user_to_notification'
1158 __table_args__ = (
1158 __table_args__ = (
1159 UniqueConstraint('user_id', 'notification_id'),
1159 UniqueConstraint('user_id', 'notification_id'),
1160 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1160 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1161 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1161 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1162 )
1162 )
1163 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1163 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1164 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1164 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1165 read = Column('read', Boolean, default=False)
1165 read = Column('read', Boolean, default=False)
1166 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1166 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1167
1167
1168 user = relationship('User', lazy="joined")
1168 user = relationship('User', lazy="joined")
1169 notification = relationship('Notification', lazy="joined",
1169 notification = relationship('Notification', lazy="joined",
1170 order_by=lambda: Notification.created_on.desc(),)
1170 order_by=lambda: Notification.created_on.desc(),)
1171
1171
1172
1172
1173 class Gist(Base, BaseModel):
1173 class Gist(Base, BaseModel):
1174 __tablename__ = 'gists'
1174 __tablename__ = 'gists'
1175 __table_args__ = (
1175 __table_args__ = (
1176 Index('g_gist_access_id_idx', 'gist_access_id'),
1176 Index('g_gist_access_id_idx', 'gist_access_id'),
1177 Index('g_created_on_idx', 'created_on'),
1177 Index('g_created_on_idx', 'created_on'),
1178 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1178 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1179 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1179 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1180 )
1180 )
1181 GIST_PUBLIC = u'public'
1181 GIST_PUBLIC = u'public'
1182 GIST_PRIVATE = u'private'
1182 GIST_PRIVATE = u'private'
1183
1183
1184 gist_id = Column('gist_id', Integer(), primary_key=True)
1184 gist_id = Column('gist_id', Integer(), primary_key=True)
1185 gist_access_id = Column('gist_access_id', Unicode(250))
1185 gist_access_id = Column('gist_access_id', Unicode(250))
1186 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1186 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1187 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1187 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1188 gist_expires = Column('gist_expires', Float(53), nullable=False)
1188 gist_expires = Column('gist_expires', Float(53), nullable=False)
1189 gist_type = Column('gist_type', Unicode(128), nullable=False)
1189 gist_type = Column('gist_type', Unicode(128), nullable=False)
1190 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1190 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1191 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1191 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1192
1192
1193 owner = relationship('User')
1193 owner = relationship('User')
1194
1194
1195
1195
1196 class DbMigrateVersion(Base, BaseModel):
1196 class DbMigrateVersion(Base, BaseModel):
1197 __tablename__ = 'db_migrate_version'
1197 __tablename__ = 'db_migrate_version'
1198 __table_args__ = (
1198 __table_args__ = (
1199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1200 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1200 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1201 )
1201 )
1202 repository_id = Column('repository_id', String(250), primary_key=True)
1202 repository_id = Column('repository_id', String(250), primary_key=True)
1203 repository_path = Column('repository_path', Text)
1203 repository_path = Column('repository_path', Text)
1204 version = Column('version', Integer)
1204 version = Column('version', Integer)
@@ -1,1224 +1,1224 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
46 get_clone_url
46 get_clone_url
47 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.ext_json import json
48 from rhodecode.lib.caching_query import FromCache
48 from rhodecode.lib.caching_query import FromCache
49
49
50 from rhodecode.model.meta import Base, Session
50 from rhodecode.model.meta import Base, Session
51
51
52 URL_SEP = '/'
52 URL_SEP = '/'
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55 #==============================================================================
55 #==============================================================================
56 # BASE CLASSES
56 # BASE CLASSES
57 #==============================================================================
57 #==============================================================================
58
58
59 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
60
60
61
61
62 class BaseModel(object):
62 class BaseModel(object):
63 """
63 """
64 Base Model for all classes
64 Base Model for all classes
65 """
65 """
66
66
67 @classmethod
67 @classmethod
68 def _get_keys(cls):
68 def _get_keys(cls):
69 """return column names for this model """
69 """return column names for this model """
70 return class_mapper(cls).c.keys()
70 return class_mapper(cls).c.keys()
71
71
72 def get_dict(self):
72 def get_dict(self):
73 """
73 """
74 return dict with keys and values corresponding
74 return dict with keys and values corresponding
75 to this model data """
75 to this model data """
76
76
77 d = {}
77 d = {}
78 for k in self._get_keys():
78 for k in self._get_keys():
79 d[k] = getattr(self, k)
79 d[k] = getattr(self, k)
80
80
81 # also use __json__() if present to get additional fields
81 # also use __json__() if present to get additional fields
82 _json_attr = getattr(self, '__json__', None)
82 _json_attr = getattr(self, '__json__', None)
83 if _json_attr:
83 if _json_attr:
84 # update with attributes from __json__
84 # update with attributes from __json__
85 if callable(_json_attr):
85 if callable(_json_attr):
86 _json_attr = _json_attr()
86 _json_attr = _json_attr()
87 for k, val in _json_attr.items():
87 for k, val in _json_attr.items():
88 d[k] = val
88 d[k] = val
89 return d
89 return d
90
90
91 def get_appstruct(self):
91 def get_appstruct(self):
92 """return list with keys and values tupples corresponding
92 """return list with keys and values tupples corresponding
93 to this model data """
93 to this model data """
94
94
95 l = []
95 l = []
96 for k in self._get_keys():
96 for k in self._get_keys():
97 l.append((k, getattr(self, k),))
97 l.append((k, getattr(self, k),))
98 return l
98 return l
99
99
100 def populate_obj(self, populate_dict):
100 def populate_obj(self, populate_dict):
101 """populate model with data from given populate_dict"""
101 """populate model with data from given populate_dict"""
102
102
103 for k in self._get_keys():
103 for k in self._get_keys():
104 if k in populate_dict:
104 if k in populate_dict:
105 setattr(self, k, populate_dict[k])
105 setattr(self, k, populate_dict[k])
106
106
107 @classmethod
107 @classmethod
108 def query(cls):
108 def query(cls):
109 return Session().query(cls)
109 return Session().query(cls)
110
110
111 @classmethod
111 @classmethod
112 def get(cls, id_):
112 def get(cls, id_):
113 if id_:
113 if id_:
114 return cls.query().get(id_)
114 return cls.query().get(id_)
115
115
116 @classmethod
116 @classmethod
117 def get_or_404(cls, id_):
117 def get_or_404(cls, id_):
118 try:
118 try:
119 id_ = int(id_)
119 id_ = int(id_)
120 except (TypeError, ValueError):
120 except (TypeError, ValueError):
121 raise HTTPNotFound
121 raise HTTPNotFound
122
122
123 res = cls.query().get(id_)
123 res = cls.query().get(id_)
124 if not res:
124 if not res:
125 raise HTTPNotFound
125 raise HTTPNotFound
126 return res
126 return res
127
127
128 @classmethod
128 @classmethod
129 def getAll(cls):
129 def getAll(cls):
130 # deprecated and left for backward compatibility
130 # deprecated and left for backward compatibility
131 return cls.get_all()
131 return cls.get_all()
132
132
133 @classmethod
133 @classmethod
134 def get_all(cls):
134 def get_all(cls):
135 return cls.query().all()
135 return cls.query().all()
136
136
137 @classmethod
137 @classmethod
138 def delete(cls, id_):
138 def delete(cls, id_):
139 obj = cls.query().get(id_)
139 obj = cls.query().get(id_)
140 Session().delete(obj)
140 Session().delete(obj)
141
141
142 def __repr__(self):
142 def __repr__(self):
143 if hasattr(self, '__unicode__'):
143 if hasattr(self, '__unicode__'):
144 # python repr needs to return str
144 # python repr needs to return str
145 try:
145 try:
146 return safe_str(self.__unicode__())
146 return safe_str(self.__unicode__())
147 except UnicodeDecodeError:
147 except UnicodeDecodeError:
148 pass
148 pass
149 return '<DB:%s>' % (self.__class__.__name__)
149 return '<DB:%s>' % (self.__class__.__name__)
150
150
151
151
152 class RhodeCodeSetting(Base, BaseModel):
152 class RhodeCodeSetting(Base, BaseModel):
153 __tablename__ = 'rhodecode_settings'
153 __tablename__ = 'rhodecode_settings'
154 __table_args__ = (
154 __table_args__ = (
155 UniqueConstraint('app_settings_name'),
155 UniqueConstraint('app_settings_name'),
156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
157 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
157 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
158 )
158 )
159
159
160 SETTINGS_TYPES = {
160 SETTINGS_TYPES = {
161 'str': safe_str,
161 'str': safe_str,
162 'int': safe_int,
162 'int': safe_int,
163 'unicode': safe_str,
163 'unicode': safe_str,
164 'bool': str2bool,
164 'bool': str2bool,
165 'list': functools.partial(aslist, sep=',')
165 'list': functools.partial(aslist, sep=',')
166 }
166 }
167 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
167 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
168
168
169 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
169 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
170 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
170 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
171 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
171 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
172 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
172 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
173
173
174 def __init__(self, key='', val='', type='unicode'):
174 def __init__(self, key='', val='', type='unicode'):
175 self.app_settings_name = key
175 self.app_settings_name = key
176 self.app_settings_value = val
176 self.app_settings_value = val
177 self.app_settings_type = type
177 self.app_settings_type = type
178
178
179 @validates('_app_settings_value')
179 @validates('_app_settings_value')
180 def validate_settings_value(self, key, val):
180 def validate_settings_value(self, key, val):
181 assert type(val) == str
181 assert type(val) == str
182 return val
182 return val
183
183
184 @hybrid_property
184 @hybrid_property
185 def app_settings_value(self):
185 def app_settings_value(self):
186 v = self._app_settings_value
186 v = self._app_settings_value
187 _type = self.app_settings_type
187 _type = self.app_settings_type
188 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
188 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
189 return converter(v)
189 return converter(v)
190
190
191 @app_settings_value.setter
191 @app_settings_value.setter
192 def app_settings_value(self, val):
192 def app_settings_value(self, val):
193 """
193 """
194 Setter that will always make sure we use unicode in app_settings_value
194 Setter that will always make sure we use unicode in app_settings_value
195
195
196 :param val:
196 :param val:
197 """
197 """
198 self._app_settings_value = safe_str(val)
198 self._app_settings_value = safe_str(val)
199
199
200 @hybrid_property
200 @hybrid_property
201 def app_settings_type(self):
201 def app_settings_type(self):
202 return self._app_settings_type
202 return self._app_settings_type
203
203
204 @app_settings_type.setter
204 @app_settings_type.setter
205 def app_settings_type(self, val):
205 def app_settings_type(self, val):
206 if val not in self.SETTINGS_TYPES:
206 if val not in self.SETTINGS_TYPES:
207 raise Exception('type must be one of %s got %s'
207 raise Exception('type must be one of %s got %s'
208 % (self.SETTINGS_TYPES.keys(), val))
208 % (self.SETTINGS_TYPES.keys(), val))
209 self._app_settings_type = val
209 self._app_settings_type = val
210
210
211 def __unicode__(self):
211 def __unicode__(self):
212 return u"<%s('%s:%s[%s]')>" % (
212 return u"<%s('%s:%s[%s]')>" % (
213 self.__class__.__name__,
213 self.__class__.__name__,
214 self.app_settings_name, self.app_settings_value, self.app_settings_type
214 self.app_settings_name, self.app_settings_value, self.app_settings_type
215 )
215 )
216
216
217
217
218 class RhodeCodeUi(Base, BaseModel):
218 class RhodeCodeUi(Base, BaseModel):
219 __tablename__ = 'rhodecode_ui'
219 __tablename__ = 'rhodecode_ui'
220 __table_args__ = (
220 __table_args__ = (
221 UniqueConstraint('ui_key'),
221 UniqueConstraint('ui_key'),
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
223 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
224 )
224 )
225
225
226 HOOK_REPO_SIZE = 'changegroup.repo_size'
226 HOOK_REPO_SIZE = 'changegroup.repo_size'
227 HOOK_PUSH = 'changegroup.push_logger'
227 HOOK_PUSH = 'changegroup.push_logger'
228 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
228 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
229 HOOK_PULL = 'outgoing.pull_logger'
229 HOOK_PULL = 'outgoing.pull_logger'
230 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
230 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
231
231
232 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
233 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
233 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
234 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
234 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
235 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
235 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
236 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
236 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
237
237
238 def __repr__(self):
238 def __repr__(self):
239 return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section,
239 return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section,
240 self.ui_key, self.ui_value)
240 self.ui_key, self.ui_value)
241
241
242
242
243 class User(Base, BaseModel):
243 class User(Base, BaseModel):
244 __tablename__ = 'users'
244 __tablename__ = 'users'
245 __table_args__ = (
245 __table_args__ = (
246 UniqueConstraint('username'), UniqueConstraint('email'),
246 UniqueConstraint('username'), UniqueConstraint('email'),
247 Index('u_username_idx', 'username'),
247 Index('u_username_idx', 'username'),
248 Index('u_email_idx', 'email'),
248 Index('u_email_idx', 'email'),
249 {'extend_existing': True, 'mysql_engine': 'InnoDB',
249 {'extend_existing': True, 'mysql_engine': 'InnoDB',
250 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
250 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
251 )
251 )
252 DEFAULT_USER = 'default'
252 DEFAULT_USER = 'default'
253 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
253 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
254
254
255 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
255 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
256 username = Column("username", String(255), nullable=True, unique=None, default=None)
256 username = Column("username", String(255), nullable=True, unique=None, default=None)
257 password = Column("password", String(255), nullable=True, unique=None, default=None)
257 password = Column("password", String(255), nullable=True, unique=None, default=None)
258 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
258 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
259 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
259 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
260 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
260 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
261 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
261 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
262 _email = Column("email", String(255), nullable=True, unique=None, default=None)
262 _email = Column("email", String(255), nullable=True, unique=None, default=None)
263 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
263 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
264 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
264 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
265 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
265 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
266 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
266 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
267 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
267 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
268 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
268 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
269 #_user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data
269 #_user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data
270
270
271 user_log = relationship('UserLog')
271 user_log = relationship('UserLog')
272 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
272 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
273
273
274 repositories = relationship('Repository')
274 repositories = relationship('Repository')
275 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
275 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
276 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
276 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
277
277
278 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
278 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
279 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
279 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
280
280
281 group_member = relationship('UserGroupMember', cascade='all')
281 group_member = relationship('UserGroupMember', cascade='all')
282
282
283 notifications = relationship('UserNotification', cascade='all')
283 notifications = relationship('UserNotification', cascade='all')
284 # notifications assigned to this user
284 # notifications assigned to this user
285 user_created_notifications = relationship('Notification', cascade='all')
285 user_created_notifications = relationship('Notification', cascade='all')
286 # comments created by this user
286 # comments created by this user
287 user_comments = relationship('ChangesetComment', cascade='all')
287 user_comments = relationship('ChangesetComment', cascade='all')
288 user_emails = relationship('UserEmailMap', cascade='all')
288 user_emails = relationship('UserEmailMap', cascade='all')
289 user_auth_tokens = relationship('UserApiKeys', cascade='all')
289 user_auth_tokens = relationship('UserApiKeys', cascade='all')
290
290
291 @hybrid_property
291 @hybrid_property
292 def email(self):
292 def email(self):
293 return self._email
293 return self._email
294
294
295 @email.setter
295 @email.setter
296 def email(self, val):
296 def email(self, val):
297 self._email = val.lower() if val else None
297 self._email = val.lower() if val else None
298
298
299 @property
299 @property
300 def firstname(self):
300 def firstname(self):
301 # alias for future
301 # alias for future
302 return self.name
302 return self.name
303
303
304 @property
304 @property
305 def username_and_name(self):
305 def username_and_name(self):
306 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
306 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
307
307
308 @property
308 @property
309 def full_name(self):
309 def full_name(self):
310 return '%s %s' % (self.firstname, self.lastname)
310 return '%s %s' % (self.firstname, self.lastname)
311
311
312 @property
312 @property
313 def full_contact(self):
313 def full_contact(self):
314 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
314 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
315
315
316 @property
316 @property
317 def short_contact(self):
317 def short_contact(self):
318 return '%s %s' % (self.firstname, self.lastname)
318 return '%s %s' % (self.firstname, self.lastname)
319
319
320 @property
320 @property
321 def is_admin(self):
321 def is_admin(self):
322 return self.admin
322 return self.admin
323
323
324 @classmethod
324 @classmethod
325 def get_by_username(cls, username, case_insensitive=False, cache=False):
325 def get_by_username(cls, username, case_insensitive=False, cache=False):
326 if case_insensitive:
326 if case_insensitive:
327 q = cls.query().filter(cls.username.ilike(username))
327 q = cls.query().filter(cls.username.ilike(username))
328 else:
328 else:
329 q = cls.query().filter(cls.username == username)
329 q = cls.query().filter(cls.username == username)
330
330
331 if cache:
331 if cache:
332 q = q.options(FromCache(
332 q = q.options(FromCache(
333 "sql_cache_short",
333 "sql_cache_short",
334 "get_user_%s" % _hash_key(username)
334 "get_user_%s" % _hash_key(username)
335 )
335 )
336 )
336 )
337 return q.scalar()
337 return q.scalar()
338
338
339 @classmethod
339 @classmethod
340 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
340 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
341 q = cls.query().filter(cls.api_key == auth_token)
341 q = cls.query().filter(cls.api_key == auth_token)
342
342
343 if cache:
343 if cache:
344 q = q.options(FromCache("sql_cache_short",
344 q = q.options(FromCache("sql_cache_short",
345 "get_auth_token_%s" % auth_token))
345 "get_auth_token_%s" % auth_token))
346 res = q.scalar()
346 res = q.scalar()
347
347
348 if fallback and not res:
348 if fallback and not res:
349 #fallback to additional keys
349 #fallback to additional keys
350 _res = UserApiKeys.query()\
350 _res = UserApiKeys.query()\
351 .filter(UserApiKeys.api_key == auth_token)\
351 .filter(UserApiKeys.api_key == auth_token)\
352 .filter(or_(UserApiKeys.expires == -1,
352 .filter(or_(UserApiKeys.expires == -1,
353 UserApiKeys.expires >= time.time()))\
353 UserApiKeys.expires >= time.time()))\
354 .first()
354 .first()
355 if _res:
355 if _res:
356 res = _res.user
356 res = _res.user
357 return res
357 return res
358
358
359 @classmethod
359 @classmethod
360 def get_by_email(cls, email, case_insensitive=False, cache=False):
360 def get_by_email(cls, email, case_insensitive=False, cache=False):
361
361
362 if case_insensitive:
362 if case_insensitive:
363 q = cls.query().filter(cls.email.ilike(email))
363 q = cls.query().filter(cls.email.ilike(email))
364 else:
364 else:
365 q = cls.query().filter(cls.email == email)
365 q = cls.query().filter(cls.email == email)
366
366
367 if cache:
367 if cache:
368 q = q.options(FromCache("sql_cache_short",
368 q = q.options(FromCache("sql_cache_short",
369 "get_email_key_%s" % email))
369 "get_email_key_%s" % email))
370
370
371 ret = q.scalar()
371 ret = q.scalar()
372 if ret is None:
372 if ret is None:
373 q = UserEmailMap.query()
373 q = UserEmailMap.query()
374 # try fetching in alternate email map
374 # try fetching in alternate email map
375 if case_insensitive:
375 if case_insensitive:
376 q = q.filter(UserEmailMap.email.ilike(email))
376 q = q.filter(UserEmailMap.email.ilike(email))
377 else:
377 else:
378 q = q.filter(UserEmailMap.email == email)
378 q = q.filter(UserEmailMap.email == email)
379 q = q.options(joinedload(UserEmailMap.user))
379 q = q.options(joinedload(UserEmailMap.user))
380 if cache:
380 if cache:
381 q = q.options(FromCache("sql_cache_short",
381 q = q.options(FromCache("sql_cache_short",
382 "get_email_map_key_%s" % email))
382 "get_email_map_key_%s" % email))
383 ret = getattr(q.scalar(), 'user', None)
383 ret = getattr(q.scalar(), 'user', None)
384
384
385 return ret
385 return ret
386
386
387 @classmethod
387 @classmethod
388 def get_first_admin(cls):
388 def get_first_admin(cls):
389 user = User.query().filter(User.admin == True).first()
389 user = User.query().filter(User.admin == True).first()
390 if user is None:
390 if user is None:
391 raise Exception('Missing administrative account!')
391 raise Exception('Missing administrative account!')
392 return user
392 return user
393
393
394 @classmethod
394 @classmethod
395 def get_default_user(cls, cache=False):
395 def get_default_user(cls, cache=False):
396 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
396 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
397 if user is None:
397 if user is None:
398 raise Exception('Missing default account!')
398 raise Exception('Missing default account!')
399 return user
399 return user
400
400
401
401
402 class UserApiKeys(Base, BaseModel):
402 class UserApiKeys(Base, BaseModel):
403 __tablename__ = 'user_api_keys'
403 __tablename__ = 'user_api_keys'
404 __table_args__ = (
404 __table_args__ = (
405 Index('uak_api_key_idx', 'api_key'),
405 Index('uak_api_key_idx', 'api_key'),
406 Index('uak_api_key_expires_idx', 'api_key', 'expires'),
406 Index('uak_api_key_expires_idx', 'api_key', 'expires'),
407 UniqueConstraint('api_key'),
407 UniqueConstraint('api_key'),
408 {'extend_existing': True, 'mysql_engine': 'InnoDB',
408 {'extend_existing': True, 'mysql_engine': 'InnoDB',
409 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
409 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
410 )
410 )
411
411
412
412
413 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
413 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
414 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
414 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
415 api_key = Column("api_key", String(255), nullable=False, unique=True)
415 api_key = Column("api_key", String(255), nullable=False, unique=True)
416 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
416 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
417 expires = Column('expires', Float(53), nullable=False)
417 expires = Column('expires', Float(53), nullable=False)
418 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
418 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
419
419
420 user = relationship('User', lazy='joined')
420 user = relationship('User', lazy='joined')
421
421
422
422
423 class UserEmailMap(Base, BaseModel):
423 class UserEmailMap(Base, BaseModel):
424 __tablename__ = 'user_email_map'
424 __tablename__ = 'user_email_map'
425 __table_args__ = (
425 __table_args__ = (
426 Index('uem_email_idx', 'email'),
426 Index('uem_email_idx', 'email'),
427 UniqueConstraint('email'),
427 UniqueConstraint('email'),
428 {'extend_existing': True, 'mysql_engine': 'InnoDB',
428 {'extend_existing': True, 'mysql_engine': 'InnoDB',
429 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
429 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
430 )
430 )
431
431
432
432
433 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
433 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
434 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
434 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
435 _email = Column("email", String(255), nullable=True, unique=False, default=None)
435 _email = Column("email", String(255), nullable=True, unique=False, default=None)
436 user = relationship('User', lazy='joined')
436 user = relationship('User', lazy='joined')
437
437
438 @validates('_email')
438 @validates('_email')
439 def validate_email(self, key, email):
439 def validate_email(self, key, email):
440 # check if this email is not main one
440 # check if this email is not main one
441 main_email = Session().query(User).filter(User.email == email).scalar()
441 main_email = Session().query(User).filter(User.email == email).scalar()
442 if main_email is not None:
442 if main_email is not None:
443 raise AttributeError('email %s is present is user table' % email)
443 raise AttributeError('email %s is present is user table' % email)
444 return email
444 return email
445
445
446 @hybrid_property
446 @hybrid_property
447 def email(self):
447 def email(self):
448 return self._email
448 return self._email
449
449
450 @email.setter
450 @email.setter
451 def email(self, val):
451 def email(self, val):
452 self._email = val.lower() if val else None
452 self._email = val.lower() if val else None
453
453
454
454
455 class UserIpMap(Base, BaseModel):
455 class UserIpMap(Base, BaseModel):
456 __tablename__ = 'user_ip_map'
456 __tablename__ = 'user_ip_map'
457 __table_args__ = (
457 __table_args__ = (
458 UniqueConstraint('user_id', 'ip_addr'),
458 UniqueConstraint('user_id', 'ip_addr'),
459 {'extend_existing': True, 'mysql_engine': 'InnoDB',
459 {'extend_existing': True, 'mysql_engine': 'InnoDB',
460 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
460 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
461 )
461 )
462
462
463
463
464 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
464 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
465 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
465 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
466 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
466 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
467 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
467 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
468 user = relationship('User', lazy='joined')
468 user = relationship('User', lazy='joined')
469
469
470 def __unicode__(self):
470 def __unicode__(self):
471 return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__,
471 return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__,
472 self.user_id, self.ip_addr)
472 self.user_id, self.ip_addr)
473
473
474
474
475 class UserLog(Base, BaseModel):
475 class UserLog(Base, BaseModel):
476 __tablename__ = 'user_logs'
476 __tablename__ = 'user_logs'
477 __table_args__ = (
477 __table_args__ = (
478 {'extend_existing': True, 'mysql_engine': 'InnoDB',
478 {'extend_existing': True, 'mysql_engine': 'InnoDB',
479 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
479 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
480 )
480 )
481 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
481 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
482 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
482 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
483 username = Column("username", String(255), nullable=True, unique=None, default=None)
483 username = Column("username", String(255), nullable=True, unique=None, default=None)
484 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
484 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
485 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
485 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
486 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
486 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
487 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
487 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
488 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
488 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
489
489
490 def __unicode__(self):
490 def __unicode__(self):
491 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
491 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
492 self.repository_name,
492 self.repository_name,
493 self.action)
493 self.action)
494
494
495 user = relationship('User')
495 user = relationship('User')
496 repository = relationship('Repository', cascade='')
496 repository = relationship('Repository', cascade='')
497
497
498
498
499 class UserGroup(Base, BaseModel):
499 class UserGroup(Base, BaseModel):
500 __tablename__ = 'users_groups'
500 __tablename__ = 'users_groups'
501 __table_args__ = (
501 __table_args__ = (
502 {'extend_existing': True, 'mysql_engine': 'InnoDB',
502 {'extend_existing': True, 'mysql_engine': 'InnoDB',
503 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
503 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
504 )
504 )
505
505
506 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
506 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
507 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
507 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
508 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
508 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
509 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
509 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
510 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
510 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
511 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
511 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
512 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
512 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
513
513
514 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
514 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
515 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
515 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
516 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
516 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
517 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
517 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
518 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
518 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
519 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
519 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
520
520
521 user = relationship('User')
521 user = relationship('User')
522
522
523 def __unicode__(self):
523 def __unicode__(self):
524 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
524 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
525 self.users_group_id,
525 self.users_group_id,
526 self.users_group_name)
526 self.users_group_name)
527
527
528 @classmethod
528 @classmethod
529 def get_by_group_name(cls, group_name, cache=False,
529 def get_by_group_name(cls, group_name, cache=False,
530 case_insensitive=False):
530 case_insensitive=False):
531 if case_insensitive:
531 if case_insensitive:
532 q = cls.query().filter(cls.users_group_name.ilike(group_name))
532 q = cls.query().filter(cls.users_group_name.ilike(group_name))
533 else:
533 else:
534 q = cls.query().filter(cls.users_group_name == group_name)
534 q = cls.query().filter(cls.users_group_name == group_name)
535 if cache:
535 if cache:
536 q = q.options(FromCache(
536 q = q.options(FromCache(
537 "sql_cache_short",
537 "sql_cache_short",
538 "get_user_%s" % _hash_key(group_name)
538 "get_user_%s" % _hash_key(group_name)
539 )
539 )
540 )
540 )
541 return q.scalar()
541 return q.scalar()
542
542
543 @classmethod
543 @classmethod
544 def get(cls, user_group_id, cache=False):
544 def get(cls, user_group_id, cache=False):
545 user_group = cls.query()
545 user_group = cls.query()
546 if cache:
546 if cache:
547 user_group = user_group.options(FromCache("sql_cache_short",
547 user_group = user_group.options(FromCache("sql_cache_short",
548 "get_users_group_%s" % user_group_id))
548 "get_users_group_%s" % user_group_id))
549 return user_group.get(user_group_id)
549 return user_group.get(user_group_id)
550
550
551
551
552 class UserGroupMember(Base, BaseModel):
552 class UserGroupMember(Base, BaseModel):
553 __tablename__ = 'users_groups_members'
553 __tablename__ = 'users_groups_members'
554 __table_args__ = (
554 __table_args__ = (
555 {'extend_existing': True, 'mysql_engine': 'InnoDB',
555 {'extend_existing': True, 'mysql_engine': 'InnoDB',
556 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
556 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
557 )
557 )
558
558
559 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
559 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
560 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
560 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
561 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
561 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
562
562
563 user = relationship('User', lazy='joined')
563 user = relationship('User', lazy='joined')
564 users_group = relationship('UserGroup')
564 users_group = relationship('UserGroup')
565
565
566 def __init__(self, gr_id='', u_id=''):
566 def __init__(self, gr_id='', u_id=''):
567 self.users_group_id = gr_id
567 self.users_group_id = gr_id
568 self.user_id = u_id
568 self.user_id = u_id
569
569
570
570
571 class RepositoryField(Base, BaseModel):
571 class RepositoryField(Base, BaseModel):
572 __tablename__ = 'repositories_fields'
572 __tablename__ = 'repositories_fields'
573 __table_args__ = (
573 __table_args__ = (
574 UniqueConstraint('repository_id', 'field_key'), # no-multi field
574 UniqueConstraint('repository_id', 'field_key'), # no-multi field
575 {'extend_existing': True, 'mysql_engine': 'InnoDB',
575 {'extend_existing': True, 'mysql_engine': 'InnoDB',
576 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
576 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
577 )
577 )
578 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
578 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
579
579
580 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
580 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
581 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
581 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
582 field_key = Column("field_key", String(250))
582 field_key = Column("field_key", String(250))
583 field_label = Column("field_label", String(1024), nullable=False)
583 field_label = Column("field_label", String(1024), nullable=False)
584 field_value = Column("field_value", String(10000), nullable=False)
584 field_value = Column("field_value", String(10000), nullable=False)
585 field_desc = Column("field_desc", String(1024), nullable=False)
585 field_desc = Column("field_desc", String(1024), nullable=False)
586 field_type = Column("field_type", String(256), nullable=False, unique=None)
586 field_type = Column("field_type", String(256), nullable=False, unique=None)
587 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
587 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
588
588
589 repository = relationship('Repository')
589 repository = relationship('Repository')
590
590
591 @classmethod
591 @classmethod
592 def get_by_key_name(cls, key, repo):
592 def get_by_key_name(cls, key, repo):
593 row = cls.query()\
593 row = cls.query()\
594 .filter(cls.repository == repo)\
594 .filter(cls.repository == repo)\
595 .filter(cls.field_key == key).scalar()
595 .filter(cls.field_key == key).scalar()
596 return row
596 return row
597
597
598
598
599 class Repository(Base, BaseModel):
599 class Repository(Base, BaseModel):
600 __tablename__ = 'repositories'
600 __tablename__ = 'repositories'
601 __table_args__ = (
601 __table_args__ = (
602 UniqueConstraint('repo_name'),
602 UniqueConstraint('repo_name'),
603 Index('r_repo_name_idx', 'repo_name'),
603 Index('r_repo_name_idx', 'repo_name'),
604 {'extend_existing': True, 'mysql_engine': 'InnoDB',
604 {'extend_existing': True, 'mysql_engine': 'InnoDB',
605 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
605 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
606 )
606 )
607 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
607 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
608 DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
608 DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
609
609
610 STATE_CREATED = 'repo_state_created'
610 STATE_CREATED = 'repo_state_created'
611 STATE_PENDING = 'repo_state_pending'
611 STATE_PENDING = 'repo_state_pending'
612 STATE_ERROR = 'repo_state_error'
612 STATE_ERROR = 'repo_state_error'
613
613
614 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
614 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
615 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
615 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
616 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
616 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
617 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
617 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
618 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
618 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
619 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
619 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
620 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
620 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
621 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
621 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
622 description = Column("description", String(10000), nullable=True, unique=None, default=None)
622 description = Column("description", String(10000), nullable=True, unique=None, default=None)
623 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
623 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
624 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
624 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
625 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
625 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
626 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
626 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
627 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
627 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
628 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
628 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
629
629
630 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
630 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
631 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
631 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
632
632
633 user = relationship('User')
633 user = relationship('User')
634 fork = relationship('Repository', remote_side=repo_id)
634 fork = relationship('Repository', remote_side=repo_id)
635 group = relationship('RepoGroup')
635 group = relationship('RepoGroup')
636 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
636 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
637 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
637 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
638 stats = relationship('Statistics', cascade='all', uselist=False)
638 stats = relationship('Statistics', cascade='all', uselist=False)
639
639
640 followers = relationship('UserFollowing',
640 followers = relationship('UserFollowing',
641 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
641 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
642 cascade='all')
642 cascade='all')
643 extra_fields = relationship('RepositoryField',
643 extra_fields = relationship('RepositoryField',
644 cascade="all, delete, delete-orphan")
644 cascade="all, delete, delete-orphan")
645
645
646 logs = relationship('UserLog')
646 logs = relationship('UserLog')
647 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
647 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
648
648
649 pull_requests_org = relationship('PullRequest',
649 pull_requests_org = relationship('PullRequest',
650 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
650 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
651 cascade="all, delete, delete-orphan")
651 cascade="all, delete, delete-orphan")
652
652
653 pull_requests_other = relationship('PullRequest',
653 pull_requests_other = relationship('PullRequest',
654 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
654 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
655 cascade="all, delete, delete-orphan")
655 cascade="all, delete, delete-orphan")
656
656
657 def __unicode__(self):
657 def __unicode__(self):
658 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
658 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
659 safe_str(self.repo_name))
659 safe_str(self.repo_name))
660
660
661 @classmethod
661 @classmethod
662 def get_by_repo_name(cls, repo_name):
662 def get_by_repo_name(cls, repo_name):
663 q = Session().query(cls).filter(cls.repo_name == repo_name)
663 q = Session().query(cls).filter(cls.repo_name == repo_name)
664 q = q.options(joinedload(Repository.fork))\
664 q = q.options(joinedload(Repository.fork))\
665 .options(joinedload(Repository.user))\
665 .options(joinedload(Repository.user))\
666 .options(joinedload(Repository.group))
666 .options(joinedload(Repository.group))
667 return q.scalar()
667 return q.scalar()
668
668
669
669
670 class RepoGroup(Base, BaseModel):
670 class RepoGroup(Base, BaseModel):
671 __tablename__ = 'groups'
671 __tablename__ = 'groups'
672 __table_args__ = (
672 __table_args__ = (
673 UniqueConstraint('group_name', 'group_parent_id'),
673 UniqueConstraint('group_name', 'group_parent_id'),
674 {'extend_existing': True, 'mysql_engine': 'InnoDB',
674 {'extend_existing': True, 'mysql_engine': 'InnoDB',
675 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
675 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
676 )
676 )
677
677
678
678
679 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
679 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
680 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
680 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
681 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
681 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
682 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
682 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
683 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
683 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
684 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
684 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
685 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
685 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
686
686
687 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
687 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
688 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
688 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
689 parent_group = relationship('RepoGroup', remote_side=group_id)
689 parent_group = relationship('RepoGroup', remote_side=group_id)
690 user = relationship('User')
690 user = relationship('User')
691
691
692 def __init__(self, group_name='', parent_group=None):
692 def __init__(self, group_name='', parent_group=None):
693 self.group_name = group_name
693 self.group_name = group_name
694 self.parent_group = parent_group
694 self.parent_group = parent_group
695
695
696 def __unicode__(self):
696 def __unicode__(self):
697 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
697 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
698 self.group_name)
698 self.group_name)
699
699
700 @classmethod
700 @classmethod
701 def url_sep(cls):
701 def url_sep(cls):
702 return URL_SEP
702 return URL_SEP
703
703
704 @classmethod
704 @classmethod
705 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
705 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
706 if case_insensitive:
706 if case_insensitive:
707 gr = cls.query()\
707 gr = cls.query()\
708 .filter(cls.group_name.ilike(group_name))
708 .filter(cls.group_name.ilike(group_name))
709 else:
709 else:
710 gr = cls.query()\
710 gr = cls.query()\
711 .filter(cls.group_name == group_name)
711 .filter(cls.group_name == group_name)
712 if cache:
712 if cache:
713 gr = gr.options(FromCache(
713 gr = gr.options(FromCache(
714 "sql_cache_short",
714 "sql_cache_short",
715 "get_group_%s" % _hash_key(group_name)
715 "get_group_%s" % _hash_key(group_name)
716 )
716 )
717 )
717 )
718 return gr.scalar()
718 return gr.scalar()
719
719
720
720
721 class Permission(Base, BaseModel):
721 class Permission(Base, BaseModel):
722 __tablename__ = 'permissions'
722 __tablename__ = 'permissions'
723 __table_args__ = (
723 __table_args__ = (
724 Index('p_perm_name_idx', 'permission_name'),
724 Index('p_perm_name_idx', 'permission_name'),
725 {'extend_existing': True, 'mysql_engine': 'InnoDB',
725 {'extend_existing': True, 'mysql_engine': 'InnoDB',
726 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
726 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
727 )
727 )
728 PERMS = [
728 PERMS = [
729 ('hg.admin', _('RhodeCode Administrator')),
729 ('hg.admin', _('RhodeCode Administrator')),
730
730
731 ('repository.none', _('Repository no access')),
731 ('repository.none', _('Repository no access')),
732 ('repository.read', _('Repository read access')),
732 ('repository.read', _('Repository read access')),
733 ('repository.write', _('Repository write access')),
733 ('repository.write', _('Repository write access')),
734 ('repository.admin', _('Repository admin access')),
734 ('repository.admin', _('Repository admin access')),
735
735
736 ('group.none', _('Repository group no access')),
736 ('group.none', _('Repository group no access')),
737 ('group.read', _('Repository group read access')),
737 ('group.read', _('Repository group read access')),
738 ('group.write', _('Repository group write access')),
738 ('group.write', _('Repository group write access')),
739 ('group.admin', _('Repository group admin access')),
739 ('group.admin', _('Repository group admin access')),
740
740
741 ('usergroup.none', _('User group no access')),
741 ('usergroup.none', _('User group no access')),
742 ('usergroup.read', _('User group read access')),
742 ('usergroup.read', _('User group read access')),
743 ('usergroup.write', _('User group write access')),
743 ('usergroup.write', _('User group write access')),
744 ('usergroup.admin', _('User group admin access')),
744 ('usergroup.admin', _('User group admin access')),
745
745
746 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
746 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
747 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
747 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
748
748
749 ('hg.usergroup.create.false', _('User Group creation disabled')),
749 ('hg.usergroup.create.false', _('User Group creation disabled')),
750 ('hg.usergroup.create.true', _('User Group creation enabled')),
750 ('hg.usergroup.create.true', _('User Group creation enabled')),
751
751
752 ('hg.create.none', _('Repository creation disabled')),
752 ('hg.create.none', _('Repository creation disabled')),
753 ('hg.create.repository', _('Repository creation enabled')),
753 ('hg.create.repository', _('Repository creation enabled')),
754 ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')),
754 ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')),
755 ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')),
755 ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')),
756
756
757 ('hg.fork.none', _('Repository forking disabled')),
757 ('hg.fork.none', _('Repository forking disabled')),
758 ('hg.fork.repository', _('Repository forking enabled')),
758 ('hg.fork.repository', _('Repository forking enabled')),
759
759
760 ('hg.register.none', _('Registration disabled')),
760 ('hg.register.none', _('Registration disabled')),
761 ('hg.register.manual_activate', _('User Registration with manual account activation')),
761 ('hg.register.manual_activate', _('User Registration with manual account activation')),
762 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
762 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
763
763
764 ('hg.extern_activate.manual', _('Manual activation of external account')),
764 ('hg.extern_activate.manual', _('Manual activation of external account')),
765 ('hg.extern_activate.auto', _('Automatic activation of external account')),
765 ('hg.extern_activate.auto', _('Automatic activation of external account')),
766
766
767 ]
767 ]
768
768
769 #definition of system default permissions for DEFAULT user
769 #definition of system default permissions for DEFAULT user
770 DEFAULT_USER_PERMISSIONS = [
770 DEFAULT_USER_PERMISSIONS = [
771 'repository.read',
771 'repository.read',
772 'group.read',
772 'group.read',
773 'usergroup.read',
773 'usergroup.read',
774 'hg.create.repository',
774 'hg.create.repository',
775 'hg.create.write_on_repogroup.true',
775 'hg.create.write_on_repogroup.true',
776 'hg.fork.repository',
776 'hg.fork.repository',
777 'hg.register.manual_activate',
777 'hg.register.manual_activate',
778 'hg.extern_activate.auto',
778 'hg.extern_activate.auto',
779 ]
779 ]
780
780
781 # defines which permissions are more important higher the more important
781 # defines which permissions are more important higher the more important
782 # Weight defines which permissions are more important.
782 # Weight defines which permissions are more important.
783 # The higher number the more important.
783 # The higher number the more important.
784 PERM_WEIGHTS = {
784 PERM_WEIGHTS = {
785 'repository.none': 0,
785 'repository.none': 0,
786 'repository.read': 1,
786 'repository.read': 1,
787 'repository.write': 3,
787 'repository.write': 3,
788 'repository.admin': 4,
788 'repository.admin': 4,
789
789
790 'group.none': 0,
790 'group.none': 0,
791 'group.read': 1,
791 'group.read': 1,
792 'group.write': 3,
792 'group.write': 3,
793 'group.admin': 4,
793 'group.admin': 4,
794
794
795 'usergroup.none': 0,
795 'usergroup.none': 0,
796 'usergroup.read': 1,
796 'usergroup.read': 1,
797 'usergroup.write': 3,
797 'usergroup.write': 3,
798 'usergroup.admin': 4,
798 'usergroup.admin': 4,
799 'hg.repogroup.create.false': 0,
799 'hg.repogroup.create.false': 0,
800 'hg.repogroup.create.true': 1,
800 'hg.repogroup.create.true': 1,
801
801
802 'hg.usergroup.create.false': 0,
802 'hg.usergroup.create.false': 0,
803 'hg.usergroup.create.true': 1,
803 'hg.usergroup.create.true': 1,
804
804
805 'hg.fork.none': 0,
805 'hg.fork.none': 0,
806 'hg.fork.repository': 1,
806 'hg.fork.repository': 1,
807 'hg.create.none': 0,
807 'hg.create.none': 0,
808 'hg.create.repository': 1
808 'hg.create.repository': 1
809 }
809 }
810
810
811 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
811 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
812 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
812 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
813 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
813 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
814
814
815 def __unicode__(self):
815 def __unicode__(self):
816 return u"<%s('%s:%s')>" % (
816 return u"<%s('%s:%s')>" % (
817 self.__class__.__name__, self.permission_id, self.permission_name
817 self.__class__.__name__, self.permission_id, self.permission_name
818 )
818 )
819
819
820 @classmethod
820 @classmethod
821 def get_by_key(cls, key):
821 def get_by_key(cls, key):
822 return cls.query().filter(cls.permission_name == key).scalar()
822 return cls.query().filter(cls.permission_name == key).scalar()
823
823
824
824
825 class UserRepoToPerm(Base, BaseModel):
825 class UserRepoToPerm(Base, BaseModel):
826 __tablename__ = 'repo_to_perm'
826 __tablename__ = 'repo_to_perm'
827 __table_args__ = (
827 __table_args__ = (
828 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
828 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
829 {'extend_existing': True, 'mysql_engine': 'InnoDB',
829 {'extend_existing': True, 'mysql_engine': 'InnoDB',
830 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
830 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
831 )
831 )
832 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
832 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
833 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
833 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
834 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
834 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
835 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
835 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
836
836
837 user = relationship('User')
837 user = relationship('User')
838 repository = relationship('Repository')
838 repository = relationship('Repository')
839 permission = relationship('Permission')
839 permission = relationship('Permission')
840
840
841 def __unicode__(self):
841 def __unicode__(self):
842 return u'<%s => %s >' % (self.user, self.repository)
842 return u'<%s => %s >' % (self.user, self.repository)
843
843
844
844
845 class UserUserGroupToPerm(Base, BaseModel):
845 class UserUserGroupToPerm(Base, BaseModel):
846 __tablename__ = 'user_user_group_to_perm'
846 __tablename__ = 'user_user_group_to_perm'
847 __table_args__ = (
847 __table_args__ = (
848 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
848 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
849 {'extend_existing': True, 'mysql_engine': 'InnoDB',
849 {'extend_existing': True, 'mysql_engine': 'InnoDB',
850 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
850 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
851 )
851 )
852 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
852 user_user_group_to_perm_id = Column("user_user_group_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)
853 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)
854 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
855 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
855 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
856
856
857 user = relationship('User')
857 user = relationship('User')
858 user_group = relationship('UserGroup')
858 user_group = relationship('UserGroup')
859 permission = relationship('Permission')
859 permission = relationship('Permission')
860
860
861 def __unicode__(self):
861 def __unicode__(self):
862 return u'<%s => %s >' % (self.user, self.user_group)
862 return u'<%s => %s >' % (self.user, self.user_group)
863
863
864
864
865 class UserToPerm(Base, BaseModel):
865 class UserToPerm(Base, BaseModel):
866 __tablename__ = 'user_to_perm'
866 __tablename__ = 'user_to_perm'
867 __table_args__ = (
867 __table_args__ = (
868 UniqueConstraint('user_id', 'permission_id'),
868 UniqueConstraint('user_id', 'permission_id'),
869 {'extend_existing': True, 'mysql_engine': 'InnoDB',
869 {'extend_existing': True, 'mysql_engine': 'InnoDB',
870 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
870 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
871 )
871 )
872 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
872 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
873 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
873 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
874 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
874 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
875
875
876 user = relationship('User')
876 user = relationship('User')
877 permission = relationship('Permission', lazy='joined')
877 permission = relationship('Permission', lazy='joined')
878
878
879 def __unicode__(self):
879 def __unicode__(self):
880 return u'<%s => %s >' % (self.user, self.permission)
880 return u'<%s => %s >' % (self.user, self.permission)
881
881
882
882
883 class UserGroupRepoToPerm(Base, BaseModel):
883 class UserGroupRepoToPerm(Base, BaseModel):
884 __tablename__ = 'users_group_repo_to_perm'
884 __tablename__ = 'users_group_repo_to_perm'
885 __table_args__ = (
885 __table_args__ = (
886 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
886 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
887 {'extend_existing': True, 'mysql_engine': 'InnoDB',
887 {'extend_existing': True, 'mysql_engine': 'InnoDB',
888 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
888 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
889 )
889 )
890 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
890 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
891 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
891 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
892 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
892 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
893 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
893 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
894
894
895 users_group = relationship('UserGroup')
895 users_group = relationship('UserGroup')
896 permission = relationship('Permission')
896 permission = relationship('Permission')
897 repository = relationship('Repository')
897 repository = relationship('Repository')
898
898
899 def __unicode__(self):
899 def __unicode__(self):
900 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
900 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
901
901
902
902
903 class UserGroupUserGroupToPerm(Base, BaseModel):
903 class UserGroupUserGroupToPerm(Base, BaseModel):
904 __tablename__ = 'user_group_user_group_to_perm'
904 __tablename__ = 'user_group_user_group_to_perm'
905 __table_args__ = (
905 __table_args__ = (
906 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
906 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
907 CheckConstraint('target_user_group_id != user_group_id'),
907 CheckConstraint('target_user_group_id != user_group_id'),
908 {'extend_existing': True, 'mysql_engine': 'InnoDB',
908 {'extend_existing': True, 'mysql_engine': 'InnoDB',
909 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
909 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
910 )
910 )
911 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
911 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
912 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
912 target_user_group_id = Column("target_user_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)
913 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
914 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
914 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
915
915
916 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
916 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
917 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
917 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
918 permission = relationship('Permission')
918 permission = relationship('Permission')
919
919
920 def __unicode__(self):
920 def __unicode__(self):
921 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
921 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
922
922
923
923
924 class UserGroupToPerm(Base, BaseModel):
924 class UserGroupToPerm(Base, BaseModel):
925 __tablename__ = 'users_group_to_perm'
925 __tablename__ = 'users_group_to_perm'
926 __table_args__ = (
926 __table_args__ = (
927 UniqueConstraint('users_group_id', 'permission_id',),
927 UniqueConstraint('users_group_id', 'permission_id',),
928 {'extend_existing': True, 'mysql_engine': 'InnoDB',
928 {'extend_existing': True, 'mysql_engine': 'InnoDB',
929 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
929 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
930 )
930 )
931 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
931 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
932 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
932 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
933 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
933 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
934
934
935 users_group = relationship('UserGroup')
935 users_group = relationship('UserGroup')
936 permission = relationship('Permission')
936 permission = relationship('Permission')
937
937
938
938
939 class UserRepoGroupToPerm(Base, BaseModel):
939 class UserRepoGroupToPerm(Base, BaseModel):
940 __tablename__ = 'user_repo_group_to_perm'
940 __tablename__ = 'user_repo_group_to_perm'
941 __table_args__ = (
941 __table_args__ = (
942 UniqueConstraint('user_id', 'group_id', 'permission_id'),
942 UniqueConstraint('user_id', 'group_id', 'permission_id'),
943 {'extend_existing': True, 'mysql_engine': 'InnoDB',
943 {'extend_existing': True, 'mysql_engine': 'InnoDB',
944 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
944 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
945 )
945 )
946
946
947 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
947 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
948 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
948 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
949 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
949 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
950 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
950 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
951
951
952 user = relationship('User')
952 user = relationship('User')
953 group = relationship('RepoGroup')
953 group = relationship('RepoGroup')
954 permission = relationship('Permission')
954 permission = relationship('Permission')
955
955
956
956
957 class UserGroupRepoGroupToPerm(Base, BaseModel):
957 class UserGroupRepoGroupToPerm(Base, BaseModel):
958 __tablename__ = 'users_group_repo_group_to_perm'
958 __tablename__ = 'users_group_repo_group_to_perm'
959 __table_args__ = (
959 __table_args__ = (
960 UniqueConstraint('users_group_id', 'group_id'),
960 UniqueConstraint('users_group_id', 'group_id'),
961 {'extend_existing': True, 'mysql_engine': 'InnoDB',
961 {'extend_existing': True, 'mysql_engine': 'InnoDB',
962 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
962 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
963 )
963 )
964
964
965 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)
965 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)
966 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
966 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
967 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
967 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
968 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
968 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
969
969
970 users_group = relationship('UserGroup')
970 users_group = relationship('UserGroup')
971 permission = relationship('Permission')
971 permission = relationship('Permission')
972 group = relationship('RepoGroup')
972 group = relationship('RepoGroup')
973
973
974
974
975 class Statistics(Base, BaseModel):
975 class Statistics(Base, BaseModel):
976 __tablename__ = 'statistics'
976 __tablename__ = 'statistics'
977 __table_args__ = (
977 __table_args__ = (
978 UniqueConstraint('repository_id'),
978 UniqueConstraint('repository_id'),
979 {'extend_existing': True, 'mysql_engine': 'InnoDB',
979 {'extend_existing': True, 'mysql_engine': 'InnoDB',
980 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
980 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
981 )
981 )
982 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
982 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
983 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
983 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
984 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
984 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
985 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
985 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
986 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
986 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
987 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
987 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
988
988
989 repository = relationship('Repository', single_parent=True)
989 repository = relationship('Repository', single_parent=True)
990
990
991
991
992 class UserFollowing(Base, BaseModel):
992 class UserFollowing(Base, BaseModel):
993 __tablename__ = 'user_followings'
993 __tablename__ = 'user_followings'
994 __table_args__ = (
994 __table_args__ = (
995 UniqueConstraint('user_id', 'follows_repository_id'),
995 UniqueConstraint('user_id', 'follows_repository_id'),
996 UniqueConstraint('user_id', 'follows_user_id'),
996 UniqueConstraint('user_id', 'follows_user_id'),
997 {'extend_existing': True, 'mysql_engine': 'InnoDB',
997 {'extend_existing': True, 'mysql_engine': 'InnoDB',
998 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
998 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
999 )
999 )
1000
1000
1001 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1001 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)
1002 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)
1003 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)
1004 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)
1005 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1006
1006
1007 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1007 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1008
1008
1009 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1009 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1010 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1010 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1011
1011
1012
1012
1013 class CacheInvalidation(Base, BaseModel):
1013 class CacheInvalidation(Base, BaseModel):
1014 __tablename__ = 'cache_invalidation'
1014 __tablename__ = 'cache_invalidation'
1015 __table_args__ = (
1015 __table_args__ = (
1016 UniqueConstraint('cache_key'),
1016 UniqueConstraint('cache_key'),
1017 Index('key_idx', 'cache_key'),
1017 Index('key_idx', 'cache_key'),
1018 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1018 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1019 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1019 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1020 )
1020 )
1021 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1021 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1022 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1022 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1023 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1023 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1024 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1024 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1025
1025
1026 def __init__(self, cache_key, cache_args=''):
1026 def __init__(self, cache_key, cache_args=''):
1027 self.cache_key = cache_key
1027 self.cache_key = cache_key
1028 self.cache_args = cache_args
1028 self.cache_args = cache_args
1029 self.cache_active = False
1029 self.cache_active = False
1030
1030
1031
1031
1032 class ChangesetComment(Base, BaseModel):
1032 class ChangesetComment(Base, BaseModel):
1033 __tablename__ = 'changeset_comments'
1033 __tablename__ = 'changeset_comments'
1034 __table_args__ = (
1034 __table_args__ = (
1035 Index('cc_revision_idx', 'revision'),
1035 Index('cc_revision_idx', 'revision'),
1036 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1036 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1037 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1037 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1038 )
1038 )
1039 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1039 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1040 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1040 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1041 revision = Column('revision', String(40), nullable=True)
1041 revision = Column('revision', String(40), nullable=True)
1042 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1042 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1043 line_no = Column('line_no', Unicode(10), nullable=True)
1043 line_no = Column('line_no', Unicode(10), nullable=True)
1044 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1044 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1045 f_path = Column('f_path', Unicode(1000), nullable=True)
1045 f_path = Column('f_path', Unicode(1000), nullable=True)
1046 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1046 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1047 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1047 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1048 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1048 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1049 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1049 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1050
1050
1051 author = relationship('User', lazy='joined')
1051 author = relationship('User', lazy='joined')
1052 repo = relationship('Repository')
1052 repo = relationship('Repository')
1053 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1053 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1054 pull_request = relationship('PullRequest', lazy='joined')
1054 pull_request = relationship('PullRequest', lazy='joined')
1055
1055
1056
1056
1057 class ChangesetStatus(Base, BaseModel):
1057 class ChangesetStatus(Base, BaseModel):
1058 __tablename__ = 'changeset_statuses'
1058 __tablename__ = 'changeset_statuses'
1059 __table_args__ = (
1059 __table_args__ = (
1060 Index('cs_revision_idx', 'revision'),
1060 Index('cs_revision_idx', 'revision'),
1061 Index('cs_version_idx', 'version'),
1061 Index('cs_version_idx', 'version'),
1062 UniqueConstraint('repo_id', 'revision', 'version'),
1062 UniqueConstraint('repo_id', 'revision', 'version'),
1063 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1063 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1064 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1064 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1065 )
1065 )
1066 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1066 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1067 STATUS_APPROVED = 'approved'
1067 STATUS_APPROVED = 'approved'
1068 STATUS_REJECTED = 'rejected'
1068 STATUS_REJECTED = 'rejected'
1069 STATUS_UNDER_REVIEW = 'under_review'
1069 STATUS_UNDER_REVIEW = 'under_review'
1070
1070
1071 STATUSES = [
1071 STATUSES = [
1072 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1072 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1073 (STATUS_APPROVED, _("Approved")),
1073 (STATUS_APPROVED, _("Approved")),
1074 (STATUS_REJECTED, _("Rejected")),
1074 (STATUS_REJECTED, _("Rejected")),
1075 (STATUS_UNDER_REVIEW, _("Under Review")),
1075 (STATUS_UNDER_REVIEW, _("Under Review")),
1076 ]
1076 ]
1077
1077
1078 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1078 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1079 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1079 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1080 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1080 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1081 revision = Column('revision', String(40), nullable=False)
1081 revision = Column('revision', String(40), nullable=False)
1082 status = Column('status', String(128), nullable=False, default=DEFAULT)
1082 status = Column('status', String(128), nullable=False, default=DEFAULT)
1083 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1083 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1084 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1084 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1085 version = Column('version', Integer(), nullable=False, default=0)
1085 version = Column('version', Integer(), nullable=False, default=0)
1086 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1086 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1087
1087
1088 author = relationship('User', lazy='joined')
1088 author = relationship('User', lazy='joined')
1089 repo = relationship('Repository')
1089 repo = relationship('Repository')
1090 comment = relationship('ChangesetComment', lazy='joined')
1090 comment = relationship('ChangesetComment', lazy='joined')
1091 pull_request = relationship('PullRequest', lazy='joined')
1091 pull_request = relationship('PullRequest', lazy='joined')
1092
1092
1093
1093
1094
1094
1095 class PullRequest(Base, BaseModel):
1095 class PullRequest(Base, BaseModel):
1096 __tablename__ = 'pull_requests'
1096 __tablename__ = 'pull_requests'
1097 __table_args__ = (
1097 __table_args__ = (
1098 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1098 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1099 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1099 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1100 )
1100 )
1101
1101
1102 STATUS_NEW = u'new'
1102 STATUS_NEW = u'new'
1103 STATUS_OPEN = u'open'
1103 STATUS_OPEN = u'open'
1104 STATUS_CLOSED = u'closed'
1104 STATUS_CLOSED = u'closed'
1105
1105
1106 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1106 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1107 title = Column('title', Unicode(256), nullable=True)
1107 title = Column('title', Unicode(256), nullable=True)
1108 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1108 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1109 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1109 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1110 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1110 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1111 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1111 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1112 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1112 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1113 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1113 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1114 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1114 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1115 org_ref = Column('org_ref', Unicode(256), nullable=False)
1115 org_ref = Column('org_ref', Unicode(256), nullable=False)
1116 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1116 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1117 other_ref = Column('other_ref', Unicode(256), nullable=False)
1117 other_ref = Column('other_ref', Unicode(256), nullable=False)
1118
1118
1119 author = relationship('User', lazy='joined')
1119 author = relationship('User', lazy='joined')
1120 reviewers = relationship('PullRequestReviewers',
1120 reviewers = relationship('PullRequestReviewers',
1121 cascade="all, delete, delete-orphan")
1121 cascade="all, delete, delete-orphan")
1122 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1122 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1123 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1123 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1124 statuses = relationship('ChangesetStatus')
1124 statuses = relationship('ChangesetStatus')
1125 comments = relationship('ChangesetComment',
1125 comments = relationship('ChangesetComment',
1126 cascade="all, delete, delete-orphan")
1126 cascade="all, delete, delete-orphan")
1127
1127
1128
1128
1129 class PullRequestReviewers(Base, BaseModel):
1129 class PullRequestReviewers(Base, BaseModel):
1130 __tablename__ = 'pull_request_reviewers'
1130 __tablename__ = 'pull_request_reviewers'
1131 __table_args__ = (
1131 __table_args__ = (
1132 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1132 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1133 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1133 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1134 )
1134 )
1135
1135
1136 def __init__(self, user=None, pull_request=None):
1136 def __init__(self, user=None, pull_request=None):
1137 self.user = user
1137 self.user = user
1138 self.pull_request = pull_request
1138 self.pull_request = pull_request
1139
1139
1140 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1140 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1141 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1141 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1142 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1142 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1143
1143
1144 user = relationship('User')
1144 user = relationship('User')
1145 pull_request = relationship('PullRequest')
1145 pull_request = relationship('PullRequest')
1146
1146
1147
1147
1148 class Notification(Base, BaseModel):
1148 class Notification(Base, BaseModel):
1149 __tablename__ = 'notifications'
1149 __tablename__ = 'notifications'
1150 __table_args__ = (
1150 __table_args__ = (
1151 Index('notification_type_idx', 'type'),
1151 Index('notification_type_idx', 'type'),
1152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1153 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1153 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1154 )
1154 )
1155
1155
1156 TYPE_CHANGESET_COMMENT = u'cs_comment'
1156 TYPE_CHANGESET_COMMENT = u'cs_comment'
1157 TYPE_MESSAGE = u'message'
1157 TYPE_MESSAGE = u'message'
1158 TYPE_MENTION = u'mention'
1158 TYPE_MENTION = u'mention'
1159 TYPE_REGISTRATION = u'registration'
1159 TYPE_REGISTRATION = u'registration'
1160 TYPE_PULL_REQUEST = u'pull_request'
1160 TYPE_PULL_REQUEST = u'pull_request'
1161 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1161 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1162
1162
1163 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1163 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1164 subject = Column('subject', Unicode(512), nullable=True)
1164 subject = Column('subject', Unicode(512), nullable=True)
1165 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1165 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1166 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1166 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1167 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1167 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1168 type_ = Column('type', Unicode(256))
1168 type_ = Column('type', Unicode(256))
1169
1169
1170 created_by_user = relationship('User')
1170 created_by_user = relationship('User')
1171 notifications_to_users = relationship('UserNotification', lazy='joined',
1171 notifications_to_users = relationship('UserNotification', lazy='joined',
1172 cascade="all, delete, delete-orphan")
1172 cascade="all, delete, delete-orphan")
1173
1173
1174
1174
1175 class UserNotification(Base, BaseModel):
1175 class UserNotification(Base, BaseModel):
1176 __tablename__ = 'user_to_notification'
1176 __tablename__ = 'user_to_notification'
1177 __table_args__ = (
1177 __table_args__ = (
1178 UniqueConstraint('user_id', 'notification_id'),
1178 UniqueConstraint('user_id', 'notification_id'),
1179 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1179 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1180 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1180 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1181 )
1181 )
1182 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1182 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1183 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1183 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1184 read = Column('read', Boolean, default=False)
1184 read = Column('read', Boolean, default=False)
1185 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1185 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1186
1186
1187 user = relationship('User', lazy="joined")
1187 user = relationship('User', lazy="joined")
1188 notification = relationship('Notification', lazy="joined",
1188 notification = relationship('Notification', lazy="joined",
1189 order_by=lambda: Notification.created_on.desc(),)
1189 order_by=lambda: Notification.created_on.desc(),)
1190
1190
1191
1191
1192 class Gist(Base, BaseModel):
1192 class Gist(Base, BaseModel):
1193 __tablename__ = 'gists'
1193 __tablename__ = 'gists'
1194 __table_args__ = (
1194 __table_args__ = (
1195 Index('g_gist_access_id_idx', 'gist_access_id'),
1195 Index('g_gist_access_id_idx', 'gist_access_id'),
1196 Index('g_created_on_idx', 'created_on'),
1196 Index('g_created_on_idx', 'created_on'),
1197 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1197 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1198 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1198 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1199 )
1199 )
1200 GIST_PUBLIC = u'public'
1200 GIST_PUBLIC = u'public'
1201 GIST_PRIVATE = u'private'
1201 GIST_PRIVATE = u'private'
1202 DEFAULT_FILENAME = u'gistfile1.txt'
1202 DEFAULT_FILENAME = u'gistfile1.txt'
1203
1203
1204 gist_id = Column('gist_id', Integer(), primary_key=True)
1204 gist_id = Column('gist_id', Integer(), primary_key=True)
1205 gist_access_id = Column('gist_access_id', Unicode(250))
1205 gist_access_id = Column('gist_access_id', Unicode(250))
1206 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1206 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1207 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1207 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1208 gist_expires = Column('gist_expires', Float(53), nullable=False)
1208 gist_expires = Column('gist_expires', Float(53), nullable=False)
1209 gist_type = Column('gist_type', Unicode(128), nullable=False)
1209 gist_type = Column('gist_type', Unicode(128), nullable=False)
1210 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1210 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1211 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1211 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1212
1212
1213 owner = relationship('User')
1213 owner = relationship('User')
1214
1214
1215
1215
1216 class DbMigrateVersion(Base, BaseModel):
1216 class DbMigrateVersion(Base, BaseModel):
1217 __tablename__ = 'db_migrate_version'
1217 __tablename__ = 'db_migrate_version'
1218 __table_args__ = (
1218 __table_args__ = (
1219 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1219 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1220 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1220 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1221 )
1221 )
1222 repository_id = Column('repository_id', String(250), primary_key=True)
1222 repository_id = Column('repository_id', String(250), primary_key=True)
1223 repository_path = Column('repository_path', Text)
1223 repository_path = Column('repository_path', Text)
1224 version = Column('version', Integer)
1224 version = Column('version', Integer)
@@ -1,1230 +1,1230 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
46 get_clone_url
46 get_clone_url
47 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.ext_json import json
48 from rhodecode.lib.caching_query import FromCache
48 from rhodecode.lib.caching_query import FromCache
49
49
50 from rhodecode.model.meta import Base, Session
50 from rhodecode.model.meta import Base, Session
51
51
52 URL_SEP = '/'
52 URL_SEP = '/'
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55 #==============================================================================
55 #==============================================================================
56 # BASE CLASSES
56 # BASE CLASSES
57 #==============================================================================
57 #==============================================================================
58
58
59 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
60
60
61
61
62 class BaseModel(object):
62 class BaseModel(object):
63 """
63 """
64 Base Model for all classes
64 Base Model for all classes
65 """
65 """
66
66
67 @classmethod
67 @classmethod
68 def _get_keys(cls):
68 def _get_keys(cls):
69 """return column names for this model """
69 """return column names for this model """
70 return class_mapper(cls).c.keys()
70 return class_mapper(cls).c.keys()
71
71
72 def get_dict(self):
72 def get_dict(self):
73 """
73 """
74 return dict with keys and values corresponding
74 return dict with keys and values corresponding
75 to this model data """
75 to this model data """
76
76
77 d = {}
77 d = {}
78 for k in self._get_keys():
78 for k in self._get_keys():
79 d[k] = getattr(self, k)
79 d[k] = getattr(self, k)
80
80
81 # also use __json__() if present to get additional fields
81 # also use __json__() if present to get additional fields
82 _json_attr = getattr(self, '__json__', None)
82 _json_attr = getattr(self, '__json__', None)
83 if _json_attr:
83 if _json_attr:
84 # update with attributes from __json__
84 # update with attributes from __json__
85 if callable(_json_attr):
85 if callable(_json_attr):
86 _json_attr = _json_attr()
86 _json_attr = _json_attr()
87 for k, val in _json_attr.items():
87 for k, val in _json_attr.items():
88 d[k] = val
88 d[k] = val
89 return d
89 return d
90
90
91 def get_appstruct(self):
91 def get_appstruct(self):
92 """return list with keys and values tupples corresponding
92 """return list with keys and values tupples corresponding
93 to this model data """
93 to this model data """
94
94
95 l = []
95 l = []
96 for k in self._get_keys():
96 for k in self._get_keys():
97 l.append((k, getattr(self, k),))
97 l.append((k, getattr(self, k),))
98 return l
98 return l
99
99
100 def populate_obj(self, populate_dict):
100 def populate_obj(self, populate_dict):
101 """populate model with data from given populate_dict"""
101 """populate model with data from given populate_dict"""
102
102
103 for k in self._get_keys():
103 for k in self._get_keys():
104 if k in populate_dict:
104 if k in populate_dict:
105 setattr(self, k, populate_dict[k])
105 setattr(self, k, populate_dict[k])
106
106
107 @classmethod
107 @classmethod
108 def query(cls):
108 def query(cls):
109 return Session().query(cls)
109 return Session().query(cls)
110
110
111 @classmethod
111 @classmethod
112 def get(cls, id_):
112 def get(cls, id_):
113 if id_:
113 if id_:
114 return cls.query().get(id_)
114 return cls.query().get(id_)
115
115
116 @classmethod
116 @classmethod
117 def get_or_404(cls, id_):
117 def get_or_404(cls, id_):
118 try:
118 try:
119 id_ = int(id_)
119 id_ = int(id_)
120 except (TypeError, ValueError):
120 except (TypeError, ValueError):
121 raise HTTPNotFound
121 raise HTTPNotFound
122
122
123 res = cls.query().get(id_)
123 res = cls.query().get(id_)
124 if not res:
124 if not res:
125 raise HTTPNotFound
125 raise HTTPNotFound
126 return res
126 return res
127
127
128 @classmethod
128 @classmethod
129 def getAll(cls):
129 def getAll(cls):
130 # deprecated and left for backward compatibility
130 # deprecated and left for backward compatibility
131 return cls.get_all()
131 return cls.get_all()
132
132
133 @classmethod
133 @classmethod
134 def get_all(cls):
134 def get_all(cls):
135 return cls.query().all()
135 return cls.query().all()
136
136
137 @classmethod
137 @classmethod
138 def delete(cls, id_):
138 def delete(cls, id_):
139 obj = cls.query().get(id_)
139 obj = cls.query().get(id_)
140 Session().delete(obj)
140 Session().delete(obj)
141
141
142 def __repr__(self):
142 def __repr__(self):
143 if hasattr(self, '__unicode__'):
143 if hasattr(self, '__unicode__'):
144 # python repr needs to return str
144 # python repr needs to return str
145 try:
145 try:
146 return safe_str(self.__unicode__())
146 return safe_str(self.__unicode__())
147 except UnicodeDecodeError:
147 except UnicodeDecodeError:
148 pass
148 pass
149 return '<DB:%s>' % (self.__class__.__name__)
149 return '<DB:%s>' % (self.__class__.__name__)
150
150
151
151
152 class RhodeCodeSetting(Base, BaseModel):
152 class RhodeCodeSetting(Base, BaseModel):
153 __tablename__ = 'rhodecode_settings'
153 __tablename__ = 'rhodecode_settings'
154 __table_args__ = (
154 __table_args__ = (
155 UniqueConstraint('app_settings_name'),
155 UniqueConstraint('app_settings_name'),
156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
157 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
157 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
158 )
158 )
159
159
160 SETTINGS_TYPES = {
160 SETTINGS_TYPES = {
161 'str': safe_str,
161 'str': safe_str,
162 'int': safe_int,
162 'int': safe_int,
163 'unicode': safe_str,
163 'unicode': safe_str,
164 'bool': str2bool,
164 'bool': str2bool,
165 'list': functools.partial(aslist, sep=',')
165 'list': functools.partial(aslist, sep=',')
166 }
166 }
167 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
167 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
168
168
169 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
169 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
170 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
170 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
171 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
171 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
172 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
172 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
173
173
174 def __init__(self, key='', val='', type='unicode'):
174 def __init__(self, key='', val='', type='unicode'):
175 self.app_settings_name = key
175 self.app_settings_name = key
176 self.app_settings_value = val
176 self.app_settings_value = val
177 self.app_settings_type = type
177 self.app_settings_type = type
178
178
179 @validates('_app_settings_value')
179 @validates('_app_settings_value')
180 def validate_settings_value(self, key, val):
180 def validate_settings_value(self, key, val):
181 assert type(val) == str
181 assert type(val) == str
182 return val
182 return val
183
183
184 @hybrid_property
184 @hybrid_property
185 def app_settings_value(self):
185 def app_settings_value(self):
186 v = self._app_settings_value
186 v = self._app_settings_value
187 _type = self.app_settings_type
187 _type = self.app_settings_type
188 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
188 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
189 return converter(v)
189 return converter(v)
190
190
191 @app_settings_value.setter
191 @app_settings_value.setter
192 def app_settings_value(self, val):
192 def app_settings_value(self, val):
193 """
193 """
194 Setter that will always make sure we use unicode in app_settings_value
194 Setter that will always make sure we use unicode in app_settings_value
195
195
196 :param val:
196 :param val:
197 """
197 """
198 self._app_settings_value = safe_str(val)
198 self._app_settings_value = safe_str(val)
199
199
200 @hybrid_property
200 @hybrid_property
201 def app_settings_type(self):
201 def app_settings_type(self):
202 return self._app_settings_type
202 return self._app_settings_type
203
203
204 @app_settings_type.setter
204 @app_settings_type.setter
205 def app_settings_type(self, val):
205 def app_settings_type(self, val):
206 if val not in self.SETTINGS_TYPES:
206 if val not in self.SETTINGS_TYPES:
207 raise Exception('type must be one of %s got %s'
207 raise Exception('type must be one of %s got %s'
208 % (self.SETTINGS_TYPES.keys(), val))
208 % (self.SETTINGS_TYPES.keys(), val))
209 self._app_settings_type = val
209 self._app_settings_type = val
210
210
211 def __unicode__(self):
211 def __unicode__(self):
212 return u"<%s('%s:%s[%s]')>" % (
212 return u"<%s('%s:%s[%s]')>" % (
213 self.__class__.__name__,
213 self.__class__.__name__,
214 self.app_settings_name, self.app_settings_value, self.app_settings_type
214 self.app_settings_name, self.app_settings_value, self.app_settings_type
215 )
215 )
216
216
217
217
218 class RhodeCodeUi(Base, BaseModel):
218 class RhodeCodeUi(Base, BaseModel):
219 __tablename__ = 'rhodecode_ui'
219 __tablename__ = 'rhodecode_ui'
220 __table_args__ = (
220 __table_args__ = (
221 UniqueConstraint('ui_key'),
221 UniqueConstraint('ui_key'),
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
223 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
224 )
224 )
225
225
226 HOOK_REPO_SIZE = 'changegroup.repo_size'
226 HOOK_REPO_SIZE = 'changegroup.repo_size'
227 HOOK_PUSH = 'changegroup.push_logger'
227 HOOK_PUSH = 'changegroup.push_logger'
228 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
228 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
229 HOOK_PULL = 'outgoing.pull_logger'
229 HOOK_PULL = 'outgoing.pull_logger'
230 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
230 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
231
231
232 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
233 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
233 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
234 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
234 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
235 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
235 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
236 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
236 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
237
237
238 def __repr__(self):
238 def __repr__(self):
239 return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section,
239 return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section,
240 self.ui_key, self.ui_value)
240 self.ui_key, self.ui_value)
241
241
242
242
243 class User(Base, BaseModel):
243 class User(Base, BaseModel):
244 __tablename__ = 'users'
244 __tablename__ = 'users'
245 __table_args__ = (
245 __table_args__ = (
246 UniqueConstraint('username'), UniqueConstraint('email'),
246 UniqueConstraint('username'), UniqueConstraint('email'),
247 Index('u_username_idx', 'username'),
247 Index('u_username_idx', 'username'),
248 Index('u_email_idx', 'email'),
248 Index('u_email_idx', 'email'),
249 {'extend_existing': True, 'mysql_engine': 'InnoDB',
249 {'extend_existing': True, 'mysql_engine': 'InnoDB',
250 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
250 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
251 )
251 )
252 DEFAULT_USER = 'default'
252 DEFAULT_USER = 'default'
253 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
253 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
254
254
255 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
255 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
256 username = Column("username", String(255), nullable=True, unique=None, default=None)
256 username = Column("username", String(255), nullable=True, unique=None, default=None)
257 password = Column("password", String(255), nullable=True, unique=None, default=None)
257 password = Column("password", String(255), nullable=True, unique=None, default=None)
258 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
258 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
259 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
259 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
260 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
260 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
261 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
261 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
262 _email = Column("email", String(255), nullable=True, unique=None, default=None)
262 _email = Column("email", String(255), nullable=True, unique=None, default=None)
263 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
263 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
264 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
264 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
265 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
265 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
266 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
266 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
267 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
267 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
268 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
268 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
269 _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data
269 _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data
270
270
271 user_log = relationship('UserLog')
271 user_log = relationship('UserLog')
272 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
272 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
273
273
274 repositories = relationship('Repository')
274 repositories = relationship('Repository')
275 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
275 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
276 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
276 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
277
277
278 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
278 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
279 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
279 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
280
280
281 group_member = relationship('UserGroupMember', cascade='all')
281 group_member = relationship('UserGroupMember', cascade='all')
282
282
283 notifications = relationship('UserNotification', cascade='all')
283 notifications = relationship('UserNotification', cascade='all')
284 # notifications assigned to this user
284 # notifications assigned to this user
285 user_created_notifications = relationship('Notification', cascade='all')
285 user_created_notifications = relationship('Notification', cascade='all')
286 # comments created by this user
286 # comments created by this user
287 user_comments = relationship('ChangesetComment', cascade='all')
287 user_comments = relationship('ChangesetComment', cascade='all')
288 user_emails = relationship('UserEmailMap', cascade='all')
288 user_emails = relationship('UserEmailMap', cascade='all')
289 user_auth_tokens = relationship('UserApiKeys', cascade='all')
289 user_auth_tokens = relationship('UserApiKeys', cascade='all')
290
290
291 @hybrid_property
291 @hybrid_property
292 def email(self):
292 def email(self):
293 return self._email
293 return self._email
294
294
295 @email.setter
295 @email.setter
296 def email(self, val):
296 def email(self, val):
297 self._email = val.lower() if val else None
297 self._email = val.lower() if val else None
298
298
299 @property
299 @property
300 def firstname(self):
300 def firstname(self):
301 # alias for future
301 # alias for future
302 return self.name
302 return self.name
303
303
304 @property
304 @property
305 def username_and_name(self):
305 def username_and_name(self):
306 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
306 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
307
307
308 @property
308 @property
309 def full_name(self):
309 def full_name(self):
310 return '%s %s' % (self.firstname, self.lastname)
310 return '%s %s' % (self.firstname, self.lastname)
311
311
312 @property
312 @property
313 def full_contact(self):
313 def full_contact(self):
314 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
314 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
315
315
316 @property
316 @property
317 def short_contact(self):
317 def short_contact(self):
318 return '%s %s' % (self.firstname, self.lastname)
318 return '%s %s' % (self.firstname, self.lastname)
319
319
320 @property
320 @property
321 def is_admin(self):
321 def is_admin(self):
322 return self.admin
322 return self.admin
323
323
324 @classmethod
324 @classmethod
325 def get_by_username(cls, username, case_insensitive=False, cache=False):
325 def get_by_username(cls, username, case_insensitive=False, cache=False):
326 if case_insensitive:
326 if case_insensitive:
327 q = cls.query().filter(cls.username.ilike(username))
327 q = cls.query().filter(cls.username.ilike(username))
328 else:
328 else:
329 q = cls.query().filter(cls.username == username)
329 q = cls.query().filter(cls.username == username)
330
330
331 if cache:
331 if cache:
332 q = q.options(FromCache(
332 q = q.options(FromCache(
333 "sql_cache_short",
333 "sql_cache_short",
334 "get_user_%s" % _hash_key(username)
334 "get_user_%s" % _hash_key(username)
335 )
335 )
336 )
336 )
337 return q.scalar()
337 return q.scalar()
338
338
339 @classmethod
339 @classmethod
340 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
340 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
341 q = cls.query().filter(cls.api_key == auth_token)
341 q = cls.query().filter(cls.api_key == auth_token)
342
342
343 if cache:
343 if cache:
344 q = q.options(FromCache("sql_cache_short",
344 q = q.options(FromCache("sql_cache_short",
345 "get_auth_token_%s" % auth_token))
345 "get_auth_token_%s" % auth_token))
346 res = q.scalar()
346 res = q.scalar()
347
347
348 if fallback and not res:
348 if fallback and not res:
349 #fallback to additional keys
349 #fallback to additional keys
350 _res = UserApiKeys.query()\
350 _res = UserApiKeys.query()\
351 .filter(UserApiKeys.api_key == auth_token)\
351 .filter(UserApiKeys.api_key == auth_token)\
352 .filter(or_(UserApiKeys.expires == -1,
352 .filter(or_(UserApiKeys.expires == -1,
353 UserApiKeys.expires >= time.time()))\
353 UserApiKeys.expires >= time.time()))\
354 .first()
354 .first()
355 if _res:
355 if _res:
356 res = _res.user
356 res = _res.user
357 return res
357 return res
358
358
359 @classmethod
359 @classmethod
360 def get_by_email(cls, email, case_insensitive=False, cache=False):
360 def get_by_email(cls, email, case_insensitive=False, cache=False):
361
361
362 if case_insensitive:
362 if case_insensitive:
363 q = cls.query().filter(cls.email.ilike(email))
363 q = cls.query().filter(cls.email.ilike(email))
364 else:
364 else:
365 q = cls.query().filter(cls.email == email)
365 q = cls.query().filter(cls.email == email)
366
366
367 if cache:
367 if cache:
368 q = q.options(FromCache("sql_cache_short",
368 q = q.options(FromCache("sql_cache_short",
369 "get_email_key_%s" % email))
369 "get_email_key_%s" % email))
370
370
371 ret = q.scalar()
371 ret = q.scalar()
372 if ret is None:
372 if ret is None:
373 q = UserEmailMap.query()
373 q = UserEmailMap.query()
374 # try fetching in alternate email map
374 # try fetching in alternate email map
375 if case_insensitive:
375 if case_insensitive:
376 q = q.filter(UserEmailMap.email.ilike(email))
376 q = q.filter(UserEmailMap.email.ilike(email))
377 else:
377 else:
378 q = q.filter(UserEmailMap.email == email)
378 q = q.filter(UserEmailMap.email == email)
379 q = q.options(joinedload(UserEmailMap.user))
379 q = q.options(joinedload(UserEmailMap.user))
380 if cache:
380 if cache:
381 q = q.options(FromCache("sql_cache_short",
381 q = q.options(FromCache("sql_cache_short",
382 "get_email_map_key_%s" % email))
382 "get_email_map_key_%s" % email))
383 ret = getattr(q.scalar(), 'user', None)
383 ret = getattr(q.scalar(), 'user', None)
384
384
385 return ret
385 return ret
386
386
387 @classmethod
387 @classmethod
388 def get_first_admin(cls):
388 def get_first_admin(cls):
389 user = User.query().filter(User.admin == True).first()
389 user = User.query().filter(User.admin == True).first()
390 if user is None:
390 if user is None:
391 raise Exception('Missing administrative account!')
391 raise Exception('Missing administrative account!')
392 return user
392 return user
393
393
394 @classmethod
394 @classmethod
395 def get_default_user(cls, cache=False):
395 def get_default_user(cls, cache=False):
396 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
396 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
397 if user is None:
397 if user is None:
398 raise Exception('Missing default account!')
398 raise Exception('Missing default account!')
399 return user
399 return user
400
400
401
401
402 class UserApiKeys(Base, BaseModel):
402 class UserApiKeys(Base, BaseModel):
403 __tablename__ = 'user_api_keys'
403 __tablename__ = 'user_api_keys'
404 __table_args__ = (
404 __table_args__ = (
405 Index('uak_api_key_idx', 'api_key'),
405 Index('uak_api_key_idx', 'api_key'),
406 Index('uak_api_key_expires_idx', 'api_key', 'expires'),
406 Index('uak_api_key_expires_idx', 'api_key', 'expires'),
407 UniqueConstraint('api_key'),
407 UniqueConstraint('api_key'),
408 {'extend_existing': True, 'mysql_engine': 'InnoDB',
408 {'extend_existing': True, 'mysql_engine': 'InnoDB',
409 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
409 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
410 )
410 )
411
411
412
412
413 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
413 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
414 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
414 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
415 api_key = Column("api_key", String(255), nullable=False, unique=True)
415 api_key = Column("api_key", String(255), nullable=False, unique=True)
416 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
416 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
417 expires = Column('expires', Float(53), nullable=False)
417 expires = Column('expires', Float(53), nullable=False)
418 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
418 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
419
419
420 user = relationship('User', lazy='joined')
420 user = relationship('User', lazy='joined')
421
421
422
422
423 class UserEmailMap(Base, BaseModel):
423 class UserEmailMap(Base, BaseModel):
424 __tablename__ = 'user_email_map'
424 __tablename__ = 'user_email_map'
425 __table_args__ = (
425 __table_args__ = (
426 Index('uem_email_idx', 'email'),
426 Index('uem_email_idx', 'email'),
427 UniqueConstraint('email'),
427 UniqueConstraint('email'),
428 {'extend_existing': True, 'mysql_engine': 'InnoDB',
428 {'extend_existing': True, 'mysql_engine': 'InnoDB',
429 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
429 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
430 )
430 )
431
431
432
432
433 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
433 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
434 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
434 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
435 _email = Column("email", String(255), nullable=True, unique=False, default=None)
435 _email = Column("email", String(255), nullable=True, unique=False, default=None)
436 user = relationship('User', lazy='joined')
436 user = relationship('User', lazy='joined')
437
437
438 @validates('_email')
438 @validates('_email')
439 def validate_email(self, key, email):
439 def validate_email(self, key, email):
440 # check if this email is not main one
440 # check if this email is not main one
441 main_email = Session().query(User).filter(User.email == email).scalar()
441 main_email = Session().query(User).filter(User.email == email).scalar()
442 if main_email is not None:
442 if main_email is not None:
443 raise AttributeError('email %s is present is user table' % email)
443 raise AttributeError('email %s is present is user table' % email)
444 return email
444 return email
445
445
446 @hybrid_property
446 @hybrid_property
447 def email(self):
447 def email(self):
448 return self._email
448 return self._email
449
449
450 @email.setter
450 @email.setter
451 def email(self, val):
451 def email(self, val):
452 self._email = val.lower() if val else None
452 self._email = val.lower() if val else None
453
453
454
454
455 class UserIpMap(Base, BaseModel):
455 class UserIpMap(Base, BaseModel):
456 __tablename__ = 'user_ip_map'
456 __tablename__ = 'user_ip_map'
457 __table_args__ = (
457 __table_args__ = (
458 UniqueConstraint('user_id', 'ip_addr'),
458 UniqueConstraint('user_id', 'ip_addr'),
459 {'extend_existing': True, 'mysql_engine': 'InnoDB',
459 {'extend_existing': True, 'mysql_engine': 'InnoDB',
460 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
460 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
461 )
461 )
462
462
463
463
464 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
464 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
465 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
465 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
466 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
466 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
467 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
467 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
468 user = relationship('User', lazy='joined')
468 user = relationship('User', lazy='joined')
469
469
470 def __unicode__(self):
470 def __unicode__(self):
471 return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__,
471 return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__,
472 self.user_id, self.ip_addr)
472 self.user_id, self.ip_addr)
473
473
474
474
475 class UserLog(Base, BaseModel):
475 class UserLog(Base, BaseModel):
476 __tablename__ = 'user_logs'
476 __tablename__ = 'user_logs'
477 __table_args__ = (
477 __table_args__ = (
478 {'extend_existing': True, 'mysql_engine': 'InnoDB',
478 {'extend_existing': True, 'mysql_engine': 'InnoDB',
479 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
479 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
480 )
480 )
481 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
481 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
482 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
482 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
483 username = Column("username", String(255), nullable=True, unique=None, default=None)
483 username = Column("username", String(255), nullable=True, unique=None, default=None)
484 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
484 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
485 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
485 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
486 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
486 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
487 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
487 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
488 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
488 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
489
489
490 def __unicode__(self):
490 def __unicode__(self):
491 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
491 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
492 self.repository_name,
492 self.repository_name,
493 self.action)
493 self.action)
494
494
495 user = relationship('User')
495 user = relationship('User')
496 repository = relationship('Repository', cascade='')
496 repository = relationship('Repository', cascade='')
497
497
498
498
499 class UserGroup(Base, BaseModel):
499 class UserGroup(Base, BaseModel):
500 __tablename__ = 'users_groups'
500 __tablename__ = 'users_groups'
501 __table_args__ = (
501 __table_args__ = (
502 {'extend_existing': True, 'mysql_engine': 'InnoDB',
502 {'extend_existing': True, 'mysql_engine': 'InnoDB',
503 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
503 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
504 )
504 )
505
505
506 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
506 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
507 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
507 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
508 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
508 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
509 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
509 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
510 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
510 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
511 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
511 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
512 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
512 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
513 _group_data = Column("group_data", LargeBinary(), nullable=True) # JSON data
513 _group_data = Column("group_data", LargeBinary(), nullable=True) # JSON data
514
514
515 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
515 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
516 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
516 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
517 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
517 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
518 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
518 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
519 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
519 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
520 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
520 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
521
521
522 user = relationship('User')
522 user = relationship('User')
523
523
524 def __unicode__(self):
524 def __unicode__(self):
525 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
525 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
526 self.users_group_id,
526 self.users_group_id,
527 self.users_group_name)
527 self.users_group_name)
528
528
529 @classmethod
529 @classmethod
530 def get_by_group_name(cls, group_name, cache=False,
530 def get_by_group_name(cls, group_name, cache=False,
531 case_insensitive=False):
531 case_insensitive=False):
532 if case_insensitive:
532 if case_insensitive:
533 q = cls.query().filter(cls.users_group_name.ilike(group_name))
533 q = cls.query().filter(cls.users_group_name.ilike(group_name))
534 else:
534 else:
535 q = cls.query().filter(cls.users_group_name == group_name)
535 q = cls.query().filter(cls.users_group_name == group_name)
536 if cache:
536 if cache:
537 q = q.options(FromCache(
537 q = q.options(FromCache(
538 "sql_cache_short",
538 "sql_cache_short",
539 "get_user_%s" % _hash_key(group_name)
539 "get_user_%s" % _hash_key(group_name)
540 )
540 )
541 )
541 )
542 return q.scalar()
542 return q.scalar()
543
543
544 @classmethod
544 @classmethod
545 def get(cls, user_group_id, cache=False):
545 def get(cls, user_group_id, cache=False):
546 user_group = cls.query()
546 user_group = cls.query()
547 if cache:
547 if cache:
548 user_group = user_group.options(FromCache("sql_cache_short",
548 user_group = user_group.options(FromCache("sql_cache_short",
549 "get_users_group_%s" % user_group_id))
549 "get_users_group_%s" % user_group_id))
550 return user_group.get(user_group_id)
550 return user_group.get(user_group_id)
551
551
552
552
553 class UserGroupMember(Base, BaseModel):
553 class UserGroupMember(Base, BaseModel):
554 __tablename__ = 'users_groups_members'
554 __tablename__ = 'users_groups_members'
555 __table_args__ = (
555 __table_args__ = (
556 {'extend_existing': True, 'mysql_engine': 'InnoDB',
556 {'extend_existing': True, 'mysql_engine': 'InnoDB',
557 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
557 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
558 )
558 )
559
559
560 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
560 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
561 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
561 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
562 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
562 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
563
563
564 user = relationship('User', lazy='joined')
564 user = relationship('User', lazy='joined')
565 users_group = relationship('UserGroup')
565 users_group = relationship('UserGroup')
566
566
567 def __init__(self, gr_id='', u_id=''):
567 def __init__(self, gr_id='', u_id=''):
568 self.users_group_id = gr_id
568 self.users_group_id = gr_id
569 self.user_id = u_id
569 self.user_id = u_id
570
570
571
571
572 class RepositoryField(Base, BaseModel):
572 class RepositoryField(Base, BaseModel):
573 __tablename__ = 'repositories_fields'
573 __tablename__ = 'repositories_fields'
574 __table_args__ = (
574 __table_args__ = (
575 UniqueConstraint('repository_id', 'field_key'), # no-multi field
575 UniqueConstraint('repository_id', 'field_key'), # no-multi field
576 {'extend_existing': True, 'mysql_engine': 'InnoDB',
576 {'extend_existing': True, 'mysql_engine': 'InnoDB',
577 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
577 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
578 )
578 )
579 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
579 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
580
580
581 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
581 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
582 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
582 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
583 field_key = Column("field_key", String(250))
583 field_key = Column("field_key", String(250))
584 field_label = Column("field_label", String(1024), nullable=False)
584 field_label = Column("field_label", String(1024), nullable=False)
585 field_value = Column("field_value", String(10000), nullable=False)
585 field_value = Column("field_value", String(10000), nullable=False)
586 field_desc = Column("field_desc", String(1024), nullable=False)
586 field_desc = Column("field_desc", String(1024), nullable=False)
587 field_type = Column("field_type", String(256), nullable=False, unique=None)
587 field_type = Column("field_type", String(256), nullable=False, unique=None)
588 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
588 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
589
589
590 repository = relationship('Repository')
590 repository = relationship('Repository')
591
591
592 @classmethod
592 @classmethod
593 def get_by_key_name(cls, key, repo):
593 def get_by_key_name(cls, key, repo):
594 row = cls.query()\
594 row = cls.query()\
595 .filter(cls.repository == repo)\
595 .filter(cls.repository == repo)\
596 .filter(cls.field_key == key).scalar()
596 .filter(cls.field_key == key).scalar()
597 return row
597 return row
598
598
599
599
600 class Repository(Base, BaseModel):
600 class Repository(Base, BaseModel):
601 __tablename__ = 'repositories'
601 __tablename__ = 'repositories'
602 __table_args__ = (
602 __table_args__ = (
603 UniqueConstraint('repo_name'),
603 UniqueConstraint('repo_name'),
604 Index('r_repo_name_idx', 'repo_name'),
604 Index('r_repo_name_idx', 'repo_name'),
605 {'extend_existing': True, 'mysql_engine': 'InnoDB',
605 {'extend_existing': True, 'mysql_engine': 'InnoDB',
606 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
606 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
607 )
607 )
608 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
608 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
609 DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
609 DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
610
610
611 STATE_CREATED = 'repo_state_created'
611 STATE_CREATED = 'repo_state_created'
612 STATE_PENDING = 'repo_state_pending'
612 STATE_PENDING = 'repo_state_pending'
613 STATE_ERROR = 'repo_state_error'
613 STATE_ERROR = 'repo_state_error'
614
614
615 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
615 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
616 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
616 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
617 repo_state = Column("repo_state", String(255), nullable=True)
617 repo_state = Column("repo_state", String(255), nullable=True)
618
618
619 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
619 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
620 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
620 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
621 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
621 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
622 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
622 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
623 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
623 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
624 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
624 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
625 description = Column("description", String(10000), nullable=True, unique=None, default=None)
625 description = Column("description", String(10000), nullable=True, unique=None, default=None)
626 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
626 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
627 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
627 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
628 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
628 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
629 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
629 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
630 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
630 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
631 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
631 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
632
632
633 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
633 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
634 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
634 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
635
635
636 user = relationship('User')
636 user = relationship('User')
637 fork = relationship('Repository', remote_side=repo_id)
637 fork = relationship('Repository', remote_side=repo_id)
638 group = relationship('RepoGroup')
638 group = relationship('RepoGroup')
639 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
639 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
640 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
640 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
641 stats = relationship('Statistics', cascade='all', uselist=False)
641 stats = relationship('Statistics', cascade='all', uselist=False)
642
642
643 followers = relationship('UserFollowing',
643 followers = relationship('UserFollowing',
644 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
644 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
645 cascade='all')
645 cascade='all')
646 extra_fields = relationship('RepositoryField',
646 extra_fields = relationship('RepositoryField',
647 cascade="all, delete, delete-orphan")
647 cascade="all, delete, delete-orphan")
648
648
649 logs = relationship('UserLog')
649 logs = relationship('UserLog')
650 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
650 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
651
651
652 pull_requests_org = relationship('PullRequest',
652 pull_requests_org = relationship('PullRequest',
653 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
653 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
654 cascade="all, delete, delete-orphan")
654 cascade="all, delete, delete-orphan")
655
655
656 pull_requests_other = relationship('PullRequest',
656 pull_requests_other = relationship('PullRequest',
657 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
657 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
658 cascade="all, delete, delete-orphan")
658 cascade="all, delete, delete-orphan")
659
659
660 def __unicode__(self):
660 def __unicode__(self):
661 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
661 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
662 safe_str(self.repo_name))
662 safe_str(self.repo_name))
663
663
664 @classmethod
664 @classmethod
665 def get_by_repo_name(cls, repo_name):
665 def get_by_repo_name(cls, repo_name):
666 q = Session().query(cls).filter(cls.repo_name == repo_name)
666 q = Session().query(cls).filter(cls.repo_name == repo_name)
667 q = q.options(joinedload(Repository.fork))\
667 q = q.options(joinedload(Repository.fork))\
668 .options(joinedload(Repository.user))\
668 .options(joinedload(Repository.user))\
669 .options(joinedload(Repository.group))
669 .options(joinedload(Repository.group))
670 return q.scalar()
670 return q.scalar()
671
671
672
672
673 class RepoGroup(Base, BaseModel):
673 class RepoGroup(Base, BaseModel):
674 __tablename__ = 'groups'
674 __tablename__ = 'groups'
675 __table_args__ = (
675 __table_args__ = (
676 UniqueConstraint('group_name', 'group_parent_id'),
676 UniqueConstraint('group_name', 'group_parent_id'),
677 {'extend_existing': True, 'mysql_engine': 'InnoDB',
677 {'extend_existing': True, 'mysql_engine': 'InnoDB',
678 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
678 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
679 )
679 )
680
680
681
681
682 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
682 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
683 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
683 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
684 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
684 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
685 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
685 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
686 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
686 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
687 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
687 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
688 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
688 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
689
689
690 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
690 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
691 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
691 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
692 parent_group = relationship('RepoGroup', remote_side=group_id)
692 parent_group = relationship('RepoGroup', remote_side=group_id)
693 user = relationship('User')
693 user = relationship('User')
694
694
695 def __init__(self, group_name='', parent_group=None):
695 def __init__(self, group_name='', parent_group=None):
696 self.group_name = group_name
696 self.group_name = group_name
697 self.parent_group = parent_group
697 self.parent_group = parent_group
698
698
699 def __unicode__(self):
699 def __unicode__(self):
700 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
700 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
701 self.group_name)
701 self.group_name)
702
702
703 @classmethod
703 @classmethod
704 def url_sep(cls):
704 def url_sep(cls):
705 return URL_SEP
705 return URL_SEP
706
706
707 @classmethod
707 @classmethod
708 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
708 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
709 if case_insensitive:
709 if case_insensitive:
710 gr = cls.query()\
710 gr = cls.query()\
711 .filter(cls.group_name.ilike(group_name))
711 .filter(cls.group_name.ilike(group_name))
712 else:
712 else:
713 gr = cls.query()\
713 gr = cls.query()\
714 .filter(cls.group_name == group_name)
714 .filter(cls.group_name == group_name)
715 if cache:
715 if cache:
716 gr = gr.options(FromCache(
716 gr = gr.options(FromCache(
717 "sql_cache_short",
717 "sql_cache_short",
718 "get_group_%s" % _hash_key(group_name)
718 "get_group_%s" % _hash_key(group_name)
719 )
719 )
720 )
720 )
721 return gr.scalar()
721 return gr.scalar()
722
722
723
723
724 class Permission(Base, BaseModel):
724 class Permission(Base, BaseModel):
725 __tablename__ = 'permissions'
725 __tablename__ = 'permissions'
726 __table_args__ = (
726 __table_args__ = (
727 Index('p_perm_name_idx', 'permission_name'),
727 Index('p_perm_name_idx', 'permission_name'),
728 {'extend_existing': True, 'mysql_engine': 'InnoDB',
728 {'extend_existing': True, 'mysql_engine': 'InnoDB',
729 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
729 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
730 )
730 )
731 PERMS = [
731 PERMS = [
732 ('hg.admin', _('RhodeCode Administrator')),
732 ('hg.admin', _('RhodeCode Administrator')),
733
733
734 ('repository.none', _('Repository no access')),
734 ('repository.none', _('Repository no access')),
735 ('repository.read', _('Repository read access')),
735 ('repository.read', _('Repository read access')),
736 ('repository.write', _('Repository write access')),
736 ('repository.write', _('Repository write access')),
737 ('repository.admin', _('Repository admin access')),
737 ('repository.admin', _('Repository admin access')),
738
738
739 ('group.none', _('Repository group no access')),
739 ('group.none', _('Repository group no access')),
740 ('group.read', _('Repository group read access')),
740 ('group.read', _('Repository group read access')),
741 ('group.write', _('Repository group write access')),
741 ('group.write', _('Repository group write access')),
742 ('group.admin', _('Repository group admin access')),
742 ('group.admin', _('Repository group admin access')),
743
743
744 ('usergroup.none', _('User group no access')),
744 ('usergroup.none', _('User group no access')),
745 ('usergroup.read', _('User group read access')),
745 ('usergroup.read', _('User group read access')),
746 ('usergroup.write', _('User group write access')),
746 ('usergroup.write', _('User group write access')),
747 ('usergroup.admin', _('User group admin access')),
747 ('usergroup.admin', _('User group admin access')),
748
748
749 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
749 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
750 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
750 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
751
751
752 ('hg.usergroup.create.false', _('User Group creation disabled')),
752 ('hg.usergroup.create.false', _('User Group creation disabled')),
753 ('hg.usergroup.create.true', _('User Group creation enabled')),
753 ('hg.usergroup.create.true', _('User Group creation enabled')),
754
754
755 ('hg.create.none', _('Repository creation disabled')),
755 ('hg.create.none', _('Repository creation disabled')),
756 ('hg.create.repository', _('Repository creation enabled')),
756 ('hg.create.repository', _('Repository creation enabled')),
757 ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')),
757 ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')),
758 ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')),
758 ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')),
759
759
760 ('hg.fork.none', _('Repository forking disabled')),
760 ('hg.fork.none', _('Repository forking disabled')),
761 ('hg.fork.repository', _('Repository forking enabled')),
761 ('hg.fork.repository', _('Repository forking enabled')),
762
762
763 ('hg.register.none', _('Registration disabled')),
763 ('hg.register.none', _('Registration disabled')),
764 ('hg.register.manual_activate', _('User Registration with manual account activation')),
764 ('hg.register.manual_activate', _('User Registration with manual account activation')),
765 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
765 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
766
766
767 ('hg.extern_activate.manual', _('Manual activation of external account')),
767 ('hg.extern_activate.manual', _('Manual activation of external account')),
768 ('hg.extern_activate.auto', _('Automatic activation of external account')),
768 ('hg.extern_activate.auto', _('Automatic activation of external account')),
769
769
770 ]
770 ]
771
771
772 #definition of system default permissions for DEFAULT user
772 #definition of system default permissions for DEFAULT user
773 DEFAULT_USER_PERMISSIONS = [
773 DEFAULT_USER_PERMISSIONS = [
774 'repository.read',
774 'repository.read',
775 'group.read',
775 'group.read',
776 'usergroup.read',
776 'usergroup.read',
777 'hg.create.repository',
777 'hg.create.repository',
778 'hg.create.write_on_repogroup.true',
778 'hg.create.write_on_repogroup.true',
779 'hg.fork.repository',
779 'hg.fork.repository',
780 'hg.register.manual_activate',
780 'hg.register.manual_activate',
781 'hg.extern_activate.auto',
781 'hg.extern_activate.auto',
782 ]
782 ]
783
783
784 # defines which permissions are more important higher the more important
784 # defines which permissions are more important higher the more important
785 # Weight defines which permissions are more important.
785 # Weight defines which permissions are more important.
786 # The higher number the more important.
786 # The higher number the more important.
787 PERM_WEIGHTS = {
787 PERM_WEIGHTS = {
788 'repository.none': 0,
788 'repository.none': 0,
789 'repository.read': 1,
789 'repository.read': 1,
790 'repository.write': 3,
790 'repository.write': 3,
791 'repository.admin': 4,
791 'repository.admin': 4,
792
792
793 'group.none': 0,
793 'group.none': 0,
794 'group.read': 1,
794 'group.read': 1,
795 'group.write': 3,
795 'group.write': 3,
796 'group.admin': 4,
796 'group.admin': 4,
797
797
798 'usergroup.none': 0,
798 'usergroup.none': 0,
799 'usergroup.read': 1,
799 'usergroup.read': 1,
800 'usergroup.write': 3,
800 'usergroup.write': 3,
801 'usergroup.admin': 4,
801 'usergroup.admin': 4,
802 'hg.repogroup.create.false': 0,
802 'hg.repogroup.create.false': 0,
803 'hg.repogroup.create.true': 1,
803 'hg.repogroup.create.true': 1,
804
804
805 'hg.usergroup.create.false': 0,
805 'hg.usergroup.create.false': 0,
806 'hg.usergroup.create.true': 1,
806 'hg.usergroup.create.true': 1,
807
807
808 'hg.fork.none': 0,
808 'hg.fork.none': 0,
809 'hg.fork.repository': 1,
809 'hg.fork.repository': 1,
810 'hg.create.none': 0,
810 'hg.create.none': 0,
811 'hg.create.repository': 1
811 'hg.create.repository': 1
812 }
812 }
813
813
814 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
814 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
815 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
815 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
816 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
816 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
817
817
818 def __unicode__(self):
818 def __unicode__(self):
819 return u"<%s('%s:%s')>" % (
819 return u"<%s('%s:%s')>" % (
820 self.__class__.__name__, self.permission_id, self.permission_name
820 self.__class__.__name__, self.permission_id, self.permission_name
821 )
821 )
822
822
823 @classmethod
823 @classmethod
824 def get_by_key(cls, key):
824 def get_by_key(cls, key):
825 return cls.query().filter(cls.permission_name == key).scalar()
825 return cls.query().filter(cls.permission_name == key).scalar()
826
826
827
827
828 class UserRepoToPerm(Base, BaseModel):
828 class UserRepoToPerm(Base, BaseModel):
829 __tablename__ = 'repo_to_perm'
829 __tablename__ = 'repo_to_perm'
830 __table_args__ = (
830 __table_args__ = (
831 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
831 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
832 {'extend_existing': True, 'mysql_engine': 'InnoDB',
832 {'extend_existing': True, 'mysql_engine': 'InnoDB',
833 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
833 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
834 )
834 )
835 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
835 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
836 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
836 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
837 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
837 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
838 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
838 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
839
839
840 user = relationship('User')
840 user = relationship('User')
841 repository = relationship('Repository')
841 repository = relationship('Repository')
842 permission = relationship('Permission')
842 permission = relationship('Permission')
843
843
844 def __unicode__(self):
844 def __unicode__(self):
845 return u'<%s => %s >' % (self.user, self.repository)
845 return u'<%s => %s >' % (self.user, self.repository)
846
846
847
847
848 class UserUserGroupToPerm(Base, BaseModel):
848 class UserUserGroupToPerm(Base, BaseModel):
849 __tablename__ = 'user_user_group_to_perm'
849 __tablename__ = 'user_user_group_to_perm'
850 __table_args__ = (
850 __table_args__ = (
851 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
851 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
852 {'extend_existing': True, 'mysql_engine': 'InnoDB',
852 {'extend_existing': True, 'mysql_engine': 'InnoDB',
853 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
853 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
854 )
854 )
855 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
855 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
856 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
856 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
857 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
857 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
858 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
858 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
859
859
860 user = relationship('User')
860 user = relationship('User')
861 user_group = relationship('UserGroup')
861 user_group = relationship('UserGroup')
862 permission = relationship('Permission')
862 permission = relationship('Permission')
863
863
864 def __unicode__(self):
864 def __unicode__(self):
865 return u'<%s => %s >' % (self.user, self.user_group)
865 return u'<%s => %s >' % (self.user, self.user_group)
866
866
867
867
868 class UserToPerm(Base, BaseModel):
868 class UserToPerm(Base, BaseModel):
869 __tablename__ = 'user_to_perm'
869 __tablename__ = 'user_to_perm'
870 __table_args__ = (
870 __table_args__ = (
871 UniqueConstraint('user_id', 'permission_id'),
871 UniqueConstraint('user_id', 'permission_id'),
872 {'extend_existing': True, 'mysql_engine': 'InnoDB',
872 {'extend_existing': True, 'mysql_engine': 'InnoDB',
873 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
873 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
874 )
874 )
875 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
875 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
876 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
876 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
877 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
877 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
878
878
879 user = relationship('User')
879 user = relationship('User')
880 permission = relationship('Permission', lazy='joined')
880 permission = relationship('Permission', lazy='joined')
881
881
882 def __unicode__(self):
882 def __unicode__(self):
883 return u'<%s => %s >' % (self.user, self.permission)
883 return u'<%s => %s >' % (self.user, self.permission)
884
884
885
885
886 class UserGroupRepoToPerm(Base, BaseModel):
886 class UserGroupRepoToPerm(Base, BaseModel):
887 __tablename__ = 'users_group_repo_to_perm'
887 __tablename__ = 'users_group_repo_to_perm'
888 __table_args__ = (
888 __table_args__ = (
889 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
889 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
890 {'extend_existing': True, 'mysql_engine': 'InnoDB',
890 {'extend_existing': True, 'mysql_engine': 'InnoDB',
891 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
891 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
892 )
892 )
893 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
893 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
894 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
894 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
895 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)
896 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)
897
897
898 users_group = relationship('UserGroup')
898 users_group = relationship('UserGroup')
899 permission = relationship('Permission')
899 permission = relationship('Permission')
900 repository = relationship('Repository')
900 repository = relationship('Repository')
901
901
902 def __unicode__(self):
902 def __unicode__(self):
903 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
903 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
904
904
905
905
906 class UserGroupUserGroupToPerm(Base, BaseModel):
906 class UserGroupUserGroupToPerm(Base, BaseModel):
907 __tablename__ = 'user_group_user_group_to_perm'
907 __tablename__ = 'user_group_user_group_to_perm'
908 __table_args__ = (
908 __table_args__ = (
909 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
909 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
910 CheckConstraint('target_user_group_id != user_group_id'),
910 CheckConstraint('target_user_group_id != user_group_id'),
911 {'extend_existing': True, 'mysql_engine': 'InnoDB',
911 {'extend_existing': True, 'mysql_engine': 'InnoDB',
912 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
912 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
913 )
913 )
914 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
914 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
915 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
915 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
916 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
916 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
917 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
917 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
918
918
919 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
919 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
920 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
920 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
921 permission = relationship('Permission')
921 permission = relationship('Permission')
922
922
923 def __unicode__(self):
923 def __unicode__(self):
924 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
924 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
925
925
926
926
927 class UserGroupToPerm(Base, BaseModel):
927 class UserGroupToPerm(Base, BaseModel):
928 __tablename__ = 'users_group_to_perm'
928 __tablename__ = 'users_group_to_perm'
929 __table_args__ = (
929 __table_args__ = (
930 UniqueConstraint('users_group_id', 'permission_id',),
930 UniqueConstraint('users_group_id', 'permission_id',),
931 {'extend_existing': True, 'mysql_engine': 'InnoDB',
931 {'extend_existing': True, 'mysql_engine': 'InnoDB',
932 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
932 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
933 )
933 )
934 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
934 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
935 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
935 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
936 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
936 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
937
937
938 users_group = relationship('UserGroup')
938 users_group = relationship('UserGroup')
939 permission = relationship('Permission')
939 permission = relationship('Permission')
940
940
941
941
942 class UserRepoGroupToPerm(Base, BaseModel):
942 class UserRepoGroupToPerm(Base, BaseModel):
943 __tablename__ = 'user_repo_group_to_perm'
943 __tablename__ = 'user_repo_group_to_perm'
944 __table_args__ = (
944 __table_args__ = (
945 UniqueConstraint('user_id', 'group_id', 'permission_id'),
945 UniqueConstraint('user_id', 'group_id', 'permission_id'),
946 {'extend_existing': True, 'mysql_engine': 'InnoDB',
946 {'extend_existing': True, 'mysql_engine': 'InnoDB',
947 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
947 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
948 )
948 )
949
949
950 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
950 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
951 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
951 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
952 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
952 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
953 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
953 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
954
954
955 user = relationship('User')
955 user = relationship('User')
956 group = relationship('RepoGroup')
956 group = relationship('RepoGroup')
957 permission = relationship('Permission')
957 permission = relationship('Permission')
958
958
959
959
960 class UserGroupRepoGroupToPerm(Base, BaseModel):
960 class UserGroupRepoGroupToPerm(Base, BaseModel):
961 __tablename__ = 'users_group_repo_group_to_perm'
961 __tablename__ = 'users_group_repo_group_to_perm'
962 __table_args__ = (
962 __table_args__ = (
963 UniqueConstraint('users_group_id', 'group_id'),
963 UniqueConstraint('users_group_id', 'group_id'),
964 {'extend_existing': True, 'mysql_engine': 'InnoDB',
964 {'extend_existing': True, 'mysql_engine': 'InnoDB',
965 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
965 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
966 )
966 )
967
967
968 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)
968 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)
969 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
969 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
970 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
970 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
971 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
971 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
972
972
973 users_group = relationship('UserGroup')
973 users_group = relationship('UserGroup')
974 permission = relationship('Permission')
974 permission = relationship('Permission')
975 group = relationship('RepoGroup')
975 group = relationship('RepoGroup')
976
976
977
977
978 class Statistics(Base, BaseModel):
978 class Statistics(Base, BaseModel):
979 __tablename__ = 'statistics'
979 __tablename__ = 'statistics'
980 __table_args__ = (
980 __table_args__ = (
981 UniqueConstraint('repository_id'),
981 UniqueConstraint('repository_id'),
982 {'extend_existing': True, 'mysql_engine': 'InnoDB',
982 {'extend_existing': True, 'mysql_engine': 'InnoDB',
983 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
983 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
984 )
984 )
985 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
985 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
986 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
986 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
987 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
987 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
988 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
988 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
989 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
989 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
990 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
990 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
991
991
992 repository = relationship('Repository', single_parent=True)
992 repository = relationship('Repository', single_parent=True)
993
993
994
994
995 class UserFollowing(Base, BaseModel):
995 class UserFollowing(Base, BaseModel):
996 __tablename__ = 'user_followings'
996 __tablename__ = 'user_followings'
997 __table_args__ = (
997 __table_args__ = (
998 UniqueConstraint('user_id', 'follows_repository_id'),
998 UniqueConstraint('user_id', 'follows_repository_id'),
999 UniqueConstraint('user_id', 'follows_user_id'),
999 UniqueConstraint('user_id', 'follows_user_id'),
1000 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1000 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1001 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1001 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1002 )
1002 )
1003
1003
1004 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1004 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1005 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1005 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1006 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1006 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1007 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1007 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1008 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1008 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1009
1009
1010 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1010 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1011
1011
1012 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1012 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1013 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1013 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1014
1014
1015
1015
1016 class CacheInvalidation(Base, BaseModel):
1016 class CacheInvalidation(Base, BaseModel):
1017 __tablename__ = 'cache_invalidation'
1017 __tablename__ = 'cache_invalidation'
1018 __table_args__ = (
1018 __table_args__ = (
1019 UniqueConstraint('cache_key'),
1019 UniqueConstraint('cache_key'),
1020 Index('key_idx', 'cache_key'),
1020 Index('key_idx', 'cache_key'),
1021 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1021 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1022 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1022 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1023 )
1023 )
1024 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1024 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1025 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1025 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1026 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1026 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1027 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1027 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1028
1028
1029 def __init__(self, cache_key, cache_args=''):
1029 def __init__(self, cache_key, cache_args=''):
1030 self.cache_key = cache_key
1030 self.cache_key = cache_key
1031 self.cache_args = cache_args
1031 self.cache_args = cache_args
1032 self.cache_active = False
1032 self.cache_active = False
1033
1033
1034
1034
1035 class ChangesetComment(Base, BaseModel):
1035 class ChangesetComment(Base, BaseModel):
1036 __tablename__ = 'changeset_comments'
1036 __tablename__ = 'changeset_comments'
1037 __table_args__ = (
1037 __table_args__ = (
1038 Index('cc_revision_idx', 'revision'),
1038 Index('cc_revision_idx', 'revision'),
1039 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1039 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1040 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1040 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1041 )
1041 )
1042 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1042 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1043 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1043 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1044 revision = Column('revision', String(40), nullable=True)
1044 revision = Column('revision', String(40), nullable=True)
1045 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1045 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1046 line_no = Column('line_no', Unicode(10), nullable=True)
1046 line_no = Column('line_no', Unicode(10), nullable=True)
1047 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1047 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1048 f_path = Column('f_path', Unicode(1000), nullable=True)
1048 f_path = Column('f_path', Unicode(1000), nullable=True)
1049 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1049 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1050 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1050 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1051 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1051 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1052 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1052 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1053
1053
1054 author = relationship('User', lazy='joined')
1054 author = relationship('User', lazy='joined')
1055 repo = relationship('Repository')
1055 repo = relationship('Repository')
1056 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1056 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1057 pull_request = relationship('PullRequest', lazy='joined')
1057 pull_request = relationship('PullRequest', lazy='joined')
1058
1058
1059
1059
1060 class ChangesetStatus(Base, BaseModel):
1060 class ChangesetStatus(Base, BaseModel):
1061 __tablename__ = 'changeset_statuses'
1061 __tablename__ = 'changeset_statuses'
1062 __table_args__ = (
1062 __table_args__ = (
1063 Index('cs_revision_idx', 'revision'),
1063 Index('cs_revision_idx', 'revision'),
1064 Index('cs_version_idx', 'version'),
1064 Index('cs_version_idx', 'version'),
1065 UniqueConstraint('repo_id', 'revision', 'version'),
1065 UniqueConstraint('repo_id', 'revision', 'version'),
1066 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1066 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1067 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1067 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1068 )
1068 )
1069 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1069 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1070 STATUS_APPROVED = 'approved'
1070 STATUS_APPROVED = 'approved'
1071 STATUS_REJECTED = 'rejected'
1071 STATUS_REJECTED = 'rejected'
1072 STATUS_UNDER_REVIEW = 'under_review'
1072 STATUS_UNDER_REVIEW = 'under_review'
1073
1073
1074 STATUSES = [
1074 STATUSES = [
1075 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1075 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1076 (STATUS_APPROVED, _("Approved")),
1076 (STATUS_APPROVED, _("Approved")),
1077 (STATUS_REJECTED, _("Rejected")),
1077 (STATUS_REJECTED, _("Rejected")),
1078 (STATUS_UNDER_REVIEW, _("Under Review")),
1078 (STATUS_UNDER_REVIEW, _("Under Review")),
1079 ]
1079 ]
1080
1080
1081 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1081 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1082 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1082 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1083 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1083 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1084 revision = Column('revision', String(40), nullable=False)
1084 revision = Column('revision', String(40), nullable=False)
1085 status = Column('status', String(128), nullable=False, default=DEFAULT)
1085 status = Column('status', String(128), nullable=False, default=DEFAULT)
1086 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1086 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1087 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1087 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1088 version = Column('version', Integer(), nullable=False, default=0)
1088 version = Column('version', Integer(), nullable=False, default=0)
1089 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1089 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1090
1090
1091 author = relationship('User', lazy='joined')
1091 author = relationship('User', lazy='joined')
1092 repo = relationship('Repository')
1092 repo = relationship('Repository')
1093 comment = relationship('ChangesetComment', lazy='joined')
1093 comment = relationship('ChangesetComment', lazy='joined')
1094 pull_request = relationship('PullRequest', lazy='joined')
1094 pull_request = relationship('PullRequest', lazy='joined')
1095
1095
1096
1096
1097
1097
1098 class PullRequest(Base, BaseModel):
1098 class PullRequest(Base, BaseModel):
1099 __tablename__ = 'pull_requests'
1099 __tablename__ = 'pull_requests'
1100 __table_args__ = (
1100 __table_args__ = (
1101 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1101 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1102 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1102 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1103 )
1103 )
1104
1104
1105 STATUS_NEW = u'new'
1105 STATUS_NEW = u'new'
1106 STATUS_OPEN = u'open'
1106 STATUS_OPEN = u'open'
1107 STATUS_CLOSED = u'closed'
1107 STATUS_CLOSED = u'closed'
1108
1108
1109 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1109 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1110 title = Column('title', Unicode(256), nullable=True)
1110 title = Column('title', Unicode(256), nullable=True)
1111 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1111 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1112 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1112 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1113 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1113 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1114 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1114 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1115 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1115 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1116 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1116 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1117 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1117 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1118 org_ref = Column('org_ref', Unicode(256), nullable=False)
1118 org_ref = Column('org_ref', Unicode(256), nullable=False)
1119 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1119 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1120 other_ref = Column('other_ref', Unicode(256), nullable=False)
1120 other_ref = Column('other_ref', Unicode(256), nullable=False)
1121
1121
1122 author = relationship('User', lazy='joined')
1122 author = relationship('User', lazy='joined')
1123 reviewers = relationship('PullRequestReviewers',
1123 reviewers = relationship('PullRequestReviewers',
1124 cascade="all, delete, delete-orphan")
1124 cascade="all, delete, delete-orphan")
1125 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1125 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1126 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1126 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1127 statuses = relationship('ChangesetStatus')
1127 statuses = relationship('ChangesetStatus')
1128 comments = relationship('ChangesetComment',
1128 comments = relationship('ChangesetComment',
1129 cascade="all, delete, delete-orphan")
1129 cascade="all, delete, delete-orphan")
1130
1130
1131
1131
1132 class PullRequestReviewers(Base, BaseModel):
1132 class PullRequestReviewers(Base, BaseModel):
1133 __tablename__ = 'pull_request_reviewers'
1133 __tablename__ = 'pull_request_reviewers'
1134 __table_args__ = (
1134 __table_args__ = (
1135 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1135 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1136 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1136 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1137 )
1137 )
1138
1138
1139 def __init__(self, user=None, pull_request=None):
1139 def __init__(self, user=None, pull_request=None):
1140 self.user = user
1140 self.user = user
1141 self.pull_request = pull_request
1141 self.pull_request = pull_request
1142
1142
1143 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1143 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1144 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1144 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1145 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1145 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1146
1146
1147 user = relationship('User')
1147 user = relationship('User')
1148 pull_request = relationship('PullRequest')
1148 pull_request = relationship('PullRequest')
1149
1149
1150
1150
1151 class Notification(Base, BaseModel):
1151 class Notification(Base, BaseModel):
1152 __tablename__ = 'notifications'
1152 __tablename__ = 'notifications'
1153 __table_args__ = (
1153 __table_args__ = (
1154 Index('notification_type_idx', 'type'),
1154 Index('notification_type_idx', 'type'),
1155 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1155 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1156 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1156 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1157 )
1157 )
1158
1158
1159 TYPE_CHANGESET_COMMENT = u'cs_comment'
1159 TYPE_CHANGESET_COMMENT = u'cs_comment'
1160 TYPE_MESSAGE = u'message'
1160 TYPE_MESSAGE = u'message'
1161 TYPE_MENTION = u'mention'
1161 TYPE_MENTION = u'mention'
1162 TYPE_REGISTRATION = u'registration'
1162 TYPE_REGISTRATION = u'registration'
1163 TYPE_PULL_REQUEST = u'pull_request'
1163 TYPE_PULL_REQUEST = u'pull_request'
1164 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1164 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1165
1165
1166 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1166 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1167 subject = Column('subject', Unicode(512), nullable=True)
1167 subject = Column('subject', Unicode(512), nullable=True)
1168 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1168 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1169 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1169 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1170 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1170 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1171 type_ = Column('type', Unicode(256))
1171 type_ = Column('type', Unicode(256))
1172
1172
1173 created_by_user = relationship('User')
1173 created_by_user = relationship('User')
1174 notifications_to_users = relationship('UserNotification', lazy='joined',
1174 notifications_to_users = relationship('UserNotification', lazy='joined',
1175 cascade="all, delete, delete-orphan")
1175 cascade="all, delete, delete-orphan")
1176
1176
1177
1177
1178 class UserNotification(Base, BaseModel):
1178 class UserNotification(Base, BaseModel):
1179 __tablename__ = 'user_to_notification'
1179 __tablename__ = 'user_to_notification'
1180 __table_args__ = (
1180 __table_args__ = (
1181 UniqueConstraint('user_id', 'notification_id'),
1181 UniqueConstraint('user_id', 'notification_id'),
1182 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1182 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1183 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1183 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1184 )
1184 )
1185 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1185 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1186 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1186 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1187 read = Column('read', Boolean, default=False)
1187 read = Column('read', Boolean, default=False)
1188 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1188 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1189
1189
1190 user = relationship('User', lazy="joined")
1190 user = relationship('User', lazy="joined")
1191 notification = relationship('Notification', lazy="joined",
1191 notification = relationship('Notification', lazy="joined",
1192 order_by=lambda: Notification.created_on.desc(),)
1192 order_by=lambda: Notification.created_on.desc(),)
1193
1193
1194
1194
1195 class Gist(Base, BaseModel):
1195 class Gist(Base, BaseModel):
1196 __tablename__ = 'gists'
1196 __tablename__ = 'gists'
1197 __table_args__ = (
1197 __table_args__ = (
1198 Index('g_gist_access_id_idx', 'gist_access_id'),
1198 Index('g_gist_access_id_idx', 'gist_access_id'),
1199 Index('g_created_on_idx', 'created_on'),
1199 Index('g_created_on_idx', 'created_on'),
1200 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1200 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1201 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1201 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1202 )
1202 )
1203 GIST_PUBLIC = u'public'
1203 GIST_PUBLIC = u'public'
1204 GIST_PRIVATE = u'private'
1204 GIST_PRIVATE = u'private'
1205 DEFAULT_FILENAME = u'gistfile1.txt'
1205 DEFAULT_FILENAME = u'gistfile1.txt'
1206
1206
1207 gist_id = Column('gist_id', Integer(), primary_key=True)
1207 gist_id = Column('gist_id', Integer(), primary_key=True)
1208 gist_access_id = Column('gist_access_id', Unicode(250))
1208 gist_access_id = Column('gist_access_id', Unicode(250))
1209 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1209 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1210 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1210 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1211 gist_expires = Column('gist_expires', Float(53), nullable=False)
1211 gist_expires = Column('gist_expires', Float(53), nullable=False)
1212 gist_type = Column('gist_type', Unicode(128), nullable=False)
1212 gist_type = Column('gist_type', Unicode(128), nullable=False)
1213 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1213 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1214 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1214 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1215
1215
1216 owner = relationship('User')
1216 owner = relationship('User')
1217
1217
1218 def __repr__(self):
1218 def __repr__(self):
1219 return '<Gist:[%s]%s>' % (self.gist_type, self.gist_access_id)
1219 return '<Gist:[%s]%s>' % (self.gist_type, self.gist_access_id)
1220
1220
1221
1221
1222 class DbMigrateVersion(Base, BaseModel):
1222 class DbMigrateVersion(Base, BaseModel):
1223 __tablename__ = 'db_migrate_version'
1223 __tablename__ = 'db_migrate_version'
1224 __table_args__ = (
1224 __table_args__ = (
1225 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1225 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1226 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1226 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1227 )
1227 )
1228 repository_id = Column('repository_id', String(250), primary_key=True)
1228 repository_id = Column('repository_id', String(250), primary_key=True)
1229 repository_path = Column('repository_path', Text)
1229 repository_path = Column('repository_path', Text)
1230 version = Column('version', Integer)
1230 version = Column('version', Integer)
@@ -1,1241 +1,1241 b''
1
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
3 #
4 # This program is free software: you can redistribute it and/or modify
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
5 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
6 # (only), as published by the Free Software Foundation.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU Affero General Public License
13 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
15 #
16 # This program is dual-licensed. If you wish to learn more about the
16 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
19
20 import os
20 import os
21 import time
21 import time
22 import logging
22 import logging
23 import datetime
23 import datetime
24 import traceback
24 import traceback
25 import hashlib
25 import hashlib
26 import collections
26 import collections
27 import functools
27 import functools
28
28
29 from sqlalchemy import *
29 from sqlalchemy import *
30 from sqlalchemy.ext.hybrid import hybrid_property
30 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
31 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from beaker.cache import cache_region, region_invalidate
33 from beaker.cache import cache_region, region_invalidate
34 from webob.exc import HTTPNotFound
34 from webob.exc import HTTPNotFound
35
35
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
41 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
42 from rhodecode.lib.vcs.backends.base import EmptyCommit
43
43
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
45 remove_prefix, time_to_datetime, aslist, Optional, safe_int, \
46 get_clone_url
46 get_clone_url
47 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.ext_json import json
48 from rhodecode.lib.caching_query import FromCache
48 from rhodecode.lib.caching_query import FromCache
49
49
50 from rhodecode.model.meta import Base, Session
50 from rhodecode.model.meta import Base, Session
51
51
52 URL_SEP = '/'
52 URL_SEP = '/'
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55 #==============================================================================
55 #==============================================================================
56 # BASE CLASSES
56 # BASE CLASSES
57 #==============================================================================
57 #==============================================================================
58
58
59 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
60
60
61
61
62 class BaseModel(object):
62 class BaseModel(object):
63 """
63 """
64 Base Model for all classes
64 Base Model for all classes
65 """
65 """
66
66
67 @classmethod
67 @classmethod
68 def _get_keys(cls):
68 def _get_keys(cls):
69 """return column names for this model """
69 """return column names for this model """
70 return class_mapper(cls).c.keys()
70 return class_mapper(cls).c.keys()
71
71
72 def get_dict(self):
72 def get_dict(self):
73 """
73 """
74 return dict with keys and values corresponding
74 return dict with keys and values corresponding
75 to this model data """
75 to this model data """
76
76
77 d = {}
77 d = {}
78 for k in self._get_keys():
78 for k in self._get_keys():
79 d[k] = getattr(self, k)
79 d[k] = getattr(self, k)
80
80
81 # also use __json__() if present to get additional fields
81 # also use __json__() if present to get additional fields
82 _json_attr = getattr(self, '__json__', None)
82 _json_attr = getattr(self, '__json__', None)
83 if _json_attr:
83 if _json_attr:
84 # update with attributes from __json__
84 # update with attributes from __json__
85 if callable(_json_attr):
85 if callable(_json_attr):
86 _json_attr = _json_attr()
86 _json_attr = _json_attr()
87 for k, val in _json_attr.items():
87 for k, val in _json_attr.items():
88 d[k] = val
88 d[k] = val
89 return d
89 return d
90
90
91 def get_appstruct(self):
91 def get_appstruct(self):
92 """return list with keys and values tupples corresponding
92 """return list with keys and values tupples corresponding
93 to this model data """
93 to this model data """
94
94
95 l = []
95 l = []
96 for k in self._get_keys():
96 for k in self._get_keys():
97 l.append((k, getattr(self, k),))
97 l.append((k, getattr(self, k),))
98 return l
98 return l
99
99
100 def populate_obj(self, populate_dict):
100 def populate_obj(self, populate_dict):
101 """populate model with data from given populate_dict"""
101 """populate model with data from given populate_dict"""
102
102
103 for k in self._get_keys():
103 for k in self._get_keys():
104 if k in populate_dict:
104 if k in populate_dict:
105 setattr(self, k, populate_dict[k])
105 setattr(self, k, populate_dict[k])
106
106
107 @classmethod
107 @classmethod
108 def query(cls):
108 def query(cls):
109 return Session().query(cls)
109 return Session().query(cls)
110
110
111 @classmethod
111 @classmethod
112 def get(cls, id_):
112 def get(cls, id_):
113 if id_:
113 if id_:
114 return cls.query().get(id_)
114 return cls.query().get(id_)
115
115
116 @classmethod
116 @classmethod
117 def get_or_404(cls, id_):
117 def get_or_404(cls, id_):
118 try:
118 try:
119 id_ = int(id_)
119 id_ = int(id_)
120 except (TypeError, ValueError):
120 except (TypeError, ValueError):
121 raise HTTPNotFound
121 raise HTTPNotFound
122
122
123 res = cls.query().get(id_)
123 res = cls.query().get(id_)
124 if not res:
124 if not res:
125 raise HTTPNotFound
125 raise HTTPNotFound
126 return res
126 return res
127
127
128 @classmethod
128 @classmethod
129 def getAll(cls):
129 def getAll(cls):
130 # deprecated and left for backward compatibility
130 # deprecated and left for backward compatibility
131 return cls.get_all()
131 return cls.get_all()
132
132
133 @classmethod
133 @classmethod
134 def get_all(cls):
134 def get_all(cls):
135 return cls.query().all()
135 return cls.query().all()
136
136
137 @classmethod
137 @classmethod
138 def delete(cls, id_):
138 def delete(cls, id_):
139 obj = cls.query().get(id_)
139 obj = cls.query().get(id_)
140 Session().delete(obj)
140 Session().delete(obj)
141
141
142 def __repr__(self):
142 def __repr__(self):
143 if hasattr(self, '__unicode__'):
143 if hasattr(self, '__unicode__'):
144 # python repr needs to return str
144 # python repr needs to return str
145 try:
145 try:
146 return safe_str(self.__unicode__())
146 return safe_str(self.__unicode__())
147 except UnicodeDecodeError:
147 except UnicodeDecodeError:
148 pass
148 pass
149 return '<DB:%s>' % (self.__class__.__name__)
149 return '<DB:%s>' % (self.__class__.__name__)
150
150
151
151
152 class RhodeCodeSetting(Base, BaseModel):
152 class RhodeCodeSetting(Base, BaseModel):
153 __tablename__ = 'rhodecode_settings'
153 __tablename__ = 'rhodecode_settings'
154 __table_args__ = (
154 __table_args__ = (
155 UniqueConstraint('app_settings_name'),
155 UniqueConstraint('app_settings_name'),
156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
157 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
157 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
158 )
158 )
159
159
160 SETTINGS_TYPES = {
160 SETTINGS_TYPES = {
161 'str': safe_str,
161 'str': safe_str,
162 'int': safe_int,
162 'int': safe_int,
163 'unicode': safe_str,
163 'unicode': safe_str,
164 'bool': str2bool,
164 'bool': str2bool,
165 'list': functools.partial(aslist, sep=',')
165 'list': functools.partial(aslist, sep=',')
166 }
166 }
167 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
167 DEFAULT_UPDATE_URL = 'https://rhodecode.com/api/v1/info/versions'
168
168
169 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
169 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
170 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
170 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
171 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
171 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
172 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
172 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
173
173
174 def __init__(self, key='', val='', type='unicode'):
174 def __init__(self, key='', val='', type='unicode'):
175 self.app_settings_name = key
175 self.app_settings_name = key
176 self.app_settings_value = val
176 self.app_settings_value = val
177 self.app_settings_type = type
177 self.app_settings_type = type
178
178
179 @validates('_app_settings_value')
179 @validates('_app_settings_value')
180 def validate_settings_value(self, key, val):
180 def validate_settings_value(self, key, val):
181 assert type(val) == str
181 assert type(val) == str
182 return val
182 return val
183
183
184 @hybrid_property
184 @hybrid_property
185 def app_settings_value(self):
185 def app_settings_value(self):
186 v = self._app_settings_value
186 v = self._app_settings_value
187 _type = self.app_settings_type
187 _type = self.app_settings_type
188 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
188 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
189 return converter(v)
189 return converter(v)
190
190
191 @app_settings_value.setter
191 @app_settings_value.setter
192 def app_settings_value(self, val):
192 def app_settings_value(self, val):
193 """
193 """
194 Setter that will always make sure we use unicode in app_settings_value
194 Setter that will always make sure we use unicode in app_settings_value
195
195
196 :param val:
196 :param val:
197 """
197 """
198 self._app_settings_value = safe_str(val)
198 self._app_settings_value = safe_str(val)
199
199
200 @hybrid_property
200 @hybrid_property
201 def app_settings_type(self):
201 def app_settings_type(self):
202 return self._app_settings_type
202 return self._app_settings_type
203
203
204 @app_settings_type.setter
204 @app_settings_type.setter
205 def app_settings_type(self, val):
205 def app_settings_type(self, val):
206 if val not in self.SETTINGS_TYPES:
206 if val not in self.SETTINGS_TYPES:
207 raise Exception('type must be one of %s got %s'
207 raise Exception('type must be one of %s got %s'
208 % (self.SETTINGS_TYPES.keys(), val))
208 % (self.SETTINGS_TYPES.keys(), val))
209 self._app_settings_type = val
209 self._app_settings_type = val
210
210
211 def __unicode__(self):
211 def __unicode__(self):
212 return u"<%s('%s:%s[%s]')>" % (
212 return u"<%s('%s:%s[%s]')>" % (
213 self.__class__.__name__,
213 self.__class__.__name__,
214 self.app_settings_name, self.app_settings_value, self.app_settings_type
214 self.app_settings_name, self.app_settings_value, self.app_settings_type
215 )
215 )
216
216
217
217
218 class RhodeCodeUi(Base, BaseModel):
218 class RhodeCodeUi(Base, BaseModel):
219 __tablename__ = 'rhodecode_ui'
219 __tablename__ = 'rhodecode_ui'
220 __table_args__ = (
220 __table_args__ = (
221 UniqueConstraint('ui_key'),
221 UniqueConstraint('ui_key'),
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
222 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
223 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
224 )
224 )
225
225
226 HOOK_REPO_SIZE = 'changegroup.repo_size'
226 HOOK_REPO_SIZE = 'changegroup.repo_size'
227 HOOK_PUSH = 'changegroup.push_logger'
227 HOOK_PUSH = 'changegroup.push_logger'
228 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
228 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
229 HOOK_PULL = 'outgoing.pull_logger'
229 HOOK_PULL = 'outgoing.pull_logger'
230 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
230 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
231
231
232 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
233 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
233 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
234 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
234 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
235 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
235 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
236 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
236 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
237
237
238 def __repr__(self):
238 def __repr__(self):
239 return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section,
239 return '<%s[%s]%s=>%s]>' % (self.__class__.__name__, self.ui_section,
240 self.ui_key, self.ui_value)
240 self.ui_key, self.ui_value)
241
241
242
242
243 class User(Base, BaseModel):
243 class User(Base, BaseModel):
244 __tablename__ = 'users'
244 __tablename__ = 'users'
245 __table_args__ = (
245 __table_args__ = (
246 UniqueConstraint('username'), UniqueConstraint('email'),
246 UniqueConstraint('username'), UniqueConstraint('email'),
247 Index('u_username_idx', 'username'),
247 Index('u_username_idx', 'username'),
248 Index('u_email_idx', 'email'),
248 Index('u_email_idx', 'email'),
249 {'extend_existing': True, 'mysql_engine': 'InnoDB',
249 {'extend_existing': True, 'mysql_engine': 'InnoDB',
250 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
250 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
251 )
251 )
252 DEFAULT_USER = 'default'
252 DEFAULT_USER = 'default'
253 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
253 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
254
254
255 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
255 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
256 username = Column("username", String(255), nullable=True, unique=None, default=None)
256 username = Column("username", String(255), nullable=True, unique=None, default=None)
257 password = Column("password", String(255), nullable=True, unique=None, default=None)
257 password = Column("password", String(255), nullable=True, unique=None, default=None)
258 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
258 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
259 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
259 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
260 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
260 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
261 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
261 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
262 _email = Column("email", String(255), nullable=True, unique=None, default=None)
262 _email = Column("email", String(255), nullable=True, unique=None, default=None)
263 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
263 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
264 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
264 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
265 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
265 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
266 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
266 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
267 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
267 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
268 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
268 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
269 _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data
269 _user_data = Column("user_data", LargeBinary(), nullable=True) # JSON data
270
270
271 user_log = relationship('UserLog')
271 user_log = relationship('UserLog')
272 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
272 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
273
273
274 repositories = relationship('Repository')
274 repositories = relationship('Repository')
275 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
275 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
276 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
276 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
277
277
278 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
278 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
279 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
279 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
280
280
281 group_member = relationship('UserGroupMember', cascade='all')
281 group_member = relationship('UserGroupMember', cascade='all')
282
282
283 notifications = relationship('UserNotification', cascade='all')
283 notifications = relationship('UserNotification', cascade='all')
284 # notifications assigned to this user
284 # notifications assigned to this user
285 user_created_notifications = relationship('Notification', cascade='all')
285 user_created_notifications = relationship('Notification', cascade='all')
286 # comments created by this user
286 # comments created by this user
287 user_comments = relationship('ChangesetComment', cascade='all')
287 user_comments = relationship('ChangesetComment', cascade='all')
288 user_emails = relationship('UserEmailMap', cascade='all')
288 user_emails = relationship('UserEmailMap', cascade='all')
289 user_auth_tokens = relationship('UserApiKeys', cascade='all')
289 user_auth_tokens = relationship('UserApiKeys', cascade='all')
290
290
291 @hybrid_property
291 @hybrid_property
292 def email(self):
292 def email(self):
293 return self._email
293 return self._email
294
294
295 @email.setter
295 @email.setter
296 def email(self, val):
296 def email(self, val):
297 self._email = val.lower() if val else None
297 self._email = val.lower() if val else None
298
298
299 @property
299 @property
300 def firstname(self):
300 def firstname(self):
301 # alias for future
301 # alias for future
302 return self.name
302 return self.name
303
303
304 @property
304 @property
305 def username_and_name(self):
305 def username_and_name(self):
306 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
306 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
307
307
308 @property
308 @property
309 def full_name(self):
309 def full_name(self):
310 return '%s %s' % (self.firstname, self.lastname)
310 return '%s %s' % (self.firstname, self.lastname)
311
311
312 @property
312 @property
313 def full_contact(self):
313 def full_contact(self):
314 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
314 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
315
315
316 @property
316 @property
317 def short_contact(self):
317 def short_contact(self):
318 return '%s %s' % (self.firstname, self.lastname)
318 return '%s %s' % (self.firstname, self.lastname)
319
319
320 @property
320 @property
321 def is_admin(self):
321 def is_admin(self):
322 return self.admin
322 return self.admin
323
323
324 @classmethod
324 @classmethod
325 def get_by_username(cls, username, case_insensitive=False, cache=False):
325 def get_by_username(cls, username, case_insensitive=False, cache=False):
326 if case_insensitive:
326 if case_insensitive:
327 q = cls.query().filter(cls.username.ilike(username))
327 q = cls.query().filter(cls.username.ilike(username))
328 else:
328 else:
329 q = cls.query().filter(cls.username == username)
329 q = cls.query().filter(cls.username == username)
330
330
331 if cache:
331 if cache:
332 q = q.options(FromCache(
332 q = q.options(FromCache(
333 "sql_cache_short",
333 "sql_cache_short",
334 "get_user_%s" % _hash_key(username)))
334 "get_user_%s" % _hash_key(username)))
335 return q.scalar()
335 return q.scalar()
336
336
337 @classmethod
337 @classmethod
338 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
338 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
339 q = cls.query().filter(cls.api_key == auth_token)
339 q = cls.query().filter(cls.api_key == auth_token)
340
340
341 if cache:
341 if cache:
342 q = q.options(FromCache("sql_cache_short",
342 q = q.options(FromCache("sql_cache_short",
343 "get_auth_token_%s" % auth_token))
343 "get_auth_token_%s" % auth_token))
344 res = q.scalar()
344 res = q.scalar()
345
345
346 if fallback and not res:
346 if fallback and not res:
347 #fallback to additional keys
347 #fallback to additional keys
348 _res = UserApiKeys.query()\
348 _res = UserApiKeys.query()\
349 .filter(UserApiKeys.api_key == auth_token)\
349 .filter(UserApiKeys.api_key == auth_token)\
350 .filter(or_(UserApiKeys.expires == -1,
350 .filter(or_(UserApiKeys.expires == -1,
351 UserApiKeys.expires >= time.time()))\
351 UserApiKeys.expires >= time.time()))\
352 .first()
352 .first()
353 if _res:
353 if _res:
354 res = _res.user
354 res = _res.user
355 return res
355 return res
356
356
357 @classmethod
357 @classmethod
358 def get_by_email(cls, email, case_insensitive=False, cache=False):
358 def get_by_email(cls, email, case_insensitive=False, cache=False):
359
359
360 if case_insensitive:
360 if case_insensitive:
361 q = cls.query().filter(cls.email.ilike(email))
361 q = cls.query().filter(cls.email.ilike(email))
362 else:
362 else:
363 q = cls.query().filter(cls.email == email)
363 q = cls.query().filter(cls.email == email)
364
364
365 if cache:
365 if cache:
366 q = q.options(FromCache("sql_cache_short",
366 q = q.options(FromCache("sql_cache_short",
367 "get_email_key_%s" % email))
367 "get_email_key_%s" % email))
368
368
369 ret = q.scalar()
369 ret = q.scalar()
370 if ret is None:
370 if ret is None:
371 q = UserEmailMap.query()
371 q = UserEmailMap.query()
372 # try fetching in alternate email map
372 # try fetching in alternate email map
373 if case_insensitive:
373 if case_insensitive:
374 q = q.filter(UserEmailMap.email.ilike(email))
374 q = q.filter(UserEmailMap.email.ilike(email))
375 else:
375 else:
376 q = q.filter(UserEmailMap.email == email)
376 q = q.filter(UserEmailMap.email == email)
377 q = q.options(joinedload(UserEmailMap.user))
377 q = q.options(joinedload(UserEmailMap.user))
378 if cache:
378 if cache:
379 q = q.options(FromCache("sql_cache_short",
379 q = q.options(FromCache("sql_cache_short",
380 "get_email_map_key_%s" % email))
380 "get_email_map_key_%s" % email))
381 ret = getattr(q.scalar(), 'user', None)
381 ret = getattr(q.scalar(), 'user', None)
382
382
383 return ret
383 return ret
384
384
385 @classmethod
385 @classmethod
386 def get_first_admin(cls):
386 def get_first_admin(cls):
387 user = User.query().filter(User.admin == True).first()
387 user = User.query().filter(User.admin == True).first()
388 if user is None:
388 if user is None:
389 raise Exception('Missing administrative account!')
389 raise Exception('Missing administrative account!')
390 return user
390 return user
391
391
392 @classmethod
392 @classmethod
393 def get_default_user(cls, cache=False):
393 def get_default_user(cls, cache=False):
394 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
394 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
395 if user is None:
395 if user is None:
396 raise Exception('Missing default account!')
396 raise Exception('Missing default account!')
397 return user
397 return user
398
398
399
399
400 class UserApiKeys(Base, BaseModel):
400 class UserApiKeys(Base, BaseModel):
401 __tablename__ = 'user_api_keys'
401 __tablename__ = 'user_api_keys'
402 __table_args__ = (
402 __table_args__ = (
403 Index('uak_api_key_idx', 'api_key'),
403 Index('uak_api_key_idx', 'api_key'),
404 Index('uak_api_key_expires_idx', 'api_key', 'expires'),
404 Index('uak_api_key_expires_idx', 'api_key', 'expires'),
405 UniqueConstraint('api_key'),
405 UniqueConstraint('api_key'),
406 {'extend_existing': True, 'mysql_engine': 'InnoDB',
406 {'extend_existing': True, 'mysql_engine': 'InnoDB',
407 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
407 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
408 )
408 )
409
409
410
410
411 # ApiKey role
411 # ApiKey role
412 ROLE_ALL = 'token_role_all'
412 ROLE_ALL = 'token_role_all'
413 ROLE_HTTP = 'token_role_http'
413 ROLE_HTTP = 'token_role_http'
414 ROLE_VCS = 'token_role_vcs'
414 ROLE_VCS = 'token_role_vcs'
415 ROLE_API = 'token_role_api'
415 ROLE_API = 'token_role_api'
416 ROLES = [ROLE_ALL, ROLE_HTTP, ROLE_VCS, ROLE_API]
416 ROLES = [ROLE_ALL, ROLE_HTTP, ROLE_VCS, ROLE_API]
417
417
418 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
418 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
419 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
419 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
420 api_key = Column("api_key", String(255), nullable=False, unique=True)
420 api_key = Column("api_key", String(255), nullable=False, unique=True)
421 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
421 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
422 expires = Column('expires', Float(53), nullable=False)
422 expires = Column('expires', Float(53), nullable=False)
423 role = Column('role', String(255), nullable=True)
423 role = Column('role', String(255), nullable=True)
424 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
424 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
425
425
426 user = relationship('User', lazy='joined')
426 user = relationship('User', lazy='joined')
427
427
428
428
429 class UserEmailMap(Base, BaseModel):
429 class UserEmailMap(Base, BaseModel):
430 __tablename__ = 'user_email_map'
430 __tablename__ = 'user_email_map'
431 __table_args__ = (
431 __table_args__ = (
432 Index('uem_email_idx', 'email'),
432 Index('uem_email_idx', 'email'),
433 UniqueConstraint('email'),
433 UniqueConstraint('email'),
434 {'extend_existing': True, 'mysql_engine': 'InnoDB',
434 {'extend_existing': True, 'mysql_engine': 'InnoDB',
435 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
435 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
436 )
436 )
437
437
438
438
439 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
439 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
440 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
440 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
441 _email = Column("email", String(255), nullable=True, unique=False, default=None)
441 _email = Column("email", String(255), nullable=True, unique=False, default=None)
442 user = relationship('User', lazy='joined')
442 user = relationship('User', lazy='joined')
443
443
444 @validates('_email')
444 @validates('_email')
445 def validate_email(self, key, email):
445 def validate_email(self, key, email):
446 # check if this email is not main one
446 # check if this email is not main one
447 main_email = Session().query(User).filter(User.email == email).scalar()
447 main_email = Session().query(User).filter(User.email == email).scalar()
448 if main_email is not None:
448 if main_email is not None:
449 raise AttributeError('email %s is present is user table' % email)
449 raise AttributeError('email %s is present is user table' % email)
450 return email
450 return email
451
451
452 @hybrid_property
452 @hybrid_property
453 def email(self):
453 def email(self):
454 return self._email
454 return self._email
455
455
456 @email.setter
456 @email.setter
457 def email(self, val):
457 def email(self, val):
458 self._email = val.lower() if val else None
458 self._email = val.lower() if val else None
459
459
460
460
461 class UserIpMap(Base, BaseModel):
461 class UserIpMap(Base, BaseModel):
462 __tablename__ = 'user_ip_map'
462 __tablename__ = 'user_ip_map'
463 __table_args__ = (
463 __table_args__ = (
464 UniqueConstraint('user_id', 'ip_addr'),
464 UniqueConstraint('user_id', 'ip_addr'),
465 {'extend_existing': True, 'mysql_engine': 'InnoDB',
465 {'extend_existing': True, 'mysql_engine': 'InnoDB',
466 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
466 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
467 )
467 )
468
468
469
469
470 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
470 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
471 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
471 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
472 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
472 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
473 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
473 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
474 user = relationship('User', lazy='joined')
474 user = relationship('User', lazy='joined')
475
475
476 def __unicode__(self):
476 def __unicode__(self):
477 return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__,
477 return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__,
478 self.user_id, self.ip_addr)
478 self.user_id, self.ip_addr)
479
479
480
480
481 class UserLog(Base, BaseModel):
481 class UserLog(Base, BaseModel):
482 __tablename__ = 'user_logs'
482 __tablename__ = 'user_logs'
483 __table_args__ = (
483 __table_args__ = (
484 {'extend_existing': True, 'mysql_engine': 'InnoDB',
484 {'extend_existing': True, 'mysql_engine': 'InnoDB',
485 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
485 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
486 )
486 )
487 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
487 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
488 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
488 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
489 username = Column("username", String(255), nullable=True, unique=None, default=None)
489 username = Column("username", String(255), nullable=True, unique=None, default=None)
490 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
490 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
491 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
491 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
492 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
492 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
493 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
493 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
494 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
494 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
495
495
496 def __unicode__(self):
496 def __unicode__(self):
497 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
497 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
498 self.repository_name,
498 self.repository_name,
499 self.action)
499 self.action)
500
500
501 user = relationship('User')
501 user = relationship('User')
502 repository = relationship('Repository', cascade='')
502 repository = relationship('Repository', cascade='')
503
503
504
504
505 class UserGroup(Base, BaseModel):
505 class UserGroup(Base, BaseModel):
506 __tablename__ = 'users_groups'
506 __tablename__ = 'users_groups'
507 __table_args__ = (
507 __table_args__ = (
508 {'extend_existing': True, 'mysql_engine': 'InnoDB',
508 {'extend_existing': True, 'mysql_engine': 'InnoDB',
509 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
509 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
510 )
510 )
511
511
512 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
512 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
513 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
513 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
514 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
514 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
515 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
515 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
516 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
516 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
517 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
517 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
518 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
518 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
519 _group_data = Column("group_data", LargeBinary(), nullable=True) # JSON data
519 _group_data = Column("group_data", LargeBinary(), nullable=True) # JSON data
520
520
521 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
521 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
522 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
522 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
523 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
523 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
524 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
524 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
525 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
525 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
526 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
526 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
527
527
528 user = relationship('User')
528 user = relationship('User')
529
529
530 def __unicode__(self):
530 def __unicode__(self):
531 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
531 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
532 self.users_group_id,
532 self.users_group_id,
533 self.users_group_name)
533 self.users_group_name)
534
534
535 @classmethod
535 @classmethod
536 def get_by_group_name(cls, group_name, cache=False,
536 def get_by_group_name(cls, group_name, cache=False,
537 case_insensitive=False):
537 case_insensitive=False):
538 if case_insensitive:
538 if case_insensitive:
539 q = cls.query().filter(cls.users_group_name.ilike(group_name))
539 q = cls.query().filter(cls.users_group_name.ilike(group_name))
540 else:
540 else:
541 q = cls.query().filter(cls.users_group_name == group_name)
541 q = cls.query().filter(cls.users_group_name == group_name)
542 if cache:
542 if cache:
543 q = q.options(FromCache(
543 q = q.options(FromCache(
544 "sql_cache_short",
544 "sql_cache_short",
545 "get_user_%s" % _hash_key(group_name)))
545 "get_user_%s" % _hash_key(group_name)))
546 return q.scalar()
546 return q.scalar()
547
547
548 @classmethod
548 @classmethod
549 def get(cls, user_group_id, cache=False):
549 def get(cls, user_group_id, cache=False):
550 user_group = cls.query()
550 user_group = cls.query()
551 if cache:
551 if cache:
552 user_group = user_group.options(FromCache("sql_cache_short",
552 user_group = user_group.options(FromCache("sql_cache_short",
553 "get_users_group_%s" % user_group_id))
553 "get_users_group_%s" % user_group_id))
554 return user_group.get(user_group_id)
554 return user_group.get(user_group_id)
555
555
556
556
557 class UserGroupMember(Base, BaseModel):
557 class UserGroupMember(Base, BaseModel):
558 __tablename__ = 'users_groups_members'
558 __tablename__ = 'users_groups_members'
559 __table_args__ = (
559 __table_args__ = (
560 {'extend_existing': True, 'mysql_engine': 'InnoDB',
560 {'extend_existing': True, 'mysql_engine': 'InnoDB',
561 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
561 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
562 )
562 )
563
563
564 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
564 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
565 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
565 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
566 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
566 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
567
567
568 user = relationship('User', lazy='joined')
568 user = relationship('User', lazy='joined')
569 users_group = relationship('UserGroup')
569 users_group = relationship('UserGroup')
570
570
571 def __init__(self, gr_id='', u_id=''):
571 def __init__(self, gr_id='', u_id=''):
572 self.users_group_id = gr_id
572 self.users_group_id = gr_id
573 self.user_id = u_id
573 self.user_id = u_id
574
574
575
575
576 class RepositoryField(Base, BaseModel):
576 class RepositoryField(Base, BaseModel):
577 __tablename__ = 'repositories_fields'
577 __tablename__ = 'repositories_fields'
578 __table_args__ = (
578 __table_args__ = (
579 UniqueConstraint('repository_id', 'field_key'), # no-multi field
579 UniqueConstraint('repository_id', 'field_key'), # no-multi field
580 {'extend_existing': True, 'mysql_engine': 'InnoDB',
580 {'extend_existing': True, 'mysql_engine': 'InnoDB',
581 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
581 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
582 )
582 )
583 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
583 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
584
584
585 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
585 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
586 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
586 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
587 field_key = Column("field_key", String(250))
587 field_key = Column("field_key", String(250))
588 field_label = Column("field_label", String(1024), nullable=False)
588 field_label = Column("field_label", String(1024), nullable=False)
589 field_value = Column("field_value", String(10000), nullable=False)
589 field_value = Column("field_value", String(10000), nullable=False)
590 field_desc = Column("field_desc", String(1024), nullable=False)
590 field_desc = Column("field_desc", String(1024), nullable=False)
591 field_type = Column("field_type", String(256), nullable=False, unique=None)
591 field_type = Column("field_type", String(256), nullable=False, unique=None)
592 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
592 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
593
593
594 repository = relationship('Repository')
594 repository = relationship('Repository')
595
595
596 @classmethod
596 @classmethod
597 def get_by_key_name(cls, key, repo):
597 def get_by_key_name(cls, key, repo):
598 row = cls.query()\
598 row = cls.query()\
599 .filter(cls.repository == repo)\
599 .filter(cls.repository == repo)\
600 .filter(cls.field_key == key).scalar()
600 .filter(cls.field_key == key).scalar()
601 return row
601 return row
602
602
603
603
604 class Repository(Base, BaseModel):
604 class Repository(Base, BaseModel):
605 __tablename__ = 'repositories'
605 __tablename__ = 'repositories'
606 __table_args__ = (
606 __table_args__ = (
607 UniqueConstraint('repo_name'),
607 UniqueConstraint('repo_name'),
608 Index('r_repo_name_idx', 'repo_name'),
608 Index('r_repo_name_idx', 'repo_name'),
609 {'extend_existing': True, 'mysql_engine': 'InnoDB',
609 {'extend_existing': True, 'mysql_engine': 'InnoDB',
610 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
610 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
611 )
611 )
612 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
612 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
613 DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
613 DEFAULT_CLONE_URI_ID = '{scheme}://{user}@{netloc}/_{repoid}'
614
614
615 STATE_CREATED = 'repo_state_created'
615 STATE_CREATED = 'repo_state_created'
616 STATE_PENDING = 'repo_state_pending'
616 STATE_PENDING = 'repo_state_pending'
617 STATE_ERROR = 'repo_state_error'
617 STATE_ERROR = 'repo_state_error'
618
618
619 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
619 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
620 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
620 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
621 repo_state = Column("repo_state", String(255), nullable=True)
621 repo_state = Column("repo_state", String(255), nullable=True)
622
622
623 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
623 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
624 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
624 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
625 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
625 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
626 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
626 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
627 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
627 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
628 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
628 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
629 description = Column("description", String(10000), nullable=True, unique=None, default=None)
629 description = Column("description", String(10000), nullable=True, unique=None, default=None)
630 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
630 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
631 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
631 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
632 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
632 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
633 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
633 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
634 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
634 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
635 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
635 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
636
636
637 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
637 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
638 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
638 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
639
639
640 user = relationship('User')
640 user = relationship('User')
641 fork = relationship('Repository', remote_side=repo_id)
641 fork = relationship('Repository', remote_side=repo_id)
642 group = relationship('RepoGroup')
642 group = relationship('RepoGroup')
643 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
643 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
644 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
644 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
645 stats = relationship('Statistics', cascade='all', uselist=False)
645 stats = relationship('Statistics', cascade='all', uselist=False)
646
646
647 followers = relationship('UserFollowing',
647 followers = relationship('UserFollowing',
648 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
648 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
649 cascade='all')
649 cascade='all')
650 extra_fields = relationship('RepositoryField',
650 extra_fields = relationship('RepositoryField',
651 cascade="all, delete, delete-orphan")
651 cascade="all, delete, delete-orphan")
652
652
653 logs = relationship('UserLog')
653 logs = relationship('UserLog')
654 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
654 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
655
655
656 pull_requests_org = relationship('PullRequest',
656 pull_requests_org = relationship('PullRequest',
657 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
657 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
658 cascade="all, delete, delete-orphan")
658 cascade="all, delete, delete-orphan")
659
659
660 pull_requests_other = relationship('PullRequest',
660 pull_requests_other = relationship('PullRequest',
661 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
661 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
662 cascade="all, delete, delete-orphan")
662 cascade="all, delete, delete-orphan")
663
663
664 def __unicode__(self):
664 def __unicode__(self):
665 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
665 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
666 safe_str(self.repo_name))
666 safe_str(self.repo_name))
667
667
668 @classmethod
668 @classmethod
669 def get_by_repo_name(cls, repo_name):
669 def get_by_repo_name(cls, repo_name):
670 q = Session().query(cls).filter(cls.repo_name == repo_name)
670 q = Session().query(cls).filter(cls.repo_name == repo_name)
671 q = q.options(joinedload(Repository.fork))\
671 q = q.options(joinedload(Repository.fork))\
672 .options(joinedload(Repository.user))\
672 .options(joinedload(Repository.user))\
673 .options(joinedload(Repository.group))
673 .options(joinedload(Repository.group))
674 return q.scalar()
674 return q.scalar()
675
675
676
676
677 class RepoGroup(Base, BaseModel):
677 class RepoGroup(Base, BaseModel):
678 __tablename__ = 'groups'
678 __tablename__ = 'groups'
679 __table_args__ = (
679 __table_args__ = (
680 UniqueConstraint('group_name', 'group_parent_id'),
680 UniqueConstraint('group_name', 'group_parent_id'),
681 {'extend_existing': True, 'mysql_engine': 'InnoDB',
681 {'extend_existing': True, 'mysql_engine': 'InnoDB',
682 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
682 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
683 )
683 )
684
684
685
685
686 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
686 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
687 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
687 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
688 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
688 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
689 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
689 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
690 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
690 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
691 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
691 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
692 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
692 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
693
693
694 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
694 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
695 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
695 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
696 parent_group = relationship('RepoGroup', remote_side=group_id)
696 parent_group = relationship('RepoGroup', remote_side=group_id)
697 user = relationship('User')
697 user = relationship('User')
698
698
699 def __init__(self, group_name='', parent_group=None):
699 def __init__(self, group_name='', parent_group=None):
700 self.group_name = group_name
700 self.group_name = group_name
701 self.parent_group = parent_group
701 self.parent_group = parent_group
702
702
703 def __unicode__(self):
703 def __unicode__(self):
704 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
704 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
705 self.group_name)
705 self.group_name)
706
706
707 @classmethod
707 @classmethod
708 def url_sep(cls):
708 def url_sep(cls):
709 return URL_SEP
709 return URL_SEP
710
710
711 @classmethod
711 @classmethod
712 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
712 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
713 if case_insensitive:
713 if case_insensitive:
714 gr = cls.query()\
714 gr = cls.query()\
715 .filter(cls.group_name.ilike(group_name))
715 .filter(cls.group_name.ilike(group_name))
716 else:
716 else:
717 gr = cls.query()\
717 gr = cls.query()\
718 .filter(cls.group_name == group_name)
718 .filter(cls.group_name == group_name)
719 if cache:
719 if cache:
720 gr = gr.options(FromCache(
720 gr = gr.options(FromCache(
721 "sql_cache_short",
721 "sql_cache_short",
722 "get_group_%s" % _hash_key(group_name)))
722 "get_group_%s" % _hash_key(group_name)))
723 return gr.scalar()
723 return gr.scalar()
724
724
725
725
726 class Permission(Base, BaseModel):
726 class Permission(Base, BaseModel):
727 __tablename__ = 'permissions'
727 __tablename__ = 'permissions'
728 __table_args__ = (
728 __table_args__ = (
729 Index('p_perm_name_idx', 'permission_name'),
729 Index('p_perm_name_idx', 'permission_name'),
730 {'extend_existing': True, 'mysql_engine': 'InnoDB',
730 {'extend_existing': True, 'mysql_engine': 'InnoDB',
731 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
731 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
732 )
732 )
733 PERMS = [
733 PERMS = [
734 ('hg.admin', _('RhodeCode Administrator')),
734 ('hg.admin', _('RhodeCode Administrator')),
735
735
736 ('repository.none', _('Repository no access')),
736 ('repository.none', _('Repository no access')),
737 ('repository.read', _('Repository read access')),
737 ('repository.read', _('Repository read access')),
738 ('repository.write', _('Repository write access')),
738 ('repository.write', _('Repository write access')),
739 ('repository.admin', _('Repository admin access')),
739 ('repository.admin', _('Repository admin access')),
740
740
741 ('group.none', _('Repository group no access')),
741 ('group.none', _('Repository group no access')),
742 ('group.read', _('Repository group read access')),
742 ('group.read', _('Repository group read access')),
743 ('group.write', _('Repository group write access')),
743 ('group.write', _('Repository group write access')),
744 ('group.admin', _('Repository group admin access')),
744 ('group.admin', _('Repository group admin access')),
745
745
746 ('usergroup.none', _('User group no access')),
746 ('usergroup.none', _('User group no access')),
747 ('usergroup.read', _('User group read access')),
747 ('usergroup.read', _('User group read access')),
748 ('usergroup.write', _('User group write access')),
748 ('usergroup.write', _('User group write access')),
749 ('usergroup.admin', _('User group admin access')),
749 ('usergroup.admin', _('User group admin access')),
750
750
751 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
751 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
752 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
752 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
753
753
754 ('hg.usergroup.create.false', _('User Group creation disabled')),
754 ('hg.usergroup.create.false', _('User Group creation disabled')),
755 ('hg.usergroup.create.true', _('User Group creation enabled')),
755 ('hg.usergroup.create.true', _('User Group creation enabled')),
756
756
757 ('hg.create.none', _('Repository creation disabled')),
757 ('hg.create.none', _('Repository creation disabled')),
758 ('hg.create.repository', _('Repository creation enabled')),
758 ('hg.create.repository', _('Repository creation enabled')),
759 ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')),
759 ('hg.create.write_on_repogroup.true', _('Repository creation enabled with write permission to a repository group')),
760 ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')),
760 ('hg.create.write_on_repogroup.false', _('Repository creation disabled with write permission to a repository group')),
761
761
762 ('hg.fork.none', _('Repository forking disabled')),
762 ('hg.fork.none', _('Repository forking disabled')),
763 ('hg.fork.repository', _('Repository forking enabled')),
763 ('hg.fork.repository', _('Repository forking enabled')),
764
764
765 ('hg.register.none', _('Registration disabled')),
765 ('hg.register.none', _('Registration disabled')),
766 ('hg.register.manual_activate', _('User Registration with manual account activation')),
766 ('hg.register.manual_activate', _('User Registration with manual account activation')),
767 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
767 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
768
768
769 ('hg.extern_activate.manual', _('Manual activation of external account')),
769 ('hg.extern_activate.manual', _('Manual activation of external account')),
770 ('hg.extern_activate.auto', _('Automatic activation of external account')),
770 ('hg.extern_activate.auto', _('Automatic activation of external account')),
771
771
772 ]
772 ]
773
773
774 #definition of system default permissions for DEFAULT user
774 #definition of system default permissions for DEFAULT user
775 DEFAULT_USER_PERMISSIONS = [
775 DEFAULT_USER_PERMISSIONS = [
776 'repository.read',
776 'repository.read',
777 'group.read',
777 'group.read',
778 'usergroup.read',
778 'usergroup.read',
779 'hg.create.repository',
779 'hg.create.repository',
780 'hg.create.write_on_repogroup.true',
780 'hg.create.write_on_repogroup.true',
781 'hg.fork.repository',
781 'hg.fork.repository',
782 'hg.register.manual_activate',
782 'hg.register.manual_activate',
783 'hg.extern_activate.auto',
783 'hg.extern_activate.auto',
784 ]
784 ]
785
785
786 # defines which permissions are more important higher the more important
786 # defines which permissions are more important higher the more important
787 # Weight defines which permissions are more important.
787 # Weight defines which permissions are more important.
788 # The higher number the more important.
788 # The higher number the more important.
789 PERM_WEIGHTS = {
789 PERM_WEIGHTS = {
790 'repository.none': 0,
790 'repository.none': 0,
791 'repository.read': 1,
791 'repository.read': 1,
792 'repository.write': 3,
792 'repository.write': 3,
793 'repository.admin': 4,
793 'repository.admin': 4,
794
794
795 'group.none': 0,
795 'group.none': 0,
796 'group.read': 1,
796 'group.read': 1,
797 'group.write': 3,
797 'group.write': 3,
798 'group.admin': 4,
798 'group.admin': 4,
799
799
800 'usergroup.none': 0,
800 'usergroup.none': 0,
801 'usergroup.read': 1,
801 'usergroup.read': 1,
802 'usergroup.write': 3,
802 'usergroup.write': 3,
803 'usergroup.admin': 4,
803 'usergroup.admin': 4,
804 'hg.repogroup.create.false': 0,
804 'hg.repogroup.create.false': 0,
805 'hg.repogroup.create.true': 1,
805 'hg.repogroup.create.true': 1,
806
806
807 'hg.usergroup.create.false': 0,
807 'hg.usergroup.create.false': 0,
808 'hg.usergroup.create.true': 1,
808 'hg.usergroup.create.true': 1,
809
809
810 'hg.fork.none': 0,
810 'hg.fork.none': 0,
811 'hg.fork.repository': 1,
811 'hg.fork.repository': 1,
812 'hg.create.none': 0,
812 'hg.create.none': 0,
813 'hg.create.repository': 1
813 'hg.create.repository': 1
814 }
814 }
815
815
816 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
816 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
817 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
817 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
818 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
818 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
819
819
820 def __unicode__(self):
820 def __unicode__(self):
821 return u"<%s('%s:%s')>" % (
821 return u"<%s('%s:%s')>" % (
822 self.__class__.__name__, self.permission_id, self.permission_name
822 self.__class__.__name__, self.permission_id, self.permission_name
823 )
823 )
824
824
825 @classmethod
825 @classmethod
826 def get_by_key(cls, key):
826 def get_by_key(cls, key):
827 return cls.query().filter(cls.permission_name == key).scalar()
827 return cls.query().filter(cls.permission_name == key).scalar()
828
828
829
829
830 class UserRepoToPerm(Base, BaseModel):
830 class UserRepoToPerm(Base, BaseModel):
831 __tablename__ = 'repo_to_perm'
831 __tablename__ = 'repo_to_perm'
832 __table_args__ = (
832 __table_args__ = (
833 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
833 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
834 {'extend_existing': True, 'mysql_engine': 'InnoDB',
834 {'extend_existing': True, 'mysql_engine': 'InnoDB',
835 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
835 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
836 )
836 )
837 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
837 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
838 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
838 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
839 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
839 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
840 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
840 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
841
841
842 user = relationship('User')
842 user = relationship('User')
843 repository = relationship('Repository')
843 repository = relationship('Repository')
844 permission = relationship('Permission')
844 permission = relationship('Permission')
845
845
846 def __unicode__(self):
846 def __unicode__(self):
847 return u'<%s => %s >' % (self.user, self.repository)
847 return u'<%s => %s >' % (self.user, self.repository)
848
848
849
849
850 class UserUserGroupToPerm(Base, BaseModel):
850 class UserUserGroupToPerm(Base, BaseModel):
851 __tablename__ = 'user_user_group_to_perm'
851 __tablename__ = 'user_user_group_to_perm'
852 __table_args__ = (
852 __table_args__ = (
853 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
853 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
854 {'extend_existing': True, 'mysql_engine': 'InnoDB',
854 {'extend_existing': True, 'mysql_engine': 'InnoDB',
855 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
855 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
856 )
856 )
857 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
857 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
858 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
858 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
859 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
859 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
860 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
860 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
861
861
862 user = relationship('User')
862 user = relationship('User')
863 user_group = relationship('UserGroup')
863 user_group = relationship('UserGroup')
864 permission = relationship('Permission')
864 permission = relationship('Permission')
865
865
866 def __unicode__(self):
866 def __unicode__(self):
867 return u'<%s => %s >' % (self.user, self.user_group)
867 return u'<%s => %s >' % (self.user, self.user_group)
868
868
869
869
870 class UserToPerm(Base, BaseModel):
870 class UserToPerm(Base, BaseModel):
871 __tablename__ = 'user_to_perm'
871 __tablename__ = 'user_to_perm'
872 __table_args__ = (
872 __table_args__ = (
873 UniqueConstraint('user_id', 'permission_id'),
873 UniqueConstraint('user_id', 'permission_id'),
874 {'extend_existing': True, 'mysql_engine': 'InnoDB',
874 {'extend_existing': True, 'mysql_engine': 'InnoDB',
875 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
875 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
876 )
876 )
877 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
877 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
878 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
878 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
879 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
879 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
880
880
881 user = relationship('User')
881 user = relationship('User')
882 permission = relationship('Permission', lazy='joined')
882 permission = relationship('Permission', lazy='joined')
883
883
884 def __unicode__(self):
884 def __unicode__(self):
885 return u'<%s => %s >' % (self.user, self.permission)
885 return u'<%s => %s >' % (self.user, self.permission)
886
886
887
887
888 class UserGroupRepoToPerm(Base, BaseModel):
888 class UserGroupRepoToPerm(Base, BaseModel):
889 __tablename__ = 'users_group_repo_to_perm'
889 __tablename__ = 'users_group_repo_to_perm'
890 __table_args__ = (
890 __table_args__ = (
891 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
891 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
892 {'extend_existing': True, 'mysql_engine': 'InnoDB',
892 {'extend_existing': True, 'mysql_engine': 'InnoDB',
893 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
893 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
894 )
894 )
895 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
895 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
896 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
896 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
897 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
898 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
898 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
899
899
900 users_group = relationship('UserGroup')
900 users_group = relationship('UserGroup')
901 permission = relationship('Permission')
901 permission = relationship('Permission')
902 repository = relationship('Repository')
902 repository = relationship('Repository')
903
903
904 def __unicode__(self):
904 def __unicode__(self):
905 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
905 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
906
906
907
907
908 class UserGroupUserGroupToPerm(Base, BaseModel):
908 class UserGroupUserGroupToPerm(Base, BaseModel):
909 __tablename__ = 'user_group_user_group_to_perm'
909 __tablename__ = 'user_group_user_group_to_perm'
910 __table_args__ = (
910 __table_args__ = (
911 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
911 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
912 CheckConstraint('target_user_group_id != user_group_id'),
912 CheckConstraint('target_user_group_id != user_group_id'),
913 {'extend_existing': True, 'mysql_engine': 'InnoDB',
913 {'extend_existing': True, 'mysql_engine': 'InnoDB',
914 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
914 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
915 )
915 )
916 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
916 user_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
917 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
917 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
918 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
918 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
919 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
919 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
920
920
921 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
921 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
922 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
922 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
923 permission = relationship('Permission')
923 permission = relationship('Permission')
924
924
925 def __unicode__(self):
925 def __unicode__(self):
926 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
926 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
927
927
928
928
929 class UserGroupToPerm(Base, BaseModel):
929 class UserGroupToPerm(Base, BaseModel):
930 __tablename__ = 'users_group_to_perm'
930 __tablename__ = 'users_group_to_perm'
931 __table_args__ = (
931 __table_args__ = (
932 UniqueConstraint('users_group_id', 'permission_id',),
932 UniqueConstraint('users_group_id', 'permission_id',),
933 {'extend_existing': True, 'mysql_engine': 'InnoDB',
933 {'extend_existing': True, 'mysql_engine': 'InnoDB',
934 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
934 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
935 )
935 )
936 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
936 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
937 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
937 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
938 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
938 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
939
939
940 users_group = relationship('UserGroup')
940 users_group = relationship('UserGroup')
941 permission = relationship('Permission')
941 permission = relationship('Permission')
942
942
943
943
944 class UserRepoGroupToPerm(Base, BaseModel):
944 class UserRepoGroupToPerm(Base, BaseModel):
945 __tablename__ = 'user_repo_group_to_perm'
945 __tablename__ = 'user_repo_group_to_perm'
946 __table_args__ = (
946 __table_args__ = (
947 UniqueConstraint('user_id', 'group_id', 'permission_id'),
947 UniqueConstraint('user_id', 'group_id', 'permission_id'),
948 {'extend_existing': True, 'mysql_engine': 'InnoDB',
948 {'extend_existing': True, 'mysql_engine': 'InnoDB',
949 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
949 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
950 )
950 )
951
951
952 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
952 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
953 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
953 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
954 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
954 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
955 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
955 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
956
956
957 user = relationship('User')
957 user = relationship('User')
958 group = relationship('RepoGroup')
958 group = relationship('RepoGroup')
959 permission = relationship('Permission')
959 permission = relationship('Permission')
960
960
961
961
962 class UserGroupRepoGroupToPerm(Base, BaseModel):
962 class UserGroupRepoGroupToPerm(Base, BaseModel):
963 __tablename__ = 'users_group_repo_group_to_perm'
963 __tablename__ = 'users_group_repo_group_to_perm'
964 __table_args__ = (
964 __table_args__ = (
965 UniqueConstraint('users_group_id', 'group_id'),
965 UniqueConstraint('users_group_id', 'group_id'),
966 {'extend_existing': True, 'mysql_engine': 'InnoDB',
966 {'extend_existing': True, 'mysql_engine': 'InnoDB',
967 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
967 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
968 )
968 )
969
969
970 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)
970 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)
971 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
971 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
972 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
972 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
973 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)
974
974
975 users_group = relationship('UserGroup')
975 users_group = relationship('UserGroup')
976 permission = relationship('Permission')
976 permission = relationship('Permission')
977 group = relationship('RepoGroup')
977 group = relationship('RepoGroup')
978
978
979 @classmethod
979 @classmethod
980 def create(cls, user_group, repository_group, permission):
980 def create(cls, user_group, repository_group, permission):
981 n = cls()
981 n = cls()
982 n.users_group = user_group
982 n.users_group = user_group
983 n.group = repository_group
983 n.group = repository_group
984 n.permission = permission
984 n.permission = permission
985 Session().add(n)
985 Session().add(n)
986 return n
986 return n
987
987
988
988
989 class Statistics(Base, BaseModel):
989 class Statistics(Base, BaseModel):
990 __tablename__ = 'statistics'
990 __tablename__ = 'statistics'
991 __table_args__ = (
991 __table_args__ = (
992 UniqueConstraint('repository_id'),
992 UniqueConstraint('repository_id'),
993 {'extend_existing': True, 'mysql_engine': 'InnoDB',
993 {'extend_existing': True, 'mysql_engine': 'InnoDB',
994 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
994 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
995 )
995 )
996 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)
997 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)
998 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
998 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
999 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
999 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1000 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
1001 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1001 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1002
1002
1003 repository = relationship('Repository', single_parent=True)
1003 repository = relationship('Repository', single_parent=True)
1004
1004
1005
1005
1006 class UserFollowing(Base, BaseModel):
1006 class UserFollowing(Base, BaseModel):
1007 __tablename__ = 'user_followings'
1007 __tablename__ = 'user_followings'
1008 __table_args__ = (
1008 __table_args__ = (
1009 UniqueConstraint('user_id', 'follows_repository_id'),
1009 UniqueConstraint('user_id', 'follows_repository_id'),
1010 UniqueConstraint('user_id', 'follows_user_id'),
1010 UniqueConstraint('user_id', 'follows_user_id'),
1011 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1011 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1012 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1012 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1013 )
1013 )
1014
1014
1015 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1015 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1016 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1016 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1017 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1017 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1018 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1018 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1019 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1019 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1020
1020
1021 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1021 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1022
1022
1023 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1023 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1024 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1024 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1025
1025
1026
1026
1027 class CacheInvalidation(Base, BaseModel):
1027 class CacheInvalidation(Base, BaseModel):
1028 __tablename__ = 'cache_invalidation'
1028 __tablename__ = 'cache_invalidation'
1029 __table_args__ = (
1029 __table_args__ = (
1030 UniqueConstraint('cache_key'),
1030 UniqueConstraint('cache_key'),
1031 Index('key_idx', 'cache_key'),
1031 Index('key_idx', 'cache_key'),
1032 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1032 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1033 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1033 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1034 )
1034 )
1035 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1035 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1036 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1036 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1037 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1037 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1038 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1038 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1039
1039
1040 def __init__(self, cache_key, cache_args=''):
1040 def __init__(self, cache_key, cache_args=''):
1041 self.cache_key = cache_key
1041 self.cache_key = cache_key
1042 self.cache_args = cache_args
1042 self.cache_args = cache_args
1043 self.cache_active = False
1043 self.cache_active = False
1044
1044
1045
1045
1046 class ChangesetComment(Base, BaseModel):
1046 class ChangesetComment(Base, BaseModel):
1047 __tablename__ = 'changeset_comments'
1047 __tablename__ = 'changeset_comments'
1048 __table_args__ = (
1048 __table_args__ = (
1049 Index('cc_revision_idx', 'revision'),
1049 Index('cc_revision_idx', 'revision'),
1050 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1050 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1051 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1051 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1052 )
1052 )
1053 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1053 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1054 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1054 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1055 revision = Column('revision', String(40), nullable=True)
1055 revision = Column('revision', String(40), nullable=True)
1056 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1056 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1057 line_no = Column('line_no', Unicode(10), nullable=True)
1057 line_no = Column('line_no', Unicode(10), nullable=True)
1058 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1058 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1059 f_path = Column('f_path', Unicode(1000), nullable=True)
1059 f_path = Column('f_path', Unicode(1000), nullable=True)
1060 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1060 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1061 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1061 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1062 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1062 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1063 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1063 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1064
1064
1065 author = relationship('User', lazy='joined')
1065 author = relationship('User', lazy='joined')
1066 repo = relationship('Repository')
1066 repo = relationship('Repository')
1067 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1067 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1068 pull_request = relationship('PullRequest', lazy='joined')
1068 pull_request = relationship('PullRequest', lazy='joined')
1069
1069
1070
1070
1071 class ChangesetStatus(Base, BaseModel):
1071 class ChangesetStatus(Base, BaseModel):
1072 __tablename__ = 'changeset_statuses'
1072 __tablename__ = 'changeset_statuses'
1073 __table_args__ = (
1073 __table_args__ = (
1074 Index('cs_revision_idx', 'revision'),
1074 Index('cs_revision_idx', 'revision'),
1075 Index('cs_version_idx', 'version'),
1075 Index('cs_version_idx', 'version'),
1076 UniqueConstraint('repo_id', 'revision', 'version'),
1076 UniqueConstraint('repo_id', 'revision', 'version'),
1077 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1077 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1078 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1078 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1079 )
1079 )
1080 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1080 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1081 STATUS_APPROVED = 'approved'
1081 STATUS_APPROVED = 'approved'
1082 STATUS_REJECTED = 'rejected'
1082 STATUS_REJECTED = 'rejected'
1083 STATUS_UNDER_REVIEW = 'under_review'
1083 STATUS_UNDER_REVIEW = 'under_review'
1084
1084
1085 STATUSES = [
1085 STATUSES = [
1086 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1086 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1087 (STATUS_APPROVED, _("Approved")),
1087 (STATUS_APPROVED, _("Approved")),
1088 (STATUS_REJECTED, _("Rejected")),
1088 (STATUS_REJECTED, _("Rejected")),
1089 (STATUS_UNDER_REVIEW, _("Under Review")),
1089 (STATUS_UNDER_REVIEW, _("Under Review")),
1090 ]
1090 ]
1091
1091
1092 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1092 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1093 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1093 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1094 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1094 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1095 revision = Column('revision', String(40), nullable=False)
1095 revision = Column('revision', String(40), nullable=False)
1096 status = Column('status', String(128), nullable=False, default=DEFAULT)
1096 status = Column('status', String(128), nullable=False, default=DEFAULT)
1097 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1097 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1098 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1098 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1099 version = Column('version', Integer(), nullable=False, default=0)
1099 version = Column('version', Integer(), nullable=False, default=0)
1100 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1100 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1101
1101
1102 author = relationship('User', lazy='joined')
1102 author = relationship('User', lazy='joined')
1103 repo = relationship('Repository')
1103 repo = relationship('Repository')
1104 comment = relationship('ChangesetComment', lazy='joined')
1104 comment = relationship('ChangesetComment', lazy='joined')
1105 pull_request = relationship('PullRequest', lazy='joined')
1105 pull_request = relationship('PullRequest', lazy='joined')
1106
1106
1107
1107
1108
1108
1109 class PullRequest(Base, BaseModel):
1109 class PullRequest(Base, BaseModel):
1110 __tablename__ = 'pull_requests'
1110 __tablename__ = 'pull_requests'
1111 __table_args__ = (
1111 __table_args__ = (
1112 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1112 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1113 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1113 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1114 )
1114 )
1115
1115
1116 STATUS_NEW = u'new'
1116 STATUS_NEW = u'new'
1117 STATUS_OPEN = u'open'
1117 STATUS_OPEN = u'open'
1118 STATUS_CLOSED = u'closed'
1118 STATUS_CLOSED = u'closed'
1119
1119
1120 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1120 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1121 title = Column('title', Unicode(256), nullable=True)
1121 title = Column('title', Unicode(256), nullable=True)
1122 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1122 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1123 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1123 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1124 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1124 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1125 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1125 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1126 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1126 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1127 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1127 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1128 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1128 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1129 org_ref = Column('org_ref', Unicode(256), nullable=False)
1129 org_ref = Column('org_ref', Unicode(256), nullable=False)
1130 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1130 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1131 other_ref = Column('other_ref', Unicode(256), nullable=False)
1131 other_ref = Column('other_ref', Unicode(256), nullable=False)
1132
1132
1133 author = relationship('User', lazy='joined')
1133 author = relationship('User', lazy='joined')
1134 reviewers = relationship('PullRequestReviewers',
1134 reviewers = relationship('PullRequestReviewers',
1135 cascade="all, delete, delete-orphan")
1135 cascade="all, delete, delete-orphan")
1136 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1136 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1137 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1137 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1138 statuses = relationship('ChangesetStatus')
1138 statuses = relationship('ChangesetStatus')
1139 comments = relationship('ChangesetComment',
1139 comments = relationship('ChangesetComment',
1140 cascade="all, delete, delete-orphan")
1140 cascade="all, delete, delete-orphan")
1141
1141
1142
1142
1143 class PullRequestReviewers(Base, BaseModel):
1143 class PullRequestReviewers(Base, BaseModel):
1144 __tablename__ = 'pull_request_reviewers'
1144 __tablename__ = 'pull_request_reviewers'
1145 __table_args__ = (
1145 __table_args__ = (
1146 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1146 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1147 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1147 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1148 )
1148 )
1149
1149
1150 def __init__(self, user=None, pull_request=None):
1150 def __init__(self, user=None, pull_request=None):
1151 self.user = user
1151 self.user = user
1152 self.pull_request = pull_request
1152 self.pull_request = pull_request
1153
1153
1154 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1154 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1155 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1155 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1156 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1156 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1157
1157
1158 user = relationship('User')
1158 user = relationship('User')
1159 pull_request = relationship('PullRequest')
1159 pull_request = relationship('PullRequest')
1160
1160
1161
1161
1162 class Notification(Base, BaseModel):
1162 class Notification(Base, BaseModel):
1163 __tablename__ = 'notifications'
1163 __tablename__ = 'notifications'
1164 __table_args__ = (
1164 __table_args__ = (
1165 Index('notification_type_idx', 'type'),
1165 Index('notification_type_idx', 'type'),
1166 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1166 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1167 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1167 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1168 )
1168 )
1169
1169
1170 TYPE_CHANGESET_COMMENT = u'cs_comment'
1170 TYPE_CHANGESET_COMMENT = u'cs_comment'
1171 TYPE_MESSAGE = u'message'
1171 TYPE_MESSAGE = u'message'
1172 TYPE_MENTION = u'mention'
1172 TYPE_MENTION = u'mention'
1173 TYPE_REGISTRATION = u'registration'
1173 TYPE_REGISTRATION = u'registration'
1174 TYPE_PULL_REQUEST = u'pull_request'
1174 TYPE_PULL_REQUEST = u'pull_request'
1175 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1175 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1176
1176
1177 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1177 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1178 subject = Column('subject', Unicode(512), nullable=True)
1178 subject = Column('subject', Unicode(512), nullable=True)
1179 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1179 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1180 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1180 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1181 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1181 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1182 type_ = Column('type', Unicode(256))
1182 type_ = Column('type', Unicode(256))
1183
1183
1184 created_by_user = relationship('User')
1184 created_by_user = relationship('User')
1185 notifications_to_users = relationship('UserNotification', lazy='joined',
1185 notifications_to_users = relationship('UserNotification', lazy='joined',
1186 cascade="all, delete, delete-orphan")
1186 cascade="all, delete, delete-orphan")
1187
1187
1188
1188
1189 class UserNotification(Base, BaseModel):
1189 class UserNotification(Base, BaseModel):
1190 __tablename__ = 'user_to_notification'
1190 __tablename__ = 'user_to_notification'
1191 __table_args__ = (
1191 __table_args__ = (
1192 UniqueConstraint('user_id', 'notification_id'),
1192 UniqueConstraint('user_id', 'notification_id'),
1193 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1193 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1194 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1194 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1195 )
1195 )
1196 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1196 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1197 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1197 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1198 read = Column('read', Boolean, default=False)
1198 read = Column('read', Boolean, default=False)
1199 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1199 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1200
1200
1201 user = relationship('User', lazy="joined")
1201 user = relationship('User', lazy="joined")
1202 notification = relationship('Notification', lazy="joined",
1202 notification = relationship('Notification', lazy="joined",
1203 order_by=lambda: Notification.created_on.desc(),)
1203 order_by=lambda: Notification.created_on.desc(),)
1204
1204
1205
1205
1206 class Gist(Base, BaseModel):
1206 class Gist(Base, BaseModel):
1207 __tablename__ = 'gists'
1207 __tablename__ = 'gists'
1208 __table_args__ = (
1208 __table_args__ = (
1209 Index('g_gist_access_id_idx', 'gist_access_id'),
1209 Index('g_gist_access_id_idx', 'gist_access_id'),
1210 Index('g_created_on_idx', 'created_on'),
1210 Index('g_created_on_idx', 'created_on'),
1211 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1211 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1212 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1212 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1213 )
1213 )
1214 GIST_PUBLIC = u'public'
1214 GIST_PUBLIC = u'public'
1215 GIST_PRIVATE = u'private'
1215 GIST_PRIVATE = u'private'
1216 DEFAULT_FILENAME = u'gistfile1.txt'
1216 DEFAULT_FILENAME = u'gistfile1.txt'
1217
1217
1218 gist_id = Column('gist_id', Integer(), primary_key=True)
1218 gist_id = Column('gist_id', Integer(), primary_key=True)
1219 gist_access_id = Column('gist_access_id', Unicode(250))
1219 gist_access_id = Column('gist_access_id', Unicode(250))
1220 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1220 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1221 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1221 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1222 gist_expires = Column('gist_expires', Float(53), nullable=False)
1222 gist_expires = Column('gist_expires', Float(53), nullable=False)
1223 gist_type = Column('gist_type', Unicode(128), nullable=False)
1223 gist_type = Column('gist_type', Unicode(128), nullable=False)
1224 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1224 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1225 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1225 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1226
1226
1227 owner = relationship('User')
1227 owner = relationship('User')
1228
1228
1229 def __repr__(self):
1229 def __repr__(self):
1230 return '<Gist:[%s]%s>' % (self.gist_type, self.gist_access_id)
1230 return '<Gist:[%s]%s>' % (self.gist_type, self.gist_access_id)
1231
1231
1232
1232
1233 class DbMigrateVersion(Base, BaseModel):
1233 class DbMigrateVersion(Base, BaseModel):
1234 __tablename__ = 'db_migrate_version'
1234 __tablename__ = 'db_migrate_version'
1235 __table_args__ = (
1235 __table_args__ = (
1236 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1236 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1237 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1237 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1238 )
1238 )
1239 repository_id = Column('repository_id', String(250), primary_key=True)
1239 repository_id = Column('repository_id', String(250), primary_key=True)
1240 repository_path = Column('repository_path', Text)
1240 repository_path = Column('repository_path', Text)
1241 version = Column('version', Integer)
1241 version = Column('version', Integer)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now