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