##// END OF EJS Templates
Simplified last_login call on user, and changed login to use User model directly
marcink -
r1400:0d7b56b9 beta
parent child Browse files
Show More
@@ -1,150 +1,151 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.login
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Login controller for rhodeocode
7 7
8 8 :created_on: Apr 22, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import formencode
28 28
29 29 from formencode import htmlfill
30 30
31 31 from pylons.i18n.translation import _
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons import request, response, session, tmpl_context as c, url
34 34
35 35 import rhodecode.lib.helpers as h
36 36 from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator
37 37 from rhodecode.lib.base import BaseController, render
38 from rhodecode.model.db import User
38 39 from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm
39 40 from rhodecode.model.user import UserModel
40 41
41 42
42 43 log = logging.getLogger(__name__)
43 44
44 45
45 46 class LoginController(BaseController):
46 47
47 48 def __before__(self):
48 49 super(LoginController, self).__before__()
49 50
50 51 def index(self):
51 52 #redirect if already logged in
52 53 c.came_from = request.GET.get('came_from', None)
53 54
54 55 if self.rhodecode_user.is_authenticated \
55 56 and self.rhodecode_user.username != 'default':
56 57
57 58 return redirect(url('home'))
58 59
59 60 if request.POST:
60 61 #import Login Form validator class
61 62 login_form = LoginForm()
62 63 try:
63 64 c.form_result = login_form.to_python(dict(request.POST))
64 65 #form checks for username/password, now we're authenticated
65 66 username = c.form_result['username']
66 user = UserModel().get_by_username(username,
67 user = User.by_username(username,
67 68 case_insensitive=True)
68 69 auth_user = AuthUser(user.user_id)
69 70 auth_user.set_authenticated()
70 71 session['rhodecode_user'] = auth_user
71 72 session.save()
72 73
73 74 log.info('user %s is now authenticated and stored in session',
74 75 username)
75 76 user.update_lastlogin()
76 77
77 78 if c.came_from:
78 79 return redirect(c.came_from)
79 80 else:
80 81 return redirect(url('home'))
81 82
82 83 except formencode.Invalid, errors:
83 84 return htmlfill.render(
84 85 render('/login.html'),
85 86 defaults=errors.value,
86 87 errors=errors.error_dict or {},
87 88 prefix_error=False,
88 89 encoding="UTF-8")
89 90
90 91 return render('/login.html')
91 92
92 93 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate',
93 94 'hg.register.manual_activate')
94 95 def register(self):
95 96 user_model = UserModel()
96 97 c.auto_active = False
97 98 for perm in user_model.get_by_username('default',
98 99 cache=False).user_perms:
99 100 if perm.permission.permission_name == 'hg.register.auto_activate':
100 101 c.auto_active = True
101 102 break
102 103
103 104 if request.POST:
104 105
105 106 register_form = RegisterForm()()
106 107 try:
107 108 form_result = register_form.to_python(dict(request.POST))
108 109 form_result['active'] = c.auto_active
109 110 user_model.create_registration(form_result)
110 111 h.flash(_('You have successfully registered into rhodecode'),
111 112 category='success')
112 113 return redirect(url('login_home'))
113 114
114 115 except formencode.Invalid, errors:
115 116 return htmlfill.render(
116 117 render('/register.html'),
117 118 defaults=errors.value,
118 119 errors=errors.error_dict or {},
119 120 prefix_error=False,
120 121 encoding="UTF-8")
121 122
122 123 return render('/register.html')
123 124
124 125 def password_reset(self):
125 126 user_model = UserModel()
126 127 if request.POST:
127 128
128 129 password_reset_form = PasswordResetForm()()
129 130 try:
130 131 form_result = password_reset_form.to_python(dict(request.POST))
131 132 user_model.reset_password(form_result)
132 133 h.flash(_('Your new password was sent'),
133 134 category='success')
134 135 return redirect(url('login_home'))
135 136
136 137 except formencode.Invalid, errors:
137 138 return htmlfill.render(
138 139 render('/password_reset.html'),
139 140 defaults=errors.value,
140 141 errors=errors.error_dict or {},
141 142 prefix_error=False,
142 143 encoding="UTF-8")
143 144
144 145 return render('/password_reset.html')
145 146
146 147 def logout(self):
147 148 del session['rhodecode_user']
148 149 session.save()
149 150 log.info('Logging out and setting user as Empty')
150 151 redirect(url('home'))
@@ -1,790 +1,790 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.db
4 4 ~~~~~~~~~~~~~~~~~~
5 5
6 6 Database Models for RhodeCode
7 7
8 8 :created_on: Apr 08, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import os
27 27 import logging
28 28 import datetime
29 29 import traceback
30 30 from datetime import date
31 31
32 32 from sqlalchemy import *
33 33 from sqlalchemy.exc import DatabaseError
34 34 from sqlalchemy.orm import relationship, backref, joinedload, class_mapper
35 35 from sqlalchemy.orm.interfaces import MapperExtension
36 36
37 37 from beaker.cache import cache_region, region_invalidate
38 38
39 39 from vcs import get_backend
40 40 from vcs.utils.helpers import get_scm
41 41 from vcs.exceptions import RepositoryError, VCSError
42 42 from vcs.utils.lazy import LazyProperty
43 43 from vcs.nodes import FileNode
44 44
45 45 from rhodecode.lib import str2bool, json
46 46 from rhodecode.model.meta import Base, Session
47 47 from rhodecode.model.caching_query import FromCache
48 48
49 49 log = logging.getLogger(__name__)
50 50
51 51 #==============================================================================
52 52 # BASE CLASSES
53 53 #==============================================================================
54 54
55 55 class ModelSerializer(json.JSONEncoder):
56 56 """
57 57 Simple Serializer for JSON,
58 58
59 59 usage::
60 60
61 61 to make object customized for serialization implement a __json__
62 62 method that will return a dict for serialization into json
63 63
64 64 example::
65 65
66 66 class Task(object):
67 67
68 68 def __init__(self, name, value):
69 69 self.name = name
70 70 self.value = value
71 71
72 72 def __json__(self):
73 73 return dict(name=self.name,
74 74 value=self.value)
75 75
76 76 """
77 77
78 78 def default(self, obj):
79 79
80 80 if hasattr(obj, '__json__'):
81 81 return obj.__json__()
82 82 else:
83 83 return json.JSONEncoder.default(self, obj)
84 84
85 85 class BaseModel(object):
86 86 """Base Model for all classess
87 87
88 88 """
89 89
90 90 @classmethod
91 91 def _get_keys(cls):
92 92 """return column names for this model """
93 93 return class_mapper(cls).c.keys()
94 94
95 95 def get_dict(self):
96 96 """return dict with keys and values corresponding
97 97 to this model data """
98 98
99 99 d = {}
100 100 for k in self._get_keys():
101 101 d[k] = getattr(self, k)
102 102 return d
103 103
104 104 def get_appstruct(self):
105 105 """return list with keys and values tupples corresponding
106 106 to this model data """
107 107
108 108 l = []
109 109 for k in self._get_keys():
110 110 l.append((k, getattr(self, k),))
111 111 return l
112 112
113 113 def populate_obj(self, populate_dict):
114 114 """populate model with data from given populate_dict"""
115 115
116 116 for k in self._get_keys():
117 117 if k in populate_dict:
118 118 setattr(self, k, populate_dict[k])
119 119
120 120 @classmethod
121 121 def query(cls):
122 122 return Session.query(cls)
123 123
124 124 @classmethod
125 125 def get(cls, id_):
126 126 return Session.query(cls).get(id_)
127 127
128 128
129 129 class RhodeCodeSettings(Base, BaseModel):
130 130 __tablename__ = 'rhodecode_settings'
131 131 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing':True})
132 132 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
133 133 app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
134 134 app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
135 135
136 136 def __init__(self, k='', v=''):
137 137 self.app_settings_name = k
138 138 self.app_settings_value = v
139 139
140 140 def __repr__(self):
141 141 return "<%s('%s:%s')>" % (self.__class__.__name__,
142 142 self.app_settings_name, self.app_settings_value)
143 143
144 144
145 145 @classmethod
146 146 def get_by_name(cls, ldap_key):
147 147 return Session.query(cls)\
148 148 .filter(cls.app_settings_name == ldap_key).scalar()
149 149
150 150 @classmethod
151 151 def get_app_settings(cls, cache=False):
152 152
153 153 ret = Session.query(cls)
154 154
155 155 if cache:
156 156 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
157 157
158 158 if not ret:
159 159 raise Exception('Could not get application settings !')
160 160 settings = {}
161 161 for each in ret:
162 162 settings['rhodecode_' + each.app_settings_name] = \
163 163 each.app_settings_value
164 164
165 165 return settings
166 166
167 167 @classmethod
168 168 def get_ldap_settings(cls, cache=False):
169 169 ret = Session.query(cls)\
170 170 .filter(cls.app_settings_name.startswith('ldap_'))\
171 171 .all()
172 172 fd = {}
173 173 for row in ret:
174 174 fd.update({row.app_settings_name:row.app_settings_value})
175 175
176 176 fd.update({'ldap_active':str2bool(fd.get('ldap_active'))})
177 177
178 178 return fd
179 179
180 180
181 181 class RhodeCodeUi(Base, BaseModel):
182 182 __tablename__ = 'rhodecode_ui'
183 183 __table_args__ = {'extend_existing':True}
184 184 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
185 185 ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
186 186 ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
187 187 ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
188 188 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
189 189
190 190
191 191 @classmethod
192 192 def get_by_key(cls, key):
193 193 return Session.query(cls).filter(cls.ui_key == key)
194 194
195 195
196 196 class User(Base, BaseModel):
197 197 __tablename__ = 'users'
198 198 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
199 199 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
200 200 username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
201 201 password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
202 202 active = Column("active", Boolean(), nullable=True, unique=None, default=None)
203 203 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
204 204 name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
205 205 lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
206 206 email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
207 207 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
208 208 ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
209 209 api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
210 210
211 211 user_log = relationship('UserLog', cascade='all')
212 212 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
213 213
214 214 repositories = relationship('Repository')
215 215 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
216 216 repo_to_perm = relationship('RepoToPerm', primaryjoin='RepoToPerm.user_id==User.user_id', cascade='all')
217 217
218 218 group_member = relationship('UsersGroupMember', cascade='all')
219 219
220 220 @property
221 221 def full_contact(self):
222 222 return '%s %s <%s>' % (self.name, self.lastname, self.email)
223 223
224 224 @property
225 225 def short_contact(self):
226 226 return '%s %s' % (self.name, self.lastname)
227 227
228
229 228 @property
230 229 def is_admin(self):
231 230 return self.admin
232 231
233 232 def __repr__(self):
234 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
235 self.user_id, self.username)
233 try:
234 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
235 self.user_id, self.username)
236 except:
237 return self.__class__.__name__
236 238
237 239 @classmethod
238 def by_username(cls, username):
239 return Session.query(cls).filter(cls.username == username).one()
240
240 def by_username(cls, username, case_insensitive=False):
241 if case_insensitive:
242 return Session.query(cls).filter(cls.username.like(username)).one()
243 else:
244 return Session.query(cls).filter(cls.username == username).one()
241 245
242 246 def update_lastlogin(self):
243 247 """Update user lastlogin"""
244 248
245 try:
246 session = Session.object_session(self)
247 self.last_login = datetime.datetime.now()
248 session.add(self)
249 session.commit()
250 log.debug('updated user %s lastlogin', self.username)
251 except (DatabaseError,):
252 session.rollback()
249 self.last_login = datetime.datetime.now()
250 Session.add(self)
251 Session.commit()
252 log.debug('updated user %s lastlogin', self.username)
253 253
254 254
255 255 class UserLog(Base, BaseModel):
256 256 __tablename__ = 'user_logs'
257 257 __table_args__ = {'extend_existing':True}
258 258 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
259 259 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
260 260 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
261 261 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
262 262 user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
263 263 action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
264 264 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
265 265
266 266 @property
267 267 def action_as_day(self):
268 268 return date(*self.action_date.timetuple()[:3])
269 269
270 270 user = relationship('User')
271 271 repository = relationship('Repository')
272 272
273 273
274 274 class UsersGroup(Base, BaseModel):
275 275 __tablename__ = 'users_groups'
276 276 __table_args__ = {'extend_existing':True}
277 277
278 278 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
279 279 users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
280 280 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
281 281
282 282 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
283 283
284 284
285 285 @classmethod
286 286 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
287 287 if case_insensitive:
288 288 gr = Session.query(cls)\
289 289 .filter(cls.users_group_name.ilike(group_name))
290 290 else:
291 291 gr = Session.query(UsersGroup)\
292 292 .filter(UsersGroup.users_group_name == group_name)
293 293 if cache:
294 294 gr = gr.options(FromCache("sql_cache_short",
295 295 "get_user_%s" % group_name))
296 296 return gr.scalar()
297 297
298 298 class UsersGroupMember(Base, BaseModel):
299 299 __tablename__ = 'users_groups_members'
300 300 __table_args__ = {'extend_existing':True}
301 301
302 302 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
303 303 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
304 304 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
305 305
306 306 user = relationship('User', lazy='joined')
307 307 users_group = relationship('UsersGroup')
308 308
309 309 def __init__(self, gr_id='', u_id=''):
310 310 self.users_group_id = gr_id
311 311 self.user_id = u_id
312 312
313 313 class Repository(Base, BaseModel):
314 314 __tablename__ = 'repositories'
315 315 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
316 316
317 317 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
318 318 repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
319 319 clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
320 320 repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
321 321 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
322 322 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
323 323 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
324 324 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
325 325 description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
326 326 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
327 327
328 328 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
329 329 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
330 330
331 331
332 332 user = relationship('User')
333 333 fork = relationship('Repository', remote_side=repo_id)
334 334 group = relationship('Group')
335 335 repo_to_perm = relationship('RepoToPerm', cascade='all', order_by='RepoToPerm.repo_to_perm_id')
336 336 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
337 337 stats = relationship('Statistics', cascade='all', uselist=False)
338 338
339 339 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
340 340
341 341 logs = relationship('UserLog', cascade='all')
342 342
343 343 def __repr__(self):
344 344 return "<%s('%s:%s')>" % (self.__class__.__name__,
345 345 self.repo_id, self.repo_name)
346 346
347 347 @classmethod
348 348 def by_repo_name(cls, repo_name):
349 349 q = Session.query(cls).filter(cls.repo_name == repo_name)
350 350
351 351 q = q.options(joinedload(Repository.fork))\
352 352 .options(joinedload(Repository.user))\
353 353 .options(joinedload(Repository.group))\
354 354
355 355 return q.one()
356 356
357 357 @classmethod
358 358 def get_repo_forks(cls, repo_id):
359 359 return Session.query(cls).filter(Repository.fork_id == repo_id)
360 360
361 361 @property
362 362 def just_name(self):
363 363 return self.repo_name.split(os.sep)[-1]
364 364
365 365 @property
366 366 def groups_with_parents(self):
367 367 groups = []
368 368 if self.group is None:
369 369 return groups
370 370
371 371 cur_gr = self.group
372 372 groups.insert(0, cur_gr)
373 373 while 1:
374 374 gr = getattr(cur_gr, 'parent_group', None)
375 375 cur_gr = cur_gr.parent_group
376 376 if gr is None:
377 377 break
378 378 groups.insert(0, gr)
379 379
380 380 return groups
381 381
382 382 @property
383 383 def groups_and_repo(self):
384 384 return self.groups_with_parents, self.just_name
385 385
386 386 @LazyProperty
387 387 def repo_path(self):
388 388 """
389 389 Returns base full path for that repository means where it actually
390 390 exists on a filesystem
391 391 """
392 392 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/')
393 393 q.options(FromCache("sql_cache_short", "repository_repo_path"))
394 394 return q.one().ui_value
395 395
396 396 @property
397 397 def repo_full_path(self):
398 398 p = [self.repo_path]
399 399 # we need to split the name by / since this is how we store the
400 400 # names in the database, but that eventually needs to be converted
401 401 # into a valid system path
402 402 p += self.repo_name.split('/')
403 403 return os.path.join(*p)
404 404
405 405 @property
406 406 def _ui(self):
407 407 """
408 408 Creates an db based ui object for this repository
409 409 """
410 410 from mercurial import ui
411 411 from mercurial import config
412 412 baseui = ui.ui()
413 413
414 414 #clean the baseui object
415 415 baseui._ocfg = config.config()
416 416 baseui._ucfg = config.config()
417 417 baseui._tcfg = config.config()
418 418
419 419
420 420 ret = Session.query(RhodeCodeUi)\
421 421 .options(FromCache("sql_cache_short",
422 422 "repository_repo_ui")).all()
423 423
424 424 hg_ui = ret
425 425 for ui_ in hg_ui:
426 426 if ui_.ui_active:
427 427 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
428 428 ui_.ui_key, ui_.ui_value)
429 429 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
430 430
431 431 return baseui
432 432
433 433 #==========================================================================
434 434 # SCM CACHE INSTANCE
435 435 #==========================================================================
436 436
437 437 @property
438 438 def invalidate(self):
439 439 """
440 440 Returns Invalidation object if this repo should be invalidated
441 441 None otherwise. `cache_active = False` means that this cache
442 442 state is not valid and needs to be invalidated
443 443 """
444 444 return Session.query(CacheInvalidation)\
445 445 .filter(CacheInvalidation.cache_key == self.repo_name)\
446 446 .filter(CacheInvalidation.cache_active == False)\
447 447 .scalar()
448 448
449 449 @property
450 450 def set_invalidate(self):
451 451 """
452 452 set a cache for invalidation for this instance
453 453 """
454 454 inv = Session.query(CacheInvalidation)\
455 455 .filter(CacheInvalidation.cache_key == self.repo_name)\
456 456 .scalar()
457 457
458 458 if inv is None:
459 459 inv = CacheInvalidation(self.repo_name)
460 460 inv.cache_active = True
461 461 Session.add(inv)
462 462 Session.commit()
463 463
464 464 @property
465 465 def scm_instance(self):
466 return self.__get_instance(self.repo_name)
466 return self.__get_instance()
467 467
468 468 @property
469 469 def scm_instance_cached(self):
470 470 @cache_region('long_term')
471 471 def _c(repo_name):
472 return self.__get_instance(repo_name)
472 return self.__get_instance()
473 473
474 474 inv = self.invalidate
475 475 if inv:
476 476 region_invalidate(_c, None, self.repo_name)
477 477 #update our cache
478 478 inv.cache_key.cache_active = True
479 479 Session.add(inv)
480 480 Session.commit()
481 481
482 482 return _c(self.repo_name)
483 483
484 def __get_instance(self, repo_name):
484 def __get_instance(self):
485 485
486 486 repo_full_path = self.repo_full_path
487 487
488 488 try:
489 489 alias = get_scm(repo_full_path)[0]
490 490 log.debug('Creating instance of %s repository', alias)
491 491 backend = get_backend(alias)
492 492 except VCSError:
493 493 log.error(traceback.format_exc())
494 494 log.error('Perhaps this repository is in db and not in '
495 495 'filesystem run rescan repositories with '
496 496 '"destroy old data " option from admin panel')
497 497 return
498 498
499 499 if alias == 'hg':
500 500 repo = backend(repo_full_path, create=False,
501 501 baseui=self._ui)
502 502 #skip hidden web repository
503 503 if repo._get_hidden():
504 504 return
505 505 else:
506 506 repo = backend(repo_full_path, create=False)
507 507
508 508 return repo
509 509
510 510
511 511 class Group(Base, BaseModel):
512 512 __tablename__ = 'groups'
513 513 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
514 514 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
515 515 __mapper_args__ = {'order_by':'group_name'}
516 516
517 517 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
518 518 group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
519 519 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
520 520 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
521 521
522 522 parent_group = relationship('Group', remote_side=group_id)
523 523
524 524
525 525 def __init__(self, group_name='', parent_group=None):
526 526 self.group_name = group_name
527 527 self.parent_group = parent_group
528 528
529 529 def __repr__(self):
530 530 return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
531 531 self.group_name)
532 532
533 533 @classmethod
534 534 def url_sep(cls):
535 535 return '/'
536 536
537 537 @property
538 538 def parents(self):
539 539 parents_recursion_limit = 5
540 540 groups = []
541 541 if self.parent_group is None:
542 542 return groups
543 543 cur_gr = self.parent_group
544 544 groups.insert(0, cur_gr)
545 545 cnt = 0
546 546 while 1:
547 547 cnt += 1
548 548 gr = getattr(cur_gr, 'parent_group', None)
549 549 cur_gr = cur_gr.parent_group
550 550 if gr is None:
551 551 break
552 552 if cnt == parents_recursion_limit:
553 553 # this will prevent accidental infinit loops
554 554 log.error('group nested more than %s' %
555 555 parents_recursion_limit)
556 556 break
557 557
558 558 groups.insert(0, gr)
559 559 return groups
560 560
561 561 @property
562 562 def children(self):
563 563 return Session.query(Group).filter(Group.parent_group == self)
564 564
565 565 @property
566 566 def full_path(self):
567 567 return Group.url_sep().join([g.group_name for g in self.parents] +
568 568 [self.group_name])
569 569
570 570 @property
571 571 def repositories(self):
572 572 return Session.query(Repository).filter(Repository.group == self)
573 573
574 574 @property
575 575 def repositories_recursive_count(self):
576 576 cnt = self.repositories.count()
577 577
578 578 def children_count(group):
579 579 cnt = 0
580 580 for child in group.children:
581 581 cnt += child.repositories.count()
582 582 cnt += children_count(child)
583 583 return cnt
584 584
585 585 return cnt + children_count(self)
586 586
587 587 class Permission(Base, BaseModel):
588 588 __tablename__ = 'permissions'
589 589 __table_args__ = {'extend_existing':True}
590 590 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
591 591 permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
592 592 permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
593 593
594 594 def __repr__(self):
595 595 return "<%s('%s:%s')>" % (self.__class__.__name__,
596 596 self.permission_id, self.permission_name)
597 597
598 598 @classmethod
599 599 def get_by_key(cls, key):
600 600 return Session.query(cls).filter(cls.permission_name == key).scalar()
601 601
602 602 class RepoToPerm(Base, BaseModel):
603 603 __tablename__ = 'repo_to_perm'
604 604 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':True})
605 605 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
606 606 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
607 607 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
608 608 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
609 609
610 610 user = relationship('User')
611 611 permission = relationship('Permission')
612 612 repository = relationship('Repository')
613 613
614 614 class UserToPerm(Base, BaseModel):
615 615 __tablename__ = 'user_to_perm'
616 616 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
617 617 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
618 618 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
619 619 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
620 620
621 621 user = relationship('User')
622 622 permission = relationship('Permission')
623 623
624 624 @classmethod
625 625 def has_perm(cls, user_id, perm):
626 626 if not isinstance(perm, Permission):
627 627 raise Exception('perm needs to be an instance of Permission class')
628 628
629 629 return Session.query(cls).filter(cls.user_id == user_id)\
630 630 .filter(cls.permission == perm).scalar() is not None
631 631
632 632 @classmethod
633 633 def grant_perm(cls, user_id, perm):
634 634 if not isinstance(perm, Permission):
635 635 raise Exception('perm needs to be an instance of Permission class')
636 636
637 637 new = cls()
638 638 new.user_id = user_id
639 639 new.permission = perm
640 640 try:
641 641 Session.add(new)
642 642 Session.commit()
643 643 except:
644 644 Session.rollback()
645 645
646 646
647 647 @classmethod
648 648 def revoke_perm(cls, user_id, perm):
649 649 if not isinstance(perm, Permission):
650 650 raise Exception('perm needs to be an instance of Permission class')
651 651
652 652 try:
653 653 Session.query(cls).filter(cls.user_id == user_id)\
654 654 .filter(cls.permission == perm).delete()
655 655 Session.commit()
656 656 except:
657 657 Session.rollback()
658 658
659 659 class UsersGroupRepoToPerm(Base, BaseModel):
660 660 __tablename__ = 'users_group_repo_to_perm'
661 661 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
662 662 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
663 663 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
664 664 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
665 665 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
666 666
667 667 users_group = relationship('UsersGroup')
668 668 permission = relationship('Permission')
669 669 repository = relationship('Repository')
670 670
671 671
672 672 class UsersGroupToPerm(Base, BaseModel):
673 673 __tablename__ = 'users_group_to_perm'
674 674 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
675 675 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
676 676 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
677 677
678 678 users_group = relationship('UsersGroup')
679 679 permission = relationship('Permission')
680 680
681 681
682 682 @classmethod
683 683 def has_perm(cls, users_group_id, perm):
684 684 if not isinstance(perm, Permission):
685 685 raise Exception('perm needs to be an instance of Permission class')
686 686
687 687 return Session.query(cls).filter(cls.users_group_id ==
688 688 users_group_id)\
689 689 .filter(cls.permission == perm)\
690 690 .scalar() is not None
691 691
692 692 @classmethod
693 693 def grant_perm(cls, users_group_id, perm):
694 694 if not isinstance(perm, Permission):
695 695 raise Exception('perm needs to be an instance of Permission class')
696 696
697 697 new = cls()
698 698 new.users_group_id = users_group_id
699 699 new.permission = perm
700 700 try:
701 701 Session.add(new)
702 702 Session.commit()
703 703 except:
704 704 Session.rollback()
705 705
706 706
707 707 @classmethod
708 708 def revoke_perm(cls, users_group_id, perm):
709 709 if not isinstance(perm, Permission):
710 710 raise Exception('perm needs to be an instance of Permission class')
711 711
712 712 try:
713 713 Session.query(cls).filter(cls.users_group_id == users_group_id)\
714 714 .filter(cls.permission == perm).delete()
715 715 Session.commit()
716 716 except:
717 717 Session.rollback()
718 718
719 719
720 720 class GroupToPerm(Base, BaseModel):
721 721 __tablename__ = 'group_to_perm'
722 722 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
723 723
724 724 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
725 725 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
726 726 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
727 727 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
728 728
729 729 user = relationship('User')
730 730 permission = relationship('Permission')
731 731 group = relationship('Group')
732 732
733 733 class Statistics(Base, BaseModel):
734 734 __tablename__ = 'statistics'
735 735 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
736 736 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
737 737 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
738 738 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
739 739 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
740 740 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
741 741 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
742 742
743 743 repository = relationship('Repository', single_parent=True)
744 744
745 745 class UserFollowing(Base, BaseModel):
746 746 __tablename__ = 'user_followings'
747 747 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
748 748 UniqueConstraint('user_id', 'follows_user_id')
749 749 , {'extend_existing':True})
750 750
751 751 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
752 752 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
753 753 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
754 754 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
755 755 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
756 756
757 757 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
758 758
759 759 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
760 760 follows_repository = relationship('Repository', order_by='Repository.repo_name')
761 761
762 762
763 763 @classmethod
764 764 def get_repo_followers(cls, repo_id):
765 765 return Session.query(cls).filter(cls.follows_repo_id == repo_id)
766 766
767 767 class CacheInvalidation(Base, BaseModel):
768 768 __tablename__ = 'cache_invalidation'
769 769 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
770 770 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
771 771 cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
772 772 cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
773 773 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
774 774
775 775
776 776 def __init__(self, cache_key, cache_args=''):
777 777 self.cache_key = cache_key
778 778 self.cache_args = cache_args
779 779 self.cache_active = False
780 780
781 781 def __repr__(self):
782 782 return "<%s('%s:%s')>" % (self.__class__.__name__,
783 783 self.cache_id, self.cache_key)
784 784
785 785 class DbMigrateVersion(Base, BaseModel):
786 786 __tablename__ = 'db_migrate_version'
787 787 __table_args__ = {'extend_existing':True}
788 788 repository_id = Column('repository_id', String(250), primary_key=True)
789 789 repository_path = Column('repository_path', Text)
790 790 version = Column('version', Integer)
General Comments 0
You need to be logged in to leave comments. Login now