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