##// END OF EJS Templates
rc-upgrade-db: added option to force update a version.
marcink -
r3406:1afbe459 default
parent child Browse files
Show More
@@ -1,621 +1,624 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Database creation, and setup module for RhodeCode Enterprise. Used for creation
23 23 of database as well as for migration operations
24 24 """
25 25
26 26 import os
27 27 import sys
28 28 import time
29 29 import uuid
30 30 import logging
31 31 import getpass
32 32 from os.path import dirname as dn, join as jn
33 33
34 34 from sqlalchemy.engine import create_engine
35 35
36 36 from rhodecode import __dbversion__
37 37 from rhodecode.model import init_model
38 38 from rhodecode.model.user import UserModel
39 39 from rhodecode.model.db import (
40 40 User, Permission, RhodeCodeUi, RhodeCodeSetting, UserToPerm,
41 41 DbMigrateVersion, RepoGroup, UserRepoGroupToPerm, CacheKey, Repository)
42 42 from rhodecode.model.meta import Session, Base
43 43 from rhodecode.model.permission import PermissionModel
44 44 from rhodecode.model.repo import RepoModel
45 45 from rhodecode.model.repo_group import RepoGroupModel
46 46 from rhodecode.model.settings import SettingsModel
47 47
48 48
49 49 log = logging.getLogger(__name__)
50 50
51 51
52 52 def notify(msg):
53 53 """
54 54 Notification for migrations messages
55 55 """
56 56 ml = len(msg) + (4 * 2)
57 57 print(('\n%s\n*** %s ***\n%s' % ('*' * ml, msg, '*' * ml)).upper())
58 58
59 59
60 60 class DbManage(object):
61 61
62 62 def __init__(self, log_sql, dbconf, root, tests=False,
63 63 SESSION=None, cli_args=None):
64 64 self.dbname = dbconf.split('/')[-1]
65 65 self.tests = tests
66 66 self.root = root
67 67 self.dburi = dbconf
68 68 self.log_sql = log_sql
69 69 self.db_exists = False
70 70 self.cli_args = cli_args or {}
71 71 self.init_db(SESSION=SESSION)
72 72 self.ask_ok = self.get_ask_ok_func(self.cli_args.get('force_ask'))
73 73
74 74 def get_ask_ok_func(self, param):
75 75 if param not in [None]:
76 76 # return a function lambda that has a default set to param
77 77 return lambda *args, **kwargs: param
78 78 else:
79 79 from rhodecode.lib.utils import ask_ok
80 80 return ask_ok
81 81
82 82 def init_db(self, SESSION=None):
83 83 if SESSION:
84 84 self.sa = SESSION
85 85 else:
86 86 # init new sessions
87 87 engine = create_engine(self.dburi, echo=self.log_sql)
88 88 init_model(engine)
89 89 self.sa = Session()
90 90
91 91 def create_tables(self, override=False):
92 92 """
93 93 Create a auth database
94 94 """
95 95
96 96 log.info("Existing database with the same name is going to be destroyed.")
97 97 log.info("Setup command will run DROP ALL command on that database.")
98 98 if self.tests:
99 99 destroy = True
100 100 else:
101 101 destroy = self.ask_ok('Are you sure that you want to destroy the old database? [y/n]')
102 102 if not destroy:
103 103 log.info('Nothing done.')
104 104 sys.exit(0)
105 105 if destroy:
106 106 Base.metadata.drop_all()
107 107
108 108 checkfirst = not override
109 109 Base.metadata.create_all(checkfirst=checkfirst)
110 110 log.info('Created tables for %s', self.dbname)
111 111
112 112 def set_db_version(self):
113 113 ver = DbMigrateVersion()
114 114 ver.version = __dbversion__
115 115 ver.repository_id = 'rhodecode_db_migrations'
116 116 ver.repository_path = 'versions'
117 117 self.sa.add(ver)
118 118 log.info('db version set to: %s', __dbversion__)
119 119
120 120 def run_pre_migration_tasks(self):
121 121 """
122 122 Run various tasks before actually doing migrations
123 123 """
124 124 # delete cache keys on each upgrade
125 125 total = CacheKey.query().count()
126 126 log.info("Deleting (%s) cache keys now...", total)
127 127 CacheKey.delete_all_cache()
128 128
129 129 def upgrade(self, version=None):
130 130 """
131 131 Upgrades given database schema to given revision following
132 132 all needed steps, to perform the upgrade
133 133
134 134 """
135 135
136 136 from rhodecode.lib.dbmigrate.migrate.versioning import api
137 137 from rhodecode.lib.dbmigrate.migrate.exceptions import \
138 138 DatabaseNotControlledError
139 139
140 140 if 'sqlite' in self.dburi:
141 141 print(
142 142 '********************** WARNING **********************\n'
143 143 'Make sure your version of sqlite is at least 3.7.X. \n'
144 144 'Earlier versions are known to fail on some migrations\n'
145 145 '*****************************************************\n')
146 146
147 147 upgrade = self.ask_ok(
148 148 'You are about to perform a database upgrade. Make '
149 149 'sure you have backed up your database. '
150 150 'Continue ? [y/n]')
151 151 if not upgrade:
152 152 log.info('No upgrade performed')
153 153 sys.exit(0)
154 154
155 155 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
156 156 'rhodecode/lib/dbmigrate')
157 157 db_uri = self.dburi
158 158
159 if version:
160 DbMigrateVersion.set_version(version)
161
159 162 try:
160 curr_version = version or api.db_version(db_uri, repository_path)
163 curr_version = api.db_version(db_uri, repository_path)
161 164 msg = ('Found current database db_uri under version '
162 165 'control with version {}'.format(curr_version))
163 166
164 167 except (RuntimeError, DatabaseNotControlledError):
165 168 curr_version = 1
166 169 msg = ('Current database is not under version control. Setting '
167 170 'as version %s' % curr_version)
168 171 api.version_control(db_uri, repository_path, curr_version)
169 172
170 173 notify(msg)
171 174
172 175 self.run_pre_migration_tasks()
173 176
174 177 if curr_version == __dbversion__:
175 178 log.info('This database is already at the newest version')
176 179 sys.exit(0)
177 180
178 181 upgrade_steps = range(curr_version + 1, __dbversion__ + 1)
179 182 notify('attempting to upgrade database from '
180 183 'version %s to version %s' % (curr_version, __dbversion__))
181 184
182 185 # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
183 186 _step = None
184 187 for step in upgrade_steps:
185 188 notify('performing upgrade step %s' % step)
186 189 time.sleep(0.5)
187 190
188 191 api.upgrade(db_uri, repository_path, step)
189 192 self.sa.rollback()
190 193 notify('schema upgrade for step %s completed' % (step,))
191 194
192 195 _step = step
193 196
194 197 notify('upgrade to version %s successful' % _step)
195 198
196 199 def fix_repo_paths(self):
197 200 """
198 201 Fixes an old RhodeCode version path into new one without a '*'
199 202 """
200 203
201 204 paths = self.sa.query(RhodeCodeUi)\
202 205 .filter(RhodeCodeUi.ui_key == '/')\
203 206 .scalar()
204 207
205 208 paths.ui_value = paths.ui_value.replace('*', '')
206 209
207 210 try:
208 211 self.sa.add(paths)
209 212 self.sa.commit()
210 213 except Exception:
211 214 self.sa.rollback()
212 215 raise
213 216
214 217 def fix_default_user(self):
215 218 """
216 219 Fixes an old default user with some 'nicer' default values,
217 220 used mostly for anonymous access
218 221 """
219 222 def_user = self.sa.query(User)\
220 223 .filter(User.username == User.DEFAULT_USER)\
221 224 .one()
222 225
223 226 def_user.name = 'Anonymous'
224 227 def_user.lastname = 'User'
225 228 def_user.email = User.DEFAULT_USER_EMAIL
226 229
227 230 try:
228 231 self.sa.add(def_user)
229 232 self.sa.commit()
230 233 except Exception:
231 234 self.sa.rollback()
232 235 raise
233 236
234 237 def fix_settings(self):
235 238 """
236 239 Fixes rhodecode settings and adds ga_code key for google analytics
237 240 """
238 241
239 242 hgsettings3 = RhodeCodeSetting('ga_code', '')
240 243
241 244 try:
242 245 self.sa.add(hgsettings3)
243 246 self.sa.commit()
244 247 except Exception:
245 248 self.sa.rollback()
246 249 raise
247 250
248 251 def create_admin_and_prompt(self):
249 252
250 253 # defaults
251 254 defaults = self.cli_args
252 255 username = defaults.get('username')
253 256 password = defaults.get('password')
254 257 email = defaults.get('email')
255 258
256 259 if username is None:
257 260 username = raw_input('Specify admin username:')
258 261 if password is None:
259 262 password = self._get_admin_password()
260 263 if not password:
261 264 # second try
262 265 password = self._get_admin_password()
263 266 if not password:
264 267 sys.exit()
265 268 if email is None:
266 269 email = raw_input('Specify admin email:')
267 270 api_key = self.cli_args.get('api_key')
268 271 self.create_user(username, password, email, True,
269 272 strict_creation_check=False,
270 273 api_key=api_key)
271 274
272 275 def _get_admin_password(self):
273 276 password = getpass.getpass('Specify admin password '
274 277 '(min 6 chars):')
275 278 confirm = getpass.getpass('Confirm password:')
276 279
277 280 if password != confirm:
278 281 log.error('passwords mismatch')
279 282 return False
280 283 if len(password) < 6:
281 284 log.error('password is too short - use at least 6 characters')
282 285 return False
283 286
284 287 return password
285 288
286 289 def create_test_admin_and_users(self):
287 290 log.info('creating admin and regular test users')
288 291 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \
289 292 TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
290 293 TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
291 294 TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
292 295 TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL
293 296
294 297 self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS,
295 298 TEST_USER_ADMIN_EMAIL, True, api_key=True)
296 299
297 300 self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS,
298 301 TEST_USER_REGULAR_EMAIL, False, api_key=True)
299 302
300 303 self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS,
301 304 TEST_USER_REGULAR2_EMAIL, False, api_key=True)
302 305
303 306 def create_ui_settings(self, repo_store_path):
304 307 """
305 308 Creates ui settings, fills out hooks
306 309 and disables dotencode
307 310 """
308 311 settings_model = SettingsModel(sa=self.sa)
309 312 from rhodecode.lib.vcs.backends.hg import largefiles_store
310 313 from rhodecode.lib.vcs.backends.git import lfs_store
311 314
312 315 # Build HOOKS
313 316 hooks = [
314 317 (RhodeCodeUi.HOOK_REPO_SIZE, 'python:vcsserver.hooks.repo_size'),
315 318
316 319 # HG
317 320 (RhodeCodeUi.HOOK_PRE_PULL, 'python:vcsserver.hooks.pre_pull'),
318 321 (RhodeCodeUi.HOOK_PULL, 'python:vcsserver.hooks.log_pull_action'),
319 322 (RhodeCodeUi.HOOK_PRE_PUSH, 'python:vcsserver.hooks.pre_push'),
320 323 (RhodeCodeUi.HOOK_PRETX_PUSH, 'python:vcsserver.hooks.pre_push'),
321 324 (RhodeCodeUi.HOOK_PUSH, 'python:vcsserver.hooks.log_push_action'),
322 325 (RhodeCodeUi.HOOK_PUSH_KEY, 'python:vcsserver.hooks.key_push'),
323 326
324 327 ]
325 328
326 329 for key, value in hooks:
327 330 hook_obj = settings_model.get_ui_by_key(key)
328 331 hooks2 = hook_obj if hook_obj else RhodeCodeUi()
329 332 hooks2.ui_section = 'hooks'
330 333 hooks2.ui_key = key
331 334 hooks2.ui_value = value
332 335 self.sa.add(hooks2)
333 336
334 337 # enable largefiles
335 338 largefiles = RhodeCodeUi()
336 339 largefiles.ui_section = 'extensions'
337 340 largefiles.ui_key = 'largefiles'
338 341 largefiles.ui_value = ''
339 342 self.sa.add(largefiles)
340 343
341 344 # set default largefiles cache dir, defaults to
342 345 # /repo_store_location/.cache/largefiles
343 346 largefiles = RhodeCodeUi()
344 347 largefiles.ui_section = 'largefiles'
345 348 largefiles.ui_key = 'usercache'
346 349 largefiles.ui_value = largefiles_store(repo_store_path)
347 350
348 351 self.sa.add(largefiles)
349 352
350 353 # set default lfs cache dir, defaults to
351 354 # /repo_store_location/.cache/lfs_store
352 355 lfsstore = RhodeCodeUi()
353 356 lfsstore.ui_section = 'vcs_git_lfs'
354 357 lfsstore.ui_key = 'store_location'
355 358 lfsstore.ui_value = lfs_store(repo_store_path)
356 359
357 360 self.sa.add(lfsstore)
358 361
359 362 # enable hgsubversion disabled by default
360 363 hgsubversion = RhodeCodeUi()
361 364 hgsubversion.ui_section = 'extensions'
362 365 hgsubversion.ui_key = 'hgsubversion'
363 366 hgsubversion.ui_value = ''
364 367 hgsubversion.ui_active = False
365 368 self.sa.add(hgsubversion)
366 369
367 370 # enable hgevolve disabled by default
368 371 hgevolve = RhodeCodeUi()
369 372 hgevolve.ui_section = 'extensions'
370 373 hgevolve.ui_key = 'evolve'
371 374 hgevolve.ui_value = ''
372 375 hgevolve.ui_active = False
373 376 self.sa.add(hgevolve)
374 377
375 378 # enable hggit disabled by default
376 379 hggit = RhodeCodeUi()
377 380 hggit.ui_section = 'extensions'
378 381 hggit.ui_key = 'hggit'
379 382 hggit.ui_value = ''
380 383 hggit.ui_active = False
381 384 self.sa.add(hggit)
382 385
383 386 # set svn branch defaults
384 387 branches = ["/branches/*", "/trunk"]
385 388 tags = ["/tags/*"]
386 389
387 390 for branch in branches:
388 391 settings_model.create_ui_section_value(
389 392 RhodeCodeUi.SVN_BRANCH_ID, branch)
390 393
391 394 for tag in tags:
392 395 settings_model.create_ui_section_value(RhodeCodeUi.SVN_TAG_ID, tag)
393 396
394 397 def create_auth_plugin_options(self, skip_existing=False):
395 398 """
396 399 Create default auth plugin settings, and make it active
397 400
398 401 :param skip_existing:
399 402 """
400 403
401 404 for k, v, t in [('auth_plugins', 'egg:rhodecode-enterprise-ce#rhodecode', 'list'),
402 405 ('auth_rhodecode_enabled', 'True', 'bool')]:
403 406 if (skip_existing and
404 407 SettingsModel().get_setting_by_name(k) is not None):
405 408 log.debug('Skipping option %s', k)
406 409 continue
407 410 setting = RhodeCodeSetting(k, v, t)
408 411 self.sa.add(setting)
409 412
410 413 def create_default_options(self, skip_existing=False):
411 414 """Creates default settings"""
412 415
413 416 for k, v, t in [
414 417 ('default_repo_enable_locking', False, 'bool'),
415 418 ('default_repo_enable_downloads', False, 'bool'),
416 419 ('default_repo_enable_statistics', False, 'bool'),
417 420 ('default_repo_private', False, 'bool'),
418 421 ('default_repo_type', 'hg', 'unicode')]:
419 422
420 423 if (skip_existing and
421 424 SettingsModel().get_setting_by_name(k) is not None):
422 425 log.debug('Skipping option %s', k)
423 426 continue
424 427 setting = RhodeCodeSetting(k, v, t)
425 428 self.sa.add(setting)
426 429
427 430 def fixup_groups(self):
428 431 def_usr = User.get_default_user()
429 432 for g in RepoGroup.query().all():
430 433 g.group_name = g.get_new_name(g.name)
431 434 self.sa.add(g)
432 435 # get default perm
433 436 default = UserRepoGroupToPerm.query()\
434 437 .filter(UserRepoGroupToPerm.group == g)\
435 438 .filter(UserRepoGroupToPerm.user == def_usr)\
436 439 .scalar()
437 440
438 441 if default is None:
439 442 log.debug('missing default permission for group %s adding', g)
440 443 perm_obj = RepoGroupModel()._create_default_perms(g)
441 444 self.sa.add(perm_obj)
442 445
443 446 def reset_permissions(self, username):
444 447 """
445 448 Resets permissions to default state, useful when old systems had
446 449 bad permissions, we must clean them up
447 450
448 451 :param username:
449 452 """
450 453 default_user = User.get_by_username(username)
451 454 if not default_user:
452 455 return
453 456
454 457 u2p = UserToPerm.query()\
455 458 .filter(UserToPerm.user == default_user).all()
456 459 fixed = False
457 460 if len(u2p) != len(Permission.DEFAULT_USER_PERMISSIONS):
458 461 for p in u2p:
459 462 Session().delete(p)
460 463 fixed = True
461 464 self.populate_default_permissions()
462 465 return fixed
463 466
464 467 def update_repo_info(self):
465 468 RepoModel.update_repoinfo()
466 469
467 470 def config_prompt(self, test_repo_path='', retries=3):
468 471 defaults = self.cli_args
469 472 _path = defaults.get('repos_location')
470 473 if retries == 3:
471 474 log.info('Setting up repositories config')
472 475
473 476 if _path is not None:
474 477 path = _path
475 478 elif not self.tests and not test_repo_path:
476 479 path = raw_input(
477 480 'Enter a valid absolute path to store repositories. '
478 481 'All repositories in that path will be added automatically:'
479 482 )
480 483 else:
481 484 path = test_repo_path
482 485 path_ok = True
483 486
484 487 # check proper dir
485 488 if not os.path.isdir(path):
486 489 path_ok = False
487 490 log.error('Given path %s is not a valid directory', path)
488 491
489 492 elif not os.path.isabs(path):
490 493 path_ok = False
491 494 log.error('Given path %s is not an absolute path', path)
492 495
493 496 # check if path is at least readable.
494 497 if not os.access(path, os.R_OK):
495 498 path_ok = False
496 499 log.error('Given path %s is not readable', path)
497 500
498 501 # check write access, warn user about non writeable paths
499 502 elif not os.access(path, os.W_OK) and path_ok:
500 503 log.warning('No write permission to given path %s', path)
501 504
502 505 q = ('Given path %s is not writeable, do you want to '
503 506 'continue with read only mode ? [y/n]' % (path,))
504 507 if not self.ask_ok(q):
505 508 log.error('Canceled by user')
506 509 sys.exit(-1)
507 510
508 511 if retries == 0:
509 512 sys.exit('max retries reached')
510 513 if not path_ok:
511 514 retries -= 1
512 515 return self.config_prompt(test_repo_path, retries)
513 516
514 517 real_path = os.path.normpath(os.path.realpath(path))
515 518
516 519 if real_path != os.path.normpath(path):
517 520 q = ('Path looks like a symlink, RhodeCode Enterprise will store '
518 521 'given path as %s ? [y/n]') % (real_path,)
519 522 if not self.ask_ok(q):
520 523 log.error('Canceled by user')
521 524 sys.exit(-1)
522 525
523 526 return real_path
524 527
525 528 def create_settings(self, path):
526 529
527 530 self.create_ui_settings(path)
528 531
529 532 ui_config = [
530 533 ('web', 'push_ssl', 'False'),
531 534 ('web', 'allow_archive', 'gz zip bz2'),
532 535 ('web', 'allow_push', '*'),
533 536 ('web', 'baseurl', '/'),
534 537 ('paths', '/', path),
535 538 ('phases', 'publish', 'True')
536 539 ]
537 540 for section, key, value in ui_config:
538 541 ui_conf = RhodeCodeUi()
539 542 setattr(ui_conf, 'ui_section', section)
540 543 setattr(ui_conf, 'ui_key', key)
541 544 setattr(ui_conf, 'ui_value', value)
542 545 self.sa.add(ui_conf)
543 546
544 547 # rhodecode app settings
545 548 settings = [
546 549 ('realm', 'RhodeCode', 'unicode'),
547 550 ('title', '', 'unicode'),
548 551 ('pre_code', '', 'unicode'),
549 552 ('post_code', '', 'unicode'),
550 553 ('show_public_icon', True, 'bool'),
551 554 ('show_private_icon', True, 'bool'),
552 555 ('stylify_metatags', False, 'bool'),
553 556 ('dashboard_items', 100, 'int'),
554 557 ('admin_grid_items', 25, 'int'),
555 558 ('show_version', True, 'bool'),
556 559 ('use_gravatar', False, 'bool'),
557 560 ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'),
558 561 ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'),
559 562 ('support_url', '', 'unicode'),
560 563 ('update_url', RhodeCodeSetting.DEFAULT_UPDATE_URL, 'unicode'),
561 564 ('show_revision_number', True, 'bool'),
562 565 ('show_sha_length', 12, 'int'),
563 566 ]
564 567
565 568 for key, val, type_ in settings:
566 569 sett = RhodeCodeSetting(key, val, type_)
567 570 self.sa.add(sett)
568 571
569 572 self.create_auth_plugin_options()
570 573 self.create_default_options()
571 574
572 575 log.info('created ui config')
573 576
574 577 def create_user(self, username, password, email='', admin=False,
575 578 strict_creation_check=True, api_key=None):
576 579 log.info('creating user `%s`', username)
577 580 user = UserModel().create_or_update(
578 581 username, password, email, firstname=u'RhodeCode', lastname=u'Admin',
579 582 active=True, admin=admin, extern_type="rhodecode",
580 583 strict_creation_check=strict_creation_check)
581 584
582 585 if api_key:
583 586 log.info('setting a new default auth token for user `%s`', username)
584 587 UserModel().add_auth_token(
585 588 user=user, lifetime_minutes=-1,
586 589 role=UserModel.auth_token_role.ROLE_ALL,
587 590 description=u'BUILTIN TOKEN')
588 591
589 592 def create_default_user(self):
590 593 log.info('creating default user')
591 594 # create default user for handling default permissions.
592 595 user = UserModel().create_or_update(username=User.DEFAULT_USER,
593 596 password=str(uuid.uuid1())[:20],
594 597 email=User.DEFAULT_USER_EMAIL,
595 598 firstname=u'Anonymous',
596 599 lastname=u'User',
597 600 strict_creation_check=False)
598 601 # based on configuration options activate/de-activate this user which
599 602 # controlls anonymous access
600 603 if self.cli_args.get('public_access') is False:
601 604 log.info('Public access disabled')
602 605 user.active = False
603 606 Session().add(user)
604 607 Session().commit()
605 608
606 609 def create_permissions(self):
607 610 """
608 611 Creates all permissions defined in the system
609 612 """
610 613 # module.(access|create|change|delete)_[name]
611 614 # module.(none|read|write|admin)
612 615 log.info('creating permissions')
613 616 PermissionModel(self.sa).create_permissions()
614 617
615 618 def populate_default_permissions(self):
616 619 """
617 620 Populate default permissions. It will create only the default
618 621 permissions that are missing, and not alter already defined ones
619 622 """
620 623 log.info('creating default user permissions')
621 624 PermissionModel(self.sa).create_default_user_permissions(user=User.DEFAULT_USER)
@@ -1,52 +1,55 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 import click
24 24 import pyramid.paster
25 25
26 26 from rhodecode.lib.pyramid_utils import bootstrap
27 27 from rhodecode.lib.db_manage import DbManage
28 from rhodecode.lib.utils2 import safe_int
28 29
29 30 log = logging.getLogger(__name__)
30 31
31 32
32 33 @click.command()
33 34 @click.argument('ini_path', type=click.Path(exists=True))
34 35 @click.option('--force-yes/--force-no', default=None,
35 36 help="Force yes/no to every question")
36 def main(ini_path, force_yes):
37 return command(ini_path, force_yes)
37 @click.option('--force-version', default=None,
38 help="Force upgrade from version")
39 def main(ini_path, force_yes, force_version):
40 return command(ini_path, force_yes, force_version)
38 41
39 42
40 def command(ini_path, force_yes):
43 def command(ini_path, force_yes, force_version):
41 44 pyramid.paster.setup_logging(ini_path)
42 45
43 46 with bootstrap(ini_path, env={'RC_CMD_UPGRADE_DB': '1'}) as env:
44 47 config = env['registry'].settings
45 48 db_uri = config['sqlalchemy.db1.url']
46 49 options = {}
47 50 if force_yes is not None:
48 51 options['force_ask'] = force_yes
49 52 dbmanage = DbManage(
50 53 log_sql=True, dbconf=db_uri, root='.', tests=False,
51 54 cli_args=options)
52 dbmanage.upgrade()
55 dbmanage.upgrade(version=safe_int(force_version))
General Comments 0
You need to be logged in to leave comments. Login now