comparison rhodecode/lib/db_manage.py @ 2031:82a88013a3fd

merge 1.3 into stable
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 26 Feb 2012 17:25:09 +0200
parents a7a282a902b2 34d009e5147a
children dc2584ba5fbc
comparison
equal deleted inserted replaced
2005:ab0e122b38a7 2031:82a88013a3fd
6 Database creation, and setup module for RhodeCode. Used for creation 6 Database creation, and setup module for RhodeCode. Used for creation
7 of database as well as for migration operations 7 of database as well as for migration operations
8 8
9 :created_on: Apr 10, 2010 9 :created_on: Apr 10, 2010
10 :author: marcink 10 :author: marcink
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com> 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details. 12 :license: GPLv3, see COPYING for more details.
13 """ 13 """
14 # This program is free software: you can redistribute it and/or modify 14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by 15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or 16 # the Free Software Foundation, either version 3 of the License, or
31 from os.path import dirname as dn, join as jn 31 from os.path import dirname as dn, join as jn
32 32
33 from rhodecode import __dbversion__ 33 from rhodecode import __dbversion__
34 from rhodecode.model import meta 34 from rhodecode.model import meta
35 35
36 from rhodecode.lib.auth import get_crypt_password, generate_api_key 36 from rhodecode.model.user import UserModel
37 from rhodecode.lib.utils import ask_ok 37 from rhodecode.lib.utils import ask_ok
38 from rhodecode.model import init_model 38 from rhodecode.model import init_model
39 from rhodecode.model.db import User, Permission, RhodeCodeUi, \ 39 from rhodecode.model.db import User, Permission, RhodeCodeUi, \
40 RhodeCodeSettings, UserToPerm, DbMigrateVersion 40 RhodeCodeSetting, UserToPerm, DbMigrateVersion, RepoGroup,\
41 UserRepoGroupToPerm
41 42
42 from sqlalchemy.engine import create_engine 43 from sqlalchemy.engine import create_engine
44 from rhodecode.model.repos_group import ReposGroupModel
43 45
44 log = logging.getLogger(__name__) 46 log = logging.getLogger(__name__)
45 47
46 48
47 class DbManage(object): 49 class DbManage(object):
55 self.init_db() 57 self.init_db()
56 58
57 def init_db(self): 59 def init_db(self):
58 engine = create_engine(self.dburi, echo=self.log_sql) 60 engine = create_engine(self.dburi, echo=self.log_sql)
59 init_model(engine) 61 init_model(engine)
60 self.sa = meta.Session() 62 self.sa = meta.Session
61 63
62 def create_tables(self, override=False): 64 def create_tables(self, override=False):
63 """Create a auth database 65 """
66 Create a auth database
64 """ 67 """
65 68
66 log.info("Any existing database is going to be destroyed") 69 log.info("Any existing database is going to be destroyed")
67 if self.tests: 70 if self.tests:
68 destroy = True 71 destroy = True
73 if destroy: 76 if destroy:
74 meta.Base.metadata.drop_all() 77 meta.Base.metadata.drop_all()
75 78
76 checkfirst = not override 79 checkfirst = not override
77 meta.Base.metadata.create_all(checkfirst=checkfirst) 80 meta.Base.metadata.create_all(checkfirst=checkfirst)
78 log.info('Created tables for %s', self.dbname) 81 log.info('Created tables for %s' % self.dbname)
79 82
80 def set_db_version(self): 83 def set_db_version(self):
81 try: 84 ver = DbMigrateVersion()
82 ver = DbMigrateVersion() 85 ver.version = __dbversion__
83 ver.version = __dbversion__ 86 ver.repository_id = 'rhodecode_db_migrations'
84 ver.repository_id = 'rhodecode_db_migrations' 87 ver.repository_path = 'versions'
85 ver.repository_path = 'versions' 88 self.sa.add(ver)
86 self.sa.add(ver) 89 log.info('db version set to: %s' % __dbversion__)
87 self.sa.commit()
88 except:
89 self.sa.rollback()
90 raise
91 log.info('db version set to: %s', __dbversion__)
92 90
93 def upgrade(self): 91 def upgrade(self):
94 """Upgrades given database schema to given revision following 92 """
93 Upgrades given database schema to given revision following
95 all needed steps, to perform the upgrade 94 all needed steps, to perform the upgrade
96 95
97 """ 96 """
98 97
99 from rhodecode.lib.dbmigrate.migrate.versioning import api 98 from rhodecode.lib.dbmigrate.migrate.versioning import api
144 143
145 def __init__(self, klass): 144 def __init__(self, klass):
146 self.klass = klass 145 self.klass = klass
147 146
148 def step_0(self): 147 def step_0(self):
149 #step 0 is the schema upgrade, and than follow proper upgrades 148 # step 0 is the schema upgrade, and than follow proper upgrades
150 print ('attempting to do database upgrade to version %s' \ 149 print ('attempting to do database upgrade to version %s' \
151 % __dbversion__) 150 % __dbversion__)
152 api.upgrade(db_uri, repository_path, __dbversion__) 151 api.upgrade(db_uri, repository_path, __dbversion__)
153 print ('Schema upgrade completed') 152 print ('Schema upgrade completed')
154 153
168 def step_3(self): 167 def step_3(self):
169 print ('Adding additional settings into RhodeCode db') 168 print ('Adding additional settings into RhodeCode db')
170 self.klass.fix_settings() 169 self.klass.fix_settings()
171 print ('Adding ldap defaults') 170 print ('Adding ldap defaults')
172 self.klass.create_ldap_options(skip_existing=True) 171 self.klass.create_ldap_options(skip_existing=True)
173 172
173 def step_4(self):
174 print ('create permissions and fix groups')
175 self.klass.create_permissions()
176 self.klass.fixup_groups()
177
178 def step_5(self):
179 pass
180
174 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1) 181 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
175 182
176 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE 183 # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
177 for step in upgrade_steps: 184 for step in upgrade_steps:
178 print ('performing upgrade step %s' % step) 185 print ('performing upgrade step %s' % step)
179 getattr(UpgradeSteps(self), 'step_%s' % step)() 186 getattr(UpgradeSteps(self), 'step_%s' % step)()
187 self.sa.commit()
180 188
181 def fix_repo_paths(self): 189 def fix_repo_paths(self):
182 """Fixes a old rhodecode version path into new one without a '*' 190 """
191 Fixes a old rhodecode version path into new one without a '*'
183 """ 192 """
184 193
185 paths = self.sa.query(RhodeCodeUi)\ 194 paths = self.sa.query(RhodeCodeUi)\
186 .filter(RhodeCodeUi.ui_key == '/')\ 195 .filter(RhodeCodeUi.ui_key == '/')\
187 .scalar() 196 .scalar()
194 except: 203 except:
195 self.sa.rollback() 204 self.sa.rollback()
196 raise 205 raise
197 206
198 def fix_default_user(self): 207 def fix_default_user(self):
199 """Fixes a old default user with some 'nicer' default values, 208 """
209 Fixes a old default user with some 'nicer' default values,
200 used mostly for anonymous access 210 used mostly for anonymous access
201 """ 211 """
202 def_user = self.sa.query(User)\ 212 def_user = self.sa.query(User)\
203 .filter(User.username == 'default')\ 213 .filter(User.username == 'default')\
204 .one() 214 .one()
213 except: 223 except:
214 self.sa.rollback() 224 self.sa.rollback()
215 raise 225 raise
216 226
217 def fix_settings(self): 227 def fix_settings(self):
218 """Fixes rhodecode settings adds ga_code key for google analytics 228 """
219 """ 229 Fixes rhodecode settings adds ga_code key for google analytics
220 230 """
221 hgsettings3 = RhodeCodeSettings('ga_code', '') 231
232 hgsettings3 = RhodeCodeSetting('ga_code', '')
222 233
223 try: 234 try:
224 self.sa.add(hgsettings3) 235 self.sa.add(hgsettings3)
225 self.sa.commit() 236 self.sa.commit()
226 except: 237 except:
256 267
257 email = raw_input('Specify admin email:') 268 email = raw_input('Specify admin email:')
258 self.create_user(username, password, email, True) 269 self.create_user(username, password, email, True)
259 else: 270 else:
260 log.info('creating admin and regular test users') 271 log.info('creating admin and regular test users')
261 self.create_user('test_admin', 'test12', 272 from rhodecode.tests import TEST_USER_ADMIN_LOGIN,\
262 'test_admin@mail.com', True) 273 TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL,\
263 self.create_user('test_regular', 'test12', 274 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,\
264 'test_regular@mail.com', False) 275 TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
265 self.create_user('test_regular2', 'test12', 276 TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
266 'test_regular2@mail.com', False) 277
278 self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
279 TEST_USER_ADMIN_EMAIL, True)
280
281 self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
282 TEST_USER_REGULAR_EMAIL, False)
283
284 self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
285 TEST_USER_REGULAR2_EMAIL, False)
267 286
268 def create_ui_settings(self): 287 def create_ui_settings(self):
269 """Creates ui settings, fills out hooks 288 """
289 Creates ui settings, fills out hooks
270 and disables dotencode 290 and disables dotencode
271 291 """
272 """ 292
273 #HOOKS 293 #HOOKS
274 hooks1_key = RhodeCodeUi.HOOK_UPDATE 294 hooks1_key = RhodeCodeUi.HOOK_UPDATE
275 hooks1_ = self.sa.query(RhodeCodeUi)\ 295 hooks1_ = self.sa.query(RhodeCodeUi)\
276 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar() 296 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
277 297
298 hooks4 = RhodeCodeUi() 318 hooks4 = RhodeCodeUi()
299 hooks4.ui_section = 'hooks' 319 hooks4.ui_section = 'hooks'
300 hooks4.ui_key = RhodeCodeUi.HOOK_PULL 320 hooks4.ui_key = RhodeCodeUi.HOOK_PULL
301 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action' 321 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
302 322
303 #For mercurial 1.7 set backward comapatibility with format 323 # For mercurial 1.7 set backward comapatibility with format
304 dotencode_disable = RhodeCodeUi() 324 dotencode_disable = RhodeCodeUi()
305 dotencode_disable.ui_section = 'format' 325 dotencode_disable.ui_section = 'format'
306 dotencode_disable.ui_key = 'dotencode' 326 dotencode_disable.ui_key = 'dotencode'
307 dotencode_disable.ui_value = 'false' 327 dotencode_disable.ui_value = 'false'
308 328
310 largefiles = RhodeCodeUi() 330 largefiles = RhodeCodeUi()
311 largefiles.ui_section = 'extensions' 331 largefiles.ui_section = 'extensions'
312 largefiles.ui_key = 'largefiles' 332 largefiles.ui_key = 'largefiles'
313 largefiles.ui_value = '' 333 largefiles.ui_value = ''
314 334
315 try: 335 self.sa.add(hooks1)
316 self.sa.add(hooks1) 336 self.sa.add(hooks2)
317 self.sa.add(hooks2) 337 self.sa.add(hooks3)
318 self.sa.add(hooks3) 338 self.sa.add(hooks4)
319 self.sa.add(hooks4) 339 self.sa.add(largefiles)
320 self.sa.add(dotencode_disable) 340
321 self.sa.add(largefiles) 341 def create_ldap_options(self, skip_existing=False):
322 self.sa.commit()
323 except:
324 self.sa.rollback()
325 raise
326
327 def create_ldap_options(self,skip_existing=False):
328 """Creates ldap settings""" 342 """Creates ldap settings"""
329 343
330 try: 344 for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
331 for k, v in [('ldap_active', 'false'), ('ldap_host', ''), 345 ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'),
332 ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'), 346 ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
333 ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''), 347 ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
334 ('ldap_dn_pass', ''), ('ldap_base_dn', ''), 348 ('ldap_filter', ''), ('ldap_search_scope', ''),
335 ('ldap_filter', ''), ('ldap_search_scope', ''), 349 ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
336 ('ldap_attr_login', ''), ('ldap_attr_firstname', ''), 350 ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:
337 ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]: 351
338 352 if skip_existing and RhodeCodeSetting.get_by_name(k) != None:
339 if skip_existing and RhodeCodeSettings.get_by_name(k) != None: 353 log.debug('Skipping option %s' % k)
340 log.debug('Skipping option %s' % k) 354 continue
341 continue 355 setting = RhodeCodeSetting(k, v)
342 setting = RhodeCodeSettings(k, v) 356 self.sa.add(setting)
343 self.sa.add(setting) 357
344 self.sa.commit() 358 def fixup_groups(self):
345 except: 359 def_usr = User.get_by_username('default')
346 self.sa.rollback() 360 for g in RepoGroup.query().all():
347 raise 361 g.group_name = g.get_new_name(g.name)
362 self.sa.add(g)
363 # get default perm
364 default = UserRepoGroupToPerm.query()\
365 .filter(UserRepoGroupToPerm.group == g)\
366 .filter(UserRepoGroupToPerm.user == def_usr)\
367 .scalar()
368
369 if default is None:
370 log.debug('missing default permission for group %s adding' % g)
371 ReposGroupModel()._create_default_perms(g)
348 372
349 def config_prompt(self, test_repo_path='', retries=3): 373 def config_prompt(self, test_repo_path='', retries=3):
350 if retries == 3: 374 if retries == 3:
351 log.info('Setting up repositories config') 375 log.info('Setting up repositories config')
352 376
357 ) 381 )
358 else: 382 else:
359 path = test_repo_path 383 path = test_repo_path
360 path_ok = True 384 path_ok = True
361 385
362 #check proper dir 386 # check proper dir
363 if not os.path.isdir(path): 387 if not os.path.isdir(path):
364 path_ok = False 388 path_ok = False
365 log.error('Given path %s is not a valid directory', path) 389 log.error('Given path %s is not a valid directory' % path)
366 390
367 #check write access 391 # check write access
368 if not os.access(path, os.W_OK) and path_ok: 392 if not os.access(path, os.W_OK) and path_ok:
369 path_ok = False 393 path_ok = False
370 log.error('No write permission to given path %s', path) 394 log.error('No write permission to given path %s' % path)
371
372 395
373 if retries == 0: 396 if retries == 0:
374 sys.exit('max retries reached') 397 sys.exit('max retries reached')
375 if path_ok is False: 398 if path_ok is False:
376 retries -= 1 399 retries -= 1
406 paths = RhodeCodeUi() 429 paths = RhodeCodeUi()
407 paths.ui_section = 'paths' 430 paths.ui_section = 'paths'
408 paths.ui_key = '/' 431 paths.ui_key = '/'
409 paths.ui_value = path 432 paths.ui_value = path
410 433
411 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication') 434 hgsettings1 = RhodeCodeSetting('realm', 'RhodeCode authentication')
412 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode') 435 hgsettings2 = RhodeCodeSetting('title', 'RhodeCode')
413 hgsettings3 = RhodeCodeSettings('ga_code', '') 436 hgsettings3 = RhodeCodeSetting('ga_code', '')
414 437
415 try: 438 self.sa.add(web1)
416 self.sa.add(web1) 439 self.sa.add(web2)
417 self.sa.add(web2) 440 self.sa.add(web3)
418 self.sa.add(web3) 441 self.sa.add(web4)
419 self.sa.add(web4) 442 self.sa.add(paths)
420 self.sa.add(paths) 443 self.sa.add(hgsettings1)
421 self.sa.add(hgsettings1) 444 self.sa.add(hgsettings2)
422 self.sa.add(hgsettings2) 445 self.sa.add(hgsettings3)
423 self.sa.add(hgsettings3)
424
425 self.sa.commit()
426 except:
427 self.sa.rollback()
428 raise
429 446
430 self.create_ldap_options() 447 self.create_ldap_options()
431 448
432 log.info('created ui config') 449 log.info('created ui config')
433 450
434 def create_user(self, username, password, email='', admin=False): 451 def create_user(self, username, password, email='', admin=False):
435 log.info('creating administrator user %s', username) 452 log.info('creating user %s' % username)
436 453 UserModel().create_or_update(username, password, email,
437 form_data = dict(username=username, 454 name='RhodeCode', lastname='Admin',
438 password=password, 455 active=True, admin=admin)
439 active=True,
440 admin=admin,
441 name='RhodeCode',
442 lastname='Admin',
443 email=email)
444 User.create(form_data)
445
446 456
447 def create_default_user(self): 457 def create_default_user(self):
448 log.info('creating default user') 458 log.info('creating default user')
449 #create default user for handling default permissions. 459 # create default user for handling default permissions.
450 460 UserModel().create_or_update(username='default',
451 form_data = dict(username='default', 461 password=str(uuid.uuid1())[:8],
452 password=str(uuid.uuid1())[:8], 462 email='anonymous@rhodecode.org',
453 active=False, 463 name='Anonymous', lastname='User')
454 admin=False, 464
455 name='Anonymous',
456 lastname='User',
457 email='anonymous@rhodecode.org')
458 User.create(form_data)
459
460 def create_permissions(self): 465 def create_permissions(self):
461 #module.(access|create|change|delete)_[name] 466 # module.(access|create|change|delete)_[name]
462 #module.(read|write|owner) 467 # module.(none|read|write|admin)
463 perms = [('repository.none', 'Repository no access'), 468 perms = [
464 ('repository.read', 'Repository read access'), 469 ('repository.none', 'Repository no access'),
465 ('repository.write', 'Repository write access'), 470 ('repository.read', 'Repository read access'),
466 ('repository.admin', 'Repository admin access'), 471 ('repository.write', 'Repository write access'),
467 ('hg.admin', 'Hg Administrator'), 472 ('repository.admin', 'Repository admin access'),
468 ('hg.create.repository', 'Repository create'), 473
469 ('hg.create.none', 'Repository creation disabled'), 474 ('group.none', 'Repositories Group no access'),
470 ('hg.register.none', 'Register disabled'), 475 ('group.read', 'Repositories Group read access'),
471 ('hg.register.manual_activate', 'Register new user with ' 476 ('group.write', 'Repositories Group write access'),
472 'RhodeCode without manual' 477 ('group.admin', 'Repositories Group admin access'),
473 'activation'), 478
474 479 ('hg.admin', 'Hg Administrator'),
475 ('hg.register.auto_activate', 'Register new user with ' 480 ('hg.create.repository', 'Repository create'),
476 'RhodeCode without auto ' 481 ('hg.create.none', 'Repository creation disabled'),
477 'activation'), 482 ('hg.register.none', 'Register disabled'),
478 ] 483 ('hg.register.manual_activate', 'Register new user with RhodeCode '
484 'without manual activation'),
485
486 ('hg.register.auto_activate', 'Register new user with RhodeCode '
487 'without auto activation'),
488 ]
479 489
480 for p in perms: 490 for p in perms:
481 new_perm = Permission() 491 if not Permission.get_by_key(p[0]):
482 new_perm.permission_name = p[0] 492 new_perm = Permission()
483 new_perm.permission_longname = p[1] 493 new_perm.permission_name = p[0]
484 try: 494 new_perm.permission_longname = p[1]
485 self.sa.add(new_perm) 495 self.sa.add(new_perm)
486 self.sa.commit()
487 except:
488 self.sa.rollback()
489 raise
490 496
491 def populate_default_permissions(self): 497 def populate_default_permissions(self):
492 log.info('creating default user permissions') 498 log.info('creating default user permissions')
493 499
494 default_user = self.sa.query(User)\ 500 default_user = self.sa.query(User)\
510 default_repo_perm.user = default_user 516 default_repo_perm.user = default_user
511 default_repo_perm.permission = self.sa.query(Permission)\ 517 default_repo_perm.permission = self.sa.query(Permission)\
512 .filter(Permission.permission_name == 'repository.read')\ 518 .filter(Permission.permission_name == 'repository.read')\
513 .scalar() 519 .scalar()
514 520
515 try: 521 self.sa.add(reg_perm)
516 self.sa.add(reg_perm) 522 self.sa.add(create_repo_perm)
517 self.sa.add(create_repo_perm) 523 self.sa.add(default_repo_perm)
518 self.sa.add(default_repo_perm)
519 self.sa.commit()
520 except:
521 self.sa.rollback()
522 raise