##// END OF EJS Templates
migration: remove usage of pylons inside migration schemas and code.
marcink -
r2096:5c18693f default
parent child Browse files
Show More

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

@@ -1,19 +1,27 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 def url(*args, **kwargs):
23 """
24 Dummy url generator to be used inside the old db migration schemas that rely on it.
25 It would protect from errors after removal of pylons.
26 """
27 return '/'
@@ -1,973 +1,972 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import os
22 import os
23 import time
23 import time
24 import logging
24 import logging
25 import datetime
25 import datetime
26 import traceback
26 import traceback
27 import hashlib
27 import hashlib
28 import collections
28 import collections
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.ext.hybrid import hybrid_property
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from beaker.cache import cache_region, region_invalidate
34 from beaker.cache import cache_region, region_invalidate
35 from webob.exc import HTTPNotFound
35 from webob.exc import HTTPNotFound
36
36
37 from pylons.i18n.translation import lazy_ugettext as _
37 from rhodecode.translation import _
38
39 from rhodecode.lib.vcs import get_backend
38 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.utils.helpers import get_scm
39 from rhodecode.lib.vcs.utils.helpers import get_scm
41 from rhodecode.lib.vcs.exceptions import VCSError
40 from rhodecode.lib.vcs.exceptions import VCSError
42 from zope.cachedescriptors.property import Lazy as LazyProperty
41 from zope.cachedescriptors.property import Lazy as LazyProperty
43
42
44 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
43 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 safe_unicode, remove_suffix
44 safe_unicode, remove_suffix
46 from rhodecode.lib.ext_json import json
45 from rhodecode.lib.ext_json import json
47 from rhodecode.lib.caching_query import FromCache
46 from rhodecode.lib.caching_query import FromCache
48
47
49 from rhodecode.model.meta import Base, Session
48 from rhodecode.model.meta import Base, Session
50
49
51 URL_SEP = '/'
50 URL_SEP = '/'
52 log = logging.getLogger(__name__)
51 log = logging.getLogger(__name__)
53
52
54 #==============================================================================
53 #==============================================================================
55 # BASE CLASSES
54 # BASE CLASSES
56 #==============================================================================
55 #==============================================================================
57
56
58 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
57 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
59
58
60
59
61 class BaseModel(object):
60 class BaseModel(object):
62 """
61 """
63 Base Model for all classes
62 Base Model for all classes
64 """
63 """
65
64
66 @classmethod
65 @classmethod
67 def _get_keys(cls):
66 def _get_keys(cls):
68 """return column names for this model """
67 """return column names for this model """
69 return class_mapper(cls).c.keys()
68 return class_mapper(cls).c.keys()
70
69
71 def get_dict(self):
70 def get_dict(self):
72 """
71 """
73 return dict with keys and values corresponding
72 return dict with keys and values corresponding
74 to this model data """
73 to this model data """
75
74
76 d = {}
75 d = {}
77 for k in self._get_keys():
76 for k in self._get_keys():
78 d[k] = getattr(self, k)
77 d[k] = getattr(self, k)
79
78
80 # also use __json__() if present to get additional fields
79 # also use __json__() if present to get additional fields
81 _json_attr = getattr(self, '__json__', None)
80 _json_attr = getattr(self, '__json__', None)
82 if _json_attr:
81 if _json_attr:
83 # update with attributes from __json__
82 # update with attributes from __json__
84 if callable(_json_attr):
83 if callable(_json_attr):
85 _json_attr = _json_attr()
84 _json_attr = _json_attr()
86 for k, val in _json_attr.iteritems():
85 for k, val in _json_attr.iteritems():
87 d[k] = val
86 d[k] = val
88 return d
87 return d
89
88
90 def get_appstruct(self):
89 def get_appstruct(self):
91 """return list with keys and values tupples corresponding
90 """return list with keys and values tupples corresponding
92 to this model data """
91 to this model data """
93
92
94 l = []
93 l = []
95 for k in self._get_keys():
94 for k in self._get_keys():
96 l.append((k, getattr(self, k),))
95 l.append((k, getattr(self, k),))
97 return l
96 return l
98
97
99 def populate_obj(self, populate_dict):
98 def populate_obj(self, populate_dict):
100 """populate model with data from given populate_dict"""
99 """populate model with data from given populate_dict"""
101
100
102 for k in self._get_keys():
101 for k in self._get_keys():
103 if k in populate_dict:
102 if k in populate_dict:
104 setattr(self, k, populate_dict[k])
103 setattr(self, k, populate_dict[k])
105
104
106 @classmethod
105 @classmethod
107 def query(cls):
106 def query(cls):
108 return Session().query(cls)
107 return Session().query(cls)
109
108
110 @classmethod
109 @classmethod
111 def get(cls, id_):
110 def get(cls, id_):
112 if id_:
111 if id_:
113 return cls.query().get(id_)
112 return cls.query().get(id_)
114
113
115 @classmethod
114 @classmethod
116 def get_or_404(cls, id_):
115 def get_or_404(cls, id_):
117 try:
116 try:
118 id_ = int(id_)
117 id_ = int(id_)
119 except (TypeError, ValueError):
118 except (TypeError, ValueError):
120 raise HTTPNotFound
119 raise HTTPNotFound
121
120
122 res = cls.query().get(id_)
121 res = cls.query().get(id_)
123 if not res:
122 if not res:
124 raise HTTPNotFound
123 raise HTTPNotFound
125 return res
124 return res
126
125
127 @classmethod
126 @classmethod
128 def getAll(cls):
127 def getAll(cls):
129 return cls.query().all()
128 return cls.query().all()
130
129
131 @classmethod
130 @classmethod
132 def delete(cls, id_):
131 def delete(cls, id_):
133 obj = cls.query().get(id_)
132 obj = cls.query().get(id_)
134 Session().delete(obj)
133 Session().delete(obj)
135
134
136 def __repr__(self):
135 def __repr__(self):
137 if hasattr(self, '__unicode__'):
136 if hasattr(self, '__unicode__'):
138 # python repr needs to return str
137 # python repr needs to return str
139 return safe_str(self.__unicode__())
138 return safe_str(self.__unicode__())
140 return '<DB:%s>' % (self.__class__.__name__)
139 return '<DB:%s>' % (self.__class__.__name__)
141
140
142
141
143 class RhodeCodeSetting(Base, BaseModel):
142 class RhodeCodeSetting(Base, BaseModel):
144 __tablename__ = 'rhodecode_settings'
143 __tablename__ = 'rhodecode_settings'
145 __table_args__ = (
144 __table_args__ = (
146 UniqueConstraint('app_settings_name'),
145 UniqueConstraint('app_settings_name'),
147 {'extend_existing': True, 'mysql_engine': 'InnoDB',
146 {'extend_existing': True, 'mysql_engine': 'InnoDB',
148 'mysql_charset': 'utf8'}
147 'mysql_charset': 'utf8'}
149 )
148 )
150 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
149 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
151 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
150 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
152 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
151 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
153
152
154 def __init__(self, k='', v=''):
153 def __init__(self, k='', v=''):
155 self.app_settings_name = k
154 self.app_settings_name = k
156 self.app_settings_value = v
155 self.app_settings_value = v
157
156
158 @validates('_app_settings_value')
157 @validates('_app_settings_value')
159 def validate_settings_value(self, key, val):
158 def validate_settings_value(self, key, val):
160 assert type(val) == unicode
159 assert type(val) == unicode
161 return val
160 return val
162
161
163 @hybrid_property
162 @hybrid_property
164 def app_settings_value(self):
163 def app_settings_value(self):
165 v = self._app_settings_value
164 v = self._app_settings_value
166 if self.app_settings_name == 'ldap_active':
165 if self.app_settings_name == 'ldap_active':
167 v = str2bool(v)
166 v = str2bool(v)
168 return v
167 return v
169
168
170 @app_settings_value.setter
169 @app_settings_value.setter
171 def app_settings_value(self, val):
170 def app_settings_value(self, val):
172 """
171 """
173 Setter that will always make sure we use unicode in app_settings_value
172 Setter that will always make sure we use unicode in app_settings_value
174
173
175 :param val:
174 :param val:
176 """
175 """
177 self._app_settings_value = safe_unicode(val)
176 self._app_settings_value = safe_unicode(val)
178
177
179 def __unicode__(self):
178 def __unicode__(self):
180 return u"<%s('%s:%s')>" % (
179 return u"<%s('%s:%s')>" % (
181 self.__class__.__name__,
180 self.__class__.__name__,
182 self.app_settings_name, self.app_settings_value
181 self.app_settings_name, self.app_settings_value
183 )
182 )
184
183
185
184
186 class RhodeCodeUi(Base, BaseModel):
185 class RhodeCodeUi(Base, BaseModel):
187 __tablename__ = 'rhodecode_ui'
186 __tablename__ = 'rhodecode_ui'
188 __table_args__ = (
187 __table_args__ = (
189 UniqueConstraint('ui_key'),
188 UniqueConstraint('ui_key'),
190 {'extend_existing': True, 'mysql_engine': 'InnoDB',
189 {'extend_existing': True, 'mysql_engine': 'InnoDB',
191 'mysql_charset': 'utf8'}
190 'mysql_charset': 'utf8'}
192 )
191 )
193
192
194 HOOK_REPO_SIZE = 'changegroup.repo_size'
193 HOOK_REPO_SIZE = 'changegroup.repo_size'
195 HOOK_PUSH = 'changegroup.push_logger'
194 HOOK_PUSH = 'changegroup.push_logger'
196 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
195 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
197 HOOK_PULL = 'outgoing.pull_logger'
196 HOOK_PULL = 'outgoing.pull_logger'
198 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
197 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
199
198
200 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
199 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
201 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
200 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
202 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
201 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
203 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
202 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
204 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
203 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
205
204
206
205
207
206
208 class User(Base, BaseModel):
207 class User(Base, BaseModel):
209 __tablename__ = 'users'
208 __tablename__ = 'users'
210 __table_args__ = (
209 __table_args__ = (
211 UniqueConstraint('username'), UniqueConstraint('email'),
210 UniqueConstraint('username'), UniqueConstraint('email'),
212 Index('u_username_idx', 'username'),
211 Index('u_username_idx', 'username'),
213 Index('u_email_idx', 'email'),
212 Index('u_email_idx', 'email'),
214 {'extend_existing': True, 'mysql_engine': 'InnoDB',
213 {'extend_existing': True, 'mysql_engine': 'InnoDB',
215 'mysql_charset': 'utf8'}
214 'mysql_charset': 'utf8'}
216 )
215 )
217 DEFAULT_USER = 'default'
216 DEFAULT_USER = 'default'
218 DEFAULT_PERMISSIONS = [
217 DEFAULT_PERMISSIONS = [
219 'hg.register.manual_activate', 'hg.create.repository',
218 'hg.register.manual_activate', 'hg.create.repository',
220 'hg.fork.repository', 'repository.read', 'group.read'
219 'hg.fork.repository', 'repository.read', 'group.read'
221 ]
220 ]
222 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
221 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
223 username = Column("username", String(255), nullable=True, unique=None, default=None)
222 username = Column("username", String(255), nullable=True, unique=None, default=None)
224 password = Column("password", String(255), nullable=True, unique=None, default=None)
223 password = Column("password", String(255), nullable=True, unique=None, default=None)
225 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
224 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
226 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
225 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
227 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
226 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
228 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
227 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
229 _email = Column("email", String(255), nullable=True, unique=None, default=None)
228 _email = Column("email", String(255), nullable=True, unique=None, default=None)
230 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
229 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
231 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
230 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
232 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
231 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
233 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
232 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
234
233
235 user_log = relationship('UserLog', cascade='all')
234 user_log = relationship('UserLog', cascade='all')
236 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
235 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
237
236
238 repositories = relationship('Repository')
237 repositories = relationship('Repository')
239 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
238 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
240 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
239 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
241 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
240 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
242
241
243 group_member = relationship('UserGroupMember', cascade='all')
242 group_member = relationship('UserGroupMember', cascade='all')
244
243
245 notifications = relationship('UserNotification', cascade='all')
244 notifications = relationship('UserNotification', cascade='all')
246 # notifications assigned to this user
245 # notifications assigned to this user
247 user_created_notifications = relationship('Notification', cascade='all')
246 user_created_notifications = relationship('Notification', cascade='all')
248 # comments created by this user
247 # comments created by this user
249 user_comments = relationship('ChangesetComment', cascade='all')
248 user_comments = relationship('ChangesetComment', cascade='all')
250 user_emails = relationship('UserEmailMap', cascade='all')
249 user_emails = relationship('UserEmailMap', cascade='all')
251
250
252 @hybrid_property
251 @hybrid_property
253 def email(self):
252 def email(self):
254 return self._email
253 return self._email
255
254
256 @email.setter
255 @email.setter
257 def email(self, val):
256 def email(self, val):
258 self._email = val.lower() if val else None
257 self._email = val.lower() if val else None
259
258
260 @property
259 @property
261 def firstname(self):
260 def firstname(self):
262 # alias for future
261 # alias for future
263 return self.name
262 return self.name
264
263
265 @property
264 @property
266 def username_and_name(self):
265 def username_and_name(self):
267 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
266 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
268
267
269 @property
268 @property
270 def full_name(self):
269 def full_name(self):
271 return '%s %s' % (self.firstname, self.lastname)
270 return '%s %s' % (self.firstname, self.lastname)
272
271
273 @property
272 @property
274 def full_contact(self):
273 def full_contact(self):
275 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
274 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
276
275
277 @property
276 @property
278 def short_contact(self):
277 def short_contact(self):
279 return '%s %s' % (self.firstname, self.lastname)
278 return '%s %s' % (self.firstname, self.lastname)
280
279
281 @property
280 @property
282 def is_admin(self):
281 def is_admin(self):
283 return self.admin
282 return self.admin
284
283
285 @classmethod
284 @classmethod
286 def get_by_username(cls, username, case_insensitive=False, cache=False):
285 def get_by_username(cls, username, case_insensitive=False, cache=False):
287 if case_insensitive:
286 if case_insensitive:
288 q = cls.query().filter(cls.username.ilike(username))
287 q = cls.query().filter(cls.username.ilike(username))
289 else:
288 else:
290 q = cls.query().filter(cls.username == username)
289 q = cls.query().filter(cls.username == username)
291
290
292 if cache:
291 if cache:
293 q = q.options(FromCache(
292 q = q.options(FromCache(
294 "sql_cache_short",
293 "sql_cache_short",
295 "get_user_%s" % _hash_key(username)
294 "get_user_%s" % _hash_key(username)
296 )
295 )
297 )
296 )
298 return q.scalar()
297 return q.scalar()
299
298
300 @classmethod
299 @classmethod
301 def get_by_auth_token(cls, auth_token, cache=False):
300 def get_by_auth_token(cls, auth_token, cache=False):
302 q = cls.query().filter(cls.api_key == auth_token)
301 q = cls.query().filter(cls.api_key == auth_token)
303
302
304 if cache:
303 if cache:
305 q = q.options(FromCache("sql_cache_short",
304 q = q.options(FromCache("sql_cache_short",
306 "get_auth_token_%s" % auth_token))
305 "get_auth_token_%s" % auth_token))
307 return q.scalar()
306 return q.scalar()
308
307
309 @classmethod
308 @classmethod
310 def get_by_email(cls, email, case_insensitive=False, cache=False):
309 def get_by_email(cls, email, case_insensitive=False, cache=False):
311 if case_insensitive:
310 if case_insensitive:
312 q = cls.query().filter(cls.email.ilike(email))
311 q = cls.query().filter(cls.email.ilike(email))
313 else:
312 else:
314 q = cls.query().filter(cls.email == email)
313 q = cls.query().filter(cls.email == email)
315
314
316 if cache:
315 if cache:
317 q = q.options(FromCache("sql_cache_short",
316 q = q.options(FromCache("sql_cache_short",
318 "get_email_key_%s" % email))
317 "get_email_key_%s" % email))
319
318
320 ret = q.scalar()
319 ret = q.scalar()
321 if ret is None:
320 if ret is None:
322 q = UserEmailMap.query()
321 q = UserEmailMap.query()
323 # try fetching in alternate email map
322 # try fetching in alternate email map
324 if case_insensitive:
323 if case_insensitive:
325 q = q.filter(UserEmailMap.email.ilike(email))
324 q = q.filter(UserEmailMap.email.ilike(email))
326 else:
325 else:
327 q = q.filter(UserEmailMap.email == email)
326 q = q.filter(UserEmailMap.email == email)
328 q = q.options(joinedload(UserEmailMap.user))
327 q = q.options(joinedload(UserEmailMap.user))
329 if cache:
328 if cache:
330 q = q.options(FromCache("sql_cache_short",
329 q = q.options(FromCache("sql_cache_short",
331 "get_email_map_key_%s" % email))
330 "get_email_map_key_%s" % email))
332 ret = getattr(q.scalar(), 'user', None)
331 ret = getattr(q.scalar(), 'user', None)
333
332
334 return ret
333 return ret
335
334
336
335
337 class UserEmailMap(Base, BaseModel):
336 class UserEmailMap(Base, BaseModel):
338 __tablename__ = 'user_email_map'
337 __tablename__ = 'user_email_map'
339 __table_args__ = (
338 __table_args__ = (
340 Index('uem_email_idx', 'email'),
339 Index('uem_email_idx', 'email'),
341 UniqueConstraint('email'),
340 UniqueConstraint('email'),
342 {'extend_existing': True, 'mysql_engine': 'InnoDB',
341 {'extend_existing': True, 'mysql_engine': 'InnoDB',
343 'mysql_charset': 'utf8'}
342 'mysql_charset': 'utf8'}
344 )
343 )
345 __mapper_args__ = {}
344 __mapper_args__ = {}
346
345
347 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
346 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
348 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
347 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
349 _email = Column("email", String(255), nullable=True, unique=False, default=None)
348 _email = Column("email", String(255), nullable=True, unique=False, default=None)
350 user = relationship('User', lazy='joined')
349 user = relationship('User', lazy='joined')
351
350
352 @validates('_email')
351 @validates('_email')
353 def validate_email(self, key, email):
352 def validate_email(self, key, email):
354 # check if this email is not main one
353 # check if this email is not main one
355 main_email = Session().query(User).filter(User.email == email).scalar()
354 main_email = Session().query(User).filter(User.email == email).scalar()
356 if main_email is not None:
355 if main_email is not None:
357 raise AttributeError('email %s is present is user table' % email)
356 raise AttributeError('email %s is present is user table' % email)
358 return email
357 return email
359
358
360 @hybrid_property
359 @hybrid_property
361 def email(self):
360 def email(self):
362 return self._email
361 return self._email
363
362
364 @email.setter
363 @email.setter
365 def email(self, val):
364 def email(self, val):
366 self._email = val.lower() if val else None
365 self._email = val.lower() if val else None
367
366
368
367
369 class UserLog(Base, BaseModel):
368 class UserLog(Base, BaseModel):
370 __tablename__ = 'user_logs'
369 __tablename__ = 'user_logs'
371 __table_args__ = (
370 __table_args__ = (
372 {'extend_existing': True, 'mysql_engine': 'InnoDB',
371 {'extend_existing': True, 'mysql_engine': 'InnoDB',
373 'mysql_charset': 'utf8'},
372 'mysql_charset': 'utf8'},
374 )
373 )
375 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
374 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
376 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
375 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
377 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
376 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
378 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
377 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
379 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
378 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
380 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
379 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
381 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
380 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
382
381
383
382
384 user = relationship('User')
383 user = relationship('User')
385 repository = relationship('Repository', cascade='')
384 repository = relationship('Repository', cascade='')
386
385
387
386
388 class UserGroup(Base, BaseModel):
387 class UserGroup(Base, BaseModel):
389 __tablename__ = 'users_groups'
388 __tablename__ = 'users_groups'
390 __table_args__ = (
389 __table_args__ = (
391 {'extend_existing': True, 'mysql_engine': 'InnoDB',
390 {'extend_existing': True, 'mysql_engine': 'InnoDB',
392 'mysql_charset': 'utf8'},
391 'mysql_charset': 'utf8'},
393 )
392 )
394
393
395 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
394 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
396 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
395 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
397 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
396 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
398 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
397 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
399
398
400 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
399 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
401 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
400 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
402 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
401 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
403
402
404 def __unicode__(self):
403 def __unicode__(self):
405 return u'<userGroup(%s)>' % (self.users_group_name)
404 return u'<userGroup(%s)>' % (self.users_group_name)
406
405
407 @classmethod
406 @classmethod
408 def get_by_group_name(cls, group_name, cache=False,
407 def get_by_group_name(cls, group_name, cache=False,
409 case_insensitive=False):
408 case_insensitive=False):
410 if case_insensitive:
409 if case_insensitive:
411 q = cls.query().filter(cls.users_group_name.ilike(group_name))
410 q = cls.query().filter(cls.users_group_name.ilike(group_name))
412 else:
411 else:
413 q = cls.query().filter(cls.users_group_name == group_name)
412 q = cls.query().filter(cls.users_group_name == group_name)
414 if cache:
413 if cache:
415 q = q.options(FromCache(
414 q = q.options(FromCache(
416 "sql_cache_short",
415 "sql_cache_short",
417 "get_user_%s" % _hash_key(group_name)
416 "get_user_%s" % _hash_key(group_name)
418 )
417 )
419 )
418 )
420 return q.scalar()
419 return q.scalar()
421
420
422 @classmethod
421 @classmethod
423 def get(cls, users_group_id, cache=False):
422 def get(cls, users_group_id, cache=False):
424 user_group = cls.query()
423 user_group = cls.query()
425 if cache:
424 if cache:
426 user_group = user_group.options(FromCache("sql_cache_short",
425 user_group = user_group.options(FromCache("sql_cache_short",
427 "get_users_group_%s" % users_group_id))
426 "get_users_group_%s" % users_group_id))
428 return user_group.get(users_group_id)
427 return user_group.get(users_group_id)
429
428
430
429
431 class UserGroupMember(Base, BaseModel):
430 class UserGroupMember(Base, BaseModel):
432 __tablename__ = 'users_groups_members'
431 __tablename__ = 'users_groups_members'
433 __table_args__ = (
432 __table_args__ = (
434 {'extend_existing': True, 'mysql_engine': 'InnoDB',
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
435 'mysql_charset': 'utf8'},
434 'mysql_charset': 'utf8'},
436 )
435 )
437
436
438 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
439 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
438 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
440 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
439 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
441
440
442 user = relationship('User', lazy='joined')
441 user = relationship('User', lazy='joined')
443 users_group = relationship('UserGroup')
442 users_group = relationship('UserGroup')
444
443
445 def __init__(self, gr_id='', u_id=''):
444 def __init__(self, gr_id='', u_id=''):
446 self.users_group_id = gr_id
445 self.users_group_id = gr_id
447 self.user_id = u_id
446 self.user_id = u_id
448
447
449
448
450 class Repository(Base, BaseModel):
449 class Repository(Base, BaseModel):
451 __tablename__ = 'repositories'
450 __tablename__ = 'repositories'
452 __table_args__ = (
451 __table_args__ = (
453 UniqueConstraint('repo_name'),
452 UniqueConstraint('repo_name'),
454 Index('r_repo_name_idx', 'repo_name'),
453 Index('r_repo_name_idx', 'repo_name'),
455 {'extend_existing': True, 'mysql_engine': 'InnoDB',
454 {'extend_existing': True, 'mysql_engine': 'InnoDB',
456 'mysql_charset': 'utf8'},
455 'mysql_charset': 'utf8'},
457 )
456 )
458
457
459 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
458 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
460 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
459 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
461 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
460 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
462 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
461 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
463 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
462 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
464 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
463 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
465 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
464 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
466 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
465 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
467 description = Column("description", String(10000), nullable=True, unique=None, default=None)
466 description = Column("description", String(10000), nullable=True, unique=None, default=None)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
467 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
469 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
468 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
470 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
469 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
471 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
470 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
472 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
471 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
473
472
474 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
473 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
475 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
474 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
476
475
477 user = relationship('User')
476 user = relationship('User')
478 fork = relationship('Repository', remote_side=repo_id)
477 fork = relationship('Repository', remote_side=repo_id)
479 group = relationship('RepoGroup')
478 group = relationship('RepoGroup')
480 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
479 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
481 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
480 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
482 stats = relationship('Statistics', cascade='all', uselist=False)
481 stats = relationship('Statistics', cascade='all', uselist=False)
483
482
484 followers = relationship('UserFollowing',
483 followers = relationship('UserFollowing',
485 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
484 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
486 cascade='all')
485 cascade='all')
487
486
488 logs = relationship('UserLog')
487 logs = relationship('UserLog')
489 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
488 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
490
489
491 pull_requests_org = relationship('PullRequest',
490 pull_requests_org = relationship('PullRequest',
492 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
491 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
493 cascade="all, delete, delete-orphan")
492 cascade="all, delete, delete-orphan")
494
493
495 pull_requests_other = relationship('PullRequest',
494 pull_requests_other = relationship('PullRequest',
496 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
495 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
497 cascade="all, delete, delete-orphan")
496 cascade="all, delete, delete-orphan")
498
497
499 def __unicode__(self):
498 def __unicode__(self):
500 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
499 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
501 self.repo_name)
500 self.repo_name)
502
501
503
502
504 @classmethod
503 @classmethod
505 def get_by_repo_name(cls, repo_name):
504 def get_by_repo_name(cls, repo_name):
506 q = Session().query(cls).filter(cls.repo_name == repo_name)
505 q = Session().query(cls).filter(cls.repo_name == repo_name)
507 q = q.options(joinedload(Repository.fork))\
506 q = q.options(joinedload(Repository.fork))\
508 .options(joinedload(Repository.user))\
507 .options(joinedload(Repository.user))\
509 .options(joinedload(Repository.group))
508 .options(joinedload(Repository.group))
510 return q.scalar()
509 return q.scalar()
511
510
512
511
513 class RepoGroup(Base, BaseModel):
512 class RepoGroup(Base, BaseModel):
514 __tablename__ = 'groups'
513 __tablename__ = 'groups'
515 __table_args__ = (
514 __table_args__ = (
516 UniqueConstraint('group_name', 'group_parent_id'),
515 UniqueConstraint('group_name', 'group_parent_id'),
517 CheckConstraint('group_id != group_parent_id'),
516 CheckConstraint('group_id != group_parent_id'),
518 {'extend_existing': True, 'mysql_engine': 'InnoDB',
517 {'extend_existing': True, 'mysql_engine': 'InnoDB',
519 'mysql_charset': 'utf8'},
518 'mysql_charset': 'utf8'},
520 )
519 )
521 __mapper_args__ = {'order_by': 'group_name'}
520 __mapper_args__ = {'order_by': 'group_name'}
522
521
523 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
522 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
524 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
523 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
525 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
524 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
526 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
525 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
527 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
526 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
528
527
529 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
528 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
530 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
529 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
531 parent_group = relationship('RepoGroup', remote_side=group_id)
530 parent_group = relationship('RepoGroup', remote_side=group_id)
532
531
533 def __init__(self, group_name='', parent_group=None):
532 def __init__(self, group_name='', parent_group=None):
534 self.group_name = group_name
533 self.group_name = group_name
535 self.parent_group = parent_group
534 self.parent_group = parent_group
536
535
537 def __unicode__(self):
536 def __unicode__(self):
538 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
537 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
539 self.group_name)
538 self.group_name)
540
539
541 @classmethod
540 @classmethod
542 def url_sep(cls):
541 def url_sep(cls):
543 return URL_SEP
542 return URL_SEP
544
543
545 @classmethod
544 @classmethod
546 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
545 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
547 if case_insensitive:
546 if case_insensitive:
548 gr = cls.query()\
547 gr = cls.query()\
549 .filter(cls.group_name.ilike(group_name))
548 .filter(cls.group_name.ilike(group_name))
550 else:
549 else:
551 gr = cls.query()\
550 gr = cls.query()\
552 .filter(cls.group_name == group_name)
551 .filter(cls.group_name == group_name)
553 if cache:
552 if cache:
554 gr = gr.options(FromCache(
553 gr = gr.options(FromCache(
555 "sql_cache_short",
554 "sql_cache_short",
556 "get_group_%s" % _hash_key(group_name)
555 "get_group_%s" % _hash_key(group_name)
557 )
556 )
558 )
557 )
559 return gr.scalar()
558 return gr.scalar()
560
559
561
560
562 class Permission(Base, BaseModel):
561 class Permission(Base, BaseModel):
563 __tablename__ = 'permissions'
562 __tablename__ = 'permissions'
564 __table_args__ = (
563 __table_args__ = (
565 Index('p_perm_name_idx', 'permission_name'),
564 Index('p_perm_name_idx', 'permission_name'),
566 {'extend_existing': True, 'mysql_engine': 'InnoDB',
565 {'extend_existing': True, 'mysql_engine': 'InnoDB',
567 'mysql_charset': 'utf8'},
566 'mysql_charset': 'utf8'},
568 )
567 )
569 PERMS = [
568 PERMS = [
570 ('repository.none', _('Repository no access')),
569 ('repository.none', _('Repository no access')),
571 ('repository.read', _('Repository read access')),
570 ('repository.read', _('Repository read access')),
572 ('repository.write', _('Repository write access')),
571 ('repository.write', _('Repository write access')),
573 ('repository.admin', _('Repository admin access')),
572 ('repository.admin', _('Repository admin access')),
574
573
575 ('group.none', _('Repositories Group no access')),
574 ('group.none', _('Repositories Group no access')),
576 ('group.read', _('Repositories Group read access')),
575 ('group.read', _('Repositories Group read access')),
577 ('group.write', _('Repositories Group write access')),
576 ('group.write', _('Repositories Group write access')),
578 ('group.admin', _('Repositories Group admin access')),
577 ('group.admin', _('Repositories Group admin access')),
579
578
580 ('hg.admin', _('RhodeCode Administrator')),
579 ('hg.admin', _('RhodeCode Administrator')),
581 ('hg.create.none', _('Repository creation disabled')),
580 ('hg.create.none', _('Repository creation disabled')),
582 ('hg.create.repository', _('Repository creation enabled')),
581 ('hg.create.repository', _('Repository creation enabled')),
583 ('hg.fork.none', _('Repository forking disabled')),
582 ('hg.fork.none', _('Repository forking disabled')),
584 ('hg.fork.repository', _('Repository forking enabled')),
583 ('hg.fork.repository', _('Repository forking enabled')),
585 ('hg.register.none', _('Register disabled')),
584 ('hg.register.none', _('Register disabled')),
586 ('hg.register.manual_activate', _('Register new user with RhodeCode '
585 ('hg.register.manual_activate', _('Register new user with RhodeCode '
587 'with manual activation')),
586 'with manual activation')),
588
587
589 ('hg.register.auto_activate', _('Register new user with RhodeCode '
588 ('hg.register.auto_activate', _('Register new user with RhodeCode '
590 'with auto activation')),
589 'with auto activation')),
591 ]
590 ]
592
591
593 # defines which permissions are more important higher the more important
592 # defines which permissions are more important higher the more important
594 PERM_WEIGHTS = {
593 PERM_WEIGHTS = {
595 'repository.none': 0,
594 'repository.none': 0,
596 'repository.read': 1,
595 'repository.read': 1,
597 'repository.write': 3,
596 'repository.write': 3,
598 'repository.admin': 4,
597 'repository.admin': 4,
599
598
600 'group.none': 0,
599 'group.none': 0,
601 'group.read': 1,
600 'group.read': 1,
602 'group.write': 3,
601 'group.write': 3,
603 'group.admin': 4,
602 'group.admin': 4,
604
603
605 'hg.fork.none': 0,
604 'hg.fork.none': 0,
606 'hg.fork.repository': 1,
605 'hg.fork.repository': 1,
607 'hg.create.none': 0,
606 'hg.create.none': 0,
608 'hg.create.repository':1
607 'hg.create.repository':1
609 }
608 }
610
609
611 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
610 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
612 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
611 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
613 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
612 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
614
613
615 def __unicode__(self):
614 def __unicode__(self):
616 return u"<%s('%s:%s')>" % (
615 return u"<%s('%s:%s')>" % (
617 self.__class__.__name__, self.permission_id, self.permission_name
616 self.__class__.__name__, self.permission_id, self.permission_name
618 )
617 )
619
618
620 @classmethod
619 @classmethod
621 def get_by_key(cls, key):
620 def get_by_key(cls, key):
622 return cls.query().filter(cls.permission_name == key).scalar()
621 return cls.query().filter(cls.permission_name == key).scalar()
623
622
624
623
625 class UserRepoToPerm(Base, BaseModel):
624 class UserRepoToPerm(Base, BaseModel):
626 __tablename__ = 'repo_to_perm'
625 __tablename__ = 'repo_to_perm'
627 __table_args__ = (
626 __table_args__ = (
628 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
627 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
629 {'extend_existing': True, 'mysql_engine': 'InnoDB',
628 {'extend_existing': True, 'mysql_engine': 'InnoDB',
630 'mysql_charset': 'utf8'}
629 'mysql_charset': 'utf8'}
631 )
630 )
632 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
631 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
633 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
632 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
634 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
633 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
635 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
634 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
636
635
637 user = relationship('User')
636 user = relationship('User')
638 repository = relationship('Repository')
637 repository = relationship('Repository')
639 permission = relationship('Permission')
638 permission = relationship('Permission')
640
639
641 def __unicode__(self):
640 def __unicode__(self):
642 return u'<user:%s => %s >' % (self.user, self.repository)
641 return u'<user:%s => %s >' % (self.user, self.repository)
643
642
644
643
645 class UserToPerm(Base, BaseModel):
644 class UserToPerm(Base, BaseModel):
646 __tablename__ = 'user_to_perm'
645 __tablename__ = 'user_to_perm'
647 __table_args__ = (
646 __table_args__ = (
648 UniqueConstraint('user_id', 'permission_id'),
647 UniqueConstraint('user_id', 'permission_id'),
649 {'extend_existing': True, 'mysql_engine': 'InnoDB',
648 {'extend_existing': True, 'mysql_engine': 'InnoDB',
650 'mysql_charset': 'utf8'}
649 'mysql_charset': 'utf8'}
651 )
650 )
652 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
651 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
653 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
652 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
654 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
653 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
655
654
656 user = relationship('User')
655 user = relationship('User')
657 permission = relationship('Permission', lazy='joined')
656 permission = relationship('Permission', lazy='joined')
658
657
659
658
660 class UserGroupRepoToPerm(Base, BaseModel):
659 class UserGroupRepoToPerm(Base, BaseModel):
661 __tablename__ = 'users_group_repo_to_perm'
660 __tablename__ = 'users_group_repo_to_perm'
662 __table_args__ = (
661 __table_args__ = (
663 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
662 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
664 {'extend_existing': True, 'mysql_engine': 'InnoDB',
663 {'extend_existing': True, 'mysql_engine': 'InnoDB',
665 'mysql_charset': 'utf8'}
664 'mysql_charset': 'utf8'}
666 )
665 )
667 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
666 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
668 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
667 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
669 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
668 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
670 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
669 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
671
670
672 users_group = relationship('UserGroup')
671 users_group = relationship('UserGroup')
673 permission = relationship('Permission')
672 permission = relationship('Permission')
674 repository = relationship('Repository')
673 repository = relationship('Repository')
675
674
676 def __unicode__(self):
675 def __unicode__(self):
677 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
676 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
678
677
679
678
680 class UserGroupToPerm(Base, BaseModel):
679 class UserGroupToPerm(Base, BaseModel):
681 __tablename__ = 'users_group_to_perm'
680 __tablename__ = 'users_group_to_perm'
682 __table_args__ = (
681 __table_args__ = (
683 UniqueConstraint('users_group_id', 'permission_id',),
682 UniqueConstraint('users_group_id', 'permission_id',),
684 {'extend_existing': True, 'mysql_engine': 'InnoDB',
683 {'extend_existing': True, 'mysql_engine': 'InnoDB',
685 'mysql_charset': 'utf8'}
684 'mysql_charset': 'utf8'}
686 )
685 )
687 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
686 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
688 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
687 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
689 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
688 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
690
689
691 users_group = relationship('UserGroup')
690 users_group = relationship('UserGroup')
692 permission = relationship('Permission')
691 permission = relationship('Permission')
693
692
694
693
695 class UserRepoGroupToPerm(Base, BaseModel):
694 class UserRepoGroupToPerm(Base, BaseModel):
696 __tablename__ = 'user_repo_group_to_perm'
695 __tablename__ = 'user_repo_group_to_perm'
697 __table_args__ = (
696 __table_args__ = (
698 UniqueConstraint('user_id', 'group_id', 'permission_id'),
697 UniqueConstraint('user_id', 'group_id', 'permission_id'),
699 {'extend_existing': True, 'mysql_engine': 'InnoDB',
698 {'extend_existing': True, 'mysql_engine': 'InnoDB',
700 'mysql_charset': 'utf8'}
699 'mysql_charset': 'utf8'}
701 )
700 )
702
701
703 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
702 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
704 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
703 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
705 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
704 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
706 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
705 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
707
706
708 user = relationship('User')
707 user = relationship('User')
709 group = relationship('RepoGroup')
708 group = relationship('RepoGroup')
710 permission = relationship('Permission')
709 permission = relationship('Permission')
711
710
712
711
713 class UserGroupRepoGroupToPerm(Base, BaseModel):
712 class UserGroupRepoGroupToPerm(Base, BaseModel):
714 __tablename__ = 'users_group_repo_group_to_perm'
713 __tablename__ = 'users_group_repo_group_to_perm'
715 __table_args__ = (
714 __table_args__ = (
716 UniqueConstraint('users_group_id', 'group_id'),
715 UniqueConstraint('users_group_id', 'group_id'),
717 {'extend_existing': True, 'mysql_engine': 'InnoDB',
716 {'extend_existing': True, 'mysql_engine': 'InnoDB',
718 'mysql_charset': 'utf8'}
717 'mysql_charset': 'utf8'}
719 )
718 )
720
719
721 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)
720 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)
722 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
721 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
723 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
722 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
724 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
723 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
725
724
726 users_group = relationship('UserGroup')
725 users_group = relationship('UserGroup')
727 permission = relationship('Permission')
726 permission = relationship('Permission')
728 group = relationship('RepoGroup')
727 group = relationship('RepoGroup')
729
728
730
729
731 class Statistics(Base, BaseModel):
730 class Statistics(Base, BaseModel):
732 __tablename__ = 'statistics'
731 __tablename__ = 'statistics'
733 __table_args__ = (
732 __table_args__ = (
734 UniqueConstraint('repository_id'),
733 UniqueConstraint('repository_id'),
735 {'extend_existing': True, 'mysql_engine': 'InnoDB',
734 {'extend_existing': True, 'mysql_engine': 'InnoDB',
736 'mysql_charset': 'utf8'}
735 'mysql_charset': 'utf8'}
737 )
736 )
738 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
737 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
739 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
738 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
740 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
739 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
741 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
740 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
742 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
741 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
743 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
742 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
744
743
745 repository = relationship('Repository', single_parent=True)
744 repository = relationship('Repository', single_parent=True)
746
745
747
746
748 class UserFollowing(Base, BaseModel):
747 class UserFollowing(Base, BaseModel):
749 __tablename__ = 'user_followings'
748 __tablename__ = 'user_followings'
750 __table_args__ = (
749 __table_args__ = (
751 UniqueConstraint('user_id', 'follows_repository_id'),
750 UniqueConstraint('user_id', 'follows_repository_id'),
752 UniqueConstraint('user_id', 'follows_user_id'),
751 UniqueConstraint('user_id', 'follows_user_id'),
753 {'extend_existing': True, 'mysql_engine': 'InnoDB',
752 {'extend_existing': True, 'mysql_engine': 'InnoDB',
754 'mysql_charset': 'utf8'}
753 'mysql_charset': 'utf8'}
755 )
754 )
756
755
757 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
756 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
758 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
757 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
759 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
758 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
760 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
759 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
761 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
760 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
762
761
763 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
762 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
764
763
765 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
764 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
766 follows_repository = relationship('Repository', order_by='Repository.repo_name')
765 follows_repository = relationship('Repository', order_by='Repository.repo_name')
767
766
768
767
769 class CacheInvalidation(Base, BaseModel):
768 class CacheInvalidation(Base, BaseModel):
770 __tablename__ = 'cache_invalidation'
769 __tablename__ = 'cache_invalidation'
771 __table_args__ = (
770 __table_args__ = (
772 UniqueConstraint('cache_key'),
771 UniqueConstraint('cache_key'),
773 Index('key_idx', 'cache_key'),
772 Index('key_idx', 'cache_key'),
774 {'extend_existing': True, 'mysql_engine': 'InnoDB',
773 {'extend_existing': True, 'mysql_engine': 'InnoDB',
775 'mysql_charset': 'utf8'},
774 'mysql_charset': 'utf8'},
776 )
775 )
777 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
776 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
778 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
777 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
779 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
778 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
780 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
779 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
781
780
782 def __init__(self, cache_key, cache_args=''):
781 def __init__(self, cache_key, cache_args=''):
783 self.cache_key = cache_key
782 self.cache_key = cache_key
784 self.cache_args = cache_args
783 self.cache_args = cache_args
785 self.cache_active = False
784 self.cache_active = False
786
785
787
786
788 class ChangesetComment(Base, BaseModel):
787 class ChangesetComment(Base, BaseModel):
789 __tablename__ = 'changeset_comments'
788 __tablename__ = 'changeset_comments'
790 __table_args__ = (
789 __table_args__ = (
791 Index('cc_revision_idx', 'revision'),
790 Index('cc_revision_idx', 'revision'),
792 {'extend_existing': True, 'mysql_engine': 'InnoDB',
791 {'extend_existing': True, 'mysql_engine': 'InnoDB',
793 'mysql_charset': 'utf8'},
792 'mysql_charset': 'utf8'},
794 )
793 )
795 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
794 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
796 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
795 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
797 revision = Column('revision', String(40), nullable=True)
796 revision = Column('revision', String(40), nullable=True)
798 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
797 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
799 line_no = Column('line_no', Unicode(10), nullable=True)
798 line_no = Column('line_no', Unicode(10), nullable=True)
800 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
799 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
801 f_path = Column('f_path', Unicode(1000), nullable=True)
800 f_path = Column('f_path', Unicode(1000), nullable=True)
802 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
801 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
803 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
802 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
804 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
803 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
805 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
804 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
806
805
807 author = relationship('User', lazy='joined')
806 author = relationship('User', lazy='joined')
808 repo = relationship('Repository')
807 repo = relationship('Repository')
809 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
808 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
810 pull_request = relationship('PullRequest', lazy='joined')
809 pull_request = relationship('PullRequest', lazy='joined')
811
810
812 @classmethod
811 @classmethod
813 def get_users(cls, revision=None, pull_request_id=None):
812 def get_users(cls, revision=None, pull_request_id=None):
814 """
813 """
815 Returns user associated with this ChangesetComment. ie those
814 Returns user associated with this ChangesetComment. ie those
816 who actually commented
815 who actually commented
817
816
818 :param cls:
817 :param cls:
819 :param revision:
818 :param revision:
820 """
819 """
821 q = Session().query(User)\
820 q = Session().query(User)\
822 .join(ChangesetComment.author)
821 .join(ChangesetComment.author)
823 if revision:
822 if revision:
824 q = q.filter(cls.revision == revision)
823 q = q.filter(cls.revision == revision)
825 elif pull_request_id:
824 elif pull_request_id:
826 q = q.filter(cls.pull_request_id == pull_request_id)
825 q = q.filter(cls.pull_request_id == pull_request_id)
827 return q.all()
826 return q.all()
828
827
829
828
830 class ChangesetStatus(Base, BaseModel):
829 class ChangesetStatus(Base, BaseModel):
831 __tablename__ = 'changeset_statuses'
830 __tablename__ = 'changeset_statuses'
832 __table_args__ = (
831 __table_args__ = (
833 Index('cs_revision_idx', 'revision'),
832 Index('cs_revision_idx', 'revision'),
834 Index('cs_version_idx', 'version'),
833 Index('cs_version_idx', 'version'),
835 UniqueConstraint('repo_id', 'revision', 'version'),
834 UniqueConstraint('repo_id', 'revision', 'version'),
836 {'extend_existing': True, 'mysql_engine': 'InnoDB',
835 {'extend_existing': True, 'mysql_engine': 'InnoDB',
837 'mysql_charset': 'utf8'}
836 'mysql_charset': 'utf8'}
838 )
837 )
839 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
838 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
840 STATUS_APPROVED = 'approved'
839 STATUS_APPROVED = 'approved'
841 STATUS_REJECTED = 'rejected'
840 STATUS_REJECTED = 'rejected'
842 STATUS_UNDER_REVIEW = 'under_review'
841 STATUS_UNDER_REVIEW = 'under_review'
843
842
844 STATUSES = [
843 STATUSES = [
845 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
844 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
846 (STATUS_APPROVED, _("Approved")),
845 (STATUS_APPROVED, _("Approved")),
847 (STATUS_REJECTED, _("Rejected")),
846 (STATUS_REJECTED, _("Rejected")),
848 (STATUS_UNDER_REVIEW, _("Under Review")),
847 (STATUS_UNDER_REVIEW, _("Under Review")),
849 ]
848 ]
850
849
851 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
850 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
852 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
851 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
853 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
852 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
854 revision = Column('revision', String(40), nullable=False)
853 revision = Column('revision', String(40), nullable=False)
855 status = Column('status', String(128), nullable=False, default=DEFAULT)
854 status = Column('status', String(128), nullable=False, default=DEFAULT)
856 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
855 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
857 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
856 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
858 version = Column('version', Integer(), nullable=False, default=0)
857 version = Column('version', Integer(), nullable=False, default=0)
859 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
858 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
860
859
861 author = relationship('User', lazy='joined')
860 author = relationship('User', lazy='joined')
862 repo = relationship('Repository')
861 repo = relationship('Repository')
863 comment = relationship('ChangesetComment', lazy='joined')
862 comment = relationship('ChangesetComment', lazy='joined')
864 pull_request = relationship('PullRequest', lazy='joined')
863 pull_request = relationship('PullRequest', lazy='joined')
865
864
866
865
867
866
868 class PullRequest(Base, BaseModel):
867 class PullRequest(Base, BaseModel):
869 __tablename__ = 'pull_requests'
868 __tablename__ = 'pull_requests'
870 __table_args__ = (
869 __table_args__ = (
871 {'extend_existing': True, 'mysql_engine': 'InnoDB',
870 {'extend_existing': True, 'mysql_engine': 'InnoDB',
872 'mysql_charset': 'utf8'},
871 'mysql_charset': 'utf8'},
873 )
872 )
874
873
875 STATUS_NEW = u'new'
874 STATUS_NEW = u'new'
876 STATUS_OPEN = u'open'
875 STATUS_OPEN = u'open'
877 STATUS_CLOSED = u'closed'
876 STATUS_CLOSED = u'closed'
878
877
879 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
878 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
880 title = Column('title', Unicode(256), nullable=True)
879 title = Column('title', Unicode(256), nullable=True)
881 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
880 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
882 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
881 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
883 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
882 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
884 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
883 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
885 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
884 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
886 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
885 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
887 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
886 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
888 org_ref = Column('org_ref', Unicode(256), nullable=False)
887 org_ref = Column('org_ref', Unicode(256), nullable=False)
889 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
888 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
890 other_ref = Column('other_ref', Unicode(256), nullable=False)
889 other_ref = Column('other_ref', Unicode(256), nullable=False)
891
890
892 author = relationship('User', lazy='joined')
891 author = relationship('User', lazy='joined')
893 reviewers = relationship('PullRequestReviewers',
892 reviewers = relationship('PullRequestReviewers',
894 cascade="all, delete, delete-orphan")
893 cascade="all, delete, delete-orphan")
895 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
894 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
896 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
895 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
897 statuses = relationship('ChangesetStatus')
896 statuses = relationship('ChangesetStatus')
898 comments = relationship('ChangesetComment',
897 comments = relationship('ChangesetComment',
899 cascade="all, delete, delete-orphan")
898 cascade="all, delete, delete-orphan")
900
899
901
900
902 class PullRequestReviewers(Base, BaseModel):
901 class PullRequestReviewers(Base, BaseModel):
903 __tablename__ = 'pull_request_reviewers'
902 __tablename__ = 'pull_request_reviewers'
904 __table_args__ = (
903 __table_args__ = (
905 {'extend_existing': True, 'mysql_engine': 'InnoDB',
904 {'extend_existing': True, 'mysql_engine': 'InnoDB',
906 'mysql_charset': 'utf8'},
905 'mysql_charset': 'utf8'},
907 )
906 )
908
907
909 def __init__(self, user=None, pull_request=None):
908 def __init__(self, user=None, pull_request=None):
910 self.user = user
909 self.user = user
911 self.pull_request = pull_request
910 self.pull_request = pull_request
912
911
913 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
912 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
914 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
913 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
915 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
914 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
916
915
917 user = relationship('User')
916 user = relationship('User')
918 pull_request = relationship('PullRequest')
917 pull_request = relationship('PullRequest')
919
918
920
919
921 class Notification(Base, BaseModel):
920 class Notification(Base, BaseModel):
922 __tablename__ = 'notifications'
921 __tablename__ = 'notifications'
923 __table_args__ = (
922 __table_args__ = (
924 Index('notification_type_idx', 'type'),
923 Index('notification_type_idx', 'type'),
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
924 {'extend_existing': True, 'mysql_engine': 'InnoDB',
926 'mysql_charset': 'utf8'},
925 'mysql_charset': 'utf8'},
927 )
926 )
928
927
929 TYPE_CHANGESET_COMMENT = u'cs_comment'
928 TYPE_CHANGESET_COMMENT = u'cs_comment'
930 TYPE_MESSAGE = u'message'
929 TYPE_MESSAGE = u'message'
931 TYPE_MENTION = u'mention'
930 TYPE_MENTION = u'mention'
932 TYPE_REGISTRATION = u'registration'
931 TYPE_REGISTRATION = u'registration'
933 TYPE_PULL_REQUEST = u'pull_request'
932 TYPE_PULL_REQUEST = u'pull_request'
934 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
933 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
935
934
936 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
935 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
937 subject = Column('subject', Unicode(512), nullable=True)
936 subject = Column('subject', Unicode(512), nullable=True)
938 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
937 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
939 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
938 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
940 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
939 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
941 type_ = Column('type', Unicode(256))
940 type_ = Column('type', Unicode(256))
942
941
943 created_by_user = relationship('User')
942 created_by_user = relationship('User')
944 notifications_to_users = relationship('UserNotification', lazy='joined',
943 notifications_to_users = relationship('UserNotification', lazy='joined',
945 cascade="all, delete, delete-orphan")
944 cascade="all, delete, delete-orphan")
946
945
947
946
948 class UserNotification(Base, BaseModel):
947 class UserNotification(Base, BaseModel):
949 __tablename__ = 'user_to_notification'
948 __tablename__ = 'user_to_notification'
950 __table_args__ = (
949 __table_args__ = (
951 UniqueConstraint('user_id', 'notification_id'),
950 UniqueConstraint('user_id', 'notification_id'),
952 {'extend_existing': True, 'mysql_engine': 'InnoDB',
951 {'extend_existing': True, 'mysql_engine': 'InnoDB',
953 'mysql_charset': 'utf8'}
952 'mysql_charset': 'utf8'}
954 )
953 )
955 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
954 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
956 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
955 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
957 read = Column('read', Boolean, default=False)
956 read = Column('read', Boolean, default=False)
958 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
957 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
959
958
960 user = relationship('User', lazy="joined")
959 user = relationship('User', lazy="joined")
961 notification = relationship('Notification', lazy="joined",
960 notification = relationship('Notification', lazy="joined",
962 order_by=lambda: Notification.created_on.desc(),)
961 order_by=lambda: Notification.created_on.desc(),)
963
962
964
963
965 class DbMigrateVersion(Base, BaseModel):
964 class DbMigrateVersion(Base, BaseModel):
966 __tablename__ = 'db_migrate_version'
965 __tablename__ = 'db_migrate_version'
967 __table_args__ = (
966 __table_args__ = (
968 {'extend_existing': True, 'mysql_engine': 'InnoDB',
967 {'extend_existing': True, 'mysql_engine': 'InnoDB',
969 'mysql_charset': 'utf8'},
968 'mysql_charset': 'utf8'},
970 )
969 )
971 repository_id = Column('repository_id', String(250), primary_key=True)
970 repository_id = Column('repository_id', String(250), primary_key=True)
972 repository_path = Column('repository_path', Text)
971 repository_path = Column('repository_path', Text)
973 version = Column('version', Integer)
972 version = Column('version', Integer)
@@ -1,993 +1,993 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import os
22 import os
23 import time
23 import time
24 import logging
24 import logging
25 import datetime
25 import datetime
26 import traceback
26 import traceback
27 import hashlib
27 import hashlib
28 import collections
28 import collections
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.ext.hybrid import hybrid_property
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from beaker.cache import cache_region, region_invalidate
34 from beaker.cache import cache_region, region_invalidate
35 from webob.exc import HTTPNotFound
35 from webob.exc import HTTPNotFound
36
36
37 from pylons.i18n.translation import lazy_ugettext as _
37 from rhodecode.translation import _
38
38
39 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.utils.helpers import get_scm
41 from rhodecode.lib.vcs.exceptions import VCSError
41 from rhodecode.lib.vcs.exceptions import VCSError
42 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from zope.cachedescriptors.property import Lazy as LazyProperty
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 safe_unicode, remove_suffix, remove_prefix
45 safe_unicode, remove_suffix, remove_prefix
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.iteritems():
86 for k, val in _json_attr.iteritems():
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 __tablename__ = 'rhodecode_settings'
149 __tablename__ = 'rhodecode_settings'
150 __table_args__ = (
150 __table_args__ = (
151 UniqueConstraint('app_settings_name'),
151 UniqueConstraint('app_settings_name'),
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
153 'mysql_charset': 'utf8'}
153 'mysql_charset': 'utf8'}
154 )
154 )
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
158
158
159 def __init__(self, k='', v=''):
159 def __init__(self, k='', v=''):
160 self.app_settings_name = k
160 self.app_settings_name = k
161 self.app_settings_value = v
161 self.app_settings_value = v
162
162
163 @validates('_app_settings_value')
163 @validates('_app_settings_value')
164 def validate_settings_value(self, key, val):
164 def validate_settings_value(self, key, val):
165 assert type(val) == unicode
165 assert type(val) == unicode
166 return val
166 return val
167
167
168 @hybrid_property
168 @hybrid_property
169 def app_settings_value(self):
169 def app_settings_value(self):
170 v = self._app_settings_value
170 v = self._app_settings_value
171 if self.app_settings_name in ["ldap_active",
171 if self.app_settings_name in ["ldap_active",
172 "default_repo_enable_statistics",
172 "default_repo_enable_statistics",
173 "default_repo_enable_locking",
173 "default_repo_enable_locking",
174 "default_repo_private",
174 "default_repo_private",
175 "default_repo_enable_downloads"]:
175 "default_repo_enable_downloads"]:
176 v = str2bool(v)
176 v = str2bool(v)
177 return v
177 return v
178
178
179 @app_settings_value.setter
179 @app_settings_value.setter
180 def app_settings_value(self, val):
180 def app_settings_value(self, val):
181 """
181 """
182 Setter that will always make sure we use unicode in app_settings_value
182 Setter that will always make sure we use unicode in app_settings_value
183
183
184 :param val:
184 :param val:
185 """
185 """
186 self._app_settings_value = safe_unicode(val)
186 self._app_settings_value = safe_unicode(val)
187
187
188 def __unicode__(self):
188 def __unicode__(self):
189 return u"<%s('%s:%s')>" % (
189 return u"<%s('%s:%s')>" % (
190 self.__class__.__name__,
190 self.__class__.__name__,
191 self.app_settings_name, self.app_settings_value
191 self.app_settings_name, self.app_settings_value
192 )
192 )
193
193
194
194
195 class RhodeCodeUi(Base, BaseModel):
195 class RhodeCodeUi(Base, BaseModel):
196 __tablename__ = 'rhodecode_ui'
196 __tablename__ = 'rhodecode_ui'
197 __table_args__ = (
197 __table_args__ = (
198 UniqueConstraint('ui_key'),
198 UniqueConstraint('ui_key'),
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
200 'mysql_charset': 'utf8'}
200 'mysql_charset': 'utf8'}
201 )
201 )
202
202
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
204 HOOK_PUSH = 'changegroup.push_logger'
204 HOOK_PUSH = 'changegroup.push_logger'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
206 HOOK_PULL = 'outgoing.pull_logger'
206 HOOK_PULL = 'outgoing.pull_logger'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
208
208
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
214
214
215
215
216
216
217 class User(Base, BaseModel):
217 class User(Base, BaseModel):
218 __tablename__ = 'users'
218 __tablename__ = 'users'
219 __table_args__ = (
219 __table_args__ = (
220 UniqueConstraint('username'), UniqueConstraint('email'),
220 UniqueConstraint('username'), UniqueConstraint('email'),
221 Index('u_username_idx', 'username'),
221 Index('u_username_idx', 'username'),
222 Index('u_email_idx', 'email'),
222 Index('u_email_idx', 'email'),
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
224 'mysql_charset': 'utf8'}
224 'mysql_charset': 'utf8'}
225 )
225 )
226 DEFAULT_USER = 'default'
226 DEFAULT_USER = 'default'
227 DEFAULT_PERMISSIONS = [
227 DEFAULT_PERMISSIONS = [
228 'hg.register.manual_activate', 'hg.create.repository',
228 'hg.register.manual_activate', 'hg.create.repository',
229 'hg.fork.repository', 'repository.read', 'group.read'
229 'hg.fork.repository', 'repository.read', 'group.read'
230 ]
230 ]
231 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
231 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 username = Column("username", String(255), nullable=True, unique=None, default=None)
232 username = Column("username", String(255), nullable=True, unique=None, default=None)
233 password = Column("password", String(255), nullable=True, unique=None, default=None)
233 password = Column("password", String(255), nullable=True, unique=None, default=None)
234 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
234 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
235 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
235 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
236 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
236 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
237 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
237 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
238 _email = Column("email", String(255), nullable=True, unique=None, default=None)
238 _email = Column("email", String(255), nullable=True, unique=None, default=None)
239 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
239 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
240 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
240 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
241 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
241 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
242 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
242 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
243
243
244 user_log = relationship('UserLog')
244 user_log = relationship('UserLog')
245 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
245 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
246
246
247 repositories = relationship('Repository')
247 repositories = relationship('Repository')
248 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
248 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
249 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
249 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
250
250
251 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
251 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
252 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
252 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
253
253
254 group_member = relationship('UserGroupMember', cascade='all')
254 group_member = relationship('UserGroupMember', cascade='all')
255
255
256 notifications = relationship('UserNotification', cascade='all')
256 notifications = relationship('UserNotification', cascade='all')
257 # notifications assigned to this user
257 # notifications assigned to this user
258 user_created_notifications = relationship('Notification', cascade='all')
258 user_created_notifications = relationship('Notification', cascade='all')
259 # comments created by this user
259 # comments created by this user
260 user_comments = relationship('ChangesetComment', cascade='all')
260 user_comments = relationship('ChangesetComment', cascade='all')
261 user_emails = relationship('UserEmailMap', cascade='all')
261 user_emails = relationship('UserEmailMap', cascade='all')
262
262
263 @hybrid_property
263 @hybrid_property
264 def email(self):
264 def email(self):
265 return self._email
265 return self._email
266
266
267 @email.setter
267 @email.setter
268 def email(self, val):
268 def email(self, val):
269 self._email = val.lower() if val else None
269 self._email = val.lower() if val else None
270
270
271 @property
271 @property
272 def firstname(self):
272 def firstname(self):
273 # alias for future
273 # alias for future
274 return self.name
274 return self.name
275
275
276 @property
276 @property
277 def username_and_name(self):
277 def username_and_name(self):
278 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
278 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
279
279
280 @property
280 @property
281 def full_name(self):
281 def full_name(self):
282 return '%s %s' % (self.firstname, self.lastname)
282 return '%s %s' % (self.firstname, self.lastname)
283
283
284 @property
284 @property
285 def full_contact(self):
285 def full_contact(self):
286 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
286 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
287
287
288 @property
288 @property
289 def short_contact(self):
289 def short_contact(self):
290 return '%s %s' % (self.firstname, self.lastname)
290 return '%s %s' % (self.firstname, self.lastname)
291
291
292 @property
292 @property
293 def is_admin(self):
293 def is_admin(self):
294 return self.admin
294 return self.admin
295
295
296 @classmethod
296 @classmethod
297 def get_by_username(cls, username, case_insensitive=False, cache=False):
297 def get_by_username(cls, username, case_insensitive=False, cache=False):
298 if case_insensitive:
298 if case_insensitive:
299 q = cls.query().filter(cls.username.ilike(username))
299 q = cls.query().filter(cls.username.ilike(username))
300 else:
300 else:
301 q = cls.query().filter(cls.username == username)
301 q = cls.query().filter(cls.username == username)
302
302
303 if cache:
303 if cache:
304 q = q.options(FromCache(
304 q = q.options(FromCache(
305 "sql_cache_short",
305 "sql_cache_short",
306 "get_user_%s" % _hash_key(username)
306 "get_user_%s" % _hash_key(username)
307 )
307 )
308 )
308 )
309 return q.scalar()
309 return q.scalar()
310
310
311 @classmethod
311 @classmethod
312 def get_by_auth_token(cls, auth_token, cache=False):
312 def get_by_auth_token(cls, auth_token, cache=False):
313 q = cls.query().filter(cls.api_key == auth_token)
313 q = cls.query().filter(cls.api_key == auth_token)
314
314
315 if cache:
315 if cache:
316 q = q.options(FromCache("sql_cache_short",
316 q = q.options(FromCache("sql_cache_short",
317 "get_auth_token_%s" % auth_token))
317 "get_auth_token_%s" % auth_token))
318 return q.scalar()
318 return q.scalar()
319
319
320 @classmethod
320 @classmethod
321 def get_by_email(cls, email, case_insensitive=False, cache=False):
321 def get_by_email(cls, email, case_insensitive=False, cache=False):
322 if case_insensitive:
322 if case_insensitive:
323 q = cls.query().filter(cls.email.ilike(email))
323 q = cls.query().filter(cls.email.ilike(email))
324 else:
324 else:
325 q = cls.query().filter(cls.email == email)
325 q = cls.query().filter(cls.email == email)
326
326
327 if cache:
327 if cache:
328 q = q.options(FromCache("sql_cache_short",
328 q = q.options(FromCache("sql_cache_short",
329 "get_email_key_%s" % email))
329 "get_email_key_%s" % email))
330
330
331 ret = q.scalar()
331 ret = q.scalar()
332 if ret is None:
332 if ret is None:
333 q = UserEmailMap.query()
333 q = UserEmailMap.query()
334 # try fetching in alternate email map
334 # try fetching in alternate email map
335 if case_insensitive:
335 if case_insensitive:
336 q = q.filter(UserEmailMap.email.ilike(email))
336 q = q.filter(UserEmailMap.email.ilike(email))
337 else:
337 else:
338 q = q.filter(UserEmailMap.email == email)
338 q = q.filter(UserEmailMap.email == email)
339 q = q.options(joinedload(UserEmailMap.user))
339 q = q.options(joinedload(UserEmailMap.user))
340 if cache:
340 if cache:
341 q = q.options(FromCache("sql_cache_short",
341 q = q.options(FromCache("sql_cache_short",
342 "get_email_map_key_%s" % email))
342 "get_email_map_key_%s" % email))
343 ret = getattr(q.scalar(), 'user', None)
343 ret = getattr(q.scalar(), 'user', None)
344
344
345 return ret
345 return ret
346
346
347
347
348 class UserEmailMap(Base, BaseModel):
348 class UserEmailMap(Base, BaseModel):
349 __tablename__ = 'user_email_map'
349 __tablename__ = 'user_email_map'
350 __table_args__ = (
350 __table_args__ = (
351 Index('uem_email_idx', 'email'),
351 Index('uem_email_idx', 'email'),
352 UniqueConstraint('email'),
352 UniqueConstraint('email'),
353 {'extend_existing': True, 'mysql_engine': 'InnoDB',
353 {'extend_existing': True, 'mysql_engine': 'InnoDB',
354 'mysql_charset': 'utf8'}
354 'mysql_charset': 'utf8'}
355 )
355 )
356 __mapper_args__ = {}
356 __mapper_args__ = {}
357
357
358 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
358 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
359 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
359 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
360 _email = Column("email", String(255), nullable=True, unique=False, default=None)
360 _email = Column("email", String(255), nullable=True, unique=False, default=None)
361 user = relationship('User', lazy='joined')
361 user = relationship('User', lazy='joined')
362
362
363 @validates('_email')
363 @validates('_email')
364 def validate_email(self, key, email):
364 def validate_email(self, key, email):
365 # check if this email is not main one
365 # check if this email is not main one
366 main_email = Session().query(User).filter(User.email == email).scalar()
366 main_email = Session().query(User).filter(User.email == email).scalar()
367 if main_email is not None:
367 if main_email is not None:
368 raise AttributeError('email %s is present is user table' % email)
368 raise AttributeError('email %s is present is user table' % email)
369 return email
369 return email
370
370
371 @hybrid_property
371 @hybrid_property
372 def email(self):
372 def email(self):
373 return self._email
373 return self._email
374
374
375 @email.setter
375 @email.setter
376 def email(self, val):
376 def email(self, val):
377 self._email = val.lower() if val else None
377 self._email = val.lower() if val else None
378
378
379
379
380 class UserLog(Base, BaseModel):
380 class UserLog(Base, BaseModel):
381 __tablename__ = 'user_logs'
381 __tablename__ = 'user_logs'
382 __table_args__ = (
382 __table_args__ = (
383 {'extend_existing': True, 'mysql_engine': 'InnoDB',
383 {'extend_existing': True, 'mysql_engine': 'InnoDB',
384 'mysql_charset': 'utf8'},
384 'mysql_charset': 'utf8'},
385 )
385 )
386 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
386 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
387 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
387 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
388 username = Column("username", String(255), nullable=True, unique=None, default=None)
388 username = Column("username", String(255), nullable=True, unique=None, default=None)
389 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
389 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
390 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
390 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
391 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
391 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
392 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
392 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
393 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
393 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
394
394
395
395
396 user = relationship('User')
396 user = relationship('User')
397 repository = relationship('Repository', cascade='')
397 repository = relationship('Repository', cascade='')
398
398
399
399
400 class UserGroup(Base, BaseModel):
400 class UserGroup(Base, BaseModel):
401 __tablename__ = 'users_groups'
401 __tablename__ = 'users_groups'
402 __table_args__ = (
402 __table_args__ = (
403 {'extend_existing': True, 'mysql_engine': 'InnoDB',
403 {'extend_existing': True, 'mysql_engine': 'InnoDB',
404 'mysql_charset': 'utf8'},
404 'mysql_charset': 'utf8'},
405 )
405 )
406
406
407 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
407 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
408 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
408 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
409 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
409 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
410 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
410 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
411
411
412 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
412 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
413 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
413 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
414 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
414 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
415
415
416 def __unicode__(self):
416 def __unicode__(self):
417 return u'<userGroup(%s)>' % (self.users_group_name)
417 return u'<userGroup(%s)>' % (self.users_group_name)
418
418
419 @classmethod
419 @classmethod
420 def get_by_group_name(cls, group_name, cache=False,
420 def get_by_group_name(cls, group_name, cache=False,
421 case_insensitive=False):
421 case_insensitive=False):
422 if case_insensitive:
422 if case_insensitive:
423 q = cls.query().filter(cls.users_group_name.ilike(group_name))
423 q = cls.query().filter(cls.users_group_name.ilike(group_name))
424 else:
424 else:
425 q = cls.query().filter(cls.users_group_name == group_name)
425 q = cls.query().filter(cls.users_group_name == group_name)
426 if cache:
426 if cache:
427 q = q.options(FromCache(
427 q = q.options(FromCache(
428 "sql_cache_short",
428 "sql_cache_short",
429 "get_user_%s" % _hash_key(group_name)
429 "get_user_%s" % _hash_key(group_name)
430 )
430 )
431 )
431 )
432 return q.scalar()
432 return q.scalar()
433
433
434 @classmethod
434 @classmethod
435 def get(cls, users_group_id, cache=False):
435 def get(cls, users_group_id, cache=False):
436 user_group = cls.query()
436 user_group = cls.query()
437 if cache:
437 if cache:
438 user_group = user_group.options(FromCache("sql_cache_short",
438 user_group = user_group.options(FromCache("sql_cache_short",
439 "get_users_group_%s" % users_group_id))
439 "get_users_group_%s" % users_group_id))
440 return user_group.get(users_group_id)
440 return user_group.get(users_group_id)
441
441
442
442
443 class UserGroupMember(Base, BaseModel):
443 class UserGroupMember(Base, BaseModel):
444 __tablename__ = 'users_groups_members'
444 __tablename__ = 'users_groups_members'
445 __table_args__ = (
445 __table_args__ = (
446 {'extend_existing': True, 'mysql_engine': 'InnoDB',
446 {'extend_existing': True, 'mysql_engine': 'InnoDB',
447 'mysql_charset': 'utf8'},
447 'mysql_charset': 'utf8'},
448 )
448 )
449
449
450 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
450 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
451 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
451 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
452 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
452 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
453
453
454 user = relationship('User', lazy='joined')
454 user = relationship('User', lazy='joined')
455 users_group = relationship('UserGroup')
455 users_group = relationship('UserGroup')
456
456
457 def __init__(self, gr_id='', u_id=''):
457 def __init__(self, gr_id='', u_id=''):
458 self.users_group_id = gr_id
458 self.users_group_id = gr_id
459 self.user_id = u_id
459 self.user_id = u_id
460
460
461
461
462 class Repository(Base, BaseModel):
462 class Repository(Base, BaseModel):
463 __tablename__ = 'repositories'
463 __tablename__ = 'repositories'
464 __table_args__ = (
464 __table_args__ = (
465 UniqueConstraint('repo_name'),
465 UniqueConstraint('repo_name'),
466 Index('r_repo_name_idx', 'repo_name'),
466 Index('r_repo_name_idx', 'repo_name'),
467 {'extend_existing': True, 'mysql_engine': 'InnoDB',
467 {'extend_existing': True, 'mysql_engine': 'InnoDB',
468 'mysql_charset': 'utf8'},
468 'mysql_charset': 'utf8'},
469 )
469 )
470
470
471 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
471 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
472 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
472 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
473 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
473 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
474 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
474 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
475 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
475 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
476 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
476 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
477 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
477 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
478 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
478 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
479 description = Column("description", String(10000), nullable=True, unique=None, default=None)
479 description = Column("description", String(10000), nullable=True, unique=None, default=None)
480 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
480 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
481 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
481 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
482 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
482 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
483 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
483 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
484 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
484 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
485
485
486 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
486 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
487 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
487 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
488
488
489 user = relationship('User')
489 user = relationship('User')
490 fork = relationship('Repository', remote_side=repo_id)
490 fork = relationship('Repository', remote_side=repo_id)
491 group = relationship('RepoGroup')
491 group = relationship('RepoGroup')
492 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
492 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
493 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
493 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
494 stats = relationship('Statistics', cascade='all', uselist=False)
494 stats = relationship('Statistics', cascade='all', uselist=False)
495
495
496 followers = relationship('UserFollowing',
496 followers = relationship('UserFollowing',
497 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
497 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
498 cascade='all')
498 cascade='all')
499
499
500 logs = relationship('UserLog')
500 logs = relationship('UserLog')
501 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
501 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
502
502
503 pull_requests_org = relationship('PullRequest',
503 pull_requests_org = relationship('PullRequest',
504 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
504 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
505 cascade="all, delete, delete-orphan")
505 cascade="all, delete, delete-orphan")
506
506
507 pull_requests_other = relationship('PullRequest',
507 pull_requests_other = relationship('PullRequest',
508 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
508 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
509 cascade="all, delete, delete-orphan")
509 cascade="all, delete, delete-orphan")
510
510
511 def __unicode__(self):
511 def __unicode__(self):
512 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
512 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
513 self.repo_name)
513 self.repo_name)
514
514
515
515
516 @classmethod
516 @classmethod
517 def get_by_repo_name(cls, repo_name):
517 def get_by_repo_name(cls, repo_name):
518 q = Session().query(cls).filter(cls.repo_name == repo_name)
518 q = Session().query(cls).filter(cls.repo_name == repo_name)
519 q = q.options(joinedload(Repository.fork))\
519 q = q.options(joinedload(Repository.fork))\
520 .options(joinedload(Repository.user))\
520 .options(joinedload(Repository.user))\
521 .options(joinedload(Repository.group))
521 .options(joinedload(Repository.group))
522 return q.scalar()
522 return q.scalar()
523
523
524
524
525 class RepoGroup(Base, BaseModel):
525 class RepoGroup(Base, BaseModel):
526 __tablename__ = 'groups'
526 __tablename__ = 'groups'
527 __table_args__ = (
527 __table_args__ = (
528 UniqueConstraint('group_name', 'group_parent_id'),
528 UniqueConstraint('group_name', 'group_parent_id'),
529 CheckConstraint('group_id != group_parent_id'),
529 CheckConstraint('group_id != group_parent_id'),
530 {'extend_existing': True, 'mysql_engine': 'InnoDB',
530 {'extend_existing': True, 'mysql_engine': 'InnoDB',
531 'mysql_charset': 'utf8'},
531 'mysql_charset': 'utf8'},
532 )
532 )
533 __mapper_args__ = {'order_by': 'group_name'}
533 __mapper_args__ = {'order_by': 'group_name'}
534
534
535 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
535 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
536 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
536 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
537 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
537 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
538 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
538 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
539 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
539 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
540
540
541 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
541 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
542 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
542 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
543 parent_group = relationship('RepoGroup', remote_side=group_id)
543 parent_group = relationship('RepoGroup', remote_side=group_id)
544
544
545 def __init__(self, group_name='', parent_group=None):
545 def __init__(self, group_name='', parent_group=None):
546 self.group_name = group_name
546 self.group_name = group_name
547 self.parent_group = parent_group
547 self.parent_group = parent_group
548
548
549 def __unicode__(self):
549 def __unicode__(self):
550 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
550 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
551 self.group_name)
551 self.group_name)
552
552
553 @classmethod
553 @classmethod
554 def url_sep(cls):
554 def url_sep(cls):
555 return URL_SEP
555 return URL_SEP
556
556
557 @classmethod
557 @classmethod
558 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
558 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
559 if case_insensitive:
559 if case_insensitive:
560 gr = cls.query()\
560 gr = cls.query()\
561 .filter(cls.group_name.ilike(group_name))
561 .filter(cls.group_name.ilike(group_name))
562 else:
562 else:
563 gr = cls.query()\
563 gr = cls.query()\
564 .filter(cls.group_name == group_name)
564 .filter(cls.group_name == group_name)
565 if cache:
565 if cache:
566 gr = gr.options(FromCache(
566 gr = gr.options(FromCache(
567 "sql_cache_short",
567 "sql_cache_short",
568 "get_group_%s" % _hash_key(group_name)
568 "get_group_%s" % _hash_key(group_name)
569 )
569 )
570 )
570 )
571 return gr.scalar()
571 return gr.scalar()
572
572
573
573
574 class Permission(Base, BaseModel):
574 class Permission(Base, BaseModel):
575 __tablename__ = 'permissions'
575 __tablename__ = 'permissions'
576 __table_args__ = (
576 __table_args__ = (
577 Index('p_perm_name_idx', 'permission_name'),
577 Index('p_perm_name_idx', 'permission_name'),
578 {'extend_existing': True, 'mysql_engine': 'InnoDB',
578 {'extend_existing': True, 'mysql_engine': 'InnoDB',
579 'mysql_charset': 'utf8'},
579 'mysql_charset': 'utf8'},
580 )
580 )
581 PERMS = [
581 PERMS = [
582 ('repository.none', _('Repository no access')),
582 ('repository.none', _('Repository no access')),
583 ('repository.read', _('Repository read access')),
583 ('repository.read', _('Repository read access')),
584 ('repository.write', _('Repository write access')),
584 ('repository.write', _('Repository write access')),
585 ('repository.admin', _('Repository admin access')),
585 ('repository.admin', _('Repository admin access')),
586
586
587 ('group.none', _('Repositories Group no access')),
587 ('group.none', _('Repositories Group no access')),
588 ('group.read', _('Repositories Group read access')),
588 ('group.read', _('Repositories Group read access')),
589 ('group.write', _('Repositories Group write access')),
589 ('group.write', _('Repositories Group write access')),
590 ('group.admin', _('Repositories Group admin access')),
590 ('group.admin', _('Repositories Group admin access')),
591
591
592 ('hg.admin', _('RhodeCode Administrator')),
592 ('hg.admin', _('RhodeCode Administrator')),
593 ('hg.create.none', _('Repository creation disabled')),
593 ('hg.create.none', _('Repository creation disabled')),
594 ('hg.create.repository', _('Repository creation enabled')),
594 ('hg.create.repository', _('Repository creation enabled')),
595 ('hg.fork.none', _('Repository forking disabled')),
595 ('hg.fork.none', _('Repository forking disabled')),
596 ('hg.fork.repository', _('Repository forking enabled')),
596 ('hg.fork.repository', _('Repository forking enabled')),
597 ('hg.register.none', _('Register disabled')),
597 ('hg.register.none', _('Register disabled')),
598 ('hg.register.manual_activate', _('Register new user with RhodeCode '
598 ('hg.register.manual_activate', _('Register new user with RhodeCode '
599 'with manual activation')),
599 'with manual activation')),
600
600
601 ('hg.register.auto_activate', _('Register new user with RhodeCode '
601 ('hg.register.auto_activate', _('Register new user with RhodeCode '
602 'with auto activation')),
602 'with auto activation')),
603 ]
603 ]
604
604
605 # defines which permissions are more important higher the more important
605 # defines which permissions are more important higher the more important
606 PERM_WEIGHTS = {
606 PERM_WEIGHTS = {
607 'repository.none': 0,
607 'repository.none': 0,
608 'repository.read': 1,
608 'repository.read': 1,
609 'repository.write': 3,
609 'repository.write': 3,
610 'repository.admin': 4,
610 'repository.admin': 4,
611
611
612 'group.none': 0,
612 'group.none': 0,
613 'group.read': 1,
613 'group.read': 1,
614 'group.write': 3,
614 'group.write': 3,
615 'group.admin': 4,
615 'group.admin': 4,
616
616
617 'hg.fork.none': 0,
617 'hg.fork.none': 0,
618 'hg.fork.repository': 1,
618 'hg.fork.repository': 1,
619 'hg.create.none': 0,
619 'hg.create.none': 0,
620 'hg.create.repository':1
620 'hg.create.repository':1
621 }
621 }
622
622
623 DEFAULT_USER_PERMISSIONS = [
623 DEFAULT_USER_PERMISSIONS = [
624 'repository.read',
624 'repository.read',
625 'group.read',
625 'group.read',
626 'hg.create.repository',
626 'hg.create.repository',
627 'hg.fork.repository',
627 'hg.fork.repository',
628 'hg.register.manual_activate',
628 'hg.register.manual_activate',
629 ]
629 ]
630
630
631 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
631 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
632 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
632 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
633 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
633 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
634
634
635 def __unicode__(self):
635 def __unicode__(self):
636 return u"<%s('%s:%s')>" % (
636 return u"<%s('%s:%s')>" % (
637 self.__class__.__name__, self.permission_id, self.permission_name
637 self.__class__.__name__, self.permission_id, self.permission_name
638 )
638 )
639
639
640 @classmethod
640 @classmethod
641 def get_by_key(cls, key):
641 def get_by_key(cls, key):
642 return cls.query().filter(cls.permission_name == key).scalar()
642 return cls.query().filter(cls.permission_name == key).scalar()
643
643
644
644
645 class UserRepoToPerm(Base, BaseModel):
645 class UserRepoToPerm(Base, BaseModel):
646 __tablename__ = 'repo_to_perm'
646 __tablename__ = 'repo_to_perm'
647 __table_args__ = (
647 __table_args__ = (
648 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
648 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
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 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
652 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
653 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
653 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
654 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
654 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
655 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
655 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
656
656
657 user = relationship('User')
657 user = relationship('User')
658 repository = relationship('Repository')
658 repository = relationship('Repository')
659 permission = relationship('Permission')
659 permission = relationship('Permission')
660
660
661 def __unicode__(self):
661 def __unicode__(self):
662 return u'<user:%s => %s >' % (self.user, self.repository)
662 return u'<user:%s => %s >' % (self.user, self.repository)
663
663
664
664
665 class UserToPerm(Base, BaseModel):
665 class UserToPerm(Base, BaseModel):
666 __tablename__ = 'user_to_perm'
666 __tablename__ = 'user_to_perm'
667 __table_args__ = (
667 __table_args__ = (
668 UniqueConstraint('user_id', 'permission_id'),
668 UniqueConstraint('user_id', 'permission_id'),
669 {'extend_existing': True, 'mysql_engine': 'InnoDB',
669 {'extend_existing': True, 'mysql_engine': 'InnoDB',
670 'mysql_charset': 'utf8'}
670 'mysql_charset': 'utf8'}
671 )
671 )
672 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
672 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
673 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
673 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
674 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
674 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
675
675
676 user = relationship('User')
676 user = relationship('User')
677 permission = relationship('Permission', lazy='joined')
677 permission = relationship('Permission', lazy='joined')
678
678
679
679
680 class UserGroupRepoToPerm(Base, BaseModel):
680 class UserGroupRepoToPerm(Base, BaseModel):
681 __tablename__ = 'users_group_repo_to_perm'
681 __tablename__ = 'users_group_repo_to_perm'
682 __table_args__ = (
682 __table_args__ = (
683 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
683 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
684 {'extend_existing': True, 'mysql_engine': 'InnoDB',
684 {'extend_existing': True, 'mysql_engine': 'InnoDB',
685 'mysql_charset': 'utf8'}
685 'mysql_charset': 'utf8'}
686 )
686 )
687 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
687 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
688 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
688 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
689 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
689 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
690 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
690 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
691
691
692 users_group = relationship('UserGroup')
692 users_group = relationship('UserGroup')
693 permission = relationship('Permission')
693 permission = relationship('Permission')
694 repository = relationship('Repository')
694 repository = relationship('Repository')
695
695
696 def __unicode__(self):
696 def __unicode__(self):
697 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
697 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
698
698
699
699
700 class UserGroupToPerm(Base, BaseModel):
700 class UserGroupToPerm(Base, BaseModel):
701 __tablename__ = 'users_group_to_perm'
701 __tablename__ = 'users_group_to_perm'
702 __table_args__ = (
702 __table_args__ = (
703 UniqueConstraint('users_group_id', 'permission_id',),
703 UniqueConstraint('users_group_id', 'permission_id',),
704 {'extend_existing': True, 'mysql_engine': 'InnoDB',
704 {'extend_existing': True, 'mysql_engine': 'InnoDB',
705 'mysql_charset': 'utf8'}
705 'mysql_charset': 'utf8'}
706 )
706 )
707 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
707 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
708 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
708 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
709 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
709 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
710
710
711 users_group = relationship('UserGroup')
711 users_group = relationship('UserGroup')
712 permission = relationship('Permission')
712 permission = relationship('Permission')
713
713
714
714
715 class UserRepoGroupToPerm(Base, BaseModel):
715 class UserRepoGroupToPerm(Base, BaseModel):
716 __tablename__ = 'user_repo_group_to_perm'
716 __tablename__ = 'user_repo_group_to_perm'
717 __table_args__ = (
717 __table_args__ = (
718 UniqueConstraint('user_id', 'group_id', 'permission_id'),
718 UniqueConstraint('user_id', 'group_id', 'permission_id'),
719 {'extend_existing': True, 'mysql_engine': 'InnoDB',
719 {'extend_existing': True, 'mysql_engine': 'InnoDB',
720 'mysql_charset': 'utf8'}
720 'mysql_charset': 'utf8'}
721 )
721 )
722
722
723 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
723 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
724 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
724 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
725 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
725 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
726 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
726 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
727
727
728 user = relationship('User')
728 user = relationship('User')
729 group = relationship('RepoGroup')
729 group = relationship('RepoGroup')
730 permission = relationship('Permission')
730 permission = relationship('Permission')
731
731
732
732
733 class UserGroupRepoGroupToPerm(Base, BaseModel):
733 class UserGroupRepoGroupToPerm(Base, BaseModel):
734 __tablename__ = 'users_group_repo_group_to_perm'
734 __tablename__ = 'users_group_repo_group_to_perm'
735 __table_args__ = (
735 __table_args__ = (
736 UniqueConstraint('users_group_id', 'group_id'),
736 UniqueConstraint('users_group_id', 'group_id'),
737 {'extend_existing': True, 'mysql_engine': 'InnoDB',
737 {'extend_existing': True, 'mysql_engine': 'InnoDB',
738 'mysql_charset': 'utf8'}
738 'mysql_charset': 'utf8'}
739 )
739 )
740
740
741 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)
741 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)
742 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
742 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
743 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
743 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
744 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
744 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
745
745
746 users_group = relationship('UserGroup')
746 users_group = relationship('UserGroup')
747 permission = relationship('Permission')
747 permission = relationship('Permission')
748 group = relationship('RepoGroup')
748 group = relationship('RepoGroup')
749
749
750
750
751 class Statistics(Base, BaseModel):
751 class Statistics(Base, BaseModel):
752 __tablename__ = 'statistics'
752 __tablename__ = 'statistics'
753 __table_args__ = (
753 __table_args__ = (
754 UniqueConstraint('repository_id'),
754 UniqueConstraint('repository_id'),
755 {'extend_existing': True, 'mysql_engine': 'InnoDB',
755 {'extend_existing': True, 'mysql_engine': 'InnoDB',
756 'mysql_charset': 'utf8'}
756 'mysql_charset': 'utf8'}
757 )
757 )
758 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
758 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
759 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
759 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
760 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
760 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
761 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
761 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
762 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
762 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
763 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
763 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
764
764
765 repository = relationship('Repository', single_parent=True)
765 repository = relationship('Repository', single_parent=True)
766
766
767
767
768 class UserFollowing(Base, BaseModel):
768 class UserFollowing(Base, BaseModel):
769 __tablename__ = 'user_followings'
769 __tablename__ = 'user_followings'
770 __table_args__ = (
770 __table_args__ = (
771 UniqueConstraint('user_id', 'follows_repository_id'),
771 UniqueConstraint('user_id', 'follows_repository_id'),
772 UniqueConstraint('user_id', 'follows_user_id'),
772 UniqueConstraint('user_id', 'follows_user_id'),
773 {'extend_existing': True, 'mysql_engine': 'InnoDB',
773 {'extend_existing': True, 'mysql_engine': 'InnoDB',
774 'mysql_charset': 'utf8'}
774 'mysql_charset': 'utf8'}
775 )
775 )
776
776
777 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
777 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
778 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
778 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
779 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
779 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
780 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
780 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
781 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
781 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
782
782
783 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
783 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
784
784
785 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
785 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
786 follows_repository = relationship('Repository', order_by='Repository.repo_name')
786 follows_repository = relationship('Repository', order_by='Repository.repo_name')
787
787
788
788
789 class CacheInvalidation(Base, BaseModel):
789 class CacheInvalidation(Base, BaseModel):
790 __tablename__ = 'cache_invalidation'
790 __tablename__ = 'cache_invalidation'
791 __table_args__ = (
791 __table_args__ = (
792 UniqueConstraint('cache_key'),
792 UniqueConstraint('cache_key'),
793 Index('key_idx', 'cache_key'),
793 Index('key_idx', 'cache_key'),
794 {'extend_existing': True, 'mysql_engine': 'InnoDB',
794 {'extend_existing': True, 'mysql_engine': 'InnoDB',
795 'mysql_charset': 'utf8'},
795 'mysql_charset': 'utf8'},
796 )
796 )
797 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
797 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
798 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
798 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
799 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
799 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
800 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
800 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
801
801
802 def __init__(self, cache_key, cache_args=''):
802 def __init__(self, cache_key, cache_args=''):
803 self.cache_key = cache_key
803 self.cache_key = cache_key
804 self.cache_args = cache_args
804 self.cache_args = cache_args
805 self.cache_active = False
805 self.cache_active = False
806
806
807
807
808 class ChangesetComment(Base, BaseModel):
808 class ChangesetComment(Base, BaseModel):
809 __tablename__ = 'changeset_comments'
809 __tablename__ = 'changeset_comments'
810 __table_args__ = (
810 __table_args__ = (
811 Index('cc_revision_idx', 'revision'),
811 Index('cc_revision_idx', 'revision'),
812 {'extend_existing': True, 'mysql_engine': 'InnoDB',
812 {'extend_existing': True, 'mysql_engine': 'InnoDB',
813 'mysql_charset': 'utf8'},
813 'mysql_charset': 'utf8'},
814 )
814 )
815 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
815 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
816 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
816 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
817 revision = Column('revision', String(40), nullable=True)
817 revision = Column('revision', String(40), nullable=True)
818 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
818 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
819 line_no = Column('line_no', Unicode(10), nullable=True)
819 line_no = Column('line_no', Unicode(10), nullable=True)
820 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
820 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
821 f_path = Column('f_path', Unicode(1000), nullable=True)
821 f_path = Column('f_path', Unicode(1000), nullable=True)
822 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
822 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
823 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
823 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
824 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
824 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
825 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
825 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
826
826
827 author = relationship('User', lazy='joined')
827 author = relationship('User', lazy='joined')
828 repo = relationship('Repository')
828 repo = relationship('Repository')
829 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
829 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
830 pull_request = relationship('PullRequest', lazy='joined')
830 pull_request = relationship('PullRequest', lazy='joined')
831
831
832 @classmethod
832 @classmethod
833 def get_users(cls, revision=None, pull_request_id=None):
833 def get_users(cls, revision=None, pull_request_id=None):
834 """
834 """
835 Returns user associated with this ChangesetComment. ie those
835 Returns user associated with this ChangesetComment. ie those
836 who actually commented
836 who actually commented
837
837
838 :param cls:
838 :param cls:
839 :param revision:
839 :param revision:
840 """
840 """
841 q = Session().query(User)\
841 q = Session().query(User)\
842 .join(ChangesetComment.author)
842 .join(ChangesetComment.author)
843 if revision:
843 if revision:
844 q = q.filter(cls.revision == revision)
844 q = q.filter(cls.revision == revision)
845 elif pull_request_id:
845 elif pull_request_id:
846 q = q.filter(cls.pull_request_id == pull_request_id)
846 q = q.filter(cls.pull_request_id == pull_request_id)
847 return q.all()
847 return q.all()
848
848
849
849
850 class ChangesetStatus(Base, BaseModel):
850 class ChangesetStatus(Base, BaseModel):
851 __tablename__ = 'changeset_statuses'
851 __tablename__ = 'changeset_statuses'
852 __table_args__ = (
852 __table_args__ = (
853 Index('cs_revision_idx', 'revision'),
853 Index('cs_revision_idx', 'revision'),
854 Index('cs_version_idx', 'version'),
854 Index('cs_version_idx', 'version'),
855 UniqueConstraint('repo_id', 'revision', 'version'),
855 UniqueConstraint('repo_id', 'revision', 'version'),
856 {'extend_existing': True, 'mysql_engine': 'InnoDB',
856 {'extend_existing': True, 'mysql_engine': 'InnoDB',
857 'mysql_charset': 'utf8'}
857 'mysql_charset': 'utf8'}
858 )
858 )
859 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
859 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
860 STATUS_APPROVED = 'approved'
860 STATUS_APPROVED = 'approved'
861 STATUS_REJECTED = 'rejected'
861 STATUS_REJECTED = 'rejected'
862 STATUS_UNDER_REVIEW = 'under_review'
862 STATUS_UNDER_REVIEW = 'under_review'
863
863
864 STATUSES = [
864 STATUSES = [
865 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
865 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
866 (STATUS_APPROVED, _("Approved")),
866 (STATUS_APPROVED, _("Approved")),
867 (STATUS_REJECTED, _("Rejected")),
867 (STATUS_REJECTED, _("Rejected")),
868 (STATUS_UNDER_REVIEW, _("Under Review")),
868 (STATUS_UNDER_REVIEW, _("Under Review")),
869 ]
869 ]
870
870
871 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
871 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
872 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
872 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
873 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
873 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
874 revision = Column('revision', String(40), nullable=False)
874 revision = Column('revision', String(40), nullable=False)
875 status = Column('status', String(128), nullable=False, default=DEFAULT)
875 status = Column('status', String(128), nullable=False, default=DEFAULT)
876 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
876 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
877 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
877 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
878 version = Column('version', Integer(), nullable=False, default=0)
878 version = Column('version', Integer(), nullable=False, default=0)
879 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
879 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
880
880
881 author = relationship('User', lazy='joined')
881 author = relationship('User', lazy='joined')
882 repo = relationship('Repository')
882 repo = relationship('Repository')
883 comment = relationship('ChangesetComment', lazy='joined')
883 comment = relationship('ChangesetComment', lazy='joined')
884 pull_request = relationship('PullRequest', lazy='joined')
884 pull_request = relationship('PullRequest', lazy='joined')
885
885
886
886
887
887
888 class PullRequest(Base, BaseModel):
888 class PullRequest(Base, BaseModel):
889 __tablename__ = 'pull_requests'
889 __tablename__ = 'pull_requests'
890 __table_args__ = (
890 __table_args__ = (
891 {'extend_existing': True, 'mysql_engine': 'InnoDB',
891 {'extend_existing': True, 'mysql_engine': 'InnoDB',
892 'mysql_charset': 'utf8'},
892 'mysql_charset': 'utf8'},
893 )
893 )
894
894
895 STATUS_NEW = u'new'
895 STATUS_NEW = u'new'
896 STATUS_OPEN = u'open'
896 STATUS_OPEN = u'open'
897 STATUS_CLOSED = u'closed'
897 STATUS_CLOSED = u'closed'
898
898
899 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
899 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
900 title = Column('title', Unicode(256), nullable=True)
900 title = Column('title', Unicode(256), nullable=True)
901 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
901 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
902 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
902 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
903 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
903 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
904 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
904 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
905 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
905 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
906 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
906 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
907 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
907 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
908 org_ref = Column('org_ref', Unicode(256), nullable=False)
908 org_ref = Column('org_ref', Unicode(256), nullable=False)
909 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
909 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
910 other_ref = Column('other_ref', Unicode(256), nullable=False)
910 other_ref = Column('other_ref', Unicode(256), nullable=False)
911
911
912 author = relationship('User', lazy='joined')
912 author = relationship('User', lazy='joined')
913 reviewers = relationship('PullRequestReviewers',
913 reviewers = relationship('PullRequestReviewers',
914 cascade="all, delete, delete-orphan")
914 cascade="all, delete, delete-orphan")
915 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
915 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
916 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
916 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
917 statuses = relationship('ChangesetStatus')
917 statuses = relationship('ChangesetStatus')
918 comments = relationship('ChangesetComment',
918 comments = relationship('ChangesetComment',
919 cascade="all, delete, delete-orphan")
919 cascade="all, delete, delete-orphan")
920
920
921
921
922 class PullRequestReviewers(Base, BaseModel):
922 class PullRequestReviewers(Base, BaseModel):
923 __tablename__ = 'pull_request_reviewers'
923 __tablename__ = 'pull_request_reviewers'
924 __table_args__ = (
924 __table_args__ = (
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
925 {'extend_existing': True, 'mysql_engine': 'InnoDB',
926 'mysql_charset': 'utf8'},
926 'mysql_charset': 'utf8'},
927 )
927 )
928
928
929 def __init__(self, user=None, pull_request=None):
929 def __init__(self, user=None, pull_request=None):
930 self.user = user
930 self.user = user
931 self.pull_request = pull_request
931 self.pull_request = pull_request
932
932
933 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
933 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
934 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
934 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
935 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
935 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
936
936
937 user = relationship('User')
937 user = relationship('User')
938 pull_request = relationship('PullRequest')
938 pull_request = relationship('PullRequest')
939
939
940
940
941 class Notification(Base, BaseModel):
941 class Notification(Base, BaseModel):
942 __tablename__ = 'notifications'
942 __tablename__ = 'notifications'
943 __table_args__ = (
943 __table_args__ = (
944 Index('notification_type_idx', 'type'),
944 Index('notification_type_idx', 'type'),
945 {'extend_existing': True, 'mysql_engine': 'InnoDB',
945 {'extend_existing': True, 'mysql_engine': 'InnoDB',
946 'mysql_charset': 'utf8'},
946 'mysql_charset': 'utf8'},
947 )
947 )
948
948
949 TYPE_CHANGESET_COMMENT = u'cs_comment'
949 TYPE_CHANGESET_COMMENT = u'cs_comment'
950 TYPE_MESSAGE = u'message'
950 TYPE_MESSAGE = u'message'
951 TYPE_MENTION = u'mention'
951 TYPE_MENTION = u'mention'
952 TYPE_REGISTRATION = u'registration'
952 TYPE_REGISTRATION = u'registration'
953 TYPE_PULL_REQUEST = u'pull_request'
953 TYPE_PULL_REQUEST = u'pull_request'
954 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
954 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
955
955
956 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
956 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
957 subject = Column('subject', Unicode(512), nullable=True)
957 subject = Column('subject', Unicode(512), nullable=True)
958 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
958 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
959 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
959 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
960 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
960 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
961 type_ = Column('type', Unicode(256))
961 type_ = Column('type', Unicode(256))
962
962
963 created_by_user = relationship('User')
963 created_by_user = relationship('User')
964 notifications_to_users = relationship('UserNotification', lazy='joined',
964 notifications_to_users = relationship('UserNotification', lazy='joined',
965 cascade="all, delete, delete-orphan")
965 cascade="all, delete, delete-orphan")
966
966
967
967
968 class UserNotification(Base, BaseModel):
968 class UserNotification(Base, BaseModel):
969 __tablename__ = 'user_to_notification'
969 __tablename__ = 'user_to_notification'
970 __table_args__ = (
970 __table_args__ = (
971 UniqueConstraint('user_id', 'notification_id'),
971 UniqueConstraint('user_id', 'notification_id'),
972 {'extend_existing': True, 'mysql_engine': 'InnoDB',
972 {'extend_existing': True, 'mysql_engine': 'InnoDB',
973 'mysql_charset': 'utf8'}
973 'mysql_charset': 'utf8'}
974 )
974 )
975 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
975 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
976 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
976 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
977 read = Column('read', Boolean, default=False)
977 read = Column('read', Boolean, default=False)
978 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
978 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
979
979
980 user = relationship('User', lazy="joined")
980 user = relationship('User', lazy="joined")
981 notification = relationship('Notification', lazy="joined",
981 notification = relationship('Notification', lazy="joined",
982 order_by=lambda: Notification.created_on.desc(),)
982 order_by=lambda: Notification.created_on.desc(),)
983
983
984
984
985 class DbMigrateVersion(Base, BaseModel):
985 class DbMigrateVersion(Base, BaseModel):
986 __tablename__ = 'db_migrate_version'
986 __tablename__ = 'db_migrate_version'
987 __table_args__ = (
987 __table_args__ = (
988 {'extend_existing': True, 'mysql_engine': 'InnoDB',
988 {'extend_existing': True, 'mysql_engine': 'InnoDB',
989 'mysql_charset': 'utf8'},
989 'mysql_charset': 'utf8'},
990 )
990 )
991 repository_id = Column('repository_id', String(250), primary_key=True)
991 repository_id = Column('repository_id', String(250), primary_key=True)
992 repository_path = Column('repository_path', Text)
992 repository_path = Column('repository_path', Text)
993 version = Column('version', Integer)
993 version = Column('version', Integer)
@@ -1,1002 +1,1002 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
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 pylons.i18n.translation import lazy_ugettext as _
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 safe_unicode, remove_suffix, remove_prefix
45 safe_unicode, remove_suffix, remove_prefix
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.iteritems():
86 for k, val in _json_attr.iteritems():
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 __tablename__ = 'rhodecode_settings'
149 __tablename__ = 'rhodecode_settings'
150 __table_args__ = (
150 __table_args__ = (
151 UniqueConstraint('app_settings_name'),
151 UniqueConstraint('app_settings_name'),
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
153 'mysql_charset': 'utf8'}
153 'mysql_charset': 'utf8'}
154 )
154 )
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
158
158
159 def __init__(self, k='', v=''):
159 def __init__(self, k='', v=''):
160 self.app_settings_name = k
160 self.app_settings_name = k
161 self.app_settings_value = v
161 self.app_settings_value = v
162
162
163 @validates('_app_settings_value')
163 @validates('_app_settings_value')
164 def validate_settings_value(self, key, val):
164 def validate_settings_value(self, key, val):
165 assert type(val) == unicode
165 assert type(val) == unicode
166 return val
166 return val
167
167
168 @hybrid_property
168 @hybrid_property
169 def app_settings_value(self):
169 def app_settings_value(self):
170 v = self._app_settings_value
170 v = self._app_settings_value
171 if self.app_settings_name in ["ldap_active",
171 if self.app_settings_name in ["ldap_active",
172 "default_repo_enable_statistics",
172 "default_repo_enable_statistics",
173 "default_repo_enable_locking",
173 "default_repo_enable_locking",
174 "default_repo_private",
174 "default_repo_private",
175 "default_repo_enable_downloads"]:
175 "default_repo_enable_downloads"]:
176 v = str2bool(v)
176 v = str2bool(v)
177 return v
177 return v
178
178
179 @app_settings_value.setter
179 @app_settings_value.setter
180 def app_settings_value(self, val):
180 def app_settings_value(self, val):
181 """
181 """
182 Setter that will always make sure we use unicode in app_settings_value
182 Setter that will always make sure we use unicode in app_settings_value
183
183
184 :param val:
184 :param val:
185 """
185 """
186 self._app_settings_value = safe_unicode(val)
186 self._app_settings_value = safe_unicode(val)
187
187
188 def __unicode__(self):
188 def __unicode__(self):
189 return u"<%s('%s:%s')>" % (
189 return u"<%s('%s:%s')>" % (
190 self.__class__.__name__,
190 self.__class__.__name__,
191 self.app_settings_name, self.app_settings_value
191 self.app_settings_name, self.app_settings_value
192 )
192 )
193
193
194
194
195 class RhodeCodeUi(Base, BaseModel):
195 class RhodeCodeUi(Base, BaseModel):
196 __tablename__ = 'rhodecode_ui'
196 __tablename__ = 'rhodecode_ui'
197 __table_args__ = (
197 __table_args__ = (
198 UniqueConstraint('ui_key'),
198 UniqueConstraint('ui_key'),
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
200 'mysql_charset': 'utf8'}
200 'mysql_charset': 'utf8'}
201 )
201 )
202
202
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
204 HOOK_PUSH = 'changegroup.push_logger'
204 HOOK_PUSH = 'changegroup.push_logger'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
206 HOOK_PULL = 'outgoing.pull_logger'
206 HOOK_PULL = 'outgoing.pull_logger'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
208
208
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
214
214
215
215
216
216
217 class User(Base, BaseModel):
217 class User(Base, BaseModel):
218 __tablename__ = 'users'
218 __tablename__ = 'users'
219 __table_args__ = (
219 __table_args__ = (
220 UniqueConstraint('username'), UniqueConstraint('email'),
220 UniqueConstraint('username'), UniqueConstraint('email'),
221 Index('u_username_idx', 'username'),
221 Index('u_username_idx', 'username'),
222 Index('u_email_idx', 'email'),
222 Index('u_email_idx', 'email'),
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
224 'mysql_charset': 'utf8'}
224 'mysql_charset': 'utf8'}
225 )
225 )
226 DEFAULT_USER = 'default'
226 DEFAULT_USER = 'default'
227 DEFAULT_PERMISSIONS = [
227 DEFAULT_PERMISSIONS = [
228 'hg.register.manual_activate', 'hg.create.repository',
228 'hg.register.manual_activate', 'hg.create.repository',
229 'hg.fork.repository', 'repository.read', 'group.read'
229 'hg.fork.repository', 'repository.read', 'group.read'
230 ]
230 ]
231 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
231 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 username = Column("username", String(255), nullable=True, unique=None, default=None)
232 username = Column("username", String(255), nullable=True, unique=None, default=None)
233 password = Column("password", String(255), nullable=True, unique=None, default=None)
233 password = Column("password", String(255), nullable=True, unique=None, default=None)
234 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
234 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
235 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
235 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
236 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
236 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
237 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
237 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
238 _email = Column("email", String(255), nullable=True, unique=None, default=None)
238 _email = Column("email", String(255), nullable=True, unique=None, default=None)
239 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
239 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
240 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
240 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
241 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
241 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
242 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
242 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
243
243
244 user_log = relationship('UserLog')
244 user_log = relationship('UserLog')
245 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
245 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
246
246
247 repositories = relationship('Repository')
247 repositories = relationship('Repository')
248 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
248 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
249 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
249 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
250
250
251 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
251 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
252 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
252 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
253
253
254 group_member = relationship('UserGroupMember', cascade='all')
254 group_member = relationship('UserGroupMember', cascade='all')
255
255
256 notifications = relationship('UserNotification', cascade='all')
256 notifications = relationship('UserNotification', cascade='all')
257 # notifications assigned to this user
257 # notifications assigned to this user
258 user_created_notifications = relationship('Notification', cascade='all')
258 user_created_notifications = relationship('Notification', cascade='all')
259 # comments created by this user
259 # comments created by this user
260 user_comments = relationship('ChangesetComment', cascade='all')
260 user_comments = relationship('ChangesetComment', cascade='all')
261 user_emails = relationship('UserEmailMap', cascade='all')
261 user_emails = relationship('UserEmailMap', cascade='all')
262
262
263 @hybrid_property
263 @hybrid_property
264 def email(self):
264 def email(self):
265 return self._email
265 return self._email
266
266
267 @email.setter
267 @email.setter
268 def email(self, val):
268 def email(self, val):
269 self._email = val.lower() if val else None
269 self._email = val.lower() if val else None
270
270
271 @property
271 @property
272 def firstname(self):
272 def firstname(self):
273 # alias for future
273 # alias for future
274 return self.name
274 return self.name
275
275
276 @property
276 @property
277 def username_and_name(self):
277 def username_and_name(self):
278 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
278 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
279
279
280 @property
280 @property
281 def full_name(self):
281 def full_name(self):
282 return '%s %s' % (self.firstname, self.lastname)
282 return '%s %s' % (self.firstname, self.lastname)
283
283
284 @property
284 @property
285 def full_contact(self):
285 def full_contact(self):
286 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
286 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
287
287
288 @property
288 @property
289 def short_contact(self):
289 def short_contact(self):
290 return '%s %s' % (self.firstname, self.lastname)
290 return '%s %s' % (self.firstname, self.lastname)
291
291
292 @property
292 @property
293 def is_admin(self):
293 def is_admin(self):
294 return self.admin
294 return self.admin
295
295
296 @classmethod
296 @classmethod
297 def get_by_username(cls, username, case_insensitive=False, cache=False):
297 def get_by_username(cls, username, case_insensitive=False, cache=False):
298 if case_insensitive:
298 if case_insensitive:
299 q = cls.query().filter(cls.username.ilike(username))
299 q = cls.query().filter(cls.username.ilike(username))
300 else:
300 else:
301 q = cls.query().filter(cls.username == username)
301 q = cls.query().filter(cls.username == username)
302
302
303 if cache:
303 if cache:
304 q = q.options(FromCache(
304 q = q.options(FromCache(
305 "sql_cache_short",
305 "sql_cache_short",
306 "get_user_%s" % _hash_key(username)
306 "get_user_%s" % _hash_key(username)
307 )
307 )
308 )
308 )
309 return q.scalar()
309 return q.scalar()
310
310
311 @classmethod
311 @classmethod
312 def get_by_auth_token(cls, auth_token, cache=False):
312 def get_by_auth_token(cls, auth_token, cache=False):
313 q = cls.query().filter(cls.api_key == auth_token)
313 q = cls.query().filter(cls.api_key == auth_token)
314
314
315 if cache:
315 if cache:
316 q = q.options(FromCache("sql_cache_short",
316 q = q.options(FromCache("sql_cache_short",
317 "get_auth_token_%s" % auth_token))
317 "get_auth_token_%s" % auth_token))
318 return q.scalar()
318 return q.scalar()
319
319
320 @classmethod
320 @classmethod
321 def get_by_email(cls, email, case_insensitive=False, cache=False):
321 def get_by_email(cls, email, case_insensitive=False, cache=False):
322 if case_insensitive:
322 if case_insensitive:
323 q = cls.query().filter(cls.email.ilike(email))
323 q = cls.query().filter(cls.email.ilike(email))
324 else:
324 else:
325 q = cls.query().filter(cls.email == email)
325 q = cls.query().filter(cls.email == email)
326
326
327 if cache:
327 if cache:
328 q = q.options(FromCache("sql_cache_short",
328 q = q.options(FromCache("sql_cache_short",
329 "get_email_key_%s" % email))
329 "get_email_key_%s" % email))
330
330
331 ret = q.scalar()
331 ret = q.scalar()
332 if ret is None:
332 if ret is None:
333 q = UserEmailMap.query()
333 q = UserEmailMap.query()
334 # try fetching in alternate email map
334 # try fetching in alternate email map
335 if case_insensitive:
335 if case_insensitive:
336 q = q.filter(UserEmailMap.email.ilike(email))
336 q = q.filter(UserEmailMap.email.ilike(email))
337 else:
337 else:
338 q = q.filter(UserEmailMap.email == email)
338 q = q.filter(UserEmailMap.email == email)
339 q = q.options(joinedload(UserEmailMap.user))
339 q = q.options(joinedload(UserEmailMap.user))
340 if cache:
340 if cache:
341 q = q.options(FromCache("sql_cache_short",
341 q = q.options(FromCache("sql_cache_short",
342 "get_email_map_key_%s" % email))
342 "get_email_map_key_%s" % email))
343 ret = getattr(q.scalar(), 'user', None)
343 ret = getattr(q.scalar(), 'user', None)
344
344
345 return ret
345 return ret
346
346
347
347
348 class UserEmailMap(Base, BaseModel):
348 class UserEmailMap(Base, BaseModel):
349 __tablename__ = 'user_email_map'
349 __tablename__ = 'user_email_map'
350 __table_args__ = (
350 __table_args__ = (
351 Index('uem_email_idx', 'email'),
351 Index('uem_email_idx', 'email'),
352 UniqueConstraint('email'),
352 UniqueConstraint('email'),
353 {'extend_existing': True, 'mysql_engine': 'InnoDB',
353 {'extend_existing': True, 'mysql_engine': 'InnoDB',
354 'mysql_charset': 'utf8'}
354 'mysql_charset': 'utf8'}
355 )
355 )
356 __mapper_args__ = {}
356 __mapper_args__ = {}
357
357
358 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
358 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
359 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
359 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
360 _email = Column("email", String(255), nullable=True, unique=False, default=None)
360 _email = Column("email", String(255), nullable=True, unique=False, default=None)
361 user = relationship('User', lazy='joined')
361 user = relationship('User', lazy='joined')
362
362
363 @validates('_email')
363 @validates('_email')
364 def validate_email(self, key, email):
364 def validate_email(self, key, email):
365 # check if this email is not main one
365 # check if this email is not main one
366 main_email = Session().query(User).filter(User.email == email).scalar()
366 main_email = Session().query(User).filter(User.email == email).scalar()
367 if main_email is not None:
367 if main_email is not None:
368 raise AttributeError('email %s is present is user table' % email)
368 raise AttributeError('email %s is present is user table' % email)
369 return email
369 return email
370
370
371 @hybrid_property
371 @hybrid_property
372 def email(self):
372 def email(self):
373 return self._email
373 return self._email
374
374
375 @email.setter
375 @email.setter
376 def email(self, val):
376 def email(self, val):
377 self._email = val.lower() if val else None
377 self._email = val.lower() if val else None
378
378
379
379
380 class UserIpMap(Base, BaseModel):
380 class UserIpMap(Base, BaseModel):
381 __tablename__ = 'user_ip_map'
381 __tablename__ = 'user_ip_map'
382 __table_args__ = (
382 __table_args__ = (
383 UniqueConstraint('user_id', 'ip_addr'),
383 UniqueConstraint('user_id', 'ip_addr'),
384 {'extend_existing': True, 'mysql_engine': 'InnoDB',
384 {'extend_existing': True, 'mysql_engine': 'InnoDB',
385 'mysql_charset': 'utf8'}
385 'mysql_charset': 'utf8'}
386 )
386 )
387 __mapper_args__ = {}
387 __mapper_args__ = {}
388
388
389 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
389 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
390 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
390 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
391 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
391 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
392 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
392 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
393 user = relationship('User', lazy='joined')
393 user = relationship('User', lazy='joined')
394
394
395
395
396 class UserLog(Base, BaseModel):
396 class UserLog(Base, BaseModel):
397 __tablename__ = 'user_logs'
397 __tablename__ = 'user_logs'
398 __table_args__ = (
398 __table_args__ = (
399 {'extend_existing': True, 'mysql_engine': 'InnoDB',
399 {'extend_existing': True, 'mysql_engine': 'InnoDB',
400 'mysql_charset': 'utf8'},
400 'mysql_charset': 'utf8'},
401 )
401 )
402 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
402 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
403 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
403 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
404 username = Column("username", String(255), nullable=True, unique=None, default=None)
404 username = Column("username", String(255), nullable=True, unique=None, default=None)
405 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
405 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
406 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
406 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
407 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
407 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
408 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
408 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
409 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
409 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
410
410
411
411
412 user = relationship('User')
412 user = relationship('User')
413 repository = relationship('Repository', cascade='')
413 repository = relationship('Repository', cascade='')
414
414
415
415
416 class UserGroup(Base, BaseModel):
416 class UserGroup(Base, BaseModel):
417 __tablename__ = 'users_groups'
417 __tablename__ = 'users_groups'
418 __table_args__ = (
418 __table_args__ = (
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
420 'mysql_charset': 'utf8'},
420 'mysql_charset': 'utf8'},
421 )
421 )
422
422
423 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
423 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
424 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
425 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
425 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
426 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
426 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
427
427
428 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
428 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
429 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
429 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
430 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
430 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
431
431
432 def __unicode__(self):
432 def __unicode__(self):
433 return u'<userGroup(%s)>' % (self.users_group_name)
433 return u'<userGroup(%s)>' % (self.users_group_name)
434
434
435 @classmethod
435 @classmethod
436 def get_by_group_name(cls, group_name, cache=False,
436 def get_by_group_name(cls, group_name, cache=False,
437 case_insensitive=False):
437 case_insensitive=False):
438 if case_insensitive:
438 if case_insensitive:
439 q = cls.query().filter(cls.users_group_name.ilike(group_name))
439 q = cls.query().filter(cls.users_group_name.ilike(group_name))
440 else:
440 else:
441 q = cls.query().filter(cls.users_group_name == group_name)
441 q = cls.query().filter(cls.users_group_name == group_name)
442 if cache:
442 if cache:
443 q = q.options(FromCache(
443 q = q.options(FromCache(
444 "sql_cache_short",
444 "sql_cache_short",
445 "get_user_%s" % _hash_key(group_name)
445 "get_user_%s" % _hash_key(group_name)
446 )
446 )
447 )
447 )
448 return q.scalar()
448 return q.scalar()
449
449
450 @classmethod
450 @classmethod
451 def get(cls, users_group_id, cache=False):
451 def get(cls, users_group_id, cache=False):
452 user_group = cls.query()
452 user_group = cls.query()
453 if cache:
453 if cache:
454 user_group = user_group.options(FromCache("sql_cache_short",
454 user_group = user_group.options(FromCache("sql_cache_short",
455 "get_users_group_%s" % users_group_id))
455 "get_users_group_%s" % users_group_id))
456 return user_group.get(users_group_id)
456 return user_group.get(users_group_id)
457
457
458
458
459 class UserGroupMember(Base, BaseModel):
459 class UserGroupMember(Base, BaseModel):
460 __tablename__ = 'users_groups_members'
460 __tablename__ = 'users_groups_members'
461 __table_args__ = (
461 __table_args__ = (
462 {'extend_existing': True, 'mysql_engine': 'InnoDB',
462 {'extend_existing': True, 'mysql_engine': 'InnoDB',
463 'mysql_charset': 'utf8'},
463 'mysql_charset': 'utf8'},
464 )
464 )
465
465
466 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
466 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
467 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
467 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
468 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
468 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
469
469
470 user = relationship('User', lazy='joined')
470 user = relationship('User', lazy='joined')
471 users_group = relationship('UserGroup')
471 users_group = relationship('UserGroup')
472
472
473 def __init__(self, gr_id='', u_id=''):
473 def __init__(self, gr_id='', u_id=''):
474 self.users_group_id = gr_id
474 self.users_group_id = gr_id
475 self.user_id = u_id
475 self.user_id = u_id
476
476
477
477
478 class Repository(Base, BaseModel):
478 class Repository(Base, BaseModel):
479 __tablename__ = 'repositories'
479 __tablename__ = 'repositories'
480 __table_args__ = (
480 __table_args__ = (
481 UniqueConstraint('repo_name'),
481 UniqueConstraint('repo_name'),
482 Index('r_repo_name_idx', 'repo_name'),
482 Index('r_repo_name_idx', 'repo_name'),
483 {'extend_existing': True, 'mysql_engine': 'InnoDB',
483 {'extend_existing': True, 'mysql_engine': 'InnoDB',
484 'mysql_charset': 'utf8'},
484 'mysql_charset': 'utf8'},
485 )
485 )
486
486
487 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
487 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
488 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
488 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
489 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
489 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
490 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
490 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
491 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
491 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
492 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
492 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
493 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
493 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
494 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
494 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
495 description = Column("description", String(10000), nullable=True, unique=None, default=None)
495 description = Column("description", String(10000), nullable=True, unique=None, default=None)
496 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
496 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
497 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
497 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
498 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
498 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
499 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
499 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
500 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
500 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
501 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
501 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
502
502
503 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
503 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
504 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
504 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
505
505
506 user = relationship('User')
506 user = relationship('User')
507 fork = relationship('Repository', remote_side=repo_id)
507 fork = relationship('Repository', remote_side=repo_id)
508 group = relationship('RepoGroup')
508 group = relationship('RepoGroup')
509 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
509 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
510 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
510 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
511 stats = relationship('Statistics', cascade='all', uselist=False)
511 stats = relationship('Statistics', cascade='all', uselist=False)
512
512
513 followers = relationship('UserFollowing',
513 followers = relationship('UserFollowing',
514 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
514 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
515 cascade='all')
515 cascade='all')
516
516
517 logs = relationship('UserLog')
517 logs = relationship('UserLog')
518 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
518 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
519
519
520 pull_requests_org = relationship('PullRequest',
520 pull_requests_org = relationship('PullRequest',
521 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
521 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
522 cascade="all, delete, delete-orphan")
522 cascade="all, delete, delete-orphan")
523
523
524 pull_requests_other = relationship('PullRequest',
524 pull_requests_other = relationship('PullRequest',
525 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
525 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
526 cascade="all, delete, delete-orphan")
526 cascade="all, delete, delete-orphan")
527
527
528 def __unicode__(self):
528 def __unicode__(self):
529 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
529 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
530 safe_unicode(self.repo_name))
530 safe_unicode(self.repo_name))
531
531
532
532
533 @classmethod
533 @classmethod
534 def get_by_repo_name(cls, repo_name):
534 def get_by_repo_name(cls, repo_name):
535 q = Session().query(cls).filter(cls.repo_name == repo_name)
535 q = Session().query(cls).filter(cls.repo_name == repo_name)
536 q = q.options(joinedload(Repository.fork))\
536 q = q.options(joinedload(Repository.fork))\
537 .options(joinedload(Repository.user))\
537 .options(joinedload(Repository.user))\
538 .options(joinedload(Repository.group))
538 .options(joinedload(Repository.group))
539 return q.scalar()
539 return q.scalar()
540
540
541
541
542 class RepoGroup(Base, BaseModel):
542 class RepoGroup(Base, BaseModel):
543 __tablename__ = 'groups'
543 __tablename__ = 'groups'
544 __table_args__ = (
544 __table_args__ = (
545 UniqueConstraint('group_name', 'group_parent_id'),
545 UniqueConstraint('group_name', 'group_parent_id'),
546 CheckConstraint('group_id != group_parent_id'),
546 CheckConstraint('group_id != group_parent_id'),
547 {'extend_existing': True, 'mysql_engine': 'InnoDB',
547 {'extend_existing': True, 'mysql_engine': 'InnoDB',
548 'mysql_charset': 'utf8'},
548 'mysql_charset': 'utf8'},
549 )
549 )
550 __mapper_args__ = {'order_by': 'group_name'}
550 __mapper_args__ = {'order_by': 'group_name'}
551
551
552 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
552 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
553 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
553 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
554 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
554 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
555 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
555 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
556 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
556 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
557
557
558 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
558 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
559 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
559 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
560 parent_group = relationship('RepoGroup', remote_side=group_id)
560 parent_group = relationship('RepoGroup', remote_side=group_id)
561
561
562 def __init__(self, group_name='', parent_group=None):
562 def __init__(self, group_name='', parent_group=None):
563 self.group_name = group_name
563 self.group_name = group_name
564 self.parent_group = parent_group
564 self.parent_group = parent_group
565
565
566 def __unicode__(self):
566 def __unicode__(self):
567 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
567 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
568 self.group_name)
568 self.group_name)
569
569
570 @classmethod
570 @classmethod
571 def url_sep(cls):
571 def url_sep(cls):
572 return URL_SEP
572 return URL_SEP
573
573
574 @classmethod
574 @classmethod
575 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
575 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
576 if case_insensitive:
576 if case_insensitive:
577 gr = cls.query()\
577 gr = cls.query()\
578 .filter(cls.group_name.ilike(group_name))
578 .filter(cls.group_name.ilike(group_name))
579 else:
579 else:
580 gr = cls.query()\
580 gr = cls.query()\
581 .filter(cls.group_name == group_name)
581 .filter(cls.group_name == group_name)
582 if cache:
582 if cache:
583 gr = gr.options(FromCache(
583 gr = gr.options(FromCache(
584 "sql_cache_short",
584 "sql_cache_short",
585 "get_group_%s" % _hash_key(group_name)
585 "get_group_%s" % _hash_key(group_name)
586 )
586 )
587 )
587 )
588 return gr.scalar()
588 return gr.scalar()
589
589
590
590
591 class Permission(Base, BaseModel):
591 class Permission(Base, BaseModel):
592 __tablename__ = 'permissions'
592 __tablename__ = 'permissions'
593 __table_args__ = (
593 __table_args__ = (
594 Index('p_perm_name_idx', 'permission_name'),
594 Index('p_perm_name_idx', 'permission_name'),
595 {'extend_existing': True, 'mysql_engine': 'InnoDB',
595 {'extend_existing': True, 'mysql_engine': 'InnoDB',
596 'mysql_charset': 'utf8'},
596 'mysql_charset': 'utf8'},
597 )
597 )
598 PERMS = [
598 PERMS = [
599 ('repository.none', _('Repository no access')),
599 ('repository.none', _('Repository no access')),
600 ('repository.read', _('Repository read access')),
600 ('repository.read', _('Repository read access')),
601 ('repository.write', _('Repository write access')),
601 ('repository.write', _('Repository write access')),
602 ('repository.admin', _('Repository admin access')),
602 ('repository.admin', _('Repository admin access')),
603
603
604 ('group.none', _('Repositories Group no access')),
604 ('group.none', _('Repositories Group no access')),
605 ('group.read', _('Repositories Group read access')),
605 ('group.read', _('Repositories Group read access')),
606 ('group.write', _('Repositories Group write access')),
606 ('group.write', _('Repositories Group write access')),
607 ('group.admin', _('Repositories Group admin access')),
607 ('group.admin', _('Repositories Group admin access')),
608
608
609 ('hg.admin', _('RhodeCode Administrator')),
609 ('hg.admin', _('RhodeCode Administrator')),
610 ('hg.create.none', _('Repository creation disabled')),
610 ('hg.create.none', _('Repository creation disabled')),
611 ('hg.create.repository', _('Repository creation enabled')),
611 ('hg.create.repository', _('Repository creation enabled')),
612 ('hg.fork.none', _('Repository forking disabled')),
612 ('hg.fork.none', _('Repository forking disabled')),
613 ('hg.fork.repository', _('Repository forking enabled')),
613 ('hg.fork.repository', _('Repository forking enabled')),
614 ('hg.register.none', _('Register disabled')),
614 ('hg.register.none', _('Register disabled')),
615 ('hg.register.manual_activate', _('Register new user with RhodeCode '
615 ('hg.register.manual_activate', _('Register new user with RhodeCode '
616 'with manual activation')),
616 'with manual activation')),
617
617
618 ('hg.register.auto_activate', _('Register new user with RhodeCode '
618 ('hg.register.auto_activate', _('Register new user with RhodeCode '
619 'with auto activation')),
619 'with auto activation')),
620 ]
620 ]
621
621
622 # defines which permissions are more important higher the more important
622 # defines which permissions are more important higher the more important
623 PERM_WEIGHTS = {
623 PERM_WEIGHTS = {
624 'repository.none': 0,
624 'repository.none': 0,
625 'repository.read': 1,
625 'repository.read': 1,
626 'repository.write': 3,
626 'repository.write': 3,
627 'repository.admin': 4,
627 'repository.admin': 4,
628
628
629 'group.none': 0,
629 'group.none': 0,
630 'group.read': 1,
630 'group.read': 1,
631 'group.write': 3,
631 'group.write': 3,
632 'group.admin': 4,
632 'group.admin': 4,
633
633
634 'hg.fork.none': 0,
634 'hg.fork.none': 0,
635 'hg.fork.repository': 1,
635 'hg.fork.repository': 1,
636 'hg.create.none': 0,
636 'hg.create.none': 0,
637 'hg.create.repository':1
637 'hg.create.repository':1
638 }
638 }
639
639
640 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
640 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
641 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
641 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
642 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
642 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
643
643
644 def __unicode__(self):
644 def __unicode__(self):
645 return u"<%s('%s:%s')>" % (
645 return u"<%s('%s:%s')>" % (
646 self.__class__.__name__, self.permission_id, self.permission_name
646 self.__class__.__name__, self.permission_id, self.permission_name
647 )
647 )
648
648
649 @classmethod
649 @classmethod
650 def get_by_key(cls, key):
650 def get_by_key(cls, key):
651 return cls.query().filter(cls.permission_name == key).scalar()
651 return cls.query().filter(cls.permission_name == key).scalar()
652
652
653
653
654 class UserRepoToPerm(Base, BaseModel):
654 class UserRepoToPerm(Base, BaseModel):
655 __tablename__ = 'repo_to_perm'
655 __tablename__ = 'repo_to_perm'
656 __table_args__ = (
656 __table_args__ = (
657 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
657 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
658 {'extend_existing': True, 'mysql_engine': 'InnoDB',
658 {'extend_existing': True, 'mysql_engine': 'InnoDB',
659 'mysql_charset': 'utf8'}
659 'mysql_charset': 'utf8'}
660 )
660 )
661 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
661 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
662 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
662 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
663 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
663 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
664 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
664 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
665
665
666 user = relationship('User')
666 user = relationship('User')
667 repository = relationship('Repository')
667 repository = relationship('Repository')
668 permission = relationship('Permission')
668 permission = relationship('Permission')
669
669
670 def __unicode__(self):
670 def __unicode__(self):
671 return u'<user:%s => %s >' % (self.user, self.repository)
671 return u'<user:%s => %s >' % (self.user, self.repository)
672
672
673
673
674 class UserToPerm(Base, BaseModel):
674 class UserToPerm(Base, BaseModel):
675 __tablename__ = 'user_to_perm'
675 __tablename__ = 'user_to_perm'
676 __table_args__ = (
676 __table_args__ = (
677 UniqueConstraint('user_id', 'permission_id'),
677 UniqueConstraint('user_id', 'permission_id'),
678 {'extend_existing': True, 'mysql_engine': 'InnoDB',
678 {'extend_existing': True, 'mysql_engine': 'InnoDB',
679 'mysql_charset': 'utf8'}
679 'mysql_charset': 'utf8'}
680 )
680 )
681 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
681 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
682 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
682 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
683 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
683 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
684
684
685 user = relationship('User')
685 user = relationship('User')
686 permission = relationship('Permission', lazy='joined')
686 permission = relationship('Permission', lazy='joined')
687
687
688
688
689 class UserGroupRepoToPerm(Base, BaseModel):
689 class UserGroupRepoToPerm(Base, BaseModel):
690 __tablename__ = 'users_group_repo_to_perm'
690 __tablename__ = 'users_group_repo_to_perm'
691 __table_args__ = (
691 __table_args__ = (
692 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
692 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
693 {'extend_existing': True, 'mysql_engine': 'InnoDB',
693 {'extend_existing': True, 'mysql_engine': 'InnoDB',
694 'mysql_charset': 'utf8'}
694 'mysql_charset': 'utf8'}
695 )
695 )
696 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
696 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
697 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
697 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
698 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
698 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
699 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
699 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
700
700
701 users_group = relationship('UserGroup')
701 users_group = relationship('UserGroup')
702 permission = relationship('Permission')
702 permission = relationship('Permission')
703 repository = relationship('Repository')
703 repository = relationship('Repository')
704
704
705 def __unicode__(self):
705 def __unicode__(self):
706 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
706 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
707
707
708
708
709 class UserGroupToPerm(Base, BaseModel):
709 class UserGroupToPerm(Base, BaseModel):
710 __tablename__ = 'users_group_to_perm'
710 __tablename__ = 'users_group_to_perm'
711 __table_args__ = (
711 __table_args__ = (
712 UniqueConstraint('users_group_id', 'permission_id',),
712 UniqueConstraint('users_group_id', 'permission_id',),
713 {'extend_existing': True, 'mysql_engine': 'InnoDB',
713 {'extend_existing': True, 'mysql_engine': 'InnoDB',
714 'mysql_charset': 'utf8'}
714 'mysql_charset': 'utf8'}
715 )
715 )
716 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
716 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
717 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
717 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
718 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
718 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
719
719
720 users_group = relationship('UserGroup')
720 users_group = relationship('UserGroup')
721 permission = relationship('Permission')
721 permission = relationship('Permission')
722
722
723
723
724 class UserRepoGroupToPerm(Base, BaseModel):
724 class UserRepoGroupToPerm(Base, BaseModel):
725 __tablename__ = 'user_repo_group_to_perm'
725 __tablename__ = 'user_repo_group_to_perm'
726 __table_args__ = (
726 __table_args__ = (
727 UniqueConstraint('user_id', 'group_id', 'permission_id'),
727 UniqueConstraint('user_id', 'group_id', 'permission_id'),
728 {'extend_existing': True, 'mysql_engine': 'InnoDB',
728 {'extend_existing': True, 'mysql_engine': 'InnoDB',
729 'mysql_charset': 'utf8'}
729 'mysql_charset': 'utf8'}
730 )
730 )
731
731
732 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
732 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
733 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
733 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
734 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
734 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
735 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
735 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
736
736
737 user = relationship('User')
737 user = relationship('User')
738 group = relationship('RepoGroup')
738 group = relationship('RepoGroup')
739 permission = relationship('Permission')
739 permission = relationship('Permission')
740
740
741
741
742 class UserGroupRepoGroupToPerm(Base, BaseModel):
742 class UserGroupRepoGroupToPerm(Base, BaseModel):
743 __tablename__ = 'users_group_repo_group_to_perm'
743 __tablename__ = 'users_group_repo_group_to_perm'
744 __table_args__ = (
744 __table_args__ = (
745 UniqueConstraint('users_group_id', 'group_id'),
745 UniqueConstraint('users_group_id', 'group_id'),
746 {'extend_existing': True, 'mysql_engine': 'InnoDB',
746 {'extend_existing': True, 'mysql_engine': 'InnoDB',
747 'mysql_charset': 'utf8'}
747 'mysql_charset': 'utf8'}
748 )
748 )
749
749
750 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)
750 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)
751 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
751 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
752 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
752 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
753 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
753 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
754
754
755 users_group = relationship('UserGroup')
755 users_group = relationship('UserGroup')
756 permission = relationship('Permission')
756 permission = relationship('Permission')
757 group = relationship('RepoGroup')
757 group = relationship('RepoGroup')
758
758
759
759
760 class Statistics(Base, BaseModel):
760 class Statistics(Base, BaseModel):
761 __tablename__ = 'statistics'
761 __tablename__ = 'statistics'
762 __table_args__ = (
762 __table_args__ = (
763 UniqueConstraint('repository_id'),
763 UniqueConstraint('repository_id'),
764 {'extend_existing': True, 'mysql_engine': 'InnoDB',
764 {'extend_existing': True, 'mysql_engine': 'InnoDB',
765 'mysql_charset': 'utf8'}
765 'mysql_charset': 'utf8'}
766 )
766 )
767 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
767 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
768 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
768 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
769 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
769 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
770 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
770 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
771 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
771 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
772 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
772 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
773
773
774 repository = relationship('Repository', single_parent=True)
774 repository = relationship('Repository', single_parent=True)
775
775
776
776
777 class UserFollowing(Base, BaseModel):
777 class UserFollowing(Base, BaseModel):
778 __tablename__ = 'user_followings'
778 __tablename__ = 'user_followings'
779 __table_args__ = (
779 __table_args__ = (
780 UniqueConstraint('user_id', 'follows_repository_id'),
780 UniqueConstraint('user_id', 'follows_repository_id'),
781 UniqueConstraint('user_id', 'follows_user_id'),
781 UniqueConstraint('user_id', 'follows_user_id'),
782 {'extend_existing': True, 'mysql_engine': 'InnoDB',
782 {'extend_existing': True, 'mysql_engine': 'InnoDB',
783 'mysql_charset': 'utf8'}
783 'mysql_charset': 'utf8'}
784 )
784 )
785
785
786 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
786 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
787 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
787 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
788 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
788 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
789 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
789 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
790 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
790 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
791
791
792 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
792 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
793
793
794 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
794 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
795 follows_repository = relationship('Repository', order_by='Repository.repo_name')
795 follows_repository = relationship('Repository', order_by='Repository.repo_name')
796
796
797
797
798 class CacheInvalidation(Base, BaseModel):
798 class CacheInvalidation(Base, BaseModel):
799 __tablename__ = 'cache_invalidation'
799 __tablename__ = 'cache_invalidation'
800 __table_args__ = (
800 __table_args__ = (
801 UniqueConstraint('cache_key'),
801 UniqueConstraint('cache_key'),
802 Index('key_idx', 'cache_key'),
802 Index('key_idx', 'cache_key'),
803 {'extend_existing': True, 'mysql_engine': 'InnoDB',
803 {'extend_existing': True, 'mysql_engine': 'InnoDB',
804 'mysql_charset': 'utf8'},
804 'mysql_charset': 'utf8'},
805 )
805 )
806 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
806 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
807 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
807 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
808 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
808 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
809 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
809 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
810
810
811 def __init__(self, cache_key, cache_args=''):
811 def __init__(self, cache_key, cache_args=''):
812 self.cache_key = cache_key
812 self.cache_key = cache_key
813 self.cache_args = cache_args
813 self.cache_args = cache_args
814 self.cache_active = False
814 self.cache_active = False
815
815
816
816
817 class ChangesetComment(Base, BaseModel):
817 class ChangesetComment(Base, BaseModel):
818 __tablename__ = 'changeset_comments'
818 __tablename__ = 'changeset_comments'
819 __table_args__ = (
819 __table_args__ = (
820 Index('cc_revision_idx', 'revision'),
820 Index('cc_revision_idx', 'revision'),
821 {'extend_existing': True, 'mysql_engine': 'InnoDB',
821 {'extend_existing': True, 'mysql_engine': 'InnoDB',
822 'mysql_charset': 'utf8'},
822 'mysql_charset': 'utf8'},
823 )
823 )
824 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
824 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
825 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
825 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
826 revision = Column('revision', String(40), nullable=True)
826 revision = Column('revision', String(40), nullable=True)
827 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
827 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
828 line_no = Column('line_no', Unicode(10), nullable=True)
828 line_no = Column('line_no', Unicode(10), nullable=True)
829 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
829 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
830 f_path = Column('f_path', Unicode(1000), nullable=True)
830 f_path = Column('f_path', Unicode(1000), nullable=True)
831 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
831 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
832 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
832 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
833 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
833 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
834 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
834 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
835
835
836 author = relationship('User', lazy='joined')
836 author = relationship('User', lazy='joined')
837 repo = relationship('Repository')
837 repo = relationship('Repository')
838 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
838 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
839 pull_request = relationship('PullRequest', lazy='joined')
839 pull_request = relationship('PullRequest', lazy='joined')
840
840
841 @classmethod
841 @classmethod
842 def get_users(cls, revision=None, pull_request_id=None):
842 def get_users(cls, revision=None, pull_request_id=None):
843 """
843 """
844 Returns user associated with this ChangesetComment. ie those
844 Returns user associated with this ChangesetComment. ie those
845 who actually commented
845 who actually commented
846
846
847 :param cls:
847 :param cls:
848 :param revision:
848 :param revision:
849 """
849 """
850 q = Session().query(User)\
850 q = Session().query(User)\
851 .join(ChangesetComment.author)
851 .join(ChangesetComment.author)
852 if revision:
852 if revision:
853 q = q.filter(cls.revision == revision)
853 q = q.filter(cls.revision == revision)
854 elif pull_request_id:
854 elif pull_request_id:
855 q = q.filter(cls.pull_request_id == pull_request_id)
855 q = q.filter(cls.pull_request_id == pull_request_id)
856 return q.all()
856 return q.all()
857
857
858
858
859 class ChangesetStatus(Base, BaseModel):
859 class ChangesetStatus(Base, BaseModel):
860 __tablename__ = 'changeset_statuses'
860 __tablename__ = 'changeset_statuses'
861 __table_args__ = (
861 __table_args__ = (
862 Index('cs_revision_idx', 'revision'),
862 Index('cs_revision_idx', 'revision'),
863 Index('cs_version_idx', 'version'),
863 Index('cs_version_idx', 'version'),
864 UniqueConstraint('repo_id', 'revision', 'version'),
864 UniqueConstraint('repo_id', 'revision', 'version'),
865 {'extend_existing': True, 'mysql_engine': 'InnoDB',
865 {'extend_existing': True, 'mysql_engine': 'InnoDB',
866 'mysql_charset': 'utf8'}
866 'mysql_charset': 'utf8'}
867 )
867 )
868 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
868 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
869 STATUS_APPROVED = 'approved'
869 STATUS_APPROVED = 'approved'
870 STATUS_REJECTED = 'rejected'
870 STATUS_REJECTED = 'rejected'
871 STATUS_UNDER_REVIEW = 'under_review'
871 STATUS_UNDER_REVIEW = 'under_review'
872
872
873 STATUSES = [
873 STATUSES = [
874 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
874 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
875 (STATUS_APPROVED, _("Approved")),
875 (STATUS_APPROVED, _("Approved")),
876 (STATUS_REJECTED, _("Rejected")),
876 (STATUS_REJECTED, _("Rejected")),
877 (STATUS_UNDER_REVIEW, _("Under Review")),
877 (STATUS_UNDER_REVIEW, _("Under Review")),
878 ]
878 ]
879
879
880 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
880 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
881 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
881 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
882 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
882 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
883 revision = Column('revision', String(40), nullable=False)
883 revision = Column('revision', String(40), nullable=False)
884 status = Column('status', String(128), nullable=False, default=DEFAULT)
884 status = Column('status', String(128), nullable=False, default=DEFAULT)
885 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
885 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
886 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
886 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
887 version = Column('version', Integer(), nullable=False, default=0)
887 version = Column('version', Integer(), nullable=False, default=0)
888 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
888 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
889
889
890 author = relationship('User', lazy='joined')
890 author = relationship('User', lazy='joined')
891 repo = relationship('Repository')
891 repo = relationship('Repository')
892 comment = relationship('ChangesetComment', lazy='joined')
892 comment = relationship('ChangesetComment', lazy='joined')
893 pull_request = relationship('PullRequest', lazy='joined')
893 pull_request = relationship('PullRequest', lazy='joined')
894
894
895
895
896
896
897 class PullRequest(Base, BaseModel):
897 class PullRequest(Base, BaseModel):
898 __tablename__ = 'pull_requests'
898 __tablename__ = 'pull_requests'
899 __table_args__ = (
899 __table_args__ = (
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
903
904 STATUS_NEW = u'new'
904 STATUS_NEW = u'new'
905 STATUS_OPEN = u'open'
905 STATUS_OPEN = u'open'
906 STATUS_CLOSED = u'closed'
906 STATUS_CLOSED = u'closed'
907
907
908 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
908 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
909 title = Column('title', Unicode(256), nullable=True)
909 title = Column('title', Unicode(256), nullable=True)
910 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
910 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
911 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
911 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
912 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
912 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
913 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
913 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
914 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
914 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
915 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
915 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
916 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
916 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
917 org_ref = Column('org_ref', Unicode(256), nullable=False)
917 org_ref = Column('org_ref', Unicode(256), nullable=False)
918 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
918 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
919 other_ref = Column('other_ref', Unicode(256), nullable=False)
919 other_ref = Column('other_ref', Unicode(256), nullable=False)
920
920
921 author = relationship('User', lazy='joined')
921 author = relationship('User', lazy='joined')
922 reviewers = relationship('PullRequestReviewers',
922 reviewers = relationship('PullRequestReviewers',
923 cascade="all, delete, delete-orphan")
923 cascade="all, delete, delete-orphan")
924 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
924 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
925 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
925 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
926 statuses = relationship('ChangesetStatus')
926 statuses = relationship('ChangesetStatus')
927 comments = relationship('ChangesetComment',
927 comments = relationship('ChangesetComment',
928 cascade="all, delete, delete-orphan")
928 cascade="all, delete, delete-orphan")
929
929
930
930
931 class PullRequestReviewers(Base, BaseModel):
931 class PullRequestReviewers(Base, BaseModel):
932 __tablename__ = 'pull_request_reviewers'
932 __tablename__ = 'pull_request_reviewers'
933 __table_args__ = (
933 __table_args__ = (
934 {'extend_existing': True, 'mysql_engine': 'InnoDB',
934 {'extend_existing': True, 'mysql_engine': 'InnoDB',
935 'mysql_charset': 'utf8'},
935 'mysql_charset': 'utf8'},
936 )
936 )
937
937
938 def __init__(self, user=None, pull_request=None):
938 def __init__(self, user=None, pull_request=None):
939 self.user = user
939 self.user = user
940 self.pull_request = pull_request
940 self.pull_request = pull_request
941
941
942 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
942 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
943 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
943 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
944 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
944 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
945
945
946 user = relationship('User')
946 user = relationship('User')
947 pull_request = relationship('PullRequest')
947 pull_request = relationship('PullRequest')
948
948
949
949
950 class Notification(Base, BaseModel):
950 class Notification(Base, BaseModel):
951 __tablename__ = 'notifications'
951 __tablename__ = 'notifications'
952 __table_args__ = (
952 __table_args__ = (
953 Index('notification_type_idx', 'type'),
953 Index('notification_type_idx', 'type'),
954 {'extend_existing': True, 'mysql_engine': 'InnoDB',
954 {'extend_existing': True, 'mysql_engine': 'InnoDB',
955 'mysql_charset': 'utf8'},
955 'mysql_charset': 'utf8'},
956 )
956 )
957
957
958 TYPE_CHANGESET_COMMENT = u'cs_comment'
958 TYPE_CHANGESET_COMMENT = u'cs_comment'
959 TYPE_MESSAGE = u'message'
959 TYPE_MESSAGE = u'message'
960 TYPE_MENTION = u'mention'
960 TYPE_MENTION = u'mention'
961 TYPE_REGISTRATION = u'registration'
961 TYPE_REGISTRATION = u'registration'
962 TYPE_PULL_REQUEST = u'pull_request'
962 TYPE_PULL_REQUEST = u'pull_request'
963 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
963 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
964
964
965 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
965 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
966 subject = Column('subject', Unicode(512), nullable=True)
966 subject = Column('subject', Unicode(512), nullable=True)
967 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
967 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
968 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
968 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
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 type_ = Column('type', Unicode(256))
970 type_ = Column('type', Unicode(256))
971
971
972 created_by_user = relationship('User')
972 created_by_user = relationship('User')
973 notifications_to_users = relationship('UserNotification', lazy='joined',
973 notifications_to_users = relationship('UserNotification', lazy='joined',
974 cascade="all, delete, delete-orphan")
974 cascade="all, delete, delete-orphan")
975
975
976
976
977 class UserNotification(Base, BaseModel):
977 class UserNotification(Base, BaseModel):
978 __tablename__ = 'user_to_notification'
978 __tablename__ = 'user_to_notification'
979 __table_args__ = (
979 __table_args__ = (
980 UniqueConstraint('user_id', 'notification_id'),
980 UniqueConstraint('user_id', 'notification_id'),
981 {'extend_existing': True, 'mysql_engine': 'InnoDB',
981 {'extend_existing': True, 'mysql_engine': 'InnoDB',
982 'mysql_charset': 'utf8'}
982 'mysql_charset': 'utf8'}
983 )
983 )
984 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
984 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
985 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
985 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
986 read = Column('read', Boolean, default=False)
986 read = Column('read', Boolean, default=False)
987 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
987 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
988
988
989 user = relationship('User', lazy="joined")
989 user = relationship('User', lazy="joined")
990 notification = relationship('Notification', lazy="joined",
990 notification = relationship('Notification', lazy="joined",
991 order_by=lambda: Notification.created_on.desc(),)
991 order_by=lambda: Notification.created_on.desc(),)
992
992
993
993
994 class DbMigrateVersion(Base, BaseModel):
994 class DbMigrateVersion(Base, BaseModel):
995 __tablename__ = 'db_migrate_version'
995 __tablename__ = 'db_migrate_version'
996 __table_args__ = (
996 __table_args__ = (
997 {'extend_existing': True, 'mysql_engine': 'InnoDB',
997 {'extend_existing': True, 'mysql_engine': 'InnoDB',
998 'mysql_charset': 'utf8'},
998 'mysql_charset': 'utf8'},
999 )
999 )
1000 repository_id = Column('repository_id', String(250), primary_key=True)
1000 repository_id = Column('repository_id', String(250), primary_key=True)
1001 repository_path = Column('repository_path', Text)
1001 repository_path = Column('repository_path', Text)
1002 version = Column('version', Integer)
1002 version = Column('version', Integer)
@@ -1,1087 +1,1087 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
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 pylons.i18n.translation import lazy_ugettext as _
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 safe_unicode, remove_suffix, remove_prefix, time_to_datetime
45 safe_unicode, remove_suffix, remove_prefix, time_to_datetime
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.iteritems():
86 for k, val in _json_attr.iteritems():
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 __tablename__ = 'rhodecode_settings'
149 __tablename__ = 'rhodecode_settings'
150 __table_args__ = (
150 __table_args__ = (
151 UniqueConstraint('app_settings_name'),
151 UniqueConstraint('app_settings_name'),
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
153 'mysql_charset': 'utf8'}
153 'mysql_charset': 'utf8'}
154 )
154 )
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
158
158
159 def __init__(self, k='', v=''):
159 def __init__(self, k='', v=''):
160 self.app_settings_name = k
160 self.app_settings_name = k
161 self.app_settings_value = v
161 self.app_settings_value = v
162
162
163 @validates('_app_settings_value')
163 @validates('_app_settings_value')
164 def validate_settings_value(self, key, val):
164 def validate_settings_value(self, key, val):
165 assert type(val) == unicode
165 assert type(val) == unicode
166 return val
166 return val
167
167
168 @hybrid_property
168 @hybrid_property
169 def app_settings_value(self):
169 def app_settings_value(self):
170 v = self._app_settings_value
170 v = self._app_settings_value
171 if self.app_settings_name in ["ldap_active",
171 if self.app_settings_name in ["ldap_active",
172 "default_repo_enable_statistics",
172 "default_repo_enable_statistics",
173 "default_repo_enable_locking",
173 "default_repo_enable_locking",
174 "default_repo_private",
174 "default_repo_private",
175 "default_repo_enable_downloads"]:
175 "default_repo_enable_downloads"]:
176 v = str2bool(v)
176 v = str2bool(v)
177 return v
177 return v
178
178
179 @app_settings_value.setter
179 @app_settings_value.setter
180 def app_settings_value(self, val):
180 def app_settings_value(self, val):
181 """
181 """
182 Setter that will always make sure we use unicode in app_settings_value
182 Setter that will always make sure we use unicode in app_settings_value
183
183
184 :param val:
184 :param val:
185 """
185 """
186 self._app_settings_value = safe_unicode(val)
186 self._app_settings_value = safe_unicode(val)
187
187
188 def __unicode__(self):
188 def __unicode__(self):
189 return u"<%s('%s:%s')>" % (
189 return u"<%s('%s:%s')>" % (
190 self.__class__.__name__,
190 self.__class__.__name__,
191 self.app_settings_name, self.app_settings_value
191 self.app_settings_name, self.app_settings_value
192 )
192 )
193
193
194
194
195 class RhodeCodeUi(Base, BaseModel):
195 class RhodeCodeUi(Base, BaseModel):
196 __tablename__ = 'rhodecode_ui'
196 __tablename__ = 'rhodecode_ui'
197 __table_args__ = (
197 __table_args__ = (
198 UniqueConstraint('ui_key'),
198 UniqueConstraint('ui_key'),
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
200 'mysql_charset': 'utf8'}
200 'mysql_charset': 'utf8'}
201 )
201 )
202
202
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
204 HOOK_PUSH = 'changegroup.push_logger'
204 HOOK_PUSH = 'changegroup.push_logger'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
206 HOOK_PULL = 'outgoing.pull_logger'
206 HOOK_PULL = 'outgoing.pull_logger'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
208
208
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
214
214
215
215
216
216
217 class User(Base, BaseModel):
217 class User(Base, BaseModel):
218 __tablename__ = 'users'
218 __tablename__ = 'users'
219 __table_args__ = (
219 __table_args__ = (
220 UniqueConstraint('username'), UniqueConstraint('email'),
220 UniqueConstraint('username'), UniqueConstraint('email'),
221 Index('u_username_idx', 'username'),
221 Index('u_username_idx', 'username'),
222 Index('u_email_idx', 'email'),
222 Index('u_email_idx', 'email'),
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
224 'mysql_charset': 'utf8'}
224 'mysql_charset': 'utf8'}
225 )
225 )
226 DEFAULT_USER = 'default'
226 DEFAULT_USER = 'default'
227 DEFAULT_PERMISSIONS = [
227 DEFAULT_PERMISSIONS = [
228 'hg.register.manual_activate', 'hg.create.repository',
228 'hg.register.manual_activate', 'hg.create.repository',
229 'hg.fork.repository', 'repository.read', 'group.read'
229 'hg.fork.repository', 'repository.read', 'group.read'
230 ]
230 ]
231 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
231 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
232 username = Column("username", String(255), nullable=True, unique=None, default=None)
232 username = Column("username", String(255), nullable=True, unique=None, default=None)
233 password = Column("password", String(255), nullable=True, unique=None, default=None)
233 password = Column("password", String(255), nullable=True, unique=None, default=None)
234 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
234 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
235 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
235 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
236 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
236 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
237 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
237 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
238 _email = Column("email", String(255), nullable=True, unique=None, default=None)
238 _email = Column("email", String(255), nullable=True, unique=None, default=None)
239 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
239 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
240 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
240 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
241 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
241 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
242 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
242 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
243
243
244 user_log = relationship('UserLog')
244 user_log = relationship('UserLog')
245 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
245 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
246
246
247 repositories = relationship('Repository')
247 repositories = relationship('Repository')
248 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
248 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
249 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
249 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
250
250
251 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
251 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
252 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
252 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
253
253
254 group_member = relationship('UserGroupMember', cascade='all')
254 group_member = relationship('UserGroupMember', cascade='all')
255
255
256 notifications = relationship('UserNotification', cascade='all')
256 notifications = relationship('UserNotification', cascade='all')
257 # notifications assigned to this user
257 # notifications assigned to this user
258 user_created_notifications = relationship('Notification', cascade='all')
258 user_created_notifications = relationship('Notification', cascade='all')
259 # comments created by this user
259 # comments created by this user
260 user_comments = relationship('ChangesetComment', cascade='all')
260 user_comments = relationship('ChangesetComment', cascade='all')
261 user_emails = relationship('UserEmailMap', cascade='all')
261 user_emails = relationship('UserEmailMap', cascade='all')
262
262
263 @hybrid_property
263 @hybrid_property
264 def email(self):
264 def email(self):
265 return self._email
265 return self._email
266
266
267 @email.setter
267 @email.setter
268 def email(self, val):
268 def email(self, val):
269 self._email = val.lower() if val else None
269 self._email = val.lower() if val else None
270
270
271 @property
271 @property
272 def firstname(self):
272 def firstname(self):
273 # alias for future
273 # alias for future
274 return self.name
274 return self.name
275
275
276 @property
276 @property
277 def username_and_name(self):
277 def username_and_name(self):
278 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
278 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
279
279
280 @property
280 @property
281 def full_name(self):
281 def full_name(self):
282 return '%s %s' % (self.firstname, self.lastname)
282 return '%s %s' % (self.firstname, self.lastname)
283
283
284 @property
284 @property
285 def full_contact(self):
285 def full_contact(self):
286 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
286 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
287
287
288 @property
288 @property
289 def short_contact(self):
289 def short_contact(self):
290 return '%s %s' % (self.firstname, self.lastname)
290 return '%s %s' % (self.firstname, self.lastname)
291
291
292 @property
292 @property
293 def is_admin(self):
293 def is_admin(self):
294 return self.admin
294 return self.admin
295
295
296 @classmethod
296 @classmethod
297 def get_by_username(cls, username, case_insensitive=False, cache=False):
297 def get_by_username(cls, username, case_insensitive=False, cache=False):
298 if case_insensitive:
298 if case_insensitive:
299 q = cls.query().filter(cls.username.ilike(username))
299 q = cls.query().filter(cls.username.ilike(username))
300 else:
300 else:
301 q = cls.query().filter(cls.username == username)
301 q = cls.query().filter(cls.username == username)
302
302
303 if cache:
303 if cache:
304 q = q.options(FromCache(
304 q = q.options(FromCache(
305 "sql_cache_short",
305 "sql_cache_short",
306 "get_user_%s" % _hash_key(username)
306 "get_user_%s" % _hash_key(username)
307 )
307 )
308 )
308 )
309 return q.scalar()
309 return q.scalar()
310
310
311 @classmethod
311 @classmethod
312 def get_by_auth_token(cls, auth_token, cache=False):
312 def get_by_auth_token(cls, auth_token, cache=False):
313 q = cls.query().filter(cls.api_key == auth_token)
313 q = cls.query().filter(cls.api_key == auth_token)
314
314
315 if cache:
315 if cache:
316 q = q.options(FromCache("sql_cache_short",
316 q = q.options(FromCache("sql_cache_short",
317 "get_auth_token_%s" % auth_token))
317 "get_auth_token_%s" % auth_token))
318 return q.scalar()
318 return q.scalar()
319
319
320 @classmethod
320 @classmethod
321 def get_by_email(cls, email, case_insensitive=False, cache=False):
321 def get_by_email(cls, email, case_insensitive=False, cache=False):
322 if case_insensitive:
322 if case_insensitive:
323 q = cls.query().filter(cls.email.ilike(email))
323 q = cls.query().filter(cls.email.ilike(email))
324 else:
324 else:
325 q = cls.query().filter(cls.email == email)
325 q = cls.query().filter(cls.email == email)
326
326
327 if cache:
327 if cache:
328 q = q.options(FromCache("sql_cache_short",
328 q = q.options(FromCache("sql_cache_short",
329 "get_email_key_%s" % email))
329 "get_email_key_%s" % email))
330
330
331 ret = q.scalar()
331 ret = q.scalar()
332 if ret is None:
332 if ret is None:
333 q = UserEmailMap.query()
333 q = UserEmailMap.query()
334 # try fetching in alternate email map
334 # try fetching in alternate email map
335 if case_insensitive:
335 if case_insensitive:
336 q = q.filter(UserEmailMap.email.ilike(email))
336 q = q.filter(UserEmailMap.email.ilike(email))
337 else:
337 else:
338 q = q.filter(UserEmailMap.email == email)
338 q = q.filter(UserEmailMap.email == email)
339 q = q.options(joinedload(UserEmailMap.user))
339 q = q.options(joinedload(UserEmailMap.user))
340 if cache:
340 if cache:
341 q = q.options(FromCache("sql_cache_short",
341 q = q.options(FromCache("sql_cache_short",
342 "get_email_map_key_%s" % email))
342 "get_email_map_key_%s" % email))
343 ret = getattr(q.scalar(), 'user', None)
343 ret = getattr(q.scalar(), 'user', None)
344
344
345 return ret
345 return ret
346
346
347
347
348 class UserEmailMap(Base, BaseModel):
348 class UserEmailMap(Base, BaseModel):
349 __tablename__ = 'user_email_map'
349 __tablename__ = 'user_email_map'
350 __table_args__ = (
350 __table_args__ = (
351 Index('uem_email_idx', 'email'),
351 Index('uem_email_idx', 'email'),
352 UniqueConstraint('email'),
352 UniqueConstraint('email'),
353 {'extend_existing': True, 'mysql_engine': 'InnoDB',
353 {'extend_existing': True, 'mysql_engine': 'InnoDB',
354 'mysql_charset': 'utf8'}
354 'mysql_charset': 'utf8'}
355 )
355 )
356 __mapper_args__ = {}
356 __mapper_args__ = {}
357
357
358 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
358 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
359 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
359 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
360 _email = Column("email", String(255), nullable=True, unique=False, default=None)
360 _email = Column("email", String(255), nullable=True, unique=False, default=None)
361 user = relationship('User', lazy='joined')
361 user = relationship('User', lazy='joined')
362
362
363 @validates('_email')
363 @validates('_email')
364 def validate_email(self, key, email):
364 def validate_email(self, key, email):
365 # check if this email is not main one
365 # check if this email is not main one
366 main_email = Session().query(User).filter(User.email == email).scalar()
366 main_email = Session().query(User).filter(User.email == email).scalar()
367 if main_email is not None:
367 if main_email is not None:
368 raise AttributeError('email %s is present is user table' % email)
368 raise AttributeError('email %s is present is user table' % email)
369 return email
369 return email
370
370
371 @hybrid_property
371 @hybrid_property
372 def email(self):
372 def email(self):
373 return self._email
373 return self._email
374
374
375 @email.setter
375 @email.setter
376 def email(self, val):
376 def email(self, val):
377 self._email = val.lower() if val else None
377 self._email = val.lower() if val else None
378
378
379
379
380 class UserIpMap(Base, BaseModel):
380 class UserIpMap(Base, BaseModel):
381 __tablename__ = 'user_ip_map'
381 __tablename__ = 'user_ip_map'
382 __table_args__ = (
382 __table_args__ = (
383 UniqueConstraint('user_id', 'ip_addr'),
383 UniqueConstraint('user_id', 'ip_addr'),
384 {'extend_existing': True, 'mysql_engine': 'InnoDB',
384 {'extend_existing': True, 'mysql_engine': 'InnoDB',
385 'mysql_charset': 'utf8'}
385 'mysql_charset': 'utf8'}
386 )
386 )
387 __mapper_args__ = {}
387 __mapper_args__ = {}
388
388
389 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
389 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
390 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
390 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
391 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
391 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
392 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
392 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
393 user = relationship('User', lazy='joined')
393 user = relationship('User', lazy='joined')
394
394
395
395
396 class UserLog(Base, BaseModel):
396 class UserLog(Base, BaseModel):
397 __tablename__ = 'user_logs'
397 __tablename__ = 'user_logs'
398 __table_args__ = (
398 __table_args__ = (
399 {'extend_existing': True, 'mysql_engine': 'InnoDB',
399 {'extend_existing': True, 'mysql_engine': 'InnoDB',
400 'mysql_charset': 'utf8'},
400 'mysql_charset': 'utf8'},
401 )
401 )
402 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
402 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
403 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
403 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
404 username = Column("username", String(255), nullable=True, unique=None, default=None)
404 username = Column("username", String(255), nullable=True, unique=None, default=None)
405 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
405 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
406 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
406 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
407 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
407 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
408 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
408 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
409 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
409 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
410
410
411
411
412 user = relationship('User')
412 user = relationship('User')
413 repository = relationship('Repository', cascade='')
413 repository = relationship('Repository', cascade='')
414
414
415
415
416 class UserGroup(Base, BaseModel):
416 class UserGroup(Base, BaseModel):
417 __tablename__ = 'users_groups'
417 __tablename__ = 'users_groups'
418 __table_args__ = (
418 __table_args__ = (
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
420 'mysql_charset': 'utf8'},
420 'mysql_charset': 'utf8'},
421 )
421 )
422
422
423 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
423 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
424 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
425 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
425 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
426 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
426 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
427
427
428 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
428 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
429 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
429 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
430 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
430 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
431
431
432 def __unicode__(self):
432 def __unicode__(self):
433 return u'<userGroup(%s)>' % (self.users_group_name)
433 return u'<userGroup(%s)>' % (self.users_group_name)
434
434
435 @classmethod
435 @classmethod
436 def get_by_group_name(cls, group_name, cache=False,
436 def get_by_group_name(cls, group_name, cache=False,
437 case_insensitive=False):
437 case_insensitive=False):
438 if case_insensitive:
438 if case_insensitive:
439 q = cls.query().filter(cls.users_group_name.ilike(group_name))
439 q = cls.query().filter(cls.users_group_name.ilike(group_name))
440 else:
440 else:
441 q = cls.query().filter(cls.users_group_name == group_name)
441 q = cls.query().filter(cls.users_group_name == group_name)
442 if cache:
442 if cache:
443 q = q.options(FromCache(
443 q = q.options(FromCache(
444 "sql_cache_short",
444 "sql_cache_short",
445 "get_user_%s" % _hash_key(group_name)
445 "get_user_%s" % _hash_key(group_name)
446 )
446 )
447 )
447 )
448 return q.scalar()
448 return q.scalar()
449
449
450 @classmethod
450 @classmethod
451 def get(cls, users_group_id, cache=False):
451 def get(cls, users_group_id, cache=False):
452 user_group = cls.query()
452 user_group = cls.query()
453 if cache:
453 if cache:
454 user_group = user_group.options(FromCache("sql_cache_short",
454 user_group = user_group.options(FromCache("sql_cache_short",
455 "get_users_group_%s" % users_group_id))
455 "get_users_group_%s" % users_group_id))
456 return user_group.get(users_group_id)
456 return user_group.get(users_group_id)
457
457
458
458
459 class UserGroupMember(Base, BaseModel):
459 class UserGroupMember(Base, BaseModel):
460 __tablename__ = 'users_groups_members'
460 __tablename__ = 'users_groups_members'
461 __table_args__ = (
461 __table_args__ = (
462 {'extend_existing': True, 'mysql_engine': 'InnoDB',
462 {'extend_existing': True, 'mysql_engine': 'InnoDB',
463 'mysql_charset': 'utf8'},
463 'mysql_charset': 'utf8'},
464 )
464 )
465
465
466 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
466 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
467 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
467 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
468 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
468 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
469
469
470 user = relationship('User', lazy='joined')
470 user = relationship('User', lazy='joined')
471 users_group = relationship('UserGroup')
471 users_group = relationship('UserGroup')
472
472
473 def __init__(self, gr_id='', u_id=''):
473 def __init__(self, gr_id='', u_id=''):
474 self.users_group_id = gr_id
474 self.users_group_id = gr_id
475 self.user_id = u_id
475 self.user_id = u_id
476
476
477
477
478 class RepositoryField(Base, BaseModel):
478 class RepositoryField(Base, BaseModel):
479 __tablename__ = 'repositories_fields'
479 __tablename__ = 'repositories_fields'
480 __table_args__ = (
480 __table_args__ = (
481 UniqueConstraint('repository_id', 'field_key'), # no-multi field
481 UniqueConstraint('repository_id', 'field_key'), # no-multi field
482 {'extend_existing': True, 'mysql_engine': 'InnoDB',
482 {'extend_existing': True, 'mysql_engine': 'InnoDB',
483 'mysql_charset': 'utf8'},
483 'mysql_charset': 'utf8'},
484 )
484 )
485 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
485 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
486
486
487 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
487 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
488 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
488 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
489 field_key = Column("field_key", String(250))
489 field_key = Column("field_key", String(250))
490 field_label = Column("field_label", String(1024), nullable=False)
490 field_label = Column("field_label", String(1024), nullable=False)
491 field_value = Column("field_value", String(10000), nullable=False)
491 field_value = Column("field_value", String(10000), nullable=False)
492 field_desc = Column("field_desc", String(1024), nullable=False)
492 field_desc = Column("field_desc", String(1024), nullable=False)
493 field_type = Column("field_type", String(256), nullable=False, unique=None)
493 field_type = Column("field_type", String(256), nullable=False, unique=None)
494 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
494 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
495
495
496 repository = relationship('Repository')
496 repository = relationship('Repository')
497
497
498 @classmethod
498 @classmethod
499 def get_by_key_name(cls, key, repo):
499 def get_by_key_name(cls, key, repo):
500 row = cls.query()\
500 row = cls.query()\
501 .filter(cls.repository == repo)\
501 .filter(cls.repository == repo)\
502 .filter(cls.field_key == key).scalar()
502 .filter(cls.field_key == key).scalar()
503 return row
503 return row
504
504
505
505
506 class Repository(Base, BaseModel):
506 class Repository(Base, BaseModel):
507 __tablename__ = 'repositories'
507 __tablename__ = 'repositories'
508 __table_args__ = (
508 __table_args__ = (
509 UniqueConstraint('repo_name'),
509 UniqueConstraint('repo_name'),
510 Index('r_repo_name_idx', 'repo_name'),
510 Index('r_repo_name_idx', 'repo_name'),
511 {'extend_existing': True, 'mysql_engine': 'InnoDB',
511 {'extend_existing': True, 'mysql_engine': 'InnoDB',
512 'mysql_charset': 'utf8'},
512 'mysql_charset': 'utf8'},
513 )
513 )
514
514
515 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
515 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
516 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
516 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
517 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
517 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
518 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
518 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
519 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
519 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
520 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
520 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
521 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
521 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
522 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
522 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
523 description = Column("description", String(10000), nullable=True, unique=None, default=None)
523 description = Column("description", String(10000), nullable=True, unique=None, default=None)
524 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
524 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
525 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
525 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
526 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
526 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
527 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
527 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
528 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
528 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
529 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
529 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
530
530
531 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
531 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
532 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
532 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
533
533
534 user = relationship('User')
534 user = relationship('User')
535 fork = relationship('Repository', remote_side=repo_id)
535 fork = relationship('Repository', remote_side=repo_id)
536 group = relationship('RepoGroup')
536 group = relationship('RepoGroup')
537 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
537 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
538 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
538 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
539 stats = relationship('Statistics', cascade='all', uselist=False)
539 stats = relationship('Statistics', cascade='all', uselist=False)
540
540
541 followers = relationship('UserFollowing',
541 followers = relationship('UserFollowing',
542 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
542 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
543 cascade='all')
543 cascade='all')
544 extra_fields = relationship('RepositoryField',
544 extra_fields = relationship('RepositoryField',
545 cascade="all, delete, delete-orphan")
545 cascade="all, delete, delete-orphan")
546
546
547 logs = relationship('UserLog')
547 logs = relationship('UserLog')
548 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
548 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
549
549
550 pull_requests_org = relationship('PullRequest',
550 pull_requests_org = relationship('PullRequest',
551 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
551 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
552 cascade="all, delete, delete-orphan")
552 cascade="all, delete, delete-orphan")
553
553
554 pull_requests_other = relationship('PullRequest',
554 pull_requests_other = relationship('PullRequest',
555 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
555 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
556 cascade="all, delete, delete-orphan")
556 cascade="all, delete, delete-orphan")
557
557
558 def __unicode__(self):
558 def __unicode__(self):
559 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
559 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
560 safe_unicode(self.repo_name))
560 safe_unicode(self.repo_name))
561
561
562 #NOTE for this migration we are required tio have it
562 #NOTE for this migration we are required tio have it
563 @hybrid_property
563 @hybrid_property
564 def changeset_cache(self):
564 def changeset_cache(self):
565 from rhodecode.lib.vcs.backends.base import EmptyCommit
565 from rhodecode.lib.vcs.backends.base import EmptyCommit
566 dummy = EmptyCommit().__json__()
566 dummy = EmptyCommit().__json__()
567 if not self._changeset_cache:
567 if not self._changeset_cache:
568 return dummy
568 return dummy
569 try:
569 try:
570 return json.loads(self._changeset_cache)
570 return json.loads(self._changeset_cache)
571 except TypeError:
571 except TypeError:
572 return dummy
572 return dummy
573
573
574 @changeset_cache.setter
574 @changeset_cache.setter
575 def changeset_cache(self, val):
575 def changeset_cache(self, val):
576 try:
576 try:
577 self._changeset_cache = json.dumps(val)
577 self._changeset_cache = json.dumps(val)
578 except Exception:
578 except Exception:
579 log.error(traceback.format_exc())
579 log.error(traceback.format_exc())
580
580
581 @classmethod
581 @classmethod
582 def get_by_repo_name(cls, repo_name):
582 def get_by_repo_name(cls, repo_name):
583 q = Session().query(cls).filter(cls.repo_name == repo_name)
583 q = Session().query(cls).filter(cls.repo_name == repo_name)
584 q = q.options(joinedload(Repository.fork))\
584 q = q.options(joinedload(Repository.fork))\
585 .options(joinedload(Repository.user))\
585 .options(joinedload(Repository.user))\
586 .options(joinedload(Repository.group))
586 .options(joinedload(Repository.group))
587 return q.scalar()
587 return q.scalar()
588
588
589 #NOTE this is required for this migration to work
589 #NOTE this is required for this migration to work
590 def update_commit_cache(self, cs_cache=None):
590 def update_commit_cache(self, cs_cache=None):
591 """
591 """
592 Update cache of last changeset for repository, keys should be::
592 Update cache of last changeset for repository, keys should be::
593
593
594 short_id
594 short_id
595 raw_id
595 raw_id
596 revision
596 revision
597 message
597 message
598 date
598 date
599 author
599 author
600
600
601 :param cs_cache:
601 :param cs_cache:
602 """
602 """
603 from rhodecode.lib.vcs.backends.base import BaseChangeset
603 from rhodecode.lib.vcs.backends.base import BaseChangeset
604 if cs_cache is None:
604 if cs_cache is None:
605 cs_cache = EmptyCommit()
605 cs_cache = EmptyCommit()
606 # Note: Using always the empty commit here in case we are
606 # Note: Using always the empty commit here in case we are
607 # upgrading towards version 3.0 and above. Reason is that in this
607 # upgrading towards version 3.0 and above. Reason is that in this
608 # case the vcsclient connection is not available and things
608 # case the vcsclient connection is not available and things
609 # would explode here.
609 # would explode here.
610
610
611 if isinstance(cs_cache, BaseChangeset):
611 if isinstance(cs_cache, BaseChangeset):
612 cs_cache = cs_cache.__json__()
612 cs_cache = cs_cache.__json__()
613
613
614 if (cs_cache != self.changeset_cache or not self.changeset_cache):
614 if (cs_cache != self.changeset_cache or not self.changeset_cache):
615 _default = datetime.datetime.fromtimestamp(0)
615 _default = datetime.datetime.fromtimestamp(0)
616 last_change = cs_cache.get('date') or _default
616 last_change = cs_cache.get('date') or _default
617 log.debug('updated repo %s with new cs cache %s'
617 log.debug('updated repo %s with new cs cache %s'
618 % (self.repo_name, cs_cache))
618 % (self.repo_name, cs_cache))
619 self.updated_on = last_change
619 self.updated_on = last_change
620 self.changeset_cache = cs_cache
620 self.changeset_cache = cs_cache
621 Session().add(self)
621 Session().add(self)
622 Session().commit()
622 Session().commit()
623 else:
623 else:
624 log.debug('Skipping repo:%s already with latest changes'
624 log.debug('Skipping repo:%s already with latest changes'
625 % self.repo_name)
625 % self.repo_name)
626
626
627 class RepoGroup(Base, BaseModel):
627 class RepoGroup(Base, BaseModel):
628 __tablename__ = 'groups'
628 __tablename__ = 'groups'
629 __table_args__ = (
629 __table_args__ = (
630 UniqueConstraint('group_name', 'group_parent_id'),
630 UniqueConstraint('group_name', 'group_parent_id'),
631 CheckConstraint('group_id != group_parent_id'),
631 CheckConstraint('group_id != group_parent_id'),
632 {'extend_existing': True, 'mysql_engine': 'InnoDB',
632 {'extend_existing': True, 'mysql_engine': 'InnoDB',
633 'mysql_charset': 'utf8'},
633 'mysql_charset': 'utf8'},
634 )
634 )
635 __mapper_args__ = {'order_by': 'group_name'}
635 __mapper_args__ = {'order_by': 'group_name'}
636
636
637 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
637 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
638 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
638 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
639 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
639 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
640 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
640 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
641 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
641 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
642
642
643 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
643 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
644 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
644 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
645 parent_group = relationship('RepoGroup', remote_side=group_id)
645 parent_group = relationship('RepoGroup', remote_side=group_id)
646
646
647 def __init__(self, group_name='', parent_group=None):
647 def __init__(self, group_name='', parent_group=None):
648 self.group_name = group_name
648 self.group_name = group_name
649 self.parent_group = parent_group
649 self.parent_group = parent_group
650
650
651 def __unicode__(self):
651 def __unicode__(self):
652 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
652 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
653 self.group_name)
653 self.group_name)
654
654
655 @classmethod
655 @classmethod
656 def url_sep(cls):
656 def url_sep(cls):
657 return URL_SEP
657 return URL_SEP
658
658
659 @classmethod
659 @classmethod
660 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
660 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
661 if case_insensitive:
661 if case_insensitive:
662 gr = cls.query()\
662 gr = cls.query()\
663 .filter(cls.group_name.ilike(group_name))
663 .filter(cls.group_name.ilike(group_name))
664 else:
664 else:
665 gr = cls.query()\
665 gr = cls.query()\
666 .filter(cls.group_name == group_name)
666 .filter(cls.group_name == group_name)
667 if cache:
667 if cache:
668 gr = gr.options(FromCache(
668 gr = gr.options(FromCache(
669 "sql_cache_short",
669 "sql_cache_short",
670 "get_group_%s" % _hash_key(group_name)
670 "get_group_%s" % _hash_key(group_name)
671 )
671 )
672 )
672 )
673 return gr.scalar()
673 return gr.scalar()
674
674
675
675
676 class Permission(Base, BaseModel):
676 class Permission(Base, BaseModel):
677 __tablename__ = 'permissions'
677 __tablename__ = 'permissions'
678 __table_args__ = (
678 __table_args__ = (
679 Index('p_perm_name_idx', 'permission_name'),
679 Index('p_perm_name_idx', 'permission_name'),
680 {'extend_existing': True, 'mysql_engine': 'InnoDB',
680 {'extend_existing': True, 'mysql_engine': 'InnoDB',
681 'mysql_charset': 'utf8'},
681 'mysql_charset': 'utf8'},
682 )
682 )
683 PERMS = [
683 PERMS = [
684 ('repository.none', _('Repository no access')),
684 ('repository.none', _('Repository no access')),
685 ('repository.read', _('Repository read access')),
685 ('repository.read', _('Repository read access')),
686 ('repository.write', _('Repository write access')),
686 ('repository.write', _('Repository write access')),
687 ('repository.admin', _('Repository admin access')),
687 ('repository.admin', _('Repository admin access')),
688
688
689 ('group.none', _('Repository group no access')),
689 ('group.none', _('Repository group no access')),
690 ('group.read', _('Repository group read access')),
690 ('group.read', _('Repository group read access')),
691 ('group.write', _('Repository group write access')),
691 ('group.write', _('Repository group write access')),
692 ('group.admin', _('Repository group admin access')),
692 ('group.admin', _('Repository group admin access')),
693
693
694 ('hg.admin', _('RhodeCode Administrator')),
694 ('hg.admin', _('RhodeCode Administrator')),
695 ('hg.create.none', _('Repository creation disabled')),
695 ('hg.create.none', _('Repository creation disabled')),
696 ('hg.create.repository', _('Repository creation enabled')),
696 ('hg.create.repository', _('Repository creation enabled')),
697 ('hg.fork.none', _('Repository forking disabled')),
697 ('hg.fork.none', _('Repository forking disabled')),
698 ('hg.fork.repository', _('Repository forking enabled')),
698 ('hg.fork.repository', _('Repository forking enabled')),
699 ('hg.register.none', _('Register disabled')),
699 ('hg.register.none', _('Register disabled')),
700 ('hg.register.manual_activate', _('Register new user with RhodeCode '
700 ('hg.register.manual_activate', _('Register new user with RhodeCode '
701 'with manual activation')),
701 'with manual activation')),
702
702
703 ('hg.register.auto_activate', _('Register new user with RhodeCode '
703 ('hg.register.auto_activate', _('Register new user with RhodeCode '
704 'with auto activation')),
704 'with auto activation')),
705 ]
705 ]
706
706
707 # defines which permissions are more important higher the more important
707 # defines which permissions are more important higher the more important
708 PERM_WEIGHTS = {
708 PERM_WEIGHTS = {
709 'repository.none': 0,
709 'repository.none': 0,
710 'repository.read': 1,
710 'repository.read': 1,
711 'repository.write': 3,
711 'repository.write': 3,
712 'repository.admin': 4,
712 'repository.admin': 4,
713
713
714 'group.none': 0,
714 'group.none': 0,
715 'group.read': 1,
715 'group.read': 1,
716 'group.write': 3,
716 'group.write': 3,
717 'group.admin': 4,
717 'group.admin': 4,
718
718
719 'hg.fork.none': 0,
719 'hg.fork.none': 0,
720 'hg.fork.repository': 1,
720 'hg.fork.repository': 1,
721 'hg.create.none': 0,
721 'hg.create.none': 0,
722 'hg.create.repository':1
722 'hg.create.repository':1
723 }
723 }
724
724
725 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
725 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
726 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
726 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
727 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
727 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
728
728
729 def __unicode__(self):
729 def __unicode__(self):
730 return u"<%s('%s:%s')>" % (
730 return u"<%s('%s:%s')>" % (
731 self.__class__.__name__, self.permission_id, self.permission_name
731 self.__class__.__name__, self.permission_id, self.permission_name
732 )
732 )
733
733
734 @classmethod
734 @classmethod
735 def get_by_key(cls, key):
735 def get_by_key(cls, key):
736 return cls.query().filter(cls.permission_name == key).scalar()
736 return cls.query().filter(cls.permission_name == key).scalar()
737
737
738
738
739 class UserRepoToPerm(Base, BaseModel):
739 class UserRepoToPerm(Base, BaseModel):
740 __tablename__ = 'repo_to_perm'
740 __tablename__ = 'repo_to_perm'
741 __table_args__ = (
741 __table_args__ = (
742 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
742 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
743 {'extend_existing': True, 'mysql_engine': 'InnoDB',
743 {'extend_existing': True, 'mysql_engine': 'InnoDB',
744 'mysql_charset': 'utf8'}
744 'mysql_charset': 'utf8'}
745 )
745 )
746 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
746 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
747 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
747 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
748 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
748 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
749 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
749 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
750
750
751 user = relationship('User')
751 user = relationship('User')
752 repository = relationship('Repository')
752 repository = relationship('Repository')
753 permission = relationship('Permission')
753 permission = relationship('Permission')
754
754
755 def __unicode__(self):
755 def __unicode__(self):
756 return u'<user:%s => %s >' % (self.user, self.repository)
756 return u'<user:%s => %s >' % (self.user, self.repository)
757
757
758
758
759 class UserToPerm(Base, BaseModel):
759 class UserToPerm(Base, BaseModel):
760 __tablename__ = 'user_to_perm'
760 __tablename__ = 'user_to_perm'
761 __table_args__ = (
761 __table_args__ = (
762 UniqueConstraint('user_id', 'permission_id'),
762 UniqueConstraint('user_id', 'permission_id'),
763 {'extend_existing': True, 'mysql_engine': 'InnoDB',
763 {'extend_existing': True, 'mysql_engine': 'InnoDB',
764 'mysql_charset': 'utf8'}
764 'mysql_charset': 'utf8'}
765 )
765 )
766 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
766 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
767 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
767 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
768 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
768 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
769
769
770 user = relationship('User')
770 user = relationship('User')
771 permission = relationship('Permission', lazy='joined')
771 permission = relationship('Permission', lazy='joined')
772
772
773
773
774 class UserGroupRepoToPerm(Base, BaseModel):
774 class UserGroupRepoToPerm(Base, BaseModel):
775 __tablename__ = 'users_group_repo_to_perm'
775 __tablename__ = 'users_group_repo_to_perm'
776 __table_args__ = (
776 __table_args__ = (
777 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
777 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
778 {'extend_existing': True, 'mysql_engine': 'InnoDB',
778 {'extend_existing': True, 'mysql_engine': 'InnoDB',
779 'mysql_charset': 'utf8'}
779 'mysql_charset': 'utf8'}
780 )
780 )
781 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
781 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
782 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
782 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
783 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
783 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
784 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
784 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
785
785
786 users_group = relationship('UserGroup')
786 users_group = relationship('UserGroup')
787 permission = relationship('Permission')
787 permission = relationship('Permission')
788 repository = relationship('Repository')
788 repository = relationship('Repository')
789
789
790 def __unicode__(self):
790 def __unicode__(self):
791 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
791 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
792
792
793
793
794 class UserGroupToPerm(Base, BaseModel):
794 class UserGroupToPerm(Base, BaseModel):
795 __tablename__ = 'users_group_to_perm'
795 __tablename__ = 'users_group_to_perm'
796 __table_args__ = (
796 __table_args__ = (
797 UniqueConstraint('users_group_id', 'permission_id',),
797 UniqueConstraint('users_group_id', 'permission_id',),
798 {'extend_existing': True, 'mysql_engine': 'InnoDB',
798 {'extend_existing': True, 'mysql_engine': 'InnoDB',
799 'mysql_charset': 'utf8'}
799 'mysql_charset': 'utf8'}
800 )
800 )
801 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
801 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
802 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
802 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
803 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
803 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
804
804
805 users_group = relationship('UserGroup')
805 users_group = relationship('UserGroup')
806 permission = relationship('Permission')
806 permission = relationship('Permission')
807
807
808
808
809 class UserRepoGroupToPerm(Base, BaseModel):
809 class UserRepoGroupToPerm(Base, BaseModel):
810 __tablename__ = 'user_repo_group_to_perm'
810 __tablename__ = 'user_repo_group_to_perm'
811 __table_args__ = (
811 __table_args__ = (
812 UniqueConstraint('user_id', 'group_id', 'permission_id'),
812 UniqueConstraint('user_id', 'group_id', 'permission_id'),
813 {'extend_existing': True, 'mysql_engine': 'InnoDB',
813 {'extend_existing': True, 'mysql_engine': 'InnoDB',
814 'mysql_charset': 'utf8'}
814 'mysql_charset': 'utf8'}
815 )
815 )
816
816
817 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
817 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
818 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
818 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
819 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
819 group_id = Column("group_id", Integer(), ForeignKey('groups.group_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 group = relationship('RepoGroup')
823 group = relationship('RepoGroup')
824 permission = relationship('Permission')
824 permission = relationship('Permission')
825
825
826
826
827 class UserGroupRepoGroupToPerm(Base, BaseModel):
827 class UserGroupRepoGroupToPerm(Base, BaseModel):
828 __tablename__ = 'users_group_repo_group_to_perm'
828 __tablename__ = 'users_group_repo_group_to_perm'
829 __table_args__ = (
829 __table_args__ = (
830 UniqueConstraint('users_group_id', 'group_id'),
830 UniqueConstraint('users_group_id', 'group_id'),
831 {'extend_existing': True, 'mysql_engine': 'InnoDB',
831 {'extend_existing': True, 'mysql_engine': 'InnoDB',
832 'mysql_charset': 'utf8'}
832 'mysql_charset': 'utf8'}
833 )
833 )
834
834
835 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)
835 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)
836 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
836 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
837 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
837 group_id = Column("group_id", Integer(), ForeignKey('groups.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
839
840 users_group = relationship('UserGroup')
840 users_group = relationship('UserGroup')
841 permission = relationship('Permission')
841 permission = relationship('Permission')
842 group = relationship('RepoGroup')
842 group = relationship('RepoGroup')
843
843
844
844
845 class Statistics(Base, BaseModel):
845 class Statistics(Base, BaseModel):
846 __tablename__ = 'statistics'
846 __tablename__ = 'statistics'
847 __table_args__ = (
847 __table_args__ = (
848 UniqueConstraint('repository_id'),
848 UniqueConstraint('repository_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 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
852 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
853 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
853 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
854 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
854 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
855 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
855 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
856 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
856 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
857 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
857 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
858
858
859 repository = relationship('Repository', single_parent=True)
859 repository = relationship('Repository', single_parent=True)
860
860
861
861
862 class UserFollowing(Base, BaseModel):
862 class UserFollowing(Base, BaseModel):
863 __tablename__ = 'user_followings'
863 __tablename__ = 'user_followings'
864 __table_args__ = (
864 __table_args__ = (
865 UniqueConstraint('user_id', 'follows_repository_id'),
865 UniqueConstraint('user_id', 'follows_repository_id'),
866 UniqueConstraint('user_id', 'follows_user_id'),
866 UniqueConstraint('user_id', 'follows_user_id'),
867 {'extend_existing': True, 'mysql_engine': 'InnoDB',
867 {'extend_existing': True, 'mysql_engine': 'InnoDB',
868 'mysql_charset': 'utf8'}
868 'mysql_charset': 'utf8'}
869 )
869 )
870
870
871 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
871 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
872 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
872 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
873 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
873 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
874 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
874 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
875 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
875 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
876
876
877 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
877 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
878
878
879 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
879 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
880 follows_repository = relationship('Repository', order_by='Repository.repo_name')
880 follows_repository = relationship('Repository', order_by='Repository.repo_name')
881
881
882
882
883 class CacheInvalidation(Base, BaseModel):
883 class CacheInvalidation(Base, BaseModel):
884 __tablename__ = 'cache_invalidation'
884 __tablename__ = 'cache_invalidation'
885 __table_args__ = (
885 __table_args__ = (
886 UniqueConstraint('cache_key'),
886 UniqueConstraint('cache_key'),
887 Index('key_idx', 'cache_key'),
887 Index('key_idx', 'cache_key'),
888 {'extend_existing': True, 'mysql_engine': 'InnoDB',
888 {'extend_existing': True, 'mysql_engine': 'InnoDB',
889 'mysql_charset': 'utf8'},
889 'mysql_charset': 'utf8'},
890 )
890 )
891 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
891 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
892 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
892 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
893 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
893 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
894 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
894 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
895
895
896 def __init__(self, cache_key, cache_args=''):
896 def __init__(self, cache_key, cache_args=''):
897 self.cache_key = cache_key
897 self.cache_key = cache_key
898 self.cache_args = cache_args
898 self.cache_args = cache_args
899 self.cache_active = False
899 self.cache_active = False
900
900
901
901
902 class ChangesetComment(Base, BaseModel):
902 class ChangesetComment(Base, BaseModel):
903 __tablename__ = 'changeset_comments'
903 __tablename__ = 'changeset_comments'
904 __table_args__ = (
904 __table_args__ = (
905 Index('cc_revision_idx', 'revision'),
905 Index('cc_revision_idx', 'revision'),
906 {'extend_existing': True, 'mysql_engine': 'InnoDB',
906 {'extend_existing': True, 'mysql_engine': 'InnoDB',
907 'mysql_charset': 'utf8'},
907 'mysql_charset': 'utf8'},
908 )
908 )
909 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
909 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
910 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
910 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
911 revision = Column('revision', String(40), nullable=True)
911 revision = Column('revision', String(40), nullable=True)
912 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
912 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
913 line_no = Column('line_no', Unicode(10), nullable=True)
913 line_no = Column('line_no', Unicode(10), nullable=True)
914 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
914 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
915 f_path = Column('f_path', Unicode(1000), nullable=True)
915 f_path = Column('f_path', Unicode(1000), nullable=True)
916 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
916 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
917 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
917 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
918 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
918 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
919 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
919 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
920
920
921 author = relationship('User', lazy='joined')
921 author = relationship('User', lazy='joined')
922 repo = relationship('Repository')
922 repo = relationship('Repository')
923 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
923 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
924 pull_request = relationship('PullRequest', lazy='joined')
924 pull_request = relationship('PullRequest', lazy='joined')
925
925
926 @classmethod
926 @classmethod
927 def get_users(cls, revision=None, pull_request_id=None):
927 def get_users(cls, revision=None, pull_request_id=None):
928 """
928 """
929 Returns user associated with this ChangesetComment. ie those
929 Returns user associated with this ChangesetComment. ie those
930 who actually commented
930 who actually commented
931
931
932 :param cls:
932 :param cls:
933 :param revision:
933 :param revision:
934 """
934 """
935 q = Session().query(User)\
935 q = Session().query(User)\
936 .join(ChangesetComment.author)
936 .join(ChangesetComment.author)
937 if revision:
937 if revision:
938 q = q.filter(cls.revision == revision)
938 q = q.filter(cls.revision == revision)
939 elif pull_request_id:
939 elif pull_request_id:
940 q = q.filter(cls.pull_request_id == pull_request_id)
940 q = q.filter(cls.pull_request_id == pull_request_id)
941 return q.all()
941 return q.all()
942
942
943
943
944 class ChangesetStatus(Base, BaseModel):
944 class ChangesetStatus(Base, BaseModel):
945 __tablename__ = 'changeset_statuses'
945 __tablename__ = 'changeset_statuses'
946 __table_args__ = (
946 __table_args__ = (
947 Index('cs_revision_idx', 'revision'),
947 Index('cs_revision_idx', 'revision'),
948 Index('cs_version_idx', 'version'),
948 Index('cs_version_idx', 'version'),
949 UniqueConstraint('repo_id', 'revision', 'version'),
949 UniqueConstraint('repo_id', 'revision', 'version'),
950 {'extend_existing': True, 'mysql_engine': 'InnoDB',
950 {'extend_existing': True, 'mysql_engine': 'InnoDB',
951 'mysql_charset': 'utf8'}
951 'mysql_charset': 'utf8'}
952 )
952 )
953 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
953 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
954 STATUS_APPROVED = 'approved'
954 STATUS_APPROVED = 'approved'
955 STATUS_REJECTED = 'rejected'
955 STATUS_REJECTED = 'rejected'
956 STATUS_UNDER_REVIEW = 'under_review'
956 STATUS_UNDER_REVIEW = 'under_review'
957
957
958 STATUSES = [
958 STATUSES = [
959 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
959 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
960 (STATUS_APPROVED, _("Approved")),
960 (STATUS_APPROVED, _("Approved")),
961 (STATUS_REJECTED, _("Rejected")),
961 (STATUS_REJECTED, _("Rejected")),
962 (STATUS_UNDER_REVIEW, _("Under Review")),
962 (STATUS_UNDER_REVIEW, _("Under Review")),
963 ]
963 ]
964
964
965 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
965 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
966 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
966 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
967 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
967 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
968 revision = Column('revision', String(40), nullable=False)
968 revision = Column('revision', String(40), nullable=False)
969 status = Column('status', String(128), nullable=False, default=DEFAULT)
969 status = Column('status', String(128), nullable=False, default=DEFAULT)
970 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
970 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
971 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
971 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
972 version = Column('version', Integer(), nullable=False, default=0)
972 version = Column('version', Integer(), nullable=False, default=0)
973 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
973 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
974
974
975 author = relationship('User', lazy='joined')
975 author = relationship('User', lazy='joined')
976 repo = relationship('Repository')
976 repo = relationship('Repository')
977 comment = relationship('ChangesetComment', lazy='joined')
977 comment = relationship('ChangesetComment', lazy='joined')
978 pull_request = relationship('PullRequest', lazy='joined')
978 pull_request = relationship('PullRequest', lazy='joined')
979
979
980
980
981
981
982 class PullRequest(Base, BaseModel):
982 class PullRequest(Base, BaseModel):
983 __tablename__ = 'pull_requests'
983 __tablename__ = 'pull_requests'
984 __table_args__ = (
984 __table_args__ = (
985 {'extend_existing': True, 'mysql_engine': 'InnoDB',
985 {'extend_existing': True, 'mysql_engine': 'InnoDB',
986 'mysql_charset': 'utf8'},
986 'mysql_charset': 'utf8'},
987 )
987 )
988
988
989 STATUS_NEW = u'new'
989 STATUS_NEW = u'new'
990 STATUS_OPEN = u'open'
990 STATUS_OPEN = u'open'
991 STATUS_CLOSED = u'closed'
991 STATUS_CLOSED = u'closed'
992
992
993 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
993 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
994 title = Column('title', Unicode(256), nullable=True)
994 title = Column('title', Unicode(256), nullable=True)
995 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
995 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
996 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
996 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
997 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
997 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
998 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
998 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
999 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
999 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1000 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1000 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1001 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1001 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1002 org_ref = Column('org_ref', Unicode(256), nullable=False)
1002 org_ref = Column('org_ref', Unicode(256), nullable=False)
1003 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1003 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1004 other_ref = Column('other_ref', Unicode(256), nullable=False)
1004 other_ref = Column('other_ref', Unicode(256), nullable=False)
1005
1005
1006 author = relationship('User', lazy='joined')
1006 author = relationship('User', lazy='joined')
1007 reviewers = relationship('PullRequestReviewers',
1007 reviewers = relationship('PullRequestReviewers',
1008 cascade="all, delete, delete-orphan")
1008 cascade="all, delete, delete-orphan")
1009 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1009 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1010 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1010 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1011 statuses = relationship('ChangesetStatus')
1011 statuses = relationship('ChangesetStatus')
1012 comments = relationship('ChangesetComment',
1012 comments = relationship('ChangesetComment',
1013 cascade="all, delete, delete-orphan")
1013 cascade="all, delete, delete-orphan")
1014
1014
1015
1015
1016 class PullRequestReviewers(Base, BaseModel):
1016 class PullRequestReviewers(Base, BaseModel):
1017 __tablename__ = 'pull_request_reviewers'
1017 __tablename__ = 'pull_request_reviewers'
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 def __init__(self, user=None, pull_request=None):
1023 def __init__(self, user=None, pull_request=None):
1024 self.user = user
1024 self.user = user
1025 self.pull_request = pull_request
1025 self.pull_request = pull_request
1026
1026
1027 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1027 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1028 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1028 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1029 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1029 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1030
1030
1031 user = relationship('User')
1031 user = relationship('User')
1032 pull_request = relationship('PullRequest')
1032 pull_request = relationship('PullRequest')
1033
1033
1034
1034
1035 class Notification(Base, BaseModel):
1035 class Notification(Base, BaseModel):
1036 __tablename__ = 'notifications'
1036 __tablename__ = 'notifications'
1037 __table_args__ = (
1037 __table_args__ = (
1038 Index('notification_type_idx', 'type'),
1038 Index('notification_type_idx', 'type'),
1039 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1039 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1040 'mysql_charset': 'utf8'},
1040 'mysql_charset': 'utf8'},
1041 )
1041 )
1042
1042
1043 TYPE_CHANGESET_COMMENT = u'cs_comment'
1043 TYPE_CHANGESET_COMMENT = u'cs_comment'
1044 TYPE_MESSAGE = u'message'
1044 TYPE_MESSAGE = u'message'
1045 TYPE_MENTION = u'mention'
1045 TYPE_MENTION = u'mention'
1046 TYPE_REGISTRATION = u'registration'
1046 TYPE_REGISTRATION = u'registration'
1047 TYPE_PULL_REQUEST = u'pull_request'
1047 TYPE_PULL_REQUEST = u'pull_request'
1048 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1048 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1049
1049
1050 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1050 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1051 subject = Column('subject', Unicode(512), nullable=True)
1051 subject = Column('subject', Unicode(512), nullable=True)
1052 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1052 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1053 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1053 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1054 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1054 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1055 type_ = Column('type', Unicode(256))
1055 type_ = Column('type', Unicode(256))
1056
1056
1057 created_by_user = relationship('User')
1057 created_by_user = relationship('User')
1058 notifications_to_users = relationship('UserNotification', lazy='joined',
1058 notifications_to_users = relationship('UserNotification', lazy='joined',
1059 cascade="all, delete, delete-orphan")
1059 cascade="all, delete, delete-orphan")
1060
1060
1061
1061
1062 class UserNotification(Base, BaseModel):
1062 class UserNotification(Base, BaseModel):
1063 __tablename__ = 'user_to_notification'
1063 __tablename__ = 'user_to_notification'
1064 __table_args__ = (
1064 __table_args__ = (
1065 UniqueConstraint('user_id', 'notification_id'),
1065 UniqueConstraint('user_id', 'notification_id'),
1066 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1066 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1067 'mysql_charset': 'utf8'}
1067 'mysql_charset': 'utf8'}
1068 )
1068 )
1069 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1069 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1070 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1070 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1071 read = Column('read', Boolean, default=False)
1071 read = Column('read', Boolean, default=False)
1072 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1072 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1073
1073
1074 user = relationship('User', lazy="joined")
1074 user = relationship('User', lazy="joined")
1075 notification = relationship('Notification', lazy="joined",
1075 notification = relationship('Notification', lazy="joined",
1076 order_by=lambda: Notification.created_on.desc(),)
1076 order_by=lambda: Notification.created_on.desc(),)
1077
1077
1078
1078
1079 class DbMigrateVersion(Base, BaseModel):
1079 class DbMigrateVersion(Base, BaseModel):
1080 __tablename__ = 'db_migrate_version'
1080 __tablename__ = 'db_migrate_version'
1081 __table_args__ = (
1081 __table_args__ = (
1082 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1082 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1083 'mysql_charset': 'utf8'},
1083 'mysql_charset': 'utf8'},
1084 )
1084 )
1085 repository_id = Column('repository_id', String(250), primary_key=True)
1085 repository_id = Column('repository_id', String(250), primary_key=True)
1086 repository_path = Column('repository_path', Text)
1086 repository_path = Column('repository_path', Text)
1087 version = Column('version', Integer)
1087 version = Column('version', Integer)
@@ -1,1146 +1,1146 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
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 pylons.i18n.translation import lazy_ugettext as _
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 safe_unicode, remove_suffix, remove_prefix, time_to_datetime
45 safe_unicode, remove_suffix, remove_prefix, time_to_datetime
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.iteritems():
86 for k, val in _json_attr.iteritems():
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 __tablename__ = 'rhodecode_settings'
149 __tablename__ = 'rhodecode_settings'
150 __table_args__ = (
150 __table_args__ = (
151 UniqueConstraint('app_settings_name'),
151 UniqueConstraint('app_settings_name'),
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
153 'mysql_charset': 'utf8'}
153 'mysql_charset': 'utf8'}
154 )
154 )
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
158
158
159 def __init__(self, k='', v=''):
159 def __init__(self, k='', v=''):
160 self.app_settings_name = k
160 self.app_settings_name = k
161 self.app_settings_value = v
161 self.app_settings_value = v
162
162
163 @validates('_app_settings_value')
163 @validates('_app_settings_value')
164 def validate_settings_value(self, key, val):
164 def validate_settings_value(self, key, val):
165 assert type(val) == unicode
165 assert type(val) == unicode
166 return val
166 return val
167
167
168 @hybrid_property
168 @hybrid_property
169 def app_settings_value(self):
169 def app_settings_value(self):
170 v = self._app_settings_value
170 v = self._app_settings_value
171 if self.app_settings_name in ["ldap_active",
171 if self.app_settings_name in ["ldap_active",
172 "default_repo_enable_statistics",
172 "default_repo_enable_statistics",
173 "default_repo_enable_locking",
173 "default_repo_enable_locking",
174 "default_repo_private",
174 "default_repo_private",
175 "default_repo_enable_downloads"]:
175 "default_repo_enable_downloads"]:
176 v = str2bool(v)
176 v = str2bool(v)
177 return v
177 return v
178
178
179 @app_settings_value.setter
179 @app_settings_value.setter
180 def app_settings_value(self, val):
180 def app_settings_value(self, val):
181 """
181 """
182 Setter that will always make sure we use unicode in app_settings_value
182 Setter that will always make sure we use unicode in app_settings_value
183
183
184 :param val:
184 :param val:
185 """
185 """
186 self._app_settings_value = safe_unicode(val)
186 self._app_settings_value = safe_unicode(val)
187
187
188 def __unicode__(self):
188 def __unicode__(self):
189 return u"<%s('%s:%s')>" % (
189 return u"<%s('%s:%s')>" % (
190 self.__class__.__name__,
190 self.__class__.__name__,
191 self.app_settings_name, self.app_settings_value
191 self.app_settings_name, self.app_settings_value
192 )
192 )
193
193
194
194
195 class RhodeCodeUi(Base, BaseModel):
195 class RhodeCodeUi(Base, BaseModel):
196 __tablename__ = 'rhodecode_ui'
196 __tablename__ = 'rhodecode_ui'
197 __table_args__ = (
197 __table_args__ = (
198 UniqueConstraint('ui_key'),
198 UniqueConstraint('ui_key'),
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
199 {'extend_existing': True, 'mysql_engine': 'InnoDB',
200 'mysql_charset': 'utf8'}
200 'mysql_charset': 'utf8'}
201 )
201 )
202
202
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
203 HOOK_REPO_SIZE = 'changegroup.repo_size'
204 HOOK_PUSH = 'changegroup.push_logger'
204 HOOK_PUSH = 'changegroup.push_logger'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
205 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
206 HOOK_PULL = 'outgoing.pull_logger'
206 HOOK_PULL = 'outgoing.pull_logger'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
207 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
208
208
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
209 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
210 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
211 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
212 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
213 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
214
214
215
215
216
216
217 class User(Base, BaseModel):
217 class User(Base, BaseModel):
218 __tablename__ = 'users'
218 __tablename__ = 'users'
219 __table_args__ = (
219 __table_args__ = (
220 UniqueConstraint('username'), UniqueConstraint('email'),
220 UniqueConstraint('username'), UniqueConstraint('email'),
221 Index('u_username_idx', 'username'),
221 Index('u_username_idx', 'username'),
222 Index('u_email_idx', 'email'),
222 Index('u_email_idx', 'email'),
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
223 {'extend_existing': True, 'mysql_engine': 'InnoDB',
224 'mysql_charset': 'utf8'}
224 'mysql_charset': 'utf8'}
225 )
225 )
226 DEFAULT_USER = 'default'
226 DEFAULT_USER = 'default'
227
227
228 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
228 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
229 username = Column("username", String(255), nullable=True, unique=None, default=None)
229 username = Column("username", String(255), nullable=True, unique=None, default=None)
230 password = Column("password", String(255), nullable=True, unique=None, default=None)
230 password = Column("password", String(255), nullable=True, unique=None, default=None)
231 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
231 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
232 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
232 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
233 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
233 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
234 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
234 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
235 _email = Column("email", String(255), nullable=True, unique=None, default=None)
235 _email = Column("email", String(255), nullable=True, unique=None, default=None)
236 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
236 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
237 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
237 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
238 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
238 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
239 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
239 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
240
240
241 user_log = relationship('UserLog')
241 user_log = relationship('UserLog')
242 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
242 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
243
243
244 repositories = relationship('Repository')
244 repositories = relationship('Repository')
245 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
245 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
246 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
246 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
247
247
248 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
248 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
249 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
249 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
250
250
251 group_member = relationship('UserGroupMember', cascade='all')
251 group_member = relationship('UserGroupMember', cascade='all')
252
252
253 notifications = relationship('UserNotification', cascade='all')
253 notifications = relationship('UserNotification', cascade='all')
254 # notifications assigned to this user
254 # notifications assigned to this user
255 user_created_notifications = relationship('Notification', cascade='all')
255 user_created_notifications = relationship('Notification', cascade='all')
256 # comments created by this user
256 # comments created by this user
257 user_comments = relationship('ChangesetComment', cascade='all')
257 user_comments = relationship('ChangesetComment', cascade='all')
258 user_emails = relationship('UserEmailMap', cascade='all')
258 user_emails = relationship('UserEmailMap', cascade='all')
259
259
260 @hybrid_property
260 @hybrid_property
261 def email(self):
261 def email(self):
262 return self._email
262 return self._email
263
263
264 @email.setter
264 @email.setter
265 def email(self, val):
265 def email(self, val):
266 self._email = val.lower() if val else None
266 self._email = val.lower() if val else None
267
267
268 @property
268 @property
269 def firstname(self):
269 def firstname(self):
270 # alias for future
270 # alias for future
271 return self.name
271 return self.name
272
272
273 @property
273 @property
274 def username_and_name(self):
274 def username_and_name(self):
275 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
275 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
276
276
277 @property
277 @property
278 def full_name(self):
278 def full_name(self):
279 return '%s %s' % (self.firstname, self.lastname)
279 return '%s %s' % (self.firstname, self.lastname)
280
280
281 @property
281 @property
282 def full_contact(self):
282 def full_contact(self):
283 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
283 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
284
284
285 @property
285 @property
286 def short_contact(self):
286 def short_contact(self):
287 return '%s %s' % (self.firstname, self.lastname)
287 return '%s %s' % (self.firstname, self.lastname)
288
288
289 @property
289 @property
290 def is_admin(self):
290 def is_admin(self):
291 return self.admin
291 return self.admin
292
292
293 @classmethod
293 @classmethod
294 def get_by_username(cls, username, case_insensitive=False, cache=False):
294 def get_by_username(cls, username, case_insensitive=False, cache=False):
295 if case_insensitive:
295 if case_insensitive:
296 q = cls.query().filter(cls.username.ilike(username))
296 q = cls.query().filter(cls.username.ilike(username))
297 else:
297 else:
298 q = cls.query().filter(cls.username == username)
298 q = cls.query().filter(cls.username == username)
299
299
300 if cache:
300 if cache:
301 q = q.options(FromCache(
301 q = q.options(FromCache(
302 "sql_cache_short",
302 "sql_cache_short",
303 "get_user_%s" % _hash_key(username)
303 "get_user_%s" % _hash_key(username)
304 )
304 )
305 )
305 )
306 return q.scalar()
306 return q.scalar()
307
307
308 @classmethod
308 @classmethod
309 def get_by_auth_token(cls, auth_token, cache=False):
309 def get_by_auth_token(cls, auth_token, cache=False):
310 q = cls.query().filter(cls.api_key == auth_token)
310 q = cls.query().filter(cls.api_key == auth_token)
311
311
312 if cache:
312 if cache:
313 q = q.options(FromCache("sql_cache_short",
313 q = q.options(FromCache("sql_cache_short",
314 "get_auth_token_%s" % auth_token))
314 "get_auth_token_%s" % auth_token))
315 return q.scalar()
315 return q.scalar()
316
316
317 @classmethod
317 @classmethod
318 def get_by_email(cls, email, case_insensitive=False, cache=False):
318 def get_by_email(cls, email, case_insensitive=False, cache=False):
319 if case_insensitive:
319 if case_insensitive:
320 q = cls.query().filter(cls.email.ilike(email))
320 q = cls.query().filter(cls.email.ilike(email))
321 else:
321 else:
322 q = cls.query().filter(cls.email == email)
322 q = cls.query().filter(cls.email == email)
323
323
324 if cache:
324 if cache:
325 q = q.options(FromCache("sql_cache_short",
325 q = q.options(FromCache("sql_cache_short",
326 "get_email_key_%s" % email))
326 "get_email_key_%s" % email))
327
327
328 ret = q.scalar()
328 ret = q.scalar()
329 if ret is None:
329 if ret is None:
330 q = UserEmailMap.query()
330 q = UserEmailMap.query()
331 # try fetching in alternate email map
331 # try fetching in alternate email map
332 if case_insensitive:
332 if case_insensitive:
333 q = q.filter(UserEmailMap.email.ilike(email))
333 q = q.filter(UserEmailMap.email.ilike(email))
334 else:
334 else:
335 q = q.filter(UserEmailMap.email == email)
335 q = q.filter(UserEmailMap.email == email)
336 q = q.options(joinedload(UserEmailMap.user))
336 q = q.options(joinedload(UserEmailMap.user))
337 if cache:
337 if cache:
338 q = q.options(FromCache("sql_cache_short",
338 q = q.options(FromCache("sql_cache_short",
339 "get_email_map_key_%s" % email))
339 "get_email_map_key_%s" % email))
340 ret = getattr(q.scalar(), 'user', None)
340 ret = getattr(q.scalar(), 'user', None)
341
341
342 return ret
342 return ret
343
343
344 @classmethod
344 @classmethod
345 def get_first_admin(cls):
345 def get_first_admin(cls):
346 user = User.query().filter(User.admin == True).first()
346 user = User.query().filter(User.admin == True).first()
347 if user is None:
347 if user is None:
348 raise Exception('Missing administrative account!')
348 raise Exception('Missing administrative account!')
349 return user
349 return user
350
350
351 @classmethod
351 @classmethod
352 def get_default_user(cls, cache=False):
352 def get_default_user(cls, cache=False):
353 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
353 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
354 if user is None:
354 if user is None:
355 raise Exception('Missing default account!')
355 raise Exception('Missing default account!')
356 return user
356 return user
357
357
358
358
359
359
360
360
361 class UserEmailMap(Base, BaseModel):
361 class UserEmailMap(Base, BaseModel):
362 __tablename__ = 'user_email_map'
362 __tablename__ = 'user_email_map'
363 __table_args__ = (
363 __table_args__ = (
364 Index('uem_email_idx', 'email'),
364 Index('uem_email_idx', 'email'),
365 UniqueConstraint('email'),
365 UniqueConstraint('email'),
366 {'extend_existing': True, 'mysql_engine': 'InnoDB',
366 {'extend_existing': True, 'mysql_engine': 'InnoDB',
367 'mysql_charset': 'utf8'}
367 'mysql_charset': 'utf8'}
368 )
368 )
369 __mapper_args__ = {}
369 __mapper_args__ = {}
370
370
371 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
371 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
372 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
372 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
373 _email = Column("email", String(255), nullable=True, unique=False, default=None)
373 _email = Column("email", String(255), nullable=True, unique=False, default=None)
374 user = relationship('User', lazy='joined')
374 user = relationship('User', lazy='joined')
375
375
376 @validates('_email')
376 @validates('_email')
377 def validate_email(self, key, email):
377 def validate_email(self, key, email):
378 # check if this email is not main one
378 # check if this email is not main one
379 main_email = Session().query(User).filter(User.email == email).scalar()
379 main_email = Session().query(User).filter(User.email == email).scalar()
380 if main_email is not None:
380 if main_email is not None:
381 raise AttributeError('email %s is present is user table' % email)
381 raise AttributeError('email %s is present is user table' % email)
382 return email
382 return email
383
383
384 @hybrid_property
384 @hybrid_property
385 def email(self):
385 def email(self):
386 return self._email
386 return self._email
387
387
388 @email.setter
388 @email.setter
389 def email(self, val):
389 def email(self, val):
390 self._email = val.lower() if val else None
390 self._email = val.lower() if val else None
391
391
392
392
393 class UserIpMap(Base, BaseModel):
393 class UserIpMap(Base, BaseModel):
394 __tablename__ = 'user_ip_map'
394 __tablename__ = 'user_ip_map'
395 __table_args__ = (
395 __table_args__ = (
396 UniqueConstraint('user_id', 'ip_addr'),
396 UniqueConstraint('user_id', 'ip_addr'),
397 {'extend_existing': True, 'mysql_engine': 'InnoDB',
397 {'extend_existing': True, 'mysql_engine': 'InnoDB',
398 'mysql_charset': 'utf8'}
398 'mysql_charset': 'utf8'}
399 )
399 )
400 __mapper_args__ = {}
400 __mapper_args__ = {}
401
401
402 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
402 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
403 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
403 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
404 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
404 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
405 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
405 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
406 user = relationship('User', lazy='joined')
406 user = relationship('User', lazy='joined')
407
407
408
408
409 class UserLog(Base, BaseModel):
409 class UserLog(Base, BaseModel):
410 __tablename__ = 'user_logs'
410 __tablename__ = 'user_logs'
411 __table_args__ = (
411 __table_args__ = (
412 {'extend_existing': True, 'mysql_engine': 'InnoDB',
412 {'extend_existing': True, 'mysql_engine': 'InnoDB',
413 'mysql_charset': 'utf8'},
413 'mysql_charset': 'utf8'},
414 )
414 )
415 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
415 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
416 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
416 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
417 username = Column("username", String(255), nullable=True, unique=None, default=None)
417 username = Column("username", String(255), nullable=True, unique=None, default=None)
418 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
418 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
419 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
419 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
420 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
420 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
421 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
421 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
422 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
422 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
423
423
424 def __unicode__(self):
424 def __unicode__(self):
425 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
425 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
426 self.repository_name,
426 self.repository_name,
427 self.action)
427 self.action)
428
428
429 user = relationship('User')
429 user = relationship('User')
430 repository = relationship('Repository', cascade='')
430 repository = relationship('Repository', cascade='')
431
431
432
432
433 class UserGroup(Base, BaseModel):
433 class UserGroup(Base, BaseModel):
434 __tablename__ = 'users_groups'
434 __tablename__ = 'users_groups'
435 __table_args__ = (
435 __table_args__ = (
436 {'extend_existing': True, 'mysql_engine': 'InnoDB',
436 {'extend_existing': True, 'mysql_engine': 'InnoDB',
437 'mysql_charset': 'utf8'},
437 'mysql_charset': 'utf8'},
438 )
438 )
439
439
440 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
440 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
441 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
441 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
442 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
442 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
443 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
443 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
444 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
444 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
445
445
446 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
446 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
447 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
447 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
448 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
448 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
449 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
449 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
450 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
450 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
451 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
451 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
452
452
453 user = relationship('User')
453 user = relationship('User')
454
454
455 def __unicode__(self):
455 def __unicode__(self):
456 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
456 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
457 self.users_group_id,
457 self.users_group_id,
458 self.users_group_name)
458 self.users_group_name)
459
459
460 @classmethod
460 @classmethod
461 def get_by_group_name(cls, group_name, cache=False,
461 def get_by_group_name(cls, group_name, cache=False,
462 case_insensitive=False):
462 case_insensitive=False):
463 if case_insensitive:
463 if case_insensitive:
464 q = cls.query().filter(cls.users_group_name.ilike(group_name))
464 q = cls.query().filter(cls.users_group_name.ilike(group_name))
465 else:
465 else:
466 q = cls.query().filter(cls.users_group_name == group_name)
466 q = cls.query().filter(cls.users_group_name == group_name)
467 if cache:
467 if cache:
468 q = q.options(FromCache(
468 q = q.options(FromCache(
469 "sql_cache_short",
469 "sql_cache_short",
470 "get_user_%s" % _hash_key(group_name)
470 "get_user_%s" % _hash_key(group_name)
471 )
471 )
472 )
472 )
473 return q.scalar()
473 return q.scalar()
474
474
475 @classmethod
475 @classmethod
476 def get(cls, users_group_id, cache=False):
476 def get(cls, users_group_id, cache=False):
477 user_group = cls.query()
477 user_group = cls.query()
478 if cache:
478 if cache:
479 user_group = user_group.options(FromCache("sql_cache_short",
479 user_group = user_group.options(FromCache("sql_cache_short",
480 "get_users_group_%s" % users_group_id))
480 "get_users_group_%s" % users_group_id))
481 return user_group.get(users_group_id)
481 return user_group.get(users_group_id)
482
482
483
483
484 class UserGroupMember(Base, BaseModel):
484 class UserGroupMember(Base, BaseModel):
485 __tablename__ = 'users_groups_members'
485 __tablename__ = 'users_groups_members'
486 __table_args__ = (
486 __table_args__ = (
487 {'extend_existing': True, 'mysql_engine': 'InnoDB',
487 {'extend_existing': True, 'mysql_engine': 'InnoDB',
488 'mysql_charset': 'utf8'},
488 'mysql_charset': 'utf8'},
489 )
489 )
490
490
491 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
491 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
492 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
492 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
493 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
493 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
494
494
495 user = relationship('User', lazy='joined')
495 user = relationship('User', lazy='joined')
496 users_group = relationship('UserGroup')
496 users_group = relationship('UserGroup')
497
497
498 def __init__(self, gr_id='', u_id=''):
498 def __init__(self, gr_id='', u_id=''):
499 self.users_group_id = gr_id
499 self.users_group_id = gr_id
500 self.user_id = u_id
500 self.user_id = u_id
501
501
502
502
503 class RepositoryField(Base, BaseModel):
503 class RepositoryField(Base, BaseModel):
504 __tablename__ = 'repositories_fields'
504 __tablename__ = 'repositories_fields'
505 __table_args__ = (
505 __table_args__ = (
506 UniqueConstraint('repository_id', 'field_key'), # no-multi field
506 UniqueConstraint('repository_id', 'field_key'), # no-multi field
507 {'extend_existing': True, 'mysql_engine': 'InnoDB',
507 {'extend_existing': True, 'mysql_engine': 'InnoDB',
508 'mysql_charset': 'utf8'},
508 'mysql_charset': 'utf8'},
509 )
509 )
510 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
510 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
511
511
512 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
512 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
513 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
513 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
514 field_key = Column("field_key", String(250))
514 field_key = Column("field_key", String(250))
515 field_label = Column("field_label", String(1024), nullable=False)
515 field_label = Column("field_label", String(1024), nullable=False)
516 field_value = Column("field_value", String(10000), nullable=False)
516 field_value = Column("field_value", String(10000), nullable=False)
517 field_desc = Column("field_desc", String(1024), nullable=False)
517 field_desc = Column("field_desc", String(1024), nullable=False)
518 field_type = Column("field_type", String(256), nullable=False, unique=None)
518 field_type = Column("field_type", String(256), nullable=False, unique=None)
519 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
519 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
520
520
521 repository = relationship('Repository')
521 repository = relationship('Repository')
522
522
523 @classmethod
523 @classmethod
524 def get_by_key_name(cls, key, repo):
524 def get_by_key_name(cls, key, repo):
525 row = cls.query()\
525 row = cls.query()\
526 .filter(cls.repository == repo)\
526 .filter(cls.repository == repo)\
527 .filter(cls.field_key == key).scalar()
527 .filter(cls.field_key == key).scalar()
528 return row
528 return row
529
529
530
530
531 class Repository(Base, BaseModel):
531 class Repository(Base, BaseModel):
532 __tablename__ = 'repositories'
532 __tablename__ = 'repositories'
533 __table_args__ = (
533 __table_args__ = (
534 UniqueConstraint('repo_name'),
534 UniqueConstraint('repo_name'),
535 Index('r_repo_name_idx', 'repo_name'),
535 Index('r_repo_name_idx', 'repo_name'),
536 {'extend_existing': True, 'mysql_engine': 'InnoDB',
536 {'extend_existing': True, 'mysql_engine': 'InnoDB',
537 'mysql_charset': 'utf8'},
537 'mysql_charset': 'utf8'},
538 )
538 )
539
539
540 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
540 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
541 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
541 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
542 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
542 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
543 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
543 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
544 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
544 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
545 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
545 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
546 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
546 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
547 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
547 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
548 description = Column("description", String(10000), nullable=True, unique=None, default=None)
548 description = Column("description", String(10000), nullable=True, unique=None, default=None)
549 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
549 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
550 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
550 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
551 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
551 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
552 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
552 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
553 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
553 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
554 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
554 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
555
555
556 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
556 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
557 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
557 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
558
558
559 user = relationship('User')
559 user = relationship('User')
560 fork = relationship('Repository', remote_side=repo_id)
560 fork = relationship('Repository', remote_side=repo_id)
561 group = relationship('RepoGroup')
561 group = relationship('RepoGroup')
562 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
562 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
563 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
563 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
564 stats = relationship('Statistics', cascade='all', uselist=False)
564 stats = relationship('Statistics', cascade='all', uselist=False)
565
565
566 followers = relationship('UserFollowing',
566 followers = relationship('UserFollowing',
567 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
567 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
568 cascade='all')
568 cascade='all')
569 extra_fields = relationship('RepositoryField',
569 extra_fields = relationship('RepositoryField',
570 cascade="all, delete, delete-orphan")
570 cascade="all, delete, delete-orphan")
571
571
572 logs = relationship('UserLog')
572 logs = relationship('UserLog')
573 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
573 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
574
574
575 pull_requests_org = relationship('PullRequest',
575 pull_requests_org = relationship('PullRequest',
576 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
576 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
577 cascade="all, delete, delete-orphan")
577 cascade="all, delete, delete-orphan")
578
578
579 pull_requests_other = relationship('PullRequest',
579 pull_requests_other = relationship('PullRequest',
580 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
580 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
581 cascade="all, delete, delete-orphan")
581 cascade="all, delete, delete-orphan")
582
582
583 def __unicode__(self):
583 def __unicode__(self):
584 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
584 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
585 safe_unicode(self.repo_name))
585 safe_unicode(self.repo_name))
586
586
587 @classmethod
587 @classmethod
588 def get_by_repo_name(cls, repo_name):
588 def get_by_repo_name(cls, repo_name):
589 q = Session().query(cls).filter(cls.repo_name == repo_name)
589 q = Session().query(cls).filter(cls.repo_name == repo_name)
590 q = q.options(joinedload(Repository.fork))\
590 q = q.options(joinedload(Repository.fork))\
591 .options(joinedload(Repository.user))\
591 .options(joinedload(Repository.user))\
592 .options(joinedload(Repository.group))
592 .options(joinedload(Repository.group))
593 return q.scalar()
593 return q.scalar()
594
594
595
595
596 class RepoGroup(Base, BaseModel):
596 class RepoGroup(Base, BaseModel):
597 __tablename__ = 'groups'
597 __tablename__ = 'groups'
598 __table_args__ = (
598 __table_args__ = (
599 UniqueConstraint('group_name', 'group_parent_id'),
599 UniqueConstraint('group_name', 'group_parent_id'),
600 CheckConstraint('group_id != group_parent_id'),
600 CheckConstraint('group_id != group_parent_id'),
601 {'extend_existing': True, 'mysql_engine': 'InnoDB',
601 {'extend_existing': True, 'mysql_engine': 'InnoDB',
602 'mysql_charset': 'utf8'},
602 'mysql_charset': 'utf8'},
603 )
603 )
604 __mapper_args__ = {'order_by': 'group_name'}
604 __mapper_args__ = {'order_by': 'group_name'}
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'},
652 'mysql_charset': 'utf8'},
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'}
753 'mysql_charset': 'utf8'}
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'}
773 'mysql_charset': 'utf8'}
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'}
793 'mysql_charset': 'utf8'}
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'}
811 'mysql_charset': 'utf8'}
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'}
832 'mysql_charset': 'utf8'}
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'}
852 'mysql_charset': 'utf8'}
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'}
867 'mysql_charset': 'utf8'}
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'}
885 'mysql_charset': 'utf8'}
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'}
903 'mysql_charset': 'utf8'}
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'}
921 'mysql_charset': 'utf8'}
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'},
942 'mysql_charset': 'utf8'},
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'},
960 'mysql_charset': 'utf8'},
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'}
987 'mysql_charset': 'utf8'}
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'},
1022 'mysql_charset': 'utf8'},
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'},
1056 'mysql_charset': 'utf8'},
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'},
1076 'mysql_charset': 'utf8'},
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'}
1103 'mysql_charset': 'utf8'}
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'}
1121 'mysql_charset': 'utf8'}
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(), nullable=False)
1130 gist_expires = Column('gist_expires', Float(), 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'},
1142 'mysql_charset': 'utf8'},
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,1148 +1,1148 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
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 pylons.i18n.translation import lazy_ugettext as _
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 safe_unicode, remove_suffix, remove_prefix, time_to_datetime
45 safe_unicode, remove_suffix, remove_prefix, time_to_datetime
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.iteritems():
86 for k, val in _json_attr.iteritems():
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 __tablename__ = 'rhodecode_settings'
149 __tablename__ = 'rhodecode_settings'
150 __table_args__ = (
150 __table_args__ = (
151 UniqueConstraint('app_settings_name'),
151 UniqueConstraint('app_settings_name'),
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 {'extend_existing': True, 'mysql_engine': 'InnoDB',
153 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
153 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
154 )
154 )
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
156 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
157 _app_settings_value = Column("app_settings_value", String(255), nullable=True, unique=None, default=None)
158 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
158 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
159
159
160 def __init__(self, key='', val='', type='unicode'):
160 def __init__(self, key='', val='', type='unicode'):
161 self.app_settings_name = key
161 self.app_settings_name = key
162 self.app_settings_value = val
162 self.app_settings_value = val
163 self.app_settings_type = type
163 self.app_settings_type = type
164
164
165 @validates('_app_settings_value')
165 @validates('_app_settings_value')
166 def validate_settings_value(self, key, val):
166 def validate_settings_value(self, key, val):
167 assert type(val) == unicode
167 assert type(val) == unicode
168 return val
168 return val
169
169
170 @hybrid_property
170 @hybrid_property
171 def app_settings_value(self):
171 def app_settings_value(self):
172 v = self._app_settings_value
172 v = self._app_settings_value
173 if self.app_settings_name in ["ldap_active",
173 if self.app_settings_name in ["ldap_active",
174 "default_repo_enable_statistics",
174 "default_repo_enable_statistics",
175 "default_repo_enable_locking",
175 "default_repo_enable_locking",
176 "default_repo_private",
176 "default_repo_private",
177 "default_repo_enable_downloads"]:
177 "default_repo_enable_downloads"]:
178 v = str2bool(v)
178 v = str2bool(v)
179 return v
179 return v
180
180
181 @app_settings_value.setter
181 @app_settings_value.setter
182 def app_settings_value(self, val):
182 def app_settings_value(self, val):
183 """
183 """
184 Setter that will always make sure we use unicode in app_settings_value
184 Setter that will always make sure we use unicode in app_settings_value
185
185
186 :param val:
186 :param val:
187 """
187 """
188 self._app_settings_value = safe_unicode(val)
188 self._app_settings_value = safe_unicode(val)
189
189
190 def __unicode__(self):
190 def __unicode__(self):
191 return u"<%s('%s:%s')>" % (
191 return u"<%s('%s:%s')>" % (
192 self.__class__.__name__,
192 self.__class__.__name__,
193 self.app_settings_name, self.app_settings_value
193 self.app_settings_name, self.app_settings_value
194 )
194 )
195
195
196
196
197 class RhodeCodeUi(Base, BaseModel):
197 class RhodeCodeUi(Base, BaseModel):
198 __tablename__ = 'rhodecode_ui'
198 __tablename__ = 'rhodecode_ui'
199 __table_args__ = (
199 __table_args__ = (
200 UniqueConstraint('ui_key'),
200 UniqueConstraint('ui_key'),
201 {'extend_existing': True, 'mysql_engine': 'InnoDB',
201 {'extend_existing': True, 'mysql_engine': 'InnoDB',
202 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
202 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
203 )
203 )
204
204
205 HOOK_REPO_SIZE = 'changegroup.repo_size'
205 HOOK_REPO_SIZE = 'changegroup.repo_size'
206 HOOK_PUSH = 'changegroup.push_logger'
206 HOOK_PUSH = 'changegroup.push_logger'
207 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
207 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
208 HOOK_PULL = 'outgoing.pull_logger'
208 HOOK_PULL = 'outgoing.pull_logger'
209 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
209 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
210
210
211 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
211 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
212 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
212 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
213 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
213 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
214 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
214 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
215 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
215 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
216
216
217
217
218
218
219 class User(Base, BaseModel):
219 class User(Base, BaseModel):
220 __tablename__ = 'users'
220 __tablename__ = 'users'
221 __table_args__ = (
221 __table_args__ = (
222 UniqueConstraint('username'), UniqueConstraint('email'),
222 UniqueConstraint('username'), UniqueConstraint('email'),
223 Index('u_username_idx', 'username'),
223 Index('u_username_idx', 'username'),
224 Index('u_email_idx', 'email'),
224 Index('u_email_idx', 'email'),
225 {'extend_existing': True, 'mysql_engine': 'InnoDB',
225 {'extend_existing': True, 'mysql_engine': 'InnoDB',
226 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
226 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
227 )
227 )
228 DEFAULT_USER = 'default'
228 DEFAULT_USER = 'default'
229
229
230 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
230 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
231 username = Column("username", String(255), nullable=True, unique=None, default=None)
231 username = Column("username", String(255), nullable=True, unique=None, default=None)
232 password = Column("password", String(255), nullable=True, unique=None, default=None)
232 password = Column("password", String(255), nullable=True, unique=None, default=None)
233 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
233 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
234 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
234 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
235 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
235 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
236 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
236 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
237 _email = Column("email", String(255), nullable=True, unique=None, default=None)
237 _email = Column("email", String(255), nullable=True, unique=None, default=None)
238 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
238 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
239 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
239 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
240 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
240 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
241 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
241 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
242
242
243 user_log = relationship('UserLog')
243 user_log = relationship('UserLog')
244 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
244 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
245
245
246 repositories = relationship('Repository')
246 repositories = relationship('Repository')
247 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
247 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
248 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
248 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
249
249
250 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
250 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
251 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
251 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
252
252
253 group_member = relationship('UserGroupMember', cascade='all')
253 group_member = relationship('UserGroupMember', cascade='all')
254
254
255 notifications = relationship('UserNotification', cascade='all')
255 notifications = relationship('UserNotification', cascade='all')
256 # notifications assigned to this user
256 # notifications assigned to this user
257 user_created_notifications = relationship('Notification', cascade='all')
257 user_created_notifications = relationship('Notification', cascade='all')
258 # comments created by this user
258 # comments created by this user
259 user_comments = relationship('ChangesetComment', cascade='all')
259 user_comments = relationship('ChangesetComment', cascade='all')
260 user_emails = relationship('UserEmailMap', cascade='all')
260 user_emails = relationship('UserEmailMap', cascade='all')
261
261
262 @hybrid_property
262 @hybrid_property
263 def email(self):
263 def email(self):
264 return self._email
264 return self._email
265
265
266 @email.setter
266 @email.setter
267 def email(self, val):
267 def email(self, val):
268 self._email = val.lower() if val else None
268 self._email = val.lower() if val else None
269
269
270 @property
270 @property
271 def firstname(self):
271 def firstname(self):
272 # alias for future
272 # alias for future
273 return self.name
273 return self.name
274
274
275 @property
275 @property
276 def username_and_name(self):
276 def username_and_name(self):
277 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
277 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
278
278
279 @property
279 @property
280 def full_name(self):
280 def full_name(self):
281 return '%s %s' % (self.firstname, self.lastname)
281 return '%s %s' % (self.firstname, self.lastname)
282
282
283 @property
283 @property
284 def full_contact(self):
284 def full_contact(self):
285 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
285 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
286
286
287 @property
287 @property
288 def short_contact(self):
288 def short_contact(self):
289 return '%s %s' % (self.firstname, self.lastname)
289 return '%s %s' % (self.firstname, self.lastname)
290
290
291 @property
291 @property
292 def is_admin(self):
292 def is_admin(self):
293 return self.admin
293 return self.admin
294
294
295 @classmethod
295 @classmethod
296 def get_by_username(cls, username, case_insensitive=False, cache=False):
296 def get_by_username(cls, username, case_insensitive=False, cache=False):
297 if case_insensitive:
297 if case_insensitive:
298 q = cls.query().filter(cls.username.ilike(username))
298 q = cls.query().filter(cls.username.ilike(username))
299 else:
299 else:
300 q = cls.query().filter(cls.username == username)
300 q = cls.query().filter(cls.username == username)
301
301
302 if cache:
302 if cache:
303 q = q.options(FromCache(
303 q = q.options(FromCache(
304 "sql_cache_short",
304 "sql_cache_short",
305 "get_user_%s" % _hash_key(username)
305 "get_user_%s" % _hash_key(username)
306 )
306 )
307 )
307 )
308 return q.scalar()
308 return q.scalar()
309
309
310 @classmethod
310 @classmethod
311 def get_by_auth_token(cls, auth_token, cache=False):
311 def get_by_auth_token(cls, auth_token, cache=False):
312 q = cls.query().filter(cls.api_key == auth_token)
312 q = cls.query().filter(cls.api_key == auth_token)
313
313
314 if cache:
314 if cache:
315 q = q.options(FromCache("sql_cache_short",
315 q = q.options(FromCache("sql_cache_short",
316 "get_auth_token_%s" % auth_token))
316 "get_auth_token_%s" % auth_token))
317 return q.scalar()
317 return q.scalar()
318
318
319 @classmethod
319 @classmethod
320 def get_by_email(cls, email, case_insensitive=False, cache=False):
320 def get_by_email(cls, email, case_insensitive=False, cache=False):
321 if case_insensitive:
321 if case_insensitive:
322 q = cls.query().filter(cls.email.ilike(email))
322 q = cls.query().filter(cls.email.ilike(email))
323 else:
323 else:
324 q = cls.query().filter(cls.email == email)
324 q = cls.query().filter(cls.email == email)
325
325
326 if cache:
326 if cache:
327 q = q.options(FromCache("sql_cache_short",
327 q = q.options(FromCache("sql_cache_short",
328 "get_email_key_%s" % email))
328 "get_email_key_%s" % email))
329
329
330 ret = q.scalar()
330 ret = q.scalar()
331 if ret is None:
331 if ret is None:
332 q = UserEmailMap.query()
332 q = UserEmailMap.query()
333 # try fetching in alternate email map
333 # try fetching in alternate email map
334 if case_insensitive:
334 if case_insensitive:
335 q = q.filter(UserEmailMap.email.ilike(email))
335 q = q.filter(UserEmailMap.email.ilike(email))
336 else:
336 else:
337 q = q.filter(UserEmailMap.email == email)
337 q = q.filter(UserEmailMap.email == email)
338 q = q.options(joinedload(UserEmailMap.user))
338 q = q.options(joinedload(UserEmailMap.user))
339 if cache:
339 if cache:
340 q = q.options(FromCache("sql_cache_short",
340 q = q.options(FromCache("sql_cache_short",
341 "get_email_map_key_%s" % email))
341 "get_email_map_key_%s" % email))
342 ret = getattr(q.scalar(), 'user', None)
342 ret = getattr(q.scalar(), 'user', None)
343
343
344 return ret
344 return ret
345
345
346 @classmethod
346 @classmethod
347 def get_first_admin(cls):
347 def get_first_admin(cls):
348 user = User.query().filter(User.admin == True).first()
348 user = User.query().filter(User.admin == True).first()
349 if user is None:
349 if user is None:
350 raise Exception('Missing administrative account!')
350 raise Exception('Missing administrative account!')
351 return user
351 return user
352
352
353 @classmethod
353 @classmethod
354 def get_default_user(cls, cache=False):
354 def get_default_user(cls, cache=False):
355 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
355 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
356 if user is None:
356 if user is None:
357 raise Exception('Missing default account!')
357 raise Exception('Missing default account!')
358 return user
358 return user
359
359
360
360
361
361
362
362
363 class UserEmailMap(Base, BaseModel):
363 class UserEmailMap(Base, BaseModel):
364 __tablename__ = 'user_email_map'
364 __tablename__ = 'user_email_map'
365 __table_args__ = (
365 __table_args__ = (
366 Index('uem_email_idx', 'email'),
366 Index('uem_email_idx', 'email'),
367 UniqueConstraint('email'),
367 UniqueConstraint('email'),
368 {'extend_existing': True, 'mysql_engine': 'InnoDB',
368 {'extend_existing': True, 'mysql_engine': 'InnoDB',
369 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
369 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
370 )
370 )
371 __mapper_args__ = {}
371 __mapper_args__ = {}
372
372
373 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
373 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
374 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
374 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
375 _email = Column("email", String(255), nullable=True, unique=False, default=None)
375 _email = Column("email", String(255), nullable=True, unique=False, default=None)
376 user = relationship('User', lazy='joined')
376 user = relationship('User', lazy='joined')
377
377
378 @validates('_email')
378 @validates('_email')
379 def validate_email(self, key, email):
379 def validate_email(self, key, email):
380 # check if this email is not main one
380 # check if this email is not main one
381 main_email = Session().query(User).filter(User.email == email).scalar()
381 main_email = Session().query(User).filter(User.email == email).scalar()
382 if main_email is not None:
382 if main_email is not None:
383 raise AttributeError('email %s is present is user table' % email)
383 raise AttributeError('email %s is present is user table' % email)
384 return email
384 return email
385
385
386 @hybrid_property
386 @hybrid_property
387 def email(self):
387 def email(self):
388 return self._email
388 return self._email
389
389
390 @email.setter
390 @email.setter
391 def email(self, val):
391 def email(self, val):
392 self._email = val.lower() if val else None
392 self._email = val.lower() if val else None
393
393
394
394
395 class UserIpMap(Base, BaseModel):
395 class UserIpMap(Base, BaseModel):
396 __tablename__ = 'user_ip_map'
396 __tablename__ = 'user_ip_map'
397 __table_args__ = (
397 __table_args__ = (
398 UniqueConstraint('user_id', 'ip_addr'),
398 UniqueConstraint('user_id', 'ip_addr'),
399 {'extend_existing': True, 'mysql_engine': 'InnoDB',
399 {'extend_existing': True, 'mysql_engine': 'InnoDB',
400 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
400 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
401 )
401 )
402 __mapper_args__ = {}
402 __mapper_args__ = {}
403
403
404 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
404 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
405 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
405 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
406 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
406 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
407 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
407 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
408 user = relationship('User', lazy='joined')
408 user = relationship('User', lazy='joined')
409
409
410
410
411 class UserLog(Base, BaseModel):
411 class UserLog(Base, BaseModel):
412 __tablename__ = 'user_logs'
412 __tablename__ = 'user_logs'
413 __table_args__ = (
413 __table_args__ = (
414 {'extend_existing': True, 'mysql_engine': 'InnoDB',
414 {'extend_existing': True, 'mysql_engine': 'InnoDB',
415 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
415 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
416 )
416 )
417 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
417 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
418 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
418 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
419 username = Column("username", String(255), nullable=True, unique=None, default=None)
419 username = Column("username", String(255), nullable=True, unique=None, default=None)
420 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
420 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
421 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
421 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
422 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
422 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
423 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
423 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
424 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
424 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
425
425
426 def __unicode__(self):
426 def __unicode__(self):
427 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
427 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
428 self.repository_name,
428 self.repository_name,
429 self.action)
429 self.action)
430
430
431 user = relationship('User')
431 user = relationship('User')
432 repository = relationship('Repository', cascade='')
432 repository = relationship('Repository', cascade='')
433
433
434
434
435 class UserGroup(Base, BaseModel):
435 class UserGroup(Base, BaseModel):
436 __tablename__ = 'users_groups'
436 __tablename__ = 'users_groups'
437 __table_args__ = (
437 __table_args__ = (
438 {'extend_existing': True, 'mysql_engine': 'InnoDB',
438 {'extend_existing': True, 'mysql_engine': 'InnoDB',
439 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
439 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
440 )
440 )
441
441
442 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
442 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
443 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
443 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
444 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
444 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
445 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
445 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
446 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
446 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
447
447
448 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
448 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
449 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
449 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
450 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
450 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
451 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
451 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
452 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
452 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
453 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
453 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
454
454
455 user = relationship('User')
455 user = relationship('User')
456
456
457 def __unicode__(self):
457 def __unicode__(self):
458 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
458 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
459 self.users_group_id,
459 self.users_group_id,
460 self.users_group_name)
460 self.users_group_name)
461
461
462 @classmethod
462 @classmethod
463 def get_by_group_name(cls, group_name, cache=False,
463 def get_by_group_name(cls, group_name, cache=False,
464 case_insensitive=False):
464 case_insensitive=False):
465 if case_insensitive:
465 if case_insensitive:
466 q = cls.query().filter(cls.users_group_name.ilike(group_name))
466 q = cls.query().filter(cls.users_group_name.ilike(group_name))
467 else:
467 else:
468 q = cls.query().filter(cls.users_group_name == group_name)
468 q = cls.query().filter(cls.users_group_name == group_name)
469 if cache:
469 if cache:
470 q = q.options(FromCache(
470 q = q.options(FromCache(
471 "sql_cache_short",
471 "sql_cache_short",
472 "get_user_%s" % _hash_key(group_name)
472 "get_user_%s" % _hash_key(group_name)
473 )
473 )
474 )
474 )
475 return q.scalar()
475 return q.scalar()
476
476
477 @classmethod
477 @classmethod
478 def get(cls, user_group_id, cache=False):
478 def get(cls, user_group_id, cache=False):
479 user_group = cls.query()
479 user_group = cls.query()
480 if cache:
480 if cache:
481 user_group = user_group.options(FromCache("sql_cache_short",
481 user_group = user_group.options(FromCache("sql_cache_short",
482 "get_users_group_%s" % user_group_id))
482 "get_users_group_%s" % user_group_id))
483 return user_group.get(user_group_id)
483 return user_group.get(user_group_id)
484
484
485
485
486 class UserGroupMember(Base, BaseModel):
486 class UserGroupMember(Base, BaseModel):
487 __tablename__ = 'users_groups_members'
487 __tablename__ = 'users_groups_members'
488 __table_args__ = (
488 __table_args__ = (
489 {'extend_existing': True, 'mysql_engine': 'InnoDB',
489 {'extend_existing': True, 'mysql_engine': 'InnoDB',
490 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
490 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
491 )
491 )
492
492
493 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
493 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
494 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
494 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
495 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
495 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
496
496
497 user = relationship('User', lazy='joined')
497 user = relationship('User', lazy='joined')
498 users_group = relationship('UserGroup')
498 users_group = relationship('UserGroup')
499
499
500 def __init__(self, gr_id='', u_id=''):
500 def __init__(self, gr_id='', u_id=''):
501 self.users_group_id = gr_id
501 self.users_group_id = gr_id
502 self.user_id = u_id
502 self.user_id = u_id
503
503
504
504
505 class RepositoryField(Base, BaseModel):
505 class RepositoryField(Base, BaseModel):
506 __tablename__ = 'repositories_fields'
506 __tablename__ = 'repositories_fields'
507 __table_args__ = (
507 __table_args__ = (
508 UniqueConstraint('repository_id', 'field_key'), # no-multi field
508 UniqueConstraint('repository_id', 'field_key'), # no-multi field
509 {'extend_existing': True, 'mysql_engine': 'InnoDB',
509 {'extend_existing': True, 'mysql_engine': 'InnoDB',
510 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
510 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
511 )
511 )
512 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
512 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
513
513
514 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
514 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
515 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
515 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
516 field_key = Column("field_key", String(250))
516 field_key = Column("field_key", String(250))
517 field_label = Column("field_label", String(1024), nullable=False)
517 field_label = Column("field_label", String(1024), nullable=False)
518 field_value = Column("field_value", String(10000), nullable=False)
518 field_value = Column("field_value", String(10000), nullable=False)
519 field_desc = Column("field_desc", String(1024), nullable=False)
519 field_desc = Column("field_desc", String(1024), nullable=False)
520 field_type = Column("field_type", String(256), nullable=False, unique=None)
520 field_type = Column("field_type", String(256), nullable=False, unique=None)
521 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
521 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
522
522
523 repository = relationship('Repository')
523 repository = relationship('Repository')
524
524
525 @classmethod
525 @classmethod
526 def get_by_key_name(cls, key, repo):
526 def get_by_key_name(cls, key, repo):
527 row = cls.query()\
527 row = cls.query()\
528 .filter(cls.repository == repo)\
528 .filter(cls.repository == repo)\
529 .filter(cls.field_key == key).scalar()
529 .filter(cls.field_key == key).scalar()
530 return row
530 return row
531
531
532
532
533 class Repository(Base, BaseModel):
533 class Repository(Base, BaseModel):
534 __tablename__ = 'repositories'
534 __tablename__ = 'repositories'
535 __table_args__ = (
535 __table_args__ = (
536 UniqueConstraint('repo_name'),
536 UniqueConstraint('repo_name'),
537 Index('r_repo_name_idx', 'repo_name'),
537 Index('r_repo_name_idx', 'repo_name'),
538 {'extend_existing': True, 'mysql_engine': 'InnoDB',
538 {'extend_existing': True, 'mysql_engine': 'InnoDB',
539 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
539 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
540 )
540 )
541
541
542 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
542 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
543 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
543 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
544 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
544 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
545 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
545 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
546 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
546 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
547 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
547 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
548 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
548 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
549 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
549 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
550 description = Column("description", String(10000), nullable=True, unique=None, default=None)
550 description = Column("description", String(10000), nullable=True, unique=None, default=None)
551 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
551 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
552 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
552 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
553 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
553 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
554 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
554 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
555 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
555 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
556 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
556 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
557
557
558 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
558 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
559 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
559 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
560
560
561 user = relationship('User')
561 user = relationship('User')
562 fork = relationship('Repository', remote_side=repo_id)
562 fork = relationship('Repository', remote_side=repo_id)
563 group = relationship('RepoGroup')
563 group = relationship('RepoGroup')
564 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
564 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
565 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
565 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
566 stats = relationship('Statistics', cascade='all', uselist=False)
566 stats = relationship('Statistics', cascade='all', uselist=False)
567
567
568 followers = relationship('UserFollowing',
568 followers = relationship('UserFollowing',
569 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
569 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
570 cascade='all')
570 cascade='all')
571 extra_fields = relationship('RepositoryField',
571 extra_fields = relationship('RepositoryField',
572 cascade="all, delete, delete-orphan")
572 cascade="all, delete, delete-orphan")
573
573
574 logs = relationship('UserLog')
574 logs = relationship('UserLog')
575 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
575 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
576
576
577 pull_requests_org = relationship('PullRequest',
577 pull_requests_org = relationship('PullRequest',
578 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
578 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
579 cascade="all, delete, delete-orphan")
579 cascade="all, delete, delete-orphan")
580
580
581 pull_requests_other = relationship('PullRequest',
581 pull_requests_other = relationship('PullRequest',
582 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
582 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
583 cascade="all, delete, delete-orphan")
583 cascade="all, delete, delete-orphan")
584
584
585 def __unicode__(self):
585 def __unicode__(self):
586 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
586 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
587 safe_unicode(self.repo_name))
587 safe_unicode(self.repo_name))
588
588
589 @classmethod
589 @classmethod
590 def get_by_repo_name(cls, repo_name):
590 def get_by_repo_name(cls, repo_name):
591 q = Session().query(cls).filter(cls.repo_name == repo_name)
591 q = Session().query(cls).filter(cls.repo_name == repo_name)
592 q = q.options(joinedload(Repository.fork))\
592 q = q.options(joinedload(Repository.fork))\
593 .options(joinedload(Repository.user))\
593 .options(joinedload(Repository.user))\
594 .options(joinedload(Repository.group))
594 .options(joinedload(Repository.group))
595 return q.scalar()
595 return q.scalar()
596
596
597
597
598 class RepoGroup(Base, BaseModel):
598 class RepoGroup(Base, BaseModel):
599 __tablename__ = 'groups'
599 __tablename__ = 'groups'
600 __table_args__ = (
600 __table_args__ = (
601 UniqueConstraint('group_name', 'group_parent_id'),
601 UniqueConstraint('group_name', 'group_parent_id'),
602 CheckConstraint('group_id != group_parent_id'),
602 CheckConstraint('group_id != group_parent_id'),
603 {'extend_existing': True, 'mysql_engine': 'InnoDB',
603 {'extend_existing': True, 'mysql_engine': 'InnoDB',
604 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
604 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
605 )
605 )
606 __mapper_args__ = {'order_by': 'group_name'}
606 __mapper_args__ = {'order_by': 'group_name'}
607
607
608 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
608 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
609 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
609 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
610 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
610 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
611 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
611 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
612 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
612 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
613 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
613 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
614
614
615 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
615 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
616 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
616 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
617 parent_group = relationship('RepoGroup', remote_side=group_id)
617 parent_group = relationship('RepoGroup', remote_side=group_id)
618 user = relationship('User')
618 user = relationship('User')
619
619
620 def __init__(self, group_name='', parent_group=None):
620 def __init__(self, group_name='', parent_group=None):
621 self.group_name = group_name
621 self.group_name = group_name
622 self.parent_group = parent_group
622 self.parent_group = parent_group
623
623
624 def __unicode__(self):
624 def __unicode__(self):
625 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
625 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
626 self.group_name)
626 self.group_name)
627
627
628 @classmethod
628 @classmethod
629 def url_sep(cls):
629 def url_sep(cls):
630 return URL_SEP
630 return URL_SEP
631
631
632 @classmethod
632 @classmethod
633 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
633 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
634 if case_insensitive:
634 if case_insensitive:
635 gr = cls.query()\
635 gr = cls.query()\
636 .filter(cls.group_name.ilike(group_name))
636 .filter(cls.group_name.ilike(group_name))
637 else:
637 else:
638 gr = cls.query()\
638 gr = cls.query()\
639 .filter(cls.group_name == group_name)
639 .filter(cls.group_name == group_name)
640 if cache:
640 if cache:
641 gr = gr.options(FromCache(
641 gr = gr.options(FromCache(
642 "sql_cache_short",
642 "sql_cache_short",
643 "get_group_%s" % _hash_key(group_name)
643 "get_group_%s" % _hash_key(group_name)
644 )
644 )
645 )
645 )
646 return gr.scalar()
646 return gr.scalar()
647
647
648
648
649 class Permission(Base, BaseModel):
649 class Permission(Base, BaseModel):
650 __tablename__ = 'permissions'
650 __tablename__ = 'permissions'
651 __table_args__ = (
651 __table_args__ = (
652 Index('p_perm_name_idx', 'permission_name'),
652 Index('p_perm_name_idx', 'permission_name'),
653 {'extend_existing': True, 'mysql_engine': 'InnoDB',
653 {'extend_existing': True, 'mysql_engine': 'InnoDB',
654 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
654 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
655 )
655 )
656 PERMS = [
656 PERMS = [
657 ('hg.admin', _('RhodeCode Administrator')),
657 ('hg.admin', _('RhodeCode Administrator')),
658
658
659 ('repository.none', _('Repository no access')),
659 ('repository.none', _('Repository no access')),
660 ('repository.read', _('Repository read access')),
660 ('repository.read', _('Repository read access')),
661 ('repository.write', _('Repository write access')),
661 ('repository.write', _('Repository write access')),
662 ('repository.admin', _('Repository admin access')),
662 ('repository.admin', _('Repository admin access')),
663
663
664 ('group.none', _('Repository group no access')),
664 ('group.none', _('Repository group no access')),
665 ('group.read', _('Repository group read access')),
665 ('group.read', _('Repository group read access')),
666 ('group.write', _('Repository group write access')),
666 ('group.write', _('Repository group write access')),
667 ('group.admin', _('Repository group admin access')),
667 ('group.admin', _('Repository group admin access')),
668
668
669 ('usergroup.none', _('User group no access')),
669 ('usergroup.none', _('User group no access')),
670 ('usergroup.read', _('User group read access')),
670 ('usergroup.read', _('User group read access')),
671 ('usergroup.write', _('User group write access')),
671 ('usergroup.write', _('User group write access')),
672 ('usergroup.admin', _('User group admin access')),
672 ('usergroup.admin', _('User group admin access')),
673
673
674 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
674 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
675 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
675 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
676
676
677 ('hg.usergroup.create.false', _('User Group creation disabled')),
677 ('hg.usergroup.create.false', _('User Group creation disabled')),
678 ('hg.usergroup.create.true', _('User Group creation enabled')),
678 ('hg.usergroup.create.true', _('User Group creation enabled')),
679
679
680 ('hg.create.none', _('Repository creation disabled')),
680 ('hg.create.none', _('Repository creation disabled')),
681 ('hg.create.repository', _('Repository creation enabled')),
681 ('hg.create.repository', _('Repository creation enabled')),
682
682
683 ('hg.fork.none', _('Repository forking disabled')),
683 ('hg.fork.none', _('Repository forking disabled')),
684 ('hg.fork.repository', _('Repository forking enabled')),
684 ('hg.fork.repository', _('Repository forking enabled')),
685
685
686 ('hg.register.none', _('Registration disabled')),
686 ('hg.register.none', _('Registration disabled')),
687 ('hg.register.manual_activate', _('User Registration with manual account activation')),
687 ('hg.register.manual_activate', _('User Registration with manual account activation')),
688 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
688 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
689
689
690 ('hg.extern_activate.manual', _('Manual activation of external account')),
690 ('hg.extern_activate.manual', _('Manual activation of external account')),
691 ('hg.extern_activate.auto', _('Automatic activation of external account')),
691 ('hg.extern_activate.auto', _('Automatic activation of external account')),
692
692
693 ]
693 ]
694
694
695 #definition of system default permissions for DEFAULT user
695 #definition of system default permissions for DEFAULT user
696 DEFAULT_USER_PERMISSIONS = [
696 DEFAULT_USER_PERMISSIONS = [
697 'repository.read',
697 'repository.read',
698 'group.read',
698 'group.read',
699 'usergroup.read',
699 'usergroup.read',
700 'hg.create.repository',
700 'hg.create.repository',
701 'hg.fork.repository',
701 'hg.fork.repository',
702 'hg.register.manual_activate',
702 'hg.register.manual_activate',
703 'hg.extern_activate.auto',
703 'hg.extern_activate.auto',
704 ]
704 ]
705
705
706 # defines which permissions are more important higher the more important
706 # defines which permissions are more important higher the more important
707 # Weight defines which permissions are more important.
707 # Weight defines which permissions are more important.
708 # The higher number the more important.
708 # The higher number the more important.
709 PERM_WEIGHTS = {
709 PERM_WEIGHTS = {
710 'repository.none': 0,
710 'repository.none': 0,
711 'repository.read': 1,
711 'repository.read': 1,
712 'repository.write': 3,
712 'repository.write': 3,
713 'repository.admin': 4,
713 'repository.admin': 4,
714
714
715 'group.none': 0,
715 'group.none': 0,
716 'group.read': 1,
716 'group.read': 1,
717 'group.write': 3,
717 'group.write': 3,
718 'group.admin': 4,
718 'group.admin': 4,
719
719
720 'usergroup.none': 0,
720 'usergroup.none': 0,
721 'usergroup.read': 1,
721 'usergroup.read': 1,
722 'usergroup.write': 3,
722 'usergroup.write': 3,
723 'usergroup.admin': 4,
723 'usergroup.admin': 4,
724 'hg.repogroup.create.false': 0,
724 'hg.repogroup.create.false': 0,
725 'hg.repogroup.create.true': 1,
725 'hg.repogroup.create.true': 1,
726
726
727 'hg.usergroup.create.false': 0,
727 'hg.usergroup.create.false': 0,
728 'hg.usergroup.create.true': 1,
728 'hg.usergroup.create.true': 1,
729
729
730 'hg.fork.none': 0,
730 'hg.fork.none': 0,
731 'hg.fork.repository': 1,
731 'hg.fork.repository': 1,
732 'hg.create.none': 0,
732 'hg.create.none': 0,
733 'hg.create.repository': 1
733 'hg.create.repository': 1
734 }
734 }
735
735
736 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
736 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
737 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
737 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
738 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
738 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
739
739
740 def __unicode__(self):
740 def __unicode__(self):
741 return u"<%s('%s:%s')>" % (
741 return u"<%s('%s:%s')>" % (
742 self.__class__.__name__, self.permission_id, self.permission_name
742 self.__class__.__name__, self.permission_id, self.permission_name
743 )
743 )
744
744
745 @classmethod
745 @classmethod
746 def get_by_key(cls, key):
746 def get_by_key(cls, key):
747 return cls.query().filter(cls.permission_name == key).scalar()
747 return cls.query().filter(cls.permission_name == key).scalar()
748
748
749
749
750 class UserRepoToPerm(Base, BaseModel):
750 class UserRepoToPerm(Base, BaseModel):
751 __tablename__ = 'repo_to_perm'
751 __tablename__ = 'repo_to_perm'
752 __table_args__ = (
752 __table_args__ = (
753 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
753 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
754 {'extend_existing': True, 'mysql_engine': 'InnoDB',
754 {'extend_existing': True, 'mysql_engine': 'InnoDB',
755 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
755 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
756 )
756 )
757 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
757 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
758 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
758 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
759 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
759 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
760 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
760 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
761
761
762 user = relationship('User')
762 user = relationship('User')
763 repository = relationship('Repository')
763 repository = relationship('Repository')
764 permission = relationship('Permission')
764 permission = relationship('Permission')
765
765
766 def __unicode__(self):
766 def __unicode__(self):
767 return u'<%s => %s >' % (self.user, self.repository)
767 return u'<%s => %s >' % (self.user, self.repository)
768
768
769
769
770 class UserUserGroupToPerm(Base, BaseModel):
770 class UserUserGroupToPerm(Base, BaseModel):
771 __tablename__ = 'user_user_group_to_perm'
771 __tablename__ = 'user_user_group_to_perm'
772 __table_args__ = (
772 __table_args__ = (
773 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
773 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
774 {'extend_existing': True, 'mysql_engine': 'InnoDB',
774 {'extend_existing': True, 'mysql_engine': 'InnoDB',
775 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
775 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
776 )
776 )
777 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
777 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
778 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
778 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
779 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
779 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
780 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
780 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
781
781
782 user = relationship('User')
782 user = relationship('User')
783 user_group = relationship('UserGroup')
783 user_group = relationship('UserGroup')
784 permission = relationship('Permission')
784 permission = relationship('Permission')
785
785
786 def __unicode__(self):
786 def __unicode__(self):
787 return u'<%s => %s >' % (self.user, self.user_group)
787 return u'<%s => %s >' % (self.user, self.user_group)
788
788
789
789
790 class UserToPerm(Base, BaseModel):
790 class UserToPerm(Base, BaseModel):
791 __tablename__ = 'user_to_perm'
791 __tablename__ = 'user_to_perm'
792 __table_args__ = (
792 __table_args__ = (
793 UniqueConstraint('user_id', 'permission_id'),
793 UniqueConstraint('user_id', 'permission_id'),
794 {'extend_existing': True, 'mysql_engine': 'InnoDB',
794 {'extend_existing': True, 'mysql_engine': 'InnoDB',
795 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
795 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
796 )
796 )
797 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
797 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
798 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
798 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
799 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
799 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
800
800
801 user = relationship('User')
801 user = relationship('User')
802 permission = relationship('Permission', lazy='joined')
802 permission = relationship('Permission', lazy='joined')
803
803
804 def __unicode__(self):
804 def __unicode__(self):
805 return u'<%s => %s >' % (self.user, self.permission)
805 return u'<%s => %s >' % (self.user, self.permission)
806
806
807
807
808 class UserGroupRepoToPerm(Base, BaseModel):
808 class UserGroupRepoToPerm(Base, BaseModel):
809 __tablename__ = 'users_group_repo_to_perm'
809 __tablename__ = 'users_group_repo_to_perm'
810 __table_args__ = (
810 __table_args__ = (
811 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
811 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
812 {'extend_existing': True, 'mysql_engine': 'InnoDB',
812 {'extend_existing': True, 'mysql_engine': 'InnoDB',
813 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
813 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
814 )
814 )
815 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
815 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
816 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
816 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
817 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
817 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
818 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
818 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
819
819
820 users_group = relationship('UserGroup')
820 users_group = relationship('UserGroup')
821 permission = relationship('Permission')
821 permission = relationship('Permission')
822 repository = relationship('Repository')
822 repository = relationship('Repository')
823
823
824 def __unicode__(self):
824 def __unicode__(self):
825 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
825 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
826
826
827
827
828 class UserGroupUserGroupToPerm(Base, BaseModel):
828 class UserGroupUserGroupToPerm(Base, BaseModel):
829 __tablename__ = 'user_group_user_group_to_perm'
829 __tablename__ = 'user_group_user_group_to_perm'
830 __table_args__ = (
830 __table_args__ = (
831 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
831 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
832 CheckConstraint('target_user_group_id != user_group_id'),
832 CheckConstraint('target_user_group_id != user_group_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_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
836 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)
837 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
837 target_user_group_id = Column("target_user_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 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
839 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
840
840
841 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
841 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
842 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
842 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
843 permission = relationship('Permission')
843 permission = relationship('Permission')
844
844
845 def __unicode__(self):
845 def __unicode__(self):
846 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
846 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
847
847
848
848
849 class UserGroupToPerm(Base, BaseModel):
849 class UserGroupToPerm(Base, BaseModel):
850 __tablename__ = 'users_group_to_perm'
850 __tablename__ = 'users_group_to_perm'
851 __table_args__ = (
851 __table_args__ = (
852 UniqueConstraint('users_group_id', 'permission_id',),
852 UniqueConstraint('users_group_id', 'permission_id',),
853 {'extend_existing': True, 'mysql_engine': 'InnoDB',
853 {'extend_existing': True, 'mysql_engine': 'InnoDB',
854 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
854 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
855 )
855 )
856 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
856 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
857 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
857 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
858 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
858 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
859
859
860 users_group = relationship('UserGroup')
860 users_group = relationship('UserGroup')
861 permission = relationship('Permission')
861 permission = relationship('Permission')
862
862
863
863
864 class UserRepoGroupToPerm(Base, BaseModel):
864 class UserRepoGroupToPerm(Base, BaseModel):
865 __tablename__ = 'user_repo_group_to_perm'
865 __tablename__ = 'user_repo_group_to_perm'
866 __table_args__ = (
866 __table_args__ = (
867 UniqueConstraint('user_id', 'group_id', 'permission_id'),
867 UniqueConstraint('user_id', '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
871
872 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
872 group_to_perm_id = Column("group_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 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
874 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
875 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
875 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
876
876
877 user = relationship('User')
877 user = relationship('User')
878 group = relationship('RepoGroup')
878 group = relationship('RepoGroup')
879 permission = relationship('Permission')
879 permission = relationship('Permission')
880
880
881
881
882 class UserGroupRepoGroupToPerm(Base, BaseModel):
882 class UserGroupRepoGroupToPerm(Base, BaseModel):
883 __tablename__ = 'users_group_repo_group_to_perm'
883 __tablename__ = 'users_group_repo_group_to_perm'
884 __table_args__ = (
884 __table_args__ = (
885 UniqueConstraint('users_group_id', 'group_id'),
885 UniqueConstraint('users_group_id', 'group_id'),
886 {'extend_existing': True, 'mysql_engine': 'InnoDB',
886 {'extend_existing': True, 'mysql_engine': 'InnoDB',
887 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
887 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
888 )
888 )
889
889
890 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)
890 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)
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 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
892 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
893 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
893 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_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 group = relationship('RepoGroup')
897 group = relationship('RepoGroup')
898
898
899
899
900 class Statistics(Base, BaseModel):
900 class Statistics(Base, BaseModel):
901 __tablename__ = 'statistics'
901 __tablename__ = 'statistics'
902 __table_args__ = (
902 __table_args__ = (
903 UniqueConstraint('repository_id'),
903 UniqueConstraint('repository_id'),
904 {'extend_existing': True, 'mysql_engine': 'InnoDB',
904 {'extend_existing': True, 'mysql_engine': 'InnoDB',
905 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
905 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
906 )
906 )
907 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
907 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
908 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
908 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
909 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
909 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
910 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
910 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
911 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
911 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
912 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
912 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
913
913
914 repository = relationship('Repository', single_parent=True)
914 repository = relationship('Repository', single_parent=True)
915
915
916
916
917 class UserFollowing(Base, BaseModel):
917 class UserFollowing(Base, BaseModel):
918 __tablename__ = 'user_followings'
918 __tablename__ = 'user_followings'
919 __table_args__ = (
919 __table_args__ = (
920 UniqueConstraint('user_id', 'follows_repository_id'),
920 UniqueConstraint('user_id', 'follows_repository_id'),
921 UniqueConstraint('user_id', 'follows_user_id'),
921 UniqueConstraint('user_id', 'follows_user_id'),
922 {'extend_existing': True, 'mysql_engine': 'InnoDB',
922 {'extend_existing': True, 'mysql_engine': 'InnoDB',
923 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
923 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
924 )
924 )
925
925
926 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
926 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
927 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
927 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
928 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
928 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
929 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
929 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
930 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
930 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
931
931
932 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
932 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
933
933
934 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
934 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
935 follows_repository = relationship('Repository', order_by='Repository.repo_name')
935 follows_repository = relationship('Repository', order_by='Repository.repo_name')
936
936
937
937
938 class CacheInvalidation(Base, BaseModel):
938 class CacheInvalidation(Base, BaseModel):
939 __tablename__ = 'cache_invalidation'
939 __tablename__ = 'cache_invalidation'
940 __table_args__ = (
940 __table_args__ = (
941 UniqueConstraint('cache_key'),
941 UniqueConstraint('cache_key'),
942 Index('key_idx', 'cache_key'),
942 Index('key_idx', 'cache_key'),
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 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
946 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
947 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
947 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
948 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
948 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
949 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
949 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
950
950
951 def __init__(self, cache_key, cache_args=''):
951 def __init__(self, cache_key, cache_args=''):
952 self.cache_key = cache_key
952 self.cache_key = cache_key
953 self.cache_args = cache_args
953 self.cache_args = cache_args
954 self.cache_active = False
954 self.cache_active = False
955
955
956
956
957 class ChangesetComment(Base, BaseModel):
957 class ChangesetComment(Base, BaseModel):
958 __tablename__ = 'changeset_comments'
958 __tablename__ = 'changeset_comments'
959 __table_args__ = (
959 __table_args__ = (
960 Index('cc_revision_idx', 'revision'),
960 Index('cc_revision_idx', 'revision'),
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 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
964 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
965 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
965 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
966 revision = Column('revision', String(40), nullable=True)
966 revision = Column('revision', String(40), nullable=True)
967 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
967 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
968 line_no = Column('line_no', Unicode(10), nullable=True)
968 line_no = Column('line_no', Unicode(10), nullable=True)
969 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
969 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
970 f_path = Column('f_path', Unicode(1000), nullable=True)
970 f_path = Column('f_path', Unicode(1000), nullable=True)
971 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
971 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
972 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
972 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
973 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
973 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
974 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
974 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
975
975
976 author = relationship('User', lazy='joined')
976 author = relationship('User', lazy='joined')
977 repo = relationship('Repository')
977 repo = relationship('Repository')
978 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
978 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
979 pull_request = relationship('PullRequest', lazy='joined')
979 pull_request = relationship('PullRequest', lazy='joined')
980
980
981
981
982 class ChangesetStatus(Base, BaseModel):
982 class ChangesetStatus(Base, BaseModel):
983 __tablename__ = 'changeset_statuses'
983 __tablename__ = 'changeset_statuses'
984 __table_args__ = (
984 __table_args__ = (
985 Index('cs_revision_idx', 'revision'),
985 Index('cs_revision_idx', 'revision'),
986 Index('cs_version_idx', 'version'),
986 Index('cs_version_idx', 'version'),
987 UniqueConstraint('repo_id', 'revision', 'version'),
987 UniqueConstraint('repo_id', 'revision', 'version'),
988 {'extend_existing': True, 'mysql_engine': 'InnoDB',
988 {'extend_existing': True, 'mysql_engine': 'InnoDB',
989 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
989 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
990 )
990 )
991 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
991 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
992 STATUS_APPROVED = 'approved'
992 STATUS_APPROVED = 'approved'
993 STATUS_REJECTED = 'rejected'
993 STATUS_REJECTED = 'rejected'
994 STATUS_UNDER_REVIEW = 'under_review'
994 STATUS_UNDER_REVIEW = 'under_review'
995
995
996 STATUSES = [
996 STATUSES = [
997 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
997 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
998 (STATUS_APPROVED, _("Approved")),
998 (STATUS_APPROVED, _("Approved")),
999 (STATUS_REJECTED, _("Rejected")),
999 (STATUS_REJECTED, _("Rejected")),
1000 (STATUS_UNDER_REVIEW, _("Under Review")),
1000 (STATUS_UNDER_REVIEW, _("Under Review")),
1001 ]
1001 ]
1002
1002
1003 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1003 changeset_status_id = Column('changeset_status_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 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1005 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1006 revision = Column('revision', String(40), nullable=False)
1006 revision = Column('revision', String(40), nullable=False)
1007 status = Column('status', String(128), nullable=False, default=DEFAULT)
1007 status = Column('status', String(128), nullable=False, default=DEFAULT)
1008 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1008 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1009 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1009 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1010 version = Column('version', Integer(), nullable=False, default=0)
1010 version = Column('version', Integer(), nullable=False, default=0)
1011 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1011 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1012
1012
1013 author = relationship('User', lazy='joined')
1013 author = relationship('User', lazy='joined')
1014 repo = relationship('Repository')
1014 repo = relationship('Repository')
1015 comment = relationship('ChangesetComment', lazy='joined')
1015 comment = relationship('ChangesetComment', lazy='joined')
1016 pull_request = relationship('PullRequest', lazy='joined')
1016 pull_request = relationship('PullRequest', lazy='joined')
1017
1017
1018
1018
1019
1019
1020 class PullRequest(Base, BaseModel):
1020 class PullRequest(Base, BaseModel):
1021 __tablename__ = 'pull_requests'
1021 __tablename__ = 'pull_requests'
1022 __table_args__ = (
1022 __table_args__ = (
1023 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1023 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1024 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1024 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1025 )
1025 )
1026
1026
1027 STATUS_NEW = u'new'
1027 STATUS_NEW = u'new'
1028 STATUS_OPEN = u'open'
1028 STATUS_OPEN = u'open'
1029 STATUS_CLOSED = u'closed'
1029 STATUS_CLOSED = u'closed'
1030
1030
1031 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1031 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1032 title = Column('title', Unicode(256), nullable=True)
1032 title = Column('title', Unicode(256), nullable=True)
1033 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1033 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1034 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1034 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1035 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1035 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1036 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1036 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1037 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1037 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1038 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1038 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1039 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1039 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1040 org_ref = Column('org_ref', Unicode(256), nullable=False)
1040 org_ref = Column('org_ref', Unicode(256), nullable=False)
1041 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1041 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1042 other_ref = Column('other_ref', Unicode(256), nullable=False)
1042 other_ref = Column('other_ref', Unicode(256), nullable=False)
1043
1043
1044 author = relationship('User', lazy='joined')
1044 author = relationship('User', lazy='joined')
1045 reviewers = relationship('PullRequestReviewers',
1045 reviewers = relationship('PullRequestReviewers',
1046 cascade="all, delete, delete-orphan")
1046 cascade="all, delete, delete-orphan")
1047 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1047 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1048 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1048 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1049 statuses = relationship('ChangesetStatus')
1049 statuses = relationship('ChangesetStatus')
1050 comments = relationship('ChangesetComment',
1050 comments = relationship('ChangesetComment',
1051 cascade="all, delete, delete-orphan")
1051 cascade="all, delete, delete-orphan")
1052
1052
1053
1053
1054 class PullRequestReviewers(Base, BaseModel):
1054 class PullRequestReviewers(Base, BaseModel):
1055 __tablename__ = 'pull_request_reviewers'
1055 __tablename__ = 'pull_request_reviewers'
1056 __table_args__ = (
1056 __table_args__ = (
1057 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1057 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1058 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1058 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1059 )
1059 )
1060
1060
1061 def __init__(self, user=None, pull_request=None):
1061 def __init__(self, user=None, pull_request=None):
1062 self.user = user
1062 self.user = user
1063 self.pull_request = pull_request
1063 self.pull_request = pull_request
1064
1064
1065 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1065 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1066 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1066 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1067 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1067 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1068
1068
1069 user = relationship('User')
1069 user = relationship('User')
1070 pull_request = relationship('PullRequest')
1070 pull_request = relationship('PullRequest')
1071
1071
1072
1072
1073 class Notification(Base, BaseModel):
1073 class Notification(Base, BaseModel):
1074 __tablename__ = 'notifications'
1074 __tablename__ = 'notifications'
1075 __table_args__ = (
1075 __table_args__ = (
1076 Index('notification_type_idx', 'type'),
1076 Index('notification_type_idx', 'type'),
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
1080
1081 TYPE_CHANGESET_COMMENT = u'cs_comment'
1081 TYPE_CHANGESET_COMMENT = u'cs_comment'
1082 TYPE_MESSAGE = u'message'
1082 TYPE_MESSAGE = u'message'
1083 TYPE_MENTION = u'mention'
1083 TYPE_MENTION = u'mention'
1084 TYPE_REGISTRATION = u'registration'
1084 TYPE_REGISTRATION = u'registration'
1085 TYPE_PULL_REQUEST = u'pull_request'
1085 TYPE_PULL_REQUEST = u'pull_request'
1086 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1086 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1087
1087
1088 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1088 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1089 subject = Column('subject', Unicode(512), nullable=True)
1089 subject = Column('subject', Unicode(512), nullable=True)
1090 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1090 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1091 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1091 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1092 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1092 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1093 type_ = Column('type', Unicode(256))
1093 type_ = Column('type', Unicode(256))
1094
1094
1095 created_by_user = relationship('User')
1095 created_by_user = relationship('User')
1096 notifications_to_users = relationship('UserNotification', lazy='joined',
1096 notifications_to_users = relationship('UserNotification', lazy='joined',
1097 cascade="all, delete, delete-orphan")
1097 cascade="all, delete, delete-orphan")
1098
1098
1099
1099
1100 class UserNotification(Base, BaseModel):
1100 class UserNotification(Base, BaseModel):
1101 __tablename__ = 'user_to_notification'
1101 __tablename__ = 'user_to_notification'
1102 __table_args__ = (
1102 __table_args__ = (
1103 UniqueConstraint('user_id', 'notification_id'),
1103 UniqueConstraint('user_id', 'notification_id'),
1104 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1104 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1105 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1105 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1106 )
1106 )
1107 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1107 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1108 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1108 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1109 read = Column('read', Boolean, default=False)
1109 read = Column('read', Boolean, default=False)
1110 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1110 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1111
1111
1112 user = relationship('User', lazy="joined")
1112 user = relationship('User', lazy="joined")
1113 notification = relationship('Notification', lazy="joined",
1113 notification = relationship('Notification', lazy="joined",
1114 order_by=lambda: Notification.created_on.desc(),)
1114 order_by=lambda: Notification.created_on.desc(),)
1115
1115
1116
1116
1117 class Gist(Base, BaseModel):
1117 class Gist(Base, BaseModel):
1118 __tablename__ = 'gists'
1118 __tablename__ = 'gists'
1119 __table_args__ = (
1119 __table_args__ = (
1120 Index('g_gist_access_id_idx', 'gist_access_id'),
1120 Index('g_gist_access_id_idx', 'gist_access_id'),
1121 Index('g_created_on_idx', 'created_on'),
1121 Index('g_created_on_idx', 'created_on'),
1122 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1122 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1123 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1123 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1124 )
1124 )
1125 GIST_PUBLIC = u'public'
1125 GIST_PUBLIC = u'public'
1126 GIST_PRIVATE = u'private'
1126 GIST_PRIVATE = u'private'
1127
1127
1128 gist_id = Column('gist_id', Integer(), primary_key=True)
1128 gist_id = Column('gist_id', Integer(), primary_key=True)
1129 gist_access_id = Column('gist_access_id', Unicode(250))
1129 gist_access_id = Column('gist_access_id', Unicode(250))
1130 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1130 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1131 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1131 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1132 gist_expires = Column('gist_expires', Float(53), nullable=False)
1132 gist_expires = Column('gist_expires', Float(53), nullable=False)
1133 gist_type = Column('gist_type', Unicode(128), nullable=False)
1133 gist_type = Column('gist_type', Unicode(128), nullable=False)
1134 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1134 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1135 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1135 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1136
1136
1137 owner = relationship('User')
1137 owner = relationship('User')
1138
1138
1139
1139
1140 class DbMigrateVersion(Base, BaseModel):
1140 class DbMigrateVersion(Base, BaseModel):
1141 __tablename__ = 'db_migrate_version'
1141 __tablename__ = 'db_migrate_version'
1142 __table_args__ = (
1142 __table_args__ = (
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 repository_id = Column('repository_id', String(250), primary_key=True)
1146 repository_id = Column('repository_id', String(250), primary_key=True)
1147 repository_path = Column('repository_path', Text)
1147 repository_path = Column('repository_path', Text)
1148 version = Column('version', Integer)
1148 version = Column('version', Integer)
@@ -1,1171 +1,1171 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
28 import functools
28 import functools
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.ext.hybrid import hybrid_property
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from beaker.cache import cache_region, region_invalidate
34 from beaker.cache import cache_region, region_invalidate
35 from webob.exc import HTTPNotFound
35 from webob.exc import HTTPNotFound
36
36
37 from pylons.i18n.translation import lazy_ugettext as _
37 from rhodecode.translation import _
38
38
39 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.utils.helpers import get_scm
41 from rhodecode.lib.vcs.exceptions import VCSError
41 from rhodecode.lib.vcs.exceptions import VCSError
42 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from zope.cachedescriptors.property import Lazy as LazyProperty
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
44
44
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
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.iteritems():
87 for k, val in _json_attr.iteritems():
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 return safe_str(self.__unicode__())
145 return safe_str(self.__unicode__())
146 return '<DB:%s>' % (self.__class__.__name__)
146 return '<DB:%s>' % (self.__class__.__name__)
147
147
148
148
149 class RhodeCodeSetting(Base, BaseModel):
149 class RhodeCodeSetting(Base, BaseModel):
150 SETTINGS_TYPES = {
150 SETTINGS_TYPES = {
151 'str': safe_str,
151 'str': safe_str,
152 'int': safe_int,
152 'int': safe_int,
153 'unicode': safe_unicode,
153 'unicode': safe_unicode,
154 'bool': str2bool,
154 'bool': str2bool,
155 'list': functools.partial(aslist, sep=',')
155 'list': functools.partial(aslist, sep=',')
156 }
156 }
157 __tablename__ = 'rhodecode_settings'
157 __tablename__ = 'rhodecode_settings'
158 __table_args__ = (
158 __table_args__ = (
159 UniqueConstraint('app_settings_name'),
159 UniqueConstraint('app_settings_name'),
160 {'extend_existing': True, 'mysql_engine': 'InnoDB',
160 {'extend_existing': True, 'mysql_engine': 'InnoDB',
161 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
161 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
162 )
162 )
163 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
163 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
164 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
164 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
165 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
165 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
166 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
166 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
167
167
168 def __init__(self, key='', val='', type='unicode'):
168 def __init__(self, key='', val='', type='unicode'):
169 self.app_settings_name = key
169 self.app_settings_name = key
170 self.app_settings_value = val
170 self.app_settings_value = val
171 self.app_settings_type = type
171 self.app_settings_type = type
172
172
173 @validates('_app_settings_value')
173 @validates('_app_settings_value')
174 def validate_settings_value(self, key, val):
174 def validate_settings_value(self, key, val):
175 assert type(val) == unicode
175 assert type(val) == unicode
176 return val
176 return val
177
177
178 @hybrid_property
178 @hybrid_property
179 def app_settings_value(self):
179 def app_settings_value(self):
180 v = self._app_settings_value
180 v = self._app_settings_value
181 _type = self.app_settings_type
181 _type = self.app_settings_type
182 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
182 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
183 return converter(v)
183 return converter(v)
184
184
185 @app_settings_value.setter
185 @app_settings_value.setter
186 def app_settings_value(self, val):
186 def app_settings_value(self, val):
187 """
187 """
188 Setter that will always make sure we use unicode in app_settings_value
188 Setter that will always make sure we use unicode in app_settings_value
189
189
190 :param val:
190 :param val:
191 """
191 """
192 self._app_settings_value = safe_unicode(val)
192 self._app_settings_value = safe_unicode(val)
193
193
194 @hybrid_property
194 @hybrid_property
195 def app_settings_type(self):
195 def app_settings_type(self):
196 return self._app_settings_type
196 return self._app_settings_type
197
197
198 @app_settings_type.setter
198 @app_settings_type.setter
199 def app_settings_type(self, val):
199 def app_settings_type(self, val):
200 if val not in self.SETTINGS_TYPES:
200 if val not in self.SETTINGS_TYPES:
201 raise Exception('type must be one of %s got %s'
201 raise Exception('type must be one of %s got %s'
202 % (self.SETTINGS_TYPES.keys(), val))
202 % (self.SETTINGS_TYPES.keys(), val))
203 self._app_settings_type = val
203 self._app_settings_type = val
204
204
205 def __unicode__(self):
205 def __unicode__(self):
206 return u"<%s('%s:%s[%s]')>" % (
206 return u"<%s('%s:%s[%s]')>" % (
207 self.__class__.__name__,
207 self.__class__.__name__,
208 self.app_settings_name, self.app_settings_value, self.app_settings_type
208 self.app_settings_name, self.app_settings_value, self.app_settings_type
209 )
209 )
210
210
211
211
212 class RhodeCodeUi(Base, BaseModel):
212 class RhodeCodeUi(Base, BaseModel):
213 __tablename__ = 'rhodecode_ui'
213 __tablename__ = 'rhodecode_ui'
214 __table_args__ = (
214 __table_args__ = (
215 UniqueConstraint('ui_key'),
215 UniqueConstraint('ui_key'),
216 {'extend_existing': True, 'mysql_engine': 'InnoDB',
216 {'extend_existing': True, 'mysql_engine': 'InnoDB',
217 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
217 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
218 )
218 )
219
219
220 HOOK_REPO_SIZE = 'changegroup.repo_size'
220 HOOK_REPO_SIZE = 'changegroup.repo_size'
221 HOOK_PUSH = 'changegroup.push_logger'
221 HOOK_PUSH = 'changegroup.push_logger'
222 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
222 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
223 HOOK_PULL = 'outgoing.pull_logger'
223 HOOK_PULL = 'outgoing.pull_logger'
224 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
224 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
225
225
226 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
226 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
227 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
227 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
228 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
228 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
229 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
229 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
230 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
230 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
231
231
232
232
233
233
234 class User(Base, BaseModel):
234 class User(Base, BaseModel):
235 __tablename__ = 'users'
235 __tablename__ = 'users'
236 __table_args__ = (
236 __table_args__ = (
237 UniqueConstraint('username'), UniqueConstraint('email'),
237 UniqueConstraint('username'), UniqueConstraint('email'),
238 Index('u_username_idx', 'username'),
238 Index('u_username_idx', 'username'),
239 Index('u_email_idx', 'email'),
239 Index('u_email_idx', 'email'),
240 {'extend_existing': True, 'mysql_engine': 'InnoDB',
240 {'extend_existing': True, 'mysql_engine': 'InnoDB',
241 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
241 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
242 )
242 )
243 DEFAULT_USER = 'default'
243 DEFAULT_USER = 'default'
244
244
245 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
245 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
246 username = Column("username", String(255), nullable=True, unique=None, default=None)
246 username = Column("username", String(255), nullable=True, unique=None, default=None)
247 password = Column("password", String(255), nullable=True, unique=None, default=None)
247 password = Column("password", String(255), nullable=True, unique=None, default=None)
248 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
248 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
249 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
249 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
250 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
250 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
251 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
251 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
252 _email = Column("email", String(255), nullable=True, unique=None, default=None)
252 _email = Column("email", String(255), nullable=True, unique=None, default=None)
253 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
253 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
254 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
254 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
255 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
255 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
256 #for migration reasons, this is going to be later deleted
256 #for migration reasons, this is going to be later deleted
257 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
257 ldap_dn = Column("ldap_dn", String(255), nullable=True, unique=None, default=None)
258
258
259 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
259 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
260 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
260 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
261 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
261 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
262
262
263 user_log = relationship('UserLog')
263 user_log = relationship('UserLog')
264 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
264 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
265
265
266 repositories = relationship('Repository')
266 repositories = relationship('Repository')
267 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
267 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
268 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
268 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
269
269
270 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
270 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
271 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
271 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
272
272
273 group_member = relationship('UserGroupMember', cascade='all')
273 group_member = relationship('UserGroupMember', cascade='all')
274
274
275 notifications = relationship('UserNotification', cascade='all')
275 notifications = relationship('UserNotification', cascade='all')
276 # notifications assigned to this user
276 # notifications assigned to this user
277 user_created_notifications = relationship('Notification', cascade='all')
277 user_created_notifications = relationship('Notification', cascade='all')
278 # comments created by this user
278 # comments created by this user
279 user_comments = relationship('ChangesetComment', cascade='all')
279 user_comments = relationship('ChangesetComment', cascade='all')
280 user_emails = relationship('UserEmailMap', cascade='all')
280 user_emails = relationship('UserEmailMap', cascade='all')
281
281
282 @hybrid_property
282 @hybrid_property
283 def email(self):
283 def email(self):
284 return self._email
284 return self._email
285
285
286 @email.setter
286 @email.setter
287 def email(self, val):
287 def email(self, val):
288 self._email = val.lower() if val else None
288 self._email = val.lower() if val else None
289
289
290 @property
290 @property
291 def firstname(self):
291 def firstname(self):
292 # alias for future
292 # alias for future
293 return self.name
293 return self.name
294
294
295 @property
295 @property
296 def username_and_name(self):
296 def username_and_name(self):
297 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
297 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
298
298
299 @property
299 @property
300 def full_name(self):
300 def full_name(self):
301 return '%s %s' % (self.firstname, self.lastname)
301 return '%s %s' % (self.firstname, self.lastname)
302
302
303 @property
303 @property
304 def full_contact(self):
304 def full_contact(self):
305 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
305 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
306
306
307 @property
307 @property
308 def short_contact(self):
308 def short_contact(self):
309 return '%s %s' % (self.firstname, self.lastname)
309 return '%s %s' % (self.firstname, self.lastname)
310
310
311 @property
311 @property
312 def is_admin(self):
312 def is_admin(self):
313 return self.admin
313 return self.admin
314
314
315 @classmethod
315 @classmethod
316 def get_by_username(cls, username, case_insensitive=False, cache=False):
316 def get_by_username(cls, username, case_insensitive=False, cache=False):
317 if case_insensitive:
317 if case_insensitive:
318 q = cls.query().filter(cls.username.ilike(username))
318 q = cls.query().filter(cls.username.ilike(username))
319 else:
319 else:
320 q = cls.query().filter(cls.username == username)
320 q = cls.query().filter(cls.username == username)
321
321
322 if cache:
322 if cache:
323 q = q.options(FromCache(
323 q = q.options(FromCache(
324 "sql_cache_short",
324 "sql_cache_short",
325 "get_user_%s" % _hash_key(username)
325 "get_user_%s" % _hash_key(username)
326 )
326 )
327 )
327 )
328 return q.scalar()
328 return q.scalar()
329
329
330 @classmethod
330 @classmethod
331 def get_by_auth_token(cls, auth_token, cache=False):
331 def get_by_auth_token(cls, auth_token, cache=False):
332 q = cls.query().filter(cls.api_key == auth_token)
332 q = cls.query().filter(cls.api_key == auth_token)
333
333
334 if cache:
334 if cache:
335 q = q.options(FromCache("sql_cache_short",
335 q = q.options(FromCache("sql_cache_short",
336 "get_auth_token_%s" % auth_token))
336 "get_auth_token_%s" % auth_token))
337 return q.scalar()
337 return q.scalar()
338
338
339 @classmethod
339 @classmethod
340 def get_by_email(cls, email, case_insensitive=False, cache=False):
340 def get_by_email(cls, email, case_insensitive=False, cache=False):
341 if case_insensitive:
341 if case_insensitive:
342 q = cls.query().filter(cls.email.ilike(email))
342 q = cls.query().filter(cls.email.ilike(email))
343 else:
343 else:
344 q = cls.query().filter(cls.email == email)
344 q = cls.query().filter(cls.email == email)
345
345
346 if cache:
346 if cache:
347 q = q.options(FromCache("sql_cache_short",
347 q = q.options(FromCache("sql_cache_short",
348 "get_email_key_%s" % email))
348 "get_email_key_%s" % email))
349
349
350 ret = q.scalar()
350 ret = q.scalar()
351 if ret is None:
351 if ret is None:
352 q = UserEmailMap.query()
352 q = UserEmailMap.query()
353 # try fetching in alternate email map
353 # try fetching in alternate email map
354 if case_insensitive:
354 if case_insensitive:
355 q = q.filter(UserEmailMap.email.ilike(email))
355 q = q.filter(UserEmailMap.email.ilike(email))
356 else:
356 else:
357 q = q.filter(UserEmailMap.email == email)
357 q = q.filter(UserEmailMap.email == email)
358 q = q.options(joinedload(UserEmailMap.user))
358 q = q.options(joinedload(UserEmailMap.user))
359 if cache:
359 if cache:
360 q = q.options(FromCache("sql_cache_short",
360 q = q.options(FromCache("sql_cache_short",
361 "get_email_map_key_%s" % email))
361 "get_email_map_key_%s" % email))
362 ret = getattr(q.scalar(), 'user', None)
362 ret = getattr(q.scalar(), 'user', None)
363
363
364 return ret
364 return ret
365
365
366 @classmethod
366 @classmethod
367 def get_first_admin(cls):
367 def get_first_admin(cls):
368 user = User.query().filter(User.admin == True).first()
368 user = User.query().filter(User.admin == True).first()
369 if user is None:
369 if user is None:
370 raise Exception('Missing administrative account!')
370 raise Exception('Missing administrative account!')
371 return user
371 return user
372
372
373 @classmethod
373 @classmethod
374 def get_default_user(cls, cache=False):
374 def get_default_user(cls, cache=False):
375 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
375 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
376 if user is None:
376 if user is None:
377 raise Exception('Missing default account!')
377 raise Exception('Missing default account!')
378 return user
378 return user
379
379
380
380
381
381
382
382
383 class UserEmailMap(Base, BaseModel):
383 class UserEmailMap(Base, BaseModel):
384 __tablename__ = 'user_email_map'
384 __tablename__ = 'user_email_map'
385 __table_args__ = (
385 __table_args__ = (
386 Index('uem_email_idx', 'email'),
386 Index('uem_email_idx', 'email'),
387 UniqueConstraint('email'),
387 UniqueConstraint('email'),
388 {'extend_existing': True, 'mysql_engine': 'InnoDB',
388 {'extend_existing': True, 'mysql_engine': 'InnoDB',
389 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
389 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
390 )
390 )
391 __mapper_args__ = {}
391 __mapper_args__ = {}
392
392
393 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
393 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
394 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
394 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
395 _email = Column("email", String(255), nullable=True, unique=False, default=None)
395 _email = Column("email", String(255), nullable=True, unique=False, default=None)
396 user = relationship('User', lazy='joined')
396 user = relationship('User', lazy='joined')
397
397
398 @validates('_email')
398 @validates('_email')
399 def validate_email(self, key, email):
399 def validate_email(self, key, email):
400 # check if this email is not main one
400 # check if this email is not main one
401 main_email = Session().query(User).filter(User.email == email).scalar()
401 main_email = Session().query(User).filter(User.email == email).scalar()
402 if main_email is not None:
402 if main_email is not None:
403 raise AttributeError('email %s is present is user table' % email)
403 raise AttributeError('email %s is present is user table' % email)
404 return email
404 return email
405
405
406 @hybrid_property
406 @hybrid_property
407 def email(self):
407 def email(self):
408 return self._email
408 return self._email
409
409
410 @email.setter
410 @email.setter
411 def email(self, val):
411 def email(self, val):
412 self._email = val.lower() if val else None
412 self._email = val.lower() if val else None
413
413
414
414
415 class UserIpMap(Base, BaseModel):
415 class UserIpMap(Base, BaseModel):
416 __tablename__ = 'user_ip_map'
416 __tablename__ = 'user_ip_map'
417 __table_args__ = (
417 __table_args__ = (
418 UniqueConstraint('user_id', 'ip_addr'),
418 UniqueConstraint('user_id', 'ip_addr'),
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
420 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
420 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
421 )
421 )
422 __mapper_args__ = {}
422 __mapper_args__ = {}
423
423
424 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
425 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
425 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
426 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
426 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
427 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
427 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
428 user = relationship('User', lazy='joined')
428 user = relationship('User', lazy='joined')
429
429
430
430
431 class UserLog(Base, BaseModel):
431 class UserLog(Base, BaseModel):
432 __tablename__ = 'user_logs'
432 __tablename__ = 'user_logs'
433 __table_args__ = (
433 __table_args__ = (
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 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
438 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
438 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
439 username = Column("username", String(255), nullable=True, unique=None, default=None)
439 username = Column("username", String(255), nullable=True, unique=None, default=None)
440 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
440 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
441 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
441 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
442 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
442 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
443 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
443 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
444 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
444 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
445
445
446 def __unicode__(self):
446 def __unicode__(self):
447 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
447 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
448 self.repository_name,
448 self.repository_name,
449 self.action)
449 self.action)
450
450
451 user = relationship('User')
451 user = relationship('User')
452 repository = relationship('Repository', cascade='')
452 repository = relationship('Repository', cascade='')
453
453
454
454
455 class UserGroup(Base, BaseModel):
455 class UserGroup(Base, BaseModel):
456 __tablename__ = 'users_groups'
456 __tablename__ = 'users_groups'
457 __table_args__ = (
457 __table_args__ = (
458 {'extend_existing': True, 'mysql_engine': 'InnoDB',
458 {'extend_existing': True, 'mysql_engine': 'InnoDB',
459 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
459 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
460 )
460 )
461
461
462 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
462 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
463 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
463 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
464 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
464 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
465 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
465 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
466 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
466 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
469
469
470 # don't trigger lazy load for migrations
470 # don't trigger lazy load for migrations
471 #members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
471 #members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
472 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
472 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
473 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
473 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
474 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
474 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
475 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
475 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
476 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
476 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
477
477
478 user = relationship('User')
478 user = relationship('User')
479
479
480 def __unicode__(self):
480 def __unicode__(self):
481 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
481 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
482 self.users_group_id,
482 self.users_group_id,
483 self.users_group_name)
483 self.users_group_name)
484
484
485 @classmethod
485 @classmethod
486 def get_by_group_name(cls, group_name, cache=False,
486 def get_by_group_name(cls, group_name, cache=False,
487 case_insensitive=False):
487 case_insensitive=False):
488 if case_insensitive:
488 if case_insensitive:
489 q = cls.query().filter(cls.users_group_name.ilike(group_name))
489 q = cls.query().filter(cls.users_group_name.ilike(group_name))
490 else:
490 else:
491 q = cls.query().filter(cls.users_group_name == group_name)
491 q = cls.query().filter(cls.users_group_name == group_name)
492 if cache:
492 if cache:
493 q = q.options(FromCache(
493 q = q.options(FromCache(
494 "sql_cache_short",
494 "sql_cache_short",
495 "get_user_%s" % _hash_key(group_name)
495 "get_user_%s" % _hash_key(group_name)
496 )
496 )
497 )
497 )
498 return q.scalar()
498 return q.scalar()
499
499
500 @classmethod
500 @classmethod
501 def get(cls, user_group_id, cache=False):
501 def get(cls, user_group_id, cache=False):
502 user_group = cls.query()
502 user_group = cls.query()
503 if cache:
503 if cache:
504 user_group = user_group.options(FromCache("sql_cache_short",
504 user_group = user_group.options(FromCache("sql_cache_short",
505 "get_users_group_%s" % user_group_id))
505 "get_users_group_%s" % user_group_id))
506 return user_group.get(user_group_id)
506 return user_group.get(user_group_id)
507
507
508
508
509 class UserGroupMember(Base, BaseModel):
509 class UserGroupMember(Base, BaseModel):
510 __tablename__ = 'users_groups_members'
510 __tablename__ = 'users_groups_members'
511 __table_args__ = (
511 __table_args__ = (
512 {'extend_existing': True, 'mysql_engine': 'InnoDB',
512 {'extend_existing': True, 'mysql_engine': 'InnoDB',
513 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
513 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
514 )
514 )
515
515
516 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
516 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
517 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
517 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
518 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
518 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
519
519
520 user = relationship('User', lazy='joined')
520 user = relationship('User', lazy='joined')
521 users_group = relationship('UserGroup')
521 users_group = relationship('UserGroup')
522
522
523 def __init__(self, gr_id='', u_id=''):
523 def __init__(self, gr_id='', u_id=''):
524 self.users_group_id = gr_id
524 self.users_group_id = gr_id
525 self.user_id = u_id
525 self.user_id = u_id
526
526
527
527
528 class RepositoryField(Base, BaseModel):
528 class RepositoryField(Base, BaseModel):
529 __tablename__ = 'repositories_fields'
529 __tablename__ = 'repositories_fields'
530 __table_args__ = (
530 __table_args__ = (
531 UniqueConstraint('repository_id', 'field_key'), # no-multi field
531 UniqueConstraint('repository_id', 'field_key'), # no-multi field
532 {'extend_existing': True, 'mysql_engine': 'InnoDB',
532 {'extend_existing': True, 'mysql_engine': 'InnoDB',
533 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
533 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
534 )
534 )
535 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
535 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
536
536
537 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
537 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
538 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
538 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
539 field_key = Column("field_key", String(250))
539 field_key = Column("field_key", String(250))
540 field_label = Column("field_label", String(1024), nullable=False)
540 field_label = Column("field_label", String(1024), nullable=False)
541 field_value = Column("field_value", String(10000), nullable=False)
541 field_value = Column("field_value", String(10000), nullable=False)
542 field_desc = Column("field_desc", String(1024), nullable=False)
542 field_desc = Column("field_desc", String(1024), nullable=False)
543 field_type = Column("field_type", String(256), nullable=False, unique=None)
543 field_type = Column("field_type", String(256), nullable=False, unique=None)
544 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
544 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
545
545
546 repository = relationship('Repository')
546 repository = relationship('Repository')
547
547
548 @classmethod
548 @classmethod
549 def get_by_key_name(cls, key, repo):
549 def get_by_key_name(cls, key, repo):
550 row = cls.query()\
550 row = cls.query()\
551 .filter(cls.repository == repo)\
551 .filter(cls.repository == repo)\
552 .filter(cls.field_key == key).scalar()
552 .filter(cls.field_key == key).scalar()
553 return row
553 return row
554
554
555
555
556 class Repository(Base, BaseModel):
556 class Repository(Base, BaseModel):
557 __tablename__ = 'repositories'
557 __tablename__ = 'repositories'
558 __table_args__ = (
558 __table_args__ = (
559 UniqueConstraint('repo_name'),
559 UniqueConstraint('repo_name'),
560 Index('r_repo_name_idx', 'repo_name'),
560 Index('r_repo_name_idx', 'repo_name'),
561 {'extend_existing': True, 'mysql_engine': 'InnoDB',
561 {'extend_existing': True, 'mysql_engine': 'InnoDB',
562 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
562 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
563 )
563 )
564
564
565 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
565 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
566 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
566 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
567 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
567 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
568 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
568 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
569 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
569 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
570 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
570 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
571 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
571 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
572 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
572 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
573 description = Column("description", String(10000), nullable=True, unique=None, default=None)
573 description = Column("description", String(10000), nullable=True, unique=None, default=None)
574 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
574 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
575 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
575 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
576 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
576 landing_rev = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
577 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
577 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
578 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
578 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
579 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
579 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
580
580
581 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
581 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
582 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
582 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
583
583
584 user = relationship('User')
584 user = relationship('User')
585 fork = relationship('Repository', remote_side=repo_id)
585 fork = relationship('Repository', remote_side=repo_id)
586 group = relationship('RepoGroup')
586 group = relationship('RepoGroup')
587 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
587 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
588 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
588 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
589 stats = relationship('Statistics', cascade='all', uselist=False)
589 stats = relationship('Statistics', cascade='all', uselist=False)
590
590
591 followers = relationship('UserFollowing',
591 followers = relationship('UserFollowing',
592 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
592 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
593 cascade='all')
593 cascade='all')
594 extra_fields = relationship('RepositoryField',
594 extra_fields = relationship('RepositoryField',
595 cascade="all, delete, delete-orphan")
595 cascade="all, delete, delete-orphan")
596
596
597 logs = relationship('UserLog')
597 logs = relationship('UserLog')
598 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
598 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
599
599
600 pull_requests_org = relationship('PullRequest',
600 pull_requests_org = relationship('PullRequest',
601 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
601 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
602 cascade="all, delete, delete-orphan")
602 cascade="all, delete, delete-orphan")
603
603
604 pull_requests_other = relationship('PullRequest',
604 pull_requests_other = relationship('PullRequest',
605 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
605 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
606 cascade="all, delete, delete-orphan")
606 cascade="all, delete, delete-orphan")
607
607
608 def __unicode__(self):
608 def __unicode__(self):
609 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
609 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
610 safe_unicode(self.repo_name))
610 safe_unicode(self.repo_name))
611
611
612 @classmethod
612 @classmethod
613 def get_by_repo_name(cls, repo_name):
613 def get_by_repo_name(cls, repo_name):
614 q = Session().query(cls).filter(cls.repo_name == repo_name)
614 q = Session().query(cls).filter(cls.repo_name == repo_name)
615 q = q.options(joinedload(Repository.fork))\
615 q = q.options(joinedload(Repository.fork))\
616 .options(joinedload(Repository.user))\
616 .options(joinedload(Repository.user))\
617 .options(joinedload(Repository.group))
617 .options(joinedload(Repository.group))
618 return q.scalar()
618 return q.scalar()
619
619
620
620
621 class RepoGroup(Base, BaseModel):
621 class RepoGroup(Base, BaseModel):
622 __tablename__ = 'groups'
622 __tablename__ = 'groups'
623 __table_args__ = (
623 __table_args__ = (
624 UniqueConstraint('group_name', 'group_parent_id'),
624 UniqueConstraint('group_name', 'group_parent_id'),
625 CheckConstraint('group_id != group_parent_id'),
625 CheckConstraint('group_id != group_parent_id'),
626 {'extend_existing': True, 'mysql_engine': 'InnoDB',
626 {'extend_existing': True, 'mysql_engine': 'InnoDB',
627 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
627 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
628 )
628 )
629 __mapper_args__ = {'order_by': 'group_name'}
629 __mapper_args__ = {'order_by': 'group_name'}
630
630
631 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
631 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
632 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
632 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
633 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
633 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
634 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
634 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
635 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
635 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
636 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
636 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
637
637
638 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
638 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
639 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
639 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
640 parent_group = relationship('RepoGroup', remote_side=group_id)
640 parent_group = relationship('RepoGroup', remote_side=group_id)
641 user = relationship('User')
641 user = relationship('User')
642
642
643 def __init__(self, group_name='', parent_group=None):
643 def __init__(self, group_name='', parent_group=None):
644 self.group_name = group_name
644 self.group_name = group_name
645 self.parent_group = parent_group
645 self.parent_group = parent_group
646
646
647 def __unicode__(self):
647 def __unicode__(self):
648 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
648 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
649 self.group_name)
649 self.group_name)
650
650
651 @classmethod
651 @classmethod
652 def url_sep(cls):
652 def url_sep(cls):
653 return URL_SEP
653 return URL_SEP
654
654
655 @classmethod
655 @classmethod
656 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
656 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
657 if case_insensitive:
657 if case_insensitive:
658 gr = cls.query()\
658 gr = cls.query()\
659 .filter(cls.group_name.ilike(group_name))
659 .filter(cls.group_name.ilike(group_name))
660 else:
660 else:
661 gr = cls.query()\
661 gr = cls.query()\
662 .filter(cls.group_name == group_name)
662 .filter(cls.group_name == group_name)
663 if cache:
663 if cache:
664 gr = gr.options(FromCache(
664 gr = gr.options(FromCache(
665 "sql_cache_short",
665 "sql_cache_short",
666 "get_group_%s" % _hash_key(group_name)
666 "get_group_%s" % _hash_key(group_name)
667 )
667 )
668 )
668 )
669 return gr.scalar()
669 return gr.scalar()
670
670
671
671
672 class Permission(Base, BaseModel):
672 class Permission(Base, BaseModel):
673 __tablename__ = 'permissions'
673 __tablename__ = 'permissions'
674 __table_args__ = (
674 __table_args__ = (
675 Index('p_perm_name_idx', 'permission_name'),
675 Index('p_perm_name_idx', 'permission_name'),
676 {'extend_existing': True, 'mysql_engine': 'InnoDB',
676 {'extend_existing': True, 'mysql_engine': 'InnoDB',
677 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
677 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
678 )
678 )
679 PERMS = [
679 PERMS = [
680 ('hg.admin', _('RhodeCode Administrator')),
680 ('hg.admin', _('RhodeCode Administrator')),
681
681
682 ('repository.none', _('Repository no access')),
682 ('repository.none', _('Repository no access')),
683 ('repository.read', _('Repository read access')),
683 ('repository.read', _('Repository read access')),
684 ('repository.write', _('Repository write access')),
684 ('repository.write', _('Repository write access')),
685 ('repository.admin', _('Repository admin access')),
685 ('repository.admin', _('Repository admin access')),
686
686
687 ('group.none', _('Repository group no access')),
687 ('group.none', _('Repository group no access')),
688 ('group.read', _('Repository group read access')),
688 ('group.read', _('Repository group read access')),
689 ('group.write', _('Repository group write access')),
689 ('group.write', _('Repository group write access')),
690 ('group.admin', _('Repository group admin access')),
690 ('group.admin', _('Repository group admin access')),
691
691
692 ('usergroup.none', _('User group no access')),
692 ('usergroup.none', _('User group no access')),
693 ('usergroup.read', _('User group read access')),
693 ('usergroup.read', _('User group read access')),
694 ('usergroup.write', _('User group write access')),
694 ('usergroup.write', _('User group write access')),
695 ('usergroup.admin', _('User group admin access')),
695 ('usergroup.admin', _('User group admin access')),
696
696
697 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
697 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
698 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
698 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
699
699
700 ('hg.usergroup.create.false', _('User Group creation disabled')),
700 ('hg.usergroup.create.false', _('User Group creation disabled')),
701 ('hg.usergroup.create.true', _('User Group creation enabled')),
701 ('hg.usergroup.create.true', _('User Group creation enabled')),
702
702
703 ('hg.create.none', _('Repository creation disabled')),
703 ('hg.create.none', _('Repository creation disabled')),
704 ('hg.create.repository', _('Repository creation enabled')),
704 ('hg.create.repository', _('Repository creation enabled')),
705
705
706 ('hg.fork.none', _('Repository forking disabled')),
706 ('hg.fork.none', _('Repository forking disabled')),
707 ('hg.fork.repository', _('Repository forking enabled')),
707 ('hg.fork.repository', _('Repository forking enabled')),
708
708
709 ('hg.register.none', _('Registration disabled')),
709 ('hg.register.none', _('Registration disabled')),
710 ('hg.register.manual_activate', _('User Registration with manual account activation')),
710 ('hg.register.manual_activate', _('User Registration with manual account activation')),
711 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
711 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
712
712
713 ('hg.extern_activate.manual', _('Manual activation of external account')),
713 ('hg.extern_activate.manual', _('Manual activation of external account')),
714 ('hg.extern_activate.auto', _('Automatic activation of external account')),
714 ('hg.extern_activate.auto', _('Automatic activation of external account')),
715
715
716 ]
716 ]
717
717
718 #definition of system default permissions for DEFAULT user
718 #definition of system default permissions for DEFAULT user
719 DEFAULT_USER_PERMISSIONS = [
719 DEFAULT_USER_PERMISSIONS = [
720 'repository.read',
720 'repository.read',
721 'group.read',
721 'group.read',
722 'usergroup.read',
722 'usergroup.read',
723 'hg.create.repository',
723 'hg.create.repository',
724 'hg.fork.repository',
724 'hg.fork.repository',
725 'hg.register.manual_activate',
725 'hg.register.manual_activate',
726 'hg.extern_activate.auto',
726 'hg.extern_activate.auto',
727 ]
727 ]
728
728
729 # defines which permissions are more important higher the more important
729 # defines which permissions are more important higher the more important
730 # Weight defines which permissions are more important.
730 # Weight defines which permissions are more important.
731 # The higher number the more important.
731 # The higher number the more important.
732 PERM_WEIGHTS = {
732 PERM_WEIGHTS = {
733 'repository.none': 0,
733 'repository.none': 0,
734 'repository.read': 1,
734 'repository.read': 1,
735 'repository.write': 3,
735 'repository.write': 3,
736 'repository.admin': 4,
736 'repository.admin': 4,
737
737
738 'group.none': 0,
738 'group.none': 0,
739 'group.read': 1,
739 'group.read': 1,
740 'group.write': 3,
740 'group.write': 3,
741 'group.admin': 4,
741 'group.admin': 4,
742
742
743 'usergroup.none': 0,
743 'usergroup.none': 0,
744 'usergroup.read': 1,
744 'usergroup.read': 1,
745 'usergroup.write': 3,
745 'usergroup.write': 3,
746 'usergroup.admin': 4,
746 'usergroup.admin': 4,
747 'hg.repogroup.create.false': 0,
747 'hg.repogroup.create.false': 0,
748 'hg.repogroup.create.true': 1,
748 'hg.repogroup.create.true': 1,
749
749
750 'hg.usergroup.create.false': 0,
750 'hg.usergroup.create.false': 0,
751 'hg.usergroup.create.true': 1,
751 'hg.usergroup.create.true': 1,
752
752
753 'hg.fork.none': 0,
753 'hg.fork.none': 0,
754 'hg.fork.repository': 1,
754 'hg.fork.repository': 1,
755 'hg.create.none': 0,
755 'hg.create.none': 0,
756 'hg.create.repository': 1
756 'hg.create.repository': 1
757 }
757 }
758
758
759 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
759 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
760 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
760 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
761 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
761 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
762
762
763 def __unicode__(self):
763 def __unicode__(self):
764 return u"<%s('%s:%s')>" % (
764 return u"<%s('%s:%s')>" % (
765 self.__class__.__name__, self.permission_id, self.permission_name
765 self.__class__.__name__, self.permission_id, self.permission_name
766 )
766 )
767
767
768 @classmethod
768 @classmethod
769 def get_by_key(cls, key):
769 def get_by_key(cls, key):
770 return cls.query().filter(cls.permission_name == key).scalar()
770 return cls.query().filter(cls.permission_name == key).scalar()
771
771
772
772
773 class UserRepoToPerm(Base, BaseModel):
773 class UserRepoToPerm(Base, BaseModel):
774 __tablename__ = 'repo_to_perm'
774 __tablename__ = 'repo_to_perm'
775 __table_args__ = (
775 __table_args__ = (
776 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
776 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
777 {'extend_existing': True, 'mysql_engine': 'InnoDB',
777 {'extend_existing': True, 'mysql_engine': 'InnoDB',
778 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
778 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
779 )
779 )
780 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
780 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
781 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
781 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
782 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
782 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
783 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
783 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
784
784
785 user = relationship('User')
785 user = relationship('User')
786 repository = relationship('Repository')
786 repository = relationship('Repository')
787 permission = relationship('Permission')
787 permission = relationship('Permission')
788
788
789 def __unicode__(self):
789 def __unicode__(self):
790 return u'<%s => %s >' % (self.user, self.repository)
790 return u'<%s => %s >' % (self.user, self.repository)
791
791
792
792
793 class UserUserGroupToPerm(Base, BaseModel):
793 class UserUserGroupToPerm(Base, BaseModel):
794 __tablename__ = 'user_user_group_to_perm'
794 __tablename__ = 'user_user_group_to_perm'
795 __table_args__ = (
795 __table_args__ = (
796 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
796 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
797 {'extend_existing': True, 'mysql_engine': 'InnoDB',
797 {'extend_existing': True, 'mysql_engine': 'InnoDB',
798 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
798 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
799 )
799 )
800 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_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
801 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
801 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
802 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
802 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
803 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
803 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
804
804
805 user = relationship('User')
805 user = relationship('User')
806 user_group = relationship('UserGroup')
806 user_group = relationship('UserGroup')
807 permission = relationship('Permission')
807 permission = relationship('Permission')
808
808
809 def __unicode__(self):
809 def __unicode__(self):
810 return u'<%s => %s >' % (self.user, self.user_group)
810 return u'<%s => %s >' % (self.user, self.user_group)
811
811
812
812
813 class UserToPerm(Base, BaseModel):
813 class UserToPerm(Base, BaseModel):
814 __tablename__ = 'user_to_perm'
814 __tablename__ = 'user_to_perm'
815 __table_args__ = (
815 __table_args__ = (
816 UniqueConstraint('user_id', 'permission_id'),
816 UniqueConstraint('user_id', 'permission_id'),
817 {'extend_existing': True, 'mysql_engine': 'InnoDB',
817 {'extend_existing': True, 'mysql_engine': 'InnoDB',
818 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
818 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
819 )
819 )
820 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
820 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
821 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
821 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
822 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
822 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
823
823
824 user = relationship('User')
824 user = relationship('User')
825 permission = relationship('Permission', lazy='joined')
825 permission = relationship('Permission', lazy='joined')
826
826
827 def __unicode__(self):
827 def __unicode__(self):
828 return u'<%s => %s >' % (self.user, self.permission)
828 return u'<%s => %s >' % (self.user, self.permission)
829
829
830
830
831 class UserGroupRepoToPerm(Base, BaseModel):
831 class UserGroupRepoToPerm(Base, BaseModel):
832 __tablename__ = 'users_group_repo_to_perm'
832 __tablename__ = 'users_group_repo_to_perm'
833 __table_args__ = (
833 __table_args__ = (
834 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
834 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
835 {'extend_existing': True, 'mysql_engine': 'InnoDB',
835 {'extend_existing': True, 'mysql_engine': 'InnoDB',
836 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
836 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
837 )
837 )
838 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
838 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
839 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
839 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
840 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
840 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
841 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
841 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
842
842
843 users_group = relationship('UserGroup')
843 users_group = relationship('UserGroup')
844 permission = relationship('Permission')
844 permission = relationship('Permission')
845 repository = relationship('Repository')
845 repository = relationship('Repository')
846
846
847 def __unicode__(self):
847 def __unicode__(self):
848 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
848 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
849
849
850
850
851 class UserGroupUserGroupToPerm(Base, BaseModel):
851 class UserGroupUserGroupToPerm(Base, BaseModel):
852 __tablename__ = 'user_group_user_group_to_perm'
852 __tablename__ = 'user_group_user_group_to_perm'
853 __table_args__ = (
853 __table_args__ = (
854 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
854 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
855 CheckConstraint('target_user_group_id != user_group_id'),
855 CheckConstraint('target_user_group_id != user_group_id'),
856 {'extend_existing': True, 'mysql_engine': 'InnoDB',
856 {'extend_existing': True, 'mysql_engine': 'InnoDB',
857 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
857 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
858 )
858 )
859 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 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)
860 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
860 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
861 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
861 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
862 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
862 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
863
863
864 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
864 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
865 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
865 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
866 permission = relationship('Permission')
866 permission = relationship('Permission')
867
867
868 def __unicode__(self):
868 def __unicode__(self):
869 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
869 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
870
870
871
871
872 class UserGroupToPerm(Base, BaseModel):
872 class UserGroupToPerm(Base, BaseModel):
873 __tablename__ = 'users_group_to_perm'
873 __tablename__ = 'users_group_to_perm'
874 __table_args__ = (
874 __table_args__ = (
875 UniqueConstraint('users_group_id', 'permission_id',),
875 UniqueConstraint('users_group_id', 'permission_id',),
876 {'extend_existing': True, 'mysql_engine': 'InnoDB',
876 {'extend_existing': True, 'mysql_engine': 'InnoDB',
877 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
877 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
878 )
878 )
879 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
879 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
880 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
880 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
881 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
881 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
882
882
883 users_group = relationship('UserGroup')
883 users_group = relationship('UserGroup')
884 permission = relationship('Permission')
884 permission = relationship('Permission')
885
885
886
886
887 class UserRepoGroupToPerm(Base, BaseModel):
887 class UserRepoGroupToPerm(Base, BaseModel):
888 __tablename__ = 'user_repo_group_to_perm'
888 __tablename__ = 'user_repo_group_to_perm'
889 __table_args__ = (
889 __table_args__ = (
890 UniqueConstraint('user_id', 'group_id', 'permission_id'),
890 UniqueConstraint('user_id', 'group_id', 'permission_id'),
891 {'extend_existing': True, 'mysql_engine': 'InnoDB',
891 {'extend_existing': True, 'mysql_engine': 'InnoDB',
892 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
892 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
893 )
893 )
894
894
895 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
895 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
896 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
896 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
897 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
897 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
898 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
898 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
899
899
900 user = relationship('User')
900 user = relationship('User')
901 group = relationship('RepoGroup')
901 group = relationship('RepoGroup')
902 permission = relationship('Permission')
902 permission = relationship('Permission')
903
903
904
904
905 class UserGroupRepoGroupToPerm(Base, BaseModel):
905 class UserGroupRepoGroupToPerm(Base, BaseModel):
906 __tablename__ = 'users_group_repo_group_to_perm'
906 __tablename__ = 'users_group_repo_group_to_perm'
907 __table_args__ = (
907 __table_args__ = (
908 UniqueConstraint('users_group_id', 'group_id'),
908 UniqueConstraint('users_group_id', 'group_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
912
913 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_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
914 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
914 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
915 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
915 group_id = Column("group_id", Integer(), ForeignKey('groups.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
917
918 users_group = relationship('UserGroup')
918 users_group = relationship('UserGroup')
919 permission = relationship('Permission')
919 permission = relationship('Permission')
920 group = relationship('RepoGroup')
920 group = relationship('RepoGroup')
921
921
922
922
923 class Statistics(Base, BaseModel):
923 class Statistics(Base, BaseModel):
924 __tablename__ = 'statistics'
924 __tablename__ = 'statistics'
925 __table_args__ = (
925 __table_args__ = (
926 UniqueConstraint('repository_id'),
926 UniqueConstraint('repository_id'),
927 {'extend_existing': True, 'mysql_engine': 'InnoDB',
927 {'extend_existing': True, 'mysql_engine': 'InnoDB',
928 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
928 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
929 )
929 )
930 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
930 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
931 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
931 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
932 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
932 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
933 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
933 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
934 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
934 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
935 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
935 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
936
936
937 repository = relationship('Repository', single_parent=True)
937 repository = relationship('Repository', single_parent=True)
938
938
939
939
940 class UserFollowing(Base, BaseModel):
940 class UserFollowing(Base, BaseModel):
941 __tablename__ = 'user_followings'
941 __tablename__ = 'user_followings'
942 __table_args__ = (
942 __table_args__ = (
943 UniqueConstraint('user_id', 'follows_repository_id'),
943 UniqueConstraint('user_id', 'follows_repository_id'),
944 UniqueConstraint('user_id', 'follows_user_id'),
944 UniqueConstraint('user_id', 'follows_user_id'),
945 {'extend_existing': True, 'mysql_engine': 'InnoDB',
945 {'extend_existing': True, 'mysql_engine': 'InnoDB',
946 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
946 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
947 )
947 )
948
948
949 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
949 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
950 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
950 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
951 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
951 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
952 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
952 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
953 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
953 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
954
954
955 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
955 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
956
956
957 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
957 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
958 follows_repository = relationship('Repository', order_by='Repository.repo_name')
958 follows_repository = relationship('Repository', order_by='Repository.repo_name')
959
959
960
960
961 class CacheInvalidation(Base, BaseModel):
961 class CacheInvalidation(Base, BaseModel):
962 __tablename__ = 'cache_invalidation'
962 __tablename__ = 'cache_invalidation'
963 __table_args__ = (
963 __table_args__ = (
964 UniqueConstraint('cache_key'),
964 UniqueConstraint('cache_key'),
965 Index('key_idx', 'cache_key'),
965 Index('key_idx', 'cache_key'),
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 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
969 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
970 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
970 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
971 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
971 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
972 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
972 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
973
973
974 def __init__(self, cache_key, cache_args=''):
974 def __init__(self, cache_key, cache_args=''):
975 self.cache_key = cache_key
975 self.cache_key = cache_key
976 self.cache_args = cache_args
976 self.cache_args = cache_args
977 self.cache_active = False
977 self.cache_active = False
978
978
979
979
980 class ChangesetComment(Base, BaseModel):
980 class ChangesetComment(Base, BaseModel):
981 __tablename__ = 'changeset_comments'
981 __tablename__ = 'changeset_comments'
982 __table_args__ = (
982 __table_args__ = (
983 Index('cc_revision_idx', 'revision'),
983 Index('cc_revision_idx', 'revision'),
984 {'extend_existing': True, 'mysql_engine': 'InnoDB',
984 {'extend_existing': True, 'mysql_engine': 'InnoDB',
985 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
985 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
986 )
986 )
987 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
987 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
988 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
988 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
989 revision = Column('revision', String(40), nullable=True)
989 revision = Column('revision', String(40), nullable=True)
990 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
990 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
991 line_no = Column('line_no', Unicode(10), nullable=True)
991 line_no = Column('line_no', Unicode(10), nullable=True)
992 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
992 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
993 f_path = Column('f_path', Unicode(1000), nullable=True)
993 f_path = Column('f_path', Unicode(1000), nullable=True)
994 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
994 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
995 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
995 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
996 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
996 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
997 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
997 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
998
998
999 author = relationship('User', lazy='joined')
999 author = relationship('User', lazy='joined')
1000 repo = relationship('Repository')
1000 repo = relationship('Repository')
1001 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1001 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1002 pull_request = relationship('PullRequest', lazy='joined')
1002 pull_request = relationship('PullRequest', lazy='joined')
1003
1003
1004
1004
1005 class ChangesetStatus(Base, BaseModel):
1005 class ChangesetStatus(Base, BaseModel):
1006 __tablename__ = 'changeset_statuses'
1006 __tablename__ = 'changeset_statuses'
1007 __table_args__ = (
1007 __table_args__ = (
1008 Index('cs_revision_idx', 'revision'),
1008 Index('cs_revision_idx', 'revision'),
1009 Index('cs_version_idx', 'version'),
1009 Index('cs_version_idx', 'version'),
1010 UniqueConstraint('repo_id', 'revision', 'version'),
1010 UniqueConstraint('repo_id', 'revision', 'version'),
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 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1014 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1015 STATUS_APPROVED = 'approved'
1015 STATUS_APPROVED = 'approved'
1016 STATUS_REJECTED = 'rejected'
1016 STATUS_REJECTED = 'rejected'
1017 STATUS_UNDER_REVIEW = 'under_review'
1017 STATUS_UNDER_REVIEW = 'under_review'
1018
1018
1019 STATUSES = [
1019 STATUSES = [
1020 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1020 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1021 (STATUS_APPROVED, _("Approved")),
1021 (STATUS_APPROVED, _("Approved")),
1022 (STATUS_REJECTED, _("Rejected")),
1022 (STATUS_REJECTED, _("Rejected")),
1023 (STATUS_UNDER_REVIEW, _("Under Review")),
1023 (STATUS_UNDER_REVIEW, _("Under Review")),
1024 ]
1024 ]
1025
1025
1026 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1026 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1027 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1027 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1028 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1028 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1029 revision = Column('revision', String(40), nullable=False)
1029 revision = Column('revision', String(40), nullable=False)
1030 status = Column('status', String(128), nullable=False, default=DEFAULT)
1030 status = Column('status', String(128), nullable=False, default=DEFAULT)
1031 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1031 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1032 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1032 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1033 version = Column('version', Integer(), nullable=False, default=0)
1033 version = Column('version', Integer(), nullable=False, default=0)
1034 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1034 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1035
1035
1036 author = relationship('User', lazy='joined')
1036 author = relationship('User', lazy='joined')
1037 repo = relationship('Repository')
1037 repo = relationship('Repository')
1038 comment = relationship('ChangesetComment', lazy='joined')
1038 comment = relationship('ChangesetComment', lazy='joined')
1039 pull_request = relationship('PullRequest', lazy='joined')
1039 pull_request = relationship('PullRequest', lazy='joined')
1040
1040
1041
1041
1042
1042
1043 class PullRequest(Base, BaseModel):
1043 class PullRequest(Base, BaseModel):
1044 __tablename__ = 'pull_requests'
1044 __tablename__ = 'pull_requests'
1045 __table_args__ = (
1045 __table_args__ = (
1046 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1046 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1047 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1047 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1048 )
1048 )
1049
1049
1050 STATUS_NEW = u'new'
1050 STATUS_NEW = u'new'
1051 STATUS_OPEN = u'open'
1051 STATUS_OPEN = u'open'
1052 STATUS_CLOSED = u'closed'
1052 STATUS_CLOSED = u'closed'
1053
1053
1054 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1054 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1055 title = Column('title', Unicode(256), nullable=True)
1055 title = Column('title', Unicode(256), nullable=True)
1056 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1056 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1057 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1057 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1058 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1058 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1059 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1059 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1060 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1060 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1061 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1061 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1062 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1062 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1063 org_ref = Column('org_ref', Unicode(256), nullable=False)
1063 org_ref = Column('org_ref', Unicode(256), nullable=False)
1064 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1064 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1065 other_ref = Column('other_ref', Unicode(256), nullable=False)
1065 other_ref = Column('other_ref', Unicode(256), nullable=False)
1066
1066
1067 author = relationship('User', lazy='joined')
1067 author = relationship('User', lazy='joined')
1068 reviewers = relationship('PullRequestReviewers',
1068 reviewers = relationship('PullRequestReviewers',
1069 cascade="all, delete, delete-orphan")
1069 cascade="all, delete, delete-orphan")
1070 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1070 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1071 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1071 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1072 statuses = relationship('ChangesetStatus')
1072 statuses = relationship('ChangesetStatus')
1073 comments = relationship('ChangesetComment',
1073 comments = relationship('ChangesetComment',
1074 cascade="all, delete, delete-orphan")
1074 cascade="all, delete, delete-orphan")
1075
1075
1076
1076
1077 class PullRequestReviewers(Base, BaseModel):
1077 class PullRequestReviewers(Base, BaseModel):
1078 __tablename__ = 'pull_request_reviewers'
1078 __tablename__ = 'pull_request_reviewers'
1079 __table_args__ = (
1079 __table_args__ = (
1080 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1080 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1081 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1081 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1082 )
1082 )
1083
1083
1084 def __init__(self, user=None, pull_request=None):
1084 def __init__(self, user=None, pull_request=None):
1085 self.user = user
1085 self.user = user
1086 self.pull_request = pull_request
1086 self.pull_request = pull_request
1087
1087
1088 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1088 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1089 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1089 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1090 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1090 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1091
1091
1092 user = relationship('User')
1092 user = relationship('User')
1093 pull_request = relationship('PullRequest')
1093 pull_request = relationship('PullRequest')
1094
1094
1095
1095
1096 class Notification(Base, BaseModel):
1096 class Notification(Base, BaseModel):
1097 __tablename__ = 'notifications'
1097 __tablename__ = 'notifications'
1098 __table_args__ = (
1098 __table_args__ = (
1099 Index('notification_type_idx', 'type'),
1099 Index('notification_type_idx', 'type'),
1100 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1100 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1101 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1101 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1102 )
1102 )
1103
1103
1104 TYPE_CHANGESET_COMMENT = u'cs_comment'
1104 TYPE_CHANGESET_COMMENT = u'cs_comment'
1105 TYPE_MESSAGE = u'message'
1105 TYPE_MESSAGE = u'message'
1106 TYPE_MENTION = u'mention'
1106 TYPE_MENTION = u'mention'
1107 TYPE_REGISTRATION = u'registration'
1107 TYPE_REGISTRATION = u'registration'
1108 TYPE_PULL_REQUEST = u'pull_request'
1108 TYPE_PULL_REQUEST = u'pull_request'
1109 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1109 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1110
1110
1111 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1111 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1112 subject = Column('subject', Unicode(512), nullable=True)
1112 subject = Column('subject', Unicode(512), nullable=True)
1113 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1113 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1114 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1114 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1115 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1115 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1116 type_ = Column('type', Unicode(256))
1116 type_ = Column('type', Unicode(256))
1117
1117
1118 created_by_user = relationship('User')
1118 created_by_user = relationship('User')
1119 notifications_to_users = relationship('UserNotification', lazy='joined',
1119 notifications_to_users = relationship('UserNotification', lazy='joined',
1120 cascade="all, delete, delete-orphan")
1120 cascade="all, delete, delete-orphan")
1121
1121
1122
1122
1123 class UserNotification(Base, BaseModel):
1123 class UserNotification(Base, BaseModel):
1124 __tablename__ = 'user_to_notification'
1124 __tablename__ = 'user_to_notification'
1125 __table_args__ = (
1125 __table_args__ = (
1126 UniqueConstraint('user_id', 'notification_id'),
1126 UniqueConstraint('user_id', 'notification_id'),
1127 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1127 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1128 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1128 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1129 )
1129 )
1130 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1130 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1131 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1131 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1132 read = Column('read', Boolean, default=False)
1132 read = Column('read', Boolean, default=False)
1133 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1133 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1134
1134
1135 user = relationship('User', lazy="joined")
1135 user = relationship('User', lazy="joined")
1136 notification = relationship('Notification', lazy="joined",
1136 notification = relationship('Notification', lazy="joined",
1137 order_by=lambda: Notification.created_on.desc(),)
1137 order_by=lambda: Notification.created_on.desc(),)
1138
1138
1139
1139
1140 class Gist(Base, BaseModel):
1140 class Gist(Base, BaseModel):
1141 __tablename__ = 'gists'
1141 __tablename__ = 'gists'
1142 __table_args__ = (
1142 __table_args__ = (
1143 Index('g_gist_access_id_idx', 'gist_access_id'),
1143 Index('g_gist_access_id_idx', 'gist_access_id'),
1144 Index('g_created_on_idx', 'created_on'),
1144 Index('g_created_on_idx', 'created_on'),
1145 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1145 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1146 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1146 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1147 )
1147 )
1148 GIST_PUBLIC = u'public'
1148 GIST_PUBLIC = u'public'
1149 GIST_PRIVATE = u'private'
1149 GIST_PRIVATE = u'private'
1150
1150
1151 gist_id = Column('gist_id', Integer(), primary_key=True)
1151 gist_id = Column('gist_id', Integer(), primary_key=True)
1152 gist_access_id = Column('gist_access_id', Unicode(250))
1152 gist_access_id = Column('gist_access_id', Unicode(250))
1153 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1153 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1154 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1154 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1155 gist_expires = Column('gist_expires', Float(53), nullable=False)
1155 gist_expires = Column('gist_expires', Float(53), nullable=False)
1156 gist_type = Column('gist_type', Unicode(128), nullable=False)
1156 gist_type = Column('gist_type', Unicode(128), nullable=False)
1157 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1157 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1158 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1158 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1159
1159
1160 owner = relationship('User')
1160 owner = relationship('User')
1161
1161
1162
1162
1163 class DbMigrateVersion(Base, BaseModel):
1163 class DbMigrateVersion(Base, BaseModel):
1164 __tablename__ = 'db_migrate_version'
1164 __tablename__ = 'db_migrate_version'
1165 __table_args__ = (
1165 __table_args__ = (
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 repository_id = Column('repository_id', String(250), primary_key=True)
1169 repository_id = Column('repository_id', String(250), primary_key=True)
1170 repository_path = Column('repository_path', Text)
1170 repository_path = Column('repository_path', Text)
1171 version = Column('version', Integer)
1171 version = Column('version', Integer)
@@ -1,1172 +1,1172 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
28 import functools
28 import functools
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.ext.hybrid import hybrid_property
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from beaker.cache import cache_region, region_invalidate
34 from beaker.cache import cache_region, region_invalidate
35 from webob.exc import HTTPNotFound
35 from webob.exc import HTTPNotFound
36
36
37 from pylons.i18n.translation import lazy_ugettext as _
37 from rhodecode.translation import _
38
38
39 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.utils.helpers import get_scm
41 from rhodecode.lib.vcs.exceptions import VCSError
41 from rhodecode.lib.vcs.exceptions import VCSError
42 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from zope.cachedescriptors.property import Lazy as LazyProperty
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
44
44
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
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.iteritems():
87 for k, val in _json_attr.iteritems():
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 SETTINGS_TYPES = {
153 SETTINGS_TYPES = {
154 'str': safe_str,
154 'str': safe_str,
155 'int': safe_int,
155 'int': safe_int,
156 'unicode': safe_unicode,
156 'unicode': safe_unicode,
157 'bool': str2bool,
157 'bool': str2bool,
158 'list': functools.partial(aslist, sep=',')
158 'list': functools.partial(aslist, sep=',')
159 }
159 }
160 __tablename__ = 'rhodecode_settings'
160 __tablename__ = 'rhodecode_settings'
161 __table_args__ = (
161 __table_args__ = (
162 UniqueConstraint('app_settings_name'),
162 UniqueConstraint('app_settings_name'),
163 {'extend_existing': True, 'mysql_engine': 'InnoDB',
163 {'extend_existing': True, 'mysql_engine': 'InnoDB',
164 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
164 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
165 )
165 )
166 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
166 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
167 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
167 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
168 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
168 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
169 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
169 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
170
170
171 def __init__(self, key='', val='', type='unicode'):
171 def __init__(self, key='', val='', type='unicode'):
172 self.app_settings_name = key
172 self.app_settings_name = key
173 self.app_settings_value = val
173 self.app_settings_value = val
174 self.app_settings_type = type
174 self.app_settings_type = type
175
175
176 @validates('_app_settings_value')
176 @validates('_app_settings_value')
177 def validate_settings_value(self, key, val):
177 def validate_settings_value(self, key, val):
178 assert type(val) == unicode
178 assert type(val) == unicode
179 return val
179 return val
180
180
181 @hybrid_property
181 @hybrid_property
182 def app_settings_value(self):
182 def app_settings_value(self):
183 v = self._app_settings_value
183 v = self._app_settings_value
184 _type = self.app_settings_type
184 _type = self.app_settings_type
185 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
185 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
186 return converter(v)
186 return converter(v)
187
187
188 @app_settings_value.setter
188 @app_settings_value.setter
189 def app_settings_value(self, val):
189 def app_settings_value(self, val):
190 """
190 """
191 Setter that will always make sure we use unicode in app_settings_value
191 Setter that will always make sure we use unicode in app_settings_value
192
192
193 :param val:
193 :param val:
194 """
194 """
195 self._app_settings_value = safe_unicode(val)
195 self._app_settings_value = safe_unicode(val)
196
196
197 @hybrid_property
197 @hybrid_property
198 def app_settings_type(self):
198 def app_settings_type(self):
199 return self._app_settings_type
199 return self._app_settings_type
200
200
201 @app_settings_type.setter
201 @app_settings_type.setter
202 def app_settings_type(self, val):
202 def app_settings_type(self, val):
203 if val not in self.SETTINGS_TYPES:
203 if val not in self.SETTINGS_TYPES:
204 raise Exception('type must be one of %s got %s'
204 raise Exception('type must be one of %s got %s'
205 % (self.SETTINGS_TYPES.keys(), val))
205 % (self.SETTINGS_TYPES.keys(), val))
206 self._app_settings_type = val
206 self._app_settings_type = val
207
207
208 def __unicode__(self):
208 def __unicode__(self):
209 return u"<%s('%s:%s[%s]')>" % (
209 return u"<%s('%s:%s[%s]')>" % (
210 self.__class__.__name__,
210 self.__class__.__name__,
211 self.app_settings_name, self.app_settings_value, self.app_settings_type
211 self.app_settings_name, self.app_settings_value, self.app_settings_type
212 )
212 )
213
213
214
214
215 class RhodeCodeUi(Base, BaseModel):
215 class RhodeCodeUi(Base, BaseModel):
216 __tablename__ = 'rhodecode_ui'
216 __tablename__ = 'rhodecode_ui'
217 __table_args__ = (
217 __table_args__ = (
218 UniqueConstraint('ui_key'),
218 UniqueConstraint('ui_key'),
219 {'extend_existing': True, 'mysql_engine': 'InnoDB',
219 {'extend_existing': True, 'mysql_engine': 'InnoDB',
220 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
220 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
221 )
221 )
222
222
223 HOOK_REPO_SIZE = 'changegroup.repo_size'
223 HOOK_REPO_SIZE = 'changegroup.repo_size'
224 HOOK_PUSH = 'changegroup.push_logger'
224 HOOK_PUSH = 'changegroup.push_logger'
225 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
225 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
226 HOOK_PULL = 'outgoing.pull_logger'
226 HOOK_PULL = 'outgoing.pull_logger'
227 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
227 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
228
228
229 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
229 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
230 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
230 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
231 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
231 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
232 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
232 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
233 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
233 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
234
234
235
235
236
236
237 class User(Base, BaseModel):
237 class User(Base, BaseModel):
238 __tablename__ = 'users'
238 __tablename__ = 'users'
239 __table_args__ = (
239 __table_args__ = (
240 UniqueConstraint('username'), UniqueConstraint('email'),
240 UniqueConstraint('username'), UniqueConstraint('email'),
241 Index('u_username_idx', 'username'),
241 Index('u_username_idx', 'username'),
242 Index('u_email_idx', 'email'),
242 Index('u_email_idx', 'email'),
243 {'extend_existing': True, 'mysql_engine': 'InnoDB',
243 {'extend_existing': True, 'mysql_engine': 'InnoDB',
244 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
244 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
245 )
245 )
246 DEFAULT_USER = 'default'
246 DEFAULT_USER = 'default'
247
247
248 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
248 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
249 username = Column("username", String(255), nullable=True, unique=None, default=None)
249 username = Column("username", String(255), nullable=True, unique=None, default=None)
250 password = Column("password", String(255), nullable=True, unique=None, default=None)
250 password = Column("password", String(255), nullable=True, unique=None, default=None)
251 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
251 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
252 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
252 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
253 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
253 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
254 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
254 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
255 _email = Column("email", String(255), nullable=True, unique=None, default=None)
255 _email = Column("email", String(255), nullable=True, unique=None, default=None)
256 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
256 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
257 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
257 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
258 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
258 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
259 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
259 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
260 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
260 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
261 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
261 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
262
262
263 user_log = relationship('UserLog')
263 user_log = relationship('UserLog')
264 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
264 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
265
265
266 repositories = relationship('Repository')
266 repositories = relationship('Repository')
267 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
267 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
268 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
268 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
269
269
270 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
270 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
271 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
271 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
272
272
273 group_member = relationship('UserGroupMember', cascade='all')
273 group_member = relationship('UserGroupMember', cascade='all')
274
274
275 notifications = relationship('UserNotification', cascade='all')
275 notifications = relationship('UserNotification', cascade='all')
276 # notifications assigned to this user
276 # notifications assigned to this user
277 user_created_notifications = relationship('Notification', cascade='all')
277 user_created_notifications = relationship('Notification', cascade='all')
278 # comments created by this user
278 # comments created by this user
279 user_comments = relationship('ChangesetComment', cascade='all')
279 user_comments = relationship('ChangesetComment', cascade='all')
280 user_emails = relationship('UserEmailMap', cascade='all')
280 user_emails = relationship('UserEmailMap', cascade='all')
281
281
282 @hybrid_property
282 @hybrid_property
283 def email(self):
283 def email(self):
284 return self._email
284 return self._email
285
285
286 @email.setter
286 @email.setter
287 def email(self, val):
287 def email(self, val):
288 self._email = val.lower() if val else None
288 self._email = val.lower() if val else None
289
289
290 @property
290 @property
291 def firstname(self):
291 def firstname(self):
292 # alias for future
292 # alias for future
293 return self.name
293 return self.name
294
294
295 @property
295 @property
296 def username_and_name(self):
296 def username_and_name(self):
297 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
297 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
298
298
299 @property
299 @property
300 def full_name(self):
300 def full_name(self):
301 return '%s %s' % (self.firstname, self.lastname)
301 return '%s %s' % (self.firstname, self.lastname)
302
302
303 @property
303 @property
304 def full_contact(self):
304 def full_contact(self):
305 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
305 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
306
306
307 @property
307 @property
308 def short_contact(self):
308 def short_contact(self):
309 return '%s %s' % (self.firstname, self.lastname)
309 return '%s %s' % (self.firstname, self.lastname)
310
310
311 @property
311 @property
312 def is_admin(self):
312 def is_admin(self):
313 return self.admin
313 return self.admin
314
314
315 @classmethod
315 @classmethod
316 def get_by_username(cls, username, case_insensitive=False, cache=False):
316 def get_by_username(cls, username, case_insensitive=False, cache=False):
317 if case_insensitive:
317 if case_insensitive:
318 q = cls.query().filter(cls.username.ilike(username))
318 q = cls.query().filter(cls.username.ilike(username))
319 else:
319 else:
320 q = cls.query().filter(cls.username == username)
320 q = cls.query().filter(cls.username == username)
321
321
322 if cache:
322 if cache:
323 q = q.options(FromCache(
323 q = q.options(FromCache(
324 "sql_cache_short",
324 "sql_cache_short",
325 "get_user_%s" % _hash_key(username)
325 "get_user_%s" % _hash_key(username)
326 )
326 )
327 )
327 )
328 return q.scalar()
328 return q.scalar()
329
329
330 @classmethod
330 @classmethod
331 def get_by_auth_token(cls, auth_token, cache=False):
331 def get_by_auth_token(cls, auth_token, cache=False):
332 q = cls.query().filter(cls.api_key == auth_token)
332 q = cls.query().filter(cls.api_key == auth_token)
333
333
334 if cache:
334 if cache:
335 q = q.options(FromCache("sql_cache_short",
335 q = q.options(FromCache("sql_cache_short",
336 "get_auth_token_%s" % auth_token))
336 "get_auth_token_%s" % auth_token))
337 return q.scalar()
337 return q.scalar()
338
338
339 @classmethod
339 @classmethod
340 def get_by_email(cls, email, case_insensitive=False, cache=False):
340 def get_by_email(cls, email, case_insensitive=False, cache=False):
341 if case_insensitive:
341 if case_insensitive:
342 q = cls.query().filter(cls.email.ilike(email))
342 q = cls.query().filter(cls.email.ilike(email))
343 else:
343 else:
344 q = cls.query().filter(cls.email == email)
344 q = cls.query().filter(cls.email == email)
345
345
346 if cache:
346 if cache:
347 q = q.options(FromCache("sql_cache_short",
347 q = q.options(FromCache("sql_cache_short",
348 "get_email_key_%s" % email))
348 "get_email_key_%s" % email))
349
349
350 ret = q.scalar()
350 ret = q.scalar()
351 if ret is None:
351 if ret is None:
352 q = UserEmailMap.query()
352 q = UserEmailMap.query()
353 # try fetching in alternate email map
353 # try fetching in alternate email map
354 if case_insensitive:
354 if case_insensitive:
355 q = q.filter(UserEmailMap.email.ilike(email))
355 q = q.filter(UserEmailMap.email.ilike(email))
356 else:
356 else:
357 q = q.filter(UserEmailMap.email == email)
357 q = q.filter(UserEmailMap.email == email)
358 q = q.options(joinedload(UserEmailMap.user))
358 q = q.options(joinedload(UserEmailMap.user))
359 if cache:
359 if cache:
360 q = q.options(FromCache("sql_cache_short",
360 q = q.options(FromCache("sql_cache_short",
361 "get_email_map_key_%s" % email))
361 "get_email_map_key_%s" % email))
362 ret = getattr(q.scalar(), 'user', None)
362 ret = getattr(q.scalar(), 'user', None)
363
363
364 return ret
364 return ret
365
365
366 @classmethod
366 @classmethod
367 def get_first_admin(cls):
367 def get_first_admin(cls):
368 user = User.query().filter(User.admin == True).first()
368 user = User.query().filter(User.admin == True).first()
369 if user is None:
369 if user is None:
370 raise Exception('Missing administrative account!')
370 raise Exception('Missing administrative account!')
371 return user
371 return user
372
372
373 @classmethod
373 @classmethod
374 def get_default_user(cls, cache=False):
374 def get_default_user(cls, cache=False):
375 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
375 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
376 if user is None:
376 if user is None:
377 raise Exception('Missing default account!')
377 raise Exception('Missing default account!')
378 return user
378 return user
379
379
380
380
381
381
382
382
383 class UserEmailMap(Base, BaseModel):
383 class UserEmailMap(Base, BaseModel):
384 __tablename__ = 'user_email_map'
384 __tablename__ = 'user_email_map'
385 __table_args__ = (
385 __table_args__ = (
386 Index('uem_email_idx', 'email'),
386 Index('uem_email_idx', 'email'),
387 UniqueConstraint('email'),
387 UniqueConstraint('email'),
388 {'extend_existing': True, 'mysql_engine': 'InnoDB',
388 {'extend_existing': True, 'mysql_engine': 'InnoDB',
389 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
389 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
390 )
390 )
391 __mapper_args__ = {}
391 __mapper_args__ = {}
392
392
393 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
393 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
394 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
394 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
395 _email = Column("email", String(255), nullable=True, unique=False, default=None)
395 _email = Column("email", String(255), nullable=True, unique=False, default=None)
396 user = relationship('User', lazy='joined')
396 user = relationship('User', lazy='joined')
397
397
398 @validates('_email')
398 @validates('_email')
399 def validate_email(self, key, email):
399 def validate_email(self, key, email):
400 # check if this email is not main one
400 # check if this email is not main one
401 main_email = Session().query(User).filter(User.email == email).scalar()
401 main_email = Session().query(User).filter(User.email == email).scalar()
402 if main_email is not None:
402 if main_email is not None:
403 raise AttributeError('email %s is present is user table' % email)
403 raise AttributeError('email %s is present is user table' % email)
404 return email
404 return email
405
405
406 @hybrid_property
406 @hybrid_property
407 def email(self):
407 def email(self):
408 return self._email
408 return self._email
409
409
410 @email.setter
410 @email.setter
411 def email(self, val):
411 def email(self, val):
412 self._email = val.lower() if val else None
412 self._email = val.lower() if val else None
413
413
414
414
415 class UserIpMap(Base, BaseModel):
415 class UserIpMap(Base, BaseModel):
416 __tablename__ = 'user_ip_map'
416 __tablename__ = 'user_ip_map'
417 __table_args__ = (
417 __table_args__ = (
418 UniqueConstraint('user_id', 'ip_addr'),
418 UniqueConstraint('user_id', 'ip_addr'),
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
420 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
420 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
421 )
421 )
422 __mapper_args__ = {}
422 __mapper_args__ = {}
423
423
424 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
425 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
425 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
426 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
426 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
427 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
427 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
428 user = relationship('User', lazy='joined')
428 user = relationship('User', lazy='joined')
429
429
430
430
431 class UserLog(Base, BaseModel):
431 class UserLog(Base, BaseModel):
432 __tablename__ = 'user_logs'
432 __tablename__ = 'user_logs'
433 __table_args__ = (
433 __table_args__ = (
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 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
438 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
438 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
439 username = Column("username", String(255), nullable=True, unique=None, default=None)
439 username = Column("username", String(255), nullable=True, unique=None, default=None)
440 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
440 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
441 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
441 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
442 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
442 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
443 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
443 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
444 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
444 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
445
445
446 def __unicode__(self):
446 def __unicode__(self):
447 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
447 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
448 self.repository_name,
448 self.repository_name,
449 self.action)
449 self.action)
450
450
451 user = relationship('User')
451 user = relationship('User')
452 repository = relationship('Repository', cascade='')
452 repository = relationship('Repository', cascade='')
453
453
454
454
455 class UserGroup(Base, BaseModel):
455 class UserGroup(Base, BaseModel):
456 __tablename__ = 'users_groups'
456 __tablename__ = 'users_groups'
457 __table_args__ = (
457 __table_args__ = (
458 {'extend_existing': True, 'mysql_engine': 'InnoDB',
458 {'extend_existing': True, 'mysql_engine': 'InnoDB',
459 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
459 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
460 )
460 )
461
461
462 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
462 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
463 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
463 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
464 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
464 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
465 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
465 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
466 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
466 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
469
469
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_unicode(self.repo_name))
609 safe_unicode(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 CheckConstraint('group_id != group_parent_id'),
624 CheckConstraint('group_id != group_parent_id'),
625 {'extend_existing': True, 'mysql_engine': 'InnoDB',
625 {'extend_existing': True, 'mysql_engine': 'InnoDB',
626 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
626 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
627 )
627 )
628 __mapper_args__ = {'order_by': 'group_name'}
628 __mapper_args__ = {'order_by': 'group_name'}
629
629
630 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
630 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
631 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
631 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
632 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
632 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
633 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
633 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
634 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
634 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
635 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
635 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
636 #TODO: create this field in migrations
636 #TODO: create this field in migrations
637 #created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
637 #created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
638
638
639 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
639 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
640 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
640 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
641 parent_group = relationship('RepoGroup', remote_side=group_id)
641 parent_group = relationship('RepoGroup', remote_side=group_id)
642 user = relationship('User')
642 user = relationship('User')
643
643
644 def __init__(self, group_name='', parent_group=None):
644 def __init__(self, group_name='', parent_group=None):
645 self.group_name = group_name
645 self.group_name = group_name
646 self.parent_group = parent_group
646 self.parent_group = parent_group
647
647
648 def __unicode__(self):
648 def __unicode__(self):
649 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
649 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
650 self.group_name)
650 self.group_name)
651
651
652 @classmethod
652 @classmethod
653 def url_sep(cls):
653 def url_sep(cls):
654 return URL_SEP
654 return URL_SEP
655
655
656 @classmethod
656 @classmethod
657 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
657 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
658 if case_insensitive:
658 if case_insensitive:
659 gr = cls.query()\
659 gr = cls.query()\
660 .filter(cls.group_name.ilike(group_name))
660 .filter(cls.group_name.ilike(group_name))
661 else:
661 else:
662 gr = cls.query()\
662 gr = cls.query()\
663 .filter(cls.group_name == group_name)
663 .filter(cls.group_name == group_name)
664 if cache:
664 if cache:
665 gr = gr.options(FromCache(
665 gr = gr.options(FromCache(
666 "sql_cache_short",
666 "sql_cache_short",
667 "get_group_%s" % _hash_key(group_name)
667 "get_group_%s" % _hash_key(group_name)
668 )
668 )
669 )
669 )
670 return gr.scalar()
670 return gr.scalar()
671
671
672
672
673 class Permission(Base, BaseModel):
673 class Permission(Base, BaseModel):
674 __tablename__ = 'permissions'
674 __tablename__ = 'permissions'
675 __table_args__ = (
675 __table_args__ = (
676 Index('p_perm_name_idx', 'permission_name'),
676 Index('p_perm_name_idx', 'permission_name'),
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 PERMS = [
680 PERMS = [
681 ('hg.admin', _('RhodeCode Administrator')),
681 ('hg.admin', _('RhodeCode Administrator')),
682
682
683 ('repository.none', _('Repository no access')),
683 ('repository.none', _('Repository no access')),
684 ('repository.read', _('Repository read access')),
684 ('repository.read', _('Repository read access')),
685 ('repository.write', _('Repository write access')),
685 ('repository.write', _('Repository write access')),
686 ('repository.admin', _('Repository admin access')),
686 ('repository.admin', _('Repository admin access')),
687
687
688 ('group.none', _('Repository group no access')),
688 ('group.none', _('Repository group no access')),
689 ('group.read', _('Repository group read access')),
689 ('group.read', _('Repository group read access')),
690 ('group.write', _('Repository group write access')),
690 ('group.write', _('Repository group write access')),
691 ('group.admin', _('Repository group admin access')),
691 ('group.admin', _('Repository group admin access')),
692
692
693 ('usergroup.none', _('User group no access')),
693 ('usergroup.none', _('User group no access')),
694 ('usergroup.read', _('User group read access')),
694 ('usergroup.read', _('User group read access')),
695 ('usergroup.write', _('User group write access')),
695 ('usergroup.write', _('User group write access')),
696 ('usergroup.admin', _('User group admin access')),
696 ('usergroup.admin', _('User group admin access')),
697
697
698 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
698 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
699 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
699 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
700
700
701 ('hg.usergroup.create.false', _('User Group creation disabled')),
701 ('hg.usergroup.create.false', _('User Group creation disabled')),
702 ('hg.usergroup.create.true', _('User Group creation enabled')),
702 ('hg.usergroup.create.true', _('User Group creation enabled')),
703
703
704 ('hg.create.none', _('Repository creation disabled')),
704 ('hg.create.none', _('Repository creation disabled')),
705 ('hg.create.repository', _('Repository creation enabled')),
705 ('hg.create.repository', _('Repository creation enabled')),
706
706
707 ('hg.fork.none', _('Repository forking disabled')),
707 ('hg.fork.none', _('Repository forking disabled')),
708 ('hg.fork.repository', _('Repository forking enabled')),
708 ('hg.fork.repository', _('Repository forking enabled')),
709
709
710 ('hg.register.none', _('Registration disabled')),
710 ('hg.register.none', _('Registration disabled')),
711 ('hg.register.manual_activate', _('User Registration with manual account activation')),
711 ('hg.register.manual_activate', _('User Registration with manual account activation')),
712 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
712 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
713
713
714 ('hg.extern_activate.manual', _('Manual activation of external account')),
714 ('hg.extern_activate.manual', _('Manual activation of external account')),
715 ('hg.extern_activate.auto', _('Automatic activation of external account')),
715 ('hg.extern_activate.auto', _('Automatic activation of external account')),
716
716
717 ]
717 ]
718
718
719 #definition of system default permissions for DEFAULT user
719 #definition of system default permissions for DEFAULT user
720 DEFAULT_USER_PERMISSIONS = [
720 DEFAULT_USER_PERMISSIONS = [
721 'repository.read',
721 'repository.read',
722 'group.read',
722 'group.read',
723 'usergroup.read',
723 'usergroup.read',
724 'hg.create.repository',
724 'hg.create.repository',
725 'hg.fork.repository',
725 'hg.fork.repository',
726 'hg.register.manual_activate',
726 'hg.register.manual_activate',
727 'hg.extern_activate.auto',
727 'hg.extern_activate.auto',
728 ]
728 ]
729
729
730 # defines which permissions are more important higher the more important
730 # defines which permissions are more important higher the more important
731 # Weight defines which permissions are more important.
731 # Weight defines which permissions are more important.
732 # The higher number the more important.
732 # The higher number the more important.
733 PERM_WEIGHTS = {
733 PERM_WEIGHTS = {
734 'repository.none': 0,
734 'repository.none': 0,
735 'repository.read': 1,
735 'repository.read': 1,
736 'repository.write': 3,
736 'repository.write': 3,
737 'repository.admin': 4,
737 'repository.admin': 4,
738
738
739 'group.none': 0,
739 'group.none': 0,
740 'group.read': 1,
740 'group.read': 1,
741 'group.write': 3,
741 'group.write': 3,
742 'group.admin': 4,
742 'group.admin': 4,
743
743
744 'usergroup.none': 0,
744 'usergroup.none': 0,
745 'usergroup.read': 1,
745 'usergroup.read': 1,
746 'usergroup.write': 3,
746 'usergroup.write': 3,
747 'usergroup.admin': 4,
747 'usergroup.admin': 4,
748 'hg.repogroup.create.false': 0,
748 'hg.repogroup.create.false': 0,
749 'hg.repogroup.create.true': 1,
749 'hg.repogroup.create.true': 1,
750
750
751 'hg.usergroup.create.false': 0,
751 'hg.usergroup.create.false': 0,
752 'hg.usergroup.create.true': 1,
752 'hg.usergroup.create.true': 1,
753
753
754 'hg.fork.none': 0,
754 'hg.fork.none': 0,
755 'hg.fork.repository': 1,
755 'hg.fork.repository': 1,
756 'hg.create.none': 0,
756 'hg.create.none': 0,
757 'hg.create.repository': 1
757 'hg.create.repository': 1
758 }
758 }
759
759
760 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
760 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
761 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
761 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
762 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
762 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
763
763
764 def __unicode__(self):
764 def __unicode__(self):
765 return u"<%s('%s:%s')>" % (
765 return u"<%s('%s:%s')>" % (
766 self.__class__.__name__, self.permission_id, self.permission_name
766 self.__class__.__name__, self.permission_id, self.permission_name
767 )
767 )
768
768
769 @classmethod
769 @classmethod
770 def get_by_key(cls, key):
770 def get_by_key(cls, key):
771 return cls.query().filter(cls.permission_name == key).scalar()
771 return cls.query().filter(cls.permission_name == key).scalar()
772
772
773
773
774 class UserRepoToPerm(Base, BaseModel):
774 class UserRepoToPerm(Base, BaseModel):
775 __tablename__ = 'repo_to_perm'
775 __tablename__ = 'repo_to_perm'
776 __table_args__ = (
776 __table_args__ = (
777 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
777 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
778 {'extend_existing': True, 'mysql_engine': 'InnoDB',
778 {'extend_existing': True, 'mysql_engine': 'InnoDB',
779 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
779 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
780 )
780 )
781 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
781 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
782 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
782 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
783 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
783 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
784 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
784 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
785
785
786 user = relationship('User')
786 user = relationship('User')
787 repository = relationship('Repository')
787 repository = relationship('Repository')
788 permission = relationship('Permission')
788 permission = relationship('Permission')
789
789
790 def __unicode__(self):
790 def __unicode__(self):
791 return u'<%s => %s >' % (self.user, self.repository)
791 return u'<%s => %s >' % (self.user, self.repository)
792
792
793
793
794 class UserUserGroupToPerm(Base, BaseModel):
794 class UserUserGroupToPerm(Base, BaseModel):
795 __tablename__ = 'user_user_group_to_perm'
795 __tablename__ = 'user_user_group_to_perm'
796 __table_args__ = (
796 __table_args__ = (
797 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
797 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
798 {'extend_existing': True, 'mysql_engine': 'InnoDB',
798 {'extend_existing': True, 'mysql_engine': 'InnoDB',
799 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
799 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
800 )
800 )
801 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
801 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
802 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
802 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
803 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
803 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
804 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
804 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
805
805
806 user = relationship('User')
806 user = relationship('User')
807 user_group = relationship('UserGroup')
807 user_group = relationship('UserGroup')
808 permission = relationship('Permission')
808 permission = relationship('Permission')
809
809
810 def __unicode__(self):
810 def __unicode__(self):
811 return u'<%s => %s >' % (self.user, self.user_group)
811 return u'<%s => %s >' % (self.user, self.user_group)
812
812
813
813
814 class UserToPerm(Base, BaseModel):
814 class UserToPerm(Base, BaseModel):
815 __tablename__ = 'user_to_perm'
815 __tablename__ = 'user_to_perm'
816 __table_args__ = (
816 __table_args__ = (
817 UniqueConstraint('user_id', 'permission_id'),
817 UniqueConstraint('user_id', 'permission_id'),
818 {'extend_existing': True, 'mysql_engine': 'InnoDB',
818 {'extend_existing': True, 'mysql_engine': 'InnoDB',
819 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
819 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
820 )
820 )
821 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
821 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
822 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
822 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
823 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
823 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
824
824
825 user = relationship('User')
825 user = relationship('User')
826 permission = relationship('Permission', lazy='joined')
826 permission = relationship('Permission', lazy='joined')
827
827
828 def __unicode__(self):
828 def __unicode__(self):
829 return u'<%s => %s >' % (self.user, self.permission)
829 return u'<%s => %s >' % (self.user, self.permission)
830
830
831
831
832 class UserGroupRepoToPerm(Base, BaseModel):
832 class UserGroupRepoToPerm(Base, BaseModel):
833 __tablename__ = 'users_group_repo_to_perm'
833 __tablename__ = 'users_group_repo_to_perm'
834 __table_args__ = (
834 __table_args__ = (
835 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
835 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
836 {'extend_existing': True, 'mysql_engine': 'InnoDB',
836 {'extend_existing': True, 'mysql_engine': 'InnoDB',
837 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
837 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
838 )
838 )
839 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
839 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
840 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
840 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
841 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
841 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
842 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
842 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
843
843
844 users_group = relationship('UserGroup')
844 users_group = relationship('UserGroup')
845 permission = relationship('Permission')
845 permission = relationship('Permission')
846 repository = relationship('Repository')
846 repository = relationship('Repository')
847
847
848 def __unicode__(self):
848 def __unicode__(self):
849 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
849 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
850
850
851
851
852 class UserGroupUserGroupToPerm(Base, BaseModel):
852 class UserGroupUserGroupToPerm(Base, BaseModel):
853 __tablename__ = 'user_group_user_group_to_perm'
853 __tablename__ = 'user_group_user_group_to_perm'
854 __table_args__ = (
854 __table_args__ = (
855 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
855 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
856 CheckConstraint('target_user_group_id != user_group_id'),
856 CheckConstraint('target_user_group_id != user_group_id'),
857 {'extend_existing': True, 'mysql_engine': 'InnoDB',
857 {'extend_existing': True, 'mysql_engine': 'InnoDB',
858 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
858 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
859 )
859 )
860 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)
860 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)
861 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
861 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
862 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
862 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
863 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
863 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
864
864
865 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
865 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
866 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
866 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
867 permission = relationship('Permission')
867 permission = relationship('Permission')
868
868
869 def __unicode__(self):
869 def __unicode__(self):
870 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
870 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
871
871
872
872
873 class UserGroupToPerm(Base, BaseModel):
873 class UserGroupToPerm(Base, BaseModel):
874 __tablename__ = 'users_group_to_perm'
874 __tablename__ = 'users_group_to_perm'
875 __table_args__ = (
875 __table_args__ = (
876 UniqueConstraint('users_group_id', 'permission_id',),
876 UniqueConstraint('users_group_id', 'permission_id',),
877 {'extend_existing': True, 'mysql_engine': 'InnoDB',
877 {'extend_existing': True, 'mysql_engine': 'InnoDB',
878 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
878 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
879 )
879 )
880 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
880 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
881 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
881 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
882 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
882 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
883
883
884 users_group = relationship('UserGroup')
884 users_group = relationship('UserGroup')
885 permission = relationship('Permission')
885 permission = relationship('Permission')
886
886
887
887
888 class UserRepoGroupToPerm(Base, BaseModel):
888 class UserRepoGroupToPerm(Base, BaseModel):
889 __tablename__ = 'user_repo_group_to_perm'
889 __tablename__ = 'user_repo_group_to_perm'
890 __table_args__ = (
890 __table_args__ = (
891 UniqueConstraint('user_id', 'group_id', 'permission_id'),
891 UniqueConstraint('user_id', '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
895
896 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
896 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
897 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
897 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
898 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
898 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
899 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
899 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
900
900
901 user = relationship('User')
901 user = relationship('User')
902 group = relationship('RepoGroup')
902 group = relationship('RepoGroup')
903 permission = relationship('Permission')
903 permission = relationship('Permission')
904
904
905
905
906 class UserGroupRepoGroupToPerm(Base, BaseModel):
906 class UserGroupRepoGroupToPerm(Base, BaseModel):
907 __tablename__ = 'users_group_repo_group_to_perm'
907 __tablename__ = 'users_group_repo_group_to_perm'
908 __table_args__ = (
908 __table_args__ = (
909 UniqueConstraint('users_group_id', 'group_id'),
909 UniqueConstraint('users_group_id', 'group_id'),
910 {'extend_existing': True, 'mysql_engine': 'InnoDB',
910 {'extend_existing': True, 'mysql_engine': 'InnoDB',
911 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
911 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
912 )
912 )
913
913
914 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)
914 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)
915 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
915 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
916 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
916 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
917 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
917 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
918
918
919 users_group = relationship('UserGroup')
919 users_group = relationship('UserGroup')
920 permission = relationship('Permission')
920 permission = relationship('Permission')
921 group = relationship('RepoGroup')
921 group = relationship('RepoGroup')
922
922
923
923
924 class Statistics(Base, BaseModel):
924 class Statistics(Base, BaseModel):
925 __tablename__ = 'statistics'
925 __tablename__ = 'statistics'
926 __table_args__ = (
926 __table_args__ = (
927 UniqueConstraint('repository_id'),
927 UniqueConstraint('repository_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 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
931 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
932 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
932 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
933 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
933 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
934 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
934 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
935 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
935 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
936 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
936 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
937
937
938 repository = relationship('Repository', single_parent=True)
938 repository = relationship('Repository', single_parent=True)
939
939
940
940
941 class UserFollowing(Base, BaseModel):
941 class UserFollowing(Base, BaseModel):
942 __tablename__ = 'user_followings'
942 __tablename__ = 'user_followings'
943 __table_args__ = (
943 __table_args__ = (
944 UniqueConstraint('user_id', 'follows_repository_id'),
944 UniqueConstraint('user_id', 'follows_repository_id'),
945 UniqueConstraint('user_id', 'follows_user_id'),
945 UniqueConstraint('user_id', 'follows_user_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 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
950 user_following_id = Column("user_following_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 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
952 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
953 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
953 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
954 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
954 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
955
955
956 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
956 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
957
957
958 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
958 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
959 follows_repository = relationship('Repository', order_by='Repository.repo_name')
959 follows_repository = relationship('Repository', order_by='Repository.repo_name')
960
960
961
961
962 class CacheInvalidation(Base, BaseModel):
962 class CacheInvalidation(Base, BaseModel):
963 __tablename__ = 'cache_invalidation'
963 __tablename__ = 'cache_invalidation'
964 __table_args__ = (
964 __table_args__ = (
965 UniqueConstraint('cache_key'),
965 UniqueConstraint('cache_key'),
966 Index('key_idx', 'cache_key'),
966 Index('key_idx', 'cache_key'),
967 {'extend_existing': True, 'mysql_engine': 'InnoDB',
967 {'extend_existing': True, 'mysql_engine': 'InnoDB',
968 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
968 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
969 )
969 )
970 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
970 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
971 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
971 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
972 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
972 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
973 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
973 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
974
974
975 def __init__(self, cache_key, cache_args=''):
975 def __init__(self, cache_key, cache_args=''):
976 self.cache_key = cache_key
976 self.cache_key = cache_key
977 self.cache_args = cache_args
977 self.cache_args = cache_args
978 self.cache_active = False
978 self.cache_active = False
979
979
980
980
981 class ChangesetComment(Base, BaseModel):
981 class ChangesetComment(Base, BaseModel):
982 __tablename__ = 'changeset_comments'
982 __tablename__ = 'changeset_comments'
983 __table_args__ = (
983 __table_args__ = (
984 Index('cc_revision_idx', 'revision'),
984 Index('cc_revision_idx', 'revision'),
985 {'extend_existing': True, 'mysql_engine': 'InnoDB',
985 {'extend_existing': True, 'mysql_engine': 'InnoDB',
986 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
986 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
987 )
987 )
988 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
988 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
989 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
989 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
990 revision = Column('revision', String(40), nullable=True)
990 revision = Column('revision', String(40), nullable=True)
991 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
991 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
992 line_no = Column('line_no', Unicode(10), nullable=True)
992 line_no = Column('line_no', Unicode(10), nullable=True)
993 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
993 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
994 f_path = Column('f_path', Unicode(1000), nullable=True)
994 f_path = Column('f_path', Unicode(1000), nullable=True)
995 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
995 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
996 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
996 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
997 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
997 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
998 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
998 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
999
999
1000 author = relationship('User', lazy='joined')
1000 author = relationship('User', lazy='joined')
1001 repo = relationship('Repository')
1001 repo = relationship('Repository')
1002 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1002 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1003 pull_request = relationship('PullRequest', lazy='joined')
1003 pull_request = relationship('PullRequest', lazy='joined')
1004
1004
1005
1005
1006 class ChangesetStatus(Base, BaseModel):
1006 class ChangesetStatus(Base, BaseModel):
1007 __tablename__ = 'changeset_statuses'
1007 __tablename__ = 'changeset_statuses'
1008 __table_args__ = (
1008 __table_args__ = (
1009 Index('cs_revision_idx', 'revision'),
1009 Index('cs_revision_idx', 'revision'),
1010 Index('cs_version_idx', 'version'),
1010 Index('cs_version_idx', 'version'),
1011 UniqueConstraint('repo_id', 'revision', 'version'),
1011 UniqueConstraint('repo_id', 'revision', 'version'),
1012 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1012 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1013 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1013 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1014 )
1014 )
1015 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1015 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1016 STATUS_APPROVED = 'approved'
1016 STATUS_APPROVED = 'approved'
1017 STATUS_REJECTED = 'rejected'
1017 STATUS_REJECTED = 'rejected'
1018 STATUS_UNDER_REVIEW = 'under_review'
1018 STATUS_UNDER_REVIEW = 'under_review'
1019
1019
1020 STATUSES = [
1020 STATUSES = [
1021 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1021 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1022 (STATUS_APPROVED, _("Approved")),
1022 (STATUS_APPROVED, _("Approved")),
1023 (STATUS_REJECTED, _("Rejected")),
1023 (STATUS_REJECTED, _("Rejected")),
1024 (STATUS_UNDER_REVIEW, _("Under Review")),
1024 (STATUS_UNDER_REVIEW, _("Under Review")),
1025 ]
1025 ]
1026
1026
1027 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1027 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1028 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1028 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1029 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1029 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1030 revision = Column('revision', String(40), nullable=False)
1030 revision = Column('revision', String(40), nullable=False)
1031 status = Column('status', String(128), nullable=False, default=DEFAULT)
1031 status = Column('status', String(128), nullable=False, default=DEFAULT)
1032 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1032 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1033 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1033 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1034 version = Column('version', Integer(), nullable=False, default=0)
1034 version = Column('version', Integer(), nullable=False, default=0)
1035 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1035 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1036
1036
1037 author = relationship('User', lazy='joined')
1037 author = relationship('User', lazy='joined')
1038 repo = relationship('Repository')
1038 repo = relationship('Repository')
1039 comment = relationship('ChangesetComment', lazy='joined')
1039 comment = relationship('ChangesetComment', lazy='joined')
1040 pull_request = relationship('PullRequest', lazy='joined')
1040 pull_request = relationship('PullRequest', lazy='joined')
1041
1041
1042
1042
1043
1043
1044 class PullRequest(Base, BaseModel):
1044 class PullRequest(Base, BaseModel):
1045 __tablename__ = 'pull_requests'
1045 __tablename__ = 'pull_requests'
1046 __table_args__ = (
1046 __table_args__ = (
1047 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1047 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1048 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1048 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1049 )
1049 )
1050
1050
1051 STATUS_NEW = u'new'
1051 STATUS_NEW = u'new'
1052 STATUS_OPEN = u'open'
1052 STATUS_OPEN = u'open'
1053 STATUS_CLOSED = u'closed'
1053 STATUS_CLOSED = u'closed'
1054
1054
1055 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1055 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1056 title = Column('title', Unicode(256), nullable=True)
1056 title = Column('title', Unicode(256), nullable=True)
1057 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1057 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1058 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1058 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1059 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1059 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1060 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1060 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
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 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1062 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1063 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1063 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1064 org_ref = Column('org_ref', Unicode(256), nullable=False)
1064 org_ref = Column('org_ref', Unicode(256), nullable=False)
1065 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1065 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1066 other_ref = Column('other_ref', Unicode(256), nullable=False)
1066 other_ref = Column('other_ref', Unicode(256), nullable=False)
1067
1067
1068 author = relationship('User', lazy='joined')
1068 author = relationship('User', lazy='joined')
1069 reviewers = relationship('PullRequestReviewers',
1069 reviewers = relationship('PullRequestReviewers',
1070 cascade="all, delete, delete-orphan")
1070 cascade="all, delete, delete-orphan")
1071 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1071 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1072 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1072 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1073 statuses = relationship('ChangesetStatus')
1073 statuses = relationship('ChangesetStatus')
1074 comments = relationship('ChangesetComment',
1074 comments = relationship('ChangesetComment',
1075 cascade="all, delete, delete-orphan")
1075 cascade="all, delete, delete-orphan")
1076
1076
1077
1077
1078 class PullRequestReviewers(Base, BaseModel):
1078 class PullRequestReviewers(Base, BaseModel):
1079 __tablename__ = 'pull_request_reviewers'
1079 __tablename__ = 'pull_request_reviewers'
1080 __table_args__ = (
1080 __table_args__ = (
1081 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1081 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1082 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1082 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1083 )
1083 )
1084
1084
1085 def __init__(self, user=None, pull_request=None):
1085 def __init__(self, user=None, pull_request=None):
1086 self.user = user
1086 self.user = user
1087 self.pull_request = pull_request
1087 self.pull_request = pull_request
1088
1088
1089 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1089 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1090 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1090 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1091 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1091 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1092
1092
1093 user = relationship('User')
1093 user = relationship('User')
1094 pull_request = relationship('PullRequest')
1094 pull_request = relationship('PullRequest')
1095
1095
1096
1096
1097 class Notification(Base, BaseModel):
1097 class Notification(Base, BaseModel):
1098 __tablename__ = 'notifications'
1098 __tablename__ = 'notifications'
1099 __table_args__ = (
1099 __table_args__ = (
1100 Index('notification_type_idx', 'type'),
1100 Index('notification_type_idx', 'type'),
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 TYPE_CHANGESET_COMMENT = u'cs_comment'
1105 TYPE_CHANGESET_COMMENT = u'cs_comment'
1106 TYPE_MESSAGE = u'message'
1106 TYPE_MESSAGE = u'message'
1107 TYPE_MENTION = u'mention'
1107 TYPE_MENTION = u'mention'
1108 TYPE_REGISTRATION = u'registration'
1108 TYPE_REGISTRATION = u'registration'
1109 TYPE_PULL_REQUEST = u'pull_request'
1109 TYPE_PULL_REQUEST = u'pull_request'
1110 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1110 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1111
1111
1112 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1112 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1113 subject = Column('subject', Unicode(512), nullable=True)
1113 subject = Column('subject', Unicode(512), nullable=True)
1114 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1114 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1115 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1115 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1116 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1116 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1117 type_ = Column('type', Unicode(256))
1117 type_ = Column('type', Unicode(256))
1118
1118
1119 created_by_user = relationship('User')
1119 created_by_user = relationship('User')
1120 notifications_to_users = relationship('UserNotification', lazy='joined',
1120 notifications_to_users = relationship('UserNotification', lazy='joined',
1121 cascade="all, delete, delete-orphan")
1121 cascade="all, delete, delete-orphan")
1122
1122
1123
1123
1124 class UserNotification(Base, BaseModel):
1124 class UserNotification(Base, BaseModel):
1125 __tablename__ = 'user_to_notification'
1125 __tablename__ = 'user_to_notification'
1126 __table_args__ = (
1126 __table_args__ = (
1127 UniqueConstraint('user_id', 'notification_id'),
1127 UniqueConstraint('user_id', 'notification_id'),
1128 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1128 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1129 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1129 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1130 )
1130 )
1131 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1131 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1132 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1132 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1133 read = Column('read', Boolean, default=False)
1133 read = Column('read', Boolean, default=False)
1134 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1134 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1135
1135
1136 user = relationship('User', lazy="joined")
1136 user = relationship('User', lazy="joined")
1137 notification = relationship('Notification', lazy="joined",
1137 notification = relationship('Notification', lazy="joined",
1138 order_by=lambda: Notification.created_on.desc(),)
1138 order_by=lambda: Notification.created_on.desc(),)
1139
1139
1140
1140
1141 class Gist(Base, BaseModel):
1141 class Gist(Base, BaseModel):
1142 __tablename__ = 'gists'
1142 __tablename__ = 'gists'
1143 __table_args__ = (
1143 __table_args__ = (
1144 Index('g_gist_access_id_idx', 'gist_access_id'),
1144 Index('g_gist_access_id_idx', 'gist_access_id'),
1145 Index('g_created_on_idx', 'created_on'),
1145 Index('g_created_on_idx', 'created_on'),
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 GIST_PUBLIC = u'public'
1149 GIST_PUBLIC = u'public'
1150 GIST_PRIVATE = u'private'
1150 GIST_PRIVATE = u'private'
1151
1151
1152 gist_id = Column('gist_id', Integer(), primary_key=True)
1152 gist_id = Column('gist_id', Integer(), primary_key=True)
1153 gist_access_id = Column('gist_access_id', Unicode(250))
1153 gist_access_id = Column('gist_access_id', Unicode(250))
1154 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1154 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1155 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1155 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1156 gist_expires = Column('gist_expires', Float(53), nullable=False)
1156 gist_expires = Column('gist_expires', Float(53), nullable=False)
1157 gist_type = Column('gist_type', Unicode(128), nullable=False)
1157 gist_type = Column('gist_type', Unicode(128), nullable=False)
1158 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1158 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1159 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1159 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1160
1160
1161 owner = relationship('User')
1161 owner = relationship('User')
1162
1162
1163
1163
1164 class DbMigrateVersion(Base, BaseModel):
1164 class DbMigrateVersion(Base, BaseModel):
1165 __tablename__ = 'db_migrate_version'
1165 __tablename__ = 'db_migrate_version'
1166 __table_args__ = (
1166 __table_args__ = (
1167 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1167 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1168 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1168 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1169 )
1169 )
1170 repository_id = Column('repository_id', String(250), primary_key=True)
1170 repository_id = Column('repository_id', String(250), primary_key=True)
1171 repository_path = Column('repository_path', Text)
1171 repository_path = Column('repository_path', Text)
1172 version = Column('version', Integer)
1172 version = Column('version', Integer)
@@ -1,1189 +1,1189 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
28 import functools
28 import functools
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.ext.hybrid import hybrid_property
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from beaker.cache import cache_region, region_invalidate
34 from beaker.cache import cache_region, region_invalidate
35 from webob.exc import HTTPNotFound
35 from webob.exc import HTTPNotFound
36
36
37 from pylons.i18n.translation import lazy_ugettext as _
37 from rhodecode.translation import _
38
38
39 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.utils.helpers import get_scm
41 from rhodecode.lib.vcs.exceptions import VCSError
41 from rhodecode.lib.vcs.exceptions import VCSError
42 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from zope.cachedescriptors.property import Lazy as LazyProperty
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
44
44
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
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.iteritems():
87 for k, val in _json_attr.iteritems():
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 SETTINGS_TYPES = {
153 SETTINGS_TYPES = {
154 'str': safe_str,
154 'str': safe_str,
155 'int': safe_int,
155 'int': safe_int,
156 'unicode': safe_unicode,
156 'unicode': safe_unicode,
157 'bool': str2bool,
157 'bool': str2bool,
158 'list': functools.partial(aslist, sep=',')
158 'list': functools.partial(aslist, sep=',')
159 }
159 }
160 __tablename__ = 'rhodecode_settings'
160 __tablename__ = 'rhodecode_settings'
161 __table_args__ = (
161 __table_args__ = (
162 UniqueConstraint('app_settings_name'),
162 UniqueConstraint('app_settings_name'),
163 {'extend_existing': True, 'mysql_engine': 'InnoDB',
163 {'extend_existing': True, 'mysql_engine': 'InnoDB',
164 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
164 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
165 )
165 )
166 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
166 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
167 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
167 app_settings_name = Column("app_settings_name", String(255), nullable=True, unique=None, default=None)
168 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
168 _app_settings_value = Column("app_settings_value", String(4096), nullable=True, unique=None, default=None)
169 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
169 _app_settings_type = Column("app_settings_type", String(255), nullable=True, unique=None, default=None)
170
170
171 def __init__(self, key='', val='', type='unicode'):
171 def __init__(self, key='', val='', type='unicode'):
172 self.app_settings_name = key
172 self.app_settings_name = key
173 self.app_settings_value = val
173 self.app_settings_value = val
174 self.app_settings_type = type
174 self.app_settings_type = type
175
175
176 @validates('_app_settings_value')
176 @validates('_app_settings_value')
177 def validate_settings_value(self, key, val):
177 def validate_settings_value(self, key, val):
178 assert type(val) == unicode
178 assert type(val) == unicode
179 return val
179 return val
180
180
181 @hybrid_property
181 @hybrid_property
182 def app_settings_value(self):
182 def app_settings_value(self):
183 v = self._app_settings_value
183 v = self._app_settings_value
184 _type = self.app_settings_type
184 _type = self.app_settings_type
185 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
185 converter = self.SETTINGS_TYPES.get(_type) or self.SETTINGS_TYPES['unicode']
186 return converter(v)
186 return converter(v)
187
187
188 @app_settings_value.setter
188 @app_settings_value.setter
189 def app_settings_value(self, val):
189 def app_settings_value(self, val):
190 """
190 """
191 Setter that will always make sure we use unicode in app_settings_value
191 Setter that will always make sure we use unicode in app_settings_value
192
192
193 :param val:
193 :param val:
194 """
194 """
195 self._app_settings_value = safe_unicode(val)
195 self._app_settings_value = safe_unicode(val)
196
196
197 @hybrid_property
197 @hybrid_property
198 def app_settings_type(self):
198 def app_settings_type(self):
199 return self._app_settings_type
199 return self._app_settings_type
200
200
201 @app_settings_type.setter
201 @app_settings_type.setter
202 def app_settings_type(self, val):
202 def app_settings_type(self, val):
203 if val not in self.SETTINGS_TYPES:
203 if val not in self.SETTINGS_TYPES:
204 raise Exception('type must be one of %s got %s'
204 raise Exception('type must be one of %s got %s'
205 % (self.SETTINGS_TYPES.keys(), val))
205 % (self.SETTINGS_TYPES.keys(), val))
206 self._app_settings_type = val
206 self._app_settings_type = val
207
207
208 def __unicode__(self):
208 def __unicode__(self):
209 return u"<%s('%s:%s[%s]')>" % (
209 return u"<%s('%s:%s[%s]')>" % (
210 self.__class__.__name__,
210 self.__class__.__name__,
211 self.app_settings_name, self.app_settings_value, self.app_settings_type
211 self.app_settings_name, self.app_settings_value, self.app_settings_type
212 )
212 )
213
213
214
214
215 class RhodeCodeUi(Base, BaseModel):
215 class RhodeCodeUi(Base, BaseModel):
216 __tablename__ = 'rhodecode_ui'
216 __tablename__ = 'rhodecode_ui'
217 __table_args__ = (
217 __table_args__ = (
218 UniqueConstraint('ui_key'),
218 UniqueConstraint('ui_key'),
219 {'extend_existing': True, 'mysql_engine': 'InnoDB',
219 {'extend_existing': True, 'mysql_engine': 'InnoDB',
220 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
220 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
221 )
221 )
222
222
223 HOOK_REPO_SIZE = 'changegroup.repo_size'
223 HOOK_REPO_SIZE = 'changegroup.repo_size'
224 HOOK_PUSH = 'changegroup.push_logger'
224 HOOK_PUSH = 'changegroup.push_logger'
225 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
225 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
226 HOOK_PULL = 'outgoing.pull_logger'
226 HOOK_PULL = 'outgoing.pull_logger'
227 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
227 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
228
228
229 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
229 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
230 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
230 ui_section = Column("ui_section", String(255), nullable=True, unique=None, default=None)
231 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
231 ui_key = Column("ui_key", String(255), nullable=True, unique=None, default=None)
232 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
232 ui_value = Column("ui_value", String(255), nullable=True, unique=None, default=None)
233 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
233 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
234
234
235
235
236
236
237 class User(Base, BaseModel):
237 class User(Base, BaseModel):
238 __tablename__ = 'users'
238 __tablename__ = 'users'
239 __table_args__ = (
239 __table_args__ = (
240 UniqueConstraint('username'), UniqueConstraint('email'),
240 UniqueConstraint('username'), UniqueConstraint('email'),
241 Index('u_username_idx', 'username'),
241 Index('u_username_idx', 'username'),
242 Index('u_email_idx', 'email'),
242 Index('u_email_idx', 'email'),
243 {'extend_existing': True, 'mysql_engine': 'InnoDB',
243 {'extend_existing': True, 'mysql_engine': 'InnoDB',
244 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
244 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
245 )
245 )
246 DEFAULT_USER = 'default'
246 DEFAULT_USER = 'default'
247
247
248 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
248 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
249 username = Column("username", String(255), nullable=True, unique=None, default=None)
249 username = Column("username", String(255), nullable=True, unique=None, default=None)
250 password = Column("password", String(255), nullable=True, unique=None, default=None)
250 password = Column("password", String(255), nullable=True, unique=None, default=None)
251 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
251 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
252 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
252 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
253 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
253 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
254 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
254 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
255 _email = Column("email", String(255), nullable=True, unique=None, default=None)
255 _email = Column("email", String(255), nullable=True, unique=None, default=None)
256 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
256 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
257 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
257 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
258 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
258 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
259 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
259 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
260 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
260 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
261 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
261 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
262
262
263 user_log = relationship('UserLog')
263 user_log = relationship('UserLog')
264 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
264 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
265
265
266 repositories = relationship('Repository')
266 repositories = relationship('Repository')
267 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
267 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
268 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
268 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
269
269
270 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
270 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
271 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
271 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
272
272
273 group_member = relationship('UserGroupMember', cascade='all')
273 group_member = relationship('UserGroupMember', cascade='all')
274
274
275 notifications = relationship('UserNotification', cascade='all')
275 notifications = relationship('UserNotification', cascade='all')
276 # notifications assigned to this user
276 # notifications assigned to this user
277 user_created_notifications = relationship('Notification', cascade='all')
277 user_created_notifications = relationship('Notification', cascade='all')
278 # comments created by this user
278 # comments created by this user
279 user_comments = relationship('ChangesetComment', cascade='all')
279 user_comments = relationship('ChangesetComment', cascade='all')
280 user_emails = relationship('UserEmailMap', cascade='all')
280 user_emails = relationship('UserEmailMap', cascade='all')
281
281
282 @hybrid_property
282 @hybrid_property
283 def email(self):
283 def email(self):
284 return self._email
284 return self._email
285
285
286 @email.setter
286 @email.setter
287 def email(self, val):
287 def email(self, val):
288 self._email = val.lower() if val else None
288 self._email = val.lower() if val else None
289
289
290 @property
290 @property
291 def firstname(self):
291 def firstname(self):
292 # alias for future
292 # alias for future
293 return self.name
293 return self.name
294
294
295 @property
295 @property
296 def username_and_name(self):
296 def username_and_name(self):
297 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
297 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
298
298
299 @property
299 @property
300 def full_name(self):
300 def full_name(self):
301 return '%s %s' % (self.firstname, self.lastname)
301 return '%s %s' % (self.firstname, self.lastname)
302
302
303 @property
303 @property
304 def full_contact(self):
304 def full_contact(self):
305 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
305 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
306
306
307 @property
307 @property
308 def short_contact(self):
308 def short_contact(self):
309 return '%s %s' % (self.firstname, self.lastname)
309 return '%s %s' % (self.firstname, self.lastname)
310
310
311 @property
311 @property
312 def is_admin(self):
312 def is_admin(self):
313 return self.admin
313 return self.admin
314
314
315 @classmethod
315 @classmethod
316 def get_by_username(cls, username, case_insensitive=False, cache=False):
316 def get_by_username(cls, username, case_insensitive=False, cache=False):
317 if case_insensitive:
317 if case_insensitive:
318 q = cls.query().filter(cls.username.ilike(username))
318 q = cls.query().filter(cls.username.ilike(username))
319 else:
319 else:
320 q = cls.query().filter(cls.username == username)
320 q = cls.query().filter(cls.username == username)
321
321
322 if cache:
322 if cache:
323 q = q.options(FromCache(
323 q = q.options(FromCache(
324 "sql_cache_short",
324 "sql_cache_short",
325 "get_user_%s" % _hash_key(username)
325 "get_user_%s" % _hash_key(username)
326 )
326 )
327 )
327 )
328 return q.scalar()
328 return q.scalar()
329
329
330 @classmethod
330 @classmethod
331 def get_by_auth_token(cls, auth_token, cache=False):
331 def get_by_auth_token(cls, auth_token, cache=False):
332 q = cls.query().filter(cls.api_key == auth_token)
332 q = cls.query().filter(cls.api_key == auth_token)
333
333
334 if cache:
334 if cache:
335 q = q.options(FromCache("sql_cache_short",
335 q = q.options(FromCache("sql_cache_short",
336 "get_auth_token_%s" % auth_token))
336 "get_auth_token_%s" % auth_token))
337 return q.scalar()
337 return q.scalar()
338
338
339 @classmethod
339 @classmethod
340 def get_by_email(cls, email, case_insensitive=False, cache=False):
340 def get_by_email(cls, email, case_insensitive=False, cache=False):
341 if case_insensitive:
341 if case_insensitive:
342 q = cls.query().filter(cls.email.ilike(email))
342 q = cls.query().filter(cls.email.ilike(email))
343 else:
343 else:
344 q = cls.query().filter(cls.email == email)
344 q = cls.query().filter(cls.email == email)
345
345
346 if cache:
346 if cache:
347 q = q.options(FromCache("sql_cache_short",
347 q = q.options(FromCache("sql_cache_short",
348 "get_email_key_%s" % email))
348 "get_email_key_%s" % email))
349
349
350 ret = q.scalar()
350 ret = q.scalar()
351 if ret is None:
351 if ret is None:
352 q = UserEmailMap.query()
352 q = UserEmailMap.query()
353 # try fetching in alternate email map
353 # try fetching in alternate email map
354 if case_insensitive:
354 if case_insensitive:
355 q = q.filter(UserEmailMap.email.ilike(email))
355 q = q.filter(UserEmailMap.email.ilike(email))
356 else:
356 else:
357 q = q.filter(UserEmailMap.email == email)
357 q = q.filter(UserEmailMap.email == email)
358 q = q.options(joinedload(UserEmailMap.user))
358 q = q.options(joinedload(UserEmailMap.user))
359 if cache:
359 if cache:
360 q = q.options(FromCache("sql_cache_short",
360 q = q.options(FromCache("sql_cache_short",
361 "get_email_map_key_%s" % email))
361 "get_email_map_key_%s" % email))
362 ret = getattr(q.scalar(), 'user', None)
362 ret = getattr(q.scalar(), 'user', None)
363
363
364 return ret
364 return ret
365
365
366 @classmethod
366 @classmethod
367 def get_first_admin(cls):
367 def get_first_admin(cls):
368 user = User.query().filter(User.admin == True).first()
368 user = User.query().filter(User.admin == True).first()
369 if user is None:
369 if user is None:
370 raise Exception('Missing administrative account!')
370 raise Exception('Missing administrative account!')
371 return user
371 return user
372
372
373 @classmethod
373 @classmethod
374 def get_default_user(cls, cache=False):
374 def get_default_user(cls, cache=False):
375 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
375 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
376 if user is None:
376 if user is None:
377 raise Exception('Missing default account!')
377 raise Exception('Missing default account!')
378 return user
378 return user
379
379
380
380
381
381
382
382
383 class UserEmailMap(Base, BaseModel):
383 class UserEmailMap(Base, BaseModel):
384 __tablename__ = 'user_email_map'
384 __tablename__ = 'user_email_map'
385 __table_args__ = (
385 __table_args__ = (
386 Index('uem_email_idx', 'email'),
386 Index('uem_email_idx', 'email'),
387 UniqueConstraint('email'),
387 UniqueConstraint('email'),
388 {'extend_existing': True, 'mysql_engine': 'InnoDB',
388 {'extend_existing': True, 'mysql_engine': 'InnoDB',
389 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
389 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
390 )
390 )
391 __mapper_args__ = {}
391 __mapper_args__ = {}
392
392
393 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
393 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
394 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
394 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
395 _email = Column("email", String(255), nullable=True, unique=False, default=None)
395 _email = Column("email", String(255), nullable=True, unique=False, default=None)
396 user = relationship('User', lazy='joined')
396 user = relationship('User', lazy='joined')
397
397
398 @validates('_email')
398 @validates('_email')
399 def validate_email(self, key, email):
399 def validate_email(self, key, email):
400 # check if this email is not main one
400 # check if this email is not main one
401 main_email = Session().query(User).filter(User.email == email).scalar()
401 main_email = Session().query(User).filter(User.email == email).scalar()
402 if main_email is not None:
402 if main_email is not None:
403 raise AttributeError('email %s is present is user table' % email)
403 raise AttributeError('email %s is present is user table' % email)
404 return email
404 return email
405
405
406 @hybrid_property
406 @hybrid_property
407 def email(self):
407 def email(self):
408 return self._email
408 return self._email
409
409
410 @email.setter
410 @email.setter
411 def email(self, val):
411 def email(self, val):
412 self._email = val.lower() if val else None
412 self._email = val.lower() if val else None
413
413
414
414
415 class UserIpMap(Base, BaseModel):
415 class UserIpMap(Base, BaseModel):
416 __tablename__ = 'user_ip_map'
416 __tablename__ = 'user_ip_map'
417 __table_args__ = (
417 __table_args__ = (
418 UniqueConstraint('user_id', 'ip_addr'),
418 UniqueConstraint('user_id', 'ip_addr'),
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
419 {'extend_existing': True, 'mysql_engine': 'InnoDB',
420 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
420 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
421 )
421 )
422 __mapper_args__ = {}
422 __mapper_args__ = {}
423
423
424 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
424 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
425 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
425 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
426 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
426 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
427 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
427 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
428 user = relationship('User', lazy='joined')
428 user = relationship('User', lazy='joined')
429
429
430
430
431 class UserLog(Base, BaseModel):
431 class UserLog(Base, BaseModel):
432 __tablename__ = 'user_logs'
432 __tablename__ = 'user_logs'
433 __table_args__ = (
433 __table_args__ = (
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 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
437 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
438 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
438 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
439 username = Column("username", String(255), nullable=True, unique=None, default=None)
439 username = Column("username", String(255), nullable=True, unique=None, default=None)
440 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
440 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
441 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
441 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
442 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
442 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
443 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
443 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
444 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
444 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
445
445
446 def __unicode__(self):
446 def __unicode__(self):
447 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
447 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
448 self.repository_name,
448 self.repository_name,
449 self.action)
449 self.action)
450
450
451 user = relationship('User')
451 user = relationship('User')
452 repository = relationship('Repository', cascade='')
452 repository = relationship('Repository', cascade='')
453
453
454
454
455 class UserGroup(Base, BaseModel):
455 class UserGroup(Base, BaseModel):
456 __tablename__ = 'users_groups'
456 __tablename__ = 'users_groups'
457 __table_args__ = (
457 __table_args__ = (
458 {'extend_existing': True, 'mysql_engine': 'InnoDB',
458 {'extend_existing': True, 'mysql_engine': 'InnoDB',
459 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
459 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
460 )
460 )
461
461
462 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
462 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
463 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
463 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
464 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
464 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
465 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
465 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
466 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
466 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
467 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
468 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
469
469
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_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
575 _landing_revision = 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 #NOTE: marcink, DO NOT REMOVE THOSE
607 #NOTE: marcink, DO NOT REMOVE THOSE
608 @hybrid_property
608 @hybrid_property
609 def landing_rev(self):
609 def landing_rev(self):
610 # always should return [rev_type, rev]
610 # always should return [rev_type, rev]
611 if self._landing_revision:
611 if self._landing_revision:
612 _rev_info = self._landing_revision.split(':')
612 _rev_info = self._landing_revision.split(':')
613 if len(_rev_info) < 2:
613 if len(_rev_info) < 2:
614 _rev_info.insert(0, 'rev')
614 _rev_info.insert(0, 'rev')
615 return [_rev_info[0], _rev_info[1]]
615 return [_rev_info[0], _rev_info[1]]
616 return [None, None]
616 return [None, None]
617
617
618 @landing_rev.setter
618 @landing_rev.setter
619 def landing_rev(self, val):
619 def landing_rev(self, val):
620 if ':' not in val:
620 if ':' not in val:
621 raise ValueError('value must be delimited with `:` and consist '
621 raise ValueError('value must be delimited with `:` and consist '
622 'of <rev_type>:<rev>, got %s instead' % val)
622 'of <rev_type>:<rev>, got %s instead' % val)
623 self._landing_revision = val
623 self._landing_revision = val
624
624
625 def __unicode__(self):
625 def __unicode__(self):
626 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
626 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
627 safe_unicode(self.repo_name))
627 safe_unicode(self.repo_name))
628
628
629 @classmethod
629 @classmethod
630 def get_by_repo_name(cls, repo_name):
630 def get_by_repo_name(cls, repo_name):
631 q = Session().query(cls).filter(cls.repo_name == repo_name)
631 q = Session().query(cls).filter(cls.repo_name == repo_name)
632 q = q.options(joinedload(Repository.fork))\
632 q = q.options(joinedload(Repository.fork))\
633 .options(joinedload(Repository.user))\
633 .options(joinedload(Repository.user))\
634 .options(joinedload(Repository.group))
634 .options(joinedload(Repository.group))
635 return q.scalar()
635 return q.scalar()
636
636
637
637
638 class RepoGroup(Base, BaseModel):
638 class RepoGroup(Base, BaseModel):
639 __tablename__ = 'groups'
639 __tablename__ = 'groups'
640 __table_args__ = (
640 __table_args__ = (
641 UniqueConstraint('group_name', 'group_parent_id'),
641 UniqueConstraint('group_name', 'group_parent_id'),
642 CheckConstraint('group_id != group_parent_id'),
642 CheckConstraint('group_id != group_parent_id'),
643 {'extend_existing': True, 'mysql_engine': 'InnoDB',
643 {'extend_existing': True, 'mysql_engine': 'InnoDB',
644 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
644 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
645 )
645 )
646 __mapper_args__ = {'order_by': 'group_name'}
646 __mapper_args__ = {'order_by': 'group_name'}
647
647
648 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
648 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
649 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
649 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
650 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
650 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
651 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
651 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
652 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
652 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
653 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
653 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
654 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
654 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
655
655
656 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
656 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
657 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
657 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
658 parent_group = relationship('RepoGroup', remote_side=group_id)
658 parent_group = relationship('RepoGroup', remote_side=group_id)
659 user = relationship('User')
659 user = relationship('User')
660
660
661 def __init__(self, group_name='', parent_group=None):
661 def __init__(self, group_name='', parent_group=None):
662 self.group_name = group_name
662 self.group_name = group_name
663 self.parent_group = parent_group
663 self.parent_group = parent_group
664
664
665 def __unicode__(self):
665 def __unicode__(self):
666 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
666 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
667 self.group_name)
667 self.group_name)
668
668
669 @classmethod
669 @classmethod
670 def url_sep(cls):
670 def url_sep(cls):
671 return URL_SEP
671 return URL_SEP
672
672
673 @classmethod
673 @classmethod
674 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
674 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
675 if case_insensitive:
675 if case_insensitive:
676 gr = cls.query()\
676 gr = cls.query()\
677 .filter(cls.group_name.ilike(group_name))
677 .filter(cls.group_name.ilike(group_name))
678 else:
678 else:
679 gr = cls.query()\
679 gr = cls.query()\
680 .filter(cls.group_name == group_name)
680 .filter(cls.group_name == group_name)
681 if cache:
681 if cache:
682 gr = gr.options(FromCache(
682 gr = gr.options(FromCache(
683 "sql_cache_short",
683 "sql_cache_short",
684 "get_group_%s" % _hash_key(group_name)
684 "get_group_%s" % _hash_key(group_name)
685 )
685 )
686 )
686 )
687 return gr.scalar()
687 return gr.scalar()
688
688
689
689
690 class Permission(Base, BaseModel):
690 class Permission(Base, BaseModel):
691 __tablename__ = 'permissions'
691 __tablename__ = 'permissions'
692 __table_args__ = (
692 __table_args__ = (
693 Index('p_perm_name_idx', 'permission_name'),
693 Index('p_perm_name_idx', 'permission_name'),
694 {'extend_existing': True, 'mysql_engine': 'InnoDB',
694 {'extend_existing': True, 'mysql_engine': 'InnoDB',
695 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
695 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
696 )
696 )
697 PERMS = [
697 PERMS = [
698 ('hg.admin', _('RhodeCode Administrator')),
698 ('hg.admin', _('RhodeCode Administrator')),
699
699
700 ('repository.none', _('Repository no access')),
700 ('repository.none', _('Repository no access')),
701 ('repository.read', _('Repository read access')),
701 ('repository.read', _('Repository read access')),
702 ('repository.write', _('Repository write access')),
702 ('repository.write', _('Repository write access')),
703 ('repository.admin', _('Repository admin access')),
703 ('repository.admin', _('Repository admin access')),
704
704
705 ('group.none', _('Repository group no access')),
705 ('group.none', _('Repository group no access')),
706 ('group.read', _('Repository group read access')),
706 ('group.read', _('Repository group read access')),
707 ('group.write', _('Repository group write access')),
707 ('group.write', _('Repository group write access')),
708 ('group.admin', _('Repository group admin access')),
708 ('group.admin', _('Repository group admin access')),
709
709
710 ('usergroup.none', _('User group no access')),
710 ('usergroup.none', _('User group no access')),
711 ('usergroup.read', _('User group read access')),
711 ('usergroup.read', _('User group read access')),
712 ('usergroup.write', _('User group write access')),
712 ('usergroup.write', _('User group write access')),
713 ('usergroup.admin', _('User group admin access')),
713 ('usergroup.admin', _('User group admin access')),
714
714
715 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
715 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
716 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
716 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
717
717
718 ('hg.usergroup.create.false', _('User Group creation disabled')),
718 ('hg.usergroup.create.false', _('User Group creation disabled')),
719 ('hg.usergroup.create.true', _('User Group creation enabled')),
719 ('hg.usergroup.create.true', _('User Group creation enabled')),
720
720
721 ('hg.create.none', _('Repository creation disabled')),
721 ('hg.create.none', _('Repository creation disabled')),
722 ('hg.create.repository', _('Repository creation enabled')),
722 ('hg.create.repository', _('Repository creation enabled')),
723
723
724 ('hg.fork.none', _('Repository forking disabled')),
724 ('hg.fork.none', _('Repository forking disabled')),
725 ('hg.fork.repository', _('Repository forking enabled')),
725 ('hg.fork.repository', _('Repository forking enabled')),
726
726
727 ('hg.register.none', _('Registration disabled')),
727 ('hg.register.none', _('Registration disabled')),
728 ('hg.register.manual_activate', _('User Registration with manual account activation')),
728 ('hg.register.manual_activate', _('User Registration with manual account activation')),
729 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
729 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
730
730
731 ('hg.extern_activate.manual', _('Manual activation of external account')),
731 ('hg.extern_activate.manual', _('Manual activation of external account')),
732 ('hg.extern_activate.auto', _('Automatic activation of external account')),
732 ('hg.extern_activate.auto', _('Automatic activation of external account')),
733
733
734 ]
734 ]
735
735
736 #definition of system default permissions for DEFAULT user
736 #definition of system default permissions for DEFAULT user
737 DEFAULT_USER_PERMISSIONS = [
737 DEFAULT_USER_PERMISSIONS = [
738 'repository.read',
738 'repository.read',
739 'group.read',
739 'group.read',
740 'usergroup.read',
740 'usergroup.read',
741 'hg.create.repository',
741 'hg.create.repository',
742 'hg.fork.repository',
742 'hg.fork.repository',
743 'hg.register.manual_activate',
743 'hg.register.manual_activate',
744 'hg.extern_activate.auto',
744 'hg.extern_activate.auto',
745 ]
745 ]
746
746
747 # defines which permissions are more important higher the more important
747 # defines which permissions are more important higher the more important
748 # Weight defines which permissions are more important.
748 # Weight defines which permissions are more important.
749 # The higher number the more important.
749 # The higher number the more important.
750 PERM_WEIGHTS = {
750 PERM_WEIGHTS = {
751 'repository.none': 0,
751 'repository.none': 0,
752 'repository.read': 1,
752 'repository.read': 1,
753 'repository.write': 3,
753 'repository.write': 3,
754 'repository.admin': 4,
754 'repository.admin': 4,
755
755
756 'group.none': 0,
756 'group.none': 0,
757 'group.read': 1,
757 'group.read': 1,
758 'group.write': 3,
758 'group.write': 3,
759 'group.admin': 4,
759 'group.admin': 4,
760
760
761 'usergroup.none': 0,
761 'usergroup.none': 0,
762 'usergroup.read': 1,
762 'usergroup.read': 1,
763 'usergroup.write': 3,
763 'usergroup.write': 3,
764 'usergroup.admin': 4,
764 'usergroup.admin': 4,
765 'hg.repogroup.create.false': 0,
765 'hg.repogroup.create.false': 0,
766 'hg.repogroup.create.true': 1,
766 'hg.repogroup.create.true': 1,
767
767
768 'hg.usergroup.create.false': 0,
768 'hg.usergroup.create.false': 0,
769 'hg.usergroup.create.true': 1,
769 'hg.usergroup.create.true': 1,
770
770
771 'hg.fork.none': 0,
771 'hg.fork.none': 0,
772 'hg.fork.repository': 1,
772 'hg.fork.repository': 1,
773 'hg.create.none': 0,
773 'hg.create.none': 0,
774 'hg.create.repository': 1
774 'hg.create.repository': 1
775 }
775 }
776
776
777 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
777 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
778 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
778 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
779 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
779 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
780
780
781 def __unicode__(self):
781 def __unicode__(self):
782 return u"<%s('%s:%s')>" % (
782 return u"<%s('%s:%s')>" % (
783 self.__class__.__name__, self.permission_id, self.permission_name
783 self.__class__.__name__, self.permission_id, self.permission_name
784 )
784 )
785
785
786 @classmethod
786 @classmethod
787 def get_by_key(cls, key):
787 def get_by_key(cls, key):
788 return cls.query().filter(cls.permission_name == key).scalar()
788 return cls.query().filter(cls.permission_name == key).scalar()
789
789
790
790
791 class UserRepoToPerm(Base, BaseModel):
791 class UserRepoToPerm(Base, BaseModel):
792 __tablename__ = 'repo_to_perm'
792 __tablename__ = 'repo_to_perm'
793 __table_args__ = (
793 __table_args__ = (
794 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
794 UniqueConstraint('user_id', 'repository_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 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
798 repo_to_perm_id = Column("repo_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 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
801 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
802
802
803 user = relationship('User')
803 user = relationship('User')
804 repository = relationship('Repository')
804 repository = relationship('Repository')
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.repository)
808 return u'<%s => %s >' % (self.user, self.repository)
809
809
810
810
811 class UserUserGroupToPerm(Base, BaseModel):
811 class UserUserGroupToPerm(Base, BaseModel):
812 __tablename__ = 'user_user_group_to_perm'
812 __tablename__ = 'user_user_group_to_perm'
813 __table_args__ = (
813 __table_args__ = (
814 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
814 UniqueConstraint('user_id', 'user_group_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_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
818 user_user_group_to_perm_id = Column("user_user_group_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 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
821 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
822
822
823 user = relationship('User')
823 user = relationship('User')
824 user_group = relationship('UserGroup')
824 user_group = relationship('UserGroup')
825 permission = relationship('Permission')
825 permission = relationship('Permission')
826
826
827 def __unicode__(self):
827 def __unicode__(self):
828 return u'<%s => %s >' % (self.user, self.user_group)
828 return u'<%s => %s >' % (self.user, self.user_group)
829
829
830
830
831 class UserToPerm(Base, BaseModel):
831 class UserToPerm(Base, BaseModel):
832 __tablename__ = 'user_to_perm'
832 __tablename__ = 'user_to_perm'
833 __table_args__ = (
833 __table_args__ = (
834 UniqueConstraint('user_id', 'permission_id'),
834 UniqueConstraint('user_id', 'permission_id'),
835 {'extend_existing': True, 'mysql_engine': 'InnoDB',
835 {'extend_existing': True, 'mysql_engine': 'InnoDB',
836 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
836 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
837 )
837 )
838 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
838 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
839 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
839 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
840 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
840 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
841
841
842 user = relationship('User')
842 user = relationship('User')
843 permission = relationship('Permission', lazy='joined')
843 permission = relationship('Permission', lazy='joined')
844
844
845 def __unicode__(self):
845 def __unicode__(self):
846 return u'<%s => %s >' % (self.user, self.permission)
846 return u'<%s => %s >' % (self.user, self.permission)
847
847
848
848
849 class UserGroupRepoToPerm(Base, BaseModel):
849 class UserGroupRepoToPerm(Base, BaseModel):
850 __tablename__ = 'users_group_repo_to_perm'
850 __tablename__ = 'users_group_repo_to_perm'
851 __table_args__ = (
851 __table_args__ = (
852 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
852 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
853 {'extend_existing': True, 'mysql_engine': 'InnoDB',
853 {'extend_existing': True, 'mysql_engine': 'InnoDB',
854 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
854 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
855 )
855 )
856 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
856 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
857 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
857 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
858 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
858 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
859 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
859 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
860
860
861 users_group = relationship('UserGroup')
861 users_group = relationship('UserGroup')
862 permission = relationship('Permission')
862 permission = relationship('Permission')
863 repository = relationship('Repository')
863 repository = relationship('Repository')
864
864
865 def __unicode__(self):
865 def __unicode__(self):
866 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
866 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
867
867
868
868
869 class UserGroupUserGroupToPerm(Base, BaseModel):
869 class UserGroupUserGroupToPerm(Base, BaseModel):
870 __tablename__ = 'user_group_user_group_to_perm'
870 __tablename__ = 'user_group_user_group_to_perm'
871 __table_args__ = (
871 __table_args__ = (
872 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
872 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
873 CheckConstraint('target_user_group_id != user_group_id'),
873 CheckConstraint('target_user_group_id != user_group_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_group_user_group_to_perm_id = Column("user_group_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
877 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)
878 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
878 target_user_group_id = Column("target_user_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 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
880 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
881
881
882 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
882 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
883 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
883 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
884 permission = relationship('Permission')
884 permission = relationship('Permission')
885
885
886 def __unicode__(self):
886 def __unicode__(self):
887 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
887 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
888
888
889
889
890 class UserGroupToPerm(Base, BaseModel):
890 class UserGroupToPerm(Base, BaseModel):
891 __tablename__ = 'users_group_to_perm'
891 __tablename__ = 'users_group_to_perm'
892 __table_args__ = (
892 __table_args__ = (
893 UniqueConstraint('users_group_id', 'permission_id',),
893 UniqueConstraint('users_group_id', 'permission_id',),
894 {'extend_existing': True, 'mysql_engine': 'InnoDB',
894 {'extend_existing': True, 'mysql_engine': 'InnoDB',
895 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
895 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
896 )
896 )
897 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
897 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
898 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
898 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
899 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
899 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
900
900
901 users_group = relationship('UserGroup')
901 users_group = relationship('UserGroup')
902 permission = relationship('Permission')
902 permission = relationship('Permission')
903
903
904
904
905 class UserRepoGroupToPerm(Base, BaseModel):
905 class UserRepoGroupToPerm(Base, BaseModel):
906 __tablename__ = 'user_repo_group_to_perm'
906 __tablename__ = 'user_repo_group_to_perm'
907 __table_args__ = (
907 __table_args__ = (
908 UniqueConstraint('user_id', 'group_id', 'permission_id'),
908 UniqueConstraint('user_id', '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
912
913 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
913 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
914 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
914 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
915 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
915 group_id = Column("group_id", Integer(), ForeignKey('groups.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
917
918 user = relationship('User')
918 user = relationship('User')
919 group = relationship('RepoGroup')
919 group = relationship('RepoGroup')
920 permission = relationship('Permission')
920 permission = relationship('Permission')
921
921
922
922
923 class UserGroupRepoGroupToPerm(Base, BaseModel):
923 class UserGroupRepoGroupToPerm(Base, BaseModel):
924 __tablename__ = 'users_group_repo_group_to_perm'
924 __tablename__ = 'users_group_repo_group_to_perm'
925 __table_args__ = (
925 __table_args__ = (
926 UniqueConstraint('users_group_id', 'group_id'),
926 UniqueConstraint('users_group_id', 'group_id'),
927 {'extend_existing': True, 'mysql_engine': 'InnoDB',
927 {'extend_existing': True, 'mysql_engine': 'InnoDB',
928 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
928 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
929 )
929 )
930
930
931 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)
931 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)
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 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
933 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
934 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
934 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
935
935
936 users_group = relationship('UserGroup')
936 users_group = relationship('UserGroup')
937 permission = relationship('Permission')
937 permission = relationship('Permission')
938 group = relationship('RepoGroup')
938 group = relationship('RepoGroup')
939
939
940
940
941 class Statistics(Base, BaseModel):
941 class Statistics(Base, BaseModel):
942 __tablename__ = 'statistics'
942 __tablename__ = 'statistics'
943 __table_args__ = (
943 __table_args__ = (
944 UniqueConstraint('repository_id'),
944 UniqueConstraint('repository_id'),
945 {'extend_existing': True, 'mysql_engine': 'InnoDB',
945 {'extend_existing': True, 'mysql_engine': 'InnoDB',
946 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
946 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
947 )
947 )
948 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
948 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
949 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
949 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
950 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
950 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
951 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
951 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
952 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
952 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
953 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
953 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
954
954
955 repository = relationship('Repository', single_parent=True)
955 repository = relationship('Repository', single_parent=True)
956
956
957
957
958 class UserFollowing(Base, BaseModel):
958 class UserFollowing(Base, BaseModel):
959 __tablename__ = 'user_followings'
959 __tablename__ = 'user_followings'
960 __table_args__ = (
960 __table_args__ = (
961 UniqueConstraint('user_id', 'follows_repository_id'),
961 UniqueConstraint('user_id', 'follows_repository_id'),
962 UniqueConstraint('user_id', 'follows_user_id'),
962 UniqueConstraint('user_id', 'follows_user_id'),
963 {'extend_existing': True, 'mysql_engine': 'InnoDB',
963 {'extend_existing': True, 'mysql_engine': 'InnoDB',
964 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
964 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
965 )
965 )
966
966
967 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
967 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
968 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
968 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
969 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
969 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
970 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
970 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
971 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
971 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
972
972
973 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
973 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
974
974
975 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
975 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
976 follows_repository = relationship('Repository', order_by='Repository.repo_name')
976 follows_repository = relationship('Repository', order_by='Repository.repo_name')
977
977
978
978
979 class CacheInvalidation(Base, BaseModel):
979 class CacheInvalidation(Base, BaseModel):
980 __tablename__ = 'cache_invalidation'
980 __tablename__ = 'cache_invalidation'
981 __table_args__ = (
981 __table_args__ = (
982 UniqueConstraint('cache_key'),
982 UniqueConstraint('cache_key'),
983 Index('key_idx', 'cache_key'),
983 Index('key_idx', 'cache_key'),
984 {'extend_existing': True, 'mysql_engine': 'InnoDB',
984 {'extend_existing': True, 'mysql_engine': 'InnoDB',
985 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
985 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
986 )
986 )
987 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
987 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
988 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
988 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
989 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
989 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
990 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
990 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
991
991
992 def __init__(self, cache_key, cache_args=''):
992 def __init__(self, cache_key, cache_args=''):
993 self.cache_key = cache_key
993 self.cache_key = cache_key
994 self.cache_args = cache_args
994 self.cache_args = cache_args
995 self.cache_active = False
995 self.cache_active = False
996
996
997
997
998 class ChangesetComment(Base, BaseModel):
998 class ChangesetComment(Base, BaseModel):
999 __tablename__ = 'changeset_comments'
999 __tablename__ = 'changeset_comments'
1000 __table_args__ = (
1000 __table_args__ = (
1001 Index('cc_revision_idx', 'revision'),
1001 Index('cc_revision_idx', 'revision'),
1002 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1002 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1003 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1003 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1004 )
1004 )
1005 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1005 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1006 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1006 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1007 revision = Column('revision', String(40), nullable=True)
1007 revision = Column('revision', String(40), nullable=True)
1008 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1008 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1009 line_no = Column('line_no', Unicode(10), nullable=True)
1009 line_no = Column('line_no', Unicode(10), nullable=True)
1010 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1010 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1011 f_path = Column('f_path', Unicode(1000), nullable=True)
1011 f_path = Column('f_path', Unicode(1000), nullable=True)
1012 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1012 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1013 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1013 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1014 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1014 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1015 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1015 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1016
1016
1017 author = relationship('User', lazy='joined')
1017 author = relationship('User', lazy='joined')
1018 repo = relationship('Repository')
1018 repo = relationship('Repository')
1019 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1019 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1020 pull_request = relationship('PullRequest', lazy='joined')
1020 pull_request = relationship('PullRequest', lazy='joined')
1021
1021
1022
1022
1023 class ChangesetStatus(Base, BaseModel):
1023 class ChangesetStatus(Base, BaseModel):
1024 __tablename__ = 'changeset_statuses'
1024 __tablename__ = 'changeset_statuses'
1025 __table_args__ = (
1025 __table_args__ = (
1026 Index('cs_revision_idx', 'revision'),
1026 Index('cs_revision_idx', 'revision'),
1027 Index('cs_version_idx', 'version'),
1027 Index('cs_version_idx', 'version'),
1028 UniqueConstraint('repo_id', 'revision', 'version'),
1028 UniqueConstraint('repo_id', 'revision', 'version'),
1029 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1029 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1030 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1030 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1031 )
1031 )
1032 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1032 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1033 STATUS_APPROVED = 'approved'
1033 STATUS_APPROVED = 'approved'
1034 STATUS_REJECTED = 'rejected'
1034 STATUS_REJECTED = 'rejected'
1035 STATUS_UNDER_REVIEW = 'under_review'
1035 STATUS_UNDER_REVIEW = 'under_review'
1036
1036
1037 STATUSES = [
1037 STATUSES = [
1038 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1038 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1039 (STATUS_APPROVED, _("Approved")),
1039 (STATUS_APPROVED, _("Approved")),
1040 (STATUS_REJECTED, _("Rejected")),
1040 (STATUS_REJECTED, _("Rejected")),
1041 (STATUS_UNDER_REVIEW, _("Under Review")),
1041 (STATUS_UNDER_REVIEW, _("Under Review")),
1042 ]
1042 ]
1043
1043
1044 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1044 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1045 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1045 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1046 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1046 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1047 revision = Column('revision', String(40), nullable=False)
1047 revision = Column('revision', String(40), nullable=False)
1048 status = Column('status', String(128), nullable=False, default=DEFAULT)
1048 status = Column('status', String(128), nullable=False, default=DEFAULT)
1049 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1049 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1050 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1050 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1051 version = Column('version', Integer(), nullable=False, default=0)
1051 version = Column('version', Integer(), nullable=False, default=0)
1052 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1052 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1053
1053
1054 author = relationship('User', lazy='joined')
1054 author = relationship('User', lazy='joined')
1055 repo = relationship('Repository')
1055 repo = relationship('Repository')
1056 comment = relationship('ChangesetComment', lazy='joined')
1056 comment = relationship('ChangesetComment', lazy='joined')
1057 pull_request = relationship('PullRequest', lazy='joined')
1057 pull_request = relationship('PullRequest', lazy='joined')
1058
1058
1059
1059
1060
1060
1061 class PullRequest(Base, BaseModel):
1061 class PullRequest(Base, BaseModel):
1062 __tablename__ = 'pull_requests'
1062 __tablename__ = 'pull_requests'
1063 __table_args__ = (
1063 __table_args__ = (
1064 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1064 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1065 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1065 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1066 )
1066 )
1067
1067
1068 STATUS_NEW = u'new'
1068 STATUS_NEW = u'new'
1069 STATUS_OPEN = u'open'
1069 STATUS_OPEN = u'open'
1070 STATUS_CLOSED = u'closed'
1070 STATUS_CLOSED = u'closed'
1071
1071
1072 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1072 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1073 title = Column('title', Unicode(256), nullable=True)
1073 title = Column('title', Unicode(256), nullable=True)
1074 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1074 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1075 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1075 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1076 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1076 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1077 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1077 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1078 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1078 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1079 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1079 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1080 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1080 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1081 org_ref = Column('org_ref', Unicode(256), nullable=False)
1081 org_ref = Column('org_ref', Unicode(256), nullable=False)
1082 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1082 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1083 other_ref = Column('other_ref', Unicode(256), nullable=False)
1083 other_ref = Column('other_ref', Unicode(256), nullable=False)
1084
1084
1085 author = relationship('User', lazy='joined')
1085 author = relationship('User', lazy='joined')
1086 reviewers = relationship('PullRequestReviewers',
1086 reviewers = relationship('PullRequestReviewers',
1087 cascade="all, delete, delete-orphan")
1087 cascade="all, delete, delete-orphan")
1088 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1088 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1089 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1089 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1090 statuses = relationship('ChangesetStatus')
1090 statuses = relationship('ChangesetStatus')
1091 comments = relationship('ChangesetComment',
1091 comments = relationship('ChangesetComment',
1092 cascade="all, delete, delete-orphan")
1092 cascade="all, delete, delete-orphan")
1093
1093
1094
1094
1095 class PullRequestReviewers(Base, BaseModel):
1095 class PullRequestReviewers(Base, BaseModel):
1096 __tablename__ = 'pull_request_reviewers'
1096 __tablename__ = 'pull_request_reviewers'
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 def __init__(self, user=None, pull_request=None):
1102 def __init__(self, user=None, pull_request=None):
1103 self.user = user
1103 self.user = user
1104 self.pull_request = pull_request
1104 self.pull_request = pull_request
1105
1105
1106 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1106 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1107 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1107 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1108 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1108 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1109
1109
1110 user = relationship('User')
1110 user = relationship('User')
1111 pull_request = relationship('PullRequest')
1111 pull_request = relationship('PullRequest')
1112
1112
1113
1113
1114 class Notification(Base, BaseModel):
1114 class Notification(Base, BaseModel):
1115 __tablename__ = 'notifications'
1115 __tablename__ = 'notifications'
1116 __table_args__ = (
1116 __table_args__ = (
1117 Index('notification_type_idx', 'type'),
1117 Index('notification_type_idx', 'type'),
1118 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1118 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1119 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1119 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1120 )
1120 )
1121
1121
1122 TYPE_CHANGESET_COMMENT = u'cs_comment'
1122 TYPE_CHANGESET_COMMENT = u'cs_comment'
1123 TYPE_MESSAGE = u'message'
1123 TYPE_MESSAGE = u'message'
1124 TYPE_MENTION = u'mention'
1124 TYPE_MENTION = u'mention'
1125 TYPE_REGISTRATION = u'registration'
1125 TYPE_REGISTRATION = u'registration'
1126 TYPE_PULL_REQUEST = u'pull_request'
1126 TYPE_PULL_REQUEST = u'pull_request'
1127 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1127 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1128
1128
1129 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1129 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1130 subject = Column('subject', Unicode(512), nullable=True)
1130 subject = Column('subject', Unicode(512), nullable=True)
1131 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1131 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1132 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1132 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1133 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1133 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1134 type_ = Column('type', Unicode(256))
1134 type_ = Column('type', Unicode(256))
1135
1135
1136 created_by_user = relationship('User')
1136 created_by_user = relationship('User')
1137 notifications_to_users = relationship('UserNotification', lazy='joined',
1137 notifications_to_users = relationship('UserNotification', lazy='joined',
1138 cascade="all, delete, delete-orphan")
1138 cascade="all, delete, delete-orphan")
1139
1139
1140
1140
1141 class UserNotification(Base, BaseModel):
1141 class UserNotification(Base, BaseModel):
1142 __tablename__ = 'user_to_notification'
1142 __tablename__ = 'user_to_notification'
1143 __table_args__ = (
1143 __table_args__ = (
1144 UniqueConstraint('user_id', 'notification_id'),
1144 UniqueConstraint('user_id', 'notification_id'),
1145 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1145 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1146 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1146 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1147 )
1147 )
1148 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1148 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1149 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1149 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1150 read = Column('read', Boolean, default=False)
1150 read = Column('read', Boolean, default=False)
1151 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1151 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1152
1152
1153 user = relationship('User', lazy="joined")
1153 user = relationship('User', lazy="joined")
1154 notification = relationship('Notification', lazy="joined",
1154 notification = relationship('Notification', lazy="joined",
1155 order_by=lambda: Notification.created_on.desc(),)
1155 order_by=lambda: Notification.created_on.desc(),)
1156
1156
1157
1157
1158 class Gist(Base, BaseModel):
1158 class Gist(Base, BaseModel):
1159 __tablename__ = 'gists'
1159 __tablename__ = 'gists'
1160 __table_args__ = (
1160 __table_args__ = (
1161 Index('g_gist_access_id_idx', 'gist_access_id'),
1161 Index('g_gist_access_id_idx', 'gist_access_id'),
1162 Index('g_created_on_idx', 'created_on'),
1162 Index('g_created_on_idx', 'created_on'),
1163 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1163 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1164 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1164 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1165 )
1165 )
1166 GIST_PUBLIC = u'public'
1166 GIST_PUBLIC = u'public'
1167 GIST_PRIVATE = u'private'
1167 GIST_PRIVATE = u'private'
1168
1168
1169 gist_id = Column('gist_id', Integer(), primary_key=True)
1169 gist_id = Column('gist_id', Integer(), primary_key=True)
1170 gist_access_id = Column('gist_access_id', Unicode(250))
1170 gist_access_id = Column('gist_access_id', Unicode(250))
1171 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1171 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1172 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1172 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1173 gist_expires = Column('gist_expires', Float(53), nullable=False)
1173 gist_expires = Column('gist_expires', Float(53), nullable=False)
1174 gist_type = Column('gist_type', Unicode(128), nullable=False)
1174 gist_type = Column('gist_type', Unicode(128), nullable=False)
1175 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1175 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1176 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1176 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1177
1177
1178 owner = relationship('User')
1178 owner = relationship('User')
1179
1179
1180
1180
1181 class DbMigrateVersion(Base, BaseModel):
1181 class DbMigrateVersion(Base, BaseModel):
1182 __tablename__ = 'db_migrate_version'
1182 __tablename__ = 'db_migrate_version'
1183 __table_args__ = (
1183 __table_args__ = (
1184 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1184 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1185 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1185 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1186 )
1186 )
1187 repository_id = Column('repository_id', String(250), primary_key=True)
1187 repository_id = Column('repository_id', String(250), primary_key=True)
1188 repository_path = Column('repository_path', Text)
1188 repository_path = Column('repository_path', Text)
1189 version = Column('version', Integer)
1189 version = Column('version', Integer)
@@ -1,1206 +1,1206 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import time
22 import time
23 import logging
23 import logging
24 import datetime
24 import datetime
25 import traceback
25 import traceback
26 import hashlib
26 import hashlib
27 import collections
27 import collections
28 import functools
28 import functools
29
29
30 from sqlalchemy import *
30 from sqlalchemy import *
31 from sqlalchemy.ext.hybrid import hybrid_property
31 from sqlalchemy.ext.hybrid import hybrid_property
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
32 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
33 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.exc import DatabaseError
34 from beaker.cache import cache_region, region_invalidate
34 from beaker.cache import cache_region, region_invalidate
35 from webob.exc import HTTPNotFound
35 from webob.exc import HTTPNotFound
36
36
37 from pylons.i18n.translation import lazy_ugettext as _
37 from rhodecode.translation import _
38
38
39 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.utils.helpers import get_scm
40 from rhodecode.lib.vcs.utils.helpers import get_scm
41 from rhodecode.lib.vcs.exceptions import VCSError
41 from rhodecode.lib.vcs.exceptions import VCSError
42 from zope.cachedescriptors.property import Lazy as LazyProperty
42 from zope.cachedescriptors.property import Lazy as LazyProperty
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
43 from rhodecode.lib.vcs.backends.base import EmptyCommit
44
44
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
45 from rhodecode.lib.utils2 import str2bool, safe_str, get_commit_safe, \
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
46 safe_unicode, remove_prefix, time_to_datetime, aslist, Optional, safe_int
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.iteritems():
87 for k, val in _json_attr.iteritems():
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_unicode,
163 'unicode': safe_unicode,
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) == unicode
181 assert type(val) == unicode
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_unicode(val)
198 self._app_settings_value = safe_unicode(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
238
239
239
240 class User(Base, BaseModel):
240 class User(Base, BaseModel):
241 __tablename__ = 'users'
241 __tablename__ = 'users'
242 __table_args__ = (
242 __table_args__ = (
243 UniqueConstraint('username'), UniqueConstraint('email'),
243 UniqueConstraint('username'), UniqueConstraint('email'),
244 Index('u_username_idx', 'username'),
244 Index('u_username_idx', 'username'),
245 Index('u_email_idx', 'email'),
245 Index('u_email_idx', 'email'),
246 {'extend_existing': True, 'mysql_engine': 'InnoDB',
246 {'extend_existing': True, 'mysql_engine': 'InnoDB',
247 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
247 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
248 )
248 )
249 DEFAULT_USER = 'default'
249 DEFAULT_USER = 'default'
250 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
250 DEFAULT_GRAVATAR_URL = 'https://secure.gravatar.com/avatar/{md5email}?d=identicon&s={size}'
251
251
252 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
252 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
253 username = Column("username", String(255), nullable=True, unique=None, default=None)
253 username = Column("username", String(255), nullable=True, unique=None, default=None)
254 password = Column("password", String(255), nullable=True, unique=None, default=None)
254 password = Column("password", String(255), nullable=True, unique=None, default=None)
255 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
255 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
256 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
256 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
257 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
257 name = Column("firstname", String(255), nullable=True, unique=None, default=None)
258 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
258 lastname = Column("lastname", String(255), nullable=True, unique=None, default=None)
259 _email = Column("email", String(255), nullable=True, unique=None, default=None)
259 _email = Column("email", String(255), nullable=True, unique=None, default=None)
260 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
260 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
261 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
261 extern_type = Column("extern_type", String(255), nullable=True, unique=None, default=None)
262 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
262 extern_name = Column("extern_name", String(255), nullable=True, unique=None, default=None)
263 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
263 api_key = Column("api_key", String(255), nullable=True, unique=None, default=None)
264 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
264 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
265 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
265 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
266
266
267 user_log = relationship('UserLog')
267 user_log = relationship('UserLog')
268 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
268 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
269
269
270 repositories = relationship('Repository')
270 repositories = relationship('Repository')
271 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
271 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
272 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
272 followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
273
273
274 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
274 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
275 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
275 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
276
276
277 group_member = relationship('UserGroupMember', cascade='all')
277 group_member = relationship('UserGroupMember', cascade='all')
278
278
279 notifications = relationship('UserNotification', cascade='all')
279 notifications = relationship('UserNotification', cascade='all')
280 # notifications assigned to this user
280 # notifications assigned to this user
281 user_created_notifications = relationship('Notification', cascade='all')
281 user_created_notifications = relationship('Notification', cascade='all')
282 # comments created by this user
282 # comments created by this user
283 user_comments = relationship('ChangesetComment', cascade='all')
283 user_comments = relationship('ChangesetComment', cascade='all')
284 user_emails = relationship('UserEmailMap', cascade='all')
284 user_emails = relationship('UserEmailMap', cascade='all')
285
285
286 @hybrid_property
286 @hybrid_property
287 def email(self):
287 def email(self):
288 return self._email
288 return self._email
289
289
290 @email.setter
290 @email.setter
291 def email(self, val):
291 def email(self, val):
292 self._email = val.lower() if val else None
292 self._email = val.lower() if val else None
293
293
294 @property
294 @property
295 def firstname(self):
295 def firstname(self):
296 # alias for future
296 # alias for future
297 return self.name
297 return self.name
298
298
299 @property
299 @property
300 def username_and_name(self):
300 def username_and_name(self):
301 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
301 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
302
302
303 @property
303 @property
304 def full_name(self):
304 def full_name(self):
305 return '%s %s' % (self.firstname, self.lastname)
305 return '%s %s' % (self.firstname, self.lastname)
306
306
307 @property
307 @property
308 def full_contact(self):
308 def full_contact(self):
309 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
309 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
310
310
311 @property
311 @property
312 def short_contact(self):
312 def short_contact(self):
313 return '%s %s' % (self.firstname, self.lastname)
313 return '%s %s' % (self.firstname, self.lastname)
314
314
315 @property
315 @property
316 def is_admin(self):
316 def is_admin(self):
317 return self.admin
317 return self.admin
318
318
319 @classmethod
319 @classmethod
320 def get_by_username(cls, username, case_insensitive=False, cache=False):
320 def get_by_username(cls, username, case_insensitive=False, cache=False):
321 if case_insensitive:
321 if case_insensitive:
322 q = cls.query().filter(cls.username.ilike(username))
322 q = cls.query().filter(cls.username.ilike(username))
323 else:
323 else:
324 q = cls.query().filter(cls.username == username)
324 q = cls.query().filter(cls.username == username)
325
325
326 if cache:
326 if cache:
327 q = q.options(FromCache(
327 q = q.options(FromCache(
328 "sql_cache_short",
328 "sql_cache_short",
329 "get_user_%s" % _hash_key(username)
329 "get_user_%s" % _hash_key(username)
330 )
330 )
331 )
331 )
332 return q.scalar()
332 return q.scalar()
333
333
334 @classmethod
334 @classmethod
335 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
335 def get_by_auth_token(cls, auth_token, cache=False, fallback=True):
336 q = cls.query().filter(cls.api_key == auth_token)
336 q = cls.query().filter(cls.api_key == auth_token)
337
337
338 if cache:
338 if cache:
339 q = q.options(FromCache("sql_cache_short",
339 q = q.options(FromCache("sql_cache_short",
340 "get_auth_token_%s" % auth_token))
340 "get_auth_token_%s" % auth_token))
341 res = q.scalar()
341 res = q.scalar()
342
342
343 if fallback and not res:
343 if fallback and not res:
344 #fallback to additional keys
344 #fallback to additional keys
345 _res = UserApiKeys.query()\
345 _res = UserApiKeys.query()\
346 .filter(UserApiKeys.api_key == auth_token)\
346 .filter(UserApiKeys.api_key == auth_token)\
347 .filter(or_(UserApiKeys.expires == -1,
347 .filter(or_(UserApiKeys.expires == -1,
348 UserApiKeys.expires >= time.time()))\
348 UserApiKeys.expires >= time.time()))\
349 .first()
349 .first()
350 if _res:
350 if _res:
351 res = _res.user
351 res = _res.user
352 return res
352 return res
353
353
354 @classmethod
354 @classmethod
355 def get_by_email(cls, email, case_insensitive=False, cache=False):
355 def get_by_email(cls, email, case_insensitive=False, cache=False):
356
356
357 if case_insensitive:
357 if case_insensitive:
358 q = cls.query().filter(cls.email.ilike(email))
358 q = cls.query().filter(cls.email.ilike(email))
359 else:
359 else:
360 q = cls.query().filter(cls.email == email)
360 q = cls.query().filter(cls.email == email)
361
361
362 if cache:
362 if cache:
363 q = q.options(FromCache("sql_cache_short",
363 q = q.options(FromCache("sql_cache_short",
364 "get_email_key_%s" % email))
364 "get_email_key_%s" % email))
365
365
366 ret = q.scalar()
366 ret = q.scalar()
367 if ret is None:
367 if ret is None:
368 q = UserEmailMap.query()
368 q = UserEmailMap.query()
369 # try fetching in alternate email map
369 # try fetching in alternate email map
370 if case_insensitive:
370 if case_insensitive:
371 q = q.filter(UserEmailMap.email.ilike(email))
371 q = q.filter(UserEmailMap.email.ilike(email))
372 else:
372 else:
373 q = q.filter(UserEmailMap.email == email)
373 q = q.filter(UserEmailMap.email == email)
374 q = q.options(joinedload(UserEmailMap.user))
374 q = q.options(joinedload(UserEmailMap.user))
375 if cache:
375 if cache:
376 q = q.options(FromCache("sql_cache_short",
376 q = q.options(FromCache("sql_cache_short",
377 "get_email_map_key_%s" % email))
377 "get_email_map_key_%s" % email))
378 ret = getattr(q.scalar(), 'user', None)
378 ret = getattr(q.scalar(), 'user', None)
379
379
380 return ret
380 return ret
381
381
382 @classmethod
382 @classmethod
383 def get_first_admin(cls):
383 def get_first_admin(cls):
384 user = User.query().filter(User.admin == True).first()
384 user = User.query().filter(User.admin == True).first()
385 if user is None:
385 if user is None:
386 raise Exception('Missing administrative account!')
386 raise Exception('Missing administrative account!')
387 return user
387 return user
388
388
389 @classmethod
389 @classmethod
390 def get_default_user(cls, cache=False):
390 def get_default_user(cls, cache=False):
391 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
391 user = User.get_by_username(User.DEFAULT_USER, cache=cache)
392 if user is None:
392 if user is None:
393 raise Exception('Missing default account!')
393 raise Exception('Missing default account!')
394 return user
394 return user
395
395
396
396
397 class UserApiKeys(Base, BaseModel):
397 class UserApiKeys(Base, BaseModel):
398 __tablename__ = 'user_api_keys'
398 __tablename__ = 'user_api_keys'
399 __table_args__ = (
399 __table_args__ = (
400 Index('uak_api_key_idx', 'api_key'),
400 Index('uak_api_key_idx', 'api_key'),
401 UniqueConstraint('api_key'),
401 UniqueConstraint('api_key'),
402 {'extend_existing': True, 'mysql_engine': 'InnoDB',
402 {'extend_existing': True, 'mysql_engine': 'InnoDB',
403 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
403 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
404 )
404 )
405 __mapper_args__ = {}
405 __mapper_args__ = {}
406
406
407 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
407 user_api_key_id = Column("user_api_key_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
408 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
408 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
409 api_key = Column("api_key", String(255), nullable=False, unique=True)
409 api_key = Column("api_key", String(255), nullable=False, unique=True)
410 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
410 description = Column('description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
411 expires = Column('expires', Float(53), nullable=False)
411 expires = Column('expires', Float(53), nullable=False)
412 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
412 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
413
413
414 user = relationship('User', lazy='joined')
414 user = relationship('User', lazy='joined')
415
415
416
416
417 class UserEmailMap(Base, BaseModel):
417 class UserEmailMap(Base, BaseModel):
418 __tablename__ = 'user_email_map'
418 __tablename__ = 'user_email_map'
419 __table_args__ = (
419 __table_args__ = (
420 Index('uem_email_idx', 'email'),
420 Index('uem_email_idx', 'email'),
421 UniqueConstraint('email'),
421 UniqueConstraint('email'),
422 {'extend_existing': True, 'mysql_engine': 'InnoDB',
422 {'extend_existing': True, 'mysql_engine': 'InnoDB',
423 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
423 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
424 )
424 )
425 __mapper_args__ = {}
425 __mapper_args__ = {}
426
426
427 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
427 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
428 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
428 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
429 _email = Column("email", String(255), nullable=True, unique=False, default=None)
429 _email = Column("email", String(255), nullable=True, unique=False, default=None)
430 user = relationship('User', lazy='joined')
430 user = relationship('User', lazy='joined')
431
431
432 @validates('_email')
432 @validates('_email')
433 def validate_email(self, key, email):
433 def validate_email(self, key, email):
434 # check if this email is not main one
434 # check if this email is not main one
435 main_email = Session().query(User).filter(User.email == email).scalar()
435 main_email = Session().query(User).filter(User.email == email).scalar()
436 if main_email is not None:
436 if main_email is not None:
437 raise AttributeError('email %s is present is user table' % email)
437 raise AttributeError('email %s is present is user table' % email)
438 return email
438 return email
439
439
440 @hybrid_property
440 @hybrid_property
441 def email(self):
441 def email(self):
442 return self._email
442 return self._email
443
443
444 @email.setter
444 @email.setter
445 def email(self, val):
445 def email(self, val):
446 self._email = val.lower() if val else None
446 self._email = val.lower() if val else None
447
447
448
448
449 class UserIpMap(Base, BaseModel):
449 class UserIpMap(Base, BaseModel):
450 __tablename__ = 'user_ip_map'
450 __tablename__ = 'user_ip_map'
451 __table_args__ = (
451 __table_args__ = (
452 UniqueConstraint('user_id', 'ip_addr'),
452 UniqueConstraint('user_id', 'ip_addr'),
453 {'extend_existing': True, 'mysql_engine': 'InnoDB',
453 {'extend_existing': True, 'mysql_engine': 'InnoDB',
454 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
454 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
455 )
455 )
456 __mapper_args__ = {}
456 __mapper_args__ = {}
457
457
458 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
458 ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
459 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
459 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
460 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
460 ip_addr = Column("ip_addr", String(255), nullable=True, unique=False, default=None)
461 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
461 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
462 user = relationship('User', lazy='joined')
462 user = relationship('User', lazy='joined')
463
463
464
464
465 class UserLog(Base, BaseModel):
465 class UserLog(Base, BaseModel):
466 __tablename__ = 'user_logs'
466 __tablename__ = 'user_logs'
467 __table_args__ = (
467 __table_args__ = (
468 {'extend_existing': True, 'mysql_engine': 'InnoDB',
468 {'extend_existing': True, 'mysql_engine': 'InnoDB',
469 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
469 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
470 )
470 )
471 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
471 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
472 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
472 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
473 username = Column("username", String(255), nullable=True, unique=None, default=None)
473 username = Column("username", String(255), nullable=True, unique=None, default=None)
474 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
474 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
475 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
475 repository_name = Column("repository_name", String(255), nullable=True, unique=None, default=None)
476 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
476 user_ip = Column("user_ip", String(255), nullable=True, unique=None, default=None)
477 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
477 action = Column("action", String(1200000), nullable=True, unique=None, default=None)
478 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
478 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
479
479
480 def __unicode__(self):
480 def __unicode__(self):
481 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
481 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
482 self.repository_name,
482 self.repository_name,
483 self.action)
483 self.action)
484
484
485 user = relationship('User')
485 user = relationship('User')
486 repository = relationship('Repository', cascade='')
486 repository = relationship('Repository', cascade='')
487
487
488
488
489 class UserGroup(Base, BaseModel):
489 class UserGroup(Base, BaseModel):
490 __tablename__ = 'users_groups'
490 __tablename__ = 'users_groups'
491 __table_args__ = (
491 __table_args__ = (
492 {'extend_existing': True, 'mysql_engine': 'InnoDB',
492 {'extend_existing': True, 'mysql_engine': 'InnoDB',
493 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
493 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
494 )
494 )
495
495
496 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
496 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
497 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
497 users_group_name = Column("users_group_name", String(255), nullable=False, unique=True, default=None)
498 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
498 user_group_description = Column("user_group_description", String(10000), nullable=True, unique=None, default=None)
499 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
499 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
500 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
500 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
501 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
501 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
502 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
502 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
503
503
504 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
504 members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
505 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
505 users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
506 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
506 users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
507 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
507 users_group_repo_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
508 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
508 user_user_group_to_perm = relationship('UserUserGroupToPerm', cascade='all')
509 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
509 user_group_user_group_to_perm = relationship('UserGroupUserGroupToPerm ', primaryjoin="UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id", cascade='all')
510
510
511 user = relationship('User')
511 user = relationship('User')
512
512
513 def __unicode__(self):
513 def __unicode__(self):
514 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
514 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
515 self.users_group_id,
515 self.users_group_id,
516 self.users_group_name)
516 self.users_group_name)
517
517
518 @classmethod
518 @classmethod
519 def get_by_group_name(cls, group_name, cache=False,
519 def get_by_group_name(cls, group_name, cache=False,
520 case_insensitive=False):
520 case_insensitive=False):
521 if case_insensitive:
521 if case_insensitive:
522 q = cls.query().filter(cls.users_group_name.ilike(group_name))
522 q = cls.query().filter(cls.users_group_name.ilike(group_name))
523 else:
523 else:
524 q = cls.query().filter(cls.users_group_name == group_name)
524 q = cls.query().filter(cls.users_group_name == group_name)
525 if cache:
525 if cache:
526 q = q.options(FromCache(
526 q = q.options(FromCache(
527 "sql_cache_short",
527 "sql_cache_short",
528 "get_user_%s" % _hash_key(group_name)
528 "get_user_%s" % _hash_key(group_name)
529 )
529 )
530 )
530 )
531 return q.scalar()
531 return q.scalar()
532
532
533 @classmethod
533 @classmethod
534 def get(cls, user_group_id, cache=False):
534 def get(cls, user_group_id, cache=False):
535 user_group = cls.query()
535 user_group = cls.query()
536 if cache:
536 if cache:
537 user_group = user_group.options(FromCache("sql_cache_short",
537 user_group = user_group.options(FromCache("sql_cache_short",
538 "get_users_group_%s" % user_group_id))
538 "get_users_group_%s" % user_group_id))
539 return user_group.get(user_group_id)
539 return user_group.get(user_group_id)
540
540
541
541
542 class UserGroupMember(Base, BaseModel):
542 class UserGroupMember(Base, BaseModel):
543 __tablename__ = 'users_groups_members'
543 __tablename__ = 'users_groups_members'
544 __table_args__ = (
544 __table_args__ = (
545 {'extend_existing': True, 'mysql_engine': 'InnoDB',
545 {'extend_existing': True, 'mysql_engine': 'InnoDB',
546 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
546 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
547 )
547 )
548
548
549 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
549 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
550 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
550 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
551 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
551 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
552
552
553 user = relationship('User', lazy='joined')
553 user = relationship('User', lazy='joined')
554 users_group = relationship('UserGroup')
554 users_group = relationship('UserGroup')
555
555
556 def __init__(self, gr_id='', u_id=''):
556 def __init__(self, gr_id='', u_id=''):
557 self.users_group_id = gr_id
557 self.users_group_id = gr_id
558 self.user_id = u_id
558 self.user_id = u_id
559
559
560
560
561 class RepositoryField(Base, BaseModel):
561 class RepositoryField(Base, BaseModel):
562 __tablename__ = 'repositories_fields'
562 __tablename__ = 'repositories_fields'
563 __table_args__ = (
563 __table_args__ = (
564 UniqueConstraint('repository_id', 'field_key'), # no-multi field
564 UniqueConstraint('repository_id', 'field_key'), # no-multi field
565 {'extend_existing': True, 'mysql_engine': 'InnoDB',
565 {'extend_existing': True, 'mysql_engine': 'InnoDB',
566 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
566 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
567 )
567 )
568 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
568 PREFIX = 'ex_' # prefix used in form to not conflict with already existing fields
569
569
570 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
570 repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
571 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
571 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
572 field_key = Column("field_key", String(250))
572 field_key = Column("field_key", String(250))
573 field_label = Column("field_label", String(1024), nullable=False)
573 field_label = Column("field_label", String(1024), nullable=False)
574 field_value = Column("field_value", String(10000), nullable=False)
574 field_value = Column("field_value", String(10000), nullable=False)
575 field_desc = Column("field_desc", String(1024), nullable=False)
575 field_desc = Column("field_desc", String(1024), nullable=False)
576 field_type = Column("field_type", String(256), nullable=False, unique=None)
576 field_type = Column("field_type", String(256), nullable=False, unique=None)
577 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
577 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
578
578
579 repository = relationship('Repository')
579 repository = relationship('Repository')
580
580
581 @classmethod
581 @classmethod
582 def get_by_key_name(cls, key, repo):
582 def get_by_key_name(cls, key, repo):
583 row = cls.query()\
583 row = cls.query()\
584 .filter(cls.repository == repo)\
584 .filter(cls.repository == repo)\
585 .filter(cls.field_key == key).scalar()
585 .filter(cls.field_key == key).scalar()
586 return row
586 return row
587
587
588
588
589 class Repository(Base, BaseModel):
589 class Repository(Base, BaseModel):
590 __tablename__ = 'repositories'
590 __tablename__ = 'repositories'
591 __table_args__ = (
591 __table_args__ = (
592 UniqueConstraint('repo_name'),
592 UniqueConstraint('repo_name'),
593 Index('r_repo_name_idx', 'repo_name'),
593 Index('r_repo_name_idx', 'repo_name'),
594 {'extend_existing': True, 'mysql_engine': 'InnoDB',
594 {'extend_existing': True, 'mysql_engine': 'InnoDB',
595 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
595 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
596 )
596 )
597 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
597 DEFAULT_CLONE_URI = '{scheme}://{user}@{netloc}/{repo}'
598
598
599 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
599 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
600 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
600 repo_name = Column("repo_name", String(255), nullable=False, unique=True, default=None)
601 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
601 clone_uri = Column("clone_uri", String(255), nullable=True, unique=False, default=None)
602 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
602 repo_type = Column("repo_type", String(255), nullable=False, unique=False, default=None)
603 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
603 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
604 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
604 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
605 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
605 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
606 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
606 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
607 description = Column("description", String(10000), nullable=True, unique=None, default=None)
607 description = Column("description", String(10000), nullable=True, unique=None, default=None)
608 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
608 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
609 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
609 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
610 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
610 _landing_revision = Column("landing_revision", String(255), nullable=False, unique=False, default=None)
611 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
611 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
612 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
612 _locked = Column("locked", String(255), nullable=True, unique=False, default=None)
613 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
613 _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
614
614
615 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
615 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
616 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
616 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
617
617
618 user = relationship('User')
618 user = relationship('User')
619 fork = relationship('Repository', remote_side=repo_id)
619 fork = relationship('Repository', remote_side=repo_id)
620 group = relationship('RepoGroup')
620 group = relationship('RepoGroup')
621 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
621 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
622 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
622 users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
623 stats = relationship('Statistics', cascade='all', uselist=False)
623 stats = relationship('Statistics', cascade='all', uselist=False)
624
624
625 followers = relationship('UserFollowing',
625 followers = relationship('UserFollowing',
626 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
626 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
627 cascade='all')
627 cascade='all')
628 extra_fields = relationship('RepositoryField',
628 extra_fields = relationship('RepositoryField',
629 cascade="all, delete, delete-orphan")
629 cascade="all, delete, delete-orphan")
630
630
631 logs = relationship('UserLog')
631 logs = relationship('UserLog')
632 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
632 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
633
633
634 pull_requests_org = relationship('PullRequest',
634 pull_requests_org = relationship('PullRequest',
635 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
635 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
636 cascade="all, delete, delete-orphan")
636 cascade="all, delete, delete-orphan")
637
637
638 pull_requests_other = relationship('PullRequest',
638 pull_requests_other = relationship('PullRequest',
639 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
639 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
640 cascade="all, delete, delete-orphan")
640 cascade="all, delete, delete-orphan")
641
641
642 def __unicode__(self):
642 def __unicode__(self):
643 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
643 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
644 safe_unicode(self.repo_name))
644 safe_unicode(self.repo_name))
645
645
646 @classmethod
646 @classmethod
647 def get_by_repo_name(cls, repo_name):
647 def get_by_repo_name(cls, repo_name):
648 q = Session().query(cls).filter(cls.repo_name == repo_name)
648 q = Session().query(cls).filter(cls.repo_name == repo_name)
649 q = q.options(joinedload(Repository.fork))\
649 q = q.options(joinedload(Repository.fork))\
650 .options(joinedload(Repository.user))\
650 .options(joinedload(Repository.user))\
651 .options(joinedload(Repository.group))
651 .options(joinedload(Repository.group))
652 return q.scalar()
652 return q.scalar()
653
653
654
654
655 class RepoGroup(Base, BaseModel):
655 class RepoGroup(Base, BaseModel):
656 __tablename__ = 'groups'
656 __tablename__ = 'groups'
657 __table_args__ = (
657 __table_args__ = (
658 UniqueConstraint('group_name', 'group_parent_id'),
658 UniqueConstraint('group_name', 'group_parent_id'),
659 CheckConstraint('group_id != group_parent_id'),
659 CheckConstraint('group_id != group_parent_id'),
660 {'extend_existing': True, 'mysql_engine': 'InnoDB',
660 {'extend_existing': True, 'mysql_engine': 'InnoDB',
661 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
661 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
662 )
662 )
663 __mapper_args__ = {'order_by': 'group_name'}
663 __mapper_args__ = {'order_by': 'group_name'}
664
664
665 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
665 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
666 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
666 group_name = Column("group_name", String(255), nullable=False, unique=True, default=None)
667 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
667 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
668 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
668 group_description = Column("group_description", String(10000), nullable=True, unique=None, default=None)
669 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
669 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
670 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
670 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
671 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
671 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
672
672
673 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
673 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
674 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
674 users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
675 parent_group = relationship('RepoGroup', remote_side=group_id)
675 parent_group = relationship('RepoGroup', remote_side=group_id)
676 user = relationship('User')
676 user = relationship('User')
677
677
678 def __init__(self, group_name='', parent_group=None):
678 def __init__(self, group_name='', parent_group=None):
679 self.group_name = group_name
679 self.group_name = group_name
680 self.parent_group = parent_group
680 self.parent_group = parent_group
681
681
682 def __unicode__(self):
682 def __unicode__(self):
683 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
683 return u"<%s('id:%s:%s')>" % (self.__class__.__name__, self.group_id,
684 self.group_name)
684 self.group_name)
685
685
686 @classmethod
686 @classmethod
687 def url_sep(cls):
687 def url_sep(cls):
688 return URL_SEP
688 return URL_SEP
689
689
690 @classmethod
690 @classmethod
691 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
691 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
692 if case_insensitive:
692 if case_insensitive:
693 gr = cls.query()\
693 gr = cls.query()\
694 .filter(cls.group_name.ilike(group_name))
694 .filter(cls.group_name.ilike(group_name))
695 else:
695 else:
696 gr = cls.query()\
696 gr = cls.query()\
697 .filter(cls.group_name == group_name)
697 .filter(cls.group_name == group_name)
698 if cache:
698 if cache:
699 gr = gr.options(FromCache(
699 gr = gr.options(FromCache(
700 "sql_cache_short",
700 "sql_cache_short",
701 "get_group_%s" % _hash_key(group_name)
701 "get_group_%s" % _hash_key(group_name)
702 )
702 )
703 )
703 )
704 return gr.scalar()
704 return gr.scalar()
705
705
706
706
707 class Permission(Base, BaseModel):
707 class Permission(Base, BaseModel):
708 __tablename__ = 'permissions'
708 __tablename__ = 'permissions'
709 __table_args__ = (
709 __table_args__ = (
710 Index('p_perm_name_idx', 'permission_name'),
710 Index('p_perm_name_idx', 'permission_name'),
711 {'extend_existing': True, 'mysql_engine': 'InnoDB',
711 {'extend_existing': True, 'mysql_engine': 'InnoDB',
712 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
712 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
713 )
713 )
714 PERMS = [
714 PERMS = [
715 ('hg.admin', _('RhodeCode Administrator')),
715 ('hg.admin', _('RhodeCode Administrator')),
716
716
717 ('repository.none', _('Repository no access')),
717 ('repository.none', _('Repository no access')),
718 ('repository.read', _('Repository read access')),
718 ('repository.read', _('Repository read access')),
719 ('repository.write', _('Repository write access')),
719 ('repository.write', _('Repository write access')),
720 ('repository.admin', _('Repository admin access')),
720 ('repository.admin', _('Repository admin access')),
721
721
722 ('group.none', _('Repository group no access')),
722 ('group.none', _('Repository group no access')),
723 ('group.read', _('Repository group read access')),
723 ('group.read', _('Repository group read access')),
724 ('group.write', _('Repository group write access')),
724 ('group.write', _('Repository group write access')),
725 ('group.admin', _('Repository group admin access')),
725 ('group.admin', _('Repository group admin access')),
726
726
727 ('usergroup.none', _('User group no access')),
727 ('usergroup.none', _('User group no access')),
728 ('usergroup.read', _('User group read access')),
728 ('usergroup.read', _('User group read access')),
729 ('usergroup.write', _('User group write access')),
729 ('usergroup.write', _('User group write access')),
730 ('usergroup.admin', _('User group admin access')),
730 ('usergroup.admin', _('User group admin access')),
731
731
732 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
732 ('hg.repogroup.create.false', _('Repository Group creation disabled')),
733 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
733 ('hg.repogroup.create.true', _('Repository Group creation enabled')),
734
734
735 ('hg.usergroup.create.false', _('User Group creation disabled')),
735 ('hg.usergroup.create.false', _('User Group creation disabled')),
736 ('hg.usergroup.create.true', _('User Group creation enabled')),
736 ('hg.usergroup.create.true', _('User Group creation enabled')),
737
737
738 ('hg.create.none', _('Repository creation disabled')),
738 ('hg.create.none', _('Repository creation disabled')),
739 ('hg.create.repository', _('Repository creation enabled')),
739 ('hg.create.repository', _('Repository creation enabled')),
740
740
741 ('hg.fork.none', _('Repository forking disabled')),
741 ('hg.fork.none', _('Repository forking disabled')),
742 ('hg.fork.repository', _('Repository forking enabled')),
742 ('hg.fork.repository', _('Repository forking enabled')),
743
743
744 ('hg.register.none', _('Registration disabled')),
744 ('hg.register.none', _('Registration disabled')),
745 ('hg.register.manual_activate', _('User Registration with manual account activation')),
745 ('hg.register.manual_activate', _('User Registration with manual account activation')),
746 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
746 ('hg.register.auto_activate', _('User Registration with automatic account activation')),
747
747
748 ('hg.extern_activate.manual', _('Manual activation of external account')),
748 ('hg.extern_activate.manual', _('Manual activation of external account')),
749 ('hg.extern_activate.auto', _('Automatic activation of external account')),
749 ('hg.extern_activate.auto', _('Automatic activation of external account')),
750
750
751 ]
751 ]
752
752
753 #definition of system default permissions for DEFAULT user
753 #definition of system default permissions for DEFAULT user
754 DEFAULT_USER_PERMISSIONS = [
754 DEFAULT_USER_PERMISSIONS = [
755 'repository.read',
755 'repository.read',
756 'group.read',
756 'group.read',
757 'usergroup.read',
757 'usergroup.read',
758 'hg.create.repository',
758 'hg.create.repository',
759 'hg.fork.repository',
759 'hg.fork.repository',
760 'hg.register.manual_activate',
760 'hg.register.manual_activate',
761 'hg.extern_activate.auto',
761 'hg.extern_activate.auto',
762 ]
762 ]
763
763
764 # defines which permissions are more important higher the more important
764 # defines which permissions are more important higher the more important
765 # Weight defines which permissions are more important.
765 # Weight defines which permissions are more important.
766 # The higher number the more important.
766 # The higher number the more important.
767 PERM_WEIGHTS = {
767 PERM_WEIGHTS = {
768 'repository.none': 0,
768 'repository.none': 0,
769 'repository.read': 1,
769 'repository.read': 1,
770 'repository.write': 3,
770 'repository.write': 3,
771 'repository.admin': 4,
771 'repository.admin': 4,
772
772
773 'group.none': 0,
773 'group.none': 0,
774 'group.read': 1,
774 'group.read': 1,
775 'group.write': 3,
775 'group.write': 3,
776 'group.admin': 4,
776 'group.admin': 4,
777
777
778 'usergroup.none': 0,
778 'usergroup.none': 0,
779 'usergroup.read': 1,
779 'usergroup.read': 1,
780 'usergroup.write': 3,
780 'usergroup.write': 3,
781 'usergroup.admin': 4,
781 'usergroup.admin': 4,
782 'hg.repogroup.create.false': 0,
782 'hg.repogroup.create.false': 0,
783 'hg.repogroup.create.true': 1,
783 'hg.repogroup.create.true': 1,
784
784
785 'hg.usergroup.create.false': 0,
785 'hg.usergroup.create.false': 0,
786 'hg.usergroup.create.true': 1,
786 'hg.usergroup.create.true': 1,
787
787
788 'hg.fork.none': 0,
788 'hg.fork.none': 0,
789 'hg.fork.repository': 1,
789 'hg.fork.repository': 1,
790 'hg.create.none': 0,
790 'hg.create.none': 0,
791 'hg.create.repository': 1
791 'hg.create.repository': 1
792 }
792 }
793
793
794 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
794 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
795 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
795 permission_name = Column("permission_name", String(255), nullable=True, unique=None, default=None)
796 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
796 permission_longname = Column("permission_longname", String(255), nullable=True, unique=None, default=None)
797
797
798 def __unicode__(self):
798 def __unicode__(self):
799 return u"<%s('%s:%s')>" % (
799 return u"<%s('%s:%s')>" % (
800 self.__class__.__name__, self.permission_id, self.permission_name
800 self.__class__.__name__, self.permission_id, self.permission_name
801 )
801 )
802
802
803 @classmethod
803 @classmethod
804 def get_by_key(cls, key):
804 def get_by_key(cls, key):
805 return cls.query().filter(cls.permission_name == key).scalar()
805 return cls.query().filter(cls.permission_name == key).scalar()
806
806
807
807
808 class UserRepoToPerm(Base, BaseModel):
808 class UserRepoToPerm(Base, BaseModel):
809 __tablename__ = 'repo_to_perm'
809 __tablename__ = 'repo_to_perm'
810 __table_args__ = (
810 __table_args__ = (
811 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
811 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
812 {'extend_existing': True, 'mysql_engine': 'InnoDB',
812 {'extend_existing': True, 'mysql_engine': 'InnoDB',
813 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
813 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
814 )
814 )
815 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
815 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
816 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
816 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
817 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
817 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
818 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
818 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
819
819
820 user = relationship('User')
820 user = relationship('User')
821 repository = relationship('Repository')
821 repository = relationship('Repository')
822 permission = relationship('Permission')
822 permission = relationship('Permission')
823
823
824 def __unicode__(self):
824 def __unicode__(self):
825 return u'<%s => %s >' % (self.user, self.repository)
825 return u'<%s => %s >' % (self.user, self.repository)
826
826
827
827
828 class UserUserGroupToPerm(Base, BaseModel):
828 class UserUserGroupToPerm(Base, BaseModel):
829 __tablename__ = 'user_user_group_to_perm'
829 __tablename__ = 'user_user_group_to_perm'
830 __table_args__ = (
830 __table_args__ = (
831 UniqueConstraint('user_id', 'user_group_id', 'permission_id'),
831 UniqueConstraint('user_id', 'user_group_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 user_user_group_to_perm_id = Column("user_user_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
835 user_user_group_to_perm_id = Column("user_user_group_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 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
838 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
839
839
840 user = relationship('User')
840 user = relationship('User')
841 user_group = relationship('UserGroup')
841 user_group = relationship('UserGroup')
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.user_group)
845 return u'<%s => %s >' % (self.user, self.user_group)
846
846
847
847
848 class UserToPerm(Base, BaseModel):
848 class UserToPerm(Base, BaseModel):
849 __tablename__ = 'user_to_perm'
849 __tablename__ = 'user_to_perm'
850 __table_args__ = (
850 __table_args__ = (
851 UniqueConstraint('user_id', 'permission_id'),
851 UniqueConstraint('user_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_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
855 user_to_perm_id = Column("user_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
858
859 user = relationship('User')
859 user = relationship('User')
860 permission = relationship('Permission', lazy='joined')
860 permission = relationship('Permission', lazy='joined')
861
861
862 def __unicode__(self):
862 def __unicode__(self):
863 return u'<%s => %s >' % (self.user, self.permission)
863 return u'<%s => %s >' % (self.user, self.permission)
864
864
865
865
866 class UserGroupRepoToPerm(Base, BaseModel):
866 class UserGroupRepoToPerm(Base, BaseModel):
867 __tablename__ = 'users_group_repo_to_perm'
867 __tablename__ = 'users_group_repo_to_perm'
868 __table_args__ = (
868 __table_args__ = (
869 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
869 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
870 {'extend_existing': True, 'mysql_engine': 'InnoDB',
870 {'extend_existing': True, 'mysql_engine': 'InnoDB',
871 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
871 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
872 )
872 )
873 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
873 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
874 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
874 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
875 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
875 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
876 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
876 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
877
877
878 users_group = relationship('UserGroup')
878 users_group = relationship('UserGroup')
879 permission = relationship('Permission')
879 permission = relationship('Permission')
880 repository = relationship('Repository')
880 repository = relationship('Repository')
881
881
882 def __unicode__(self):
882 def __unicode__(self):
883 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
883 return u'<UserGroupRepoToPerm:%s => %s >' % (self.users_group, self.repository)
884
884
885
885
886 class UserGroupUserGroupToPerm(Base, BaseModel):
886 class UserGroupUserGroupToPerm(Base, BaseModel):
887 __tablename__ = 'user_group_user_group_to_perm'
887 __tablename__ = 'user_group_user_group_to_perm'
888 __table_args__ = (
888 __table_args__ = (
889 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
889 UniqueConstraint('target_user_group_id', 'user_group_id', 'permission_id'),
890 CheckConstraint('target_user_group_id != user_group_id'),
890 CheckConstraint('target_user_group_id != user_group_id'),
891 {'extend_existing': True, 'mysql_engine': 'InnoDB',
891 {'extend_existing': True, 'mysql_engine': 'InnoDB',
892 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
892 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
893 )
893 )
894 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)
894 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)
895 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
895 target_user_group_id = Column("target_user_group_id", Integer(), ForeignKey('users_groups.users_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 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
897 user_group_id = Column("user_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
898
898
899 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
899 target_user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.target_user_group_id==UserGroup.users_group_id')
900 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
900 user_group = relationship('UserGroup', primaryjoin='UserGroupUserGroupToPerm.user_group_id==UserGroup.users_group_id')
901 permission = relationship('Permission')
901 permission = relationship('Permission')
902
902
903 def __unicode__(self):
903 def __unicode__(self):
904 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
904 return u'<UserGroupUserGroup:%s => %s >' % (self.target_user_group, self.user_group)
905
905
906
906
907 class UserGroupToPerm(Base, BaseModel):
907 class UserGroupToPerm(Base, BaseModel):
908 __tablename__ = 'users_group_to_perm'
908 __tablename__ = 'users_group_to_perm'
909 __table_args__ = (
909 __table_args__ = (
910 UniqueConstraint('users_group_id', 'permission_id',),
910 UniqueConstraint('users_group_id', 'permission_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 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
914 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
915 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
915 users_group_id = Column("users_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
917
918 users_group = relationship('UserGroup')
918 users_group = relationship('UserGroup')
919 permission = relationship('Permission')
919 permission = relationship('Permission')
920
920
921
921
922 class UserRepoGroupToPerm(Base, BaseModel):
922 class UserRepoGroupToPerm(Base, BaseModel):
923 __tablename__ = 'user_repo_group_to_perm'
923 __tablename__ = 'user_repo_group_to_perm'
924 __table_args__ = (
924 __table_args__ = (
925 UniqueConstraint('user_id', 'group_id', 'permission_id'),
925 UniqueConstraint('user_id', 'group_id', 'permission_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
929
930 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
930 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
931 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
931 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
932 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
932 group_id = Column("group_id", Integer(), ForeignKey('groups.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 user = relationship('User')
935 user = relationship('User')
936 group = relationship('RepoGroup')
936 group = relationship('RepoGroup')
937 permission = relationship('Permission')
937 permission = relationship('Permission')
938
938
939
939
940 class UserGroupRepoGroupToPerm(Base, BaseModel):
940 class UserGroupRepoGroupToPerm(Base, BaseModel):
941 __tablename__ = 'users_group_repo_group_to_perm'
941 __tablename__ = 'users_group_repo_group_to_perm'
942 __table_args__ = (
942 __table_args__ = (
943 UniqueConstraint('users_group_id', 'group_id'),
943 UniqueConstraint('users_group_id', 'group_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 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)
948 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)
949 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
949 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
950 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
950 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
951 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
951 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
952
952
953 users_group = relationship('UserGroup')
953 users_group = relationship('UserGroup')
954 permission = relationship('Permission')
954 permission = relationship('Permission')
955 group = relationship('RepoGroup')
955 group = relationship('RepoGroup')
956
956
957
957
958 class Statistics(Base, BaseModel):
958 class Statistics(Base, BaseModel):
959 __tablename__ = 'statistics'
959 __tablename__ = 'statistics'
960 __table_args__ = (
960 __table_args__ = (
961 UniqueConstraint('repository_id'),
961 UniqueConstraint('repository_id'),
962 {'extend_existing': True, 'mysql_engine': 'InnoDB',
962 {'extend_existing': True, 'mysql_engine': 'InnoDB',
963 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
963 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
964 )
964 )
965 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
965 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
966 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
966 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
967 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
967 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
968 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
968 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
969 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
969 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
970 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
970 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
971
971
972 repository = relationship('Repository', single_parent=True)
972 repository = relationship('Repository', single_parent=True)
973
973
974
974
975 class UserFollowing(Base, BaseModel):
975 class UserFollowing(Base, BaseModel):
976 __tablename__ = 'user_followings'
976 __tablename__ = 'user_followings'
977 __table_args__ = (
977 __table_args__ = (
978 UniqueConstraint('user_id', 'follows_repository_id'),
978 UniqueConstraint('user_id', 'follows_repository_id'),
979 UniqueConstraint('user_id', 'follows_user_id'),
979 UniqueConstraint('user_id', 'follows_user_id'),
980 {'extend_existing': True, 'mysql_engine': 'InnoDB',
980 {'extend_existing': True, 'mysql_engine': 'InnoDB',
981 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
981 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
982 )
982 )
983
983
984 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
984 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
985 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
985 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
986 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
986 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
987 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
987 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
988 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
988 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
989
989
990 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
990 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
991
991
992 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
992 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
993 follows_repository = relationship('Repository', order_by='Repository.repo_name')
993 follows_repository = relationship('Repository', order_by='Repository.repo_name')
994
994
995
995
996 class CacheInvalidation(Base, BaseModel):
996 class CacheInvalidation(Base, BaseModel):
997 __tablename__ = 'cache_invalidation'
997 __tablename__ = 'cache_invalidation'
998 __table_args__ = (
998 __table_args__ = (
999 UniqueConstraint('cache_key'),
999 UniqueConstraint('cache_key'),
1000 Index('key_idx', 'cache_key'),
1000 Index('key_idx', 'cache_key'),
1001 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1001 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1002 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1002 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1003 )
1003 )
1004 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1004 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1005 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1005 cache_key = Column("cache_key", String(255), nullable=True, unique=None, default=None)
1006 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1006 cache_args = Column("cache_args", String(255), nullable=True, unique=None, default=None)
1007 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1007 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1008
1008
1009 def __init__(self, cache_key, cache_args=''):
1009 def __init__(self, cache_key, cache_args=''):
1010 self.cache_key = cache_key
1010 self.cache_key = cache_key
1011 self.cache_args = cache_args
1011 self.cache_args = cache_args
1012 self.cache_active = False
1012 self.cache_active = False
1013
1013
1014
1014
1015 class ChangesetComment(Base, BaseModel):
1015 class ChangesetComment(Base, BaseModel):
1016 __tablename__ = 'changeset_comments'
1016 __tablename__ = 'changeset_comments'
1017 __table_args__ = (
1017 __table_args__ = (
1018 Index('cc_revision_idx', 'revision'),
1018 Index('cc_revision_idx', 'revision'),
1019 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1019 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1020 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1020 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1021 )
1021 )
1022 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1022 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1023 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1023 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1024 revision = Column('revision', String(40), nullable=True)
1024 revision = Column('revision', String(40), nullable=True)
1025 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1025 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1026 line_no = Column('line_no', Unicode(10), nullable=True)
1026 line_no = Column('line_no', Unicode(10), nullable=True)
1027 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1027 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1028 f_path = Column('f_path', Unicode(1000), nullable=True)
1028 f_path = Column('f_path', Unicode(1000), nullable=True)
1029 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1029 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1030 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
1030 text = Column('text', UnicodeText().with_variant(UnicodeText(25000), 'mysql'), nullable=False)
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 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1032 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1033
1033
1034 author = relationship('User', lazy='joined')
1034 author = relationship('User', lazy='joined')
1035 repo = relationship('Repository')
1035 repo = relationship('Repository')
1036 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1036 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1037 pull_request = relationship('PullRequest', lazy='joined')
1037 pull_request = relationship('PullRequest', lazy='joined')
1038
1038
1039
1039
1040 class ChangesetStatus(Base, BaseModel):
1040 class ChangesetStatus(Base, BaseModel):
1041 __tablename__ = 'changeset_statuses'
1041 __tablename__ = 'changeset_statuses'
1042 __table_args__ = (
1042 __table_args__ = (
1043 Index('cs_revision_idx', 'revision'),
1043 Index('cs_revision_idx', 'revision'),
1044 Index('cs_version_idx', 'version'),
1044 Index('cs_version_idx', 'version'),
1045 UniqueConstraint('repo_id', 'revision', 'version'),
1045 UniqueConstraint('repo_id', 'revision', 'version'),
1046 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1046 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1047 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1047 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1048 )
1048 )
1049 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1049 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1050 STATUS_APPROVED = 'approved'
1050 STATUS_APPROVED = 'approved'
1051 STATUS_REJECTED = 'rejected'
1051 STATUS_REJECTED = 'rejected'
1052 STATUS_UNDER_REVIEW = 'under_review'
1052 STATUS_UNDER_REVIEW = 'under_review'
1053
1053
1054 STATUSES = [
1054 STATUSES = [
1055 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1055 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1056 (STATUS_APPROVED, _("Approved")),
1056 (STATUS_APPROVED, _("Approved")),
1057 (STATUS_REJECTED, _("Rejected")),
1057 (STATUS_REJECTED, _("Rejected")),
1058 (STATUS_UNDER_REVIEW, _("Under Review")),
1058 (STATUS_UNDER_REVIEW, _("Under Review")),
1059 ]
1059 ]
1060
1060
1061 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1061 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1062 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1062 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1063 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1063 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1064 revision = Column('revision', String(40), nullable=False)
1064 revision = Column('revision', String(40), nullable=False)
1065 status = Column('status', String(128), nullable=False, default=DEFAULT)
1065 status = Column('status', String(128), nullable=False, default=DEFAULT)
1066 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1066 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1067 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1067 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1068 version = Column('version', Integer(), nullable=False, default=0)
1068 version = Column('version', Integer(), nullable=False, default=0)
1069 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1069 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1070
1070
1071 author = relationship('User', lazy='joined')
1071 author = relationship('User', lazy='joined')
1072 repo = relationship('Repository')
1072 repo = relationship('Repository')
1073 comment = relationship('ChangesetComment', lazy='joined')
1073 comment = relationship('ChangesetComment', lazy='joined')
1074 pull_request = relationship('PullRequest', lazy='joined')
1074 pull_request = relationship('PullRequest', lazy='joined')
1075
1075
1076
1076
1077
1077
1078 class PullRequest(Base, BaseModel):
1078 class PullRequest(Base, BaseModel):
1079 __tablename__ = 'pull_requests'
1079 __tablename__ = 'pull_requests'
1080 __table_args__ = (
1080 __table_args__ = (
1081 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1081 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1082 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1082 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1083 )
1083 )
1084
1084
1085 STATUS_NEW = u'new'
1085 STATUS_NEW = u'new'
1086 STATUS_OPEN = u'open'
1086 STATUS_OPEN = u'open'
1087 STATUS_CLOSED = u'closed'
1087 STATUS_CLOSED = u'closed'
1088
1088
1089 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1089 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1090 title = Column('title', Unicode(256), nullable=True)
1090 title = Column('title', Unicode(256), nullable=True)
1091 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1091 description = Column('description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), nullable=True)
1092 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1092 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1093 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1093 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1094 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1094 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1095 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1095 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1096 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1096 _revisions = Column('revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql'))
1097 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1097 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1098 org_ref = Column('org_ref', Unicode(256), nullable=False)
1098 org_ref = Column('org_ref', Unicode(256), nullable=False)
1099 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1099 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1100 other_ref = Column('other_ref', Unicode(256), nullable=False)
1100 other_ref = Column('other_ref', Unicode(256), nullable=False)
1101
1101
1102 author = relationship('User', lazy='joined')
1102 author = relationship('User', lazy='joined')
1103 reviewers = relationship('PullRequestReviewers',
1103 reviewers = relationship('PullRequestReviewers',
1104 cascade="all, delete, delete-orphan")
1104 cascade="all, delete, delete-orphan")
1105 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1105 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1106 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1106 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1107 statuses = relationship('ChangesetStatus')
1107 statuses = relationship('ChangesetStatus')
1108 comments = relationship('ChangesetComment',
1108 comments = relationship('ChangesetComment',
1109 cascade="all, delete, delete-orphan")
1109 cascade="all, delete, delete-orphan")
1110
1110
1111
1111
1112 class PullRequestReviewers(Base, BaseModel):
1112 class PullRequestReviewers(Base, BaseModel):
1113 __tablename__ = 'pull_request_reviewers'
1113 __tablename__ = 'pull_request_reviewers'
1114 __table_args__ = (
1114 __table_args__ = (
1115 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1115 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1116 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1116 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1117 )
1117 )
1118
1118
1119 def __init__(self, user=None, pull_request=None):
1119 def __init__(self, user=None, pull_request=None):
1120 self.user = user
1120 self.user = user
1121 self.pull_request = pull_request
1121 self.pull_request = pull_request
1122
1122
1123 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1123 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1124 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1124 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1125 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1125 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1126
1126
1127 user = relationship('User')
1127 user = relationship('User')
1128 pull_request = relationship('PullRequest')
1128 pull_request = relationship('PullRequest')
1129
1129
1130
1130
1131 class Notification(Base, BaseModel):
1131 class Notification(Base, BaseModel):
1132 __tablename__ = 'notifications'
1132 __tablename__ = 'notifications'
1133 __table_args__ = (
1133 __table_args__ = (
1134 Index('notification_type_idx', 'type'),
1134 Index('notification_type_idx', 'type'),
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 TYPE_CHANGESET_COMMENT = u'cs_comment'
1139 TYPE_CHANGESET_COMMENT = u'cs_comment'
1140 TYPE_MESSAGE = u'message'
1140 TYPE_MESSAGE = u'message'
1141 TYPE_MENTION = u'mention'
1141 TYPE_MENTION = u'mention'
1142 TYPE_REGISTRATION = u'registration'
1142 TYPE_REGISTRATION = u'registration'
1143 TYPE_PULL_REQUEST = u'pull_request'
1143 TYPE_PULL_REQUEST = u'pull_request'
1144 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1144 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1145
1145
1146 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1146 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1147 subject = Column('subject', Unicode(512), nullable=True)
1147 subject = Column('subject', Unicode(512), nullable=True)
1148 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1148 body = Column('body', UnicodeText().with_variant(UnicodeText(50000), 'mysql'), nullable=True)
1149 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1149 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1150 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1150 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1151 type_ = Column('type', Unicode(256))
1151 type_ = Column('type', Unicode(256))
1152
1152
1153 created_by_user = relationship('User')
1153 created_by_user = relationship('User')
1154 notifications_to_users = relationship('UserNotification', lazy='joined',
1154 notifications_to_users = relationship('UserNotification', lazy='joined',
1155 cascade="all, delete, delete-orphan")
1155 cascade="all, delete, delete-orphan")
1156
1156
1157
1157
1158 class UserNotification(Base, BaseModel):
1158 class UserNotification(Base, BaseModel):
1159 __tablename__ = 'user_to_notification'
1159 __tablename__ = 'user_to_notification'
1160 __table_args__ = (
1160 __table_args__ = (
1161 UniqueConstraint('user_id', 'notification_id'),
1161 UniqueConstraint('user_id', 'notification_id'),
1162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1163 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1163 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1164 )
1164 )
1165 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1165 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1166 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1166 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1167 read = Column('read', Boolean, default=False)
1167 read = Column('read', Boolean, default=False)
1168 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1168 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1169
1169
1170 user = relationship('User', lazy="joined")
1170 user = relationship('User', lazy="joined")
1171 notification = relationship('Notification', lazy="joined",
1171 notification = relationship('Notification', lazy="joined",
1172 order_by=lambda: Notification.created_on.desc(),)
1172 order_by=lambda: Notification.created_on.desc(),)
1173
1173
1174
1174
1175 class Gist(Base, BaseModel):
1175 class Gist(Base, BaseModel):
1176 __tablename__ = 'gists'
1176 __tablename__ = 'gists'
1177 __table_args__ = (
1177 __table_args__ = (
1178 Index('g_gist_access_id_idx', 'gist_access_id'),
1178 Index('g_gist_access_id_idx', 'gist_access_id'),
1179 Index('g_created_on_idx', 'created_on'),
1179 Index('g_created_on_idx', 'created_on'),
1180 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1180 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1181 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1181 'mysql_charset': 'utf8', 'sqlite_autoincrement': True}
1182 )
1182 )
1183 GIST_PUBLIC = u'public'
1183 GIST_PUBLIC = u'public'
1184 GIST_PRIVATE = u'private'
1184 GIST_PRIVATE = u'private'
1185
1185
1186 gist_id = Column('gist_id', Integer(), primary_key=True)
1186 gist_id = Column('gist_id', Integer(), primary_key=True)
1187 gist_access_id = Column('gist_access_id', Unicode(250))
1187 gist_access_id = Column('gist_access_id', Unicode(250))
1188 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1188 gist_description = Column('gist_description', UnicodeText().with_variant(UnicodeText(1024), 'mysql'))
1189 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1189 gist_owner = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=True)
1190 gist_expires = Column('gist_expires', Float(53), nullable=False)
1190 gist_expires = Column('gist_expires', Float(53), nullable=False)
1191 gist_type = Column('gist_type', Unicode(128), nullable=False)
1191 gist_type = Column('gist_type', Unicode(128), nullable=False)
1192 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1192 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1193 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1193 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1194
1194
1195 owner = relationship('User')
1195 owner = relationship('User')
1196
1196
1197
1197
1198 class DbMigrateVersion(Base, BaseModel):
1198 class DbMigrateVersion(Base, BaseModel):
1199 __tablename__ = 'db_migrate_version'
1199 __tablename__ = 'db_migrate_version'
1200 __table_args__ = (
1200 __table_args__ = (
1201 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1201 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1202 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1202 'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
1203 )
1203 )
1204 repository_id = Column('repository_id', String(250), primary_key=True)
1204 repository_id = Column('repository_id', String(250), primary_key=True)
1205 repository_path = Column('repository_path', Text)
1205 repository_path = Column('repository_path', Text)
1206 version = Column('version', Integer)
1206 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
General Comments 0
You need to be logged in to leave comments. Login now