##// END OF EJS Templates
fixed ldap settings creation, we need to fill in some bool defaults properly to make it work fine
marcink -
r1138:9c45e114 beta
parent child Browse files
Show More
@@ -1,536 +1,519 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.db_manage
4 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Database creation, and setup module for RhodeCode. Used for creation
7 7 of database as well as for migration operations
8 8
9 9 :created_on: Apr 10, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software; you can redistribute it and/or
15 15 # modify it under the terms of the GNU General Public License
16 16 # as published by the Free Software Foundation; version 2
17 17 # of the License or (at your opinion) any later version of the license.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program; if not, write to the Free Software
26 26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 27 # MA 02110-1301, USA.
28 28
29 29 import os
30 30 import sys
31 31 import uuid
32 32 import logging
33 33 from os.path import dirname as dn, join as jn
34 34
35 35 from rhodecode import __dbversion__
36 36 from rhodecode.model import meta
37 37
38 38 from rhodecode.lib.auth import get_crypt_password, generate_api_key
39 39 from rhodecode.lib.utils import ask_ok
40 40 from rhodecode.model import init_model
41 41 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
42 42 UserToPerm, DbMigrateVersion
43 43
44 44 from sqlalchemy.engine import create_engine
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48 class DbManage(object):
49 49 def __init__(self, log_sql, dbconf, root, tests=False):
50 50 self.dbname = dbconf.split('/')[-1]
51 51 self.tests = tests
52 52 self.root = root
53 53 self.dburi = dbconf
54 54 self.log_sql = log_sql
55 55 self.db_exists = False
56 56 self.init_db()
57 57
58 58 def init_db(self):
59 59 engine = create_engine(self.dburi, echo=self.log_sql)
60 60 init_model(engine)
61 61 self.sa = meta.Session()
62 62
63 def check_for_db(self, override):
64 db_path = jn(self.root, self.dbname)
65 if self.dburi.startswith('sqlite'):
66 log.info('checking for existing db in %s', db_path)
67 if os.path.isfile(db_path):
68
69 self.db_exists = True
70 if not override:
71 raise Exception('database already exists')
72 return 'sqlite'
73 if self.dburi.startswith('postgresql'):
74 self.db_exists = True
75 return 'postgresql'
76
77
78 63 def create_tables(self, override=False):
79 64 """Create a auth database
80 65 """
81 66
82 db_type = self.check_for_db(override)
83 if self.db_exists:
84 log.info("database exist and it's going to be destroyed")
85 if self.tests:
86 destroy = True
87 else:
88 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
89 if not destroy:
90 sys.exit()
91 if self.db_exists and destroy:
92 if db_type == 'sqlite':
93 os.remove(jn(self.root, self.dbname))
94 if db_type == 'postgresql':
95 meta.Base.metadata.drop_all()
67 log.info("Any existing database is going to be destroyed")
68 if self.tests:
69 destroy = True
70 else:
71 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
72 if not destroy:
73 sys.exit()
74 if destroy:
75 meta.Base.metadata.drop_all()
96 76
97 77 checkfirst = not override
98 78 meta.Base.metadata.create_all(checkfirst=checkfirst)
99 79 log.info('Created tables for %s', self.dbname)
100 80
101 81
102 82
103 83 def set_db_version(self):
104 84 try:
105 85 ver = DbMigrateVersion()
106 86 ver.version = __dbversion__
107 87 ver.repository_id = 'rhodecode_db_migrations'
108 88 ver.repository_path = 'versions'
109 89 self.sa.add(ver)
110 90 self.sa.commit()
111 91 except:
112 92 self.sa.rollback()
113 93 raise
114 94 log.info('db version set to: %s', __dbversion__)
115 95
116 96
117 97 def upgrade(self):
118 98 """Upgrades given database schema to given revision following
119 99 all needed steps, to perform the upgrade
120 100
121 101 """
122 102
123 103 from rhodecode.lib.dbmigrate.migrate.versioning import api
124 104 from rhodecode.lib.dbmigrate.migrate.exceptions import \
125 105 DatabaseNotControlledError
126 106
127 107 upgrade = ask_ok('You are about to perform database upgrade, make '
128 108 'sure You backed up your database before. '
129 109 'Continue ? [y/n]')
130 110 if not upgrade:
131 111 sys.exit('Nothing done')
132 112
133 113 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
134 114 'rhodecode/lib/dbmigrate')
135 115 db_uri = self.dburi
136 116
137 117 try:
138 118 curr_version = api.db_version(db_uri, repository_path)
139 119 msg = ('Found current database under version'
140 120 ' control with version %s' % curr_version)
141 121
142 122 except (RuntimeError, DatabaseNotControlledError), e:
143 123 curr_version = 1
144 124 msg = ('Current database is not under version control. Setting'
145 125 ' as version %s' % curr_version)
146 126 api.version_control(db_uri, repository_path, curr_version)
147 127
148 128 print (msg)
149 129
150 130 if curr_version == __dbversion__:
151 131 sys.exit('This database is already at the newest version')
152 132
153 133 #======================================================================
154 134 # UPGRADE STEPS
155 135 #======================================================================
156 136 class UpgradeSteps(object):
157 137 """Those steps follow schema versions so for example schema
158 138 for example schema with seq 002 == step_2 and so on.
159 139 """
160 140
161 141 def __init__(self, klass):
162 142 self.klass = klass
163 143
164 144 def step_0(self):
165 145 #step 0 is the schema upgrade, and than follow proper upgrades
166 146 print ('attempting to do database upgrade to version %s' \
167 147 % __dbversion__)
168 148 api.upgrade(db_uri, repository_path, __dbversion__)
169 149 print ('Schema upgrade completed')
170 150
171 151 def step_1(self):
172 152 pass
173 153
174 154 def step_2(self):
175 155 print ('Patching repo paths for newer version of RhodeCode')
176 156 self.klass.fix_repo_paths()
177 157
178 158 print ('Patching default user of RhodeCode')
179 159 self.klass.fix_default_user()
180 160
181 161 log.info('Changing ui settings')
182 162 self.klass.create_ui_settings()
183 163
184 164 def step_3(self):
185 165 print ('Adding additional settings into RhodeCode db')
186 166 self.klass.fix_settings()
187 167
188 168 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
189 169
190 170 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
191 171 for step in upgrade_steps:
192 172 print ('performing upgrade step %s' % step)
193 173 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
194 174
195 175
196 176
197 177 def fix_repo_paths(self):
198 178 """Fixes a old rhodecode version path into new one without a '*'
199 179 """
200 180
201 181 paths = self.sa.query(RhodeCodeUi)\
202 182 .filter(RhodeCodeUi.ui_key == '/')\
203 183 .scalar()
204 184
205 185 paths.ui_value = paths.ui_value.replace('*', '')
206 186
207 187 try:
208 188 self.sa.add(paths)
209 189 self.sa.commit()
210 190 except:
211 191 self.sa.rollback()
212 192 raise
213 193
214 194 def fix_default_user(self):
215 195 """Fixes a old default user with some 'nicer' default values,
216 196 used mostly for anonymous access
217 197 """
218 198 def_user = self.sa.query(User)\
219 199 .filter(User.username == 'default')\
220 200 .one()
221 201
222 202 def_user.name = 'Anonymous'
223 203 def_user.lastname = 'User'
224 204 def_user.email = 'anonymous@rhodecode.org'
225 205
226 206 try:
227 207 self.sa.add(def_user)
228 208 self.sa.commit()
229 209 except:
230 210 self.sa.rollback()
231 211 raise
232 212
233 213 def fix_settings(self):
234 214 """Fixes rhodecode settings adds ga_code key for google analytics
235 215 """
236 216
237 217 hgsettings3 = RhodeCodeSettings('ga_code', '')
238 218
239 219 try:
240 220 self.sa.add(hgsettings3)
241 221 self.sa.commit()
242 222 except:
243 223 self.sa.rollback()
244 224 raise
245 225
246 226 def admin_prompt(self, second=False):
247 227 if not self.tests:
248 228 import getpass
249 229
250 230
251 231 def get_password():
252 232 password = getpass.getpass('Specify admin password (min 6 chars):')
253 233 confirm = getpass.getpass('Confirm password:')
254 234
255 235 if password != confirm:
256 236 log.error('passwords mismatch')
257 237 return False
258 238 if len(password) < 6:
259 239 log.error('password is to short use at least 6 characters')
260 240 return False
261 241
262 242 return password
263 243
264 244 username = raw_input('Specify admin username:')
265 245
266 246 password = get_password()
267 247 if not password:
268 248 #second try
269 249 password = get_password()
270 250 if not password:
271 251 sys.exit()
272 252
273 253 email = raw_input('Specify admin email:')
274 254 self.create_user(username, password, email, True)
275 255 else:
276 256 log.info('creating admin and regular test users')
277 257 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
278 258 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
279 259 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
280 260
281 261 def create_ui_settings(self):
282 262 """Creates ui settings, fills out hooks
283 263 and disables dotencode
284 264
285 265 """
286 266 #HOOKS
287 267 hooks1_key = 'changegroup.update'
288 268 hooks1_ = self.sa.query(RhodeCodeUi)\
289 269 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
290 270
291 271 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
292 272 hooks1.ui_section = 'hooks'
293 273 hooks1.ui_key = hooks1_key
294 274 hooks1.ui_value = 'hg update >&2'
295 275 hooks1.ui_active = False
296 276
297 277 hooks2_key = 'changegroup.repo_size'
298 278 hooks2_ = self.sa.query(RhodeCodeUi)\
299 279 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
300 280
301 281 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
302 282 hooks2.ui_section = 'hooks'
303 283 hooks2.ui_key = hooks2_key
304 284 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
305 285
306 286 hooks3 = RhodeCodeUi()
307 287 hooks3.ui_section = 'hooks'
308 288 hooks3.ui_key = 'pretxnchangegroup.push_logger'
309 289 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
310 290
311 291 hooks4 = RhodeCodeUi()
312 292 hooks4.ui_section = 'hooks'
313 293 hooks4.ui_key = 'preoutgoing.pull_logger'
314 294 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
315 295
316 296 #For mercurial 1.7 set backward comapatibility with format
317 297 dotencode_disable = RhodeCodeUi()
318 298 dotencode_disable.ui_section = 'format'
319 299 dotencode_disable.ui_key = 'dotencode'
320 300 dotencode_disable.ui_value = 'false'
321 301
322 302 try:
323 303 self.sa.add(hooks1)
324 304 self.sa.add(hooks2)
325 305 self.sa.add(hooks3)
326 306 self.sa.add(hooks4)
327 307 self.sa.add(dotencode_disable)
328 308 self.sa.commit()
329 309 except:
330 310 self.sa.rollback()
331 311 raise
332 312
333 313
334 314 def create_ldap_options(self):
335 315 """Creates ldap settings"""
336 316
337 317 try:
338 for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
339 'ldap_tls_reqcert', 'ldap_dn_user', 'ldap_dn_pass',
340 'ldap_base_dn', 'ldap_filter', 'ldap_search_scope',
341 'ldap_attr_login', 'ldap_attr_firstname', 'ldap_attr_lastname',
342 'ldap_attr_email']:
318 for k, v in [('ldap_active', 'false'), ('ldap_host', ''),
319 ('ldap_port', '389'), ('ldap_ldaps', 'false'),
320 ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''),
321 ('ldap_dn_pass', ''), ('ldap_base_dn', ''),
322 ('ldap_filter', ''), ('ldap_search_scope', ''),
323 ('ldap_attr_login', ''), ('ldap_attr_firstname', ''),
324 ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]:
343 325
344 setting = RhodeCodeSettings(k, '')
326
327 setting = RhodeCodeSettings(k, v)
345 328 self.sa.add(setting)
346 329 self.sa.commit()
347 330 except:
348 331 self.sa.rollback()
349 332 raise
350 333
351 334 def config_prompt(self, test_repo_path='', retries=3):
352 335 if retries == 3:
353 336 log.info('Setting up repositories config')
354 337
355 338 if not self.tests and not test_repo_path:
356 339 path = raw_input('Specify valid full path to your repositories'
357 340 ' you can change this later in application settings:')
358 341 else:
359 342 path = test_repo_path
360 343 path_ok = True
361 344
362 345 #check proper dir
363 346 if not os.path.isdir(path):
364 347 path_ok = False
365 348 log.error('Entered path is not a valid directory: %s [%s/3]',
366 349 path, retries)
367 350
368 351 #check write access
369 352 if not os.access(path, os.W_OK):
370 353 path_ok = False
371 354
372 355 log.error('No write permission to given path: %s [%s/3]',
373 356 path, retries)
374 357
375 358
376 359 if retries == 0:
377 360 sys.exit()
378 361 if path_ok is False:
379 362 retries -= 1
380 363 return self.config_prompt(test_repo_path, retries)
381 364
382 365
383 366 return path
384 367
385 368 def create_settings(self, path):
386 369
387 370 self.create_ui_settings()
388 371
389 372 #HG UI OPTIONS
390 373 web1 = RhodeCodeUi()
391 374 web1.ui_section = 'web'
392 375 web1.ui_key = 'push_ssl'
393 376 web1.ui_value = 'false'
394 377
395 378 web2 = RhodeCodeUi()
396 379 web2.ui_section = 'web'
397 380 web2.ui_key = 'allow_archive'
398 381 web2.ui_value = 'gz zip bz2'
399 382
400 383 web3 = RhodeCodeUi()
401 384 web3.ui_section = 'web'
402 385 web3.ui_key = 'allow_push'
403 386 web3.ui_value = '*'
404 387
405 388 web4 = RhodeCodeUi()
406 389 web4.ui_section = 'web'
407 390 web4.ui_key = 'baseurl'
408 391 web4.ui_value = '/'
409 392
410 393 paths = RhodeCodeUi()
411 394 paths.ui_section = 'paths'
412 395 paths.ui_key = '/'
413 396 paths.ui_value = path
414 397
415 398
416 399 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
417 400 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
418 401 hgsettings3 = RhodeCodeSettings('ga_code', '')
419 402
420 403
421 404 try:
422 405 self.sa.add(web1)
423 406 self.sa.add(web2)
424 407 self.sa.add(web3)
425 408 self.sa.add(web4)
426 409 self.sa.add(paths)
427 410 self.sa.add(hgsettings1)
428 411 self.sa.add(hgsettings2)
429 412 self.sa.add(hgsettings3)
430 413
431 414 self.sa.commit()
432 415 except:
433 416 self.sa.rollback()
434 417 raise
435 418
436 419 self.create_ldap_options()
437 420
438 421 log.info('created ui config')
439 422
440 423 def create_user(self, username, password, email='', admin=False):
441 424 log.info('creating administrator user %s', username)
442 425 new_user = User()
443 426 new_user.username = username
444 427 new_user.password = get_crypt_password(password)
445 428 new_user.api_key = generate_api_key(username)
446 429 new_user.name = 'RhodeCode'
447 430 new_user.lastname = 'Admin'
448 431 new_user.email = email
449 432 new_user.admin = admin
450 433 new_user.active = True
451 434
452 435 try:
453 436 self.sa.add(new_user)
454 437 self.sa.commit()
455 438 except:
456 439 self.sa.rollback()
457 440 raise
458 441
459 442 def create_default_user(self):
460 443 log.info('creating default user')
461 444 #create default user for handling default permissions.
462 445 def_user = User()
463 446 def_user.username = 'default'
464 447 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
465 448 def_user.api_key = generate_api_key('default')
466 449 def_user.name = 'Anonymous'
467 450 def_user.lastname = 'User'
468 451 def_user.email = 'anonymous@rhodecode.org'
469 452 def_user.admin = False
470 453 def_user.active = False
471 454 try:
472 455 self.sa.add(def_user)
473 456 self.sa.commit()
474 457 except:
475 458 self.sa.rollback()
476 459 raise
477 460
478 461 def create_permissions(self):
479 462 #module.(access|create|change|delete)_[name]
480 463 #module.(read|write|owner)
481 464 perms = [('repository.none', 'Repository no access'),
482 465 ('repository.read', 'Repository read access'),
483 466 ('repository.write', 'Repository write access'),
484 467 ('repository.admin', 'Repository admin access'),
485 468 ('hg.admin', 'Hg Administrator'),
486 469 ('hg.create.repository', 'Repository create'),
487 470 ('hg.create.none', 'Repository creation disabled'),
488 471 ('hg.register.none', 'Register disabled'),
489 472 ('hg.register.manual_activate', 'Register new user with RhodeCode without manual activation'),
490 473 ('hg.register.auto_activate', 'Register new user with RhodeCode without auto activation'),
491 474 ]
492 475
493 476 for p in perms:
494 477 new_perm = Permission()
495 478 new_perm.permission_name = p[0]
496 479 new_perm.permission_longname = p[1]
497 480 try:
498 481 self.sa.add(new_perm)
499 482 self.sa.commit()
500 483 except:
501 484 self.sa.rollback()
502 485 raise
503 486
504 487 def populate_default_permissions(self):
505 488 log.info('creating default user permissions')
506 489
507 490 default_user = self.sa.query(User)\
508 491 .filter(User.username == 'default').scalar()
509 492
510 493 reg_perm = UserToPerm()
511 494 reg_perm.user = default_user
512 495 reg_perm.permission = self.sa.query(Permission)\
513 496 .filter(Permission.permission_name == 'hg.register.manual_activate')\
514 497 .scalar()
515 498
516 499 create_repo_perm = UserToPerm()
517 500 create_repo_perm.user = default_user
518 501 create_repo_perm.permission = self.sa.query(Permission)\
519 502 .filter(Permission.permission_name == 'hg.create.repository')\
520 503 .scalar()
521 504
522 505 default_repo_perm = UserToPerm()
523 506 default_repo_perm.user = default_user
524 507 default_repo_perm.permission = self.sa.query(Permission)\
525 508 .filter(Permission.permission_name == 'repository.read')\
526 509 .scalar()
527 510
528 511 try:
529 512 self.sa.add(reg_perm)
530 513 self.sa.add(create_repo_perm)
531 514 self.sa.add(default_repo_perm)
532 515 self.sa.commit()
533 516 except:
534 517 self.sa.rollback()
535 518 raise
536 519
General Comments 0
You need to be logged in to leave comments. Login now