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