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