##// END OF EJS Templates
added fault tolerant case when celeryconfig is not present in the directory....
marcink -
r555:03676d39 default
parent child Browse files
Show More
@@ -1,316 +1,323 b''
1 1 from celery.decorators import task
2 from celery.task.sets import subtask
3 from celeryconfig import PYLONS_CONFIG as config
2
4 3 from operator import itemgetter
5 4 from pylons.i18n.translation import _
6 5 from rhodecode.lib.celerylib import run_task, locked_task
7 6 from rhodecode.lib.helpers import person
8 7 from rhodecode.lib.smtp_mailer import SmtpMailer
9 8 from rhodecode.lib.utils import OrderedDict
10 9 from time import mktime
11 10 from vcs.backends.hg import MercurialRepository
12 11 import json
13 12 import traceback
14 13
14 try:
15 from celeryconfig import PYLONS_CONFIG as config
16 except ImportError:
17 #if celeryconfig is not present let's just load our pylons
18 #config instead
19 from pylons import config
20
21
15 22 __all__ = ['whoosh_index', 'get_commits_stats',
16 23 'reset_user_password', 'send_email']
17 24
18 25 def get_session():
19 26 from sqlalchemy import engine_from_config
20 27 from sqlalchemy.orm import sessionmaker, scoped_session
21 28 engine = engine_from_config(dict(config.items('app:main')), 'sqlalchemy.db1.')
22 29 sa = scoped_session(sessionmaker(bind=engine))
23 30 return sa
24 31
25 32 def get_hg_settings():
26 33 from rhodecode.model.db import RhodeCodeSettings
27 34 try:
28 35 sa = get_session()
29 36 ret = sa.query(RhodeCodeSettings).all()
30 37 finally:
31 38 sa.remove()
32 39
33 40 if not ret:
34 41 raise Exception('Could not get application settings !')
35 42 settings = {}
36 43 for each in ret:
37 44 settings['rhodecode_' + each.app_settings_name] = each.app_settings_value
38 45
39 46 return settings
40 47
41 48 def get_hg_ui_settings():
42 49 from rhodecode.model.db import RhodeCodeUi
43 50 try:
44 51 sa = get_session()
45 52 ret = sa.query(RhodeCodeUi).all()
46 53 finally:
47 54 sa.remove()
48 55
49 56 if not ret:
50 57 raise Exception('Could not get application ui settings !')
51 58 settings = {}
52 59 for each in ret:
53 60 k = each.ui_key
54 61 v = each.ui_value
55 62 if k == '/':
56 63 k = 'root_path'
57 64
58 65 if k.find('.') != -1:
59 66 k = k.replace('.', '_')
60 67
61 68 if each.ui_section == 'hooks':
62 69 v = each.ui_active
63 70
64 71 settings[each.ui_section + '_' + k] = v
65 72
66 73 return settings
67 74
68 75 @task
69 76 @locked_task
70 77 def whoosh_index(repo_location, full_index):
71 78 log = whoosh_index.get_logger()
72 79 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
73 80 WhooshIndexingDaemon(repo_location=repo_location).run(full_index=full_index)
74 81
75 82 @task
76 83 @locked_task
77 84 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
78 85 from rhodecode.model.db import Statistics, Repository
79 86 log = get_commits_stats.get_logger()
80 87 author_key_cleaner = lambda k: person(k).replace('"', "") #for js data compatibilty
81 88
82 89 commits_by_day_author_aggregate = {}
83 90 commits_by_day_aggregate = {}
84 91 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
85 92 repo = MercurialRepository(repos_path + repo_name)
86 93
87 94 skip_date_limit = True
88 95 parse_limit = 350 #limit for single task changeset parsing optimal for
89 96 last_rev = 0
90 97 last_cs = None
91 98 timegetter = itemgetter('time')
92 99
93 100 sa = get_session()
94 101
95 102 dbrepo = sa.query(Repository)\
96 103 .filter(Repository.repo_name == repo_name).scalar()
97 104 cur_stats = sa.query(Statistics)\
98 105 .filter(Statistics.repository == dbrepo).scalar()
99 106 if cur_stats:
100 107 last_rev = cur_stats.stat_on_revision
101 108 if not repo.revisions:
102 109 return True
103 110
104 111 if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
105 112 #pass silently without any work if we're not on first revision or current
106 113 #state of parsing revision(from db marker) is the last revision
107 114 return True
108 115
109 116 if cur_stats:
110 117 commits_by_day_aggregate = OrderedDict(
111 118 json.loads(
112 119 cur_stats.commit_activity_combined))
113 120 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
114 121
115 122 log.debug('starting parsing %s', parse_limit)
116 123 for cnt, rev in enumerate(repo.revisions[last_rev:]):
117 124 last_cs = cs = repo.get_changeset(rev)
118 125 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
119 126 cs.date.timetuple()[2])
120 127 timetupple = [int(x) for x in k.split('-')]
121 128 timetupple.extend([0 for _ in xrange(6)])
122 129 k = mktime(timetupple)
123 130 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
124 131 try:
125 132 l = [timegetter(x) for x in commits_by_day_author_aggregate\
126 133 [author_key_cleaner(cs.author)]['data']]
127 134 time_pos = l.index(k)
128 135 except ValueError:
129 136 time_pos = False
130 137
131 138 if time_pos >= 0 and time_pos is not False:
132 139
133 140 datadict = commits_by_day_author_aggregate\
134 141 [author_key_cleaner(cs.author)]['data'][time_pos]
135 142
136 143 datadict["commits"] += 1
137 144 datadict["added"] += len(cs.added)
138 145 datadict["changed"] += len(cs.changed)
139 146 datadict["removed"] += len(cs.removed)
140 147 #print datadict
141 148
142 149 else:
143 150 #print 'ELSE !!!!'
144 151 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
145 152
146 153 datadict = {"time":k,
147 154 "commits":1,
148 155 "added":len(cs.added),
149 156 "changed":len(cs.changed),
150 157 "removed":len(cs.removed),
151 158 }
152 159 commits_by_day_author_aggregate\
153 160 [author_key_cleaner(cs.author)]['data'].append(datadict)
154 161
155 162 else:
156 163 #print k, 'nokey ADDING'
157 164 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
158 165 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
159 166 "label":author_key_cleaner(cs.author),
160 167 "data":[{"time":k,
161 168 "commits":1,
162 169 "added":len(cs.added),
163 170 "changed":len(cs.changed),
164 171 "removed":len(cs.removed),
165 172 }],
166 173 "schema":["commits"],
167 174 }
168 175
169 176 # #gather all data by day
170 177 if commits_by_day_aggregate.has_key(k):
171 178 commits_by_day_aggregate[k] += 1
172 179 else:
173 180 commits_by_day_aggregate[k] = 1
174 181
175 182 if cnt >= parse_limit:
176 183 #don't fetch to much data since we can freeze application
177 184 break
178 185
179 186 overview_data = []
180 187 for k, v in commits_by_day_aggregate.items():
181 188 overview_data.append([k, v])
182 189 overview_data = sorted(overview_data, key=itemgetter(0))
183 190
184 191 if not commits_by_day_author_aggregate:
185 192 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
186 193 "label":author_key_cleaner(repo.contact),
187 194 "data":[0, 1],
188 195 "schema":["commits"],
189 196 }
190 197
191 198 stats = cur_stats if cur_stats else Statistics()
192 199 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
193 200 stats.commit_activity_combined = json.dumps(overview_data)
194 201
195 202 log.debug('last revison %s', last_rev)
196 203 leftovers = len(repo.revisions[last_rev:])
197 204 log.debug('revisions to parse %s', leftovers)
198 205
199 206 if last_rev == 0 or leftovers < parse_limit:
200 207 stats.languages = json.dumps(__get_codes_stats(repo_name))
201 208
202 209 stats.repository = dbrepo
203 210 stats.stat_on_revision = last_cs.revision
204 211
205 212 try:
206 213 sa.add(stats)
207 214 sa.commit()
208 215 except:
209 216 log.error(traceback.format_exc())
210 217 sa.rollback()
211 218 return False
212 219 if len(repo.revisions) > 1:
213 220 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
214 221
215 222 return True
216 223
217 224 @task
218 225 def reset_user_password(user_email):
219 226 log = reset_user_password.get_logger()
220 227 from rhodecode.lib import auth
221 228 from rhodecode.model.db import User
222 229
223 230 try:
224 231 try:
225 232 sa = get_session()
226 233 user = sa.query(User).filter(User.email == user_email).scalar()
227 234 new_passwd = auth.PasswordGenerator().gen_password(8,
228 235 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
229 236 if user:
230 237 user.password = auth.get_crypt_password(new_passwd)
231 238 sa.add(user)
232 239 sa.commit()
233 240 log.info('change password for %s', user_email)
234 241 if new_passwd is None:
235 242 raise Exception('unable to generate new password')
236 243
237 244 except:
238 245 log.error(traceback.format_exc())
239 246 sa.rollback()
240 247
241 248 run_task(send_email, user_email,
242 249 "Your new rhodecode password",
243 250 'Your new rhodecode password:%s' % (new_passwd))
244 251 log.info('send new password mail to %s', user_email)
245 252
246 253
247 254 except:
248 255 log.error('Failed to update user password')
249 256 log.error(traceback.format_exc())
250 257 return True
251 258
252 259 @task
253 260 def send_email(recipients, subject, body):
254 261 log = send_email.get_logger()
255 262 email_config = dict(config.items('DEFAULT'))
256 263 mail_from = email_config.get('app_email_from')
257 264 user = email_config.get('smtp_username')
258 265 passwd = email_config.get('smtp_password')
259 266 mail_server = email_config.get('smtp_server')
260 267 mail_port = email_config.get('smtp_port')
261 268 tls = email_config.get('smtp_use_tls')
262 269 ssl = False
263 270
264 271 try:
265 272 m = SmtpMailer(mail_from, user, passwd, mail_server,
266 273 mail_port, ssl, tls)
267 274 m.send(recipients, subject, body)
268 275 except:
269 276 log.error('Mail sending failed')
270 277 log.error(traceback.format_exc())
271 278 return False
272 279 return True
273 280
274 281 @task
275 282 def create_repo_fork(form_data, cur_user):
276 283 import os
277 284 from rhodecode.model.repo_model import RepoModel
278 285 sa = get_session()
279 286 rm = RepoModel(sa)
280 287
281 288 rm.create(form_data, cur_user, just_db=True, fork=True)
282 289
283 290 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
284 291 repo_path = os.path.join(repos_path, form_data['repo_name'])
285 292 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
286 293
287 294 MercurialRepository(str(repo_fork_path), True, clone_url=str(repo_path))
288 295
289 296
290 297 def __get_codes_stats(repo_name):
291 298 LANGUAGES_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c',
292 299 'cfg', 'cfm', 'cpp', 'cs', 'diff', 'do', 'el', 'erl',
293 300 'h', 'java', 'js', 'jsp', 'jspx', 'lisp',
294 301 'lua', 'm', 'mako', 'ml', 'pas', 'patch', 'php', 'php3',
295 302 'php4', 'phtml', 'pm', 'py', 'rb', 'rst', 's', 'sh',
296 303 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt',
297 304 'yaws']
298 305 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
299 306 repo = MercurialRepository(repos_path + repo_name)
300 307
301 308 code_stats = {}
302 309 for topnode, dirs, files in repo.walk('/', 'tip'):
303 310 for f in files:
304 311 k = f.mimetype
305 312 if f.extension in LANGUAGES_EXTENSIONS:
306 313 if code_stats.has_key(k):
307 314 code_stats[k] += 1
308 315 else:
309 316 code_stats[k] = 1
310 317
311 318 return code_stats or {}
312 319
313 320
314 321
315 322
316 323
@@ -1,269 +1,269 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # database managment for hg app
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 """
22 22 Created on April 10, 2010
23 23 database managment and creation for hg app
24 24 @author: marcink
25 25 """
26 26
27 27 from os.path import dirname as dn, join as jn
28 28 import os
29 29 import sys
30 30 import uuid
31 31
32 32 from rhodecode.lib.auth import get_crypt_password
33 33 from rhodecode.lib.utils import ask_ok
34 34 from rhodecode.model import init_model
35 35 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
36 36 UserToPerm
37 37 from rhodecode.model import meta
38 38 from sqlalchemy.engine import create_engine
39 39 import logging
40 40
41 41 log = logging.getLogger(__name__)
42 42
43 43 class DbManage(object):
44 44 def __init__(self, log_sql, dbname, root, tests=False):
45 45 self.dbname = dbname
46 46 self.tests = tests
47 47 self.root = root
48 48 dburi = 'sqlite:////%s' % jn(self.root, self.dbname)
49 49 engine = create_engine(dburi, echo=log_sql)
50 50 init_model(engine)
51 51 self.sa = meta.Session
52 52 self.db_exists = False
53 53
54 54 def check_for_db(self, override):
55 55 db_path = jn(self.root, self.dbname)
56 56 log.info('checking for existing db in %s', db_path)
57 57 if os.path.isfile(db_path):
58 58 self.db_exists = True
59 59 log.info('database exist')
60 60 if not override:
61 61 raise Exception('database already exists')
62 62
63 63 def create_tables(self, override=False):
64 64 """
65 65 Create a auth database
66 66 """
67 67 self.check_for_db(override)
68 68 if override:
69 69 log.info("database exist and it's going to be destroyed")
70 70 if self.tests:
71 71 destroy = True
72 72 else:
73 73 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
74 74 if not destroy:
75 75 sys.exit()
76 76 if self.db_exists and destroy:
77 77 os.remove(jn(self.root, self.dbname))
78 78 checkfirst = not override
79 79 meta.Base.metadata.create_all(checkfirst=checkfirst)
80 80 log.info('Created tables for %s', self.dbname)
81 81
82 82 def admin_prompt(self):
83 83 if not self.tests:
84 84 import getpass
85 85 username = raw_input('Specify admin username:')
86 86 password = getpass.getpass('Specify admin password:')
87 87 confirm = getpass.getpass('Confirm password:')
88 88 if password != confirm:
89 89 log.error('passwords mismatch')
90 90 sys.exit()
91 91 email = raw_input('Specify admin email:')
92 92 self.create_user(username, password, email, True)
93 93 else:
94 94 log.info('creating admin and regular test users')
95 95 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
96 96 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
97 97 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
98 98
99 99
100 100
101 101 def config_prompt(self, test_repo_path=''):
102 102 log.info('Setting up repositories config')
103 103
104 104 if not self.tests and not test_repo_path:
105 105 path = raw_input('Specify valid full path to your repositories'
106 106 ' you can change this later in application settings:')
107 107 else:
108 108 path = test_repo_path
109 109
110 110 if not os.path.isdir(path):
111 111 log.error('You entered wrong path: %s', path)
112 112 sys.exit()
113 113
114 114 hooks1 = RhodeCodeUi()
115 115 hooks1.ui_section = 'hooks'
116 116 hooks1.ui_key = 'changegroup.update'
117 117 hooks1.ui_value = 'hg update >&2'
118 118
119 119 hooks2 = RhodeCodeUi()
120 120 hooks2.ui_section = 'hooks'
121 121 hooks2.ui_key = 'changegroup.repo_size'
122 122 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
123 123
124 124 web1 = RhodeCodeUi()
125 125 web1.ui_section = 'web'
126 126 web1.ui_key = 'push_ssl'
127 127 web1.ui_value = 'false'
128 128
129 129 web2 = RhodeCodeUi()
130 130 web2.ui_section = 'web'
131 131 web2.ui_key = 'allow_archive'
132 132 web2.ui_value = 'gz zip bz2'
133 133
134 134 web3 = RhodeCodeUi()
135 135 web3.ui_section = 'web'
136 136 web3.ui_key = 'allow_push'
137 137 web3.ui_value = '*'
138 138
139 139 web4 = RhodeCodeUi()
140 140 web4.ui_section = 'web'
141 141 web4.ui_key = 'baseurl'
142 142 web4.ui_value = '/'
143 143
144 144 paths = RhodeCodeUi()
145 145 paths.ui_section = 'paths'
146 146 paths.ui_key = '/'
147 147 paths.ui_value = os.path.join(path, '*')
148 148
149 149
150 150 hgsettings1 = RhodeCodeSettings()
151 151
152 152 hgsettings1.app_settings_name = 'realm'
153 hgsettings1.app_settings_value = 'rhodecode authentication'
153 hgsettings1.app_settings_value = 'RhodeCode authentication'
154 154
155 155 hgsettings2 = RhodeCodeSettings()
156 156 hgsettings2.app_settings_name = 'title'
157 hgsettings2.app_settings_value = 'rhodecode'
157 hgsettings2.app_settings_value = 'RhodeCode'
158 158
159 159 try:
160 160 self.sa.add(hooks1)
161 161 self.sa.add(hooks2)
162 162 self.sa.add(web1)
163 163 self.sa.add(web2)
164 164 self.sa.add(web3)
165 165 self.sa.add(web4)
166 166 self.sa.add(paths)
167 167 self.sa.add(hgsettings1)
168 168 self.sa.add(hgsettings2)
169 169 self.sa.commit()
170 170 except:
171 171 self.sa.rollback()
172 172 raise
173 173 log.info('created ui config')
174 174
175 175 def create_user(self, username, password, email='', admin=False):
176 176 log.info('creating administrator user %s', username)
177 177 new_user = User()
178 178 new_user.username = username
179 179 new_user.password = get_crypt_password(password)
180 new_user.name = 'Hg'
180 new_user.name = 'RhodeCode'
181 181 new_user.lastname = 'Admin'
182 182 new_user.email = email
183 183 new_user.admin = admin
184 184 new_user.active = True
185 185
186 186 try:
187 187 self.sa.add(new_user)
188 188 self.sa.commit()
189 189 except:
190 190 self.sa.rollback()
191 191 raise
192 192
193 193 def create_default_user(self):
194 194 log.info('creating default user')
195 195 #create default user for handling default permissions.
196 196 def_user = User()
197 197 def_user.username = 'default'
198 198 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
199 199 def_user.name = 'default'
200 200 def_user.lastname = 'default'
201 201 def_user.email = 'default@default.com'
202 202 def_user.admin = False
203 203 def_user.active = False
204 204 try:
205 205 self.sa.add(def_user)
206 206 self.sa.commit()
207 207 except:
208 208 self.sa.rollback()
209 209 raise
210 210
211 211 def create_permissions(self):
212 212 #module.(access|create|change|delete)_[name]
213 213 #module.(read|write|owner)
214 214 perms = [('repository.none', 'Repository no access'),
215 215 ('repository.read', 'Repository read access'),
216 216 ('repository.write', 'Repository write access'),
217 217 ('repository.admin', 'Repository admin access'),
218 218 ('hg.admin', 'Hg Administrator'),
219 219 ('hg.create.repository', 'Repository create'),
220 220 ('hg.create.none', 'Repository creation disabled'),
221 221 ('hg.register.none', 'Register disabled'),
222 222 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
223 223 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
224 224 ]
225 225
226 226 for p in perms:
227 227 new_perm = Permission()
228 228 new_perm.permission_name = p[0]
229 229 new_perm.permission_longname = p[1]
230 230 try:
231 231 self.sa.add(new_perm)
232 232 self.sa.commit()
233 233 except:
234 234 self.sa.rollback()
235 235 raise
236 236
237 237 def populate_default_permissions(self):
238 238 log.info('creating default user permissions')
239 239
240 240 default_user = self.sa.query(User)\
241 241 .filter(User.username == 'default').scalar()
242 242
243 243 reg_perm = UserToPerm()
244 244 reg_perm.user = default_user
245 245 reg_perm.permission = self.sa.query(Permission)\
246 246 .filter(Permission.permission_name == 'hg.register.manual_activate')\
247 247 .scalar()
248 248
249 249 create_repo_perm = UserToPerm()
250 250 create_repo_perm.user = default_user
251 251 create_repo_perm.permission = self.sa.query(Permission)\
252 252 .filter(Permission.permission_name == 'hg.create.repository')\
253 253 .scalar()
254 254
255 255 default_repo_perm = UserToPerm()
256 256 default_repo_perm.user = default_user
257 257 default_repo_perm.permission = self.sa.query(Permission)\
258 258 .filter(Permission.permission_name == 'repository.read')\
259 259 .scalar()
260 260
261 261 try:
262 262 self.sa.add(reg_perm)
263 263 self.sa.add(create_repo_perm)
264 264 self.sa.add(default_repo_perm)
265 265 self.sa.commit()
266 266 except:
267 267 self.sa.rollback()
268 268 raise
269 269
@@ -1,361 +1,361 b''
1 1 """ this is forms validation classes
2 2 http://formencode.org/module-formencode.validators.html
3 3 for list off all availible validators
4 4
5 5 we can create our own validators
6 6
7 7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 8 pre_validators [] These validators will be applied before the schema
9 9 chained_validators [] These validators will be applied after the schema
10 10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14 14
15 15
16 16 <name> = formencode.validators.<name of validator>
17 17 <name> must equal form name
18 18 list=[1,2,3,4,5]
19 19 for SELECT use formencode.All(OneOf(list), Int())
20 20
21 21 """
22 22 from formencode import All
23 23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 24 Email, Bool, StringBoolean
25 25 from pylons import session
26 26 from pylons.i18n.translation import _
27 27 from rhodecode.lib.auth import check_password, get_crypt_password
28 28 from rhodecode.model import meta
29 29 from rhodecode.model.user_model import UserModel
30 30 from rhodecode.model.db import User, Repository
31 31 from sqlalchemy.exc import OperationalError
32 32 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
33 33 from webhelpers.pylonslib.secure_form import authentication_token
34 34 import formencode
35 35 import logging
36 36 import os
37 37 import rhodecode.lib.helpers as h
38 38 log = logging.getLogger(__name__)
39 39
40 40
41 41 #this is needed to translate the messages using _() in validators
42 42 class State_obj(object):
43 43 _ = staticmethod(_)
44 44
45 45 #===============================================================================
46 46 # VALIDATORS
47 47 #===============================================================================
48 48 class ValidAuthToken(formencode.validators.FancyValidator):
49 49 messages = {'invalid_token':_('Token mismatch')}
50 50
51 51 def validate_python(self, value, state):
52 52
53 53 if value != authentication_token():
54 54 raise formencode.Invalid(self.message('invalid_token', state,
55 55 search_number=value), value, state)
56 56
57 57 def ValidUsername(edit, old_data):
58 58 class _ValidUsername(formencode.validators.FancyValidator):
59 59
60 60 def validate_python(self, value, state):
61 61 if value in ['default', 'new_user']:
62 62 raise formencode.Invalid(_('Invalid username'), value, state)
63 63 #check if user is uniq
64 64 sa = meta.Session
65 65 old_un = None
66 66 if edit:
67 67 old_un = sa.query(User).get(old_data.get('user_id')).username
68 68
69 69 if old_un != value or not edit:
70 70 if sa.query(User).filter(User.username == value).scalar():
71 71 raise formencode.Invalid(_('This username already exists') ,
72 72 value, state)
73 73 meta.Session.remove()
74 74
75 75 return _ValidUsername
76 76
77 77 class ValidPassword(formencode.validators.FancyValidator):
78 78
79 79 def to_python(self, value, state):
80 80 if value:
81 81 return get_crypt_password(value)
82 82
83 83 class ValidAuth(formencode.validators.FancyValidator):
84 84 messages = {
85 85 'invalid_password':_('invalid password'),
86 86 'invalid_login':_('invalid user name'),
87 87 'disabled_account':_('Your acccount is disabled')
88 88
89 89 }
90 90 #error mapping
91 91 e_dict = {'username':messages['invalid_login'],
92 92 'password':messages['invalid_password']}
93 93 e_dict_disable = {'username':messages['disabled_account']}
94 94
95 95 def validate_python(self, value, state):
96 96 password = value['password']
97 97 username = value['username']
98 98 user = UserModel().get_user_by_name(username)
99 99 if user is None:
100 100 raise formencode.Invalid(self.message('invalid_password',
101 101 state=State_obj), value, state,
102 102 error_dict=self.e_dict)
103 103 if user:
104 104 if user.active:
105 105 if user.username == username and check_password(password,
106 106 user.password):
107 107 return value
108 108 else:
109 109 log.warning('user %s not authenticated', username)
110 110 raise formencode.Invalid(self.message('invalid_password',
111 111 state=State_obj), value, state,
112 112 error_dict=self.e_dict)
113 113 else:
114 114 log.warning('user %s is disabled', username)
115 115 raise formencode.Invalid(self.message('disabled_account',
116 116 state=State_obj),
117 117 value, state,
118 118 error_dict=self.e_dict_disable)
119 119
120 120 class ValidRepoUser(formencode.validators.FancyValidator):
121 121
122 122 def to_python(self, value, state):
123 123 try:
124 124 self.user_db = meta.Session.query(User)\
125 125 .filter(User.active == True)\
126 126 .filter(User.username == value).one()
127 127 except Exception:
128 128 raise formencode.Invalid(_('This username is not valid'),
129 129 value, state)
130 130 finally:
131 131 meta.Session.remove()
132 132
133 133 return self.user_db.user_id
134 134
135 135 def ValidRepoName(edit, old_data):
136 136 class _ValidRepoName(formencode.validators.FancyValidator):
137 137
138 138 def to_python(self, value, state):
139 139 slug = h.repo_name_slug(value)
140 140 if slug in ['_admin']:
141 141 raise formencode.Invalid(_('This repository name is disallowed'),
142 142 value, state)
143 143 if old_data.get('repo_name') != value or not edit:
144 144 sa = meta.Session
145 145 if sa.query(Repository).filter(Repository.repo_name == slug).scalar():
146 146 raise formencode.Invalid(_('This repository already exists') ,
147 147 value, state)
148 148 meta.Session.remove()
149 149 return slug
150 150
151 151
152 152 return _ValidRepoName
153 153
154 154 class ValidPerms(formencode.validators.FancyValidator):
155 155 messages = {'perm_new_user_name':_('This username is not valid')}
156 156
157 157 def to_python(self, value, state):
158 158 perms_update = []
159 159 perms_new = []
160 160 #build a list of permission to update and new permission to create
161 161 for k, v in value.items():
162 162 if k.startswith('perm_'):
163 163 if k.startswith('perm_new_user'):
164 164 new_perm = value.get('perm_new_user', False)
165 165 new_user = value.get('perm_new_user_name', False)
166 166 if new_user and new_perm:
167 167 if (new_user, new_perm) not in perms_new:
168 168 perms_new.append((new_user, new_perm))
169 169 else:
170 170 usr = k[5:]
171 171 if usr == 'default':
172 172 if value['private']:
173 173 #set none for default when updating to private repo
174 174 v = 'repository.none'
175 175 perms_update.append((usr, v))
176 176 value['perms_updates'] = perms_update
177 177 value['perms_new'] = perms_new
178 178 sa = meta.Session
179 179 for k, v in perms_new:
180 180 try:
181 181 self.user_db = sa.query(User)\
182 182 .filter(User.active == True)\
183 183 .filter(User.username == k).one()
184 184 except Exception:
185 185 msg = self.message('perm_new_user_name',
186 186 state=State_obj)
187 187 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
188 188 return value
189 189
190 190 class ValidSettings(formencode.validators.FancyValidator):
191 191
192 192 def to_python(self, value, state):
193 193 #settings form can't edit user
194 194 if value.has_key('user'):
195 195 del['value']['user']
196 196
197 197 return value
198 198
199 199 class ValidPath(formencode.validators.FancyValidator):
200 200 def to_python(self, value, state):
201 201 isdir = os.path.isdir(value.replace('*', ''))
202 202 if (value.endswith('/*') or value.endswith('/**')) and isdir:
203 203 return value
204 204 elif not isdir:
205 205 msg = _('This is not a valid path')
206 206 else:
207 207 msg = _('You need to specify * or ** at the end of path (ie. /tmp/*)')
208 208
209 209 raise formencode.Invalid(msg, value, state,
210 210 error_dict={'paths_root_path':msg})
211 211
212 212 def UniqSystemEmail(old_data):
213 213 class _UniqSystemEmail(formencode.validators.FancyValidator):
214 214 def to_python(self, value, state):
215 215 if old_data.get('email') != value:
216 216 sa = meta.Session
217 217 try:
218 218 user = sa.query(User).filter(User.email == value).scalar()
219 219 if user:
220 220 raise formencode.Invalid(_("That e-mail address is already taken") ,
221 221 value, state)
222 222 finally:
223 223 meta.Session.remove()
224 224
225 225 return value
226 226
227 227 return _UniqSystemEmail
228 228
229 229 class ValidSystemEmail(formencode.validators.FancyValidator):
230 230 def to_python(self, value, state):
231 231 sa = meta.Session
232 232 try:
233 233 user = sa.query(User).filter(User.email == value).scalar()
234 234 if user is None:
235 235 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
236 236 value, state)
237 237 finally:
238 238 meta.Session.remove()
239 239
240 240 return value
241 241
242 242 #===============================================================================
243 243 # FORMS
244 244 #===============================================================================
245 245 class LoginForm(formencode.Schema):
246 246 allow_extra_fields = True
247 247 filter_extra_fields = True
248 248 username = UnicodeString(
249 249 strip=True,
250 250 min=1,
251 251 not_empty=True,
252 252 messages={
253 253 'empty':_('Please enter a login'),
254 254 'tooShort':_('Enter a value %(min)i characters long or more')}
255 255 )
256 256
257 257 password = UnicodeString(
258 258 strip=True,
259 259 min=6,
260 260 not_empty=True,
261 261 messages={
262 262 'empty':_('Please enter a password'),
263 'tooShort':_('Enter a value %(min)i characters long or more')}
263 'tooShort':_('Enter %(min)i characters or more')}
264 264 )
265 265
266 266
267 267 #chained validators have access to all data
268 268 chained_validators = [ValidAuth]
269 269
270 270 def UserForm(edit=False, old_data={}):
271 271 class _UserForm(formencode.Schema):
272 272 allow_extra_fields = True
273 273 filter_extra_fields = True
274 274 username = All(UnicodeString(strip=True, min=1, not_empty=True), ValidUsername(edit, old_data))
275 275 if edit:
276 276 new_password = All(UnicodeString(strip=True, min=6, not_empty=False), ValidPassword)
277 277 admin = StringBoolean(if_missing=False)
278 278 else:
279 279 password = All(UnicodeString(strip=True, min=6, not_empty=True), ValidPassword)
280 280 active = StringBoolean(if_missing=False)
281 281 name = UnicodeString(strip=True, min=1, not_empty=True)
282 282 lastname = UnicodeString(strip=True, min=1, not_empty=True)
283 283 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
284 284
285 285 return _UserForm
286 286
287 287 RegisterForm = UserForm
288 288
289 289 def PasswordResetForm():
290 290 class _PasswordResetForm(formencode.Schema):
291 291 allow_extra_fields = True
292 292 filter_extra_fields = True
293 293 email = All(ValidSystemEmail(), Email(not_empty=True))
294 294 return _PasswordResetForm
295 295
296 296 def RepoForm(edit=False, old_data={}):
297 297 class _RepoForm(formencode.Schema):
298 298 allow_extra_fields = True
299 299 filter_extra_fields = False
300 300 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
301 301 description = UnicodeString(strip=True, min=1, not_empty=True)
302 302 private = StringBoolean(if_missing=False)
303 303
304 304 if edit:
305 305 user = All(Int(not_empty=True), ValidRepoUser)
306 306
307 307 chained_validators = [ValidPerms]
308 308 return _RepoForm
309 309
310 310 def RepoForkForm(edit=False, old_data={}):
311 311 class _RepoForkForm(formencode.Schema):
312 312 allow_extra_fields = True
313 313 filter_extra_fields = False
314 314 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
315 315 description = UnicodeString(strip=True, min=1, not_empty=True)
316 316 private = StringBoolean(if_missing=False)
317 317
318 318 return _RepoForkForm
319 319
320 320 def RepoSettingsForm(edit=False, old_data={}):
321 321 class _RepoForm(formencode.Schema):
322 322 allow_extra_fields = True
323 323 filter_extra_fields = False
324 324 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
325 325 description = UnicodeString(strip=True, min=1, not_empty=True)
326 326 private = StringBoolean(if_missing=False)
327 327
328 328 chained_validators = [ValidPerms, ValidSettings]
329 329 return _RepoForm
330 330
331 331
332 332 def ApplicationSettingsForm():
333 333 class _ApplicationSettingsForm(formencode.Schema):
334 334 allow_extra_fields = True
335 335 filter_extra_fields = False
336 336 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
337 337 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
338 338
339 339 return _ApplicationSettingsForm
340 340
341 341 def ApplicationUiSettingsForm():
342 342 class _ApplicationUiSettingsForm(formencode.Schema):
343 343 allow_extra_fields = True
344 344 filter_extra_fields = False
345 345 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
346 346 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
347 347 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
348 348 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
349 349
350 350 return _ApplicationUiSettingsForm
351 351
352 352 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
353 353 class _DefaultPermissionsForm(formencode.Schema):
354 354 allow_extra_fields = True
355 355 filter_extra_fields = True
356 356 overwrite_default = OneOf(['true', 'false'], if_missing='false')
357 357 default_perm = OneOf(perms_choices)
358 358 default_register = OneOf(register_choices)
359 359 default_create = OneOf(create_choices)
360 360
361 361 return _DefaultPermissionsForm
@@ -1,44 +1,26 b''
1 1 """Setup the rhodecode application"""
2 from os.path import dirname as dn, join as jn
3 2 from rhodecode.config.environment import load_environment
4 3 from rhodecode.lib.db_manage import DbManage
5 4 import logging
6 5 import os
7 import shutil
8 6
9 7 log = logging.getLogger(__name__)
10 ROOT = dn(os.path.realpath(__file__))
11 8
12 9 def setup_app(command, conf, vars):
13 10 """Place any commands to setup rhodecode here"""
14 print dn(os.path.realpath(__file__))
15 print(ROOT)
16 11 dbname = os.path.split(conf['sqlalchemy.db1.url'])[-1]
17 12 dbmanage = DbManage(log_sql=True, dbname=dbname, root=conf['here'],
18 13 tests=False)
19 14 dbmanage.create_tables(override=True)
20 15 dbmanage.config_prompt(None)
21 16 dbmanage.create_default_user()
22 17 dbmanage.admin_prompt()
23 18 dbmanage.create_permissions()
24 19 dbmanage.populate_default_permissions()
25 20
26 celeryconfig_file = 'celeryconfig.py'
27
28 celeryconfig_path = jn(ROOT, celeryconfig_file)
29
30
31 if not os.path.isfile(jn(conf['here'], celeryconfig_file)):
32 try:
33 shutil.copy(celeryconfig_path, conf['here'])
34 except IOError:
35 log.error('failed to copy celeryconfig.py from source %s '
36 ' to this directory please copy it manually ',
37 celeryconfig_path)
38 else:
39 21 load_environment(conf.global_conf, conf.local_conf, initial=True)
40 22
41 23
42 24
43 25
44 26
General Comments 0
You need to be logged in to leave comments. Login now