##// END OF EJS Templates
User active flag should be default to True
marcink -
r2480:cb9e73b2 beta
parent child Browse files
Show More
@@ -1,1549 +1,1549 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.db
3 rhodecode.model.db
4 ~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~
5
5
6 Database Models for RhodeCode
6 Database Models for RhodeCode
7
7
8 :created_on: Apr 08, 2010
8 :created_on: Apr 08, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import datetime
28 import datetime
29 import traceback
29 import traceback
30 import hashlib
30 import hashlib
31 from collections import defaultdict
31 from collections import defaultdict
32
32
33 from sqlalchemy import *
33 from sqlalchemy import *
34 from sqlalchemy.ext.hybrid import hybrid_property
34 from sqlalchemy.ext.hybrid import hybrid_property
35 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
35 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
36 from sqlalchemy.exc import DatabaseError
36 from sqlalchemy.exc import DatabaseError
37 from beaker.cache import cache_region, region_invalidate
37 from beaker.cache import cache_region, region_invalidate
38
38
39 from pylons.i18n.translation import lazy_ugettext as _
39 from pylons.i18n.translation import lazy_ugettext as _
40
40
41 from rhodecode.lib.vcs import get_backend
41 from rhodecode.lib.vcs import get_backend
42 from rhodecode.lib.vcs.utils.helpers import get_scm
42 from rhodecode.lib.vcs.utils.helpers import get_scm
43 from rhodecode.lib.vcs.exceptions import VCSError
43 from rhodecode.lib.vcs.exceptions import VCSError
44 from rhodecode.lib.vcs.utils.lazy import LazyProperty
44 from rhodecode.lib.vcs.utils.lazy import LazyProperty
45
45
46 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
46 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
47 safe_unicode
47 safe_unicode
48 from rhodecode.lib.compat import json
48 from rhodecode.lib.compat import json
49 from rhodecode.lib.caching_query import FromCache
49 from rhodecode.lib.caching_query import FromCache
50
50
51 from rhodecode.model.meta import Base, Session
51 from rhodecode.model.meta import Base, Session
52
52
53
53
54 URL_SEP = '/'
54 URL_SEP = '/'
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57 #==============================================================================
57 #==============================================================================
58 # BASE CLASSES
58 # BASE CLASSES
59 #==============================================================================
59 #==============================================================================
60
60
61 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
61 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
62
62
63
63
64 class ModelSerializer(json.JSONEncoder):
64 class ModelSerializer(json.JSONEncoder):
65 """
65 """
66 Simple Serializer for JSON,
66 Simple Serializer for JSON,
67
67
68 usage::
68 usage::
69
69
70 to make object customized for serialization implement a __json__
70 to make object customized for serialization implement a __json__
71 method that will return a dict for serialization into json
71 method that will return a dict for serialization into json
72
72
73 example::
73 example::
74
74
75 class Task(object):
75 class Task(object):
76
76
77 def __init__(self, name, value):
77 def __init__(self, name, value):
78 self.name = name
78 self.name = name
79 self.value = value
79 self.value = value
80
80
81 def __json__(self):
81 def __json__(self):
82 return dict(name=self.name,
82 return dict(name=self.name,
83 value=self.value)
83 value=self.value)
84
84
85 """
85 """
86
86
87 def default(self, obj):
87 def default(self, obj):
88
88
89 if hasattr(obj, '__json__'):
89 if hasattr(obj, '__json__'):
90 return obj.__json__()
90 return obj.__json__()
91 else:
91 else:
92 return json.JSONEncoder.default(self, obj)
92 return json.JSONEncoder.default(self, obj)
93
93
94
94
95 class BaseModel(object):
95 class BaseModel(object):
96 """
96 """
97 Base Model for all classess
97 Base Model for all classess
98 """
98 """
99
99
100 @classmethod
100 @classmethod
101 def _get_keys(cls):
101 def _get_keys(cls):
102 """return column names for this model """
102 """return column names for this model """
103 return class_mapper(cls).c.keys()
103 return class_mapper(cls).c.keys()
104
104
105 def get_dict(self):
105 def get_dict(self):
106 """
106 """
107 return dict with keys and values corresponding
107 return dict with keys and values corresponding
108 to this model data """
108 to this model data """
109
109
110 d = {}
110 d = {}
111 for k in self._get_keys():
111 for k in self._get_keys():
112 d[k] = getattr(self, k)
112 d[k] = getattr(self, k)
113
113
114 # also use __json__() if present to get additional fields
114 # also use __json__() if present to get additional fields
115 for k, val in getattr(self, '__json__', lambda: {})().iteritems():
115 for k, val in getattr(self, '__json__', lambda: {})().iteritems():
116 d[k] = val
116 d[k] = val
117 return d
117 return d
118
118
119 def get_appstruct(self):
119 def get_appstruct(self):
120 """return list with keys and values tupples corresponding
120 """return list with keys and values tupples corresponding
121 to this model data """
121 to this model data """
122
122
123 l = []
123 l = []
124 for k in self._get_keys():
124 for k in self._get_keys():
125 l.append((k, getattr(self, k),))
125 l.append((k, getattr(self, k),))
126 return l
126 return l
127
127
128 def populate_obj(self, populate_dict):
128 def populate_obj(self, populate_dict):
129 """populate model with data from given populate_dict"""
129 """populate model with data from given populate_dict"""
130
130
131 for k in self._get_keys():
131 for k in self._get_keys():
132 if k in populate_dict:
132 if k in populate_dict:
133 setattr(self, k, populate_dict[k])
133 setattr(self, k, populate_dict[k])
134
134
135 @classmethod
135 @classmethod
136 def query(cls):
136 def query(cls):
137 return Session.query(cls)
137 return Session.query(cls)
138
138
139 @classmethod
139 @classmethod
140 def get(cls, id_):
140 def get(cls, id_):
141 if id_:
141 if id_:
142 return cls.query().get(id_)
142 return cls.query().get(id_)
143
143
144 @classmethod
144 @classmethod
145 def getAll(cls):
145 def getAll(cls):
146 return cls.query().all()
146 return cls.query().all()
147
147
148 @classmethod
148 @classmethod
149 def delete(cls, id_):
149 def delete(cls, id_):
150 obj = cls.query().get(id_)
150 obj = cls.query().get(id_)
151 Session.delete(obj)
151 Session.delete(obj)
152
152
153 def __repr__(self):
153 def __repr__(self):
154 if hasattr(self, '__unicode__'):
154 if hasattr(self, '__unicode__'):
155 # python repr needs to return str
155 # python repr needs to return str
156 return safe_str(self.__unicode__())
156 return safe_str(self.__unicode__())
157 return '<DB:%s>' % (self.__class__.__name__)
157 return '<DB:%s>' % (self.__class__.__name__)
158
158
159
159
160 class RhodeCodeSetting(Base, BaseModel):
160 class RhodeCodeSetting(Base, BaseModel):
161 __tablename__ = 'rhodecode_settings'
161 __tablename__ = 'rhodecode_settings'
162 __table_args__ = (
162 __table_args__ = (
163 UniqueConstraint('app_settings_name'),
163 UniqueConstraint('app_settings_name'),
164 {'extend_existing': True, 'mysql_engine': 'InnoDB',
164 {'extend_existing': True, 'mysql_engine': 'InnoDB',
165 'mysql_charset': 'utf8'}
165 'mysql_charset': 'utf8'}
166 )
166 )
167 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
167 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
168 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
168 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
169 _app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
169 _app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
170
170
171 def __init__(self, k='', v=''):
171 def __init__(self, k='', v=''):
172 self.app_settings_name = k
172 self.app_settings_name = k
173 self.app_settings_value = v
173 self.app_settings_value = v
174
174
175 @validates('_app_settings_value')
175 @validates('_app_settings_value')
176 def validate_settings_value(self, key, val):
176 def validate_settings_value(self, key, val):
177 assert type(val) == unicode
177 assert type(val) == unicode
178 return val
178 return val
179
179
180 @hybrid_property
180 @hybrid_property
181 def app_settings_value(self):
181 def app_settings_value(self):
182 v = self._app_settings_value
182 v = self._app_settings_value
183 if self.app_settings_name == 'ldap_active':
183 if self.app_settings_name == 'ldap_active':
184 v = str2bool(v)
184 v = str2bool(v)
185 return v
185 return v
186
186
187 @app_settings_value.setter
187 @app_settings_value.setter
188 def app_settings_value(self, val):
188 def app_settings_value(self, val):
189 """
189 """
190 Setter that will always make sure we use unicode in app_settings_value
190 Setter that will always make sure we use unicode in app_settings_value
191
191
192 :param val:
192 :param val:
193 """
193 """
194 self._app_settings_value = safe_unicode(val)
194 self._app_settings_value = safe_unicode(val)
195
195
196 def __unicode__(self):
196 def __unicode__(self):
197 return u"<%s('%s:%s')>" % (
197 return u"<%s('%s:%s')>" % (
198 self.__class__.__name__,
198 self.__class__.__name__,
199 self.app_settings_name, self.app_settings_value
199 self.app_settings_name, self.app_settings_value
200 )
200 )
201
201
202 @classmethod
202 @classmethod
203 def get_by_name(cls, ldap_key):
203 def get_by_name(cls, ldap_key):
204 return cls.query()\
204 return cls.query()\
205 .filter(cls.app_settings_name == ldap_key).scalar()
205 .filter(cls.app_settings_name == ldap_key).scalar()
206
206
207 @classmethod
207 @classmethod
208 def get_app_settings(cls, cache=False):
208 def get_app_settings(cls, cache=False):
209
209
210 ret = cls.query()
210 ret = cls.query()
211
211
212 if cache:
212 if cache:
213 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
213 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
214
214
215 if not ret:
215 if not ret:
216 raise Exception('Could not get application settings !')
216 raise Exception('Could not get application settings !')
217 settings = {}
217 settings = {}
218 for each in ret:
218 for each in ret:
219 settings['rhodecode_' + each.app_settings_name] = \
219 settings['rhodecode_' + each.app_settings_name] = \
220 each.app_settings_value
220 each.app_settings_value
221
221
222 return settings
222 return settings
223
223
224 @classmethod
224 @classmethod
225 def get_ldap_settings(cls, cache=False):
225 def get_ldap_settings(cls, cache=False):
226 ret = cls.query()\
226 ret = cls.query()\
227 .filter(cls.app_settings_name.startswith('ldap_')).all()
227 .filter(cls.app_settings_name.startswith('ldap_')).all()
228 fd = {}
228 fd = {}
229 for row in ret:
229 for row in ret:
230 fd.update({row.app_settings_name: row.app_settings_value})
230 fd.update({row.app_settings_name: row.app_settings_value})
231
231
232 return fd
232 return fd
233
233
234
234
235 class RhodeCodeUi(Base, BaseModel):
235 class RhodeCodeUi(Base, BaseModel):
236 __tablename__ = 'rhodecode_ui'
236 __tablename__ = 'rhodecode_ui'
237 __table_args__ = (
237 __table_args__ = (
238 UniqueConstraint('ui_key'),
238 UniqueConstraint('ui_key'),
239 {'extend_existing': True, 'mysql_engine': 'InnoDB',
239 {'extend_existing': True, 'mysql_engine': 'InnoDB',
240 'mysql_charset': 'utf8'}
240 'mysql_charset': 'utf8'}
241 )
241 )
242
242
243 HOOK_UPDATE = 'changegroup.update'
243 HOOK_UPDATE = 'changegroup.update'
244 HOOK_REPO_SIZE = 'changegroup.repo_size'
244 HOOK_REPO_SIZE = 'changegroup.repo_size'
245 HOOK_PUSH = 'changegroup.push_logger'
245 HOOK_PUSH = 'changegroup.push_logger'
246 HOOK_PULL = 'preoutgoing.pull_logger'
246 HOOK_PULL = 'preoutgoing.pull_logger'
247
247
248 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
248 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
249 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
249 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
250 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
250 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
251 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
251 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
252 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
252 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
253
253
254 @classmethod
254 @classmethod
255 def get_by_key(cls, key):
255 def get_by_key(cls, key):
256 return cls.query().filter(cls.ui_key == key)
256 return cls.query().filter(cls.ui_key == key)
257
257
258 @classmethod
258 @classmethod
259 def get_builtin_hooks(cls):
259 def get_builtin_hooks(cls):
260 q = cls.query()
260 q = cls.query()
261 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
261 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
262 cls.HOOK_REPO_SIZE,
262 cls.HOOK_REPO_SIZE,
263 cls.HOOK_PUSH, cls.HOOK_PULL]))
263 cls.HOOK_PUSH, cls.HOOK_PULL]))
264 return q.all()
264 return q.all()
265
265
266 @classmethod
266 @classmethod
267 def get_custom_hooks(cls):
267 def get_custom_hooks(cls):
268 q = cls.query()
268 q = cls.query()
269 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
269 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
270 cls.HOOK_REPO_SIZE,
270 cls.HOOK_REPO_SIZE,
271 cls.HOOK_PUSH, cls.HOOK_PULL]))
271 cls.HOOK_PUSH, cls.HOOK_PULL]))
272 q = q.filter(cls.ui_section == 'hooks')
272 q = q.filter(cls.ui_section == 'hooks')
273 return q.all()
273 return q.all()
274
274
275 @classmethod
275 @classmethod
276 def get_repos_location(cls):
276 def get_repos_location(cls):
277 return cls.get_by_key('/').one().ui_value
277 return cls.get_by_key('/').one().ui_value
278
278
279 @classmethod
279 @classmethod
280 def create_or_update_hook(cls, key, val):
280 def create_or_update_hook(cls, key, val):
281 new_ui = cls.get_by_key(key).scalar() or cls()
281 new_ui = cls.get_by_key(key).scalar() or cls()
282 new_ui.ui_section = 'hooks'
282 new_ui.ui_section = 'hooks'
283 new_ui.ui_active = True
283 new_ui.ui_active = True
284 new_ui.ui_key = key
284 new_ui.ui_key = key
285 new_ui.ui_value = val
285 new_ui.ui_value = val
286
286
287 Session.add(new_ui)
287 Session.add(new_ui)
288
288
289
289
290 class User(Base, BaseModel):
290 class User(Base, BaseModel):
291 __tablename__ = 'users'
291 __tablename__ = 'users'
292 __table_args__ = (
292 __table_args__ = (
293 UniqueConstraint('username'), UniqueConstraint('email'),
293 UniqueConstraint('username'), UniqueConstraint('email'),
294 {'extend_existing': True, 'mysql_engine': 'InnoDB',
294 {'extend_existing': True, 'mysql_engine': 'InnoDB',
295 'mysql_charset': 'utf8'}
295 'mysql_charset': 'utf8'}
296 )
296 )
297 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
297 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
298 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
298 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
299 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
299 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
300 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
300 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
301 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
301 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
302 name = Column("firstname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
302 name = Column("firstname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
303 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
303 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
304 _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
304 _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
305 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
305 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
306 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
306 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
307 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
307 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
308
308
309 user_log = relationship('UserLog', cascade='all')
309 user_log = relationship('UserLog', cascade='all')
310 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
310 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
311
311
312 repositories = relationship('Repository')
312 repositories = relationship('Repository')
313 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
313 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
314 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
314 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
315 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
315 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
316
316
317 group_member = relationship('UsersGroupMember', cascade='all')
317 group_member = relationship('UsersGroupMember', cascade='all')
318
318
319 notifications = relationship('UserNotification', cascade='all')
319 notifications = relationship('UserNotification', cascade='all')
320 # notifications assigned to this user
320 # notifications assigned to this user
321 user_created_notifications = relationship('Notification', cascade='all')
321 user_created_notifications = relationship('Notification', cascade='all')
322 # comments created by this user
322 # comments created by this user
323 user_comments = relationship('ChangesetComment', cascade='all')
323 user_comments = relationship('ChangesetComment', cascade='all')
324
324
325 @hybrid_property
325 @hybrid_property
326 def email(self):
326 def email(self):
327 return self._email
327 return self._email
328
328
329 @email.setter
329 @email.setter
330 def email(self, val):
330 def email(self, val):
331 self._email = val.lower() if val else None
331 self._email = val.lower() if val else None
332
332
333 @property
333 @property
334 def full_name(self):
334 def full_name(self):
335 return '%s %s' % (self.name, self.lastname)
335 return '%s %s' % (self.name, self.lastname)
336
336
337 @property
337 @property
338 def full_name_or_username(self):
338 def full_name_or_username(self):
339 return ('%s %s' % (self.name, self.lastname)
339 return ('%s %s' % (self.name, self.lastname)
340 if (self.name and self.lastname) else self.username)
340 if (self.name and self.lastname) else self.username)
341
341
342 @property
342 @property
343 def full_contact(self):
343 def full_contact(self):
344 return '%s %s <%s>' % (self.name, self.lastname, self.email)
344 return '%s %s <%s>' % (self.name, self.lastname, self.email)
345
345
346 @property
346 @property
347 def short_contact(self):
347 def short_contact(self):
348 return '%s %s' % (self.name, self.lastname)
348 return '%s %s' % (self.name, self.lastname)
349
349
350 @property
350 @property
351 def is_admin(self):
351 def is_admin(self):
352 return self.admin
352 return self.admin
353
353
354 def __unicode__(self):
354 def __unicode__(self):
355 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
355 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
356 self.user_id, self.username)
356 self.user_id, self.username)
357
357
358 @classmethod
358 @classmethod
359 def get_by_username(cls, username, case_insensitive=False, cache=False):
359 def get_by_username(cls, username, case_insensitive=False, cache=False):
360 if case_insensitive:
360 if case_insensitive:
361 q = cls.query().filter(cls.username.ilike(username))
361 q = cls.query().filter(cls.username.ilike(username))
362 else:
362 else:
363 q = cls.query().filter(cls.username == username)
363 q = cls.query().filter(cls.username == username)
364
364
365 if cache:
365 if cache:
366 q = q.options(FromCache(
366 q = q.options(FromCache(
367 "sql_cache_short",
367 "sql_cache_short",
368 "get_user_%s" % _hash_key(username)
368 "get_user_%s" % _hash_key(username)
369 )
369 )
370 )
370 )
371 return q.scalar()
371 return q.scalar()
372
372
373 @classmethod
373 @classmethod
374 def get_by_api_key(cls, api_key, cache=False):
374 def get_by_api_key(cls, api_key, cache=False):
375 q = cls.query().filter(cls.api_key == api_key)
375 q = cls.query().filter(cls.api_key == api_key)
376
376
377 if cache:
377 if cache:
378 q = q.options(FromCache("sql_cache_short",
378 q = q.options(FromCache("sql_cache_short",
379 "get_api_key_%s" % api_key))
379 "get_api_key_%s" % api_key))
380 return q.scalar()
380 return q.scalar()
381
381
382 @classmethod
382 @classmethod
383 def get_by_email(cls, email, case_insensitive=False, cache=False):
383 def get_by_email(cls, email, case_insensitive=False, cache=False):
384 if case_insensitive:
384 if case_insensitive:
385 q = cls.query().filter(cls.email.ilike(email))
385 q = cls.query().filter(cls.email.ilike(email))
386 else:
386 else:
387 q = cls.query().filter(cls.email == email)
387 q = cls.query().filter(cls.email == email)
388
388
389 if cache:
389 if cache:
390 q = q.options(FromCache("sql_cache_short",
390 q = q.options(FromCache("sql_cache_short",
391 "get_email_key_%s" % email))
391 "get_email_key_%s" % email))
392
392
393 ret = q.scalar()
393 ret = q.scalar()
394 if ret is None:
394 if ret is None:
395 q = UserEmailMap.query()
395 q = UserEmailMap.query()
396 # try fetching in alternate email map
396 # try fetching in alternate email map
397 if case_insensitive:
397 if case_insensitive:
398 q = q.filter(UserEmailMap.email.ilike(email))
398 q = q.filter(UserEmailMap.email.ilike(email))
399 else:
399 else:
400 q = q.filter(UserEmailMap.email == email)
400 q = q.filter(UserEmailMap.email == email)
401 q = q.options(joinedload(UserEmailMap.user))
401 q = q.options(joinedload(UserEmailMap.user))
402 if cache:
402 if cache:
403 q = q.options(FromCache("sql_cache_short",
403 q = q.options(FromCache("sql_cache_short",
404 "get_email_map_key_%s" % email))
404 "get_email_map_key_%s" % email))
405 ret = getattr(q.scalar(), 'user', None)
405 ret = getattr(q.scalar(), 'user', None)
406
406
407 return ret
407 return ret
408
408
409 def update_lastlogin(self):
409 def update_lastlogin(self):
410 """Update user lastlogin"""
410 """Update user lastlogin"""
411 self.last_login = datetime.datetime.now()
411 self.last_login = datetime.datetime.now()
412 Session.add(self)
412 Session.add(self)
413 log.debug('updated user %s lastlogin' % self.username)
413 log.debug('updated user %s lastlogin' % self.username)
414
414
415 def __json__(self):
415 def __json__(self):
416 return dict(
416 return dict(
417 user_id=self.user_id,
417 user_id=self.user_id,
418 first_name=self.name,
418 first_name=self.name,
419 last_name=self.lastname,
419 last_name=self.lastname,
420 email=self.email,
420 email=self.email,
421 full_name=self.full_name,
421 full_name=self.full_name,
422 full_name_or_username=self.full_name_or_username,
422 full_name_or_username=self.full_name_or_username,
423 short_contact=self.short_contact,
423 short_contact=self.short_contact,
424 full_contact=self.full_contact
424 full_contact=self.full_contact
425 )
425 )
426
426
427
427
428 class UserEmailMap(Base, BaseModel):
428 class UserEmailMap(Base, BaseModel):
429 __tablename__ = 'user_email_map'
429 __tablename__ = 'user_email_map'
430 __table_args__ = (
430 __table_args__ = (
431 Index('uem_email_idx', 'email'),
431 Index('uem_email_idx', 'email'),
432 UniqueConstraint('email'),
432 UniqueConstraint('email'),
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
433 {'extend_existing': True, 'mysql_engine': 'InnoDB',
434 'mysql_charset': 'utf8'}
434 'mysql_charset': 'utf8'}
435 )
435 )
436 __mapper_args__ = {}
436 __mapper_args__ = {}
437
437
438 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
438 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
439 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
439 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
440 _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
440 _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
441
441
442 user = relationship('User', lazy='joined')
442 user = relationship('User', lazy='joined')
443
443
444 @validates('_email')
444 @validates('_email')
445 def validate_email(self, key, email):
445 def validate_email(self, key, email):
446 # check if this email is not main one
446 # check if this email is not main one
447 main_email = Session.query(User).filter(User.email == email).scalar()
447 main_email = Session.query(User).filter(User.email == email).scalar()
448 if main_email is not None:
448 if main_email is not None:
449 raise AttributeError('email %s is present is user table' % email)
449 raise AttributeError('email %s is present is user table' % email)
450 return email
450 return email
451
451
452 @hybrid_property
452 @hybrid_property
453 def email(self):
453 def email(self):
454 return self._email
454 return self._email
455
455
456 @email.setter
456 @email.setter
457 def email(self, val):
457 def email(self, val):
458 self._email = val.lower() if val else None
458 self._email = val.lower() if val else None
459
459
460
460
461 class UserLog(Base, BaseModel):
461 class UserLog(Base, BaseModel):
462 __tablename__ = 'user_logs'
462 __tablename__ = 'user_logs'
463 __table_args__ = (
463 __table_args__ = (
464 {'extend_existing': True, 'mysql_engine': 'InnoDB',
464 {'extend_existing': True, 'mysql_engine': 'InnoDB',
465 'mysql_charset': 'utf8'},
465 'mysql_charset': 'utf8'},
466 )
466 )
467 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
467 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
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 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
469 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
470 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
470 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
471 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
471 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
472 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
472 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
473 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
473 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
474
474
475 @property
475 @property
476 def action_as_day(self):
476 def action_as_day(self):
477 return datetime.date(*self.action_date.timetuple()[:3])
477 return datetime.date(*self.action_date.timetuple()[:3])
478
478
479 user = relationship('User')
479 user = relationship('User')
480 repository = relationship('Repository', cascade='')
480 repository = relationship('Repository', cascade='')
481
481
482
482
483 class UsersGroup(Base, BaseModel):
483 class UsersGroup(Base, BaseModel):
484 __tablename__ = 'users_groups'
484 __tablename__ = 'users_groups'
485 __table_args__ = (
485 __table_args__ = (
486 {'extend_existing': True, 'mysql_engine': 'InnoDB',
486 {'extend_existing': True, 'mysql_engine': 'InnoDB',
487 'mysql_charset': 'utf8'},
487 'mysql_charset': 'utf8'},
488 )
488 )
489
489
490 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
490 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
491 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
491 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
492 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
492 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
493
493
494 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
494 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
495 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
495 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
496 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
496 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
497
497
498 def __unicode__(self):
498 def __unicode__(self):
499 return u'<userGroup(%s)>' % (self.users_group_name)
499 return u'<userGroup(%s)>' % (self.users_group_name)
500
500
501 @classmethod
501 @classmethod
502 def get_by_group_name(cls, group_name, cache=False,
502 def get_by_group_name(cls, group_name, cache=False,
503 case_insensitive=False):
503 case_insensitive=False):
504 if case_insensitive:
504 if case_insensitive:
505 q = cls.query().filter(cls.users_group_name.ilike(group_name))
505 q = cls.query().filter(cls.users_group_name.ilike(group_name))
506 else:
506 else:
507 q = cls.query().filter(cls.users_group_name == group_name)
507 q = cls.query().filter(cls.users_group_name == group_name)
508 if cache:
508 if cache:
509 q = q.options(FromCache(
509 q = q.options(FromCache(
510 "sql_cache_short",
510 "sql_cache_short",
511 "get_user_%s" % _hash_key(group_name)
511 "get_user_%s" % _hash_key(group_name)
512 )
512 )
513 )
513 )
514 return q.scalar()
514 return q.scalar()
515
515
516 @classmethod
516 @classmethod
517 def get(cls, users_group_id, cache=False):
517 def get(cls, users_group_id, cache=False):
518 users_group = cls.query()
518 users_group = cls.query()
519 if cache:
519 if cache:
520 users_group = users_group.options(FromCache("sql_cache_short",
520 users_group = users_group.options(FromCache("sql_cache_short",
521 "get_users_group_%s" % users_group_id))
521 "get_users_group_%s" % users_group_id))
522 return users_group.get(users_group_id)
522 return users_group.get(users_group_id)
523
523
524
524
525 class UsersGroupMember(Base, BaseModel):
525 class UsersGroupMember(Base, BaseModel):
526 __tablename__ = 'users_groups_members'
526 __tablename__ = 'users_groups_members'
527 __table_args__ = (
527 __table_args__ = (
528 {'extend_existing': True, 'mysql_engine': 'InnoDB',
528 {'extend_existing': True, 'mysql_engine': 'InnoDB',
529 'mysql_charset': 'utf8'},
529 'mysql_charset': 'utf8'},
530 )
530 )
531
531
532 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
532 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
533 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
533 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
534 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
534 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
535
535
536 user = relationship('User', lazy='joined')
536 user = relationship('User', lazy='joined')
537 users_group = relationship('UsersGroup')
537 users_group = relationship('UsersGroup')
538
538
539 def __init__(self, gr_id='', u_id=''):
539 def __init__(self, gr_id='', u_id=''):
540 self.users_group_id = gr_id
540 self.users_group_id = gr_id
541 self.user_id = u_id
541 self.user_id = u_id
542
542
543
543
544 class Repository(Base, BaseModel):
544 class Repository(Base, BaseModel):
545 __tablename__ = 'repositories'
545 __tablename__ = 'repositories'
546 __table_args__ = (
546 __table_args__ = (
547 UniqueConstraint('repo_name'),
547 UniqueConstraint('repo_name'),
548 {'extend_existing': True, 'mysql_engine': 'InnoDB',
548 {'extend_existing': True, 'mysql_engine': 'InnoDB',
549 'mysql_charset': 'utf8'},
549 'mysql_charset': 'utf8'},
550 )
550 )
551
551
552 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
552 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
553 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
553 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
554 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
554 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
555 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
555 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
556 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
556 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
557 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
557 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
558 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
558 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
559 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
559 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
560 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
560 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
561 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
561 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
562 landing_rev = Column("landing_revision", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
562 landing_rev = Column("landing_revision", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
563
563
564 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
564 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
565 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
565 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
566
566
567 user = relationship('User')
567 user = relationship('User')
568 fork = relationship('Repository', remote_side=repo_id)
568 fork = relationship('Repository', remote_side=repo_id)
569 group = relationship('RepoGroup')
569 group = relationship('RepoGroup')
570 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
570 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
571 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
571 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
572 stats = relationship('Statistics', cascade='all', uselist=False)
572 stats = relationship('Statistics', cascade='all', uselist=False)
573
573
574 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
574 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
575
575
576 logs = relationship('UserLog')
576 logs = relationship('UserLog')
577 comments = relationship('ChangesetComment')
577 comments = relationship('ChangesetComment')
578
578
579 def __unicode__(self):
579 def __unicode__(self):
580 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
580 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
581 self.repo_name)
581 self.repo_name)
582
582
583 @classmethod
583 @classmethod
584 def url_sep(cls):
584 def url_sep(cls):
585 return URL_SEP
585 return URL_SEP
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 @classmethod
595 @classmethod
596 def get_by_full_path(cls, repo_full_path):
596 def get_by_full_path(cls, repo_full_path):
597 repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
597 repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
598 return cls.get_by_repo_name(repo_name.strip(URL_SEP))
598 return cls.get_by_repo_name(repo_name.strip(URL_SEP))
599
599
600 @classmethod
600 @classmethod
601 def get_repo_forks(cls, repo_id):
601 def get_repo_forks(cls, repo_id):
602 return cls.query().filter(Repository.fork_id == repo_id)
602 return cls.query().filter(Repository.fork_id == repo_id)
603
603
604 @classmethod
604 @classmethod
605 def base_path(cls):
605 def base_path(cls):
606 """
606 """
607 Returns base path when all repos are stored
607 Returns base path when all repos are stored
608
608
609 :param cls:
609 :param cls:
610 """
610 """
611 q = Session.query(RhodeCodeUi)\
611 q = Session.query(RhodeCodeUi)\
612 .filter(RhodeCodeUi.ui_key == cls.url_sep())
612 .filter(RhodeCodeUi.ui_key == cls.url_sep())
613 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
613 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
614 return q.one().ui_value
614 return q.one().ui_value
615
615
616 @property
616 @property
617 def forks(self):
617 def forks(self):
618 """
618 """
619 Return forks of this repo
619 Return forks of this repo
620 """
620 """
621 return Repository.get_repo_forks(self.repo_id)
621 return Repository.get_repo_forks(self.repo_id)
622
622
623 @property
623 @property
624 def parent(self):
624 def parent(self):
625 """
625 """
626 Returns fork parent
626 Returns fork parent
627 """
627 """
628 return self.fork
628 return self.fork
629
629
630 @property
630 @property
631 def just_name(self):
631 def just_name(self):
632 return self.repo_name.split(Repository.url_sep())[-1]
632 return self.repo_name.split(Repository.url_sep())[-1]
633
633
634 @property
634 @property
635 def groups_with_parents(self):
635 def groups_with_parents(self):
636 groups = []
636 groups = []
637 if self.group is None:
637 if self.group is None:
638 return groups
638 return groups
639
639
640 cur_gr = self.group
640 cur_gr = self.group
641 groups.insert(0, cur_gr)
641 groups.insert(0, cur_gr)
642 while 1:
642 while 1:
643 gr = getattr(cur_gr, 'parent_group', None)
643 gr = getattr(cur_gr, 'parent_group', None)
644 cur_gr = cur_gr.parent_group
644 cur_gr = cur_gr.parent_group
645 if gr is None:
645 if gr is None:
646 break
646 break
647 groups.insert(0, gr)
647 groups.insert(0, gr)
648
648
649 return groups
649 return groups
650
650
651 @property
651 @property
652 def groups_and_repo(self):
652 def groups_and_repo(self):
653 return self.groups_with_parents, self.just_name
653 return self.groups_with_parents, self.just_name
654
654
655 @LazyProperty
655 @LazyProperty
656 def repo_path(self):
656 def repo_path(self):
657 """
657 """
658 Returns base full path for that repository means where it actually
658 Returns base full path for that repository means where it actually
659 exists on a filesystem
659 exists on a filesystem
660 """
660 """
661 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
661 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
662 Repository.url_sep())
662 Repository.url_sep())
663 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
663 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
664 return q.one().ui_value
664 return q.one().ui_value
665
665
666 @property
666 @property
667 def repo_full_path(self):
667 def repo_full_path(self):
668 p = [self.repo_path]
668 p = [self.repo_path]
669 # we need to split the name by / since this is how we store the
669 # we need to split the name by / since this is how we store the
670 # names in the database, but that eventually needs to be converted
670 # names in the database, but that eventually needs to be converted
671 # into a valid system path
671 # into a valid system path
672 p += self.repo_name.split(Repository.url_sep())
672 p += self.repo_name.split(Repository.url_sep())
673 return os.path.join(*p)
673 return os.path.join(*p)
674
674
675 def get_new_name(self, repo_name):
675 def get_new_name(self, repo_name):
676 """
676 """
677 returns new full repository name based on assigned group and new new
677 returns new full repository name based on assigned group and new new
678
678
679 :param group_name:
679 :param group_name:
680 """
680 """
681 path_prefix = self.group.full_path_splitted if self.group else []
681 path_prefix = self.group.full_path_splitted if self.group else []
682 return Repository.url_sep().join(path_prefix + [repo_name])
682 return Repository.url_sep().join(path_prefix + [repo_name])
683
683
684 @property
684 @property
685 def _ui(self):
685 def _ui(self):
686 """
686 """
687 Creates an db based ui object for this repository
687 Creates an db based ui object for this repository
688 """
688 """
689 from mercurial import ui
689 from mercurial import ui
690 from mercurial import config
690 from mercurial import config
691 baseui = ui.ui()
691 baseui = ui.ui()
692
692
693 #clean the baseui object
693 #clean the baseui object
694 baseui._ocfg = config.config()
694 baseui._ocfg = config.config()
695 baseui._ucfg = config.config()
695 baseui._ucfg = config.config()
696 baseui._tcfg = config.config()
696 baseui._tcfg = config.config()
697
697
698 ret = RhodeCodeUi.query()\
698 ret = RhodeCodeUi.query()\
699 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
699 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
700
700
701 hg_ui = ret
701 hg_ui = ret
702 for ui_ in hg_ui:
702 for ui_ in hg_ui:
703 if ui_.ui_active:
703 if ui_.ui_active:
704 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
704 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
705 ui_.ui_key, ui_.ui_value)
705 ui_.ui_key, ui_.ui_value)
706 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
706 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
707
707
708 return baseui
708 return baseui
709
709
710 @classmethod
710 @classmethod
711 def is_valid(cls, repo_name):
711 def is_valid(cls, repo_name):
712 """
712 """
713 returns True if given repo name is a valid filesystem repository
713 returns True if given repo name is a valid filesystem repository
714
714
715 :param cls:
715 :param cls:
716 :param repo_name:
716 :param repo_name:
717 """
717 """
718 from rhodecode.lib.utils import is_valid_repo
718 from rhodecode.lib.utils import is_valid_repo
719
719
720 return is_valid_repo(repo_name, cls.base_path())
720 return is_valid_repo(repo_name, cls.base_path())
721
721
722 #==========================================================================
722 #==========================================================================
723 # SCM PROPERTIES
723 # SCM PROPERTIES
724 #==========================================================================
724 #==========================================================================
725
725
726 def get_changeset(self, rev=None):
726 def get_changeset(self, rev=None):
727 return get_changeset_safe(self.scm_instance, rev)
727 return get_changeset_safe(self.scm_instance, rev)
728
728
729 @property
729 @property
730 def tip(self):
730 def tip(self):
731 return self.get_changeset('tip')
731 return self.get_changeset('tip')
732
732
733 @property
733 @property
734 def author(self):
734 def author(self):
735 return self.tip.author
735 return self.tip.author
736
736
737 @property
737 @property
738 def last_change(self):
738 def last_change(self):
739 return self.scm_instance.last_change
739 return self.scm_instance.last_change
740
740
741 def comments(self, revisions=None):
741 def comments(self, revisions=None):
742 """
742 """
743 Returns comments for this repository grouped by revisions
743 Returns comments for this repository grouped by revisions
744
744
745 :param revisions: filter query by revisions only
745 :param revisions: filter query by revisions only
746 """
746 """
747 cmts = ChangesetComment.query()\
747 cmts = ChangesetComment.query()\
748 .filter(ChangesetComment.repo == self)
748 .filter(ChangesetComment.repo == self)
749 if revisions:
749 if revisions:
750 cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
750 cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
751 grouped = defaultdict(list)
751 grouped = defaultdict(list)
752 for cmt in cmts.all():
752 for cmt in cmts.all():
753 grouped[cmt.revision].append(cmt)
753 grouped[cmt.revision].append(cmt)
754 return grouped
754 return grouped
755
755
756 def statuses(self, revisions=None):
756 def statuses(self, revisions=None):
757 """
757 """
758 Returns statuses for this repository
758 Returns statuses for this repository
759
759
760 :param revisions: list of revisions to get statuses for
760 :param revisions: list of revisions to get statuses for
761 :type revisions: list
761 :type revisions: list
762 """
762 """
763
763
764 statuses = ChangesetStatus.query()\
764 statuses = ChangesetStatus.query()\
765 .filter(ChangesetStatus.repo == self)\
765 .filter(ChangesetStatus.repo == self)\
766 .filter(ChangesetStatus.version == 0)
766 .filter(ChangesetStatus.version == 0)
767 if revisions:
767 if revisions:
768 statuses = statuses.filter(ChangesetStatus.revision.in_(revisions))
768 statuses = statuses.filter(ChangesetStatus.revision.in_(revisions))
769 grouped = {}
769 grouped = {}
770 for stat in statuses.all():
770 for stat in statuses.all():
771 pr_id = pr_repo = None
771 pr_id = pr_repo = None
772 if stat.pull_request:
772 if stat.pull_request:
773 pr_id = stat.pull_request.pull_request_id
773 pr_id = stat.pull_request.pull_request_id
774 pr_repo = stat.pull_request.other_repo.repo_name
774 pr_repo = stat.pull_request.other_repo.repo_name
775 grouped[stat.revision] = [str(stat.status), stat.status_lbl,
775 grouped[stat.revision] = [str(stat.status), stat.status_lbl,
776 pr_id, pr_repo]
776 pr_id, pr_repo]
777 return grouped
777 return grouped
778
778
779 #==========================================================================
779 #==========================================================================
780 # SCM CACHE INSTANCE
780 # SCM CACHE INSTANCE
781 #==========================================================================
781 #==========================================================================
782
782
783 @property
783 @property
784 def invalidate(self):
784 def invalidate(self):
785 return CacheInvalidation.invalidate(self.repo_name)
785 return CacheInvalidation.invalidate(self.repo_name)
786
786
787 def set_invalidate(self):
787 def set_invalidate(self):
788 """
788 """
789 set a cache for invalidation for this instance
789 set a cache for invalidation for this instance
790 """
790 """
791 CacheInvalidation.set_invalidate(self.repo_name)
791 CacheInvalidation.set_invalidate(self.repo_name)
792
792
793 @LazyProperty
793 @LazyProperty
794 def scm_instance(self):
794 def scm_instance(self):
795 return self.__get_instance()
795 return self.__get_instance()
796
796
797 def scm_instance_cached(self, cache_map=None):
797 def scm_instance_cached(self, cache_map=None):
798 @cache_region('long_term')
798 @cache_region('long_term')
799 def _c(repo_name):
799 def _c(repo_name):
800 return self.__get_instance()
800 return self.__get_instance()
801 rn = self.repo_name
801 rn = self.repo_name
802 log.debug('Getting cached instance of repo')
802 log.debug('Getting cached instance of repo')
803
803
804 if cache_map:
804 if cache_map:
805 # get using prefilled cache_map
805 # get using prefilled cache_map
806 invalidate_repo = cache_map[self.repo_name]
806 invalidate_repo = cache_map[self.repo_name]
807 if invalidate_repo:
807 if invalidate_repo:
808 invalidate_repo = (None if invalidate_repo.cache_active
808 invalidate_repo = (None if invalidate_repo.cache_active
809 else invalidate_repo)
809 else invalidate_repo)
810 else:
810 else:
811 # get from invalidate
811 # get from invalidate
812 invalidate_repo = self.invalidate
812 invalidate_repo = self.invalidate
813
813
814 if invalidate_repo is not None:
814 if invalidate_repo is not None:
815 region_invalidate(_c, None, rn)
815 region_invalidate(_c, None, rn)
816 # update our cache
816 # update our cache
817 CacheInvalidation.set_valid(invalidate_repo.cache_key)
817 CacheInvalidation.set_valid(invalidate_repo.cache_key)
818 return _c(rn)
818 return _c(rn)
819
819
820 def __get_instance(self):
820 def __get_instance(self):
821 repo_full_path = self.repo_full_path
821 repo_full_path = self.repo_full_path
822 try:
822 try:
823 alias = get_scm(repo_full_path)[0]
823 alias = get_scm(repo_full_path)[0]
824 log.debug('Creating instance of %s repository' % alias)
824 log.debug('Creating instance of %s repository' % alias)
825 backend = get_backend(alias)
825 backend = get_backend(alias)
826 except VCSError:
826 except VCSError:
827 log.error(traceback.format_exc())
827 log.error(traceback.format_exc())
828 log.error('Perhaps this repository is in db and not in '
828 log.error('Perhaps this repository is in db and not in '
829 'filesystem run rescan repositories with '
829 'filesystem run rescan repositories with '
830 '"destroy old data " option from admin panel')
830 '"destroy old data " option from admin panel')
831 return
831 return
832
832
833 if alias == 'hg':
833 if alias == 'hg':
834
834
835 repo = backend(safe_str(repo_full_path), create=False,
835 repo = backend(safe_str(repo_full_path), create=False,
836 baseui=self._ui)
836 baseui=self._ui)
837 # skip hidden web repository
837 # skip hidden web repository
838 if repo._get_hidden():
838 if repo._get_hidden():
839 return
839 return
840 else:
840 else:
841 repo = backend(repo_full_path, create=False)
841 repo = backend(repo_full_path, create=False)
842
842
843 return repo
843 return repo
844
844
845
845
846 class RepoGroup(Base, BaseModel):
846 class RepoGroup(Base, BaseModel):
847 __tablename__ = 'groups'
847 __tablename__ = 'groups'
848 __table_args__ = (
848 __table_args__ = (
849 UniqueConstraint('group_name', 'group_parent_id'),
849 UniqueConstraint('group_name', 'group_parent_id'),
850 CheckConstraint('group_id != group_parent_id'),
850 CheckConstraint('group_id != group_parent_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 __mapper_args__ = {'order_by': 'group_name'}
854 __mapper_args__ = {'order_by': 'group_name'}
855
855
856 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
856 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
857 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
857 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
858 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
858 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
859 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
859 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
860
860
861 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
861 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
862 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
862 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
863
863
864 parent_group = relationship('RepoGroup', remote_side=group_id)
864 parent_group = relationship('RepoGroup', remote_side=group_id)
865
865
866 def __init__(self, group_name='', parent_group=None):
866 def __init__(self, group_name='', parent_group=None):
867 self.group_name = group_name
867 self.group_name = group_name
868 self.parent_group = parent_group
868 self.parent_group = parent_group
869
869
870 def __unicode__(self):
870 def __unicode__(self):
871 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
871 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
872 self.group_name)
872 self.group_name)
873
873
874 @classmethod
874 @classmethod
875 def groups_choices(cls):
875 def groups_choices(cls):
876 from webhelpers.html import literal as _literal
876 from webhelpers.html import literal as _literal
877 repo_groups = [('', '')]
877 repo_groups = [('', '')]
878 sep = ' &raquo; '
878 sep = ' &raquo; '
879 _name = lambda k: _literal(sep.join(k))
879 _name = lambda k: _literal(sep.join(k))
880
880
881 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
881 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
882 for x in cls.query().all()])
882 for x in cls.query().all()])
883
883
884 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
884 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
885 return repo_groups
885 return repo_groups
886
886
887 @classmethod
887 @classmethod
888 def url_sep(cls):
888 def url_sep(cls):
889 return URL_SEP
889 return URL_SEP
890
890
891 @classmethod
891 @classmethod
892 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
892 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
893 if case_insensitive:
893 if case_insensitive:
894 gr = cls.query()\
894 gr = cls.query()\
895 .filter(cls.group_name.ilike(group_name))
895 .filter(cls.group_name.ilike(group_name))
896 else:
896 else:
897 gr = cls.query()\
897 gr = cls.query()\
898 .filter(cls.group_name == group_name)
898 .filter(cls.group_name == group_name)
899 if cache:
899 if cache:
900 gr = gr.options(FromCache(
900 gr = gr.options(FromCache(
901 "sql_cache_short",
901 "sql_cache_short",
902 "get_group_%s" % _hash_key(group_name)
902 "get_group_%s" % _hash_key(group_name)
903 )
903 )
904 )
904 )
905 return gr.scalar()
905 return gr.scalar()
906
906
907 @property
907 @property
908 def parents(self):
908 def parents(self):
909 parents_recursion_limit = 5
909 parents_recursion_limit = 5
910 groups = []
910 groups = []
911 if self.parent_group is None:
911 if self.parent_group is None:
912 return groups
912 return groups
913 cur_gr = self.parent_group
913 cur_gr = self.parent_group
914 groups.insert(0, cur_gr)
914 groups.insert(0, cur_gr)
915 cnt = 0
915 cnt = 0
916 while 1:
916 while 1:
917 cnt += 1
917 cnt += 1
918 gr = getattr(cur_gr, 'parent_group', None)
918 gr = getattr(cur_gr, 'parent_group', None)
919 cur_gr = cur_gr.parent_group
919 cur_gr = cur_gr.parent_group
920 if gr is None:
920 if gr is None:
921 break
921 break
922 if cnt == parents_recursion_limit:
922 if cnt == parents_recursion_limit:
923 # this will prevent accidental infinit loops
923 # this will prevent accidental infinit loops
924 log.error('group nested more than %s' %
924 log.error('group nested more than %s' %
925 parents_recursion_limit)
925 parents_recursion_limit)
926 break
926 break
927
927
928 groups.insert(0, gr)
928 groups.insert(0, gr)
929 return groups
929 return groups
930
930
931 @property
931 @property
932 def children(self):
932 def children(self):
933 return RepoGroup.query().filter(RepoGroup.parent_group == self)
933 return RepoGroup.query().filter(RepoGroup.parent_group == self)
934
934
935 @property
935 @property
936 def name(self):
936 def name(self):
937 return self.group_name.split(RepoGroup.url_sep())[-1]
937 return self.group_name.split(RepoGroup.url_sep())[-1]
938
938
939 @property
939 @property
940 def full_path(self):
940 def full_path(self):
941 return self.group_name
941 return self.group_name
942
942
943 @property
943 @property
944 def full_path_splitted(self):
944 def full_path_splitted(self):
945 return self.group_name.split(RepoGroup.url_sep())
945 return self.group_name.split(RepoGroup.url_sep())
946
946
947 @property
947 @property
948 def repositories(self):
948 def repositories(self):
949 return Repository.query()\
949 return Repository.query()\
950 .filter(Repository.group == self)\
950 .filter(Repository.group == self)\
951 .order_by(Repository.repo_name)
951 .order_by(Repository.repo_name)
952
952
953 @property
953 @property
954 def repositories_recursive_count(self):
954 def repositories_recursive_count(self):
955 cnt = self.repositories.count()
955 cnt = self.repositories.count()
956
956
957 def children_count(group):
957 def children_count(group):
958 cnt = 0
958 cnt = 0
959 for child in group.children:
959 for child in group.children:
960 cnt += child.repositories.count()
960 cnt += child.repositories.count()
961 cnt += children_count(child)
961 cnt += children_count(child)
962 return cnt
962 return cnt
963
963
964 return cnt + children_count(self)
964 return cnt + children_count(self)
965
965
966 def get_new_name(self, group_name):
966 def get_new_name(self, group_name):
967 """
967 """
968 returns new full group name based on parent and new name
968 returns new full group name based on parent and new name
969
969
970 :param group_name:
970 :param group_name:
971 """
971 """
972 path_prefix = (self.parent_group.full_path_splitted if
972 path_prefix = (self.parent_group.full_path_splitted if
973 self.parent_group else [])
973 self.parent_group else [])
974 return RepoGroup.url_sep().join(path_prefix + [group_name])
974 return RepoGroup.url_sep().join(path_prefix + [group_name])
975
975
976
976
977 class Permission(Base, BaseModel):
977 class Permission(Base, BaseModel):
978 __tablename__ = 'permissions'
978 __tablename__ = 'permissions'
979 __table_args__ = (
979 __table_args__ = (
980 Index('p_perm_name_idx', 'permission_name'),
980 Index('p_perm_name_idx', 'permission_name'),
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 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
984 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
985 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
985 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
986 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
986 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
987
987
988 def __unicode__(self):
988 def __unicode__(self):
989 return u"<%s('%s:%s')>" % (
989 return u"<%s('%s:%s')>" % (
990 self.__class__.__name__, self.permission_id, self.permission_name
990 self.__class__.__name__, self.permission_id, self.permission_name
991 )
991 )
992
992
993 @classmethod
993 @classmethod
994 def get_by_key(cls, key):
994 def get_by_key(cls, key):
995 return cls.query().filter(cls.permission_name == key).scalar()
995 return cls.query().filter(cls.permission_name == key).scalar()
996
996
997 @classmethod
997 @classmethod
998 def get_default_perms(cls, default_user_id):
998 def get_default_perms(cls, default_user_id):
999 q = Session.query(UserRepoToPerm, Repository, cls)\
999 q = Session.query(UserRepoToPerm, Repository, cls)\
1000 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
1000 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
1001 .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
1001 .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
1002 .filter(UserRepoToPerm.user_id == default_user_id)
1002 .filter(UserRepoToPerm.user_id == default_user_id)
1003
1003
1004 return q.all()
1004 return q.all()
1005
1005
1006 @classmethod
1006 @classmethod
1007 def get_default_group_perms(cls, default_user_id):
1007 def get_default_group_perms(cls, default_user_id):
1008 q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
1008 q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
1009 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
1009 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
1010 .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
1010 .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
1011 .filter(UserRepoGroupToPerm.user_id == default_user_id)
1011 .filter(UserRepoGroupToPerm.user_id == default_user_id)
1012
1012
1013 return q.all()
1013 return q.all()
1014
1014
1015
1015
1016 class UserRepoToPerm(Base, BaseModel):
1016 class UserRepoToPerm(Base, BaseModel):
1017 __tablename__ = 'repo_to_perm'
1017 __tablename__ = 'repo_to_perm'
1018 __table_args__ = (
1018 __table_args__ = (
1019 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
1019 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
1020 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1020 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1021 'mysql_charset': 'utf8'}
1021 'mysql_charset': 'utf8'}
1022 )
1022 )
1023 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1023 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1024 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1024 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1025 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1025 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1026 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1026 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1027
1027
1028 user = relationship('User')
1028 user = relationship('User')
1029 repository = relationship('Repository')
1029 repository = relationship('Repository')
1030 permission = relationship('Permission')
1030 permission = relationship('Permission')
1031
1031
1032 @classmethod
1032 @classmethod
1033 def create(cls, user, repository, permission):
1033 def create(cls, user, repository, permission):
1034 n = cls()
1034 n = cls()
1035 n.user = user
1035 n.user = user
1036 n.repository = repository
1036 n.repository = repository
1037 n.permission = permission
1037 n.permission = permission
1038 Session.add(n)
1038 Session.add(n)
1039 return n
1039 return n
1040
1040
1041 def __unicode__(self):
1041 def __unicode__(self):
1042 return u'<user:%s => %s >' % (self.user, self.repository)
1042 return u'<user:%s => %s >' % (self.user, self.repository)
1043
1043
1044
1044
1045 class UserToPerm(Base, BaseModel):
1045 class UserToPerm(Base, BaseModel):
1046 __tablename__ = 'user_to_perm'
1046 __tablename__ = 'user_to_perm'
1047 __table_args__ = (
1047 __table_args__ = (
1048 UniqueConstraint('user_id', 'permission_id'),
1048 UniqueConstraint('user_id', 'permission_id'),
1049 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1049 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1050 'mysql_charset': 'utf8'}
1050 'mysql_charset': 'utf8'}
1051 )
1051 )
1052 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1052 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1053 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1053 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1054 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1054 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1055
1055
1056 user = relationship('User')
1056 user = relationship('User')
1057 permission = relationship('Permission', lazy='joined')
1057 permission = relationship('Permission', lazy='joined')
1058
1058
1059
1059
1060 class UsersGroupRepoToPerm(Base, BaseModel):
1060 class UsersGroupRepoToPerm(Base, BaseModel):
1061 __tablename__ = 'users_group_repo_to_perm'
1061 __tablename__ = 'users_group_repo_to_perm'
1062 __table_args__ = (
1062 __table_args__ = (
1063 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1063 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1064 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1064 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1065 'mysql_charset': 'utf8'}
1065 'mysql_charset': 'utf8'}
1066 )
1066 )
1067 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1067 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1068 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1068 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1069 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1069 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1070 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1070 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1071
1071
1072 users_group = relationship('UsersGroup')
1072 users_group = relationship('UsersGroup')
1073 permission = relationship('Permission')
1073 permission = relationship('Permission')
1074 repository = relationship('Repository')
1074 repository = relationship('Repository')
1075
1075
1076 @classmethod
1076 @classmethod
1077 def create(cls, users_group, repository, permission):
1077 def create(cls, users_group, repository, permission):
1078 n = cls()
1078 n = cls()
1079 n.users_group = users_group
1079 n.users_group = users_group
1080 n.repository = repository
1080 n.repository = repository
1081 n.permission = permission
1081 n.permission = permission
1082 Session.add(n)
1082 Session.add(n)
1083 return n
1083 return n
1084
1084
1085 def __unicode__(self):
1085 def __unicode__(self):
1086 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1086 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1087
1087
1088
1088
1089 class UsersGroupToPerm(Base, BaseModel):
1089 class UsersGroupToPerm(Base, BaseModel):
1090 __tablename__ = 'users_group_to_perm'
1090 __tablename__ = 'users_group_to_perm'
1091 __table_args__ = (
1091 __table_args__ = (
1092 UniqueConstraint('users_group_id', 'permission_id',),
1092 UniqueConstraint('users_group_id', 'permission_id',),
1093 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1093 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1094 'mysql_charset': 'utf8'}
1094 'mysql_charset': 'utf8'}
1095 )
1095 )
1096 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1096 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1097 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1097 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1098 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1098 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1099
1099
1100 users_group = relationship('UsersGroup')
1100 users_group = relationship('UsersGroup')
1101 permission = relationship('Permission')
1101 permission = relationship('Permission')
1102
1102
1103
1103
1104 class UserRepoGroupToPerm(Base, BaseModel):
1104 class UserRepoGroupToPerm(Base, BaseModel):
1105 __tablename__ = 'user_repo_group_to_perm'
1105 __tablename__ = 'user_repo_group_to_perm'
1106 __table_args__ = (
1106 __table_args__ = (
1107 UniqueConstraint('user_id', 'group_id', 'permission_id'),
1107 UniqueConstraint('user_id', 'group_id', 'permission_id'),
1108 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1108 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1109 'mysql_charset': 'utf8'}
1109 'mysql_charset': 'utf8'}
1110 )
1110 )
1111
1111
1112 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1112 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1113 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1113 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1114 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1114 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1115 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1115 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1116
1116
1117 user = relationship('User')
1117 user = relationship('User')
1118 group = relationship('RepoGroup')
1118 group = relationship('RepoGroup')
1119 permission = relationship('Permission')
1119 permission = relationship('Permission')
1120
1120
1121
1121
1122 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1122 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1123 __tablename__ = 'users_group_repo_group_to_perm'
1123 __tablename__ = 'users_group_repo_group_to_perm'
1124 __table_args__ = (
1124 __table_args__ = (
1125 UniqueConstraint('users_group_id', 'group_id'),
1125 UniqueConstraint('users_group_id', 'group_id'),
1126 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1126 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1127 'mysql_charset': 'utf8'}
1127 'mysql_charset': 'utf8'}
1128 )
1128 )
1129
1129
1130 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)
1130 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)
1131 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1131 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1132 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1132 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1133 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1133 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1134
1134
1135 users_group = relationship('UsersGroup')
1135 users_group = relationship('UsersGroup')
1136 permission = relationship('Permission')
1136 permission = relationship('Permission')
1137 group = relationship('RepoGroup')
1137 group = relationship('RepoGroup')
1138
1138
1139
1139
1140 class Statistics(Base, BaseModel):
1140 class Statistics(Base, BaseModel):
1141 __tablename__ = 'statistics'
1141 __tablename__ = 'statistics'
1142 __table_args__ = (
1142 __table_args__ = (
1143 UniqueConstraint('repository_id'),
1143 UniqueConstraint('repository_id'),
1144 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1144 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1145 'mysql_charset': 'utf8'}
1145 'mysql_charset': 'utf8'}
1146 )
1146 )
1147 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1147 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1148 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
1148 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
1149 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
1149 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
1150 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1150 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1151 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
1151 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
1152 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1152 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1153
1153
1154 repository = relationship('Repository', single_parent=True)
1154 repository = relationship('Repository', single_parent=True)
1155
1155
1156
1156
1157 class UserFollowing(Base, BaseModel):
1157 class UserFollowing(Base, BaseModel):
1158 __tablename__ = 'user_followings'
1158 __tablename__ = 'user_followings'
1159 __table_args__ = (
1159 __table_args__ = (
1160 UniqueConstraint('user_id', 'follows_repository_id'),
1160 UniqueConstraint('user_id', 'follows_repository_id'),
1161 UniqueConstraint('user_id', 'follows_user_id'),
1161 UniqueConstraint('user_id', 'follows_user_id'),
1162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1162 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1163 'mysql_charset': 'utf8'}
1163 'mysql_charset': 'utf8'}
1164 )
1164 )
1165
1165
1166 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1166 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1167 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1167 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1168 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1168 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1169 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1169 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1170 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1170 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1171
1171
1172 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1172 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1173
1173
1174 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1174 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1175 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1175 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1176
1176
1177 @classmethod
1177 @classmethod
1178 def get_repo_followers(cls, repo_id):
1178 def get_repo_followers(cls, repo_id):
1179 return cls.query().filter(cls.follows_repo_id == repo_id)
1179 return cls.query().filter(cls.follows_repo_id == repo_id)
1180
1180
1181
1181
1182 class CacheInvalidation(Base, BaseModel):
1182 class CacheInvalidation(Base, BaseModel):
1183 __tablename__ = 'cache_invalidation'
1183 __tablename__ = 'cache_invalidation'
1184 __table_args__ = (
1184 __table_args__ = (
1185 UniqueConstraint('cache_key'),
1185 UniqueConstraint('cache_key'),
1186 Index('key_idx', 'cache_key'),
1186 Index('key_idx', 'cache_key'),
1187 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1187 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1188 'mysql_charset': 'utf8'},
1188 'mysql_charset': 'utf8'},
1189 )
1189 )
1190 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1190 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1191 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1191 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1192 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1192 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1193 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1193 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1194
1194
1195 def __init__(self, cache_key, cache_args=''):
1195 def __init__(self, cache_key, cache_args=''):
1196 self.cache_key = cache_key
1196 self.cache_key = cache_key
1197 self.cache_args = cache_args
1197 self.cache_args = cache_args
1198 self.cache_active = False
1198 self.cache_active = False
1199
1199
1200 def __unicode__(self):
1200 def __unicode__(self):
1201 return u"<%s('%s:%s')>" % (self.__class__.__name__,
1201 return u"<%s('%s:%s')>" % (self.__class__.__name__,
1202 self.cache_id, self.cache_key)
1202 self.cache_id, self.cache_key)
1203
1203
1204 @classmethod
1204 @classmethod
1205 def clear_cache(cls):
1205 def clear_cache(cls):
1206 cls.query().delete()
1206 cls.query().delete()
1207
1207
1208 @classmethod
1208 @classmethod
1209 def _get_key(cls, key):
1209 def _get_key(cls, key):
1210 """
1210 """
1211 Wrapper for generating a key, together with a prefix
1211 Wrapper for generating a key, together with a prefix
1212
1212
1213 :param key:
1213 :param key:
1214 """
1214 """
1215 import rhodecode
1215 import rhodecode
1216 prefix = ''
1216 prefix = ''
1217 iid = rhodecode.CONFIG.get('instance_id')
1217 iid = rhodecode.CONFIG.get('instance_id')
1218 if iid:
1218 if iid:
1219 prefix = iid
1219 prefix = iid
1220 return "%s%s" % (prefix, key), prefix, key.rstrip('_README')
1220 return "%s%s" % (prefix, key), prefix, key.rstrip('_README')
1221
1221
1222 @classmethod
1222 @classmethod
1223 def get_by_key(cls, key):
1223 def get_by_key(cls, key):
1224 return cls.query().filter(cls.cache_key == key).scalar()
1224 return cls.query().filter(cls.cache_key == key).scalar()
1225
1225
1226 @classmethod
1226 @classmethod
1227 def _get_or_create_key(cls, key, prefix, org_key):
1227 def _get_or_create_key(cls, key, prefix, org_key):
1228 inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar()
1228 inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar()
1229 if not inv_obj:
1229 if not inv_obj:
1230 try:
1230 try:
1231 inv_obj = CacheInvalidation(key, org_key)
1231 inv_obj = CacheInvalidation(key, org_key)
1232 Session.add(inv_obj)
1232 Session.add(inv_obj)
1233 Session.commit()
1233 Session.commit()
1234 except Exception:
1234 except Exception:
1235 log.error(traceback.format_exc())
1235 log.error(traceback.format_exc())
1236 Session.rollback()
1236 Session.rollback()
1237 return inv_obj
1237 return inv_obj
1238
1238
1239 @classmethod
1239 @classmethod
1240 def invalidate(cls, key):
1240 def invalidate(cls, key):
1241 """
1241 """
1242 Returns Invalidation object if this given key should be invalidated
1242 Returns Invalidation object if this given key should be invalidated
1243 None otherwise. `cache_active = False` means that this cache
1243 None otherwise. `cache_active = False` means that this cache
1244 state is not valid and needs to be invalidated
1244 state is not valid and needs to be invalidated
1245
1245
1246 :param key:
1246 :param key:
1247 """
1247 """
1248
1248
1249 key, _prefix, _org_key = cls._get_key(key)
1249 key, _prefix, _org_key = cls._get_key(key)
1250 inv = cls._get_or_create_key(key, _prefix, _org_key)
1250 inv = cls._get_or_create_key(key, _prefix, _org_key)
1251
1251
1252 if inv and inv.cache_active is False:
1252 if inv and inv.cache_active is False:
1253 return inv
1253 return inv
1254
1254
1255 @classmethod
1255 @classmethod
1256 def set_invalidate(cls, key):
1256 def set_invalidate(cls, key):
1257 """
1257 """
1258 Mark this Cache key for invalidation
1258 Mark this Cache key for invalidation
1259
1259
1260 :param key:
1260 :param key:
1261 """
1261 """
1262
1262
1263 key, _prefix, _org_key = cls._get_key(key)
1263 key, _prefix, _org_key = cls._get_key(key)
1264 inv_objs = Session.query(cls).filter(cls.cache_args == _org_key).all()
1264 inv_objs = Session.query(cls).filter(cls.cache_args == _org_key).all()
1265 log.debug('marking %s key[s] %s for invalidation' % (len(inv_objs),
1265 log.debug('marking %s key[s] %s for invalidation' % (len(inv_objs),
1266 _org_key))
1266 _org_key))
1267 try:
1267 try:
1268 for inv_obj in inv_objs:
1268 for inv_obj in inv_objs:
1269 if inv_obj:
1269 if inv_obj:
1270 inv_obj.cache_active = False
1270 inv_obj.cache_active = False
1271
1271
1272 Session.add(inv_obj)
1272 Session.add(inv_obj)
1273 Session.commit()
1273 Session.commit()
1274 except Exception:
1274 except Exception:
1275 log.error(traceback.format_exc())
1275 log.error(traceback.format_exc())
1276 Session.rollback()
1276 Session.rollback()
1277
1277
1278 @classmethod
1278 @classmethod
1279 def set_valid(cls, key):
1279 def set_valid(cls, key):
1280 """
1280 """
1281 Mark this cache key as active and currently cached
1281 Mark this cache key as active and currently cached
1282
1282
1283 :param key:
1283 :param key:
1284 """
1284 """
1285 inv_obj = cls.get_by_key(key)
1285 inv_obj = cls.get_by_key(key)
1286 inv_obj.cache_active = True
1286 inv_obj.cache_active = True
1287 Session.add(inv_obj)
1287 Session.add(inv_obj)
1288 Session.commit()
1288 Session.commit()
1289
1289
1290 @classmethod
1290 @classmethod
1291 def get_cache_map(cls):
1291 def get_cache_map(cls):
1292
1292
1293 class cachemapdict(dict):
1293 class cachemapdict(dict):
1294
1294
1295 def __init__(self, *args, **kwargs):
1295 def __init__(self, *args, **kwargs):
1296 fixkey = kwargs.get('fixkey')
1296 fixkey = kwargs.get('fixkey')
1297 if fixkey:
1297 if fixkey:
1298 del kwargs['fixkey']
1298 del kwargs['fixkey']
1299 self.fixkey = fixkey
1299 self.fixkey = fixkey
1300 super(cachemapdict, self).__init__(*args, **kwargs)
1300 super(cachemapdict, self).__init__(*args, **kwargs)
1301
1301
1302 def __getattr__(self, name):
1302 def __getattr__(self, name):
1303 key = name
1303 key = name
1304 if self.fixkey:
1304 if self.fixkey:
1305 key, _prefix, _org_key = cls._get_key(key)
1305 key, _prefix, _org_key = cls._get_key(key)
1306 if key in self.__dict__:
1306 if key in self.__dict__:
1307 return self.__dict__[key]
1307 return self.__dict__[key]
1308 else:
1308 else:
1309 return self[key]
1309 return self[key]
1310
1310
1311 def __getitem__(self, key):
1311 def __getitem__(self, key):
1312 if self.fixkey:
1312 if self.fixkey:
1313 key, _prefix, _org_key = cls._get_key(key)
1313 key, _prefix, _org_key = cls._get_key(key)
1314 try:
1314 try:
1315 return super(cachemapdict, self).__getitem__(key)
1315 return super(cachemapdict, self).__getitem__(key)
1316 except KeyError:
1316 except KeyError:
1317 return
1317 return
1318
1318
1319 cache_map = cachemapdict(fixkey=True)
1319 cache_map = cachemapdict(fixkey=True)
1320 for obj in cls.query().all():
1320 for obj in cls.query().all():
1321 cache_map[obj.cache_key] = cachemapdict(obj.get_dict())
1321 cache_map[obj.cache_key] = cachemapdict(obj.get_dict())
1322 return cache_map
1322 return cache_map
1323
1323
1324
1324
1325 class ChangesetComment(Base, BaseModel):
1325 class ChangesetComment(Base, BaseModel):
1326 __tablename__ = 'changeset_comments'
1326 __tablename__ = 'changeset_comments'
1327 __table_args__ = (
1327 __table_args__ = (
1328 Index('cc_revision_idx', 'revision'),
1328 Index('cc_revision_idx', 'revision'),
1329 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1329 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1330 'mysql_charset': 'utf8'},
1330 'mysql_charset': 'utf8'},
1331 )
1331 )
1332 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1332 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1333 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1333 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1334 revision = Column('revision', String(40), nullable=True)
1334 revision = Column('revision', String(40), nullable=True)
1335 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1335 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1336 line_no = Column('line_no', Unicode(10), nullable=True)
1336 line_no = Column('line_no', Unicode(10), nullable=True)
1337 f_path = Column('f_path', Unicode(1000), nullable=True)
1337 f_path = Column('f_path', Unicode(1000), nullable=True)
1338 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1338 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1339 text = Column('text', Unicode(25000), nullable=False)
1339 text = Column('text', Unicode(25000), nullable=False)
1340 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1340 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1341
1341
1342 author = relationship('User', lazy='joined')
1342 author = relationship('User', lazy='joined')
1343 repo = relationship('Repository')
1343 repo = relationship('Repository')
1344 status_change = relationship('ChangesetStatus', uselist=False)
1344 status_change = relationship('ChangesetStatus', uselist=False)
1345 pull_request = relationship('PullRequest', lazy='joined')
1345 pull_request = relationship('PullRequest', lazy='joined')
1346
1346
1347 @classmethod
1347 @classmethod
1348 def get_users(cls, revision=None, pull_request_id=None):
1348 def get_users(cls, revision=None, pull_request_id=None):
1349 """
1349 """
1350 Returns user associated with this ChangesetComment. ie those
1350 Returns user associated with this ChangesetComment. ie those
1351 who actually commented
1351 who actually commented
1352
1352
1353 :param cls:
1353 :param cls:
1354 :param revision:
1354 :param revision:
1355 """
1355 """
1356 q = Session.query(User)\
1356 q = Session.query(User)\
1357 .join(ChangesetComment.author)
1357 .join(ChangesetComment.author)
1358 if revision:
1358 if revision:
1359 q = q.filter(cls.revision == revision)
1359 q = q.filter(cls.revision == revision)
1360 elif pull_request_id:
1360 elif pull_request_id:
1361 q = q.filter(cls.pull_request_id == pull_request_id)
1361 q = q.filter(cls.pull_request_id == pull_request_id)
1362 return q.all()
1362 return q.all()
1363
1363
1364
1364
1365 class ChangesetStatus(Base, BaseModel):
1365 class ChangesetStatus(Base, BaseModel):
1366 __tablename__ = 'changeset_statuses'
1366 __tablename__ = 'changeset_statuses'
1367 __table_args__ = (
1367 __table_args__ = (
1368 Index('cs_revision_idx', 'revision'),
1368 Index('cs_revision_idx', 'revision'),
1369 Index('cs_version_idx', 'version'),
1369 Index('cs_version_idx', 'version'),
1370 UniqueConstraint('repo_id', 'revision', 'version'),
1370 UniqueConstraint('repo_id', 'revision', 'version'),
1371 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1371 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1372 'mysql_charset': 'utf8'}
1372 'mysql_charset': 'utf8'}
1373 )
1373 )
1374
1374
1375 STATUSES = [
1375 STATUSES = [
1376 ('not_reviewed', _("Not Reviewed")), # (no icon) and default
1376 ('not_reviewed', _("Not Reviewed")), # (no icon) and default
1377 ('approved', _("Approved")),
1377 ('approved', _("Approved")),
1378 ('rejected', _("Rejected")),
1378 ('rejected', _("Rejected")),
1379 ('under_review', _("Under Review")),
1379 ('under_review', _("Under Review")),
1380 ]
1380 ]
1381 DEFAULT = STATUSES[0][0]
1381 DEFAULT = STATUSES[0][0]
1382
1382
1383 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1383 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1384 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1384 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1385 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1385 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1386 revision = Column('revision', String(40), nullable=False)
1386 revision = Column('revision', String(40), nullable=False)
1387 status = Column('status', String(128), nullable=False, default=DEFAULT)
1387 status = Column('status', String(128), nullable=False, default=DEFAULT)
1388 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1388 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1389 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1389 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1390 version = Column('version', Integer(), nullable=False, default=0)
1390 version = Column('version', Integer(), nullable=False, default=0)
1391 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1391 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1392
1392
1393 author = relationship('User', lazy='joined')
1393 author = relationship('User', lazy='joined')
1394 repo = relationship('Repository')
1394 repo = relationship('Repository')
1395 comment = relationship('ChangesetComment', lazy='joined')
1395 comment = relationship('ChangesetComment', lazy='joined')
1396 pull_request = relationship('PullRequest', lazy='joined')
1396 pull_request = relationship('PullRequest', lazy='joined')
1397
1397
1398 @classmethod
1398 @classmethod
1399 def get_status_lbl(cls, value):
1399 def get_status_lbl(cls, value):
1400 return dict(cls.STATUSES).get(value)
1400 return dict(cls.STATUSES).get(value)
1401
1401
1402 @property
1402 @property
1403 def status_lbl(self):
1403 def status_lbl(self):
1404 return ChangesetStatus.get_status_lbl(self.status)
1404 return ChangesetStatus.get_status_lbl(self.status)
1405
1405
1406
1406
1407 class PullRequest(Base, BaseModel):
1407 class PullRequest(Base, BaseModel):
1408 __tablename__ = 'pull_requests'
1408 __tablename__ = 'pull_requests'
1409 __table_args__ = (
1409 __table_args__ = (
1410 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1410 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1411 'mysql_charset': 'utf8'},
1411 'mysql_charset': 'utf8'},
1412 )
1412 )
1413
1413
1414 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1414 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1415 title = Column('title', Unicode(256), nullable=True)
1415 title = Column('title', Unicode(256), nullable=True)
1416 description = Column('description', Unicode(10240), nullable=True)
1416 description = Column('description', Unicode(10240), nullable=True)
1417 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1417 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1418 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1418 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1419 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1419 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1420 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1420 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1421 org_ref = Column('org_ref', Unicode(256), nullable=False)
1421 org_ref = Column('org_ref', Unicode(256), nullable=False)
1422 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1422 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1423 other_ref = Column('other_ref', Unicode(256), nullable=False)
1423 other_ref = Column('other_ref', Unicode(256), nullable=False)
1424
1424
1425 @hybrid_property
1425 @hybrid_property
1426 def revisions(self):
1426 def revisions(self):
1427 return self._revisions.split(':')
1427 return self._revisions.split(':')
1428
1428
1429 @revisions.setter
1429 @revisions.setter
1430 def revisions(self, val):
1430 def revisions(self, val):
1431 self._revisions = ':'.join(val)
1431 self._revisions = ':'.join(val)
1432
1432
1433 author = relationship('User', lazy='joined')
1433 author = relationship('User', lazy='joined')
1434 reviewers = relationship('PullRequestReviewers')
1434 reviewers = relationship('PullRequestReviewers')
1435 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1435 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1436 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1436 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1437
1437
1438 def __json__(self):
1438 def __json__(self):
1439 return dict(
1439 return dict(
1440 revisions=self.revisions
1440 revisions=self.revisions
1441 )
1441 )
1442
1442
1443
1443
1444 class PullRequestReviewers(Base, BaseModel):
1444 class PullRequestReviewers(Base, BaseModel):
1445 __tablename__ = 'pull_request_reviewers'
1445 __tablename__ = 'pull_request_reviewers'
1446 __table_args__ = (
1446 __table_args__ = (
1447 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1447 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1448 'mysql_charset': 'utf8'},
1448 'mysql_charset': 'utf8'},
1449 )
1449 )
1450
1450
1451 def __init__(self, user=None, pull_request=None):
1451 def __init__(self, user=None, pull_request=None):
1452 self.user = user
1452 self.user = user
1453 self.pull_request = pull_request
1453 self.pull_request = pull_request
1454
1454
1455 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1455 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1456 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1456 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1457 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1457 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1458
1458
1459 user = relationship('User')
1459 user = relationship('User')
1460 pull_request = relationship('PullRequest')
1460 pull_request = relationship('PullRequest')
1461
1461
1462
1462
1463 class Notification(Base, BaseModel):
1463 class Notification(Base, BaseModel):
1464 __tablename__ = 'notifications'
1464 __tablename__ = 'notifications'
1465 __table_args__ = (
1465 __table_args__ = (
1466 Index('notification_type_idx', 'type'),
1466 Index('notification_type_idx', 'type'),
1467 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1467 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1468 'mysql_charset': 'utf8'},
1468 'mysql_charset': 'utf8'},
1469 )
1469 )
1470
1470
1471 TYPE_CHANGESET_COMMENT = u'cs_comment'
1471 TYPE_CHANGESET_COMMENT = u'cs_comment'
1472 TYPE_MESSAGE = u'message'
1472 TYPE_MESSAGE = u'message'
1473 TYPE_MENTION = u'mention'
1473 TYPE_MENTION = u'mention'
1474 TYPE_REGISTRATION = u'registration'
1474 TYPE_REGISTRATION = u'registration'
1475 TYPE_PULL_REQUEST = u'pull_request'
1475 TYPE_PULL_REQUEST = u'pull_request'
1476 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1476 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1477
1477
1478 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1478 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1479 subject = Column('subject', Unicode(512), nullable=True)
1479 subject = Column('subject', Unicode(512), nullable=True)
1480 body = Column('body', Unicode(50000), nullable=True)
1480 body = Column('body', Unicode(50000), nullable=True)
1481 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1481 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1482 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1482 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1483 type_ = Column('type', Unicode(256))
1483 type_ = Column('type', Unicode(256))
1484
1484
1485 created_by_user = relationship('User')
1485 created_by_user = relationship('User')
1486 notifications_to_users = relationship('UserNotification', lazy='joined',
1486 notifications_to_users = relationship('UserNotification', lazy='joined',
1487 cascade="all, delete, delete-orphan")
1487 cascade="all, delete, delete-orphan")
1488
1488
1489 @property
1489 @property
1490 def recipients(self):
1490 def recipients(self):
1491 return [x.user for x in UserNotification.query()\
1491 return [x.user for x in UserNotification.query()\
1492 .filter(UserNotification.notification == self)\
1492 .filter(UserNotification.notification == self)\
1493 .order_by(UserNotification.user).all()]
1493 .order_by(UserNotification.user).all()]
1494
1494
1495 @classmethod
1495 @classmethod
1496 def create(cls, created_by, subject, body, recipients, type_=None):
1496 def create(cls, created_by, subject, body, recipients, type_=None):
1497 if type_ is None:
1497 if type_ is None:
1498 type_ = Notification.TYPE_MESSAGE
1498 type_ = Notification.TYPE_MESSAGE
1499
1499
1500 notification = cls()
1500 notification = cls()
1501 notification.created_by_user = created_by
1501 notification.created_by_user = created_by
1502 notification.subject = subject
1502 notification.subject = subject
1503 notification.body = body
1503 notification.body = body
1504 notification.type_ = type_
1504 notification.type_ = type_
1505 notification.created_on = datetime.datetime.now()
1505 notification.created_on = datetime.datetime.now()
1506
1506
1507 for u in recipients:
1507 for u in recipients:
1508 assoc = UserNotification()
1508 assoc = UserNotification()
1509 assoc.notification = notification
1509 assoc.notification = notification
1510 u.notifications.append(assoc)
1510 u.notifications.append(assoc)
1511 Session.add(notification)
1511 Session.add(notification)
1512 return notification
1512 return notification
1513
1513
1514 @property
1514 @property
1515 def description(self):
1515 def description(self):
1516 from rhodecode.model.notification import NotificationModel
1516 from rhodecode.model.notification import NotificationModel
1517 return NotificationModel().make_description(self)
1517 return NotificationModel().make_description(self)
1518
1518
1519
1519
1520 class UserNotification(Base, BaseModel):
1520 class UserNotification(Base, BaseModel):
1521 __tablename__ = 'user_to_notification'
1521 __tablename__ = 'user_to_notification'
1522 __table_args__ = (
1522 __table_args__ = (
1523 UniqueConstraint('user_id', 'notification_id'),
1523 UniqueConstraint('user_id', 'notification_id'),
1524 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1524 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1525 'mysql_charset': 'utf8'}
1525 'mysql_charset': 'utf8'}
1526 )
1526 )
1527 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1527 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1528 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1528 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1529 read = Column('read', Boolean, default=False)
1529 read = Column('read', Boolean, default=False)
1530 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1530 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1531
1531
1532 user = relationship('User', lazy="joined")
1532 user = relationship('User', lazy="joined")
1533 notification = relationship('Notification', lazy="joined",
1533 notification = relationship('Notification', lazy="joined",
1534 order_by=lambda: Notification.created_on.desc(),)
1534 order_by=lambda: Notification.created_on.desc(),)
1535
1535
1536 def mark_as_read(self):
1536 def mark_as_read(self):
1537 self.read = True
1537 self.read = True
1538 Session.add(self)
1538 Session.add(self)
1539
1539
1540
1540
1541 class DbMigrateVersion(Base, BaseModel):
1541 class DbMigrateVersion(Base, BaseModel):
1542 __tablename__ = 'db_migrate_version'
1542 __tablename__ = 'db_migrate_version'
1543 __table_args__ = (
1543 __table_args__ = (
1544 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1544 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1545 'mysql_charset': 'utf8'},
1545 'mysql_charset': 'utf8'},
1546 )
1546 )
1547 repository_id = Column('repository_id', String(250), primary_key=True)
1547 repository_id = Column('repository_id', String(250), primary_key=True)
1548 repository_path = Column('repository_path', Text)
1548 repository_path = Column('repository_path', Text)
1549 version = Column('version', Integer)
1549 version = Column('version', Integer)
@@ -1,308 +1,308 b''
1 """ this is forms validation classes
1 """ this is forms validation classes
2 http://formencode.org/module-formencode.validators.html
2 http://formencode.org/module-formencode.validators.html
3 for list off all availible validators
3 for list off all availible validators
4
4
5 we can create our own validators
5 we can create our own validators
6
6
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 pre_validators [] These validators will be applied before the schema
8 pre_validators [] These validators will be applied before the schema
9 chained_validators [] These validators will be applied after the schema
9 chained_validators [] These validators will be applied after the schema
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14
14
15
15
16 <name> = formencode.validators.<name of validator>
16 <name> = formencode.validators.<name of validator>
17 <name> must equal form name
17 <name> must equal form name
18 list=[1,2,3,4,5]
18 list=[1,2,3,4,5]
19 for SELECT use formencode.All(OneOf(list), Int())
19 for SELECT use formencode.All(OneOf(list), Int())
20
20
21 """
21 """
22 import logging
22 import logging
23
23
24 import formencode
24 import formencode
25 from formencode import All
25 from formencode import All
26
26
27 from pylons.i18n.translation import _
27 from pylons.i18n.translation import _
28
28
29 from rhodecode.model import validators as v
29 from rhodecode.model import validators as v
30 from rhodecode import BACKENDS
30 from rhodecode import BACKENDS
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
34
34
35 class LoginForm(formencode.Schema):
35 class LoginForm(formencode.Schema):
36 allow_extra_fields = True
36 allow_extra_fields = True
37 filter_extra_fields = True
37 filter_extra_fields = True
38 username = v.UnicodeString(
38 username = v.UnicodeString(
39 strip=True,
39 strip=True,
40 min=1,
40 min=1,
41 not_empty=True,
41 not_empty=True,
42 messages={
42 messages={
43 'empty': _(u'Please enter a login'),
43 'empty': _(u'Please enter a login'),
44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
44 'tooShort': _(u'Enter a value %(min)i characters long or more')}
45 )
45 )
46
46
47 password = v.UnicodeString(
47 password = v.UnicodeString(
48 strip=False,
48 strip=False,
49 min=3,
49 min=3,
50 not_empty=True,
50 not_empty=True,
51 messages={
51 messages={
52 'empty': _(u'Please enter a password'),
52 'empty': _(u'Please enter a password'),
53 'tooShort': _(u'Enter %(min)i characters or more')}
53 'tooShort': _(u'Enter %(min)i characters or more')}
54 )
54 )
55
55
56 remember = v.StringBoolean(if_missing=False)
56 remember = v.StringBoolean(if_missing=False)
57
57
58 chained_validators = [v.ValidAuth()]
58 chained_validators = [v.ValidAuth()]
59
59
60
60
61 def UserForm(edit=False, old_data={}):
61 def UserForm(edit=False, old_data={}):
62 class _UserForm(formencode.Schema):
62 class _UserForm(formencode.Schema):
63 allow_extra_fields = True
63 allow_extra_fields = True
64 filter_extra_fields = True
64 filter_extra_fields = True
65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
65 username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
66 v.ValidUsername(edit, old_data))
66 v.ValidUsername(edit, old_data))
67 if edit:
67 if edit:
68 new_password = All(
68 new_password = All(
69 v.UnicodeString(strip=False, min=6, not_empty=False)
69 v.UnicodeString(strip=False, min=6, not_empty=False)
70 )
70 )
71 password_confirmation = All(
71 password_confirmation = All(
72 v.ValidPassword(),
72 v.ValidPassword(),
73 v.UnicodeString(strip=False, min=6, not_empty=False),
73 v.UnicodeString(strip=False, min=6, not_empty=False),
74 )
74 )
75 admin = v.StringBoolean(if_missing=False)
75 admin = v.StringBoolean(if_missing=False)
76 else:
76 else:
77 password = All(
77 password = All(
78 v.ValidPassword(),
78 v.ValidPassword(),
79 v.UnicodeString(strip=False, min=6, not_empty=True)
79 v.UnicodeString(strip=False, min=6, not_empty=True)
80 )
80 )
81 password_confirmation = All(
81 password_confirmation = All(
82 v.ValidPassword(),
82 v.ValidPassword(),
83 v.UnicodeString(strip=False, min=6, not_empty=False)
83 v.UnicodeString(strip=False, min=6, not_empty=False)
84 )
84 )
85
85
86 active = v.StringBoolean(if_missing=False)
86 active = v.StringBoolean(if_missing=False)
87 name = v.UnicodeString(strip=True, min=1, not_empty=False)
87 name = v.UnicodeString(strip=True, min=1, not_empty=False)
88 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
88 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
89 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
89 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
90
90
91 chained_validators = [v.ValidPasswordsMatch()]
91 chained_validators = [v.ValidPasswordsMatch()]
92
92
93 return _UserForm
93 return _UserForm
94
94
95
95
96 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
96 def UsersGroupForm(edit=False, old_data={}, available_members=[]):
97 class _UsersGroupForm(formencode.Schema):
97 class _UsersGroupForm(formencode.Schema):
98 allow_extra_fields = True
98 allow_extra_fields = True
99 filter_extra_fields = True
99 filter_extra_fields = True
100
100
101 users_group_name = All(
101 users_group_name = All(
102 v.UnicodeString(strip=True, min=1, not_empty=True),
102 v.UnicodeString(strip=True, min=1, not_empty=True),
103 v.ValidUsersGroup(edit, old_data)
103 v.ValidUsersGroup(edit, old_data)
104 )
104 )
105
105
106 users_group_active = v.StringBoolean(if_missing=False)
106 users_group_active = v.StringBoolean(if_missing=False)
107
107
108 if edit:
108 if edit:
109 users_group_members = v.OneOf(
109 users_group_members = v.OneOf(
110 available_members, hideList=False, testValueList=True,
110 available_members, hideList=False, testValueList=True,
111 if_missing=None, not_empty=False
111 if_missing=None, not_empty=False
112 )
112 )
113
113
114 return _UsersGroupForm
114 return _UsersGroupForm
115
115
116
116
117 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
117 def ReposGroupForm(edit=False, old_data={}, available_groups=[]):
118 class _ReposGroupForm(formencode.Schema):
118 class _ReposGroupForm(formencode.Schema):
119 allow_extra_fields = True
119 allow_extra_fields = True
120 filter_extra_fields = False
120 filter_extra_fields = False
121
121
122 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
122 group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
123 v.SlugifyName())
123 v.SlugifyName())
124 group_description = v.UnicodeString(strip=True, min=1,
124 group_description = v.UnicodeString(strip=True, min=1,
125 not_empty=True)
125 not_empty=True)
126 group_parent_id = v.OneOf(available_groups, hideList=False,
126 group_parent_id = v.OneOf(available_groups, hideList=False,
127 testValueList=True,
127 testValueList=True,
128 if_missing=None, not_empty=False)
128 if_missing=None, not_empty=False)
129
129
130 chained_validators = [v.ValidReposGroup(edit, old_data),
130 chained_validators = [v.ValidReposGroup(edit, old_data),
131 v.ValidPerms('group')]
131 v.ValidPerms('group')]
132
132
133 return _ReposGroupForm
133 return _ReposGroupForm
134
134
135
135
136 def RegisterForm(edit=False, old_data={}):
136 def RegisterForm(edit=False, old_data={}):
137 class _RegisterForm(formencode.Schema):
137 class _RegisterForm(formencode.Schema):
138 allow_extra_fields = True
138 allow_extra_fields = True
139 filter_extra_fields = True
139 filter_extra_fields = True
140 username = All(
140 username = All(
141 v.ValidUsername(edit, old_data),
141 v.ValidUsername(edit, old_data),
142 v.UnicodeString(strip=True, min=1, not_empty=True)
142 v.UnicodeString(strip=True, min=1, not_empty=True)
143 )
143 )
144 password = All(
144 password = All(
145 v.ValidPassword(),
145 v.ValidPassword(),
146 v.UnicodeString(strip=False, min=6, not_empty=True)
146 v.UnicodeString(strip=False, min=6, not_empty=True)
147 )
147 )
148 password_confirmation = All(
148 password_confirmation = All(
149 v.ValidPassword(),
149 v.ValidPassword(),
150 v.UnicodeString(strip=False, min=6, not_empty=True)
150 v.UnicodeString(strip=False, min=6, not_empty=True)
151 )
151 )
152 active = v.StringBoolean(if_missing=False)
152 active = v.StringBoolean(if_missing=False)
153 name = v.UnicodeString(strip=True, min=1, not_empty=False)
153 name = v.UnicodeString(strip=True, min=1, not_empty=False)
154 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
154 lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
155 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
155 email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
156
156
157 chained_validators = [v.ValidPasswordsMatch()]
157 chained_validators = [v.ValidPasswordsMatch()]
158
158
159 return _RegisterForm
159 return _RegisterForm
160
160
161
161
162 def PasswordResetForm():
162 def PasswordResetForm():
163 class _PasswordResetForm(formencode.Schema):
163 class _PasswordResetForm(formencode.Schema):
164 allow_extra_fields = True
164 allow_extra_fields = True
165 filter_extra_fields = True
165 filter_extra_fields = True
166 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
166 email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
167 return _PasswordResetForm
167 return _PasswordResetForm
168
168
169
169
170 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
170 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
171 repo_groups=[], landing_revs=[]):
171 repo_groups=[], landing_revs=[]):
172 class _RepoForm(formencode.Schema):
172 class _RepoForm(formencode.Schema):
173 allow_extra_fields = True
173 allow_extra_fields = True
174 filter_extra_fields = False
174 filter_extra_fields = False
175 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
175 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
176 v.SlugifyName())
176 v.SlugifyName())
177 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
177 clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
178 repo_group = v.OneOf(repo_groups, hideList=True)
178 repo_group = v.OneOf(repo_groups, hideList=True)
179 repo_type = v.OneOf(supported_backends)
179 repo_type = v.OneOf(supported_backends)
180 description = v.UnicodeString(strip=True, min=1, not_empty=False)
180 description = v.UnicodeString(strip=True, min=1, not_empty=False)
181 private = v.StringBoolean(if_missing=False)
181 private = v.StringBoolean(if_missing=False)
182 enable_statistics = v.StringBoolean(if_missing=False)
182 enable_statistics = v.StringBoolean(if_missing=False)
183 enable_downloads = v.StringBoolean(if_missing=False)
183 enable_downloads = v.StringBoolean(if_missing=False)
184 landing_rev = v.OneOf(landing_revs, hideList=True)
184 landing_rev = v.OneOf(landing_revs, hideList=True)
185
185
186 if edit:
186 if edit:
187 #this is repo owner
187 #this is repo owner
188 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
188 user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
189
189
190 chained_validators = [v.ValidCloneUri(),
190 chained_validators = [v.ValidCloneUri(),
191 v.ValidRepoName(edit, old_data),
191 v.ValidRepoName(edit, old_data),
192 v.ValidPerms()]
192 v.ValidPerms()]
193 return _RepoForm
193 return _RepoForm
194
194
195
195
196 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
196 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
197 repo_groups=[]):
197 repo_groups=[]):
198 class _RepoForkForm(formencode.Schema):
198 class _RepoForkForm(formencode.Schema):
199 allow_extra_fields = True
199 allow_extra_fields = True
200 filter_extra_fields = False
200 filter_extra_fields = False
201 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
201 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
202 v.SlugifyName())
202 v.SlugifyName())
203 repo_group = v.OneOf(repo_groups, hideList=True)
203 repo_group = v.OneOf(repo_groups, hideList=True)
204 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
204 repo_type = All(v.ValidForkType(old_data), v.OneOf(supported_backends))
205 description = v.UnicodeString(strip=True, min=1, not_empty=True)
205 description = v.UnicodeString(strip=True, min=1, not_empty=True)
206 private = v.StringBoolean(if_missing=False)
206 private = v.StringBoolean(if_missing=False)
207 copy_permissions = v.StringBoolean(if_missing=False)
207 copy_permissions = v.StringBoolean(if_missing=False)
208 update_after_clone = v.StringBoolean(if_missing=False)
208 update_after_clone = v.StringBoolean(if_missing=False)
209 fork_parent_id = v.UnicodeString()
209 fork_parent_id = v.UnicodeString()
210 chained_validators = [v.ValidForkName(edit, old_data)]
210 chained_validators = [v.ValidForkName(edit, old_data)]
211
211
212 return _RepoForkForm
212 return _RepoForkForm
213
213
214
214
215 def RepoSettingsForm(edit=False, old_data={},
215 def RepoSettingsForm(edit=False, old_data={},
216 supported_backends=BACKENDS.keys(), repo_groups=[],
216 supported_backends=BACKENDS.keys(), repo_groups=[],
217 landing_revs=[]):
217 landing_revs=[]):
218 class _RepoForm(formencode.Schema):
218 class _RepoForm(formencode.Schema):
219 allow_extra_fields = True
219 allow_extra_fields = True
220 filter_extra_fields = False
220 filter_extra_fields = False
221 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
221 repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
222 v.SlugifyName())
222 v.SlugifyName())
223 description = v.UnicodeString(strip=True, min=1, not_empty=True)
223 description = v.UnicodeString(strip=True, min=1, not_empty=True)
224 repo_group = v.OneOf(repo_groups, hideList=True)
224 repo_group = v.OneOf(repo_groups, hideList=True)
225 private = v.StringBoolean(if_missing=False)
225 private = v.StringBoolean(if_missing=False)
226 landing_rev = v.OneOf(landing_revs, hideList=True)
226 landing_rev = v.OneOf(landing_revs, hideList=True)
227 chained_validators = [v.ValidRepoName(edit, old_data), v.ValidPerms(),
227 chained_validators = [v.ValidRepoName(edit, old_data), v.ValidPerms(),
228 v.ValidSettings()]
228 v.ValidSettings()]
229 return _RepoForm
229 return _RepoForm
230
230
231
231
232 def ApplicationSettingsForm():
232 def ApplicationSettingsForm():
233 class _ApplicationSettingsForm(formencode.Schema):
233 class _ApplicationSettingsForm(formencode.Schema):
234 allow_extra_fields = True
234 allow_extra_fields = True
235 filter_extra_fields = False
235 filter_extra_fields = False
236 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
236 rhodecode_title = v.UnicodeString(strip=True, min=1, not_empty=True)
237 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
237 rhodecode_realm = v.UnicodeString(strip=True, min=1, not_empty=True)
238 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
238 rhodecode_ga_code = v.UnicodeString(strip=True, min=1, not_empty=False)
239
239
240 return _ApplicationSettingsForm
240 return _ApplicationSettingsForm
241
241
242
242
243 def ApplicationUiSettingsForm():
243 def ApplicationUiSettingsForm():
244 class _ApplicationUiSettingsForm(formencode.Schema):
244 class _ApplicationUiSettingsForm(formencode.Schema):
245 allow_extra_fields = True
245 allow_extra_fields = True
246 filter_extra_fields = False
246 filter_extra_fields = False
247 web_push_ssl = v.OneOf(['true', 'false'], if_missing='false')
247 web_push_ssl = v.OneOf(['true', 'false'], if_missing='false')
248 paths_root_path = All(
248 paths_root_path = All(
249 v.ValidPath(),
249 v.ValidPath(),
250 v.UnicodeString(strip=True, min=1, not_empty=True)
250 v.UnicodeString(strip=True, min=1, not_empty=True)
251 )
251 )
252 hooks_changegroup_update = v.OneOf(['True', 'False'],
252 hooks_changegroup_update = v.OneOf(['True', 'False'],
253 if_missing=False)
253 if_missing=False)
254 hooks_changegroup_repo_size = v.OneOf(['True', 'False'],
254 hooks_changegroup_repo_size = v.OneOf(['True', 'False'],
255 if_missing=False)
255 if_missing=False)
256 hooks_changegroup_push_logger = v.OneOf(['True', 'False'],
256 hooks_changegroup_push_logger = v.OneOf(['True', 'False'],
257 if_missing=False)
257 if_missing=False)
258 hooks_preoutgoing_pull_logger = v.OneOf(['True', 'False'],
258 hooks_preoutgoing_pull_logger = v.OneOf(['True', 'False'],
259 if_missing=False)
259 if_missing=False)
260
260
261 return _ApplicationUiSettingsForm
261 return _ApplicationUiSettingsForm
262
262
263
263
264 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
264 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
265 class _DefaultPermissionsForm(formencode.Schema):
265 class _DefaultPermissionsForm(formencode.Schema):
266 allow_extra_fields = True
266 allow_extra_fields = True
267 filter_extra_fields = True
267 filter_extra_fields = True
268 overwrite_default = v.StringBoolean(if_missing=False)
268 overwrite_default = v.StringBoolean(if_missing=False)
269 anonymous = v.OneOf(['True', 'False'], if_missing=False)
269 anonymous = v.OneOf(['True', 'False'], if_missing=False)
270 default_perm = v.OneOf(perms_choices)
270 default_perm = v.OneOf(perms_choices)
271 default_register = v.OneOf(register_choices)
271 default_register = v.OneOf(register_choices)
272 default_create = v.OneOf(create_choices)
272 default_create = v.OneOf(create_choices)
273
273
274 return _DefaultPermissionsForm
274 return _DefaultPermissionsForm
275
275
276
276
277 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
277 def LdapSettingsForm(tls_reqcert_choices, search_scope_choices,
278 tls_kind_choices):
278 tls_kind_choices):
279 class _LdapSettingsForm(formencode.Schema):
279 class _LdapSettingsForm(formencode.Schema):
280 allow_extra_fields = True
280 allow_extra_fields = True
281 filter_extra_fields = True
281 filter_extra_fields = True
282 #pre_validators = [LdapLibValidator]
282 #pre_validators = [LdapLibValidator]
283 ldap_active = v.StringBoolean(if_missing=False)
283 ldap_active = v.StringBoolean(if_missing=False)
284 ldap_host = v.UnicodeString(strip=True,)
284 ldap_host = v.UnicodeString(strip=True,)
285 ldap_port = v.Number(strip=True,)
285 ldap_port = v.Number(strip=True,)
286 ldap_tls_kind = v.OneOf(tls_kind_choices)
286 ldap_tls_kind = v.OneOf(tls_kind_choices)
287 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
287 ldap_tls_reqcert = v.OneOf(tls_reqcert_choices)
288 ldap_dn_user = v.UnicodeString(strip=True,)
288 ldap_dn_user = v.UnicodeString(strip=True,)
289 ldap_dn_pass = v.UnicodeString(strip=True,)
289 ldap_dn_pass = v.UnicodeString(strip=True,)
290 ldap_base_dn = v.UnicodeString(strip=True,)
290 ldap_base_dn = v.UnicodeString(strip=True,)
291 ldap_filter = v.UnicodeString(strip=True,)
291 ldap_filter = v.UnicodeString(strip=True,)
292 ldap_search_scope = v.OneOf(search_scope_choices)
292 ldap_search_scope = v.OneOf(search_scope_choices)
293 ldap_attr_login = All(
293 ldap_attr_login = All(
294 v.AttrLoginValidator(),
294 v.AttrLoginValidator(),
295 v.UnicodeString(strip=True,)
295 v.UnicodeString(strip=True,)
296 )
296 )
297 ldap_attr_firstname = v.UnicodeString(strip=True,)
297 ldap_attr_firstname = v.UnicodeString(strip=True,)
298 ldap_attr_lastname = v.UnicodeString(strip=True,)
298 ldap_attr_lastname = v.UnicodeString(strip=True,)
299 ldap_attr_email = v.UnicodeString(strip=True,)
299 ldap_attr_email = v.UnicodeString(strip=True,)
300
300
301 return _LdapSettingsForm
301 return _LdapSettingsForm
302
302
303
303
304 def UserExtraEmailForm():
304 def UserExtraEmailForm():
305 class _UserExtraEmailForm(formencode.Schema):
305 class _UserExtraEmailForm(formencode.Schema):
306 email = All(v.UniqSystemEmail(), v.Email)
306 email = All(v.UniqSystemEmail(), v.Email)
307
307
308 return _UserExtraEmailForm No newline at end of file
308 return _UserExtraEmailForm
General Comments 0
You need to be logged in to leave comments. Login now