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