##// END OF EJS Templates
fixed Example celery config to ampq,...
marcink -
r752:89b9037d beta
parent child Browse files
Show More
@@ -1,77 +1,79
1 1 # List of modules to import when celery starts.
2 2 import sys
3 3 import os
4 4 import ConfigParser
5 5 root = os.getcwd()
6 6
7 7 PYLONS_CONFIG_NAME = 'production.ini'
8 8
9 9 sys.path.append(root)
10 10 config = ConfigParser.ConfigParser({'here':root})
11 11 config.read('%s/%s' % (root, PYLONS_CONFIG_NAME))
12 12 PYLONS_CONFIG = config
13 13
14 14 CELERY_IMPORTS = ("rhodecode.lib.celerylib.tasks",)
15 15
16 16 ## Result store settings.
17 CELERY_RESULT_BACKEND = "database"
18 CELERY_RESULT_DBURI = dict(config.items('app:main'))['sqlalchemy.db1.url']
17 CELERY_RESULT_BACKEND = "amqp"
18 CELERY_AMQP_TASK_RESULT_EXPIRES = 18000 # 5 hours.
19
20 #CELERY_RESULT_DBURI = dict(config.items('app:main'))['sqlalchemy.db1.url']
19 21 CELERY_RESULT_SERIALIZER = 'json'
20 22
21 23
22 24 BROKER_CONNECTION_MAX_RETRIES = 30
23 25
24 26 ## Broker settings.
25 27 BROKER_HOST = "localhost"
26 28 BROKER_PORT = 5672
27 29 BROKER_VHOST = "rabbitmqhost"
28 30 BROKER_USER = "rabbitmq"
29 31 BROKER_PASSWORD = "qweqwe"
30 32
31 33 ## Worker settings
32 34 ## If you're doing mostly I/O you can have more processes,
33 35 ## but if mostly spending CPU, try to keep it close to the
34 36 ## number of CPUs on your machine. If not set, the number of CPUs/cores
35 37 ## available will be used.
36 38 CELERYD_CONCURRENCY = 2
37 39 # CELERYD_LOG_FILE = "celeryd.log"
38 40 CELERYD_LOG_LEVEL = "DEBUG"
39 41 CELERYD_MAX_TASKS_PER_CHILD = 3
40 42
41 43 #Tasks will never be sent to the queue, but executed locally instead.
42 44 CELERY_ALWAYS_EAGER = False
43 45 if PYLONS_CONFIG_NAME == 'test.ini':
44 46 #auto eager for tests
45 47 CELERY_ALWAYS_EAGER = True
46 48
47 49 #===============================================================================
48 50 # EMAIL SETTINGS
49 51 #===============================================================================
50 52 pylons_email_config = dict(config.items('DEFAULT'))
51 53
52 54 CELERY_SEND_TASK_ERROR_EMAILS = True
53 55
54 56 #List of (name, email_address) tuples for the admins that should receive error e-mails.
55 57 ADMINS = [('Administrator', pylons_email_config.get('email_to'))]
56 58
57 59 #The e-mail address this worker sends e-mails from. Default is "celery@localhost".
58 60 SERVER_EMAIL = pylons_email_config.get('error_email_from')
59 61
60 62 #The mail server to use. Default is "localhost".
61 63 MAIL_HOST = pylons_email_config.get('smtp_server')
62 64
63 65 #Username (if required) to log on to the mail server with.
64 66 MAIL_HOST_USER = pylons_email_config.get('smtp_username')
65 67
66 68 #Password (if required) to log on to the mail server with.
67 69 MAIL_HOST_PASSWORD = pylons_email_config.get('smtp_password')
68 70
69 71 MAIL_PORT = pylons_email_config.get('smtp_port')
70 72
71 73
72 74 #===============================================================================
73 75 # INSTRUCTIONS FOR RABBITMQ
74 76 #===============================================================================
75 77 # rabbitmqctl add_user rabbitmq qweqwe
76 78 # rabbitmqctl add_vhost rabbitmqhost
77 79 # rabbitmqctl set_permissions -p rabbitmqhost rabbitmq ".*" ".*" ".*"
@@ -1,324 +1,324
1 1 from celery.decorators import task
2 2
3 3 import os
4 4 import traceback
5 5 from time import mktime
6 6
7 7 from operator import itemgetter
8 8 from pylons.i18n.translation import _
9 9 from rhodecode.lib.celerylib import run_task, locked_task
10 10 from rhodecode.lib.helpers import person
11 11 from rhodecode.lib.smtp_mailer import SmtpMailer
12 12 from rhodecode.lib.utils import OrderedDict
13 13 from vcs.backends import get_repo
14 14 from rhodecode.model.db import RhodeCodeUi
15 15
16 16 try:
17 17 import json
18 18 except ImportError:
19 19 #python 2.5 compatibility
20 20 import simplejson as json
21 21
22 22 try:
23 23 from celeryconfig import PYLONS_CONFIG as config
24 24 celery_on = True
25 25 except ImportError:
26 26 #if celeryconfig is not present let's just load our pylons
27 27 #config instead
28 28 from pylons import config
29 29 celery_on = False
30 30
31 31
32 32 __all__ = ['whoosh_index', 'get_commits_stats',
33 33 'reset_user_password', 'send_email']
34 34
35 35 def get_session():
36 36 if celery_on:
37 37 from sqlalchemy import engine_from_config
38 38 from sqlalchemy.orm import sessionmaker, scoped_session
39 39 engine = engine_from_config(dict(config.items('app:main')),
40 40 'sqlalchemy.db1.')
41 41 sa = scoped_session(sessionmaker(bind=engine))
42 42 else:
43 43 #If we don't use celery reuse our current application Session
44 44 from rhodecode.model.meta import Session
45 45 sa = Session()
46 46
47 47 return sa
48 48
49 49 def get_repos_path():
50 50 sa = get_session()
51 51 q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
52 52 return q.ui_value
53 53
54 54 @task
55 55 @locked_task
56 56 def whoosh_index(repo_location, full_index):
57 57 log = whoosh_index.get_logger()
58 58 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
59 59 index_location = dict(config.items('app:main'))['index_dir']
60 60 WhooshIndexingDaemon(index_location=index_location,
61 61 repo_location=repo_location).run(full_index=full_index)
62 62
63 63 @task
64 64 @locked_task
65 65 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
66 66 from rhodecode.model.db import Statistics, Repository
67 67 log = get_commits_stats.get_logger()
68 68
69 69 #for js data compatibilty
70 70 author_key_cleaner = lambda k: person(k).replace('"', "")
71 71
72 72 commits_by_day_author_aggregate = {}
73 73 commits_by_day_aggregate = {}
74 74 repos_path = get_repos_path()
75 75 p = os.path.join(repos_path, repo_name)
76 76 repo = get_repo(p)
77 77
78 78 skip_date_limit = True
79 79 parse_limit = 250 #limit for single task changeset parsing optimal for
80 80 last_rev = 0
81 81 last_cs = None
82 82 timegetter = itemgetter('time')
83 83
84 84 sa = get_session()
85 85
86 86 dbrepo = sa.query(Repository)\
87 87 .filter(Repository.repo_name == repo_name).scalar()
88 88 cur_stats = sa.query(Statistics)\
89 89 .filter(Statistics.repository == dbrepo).scalar()
90 90 if cur_stats:
91 91 last_rev = cur_stats.stat_on_revision
92 92 if not repo.revisions:
93 93 return True
94 94
95 95 if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
96 96 #pass silently without any work if we're not on first revision or
97 97 #current state of parsing revision(from db marker) is the last revision
98 98 return True
99 99
100 100 if cur_stats:
101 101 commits_by_day_aggregate = OrderedDict(
102 102 json.loads(
103 103 cur_stats.commit_activity_combined))
104 104 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
105 105
106 106 log.debug('starting parsing %s', parse_limit)
107 107 lmktime = mktime
108 108
109 109 for cnt, rev in enumerate(repo.revisions[last_rev:]):
110 110 last_cs = cs = repo.get_changeset(rev)
111 111 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
112 112 cs.date.timetuple()[2])
113 113 timetupple = [int(x) for x in k.split('-')]
114 114 timetupple.extend([0 for _ in xrange(6)])
115 115 k = lmktime(timetupple)
116 116 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
117 117 try:
118 118 l = [timegetter(x) for x in commits_by_day_author_aggregate\
119 119 [author_key_cleaner(cs.author)]['data']]
120 120 time_pos = l.index(k)
121 121 except ValueError:
122 122 time_pos = False
123 123
124 124 if time_pos >= 0 and time_pos is not False:
125 125
126 126 datadict = commits_by_day_author_aggregate\
127 127 [author_key_cleaner(cs.author)]['data'][time_pos]
128 128
129 129 datadict["commits"] += 1
130 130 datadict["added"] += len(cs.added)
131 131 datadict["changed"] += len(cs.changed)
132 132 datadict["removed"] += len(cs.removed)
133 133
134 134 else:
135 135 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
136 136
137 137 datadict = {"time":k,
138 138 "commits":1,
139 139 "added":len(cs.added),
140 140 "changed":len(cs.changed),
141 141 "removed":len(cs.removed),
142 142 }
143 143 commits_by_day_author_aggregate\
144 144 [author_key_cleaner(cs.author)]['data'].append(datadict)
145 145
146 146 else:
147 147 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
148 148 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
149 149 "label":author_key_cleaner(cs.author),
150 150 "data":[{"time":k,
151 151 "commits":1,
152 152 "added":len(cs.added),
153 153 "changed":len(cs.changed),
154 154 "removed":len(cs.removed),
155 155 }],
156 156 "schema":["commits"],
157 157 }
158 158
159 159 #gather all data by day
160 160 if commits_by_day_aggregate.has_key(k):
161 161 commits_by_day_aggregate[k] += 1
162 162 else:
163 163 commits_by_day_aggregate[k] = 1
164 164
165 165 if cnt >= parse_limit:
166 166 #don't fetch to much data since we can freeze application
167 167 break
168 168 overview_data = []
169 169 for k, v in commits_by_day_aggregate.items():
170 170 overview_data.append([k, v])
171 171 overview_data = sorted(overview_data, key=itemgetter(0))
172 172 if not commits_by_day_author_aggregate:
173 173 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
174 174 "label":author_key_cleaner(repo.contact),
175 175 "data":[0, 1],
176 176 "schema":["commits"],
177 177 }
178 178
179 179 stats = cur_stats if cur_stats else Statistics()
180 180 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
181 181 stats.commit_activity_combined = json.dumps(overview_data)
182 182
183 183 log.debug('last revison %s', last_rev)
184 184 leftovers = len(repo.revisions[last_rev:])
185 185 log.debug('revisions to parse %s', leftovers)
186 186
187 187 if last_rev == 0 or leftovers < parse_limit:
188 188 stats.languages = json.dumps(__get_codes_stats(repo_name))
189 189
190 190 stats.repository = dbrepo
191 191 stats.stat_on_revision = last_cs.revision
192 192
193 193 try:
194 194 sa.add(stats)
195 195 sa.commit()
196 196 except:
197 197 log.error(traceback.format_exc())
198 198 sa.rollback()
199 199 return False
200 200 if len(repo.revisions) > 1:
201 201 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
202 202
203 203 return True
204 204
205 205 @task
206 206 def reset_user_password(user_email):
207 207 log = reset_user_password.get_logger()
208 208 from rhodecode.lib import auth
209 209 from rhodecode.model.db import User
210 210
211 211 try:
212 212 try:
213 213 sa = get_session()
214 214 user = sa.query(User).filter(User.email == user_email).scalar()
215 215 new_passwd = auth.PasswordGenerator().gen_password(8,
216 216 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
217 217 if user:
218 218 user.password = auth.get_crypt_password(new_passwd)
219 219 sa.add(user)
220 220 sa.commit()
221 221 log.info('change password for %s', user_email)
222 222 if new_passwd is None:
223 223 raise Exception('unable to generate new password')
224 224
225 225 except:
226 226 log.error(traceback.format_exc())
227 227 sa.rollback()
228 228
229 229 run_task(send_email, user_email,
230 230 "Your new rhodecode password",
231 231 'Your new rhodecode password:%s' % (new_passwd))
232 232 log.info('send new password mail to %s', user_email)
233 233
234 234
235 235 except:
236 236 log.error('Failed to update user password')
237 237 log.error(traceback.format_exc())
238 238 return True
239 239
240 240 @task
241 241 def send_email(recipients, subject, body):
242 242 """
243 243 Sends an email with defined parameters from the .ini files.
244 244
245 245
246 246 :param recipients: list of recipients, it this is empty the defined email
247 247 address from field 'email_to' is used instead
248 248 :param subject: subject of the mail
249 249 :param body: body of the mail
250 250 """
251 251 log = send_email.get_logger()
252 252 email_config = dict(config.items('DEFAULT'))
253 253
254 254 if not recipients:
255 255 recipients = [email_config.get('email_to')]
256 256
257 257 def str2bool(v):
258 258 return v.lower() in ["yes", "true", "t", "1"] if v else None
259 259
260 260 mail_from = email_config.get('app_email_from')
261 261 user = email_config.get('smtp_username')
262 262 passwd = email_config.get('smtp_password')
263 263 mail_server = email_config.get('smtp_server')
264 264 mail_port = email_config.get('smtp_port')
265 265 tls = str2bool(email_config.get('smtp_use_tls'))
266 266 ssl = str2bool(email_config.get('smtp_use_ssl'))
267 267
268 268 try:
269 269 m = SmtpMailer(mail_from, user, passwd, mail_server,
270 270 mail_port, ssl, tls)
271 271 m.send(recipients, subject, body)
272 272 except:
273 273 log.error('Mail sending failed')
274 274 log.error(traceback.format_exc())
275 275 return False
276 276 return True
277 277
278 278 @task
279 279 def create_repo_fork(form_data, cur_user):
280 280 from rhodecode.model.repo import RepoModel
281 281 from vcs import get_backend
282 282 log = create_repo_fork.get_logger()
283 repo_model = RepoModel()
283 repo_model = RepoModel(get_session())
284 284 repo_model.create(form_data, cur_user, just_db=True, fork=True)
285 285 repo_name = form_data['repo_name']
286 286 repos_path = get_repos_path()
287 287 repo_path = os.path.join(repos_path, repo_name)
288 288 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
289 289 alias = form_data['repo_type']
290 290
291 291 log.info('creating repo fork %s as %s', repo_name, repo_path)
292 292 backend = get_backend(alias)
293 293 backend(str(repo_fork_path), create=True, src_url=str(repo_path))
294 294
295 295 def __get_codes_stats(repo_name):
296 296 LANGUAGES_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx',
297 297 'aspx', 'asx', 'axd', 'c', 'cfg', 'cfm', 'cpp', 'cs', 'diff', 'do', 'el',
298 298 'erl', 'h', 'java', 'js', 'jsp', 'jspx', 'lisp', 'lua', 'm', 'mako', 'ml',
299 299 'pas', 'patch', 'php', 'php3', 'php4', 'phtml', 'pm', 'py', 'rb', 'rst',
300 300 's', 'sh', 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt', 'yaws']
301 301
302 302
303 303 repos_path = get_repos_path()
304 304 p = os.path.join(repos_path, repo_name)
305 305 repo = get_repo(p)
306 306 tip = repo.get_changeset()
307 307 code_stats = {}
308 308
309 309 def aggregate(cs):
310 310 for f in cs[2]:
311 311 k = f.mimetype
312 312 if f.extension in LANGUAGES_EXTENSIONS:
313 313 if code_stats.has_key(k):
314 314 code_stats[k] += 1
315 315 else:
316 316 code_stats[k] = 1
317 317
318 318 map(aggregate, tip.walk('/'))
319 319
320 320 return code_stats or {}
321 321
322 322
323 323
324 324
@@ -1,23 +1,32
1 1 """The application's model objects"""
2 2 import logging
3 3 from rhodecode.model import meta
4 4 log = logging.getLogger(__name__)
5 5
6 6 def init_model(engine):
7 7 """Call me before using any of the tables or classes in the model"""
8 8 log.info("INITIALIZING DB MODELS")
9 9 meta.Base.metadata.bind = engine
10 10 #meta.Base2.metadata.bind = engine2
11 11
12 12 #THIS IS A TEST FOR EXECUTING SCRIPT AND LOAD PYLONS APPLICATION GLOBALS
13 13 #from paste.deploy import appconfig
14 14 #from pylons import config
15 15 #from sqlalchemy import engine_from_config
16 16 #from rhodecode.config.environment import load_environment
17 17 #
18 18 #conf = appconfig('config:development.ini', relative_to = './../../')
19 19 #load_environment(conf.global_conf, conf.local_conf)
20 20 #
21 21 #engine = engine_from_config(config, 'sqlalchemy.')
22 22 #init_model(engine)
23 23 # DO SOMETHING
24
25
26 class BaseModel(object):
27
28 def __init__(self, sa=None):
29 if sa is not None:
30 self.sa = sa
31 else:
32 self.sa = meta.Session()
@@ -1,99 +1,96
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Model for permissions
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on Aug 20, 2010
22 22 Model for permissions
23 @author: marcink
23 :author: marcink
24 24 """
25 25
26 from rhodecode.model import BaseModel
26 27 from rhodecode.model.db import User, Permission, UserToPerm, RepoToPerm
27 28 from rhodecode.model.caching_query import FromCache
28 from rhodecode.model.meta import Session
29 29 import logging
30 30 import traceback
31 31 log = logging.getLogger(__name__)
32 32
33 33
34 class PermissionModel(object):
35
36 def __init__(self):
37 self.sa = Session()
34 class PermissionModel(BaseModel):
38 35
39 36 def get_permission(self, permission_id, cache=False):
40 37 perm = self.sa.query(Permission)
41 38 if cache:
42 39 perm = perm.options(FromCache("sql_cache_short",
43 40 "get_permission_%s" % permission_id))
44 41 return perm.get(permission_id)
45 42
46 43 def get_permission_by_name(self, name, cache=False):
47 44 perm = self.sa.query(Permission)\
48 45 .filter(Permission.permission_name == name)
49 46 if cache:
50 47 perm = perm.options(FromCache("sql_cache_short",
51 48 "get_permission_%s" % name))
52 49 return perm.scalar()
53 50
54 51 def update(self, form_result):
55 52 perm_user = self.sa.query(User)\
56 53 .filter(User.username == form_result['perm_user_name']).scalar()
57 54 u2p = self.sa.query(UserToPerm).filter(UserToPerm.user == perm_user).all()
58 55 if len(u2p) != 3:
59 56 raise Exception('Defined: %s should be 3 permissions for default'
60 57 ' user. This should not happen please verify'
61 58 ' your database' % len(u2p))
62 59
63 60 try:
64 61 #stage 1 change defaults
65 62 for p in u2p:
66 63 if p.permission.permission_name.startswith('repository.'):
67 64 p.permission = self.get_permission_by_name(
68 65 form_result['default_perm'])
69 66 self.sa.add(p)
70 67
71 68 if p.permission.permission_name.startswith('hg.register.'):
72 69 p.permission = self.get_permission_by_name(
73 70 form_result['default_register'])
74 71 self.sa.add(p)
75 72
76 73 if p.permission.permission_name.startswith('hg.create.'):
77 74 p.permission = self.get_permission_by_name(
78 75 form_result['default_create'])
79 76 self.sa.add(p)
80 77
81 78 #stage 2 update all default permissions for repos if checked
82 79 if form_result['overwrite_default'] == True:
83 80 for r2p in self.sa.query(RepoToPerm)\
84 81 .filter(RepoToPerm.user == perm_user).all():
85 82 r2p.permission = self.get_permission_by_name(
86 83 form_result['default_perm'])
87 84 self.sa.add(r2p)
88 85
89 86 #stage 3 set anonymous access
90 87 if perm_user.username == 'default':
91 88 perm_user.active = bool(form_result['anonymous'])
92 89 self.sa.add(perm_user)
93 90
94 91
95 92 self.sa.commit()
96 93 except:
97 94 log.error(traceback.format_exc())
98 95 self.sa.rollback()
99 96 raise
@@ -1,235 +1,233
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # model for handling repositories actions
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 # This program is free software; you can redistribute it and/or
6 6 # modify it under the terms of the GNU General Public License
7 7 # as published by the Free Software Foundation; version 2
8 8 # of the License or (at your opinion) any later version of the license.
9 9 #
10 10 # This program is distributed in the hope that it will be useful,
11 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 # GNU General Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License
16 16 # along with this program; if not, write to the Free Software
17 17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 18 # MA 02110-1301, USA.
19 19 """
20 20 Created on Jun 5, 2010
21 21 model for handling repositories actions
22 22 :author: marcink
23 23 """
24 from vcs.backends import get_repo, get_backend
24 from vcs.backends import get_backend
25 25 from datetime import datetime
26 26 from pylons import app_globals as g
27 27 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
28 28 Statistics
29 from rhodecode.model.meta import Session
29 from rhodecode.model import BaseModel
30 30 from rhodecode.model.user import UserModel
31 31 from rhodecode.model.caching_query import FromCache
32 32 import logging
33 33 import os
34 34 import shutil
35 35 import traceback
36 36 log = logging.getLogger(__name__)
37 37
38 class RepoModel(object):
39
40 def __init__(self):
41 self.sa = Session()
38 class RepoModel(BaseModel):
42 39
43 40 def get(self, repo_id, cache=False):
44 41 repo = self.sa.query(Repository)\
45 42 .filter(Repository.repo_id == repo_id)
46 43
47 44 if cache:
48 45 repo = repo.options(FromCache("sql_cache_short",
49 46 "get_repo_%s" % repo_id))
50 47 return repo.scalar()
51 48
52 49
53 50 def get_by_repo_name(self, repo_name, cache=False):
54 51 repo = self.sa.query(Repository)\
55 52 .filter(Repository.repo_name == repo_name)
56 53
57 54 if cache:
58 55 repo = repo.options(FromCache("sql_cache_short",
59 56 "get_repo_%s" % repo_name))
60 57 return repo.scalar()
61 58
62 59 def get_users_js(self):
63 60
64 61 users = self.sa.query(User).filter(User.active == True).all()
65 62 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
66 63 users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
67 64 u.lastname, u.username)
68 65 for u in users])
69 66 return users_array
70 67
71 68
72 69 def update(self, repo_name, form_data):
73 70 try:
74 71
75 72 #update permissions
76 73 for username, perm in form_data['perms_updates']:
77 74 r2p = self.sa.query(RepoToPerm)\
78 .filter(RepoToPerm.user == UserModel()\
75 .filter(RepoToPerm.user == UserModel(self.sa)\
79 76 .get_by_username(username, cache=False))\
80 77 .filter(RepoToPerm.repository == \
81 78 self.get_by_repo_name(repo_name))\
82 79 .one()
83 80
84 81 r2p.permission_id = self.sa.query(Permission).filter(
85 82 Permission.permission_name ==
86 83 perm).one().permission_id
87 84 self.sa.add(r2p)
88 85
89 86 #set new permissions
90 87 for username, perm in form_data['perms_new']:
91 88 r2p = RepoToPerm()
92 89 r2p.repository = self.get_by_repo_name(repo_name)
93 r2p.user = UserModel().get_by_username(username, cache=False)
90 r2p.user = UserModel(self.sa).get_by_username(username, cache=False)
94 91
95 92 r2p.permission_id = self.sa.query(Permission).filter(
96 93 Permission.permission_name == perm)\
97 94 .one().permission_id
98 95 self.sa.add(r2p)
99 96
100 97 #update current repo
101 98 cur_repo = self.get_by_repo_name(repo_name, cache=False)
102 99
103 100 for k, v in form_data.items():
104 101 if k == 'user':
105 102 cur_repo.user_id = v
106 103 else:
107 104 setattr(cur_repo, k, v)
108 105
109 106 self.sa.add(cur_repo)
110 107
111 108 if repo_name != form_data['repo_name']:
112 109 #rename our data
113 110 self.__rename_repo(repo_name, form_data['repo_name'])
114 111
115 112 self.sa.commit()
116 113 except:
117 114 log.error(traceback.format_exc())
118 115 self.sa.rollback()
119 116 raise
120 117
121 118 def create(self, form_data, cur_user, just_db=False, fork=False):
122 119 try:
123 120 if fork:
124 121 #force str since hg doesn't go with unicode
125 122 repo_name = str(form_data['fork_name'])
126 123 org_name = str(form_data['repo_name'])
127 124
128 125 else:
129 126 org_name = repo_name = str(form_data['repo_name'])
130 127 new_repo = Repository()
131 128 for k, v in form_data.items():
132 129 if k == 'repo_name':
133 130 v = repo_name
134 131 setattr(new_repo, k, v)
135 132
136 133 if fork:
137 134 parent_repo = self.sa.query(Repository)\
138 135 .filter(Repository.repo_name == org_name).scalar()
139 136 new_repo.fork = parent_repo
140 137
141 138 new_repo.user_id = cur_user.user_id
142 139 self.sa.add(new_repo)
143 140
144 141 #create default permission
145 142 repo_to_perm = RepoToPerm()
146 143 default = 'repository.read'
147 for p in UserModel().get_by_username('default', cache=False).user_perms:
144 for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
148 145 if p.permission.permission_name.startswith('repository.'):
149 146 default = p.permission.permission_name
150 147 break
151 148
152 149 default_perm = 'repository.none' if form_data['private'] else default
153 150
154 151 repo_to_perm.permission_id = self.sa.query(Permission)\
155 152 .filter(Permission.permission_name == default_perm)\
156 153 .one().permission_id
157 154
158 155 repo_to_perm.repository_id = new_repo.repo_id
159 repo_to_perm.user_id = UserModel().get_by_username('default', cache=False).user_id
156 repo_to_perm.user_id = UserModel(self.sa)\
157 .get_by_username('default', cache=False).user_id
160 158
161 159 self.sa.add(repo_to_perm)
162 160 self.sa.commit()
163 161 if not just_db:
164 162 self.__create_repo(repo_name, form_data['repo_type'])
165 163 except:
166 164 log.error(traceback.format_exc())
167 165 self.sa.rollback()
168 166 raise
169 167
170 168 def create_fork(self, form_data, cur_user):
171 169 from rhodecode.lib.celerylib import tasks, run_task
172 170 run_task(tasks.create_repo_fork, form_data, cur_user)
173 171
174 172 def delete(self, repo):
175 173 try:
176 174 self.sa.delete(repo)
177 175 self.__delete_repo(repo)
178 176 self.sa.commit()
179 177 except:
180 178 log.error(traceback.format_exc())
181 179 self.sa.rollback()
182 180 raise
183 181
184 182 def delete_perm_user(self, form_data, repo_name):
185 183 try:
186 184 self.sa.query(RepoToPerm)\
187 185 .filter(RepoToPerm.repository \
188 186 == self.get_by_repo_name(repo_name))\
189 187 .filter(RepoToPerm.user_id == form_data['user_id']).delete()
190 188 self.sa.commit()
191 189 except:
192 190 log.error(traceback.format_exc())
193 191 self.sa.rollback()
194 192 raise
195 193
196 194 def delete_stats(self, repo_name):
197 195 try:
198 196 self.sa.query(Statistics)\
199 197 .filter(Statistics.repository == \
200 198 self.get_by_repo_name(repo_name)).delete()
201 199 self.sa.commit()
202 200 except:
203 201 log.error(traceback.format_exc())
204 202 self.sa.rollback()
205 203 raise
206 204
207 205
208 206 def __create_repo(self, repo_name, alias):
209 207 from rhodecode.lib.utils import check_repo
210 208 repo_path = os.path.join(g.base_path, repo_name)
211 209 if check_repo(repo_name, g.base_path):
212 210 log.info('creating repo %s in %s', repo_name, repo_path)
213 211 backend = get_backend(alias)
214 212 backend(repo_path, create=True)
215 213
216 214 def __rename_repo(self, old, new):
217 215 log.info('renaming repo from %s to %s', old, new)
218 216
219 217 old_path = os.path.join(g.base_path, old)
220 218 new_path = os.path.join(g.base_path, new)
221 219 if os.path.isdir(new_path):
222 220 raise Exception('Was trying to rename to already existing dir %s',
223 221 new_path)
224 222 shutil.move(old_path, new_path)
225 223
226 224 def __delete_repo(self, repo):
227 225 rm_path = os.path.join(g.base_path, repo.repo_name)
228 226 log.info("Removing %s", rm_path)
229 227 #disable hg/git
230 228 alias = repo.repo_type
231 229 shutil.move(os.path.join(rm_path, '.%s' % alias),
232 230 os.path.join(rm_path, 'rm__.%s' % alias))
233 231 #disable repo
234 232 shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
235 233 % (datetime.today(), repo.repo_name)))
@@ -1,350 +1,347
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Model for RhodeCode
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 9, 2010
22 22 Model for RhodeCode
23 23 @author: marcink
24 24 """
25 25 from beaker.cache import cache_region, region_invalidate
26 26 from mercurial import ui
27 27 from rhodecode import BACKENDS
28 28 from rhodecode.lib import helpers as h
29 29 from rhodecode.lib.auth import HasRepoPermissionAny
30 30 from rhodecode.lib.utils import get_repos, make_ui, action_logger
31 from rhodecode.model import meta
31 from rhodecode.model import BaseModel
32 32 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation, \
33 33 UserFollowing
34 34 from rhodecode.model.caching_query import FromCache
35 35 from sqlalchemy.orm import joinedload
36 36 from sqlalchemy.orm.session import make_transient
37 37 from vcs import get_backend
38 38 from vcs.utils.helpers import get_scm
39 39 from vcs.exceptions import RepositoryError, VCSError
40 40 from vcs.utils.lazy import LazyProperty
41 41 import traceback
42 42 import logging
43 43 import os
44 44 import time
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48 class UserTemp(object):
49 49 def __init__(self, user_id):
50 50 self.user_id = user_id
51 51
52 52 class RepoTemp(object):
53 53 def __init__(self, repo_id):
54 54 self.repo_id = repo_id
55 55
56 56
57 class ScmModel(object):
57 class ScmModel(BaseModel):
58 58 """
59 59 Mercurial Model
60 60 """
61 61
62 def __init__(self):
63 self.sa = meta.Session()
64
65 62 @LazyProperty
66 63 def repos_path(self):
67 64 """
68 65 Get's the repositories root path from database
69 66 """
70 67 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
71 68
72 69 return q.ui_value
73 70
74 71 def repo_scan(self, repos_path, baseui, initial=False):
75 72 """
76 73 Listing of repositories in given path. This path should not be a
77 74 repository itself. Return a dictionary of repository objects
78 75
79 76 :param repos_path: path to directory containing repositories
80 77 :param baseui
81 78 :param initial: initial scan
82 79 """
83 80 log.info('scanning for repositories in %s', repos_path)
84 81
85 82 if not isinstance(baseui, ui.ui):
86 83 baseui = make_ui('db')
87 84 repos_list = {}
88 85
89 86 for name, path in get_repos(repos_path):
90 87 try:
91 88 if repos_list.has_key(name):
92 89 raise RepositoryError('Duplicate repository name %s '
93 90 'found in %s' % (name, path))
94 91 else:
95 92
96 93 klass = get_backend(path[0])
97 94
98 95 if path[0] == 'hg' and path[0] in BACKENDS.keys():
99 96 repos_list[name] = klass(path[1], baseui=baseui)
100 97
101 98 if path[0] == 'git' and path[0] in BACKENDS.keys():
102 99 repos_list[name] = klass(path[1])
103 100 except OSError:
104 101 continue
105 102
106 103 return repos_list
107 104
108 105 def get_repos(self, all_repos=None):
109 106 """
110 107 Get all repos from db and for each repo create it's backend instance.
111 108 and fill that backed with information from database
112 109
113 110 :param all_repos: give specific repositories list, good for filtering
114 111 """
115 112 if not all_repos:
116 113 all_repos = self.sa.query(Repository)\
117 114 .order_by(Repository.repo_name).all()
118 115
119 116 invalidation_list = [str(x.cache_key) for x in \
120 117 self.sa.query(CacheInvalidation.cache_key)\
121 118 .filter(CacheInvalidation.cache_active == False)\
122 119 .all()]
123 120
124 121 for r in all_repos:
125 122
126 123 repo = self.get(r.repo_name, invalidation_list)
127 124
128 125 if repo is not None:
129 126 last_change = repo.last_change
130 127 tip = h.get_changeset_safe(repo, 'tip')
131 128
132 129 tmp_d = {}
133 130 tmp_d['name'] = repo.name
134 131 tmp_d['name_sort'] = tmp_d['name'].lower()
135 132 tmp_d['description'] = repo.dbrepo.description
136 133 tmp_d['description_sort'] = tmp_d['description']
137 134 tmp_d['last_change'] = last_change
138 135 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
139 136 tmp_d['tip'] = tip.raw_id
140 137 tmp_d['tip_sort'] = tip.revision
141 138 tmp_d['rev'] = tip.revision
142 139 tmp_d['contact'] = repo.dbrepo.user.full_contact
143 140 tmp_d['contact_sort'] = tmp_d['contact']
144 141 tmp_d['repo_archives'] = list(repo._get_archives())
145 142 tmp_d['last_msg'] = tip.message
146 143 tmp_d['repo'] = repo
147 144 yield tmp_d
148 145
149 146 def get_repo(self, repo_name):
150 147 return self.get(repo_name)
151 148
152 149 def get(self, repo_name, invalidation_list=None):
153 150 """
154 151 Get's repository from given name, creates BackendInstance and
155 152 propagates it's data from database with all additional information
156 153 :param repo_name:
157 154 """
158 155 if not HasRepoPermissionAny('repository.read', 'repository.write',
159 156 'repository.admin')(repo_name, 'get repo check'):
160 157 return
161 158
162 159 @cache_region('long_term')
163 160 def _get_repo(repo_name):
164 161
165 162 repo_path = os.path.join(self.repos_path, repo_name)
166 163 alias = get_scm(repo_path)[0]
167 164
168 165 log.debug('Creating instance of %s repository', alias)
169 166 backend = get_backend(alias)
170 167
171 168 #TODO: get the baseui from somewhere for this
172 169 if alias == 'hg':
173 170 from pylons import app_globals as g
174 171 repo = backend(repo_path, create=False, baseui=g.baseui)
175 172 #skip hidden web repository
176 173 if repo._get_hidden():
177 174 return
178 175 else:
179 176 repo = backend(repo_path, create=False)
180 177
181 178 dbrepo = self.sa.query(Repository)\
182 179 .options(joinedload(Repository.fork))\
183 180 .options(joinedload(Repository.user))\
184 181 .filter(Repository.repo_name == repo_name)\
185 182 .scalar()
186 183 make_transient(dbrepo)
187 184 repo.dbrepo = dbrepo
188 185 return repo
189 186
190 187 pre_invalidate = True
191 188 if invalidation_list:
192 189 pre_invalidate = repo_name in invalidation_list
193 190
194 191 if pre_invalidate:
195 192 invalidate = self._should_invalidate(repo_name)
196 193
197 194 if invalidate:
198 195 log.info('invalidating cache for repository %s', repo_name)
199 196 region_invalidate(_get_repo, None, repo_name)
200 197 self._mark_invalidated(invalidate)
201 198
202 199 return _get_repo(repo_name)
203 200
204 201
205 202
206 203 def mark_for_invalidation(self, repo_name):
207 204 """
208 205 Puts cache invalidation task into db for
209 206 further global cache invalidation
210 207
211 208 :param repo_name: this repo that should invalidation take place
212 209 """
213 210 log.debug('marking %s for invalidation', repo_name)
214 211 cache = self.sa.query(CacheInvalidation)\
215 212 .filter(CacheInvalidation.cache_key == repo_name).scalar()
216 213
217 214 if cache:
218 215 #mark this cache as inactive
219 216 cache.cache_active = False
220 217 else:
221 218 log.debug('cache key not found in invalidation db -> creating one')
222 219 cache = CacheInvalidation(repo_name)
223 220
224 221 try:
225 222 self.sa.add(cache)
226 223 self.sa.commit()
227 224 except:
228 225 log.error(traceback.format_exc())
229 226 self.sa.rollback()
230 227
231 228
232 229 def toggle_following_repo(self, follow_repo_id, user_id):
233 230
234 231 f = self.sa.query(UserFollowing)\
235 232 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
236 233 .filter(UserFollowing.user_id == user_id).scalar()
237 234
238 235 if f is not None:
239 236
240 237 try:
241 238 self.sa.delete(f)
242 239 self.sa.commit()
243 240 action_logger(UserTemp(user_id),
244 241 'stopped_following_repo',
245 242 RepoTemp(follow_repo_id))
246 243 return
247 244 except:
248 245 log.error(traceback.format_exc())
249 246 self.sa.rollback()
250 247 raise
251 248
252 249
253 250 try:
254 251 f = UserFollowing()
255 252 f.user_id = user_id
256 253 f.follows_repo_id = follow_repo_id
257 254 self.sa.add(f)
258 255 self.sa.commit()
259 256 action_logger(UserTemp(user_id),
260 257 'started_following_repo',
261 258 RepoTemp(follow_repo_id))
262 259 except:
263 260 log.error(traceback.format_exc())
264 261 self.sa.rollback()
265 262 raise
266 263
267 264 def toggle_following_user(self, follow_user_id , user_id):
268 265 f = self.sa.query(UserFollowing)\
269 266 .filter(UserFollowing.follows_user_id == follow_user_id)\
270 267 .filter(UserFollowing.user_id == user_id).scalar()
271 268
272 269 if f is not None:
273 270 try:
274 271 self.sa.delete(f)
275 272 self.sa.commit()
276 273 return
277 274 except:
278 275 log.error(traceback.format_exc())
279 276 self.sa.rollback()
280 277 raise
281 278
282 279 try:
283 280 f = UserFollowing()
284 281 f.user_id = user_id
285 282 f.follows_user_id = follow_user_id
286 283 self.sa.add(f)
287 284 self.sa.commit()
288 285 except:
289 286 log.error(traceback.format_exc())
290 287 self.sa.rollback()
291 288 raise
292 289
293 290 def is_following_repo(self, repo_name, user_id):
294 291 r = self.sa.query(Repository)\
295 292 .filter(Repository.repo_name == repo_name).scalar()
296 293
297 294 f = self.sa.query(UserFollowing)\
298 295 .filter(UserFollowing.follows_repository == r)\
299 296 .filter(UserFollowing.user_id == user_id).scalar()
300 297
301 298 return f is not None
302 299
303 300 def is_following_user(self, username, user_id):
304 301 u = self.sa.query(User)\
305 302 .filter(User.username == username).scalar()
306 303
307 304 f = self.sa.query(UserFollowing)\
308 305 .filter(UserFollowing.follows_user == u)\
309 306 .filter(UserFollowing.user_id == user_id).scalar()
310 307
311 308 return f is not None
312 309
313 310 def get_followers(self, repo_id):
314 311 return self.sa.query(UserFollowing)\
315 312 .filter(UserFollowing.follows_repo_id == repo_id).count()
316 313
317 314 def get_forks(self, repo_id):
318 315 return self.sa.query(Repository)\
319 316 .filter(Repository.fork_id == repo_id).count()
320 317
321 318 def _should_invalidate(self, repo_name):
322 319 """
323 320 Looks up database for invalidation signals for this repo_name
324 321 :param repo_name:
325 322 """
326 323
327 324 ret = self.sa.query(CacheInvalidation)\
328 325 .options(FromCache('sql_cache_short',
329 326 'get_invalidation_%s' % repo_name))\
330 327 .filter(CacheInvalidation.cache_key == repo_name)\
331 328 .filter(CacheInvalidation.cache_active == False)\
332 329 .scalar()
333 330
334 331 return ret
335 332
336 333 def _mark_invalidated(self, cache_key):
337 334 """
338 335 Marks all occurences of cache to invaldation as already invalidated
339 336 @param repo_name:
340 337 """
341 338 if cache_key:
342 339 log.debug('marking %s as already invalidated', cache_key)
343 340 try:
344 341 cache_key.cache_active = True
345 342 self.sa.add(cache_key)
346 343 self.sa.commit()
347 344 except:
348 345 log.error(traceback.format_exc())
349 346 self.sa.rollback()
350 347
@@ -1,79 +1,76
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Model for RhodeCode settings
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on Nov 17, 2010
22 22 Model for RhodeCode
23 @author: marcink
23 :author: marcink
24 24 """
25
25 26 from rhodecode.lib import helpers as h
26 from rhodecode.model import meta
27 from rhodecode.model import BaseModel
27 28 from rhodecode.model.caching_query import FromCache
28 29 from rhodecode.model.db import RhodeCodeSettings
29 30 from sqlalchemy.orm import joinedload
30 31 from sqlalchemy.orm.session import make_transient
31 32 import logging
32 33
33 34 log = logging.getLogger(__name__)
34 35
35 class SettingsModel(object):
36 class SettingsModel(BaseModel):
36 37 """
37 38 Settings model
38 39 """
39 40
40 def __init__(self):
41 self.sa = meta.Session()
42
43
44 41 def get(self, settings_key, cache=False):
45 42 r = self.sa.query(RhodeCodeSettings)\
46 43 .filter(RhodeCodeSettings.app_settings_name == settings_key).scalar()
47 44 if cache:
48 45 r = r.options(FromCache("sql_cache_short",
49 46 "get_setting_%s" % settings_key))
50 47 return r
51 48
52 49
53 50 def get_ldap_settings(self):
54 51 """
55 52 Returns ldap settings from database
56 53 :returns:
57 54 ldap_active
58 55 ldap_host
59 56 ldap_port
60 57 ldap_ldaps
61 58 ldap_dn_user
62 59 ldap_dn_pass
63 60 ldap_base_dn
64 61 """
65 62
66 63 r = self.sa.query(RhodeCodeSettings)\
67 64 .filter(RhodeCodeSettings.app_settings_name\
68 65 .startswith('ldap_'))\
69 66 .all()
70 67
71 68 fd = {}
72 69
73 70 for row in r:
74 71 v = row.app_settings_value
75 72 if v in ['0', '1']:
76 73 v = v == '1'
77 74 fd.update({row.app_settings_name:v})
78 75
79 76 return fd
@@ -1,220 +1,217
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Model for users
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 9, 2010
22 22 Model for users
23 23 :author: marcink
24 24 """
25 25
26 26 from pylons.i18n.translation import _
27 from rhodecode.model import BaseModel
27 28 from rhodecode.model.caching_query import FromCache
28 29 from rhodecode.model.db import User
29 from rhodecode.model.meta import Session
30 30 from rhodecode.lib.exceptions import *
31 31
32 32 import logging
33 33 import traceback
34 34
35 35 log = logging.getLogger(__name__)
36 36
37 37
38 38
39 class UserModel(object):
40
41 def __init__(self):
42 self.sa = Session()
39 class UserModel(BaseModel):
43 40
44 41 def get(self, user_id, cache=False):
45 42 user = self.sa.query(User)
46 43 if cache:
47 44 user = user.options(FromCache("sql_cache_short",
48 45 "get_user_%s" % user_id))
49 46 return user.get(user_id)
50 47
51 48
52 49 def get_by_username(self, username, cache=False, case_insensitive=False):
53 50
54 51 if case_insensitive:
55 52 user = self.sa.query(User).filter(User.username.ilike(username))
56 53 else:
57 54 user = self.sa.query(User)\
58 55 .filter(User.username == username)
59 56 if cache:
60 57 user = user.options(FromCache("sql_cache_short",
61 58 "get_user_%s" % username))
62 59 return user.scalar()
63 60
64 61 def create(self, form_data):
65 62 try:
66 63 new_user = User()
67 64 for k, v in form_data.items():
68 65 setattr(new_user, k, v)
69 66
70 67 self.sa.add(new_user)
71 68 self.sa.commit()
72 69 except:
73 70 log.error(traceback.format_exc())
74 71 self.sa.rollback()
75 72 raise
76 73
77 74 def create_ldap(self, username, password):
78 75 """
79 76 Checks if user is in database, if not creates this user marked
80 77 as ldap user
81 78 :param username:
82 79 :param password:
83 80 """
84 81 from rhodecode.lib.auth import get_crypt_password
85 82 if self.get_by_username(username) is None:
86 83 try:
87 84 new_user = User()
88 85 new_user.username = username
89 86 new_user.password = get_crypt_password(password)
90 87 new_user.email = '%s@ldap.server' % username
91 88 new_user.active = True
92 89 new_user.is_ldap = True
93 90 new_user.name = '%s@ldap' % username
94 91 new_user.lastname = ''
95 92
96 93
97 94 self.sa.add(new_user)
98 95 self.sa.commit()
99 96 return True
100 97 except:
101 98 log.error(traceback.format_exc())
102 99 self.sa.rollback()
103 100 raise
104 101
105 102 return False
106 103
107 104 def create_registration(self, form_data):
108 105 from rhodecode.lib.celerylib import tasks, run_task
109 106 try:
110 107 new_user = User()
111 108 for k, v in form_data.items():
112 109 if k != 'admin':
113 110 setattr(new_user, k, v)
114 111
115 112 self.sa.add(new_user)
116 113 self.sa.commit()
117 114 body = ('New user registration\n'
118 115 'username: %s\n'
119 116 'email: %s\n')
120 117 body = body % (form_data['username'], form_data['email'])
121 118
122 119 run_task(tasks.send_email, None,
123 120 _('[RhodeCode] New User registration'),
124 121 body)
125 122 except:
126 123 log.error(traceback.format_exc())
127 124 self.sa.rollback()
128 125 raise
129 126
130 127 def update(self, user_id, form_data):
131 128 try:
132 129 new_user = self.get(user_id, cache=False)
133 130 if new_user.username == 'default':
134 131 raise DefaultUserException(
135 132 _("You can't Edit this user since it's"
136 133 " crucial for entire application"))
137 134
138 135 for k, v in form_data.items():
139 136 if k == 'new_password' and v != '':
140 137 new_user.password = v
141 138 else:
142 139 setattr(new_user, k, v)
143 140
144 141 self.sa.add(new_user)
145 142 self.sa.commit()
146 143 except:
147 144 log.error(traceback.format_exc())
148 145 self.sa.rollback()
149 146 raise
150 147
151 148 def update_my_account(self, user_id, form_data):
152 149 try:
153 150 new_user = self.get(user_id, cache=False)
154 151 if new_user.username == 'default':
155 152 raise DefaultUserException(
156 153 _("You can't Edit this user since it's"
157 154 " crucial for entire application"))
158 155 for k, v in form_data.items():
159 156 if k == 'new_password' and v != '':
160 157 new_user.password = v
161 158 else:
162 159 if k not in ['admin', 'active']:
163 160 setattr(new_user, k, v)
164 161
165 162 self.sa.add(new_user)
166 163 self.sa.commit()
167 164 except:
168 165 log.error(traceback.format_exc())
169 166 self.sa.rollback()
170 167 raise
171 168
172 169 def delete(self, user_id):
173 170 try:
174 171 user = self.get(user_id, cache=False)
175 172 if user.username == 'default':
176 173 raise DefaultUserException(
177 174 _("You can't remove this user since it's"
178 175 " crucial for entire application"))
179 176 if user.repositories:
180 177 raise UserOwnsReposException(_('This user still owns %s '
181 178 'repositories and cannot be '
182 179 'removed. Switch owners or '
183 180 'remove those repositories') \
184 181 % user.repositories)
185 182 self.sa.delete(user)
186 183 self.sa.commit()
187 184 except:
188 185 log.error(traceback.format_exc())
189 186 self.sa.rollback()
190 187 raise
191 188
192 189 def reset_password(self, data):
193 190 from rhodecode.lib.celerylib import tasks, run_task
194 191 run_task(tasks.reset_user_password, data['email'])
195 192
196 193
197 194 def fill_data(self, user):
198 195 """
199 196 Fills user data with those from database and log out user if not
200 197 present in database
201 198 :param user:
202 199 """
203 200
204 201 if not hasattr(user, 'user_id') or user.user_id is None:
205 202 raise Exception('passed in user has to have the user_id attribute')
206 203
207 204
208 205 log.debug('filling auth user data')
209 206 try:
210 207 dbuser = self.get(user.user_id)
211 208 user.username = dbuser.username
212 209 user.is_admin = dbuser.admin
213 210 user.name = dbuser.name
214 211 user.lastname = dbuser.lastname
215 212 user.email = dbuser.email
216 213 except:
217 214 log.error(traceback.format_exc())
218 215 user.is_authenticated = False
219 216
220 217 return user
General Comments 0
You need to be logged in to leave comments. Login now