##// END OF EJS Templates
ssh: embedded ssh support...
marcink -
r2043:338dc54d default
parent child Browse files
Show More
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
This diff has been collapsed as it changes many lines, (607 lines changed) Show them Hide them
@@ -0,0 +1,607 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import os
22 import re
23 import sys
24 import json
25 import logging
26 import random
27 import signal
28 import tempfile
29 from subprocess import Popen, PIPE, check_output, CalledProcessError
30 import ConfigParser
31 import urllib2
32 import urlparse
33
34 import click
35 import pyramid.paster
36
37
38 log = logging.getLogger(__name__)
39
40
41 def setup_logging(ini_path, debug):
42 if debug:
43 # enabled rhodecode.ini controlled logging setup
44 pyramid.paster.setup_logging(ini_path)
45 else:
46 # configure logging in a mode that doesn't print anything.
47 # in case of regularly configured logging it gets printed out back
48 # to the client doing an SSH command.
49 logger = logging.getLogger('')
50 null = logging.NullHandler()
51 # add the handler to the root logger
52 logger.handlers = [null]
53
54
55 class SubversionTunnelWrapper(object):
56 process = None
57
58 def __init__(self, timeout, repositories_root=None, svn_path=None):
59 self.timeout = timeout
60 self.stdin = sys.stdin
61 self.repositories_root = repositories_root
62 self.svn_path = svn_path or 'svnserve'
63 self.svn_conf_fd, self.svn_conf_path = tempfile.mkstemp()
64 self.hooks_env_fd, self.hooks_env_path = tempfile.mkstemp()
65 self.read_only = False
66 self.create_svn_config()
67
68 def create_svn_config(self):
69 content = (
70 '[general]\n'
71 'hooks-env = {}\n').format(self.hooks_env_path)
72 with os.fdopen(self.svn_conf_fd, 'w') as config_file:
73 config_file.write(content)
74
75 def create_hooks_env(self):
76 content = (
77 '[default]\n'
78 'LANG = en_US.UTF-8\n')
79 if self.read_only:
80 content += 'SSH_READ_ONLY = 1\n'
81 with os.fdopen(self.hooks_env_fd, 'w') as hooks_env_file:
82 hooks_env_file.write(content)
83
84 def remove_configs(self):
85 os.remove(self.svn_conf_path)
86 os.remove(self.hooks_env_path)
87
88 def start(self):
89 config = ['--config-file', self.svn_conf_path]
90 command = [self.svn_path, '-t'] + config
91 if self.repositories_root:
92 command.extend(['-r', self.repositories_root])
93 self.process = Popen(command, stdin=PIPE)
94
95 def sync(self):
96 while self.process.poll() is None:
97 next_byte = self.stdin.read(1)
98 if not next_byte:
99 break
100 self.process.stdin.write(next_byte)
101 self.remove_configs()
102
103 @property
104 def return_code(self):
105 return self.process.returncode
106
107 def get_first_client_response(self):
108 signal.signal(signal.SIGALRM, self.interrupt)
109 signal.alarm(self.timeout)
110 first_response = self._read_first_client_response()
111 signal.alarm(0)
112 return (
113 self._parse_first_client_response(first_response)
114 if first_response else None)
115
116 def patch_first_client_response(self, response, **kwargs):
117 self.create_hooks_env()
118 data = response.copy()
119 data.update(kwargs)
120 data['url'] = self._svn_string(data['url'])
121 data['ra_client'] = self._svn_string(data['ra_client'])
122 data['client'] = data['client'] or ''
123 buffer_ = (
124 "( {version} ( {capabilities} ) {url}{ra_client}"
125 "( {client}) ) ".format(**data))
126 self.process.stdin.write(buffer_)
127
128 def fail(self, message):
129 print(
130 "( failure ( ( 210005 {message} 0: 0 ) ) )".format(
131 message=self._svn_string(message)))
132 self.remove_configs()
133 self.process.kill()
134
135 def interrupt(self, signum, frame):
136 self.fail("Exited by timeout")
137
138 def _svn_string(self, str_):
139 if not str_:
140 return ''
141 return '{length}:{string} '.format(length=len(str_), string=str_)
142
143 def _read_first_client_response(self):
144 buffer_ = ""
145 brackets_stack = []
146 while True:
147 next_byte = self.stdin.read(1)
148 buffer_ += next_byte
149 if next_byte == "(":
150 brackets_stack.append(next_byte)
151 elif next_byte == ")":
152 brackets_stack.pop()
153 elif next_byte == " " and not brackets_stack:
154 break
155 return buffer_
156
157 def _parse_first_client_response(self, buffer_):
158 """
159 According to the Subversion RA protocol, the first request
160 should look like:
161
162 ( version:number ( cap:word ... ) url:string ? ra-client:string
163 ( ? client:string ) )
164
165 Please check https://svn.apache.org/repos/asf/subversion/trunk/
166 subversion/libsvn_ra_svn/protocol
167 """
168 version_re = r'(?P<version>\d+)'
169 capabilities_re = r'\(\s(?P<capabilities>[\w\d\-\ ]+)\s\)'
170 url_re = r'\d+\:(?P<url>[\W\w]+)'
171 ra_client_re = r'(\d+\:(?P<ra_client>[\W\w]+)\s)'
172 client_re = r'(\d+\:(?P<client>[\W\w]+)\s)*'
173 regex = re.compile(
174 r'^\(\s{version}\s{capabilities}\s{url}\s{ra_client}'
175 r'\(\s{client}\)\s\)\s*$'.format(
176 version=version_re, capabilities=capabilities_re,
177 url=url_re, ra_client=ra_client_re, client=client_re))
178 matcher = regex.match(buffer_)
179 return matcher.groupdict() if matcher else None
180
181
182 class RhodeCodeApiClient(object):
183 def __init__(self, api_key, api_host):
184 self.api_key = api_key
185 self.api_host = api_host
186
187 if not api_host:
188 raise ValueError('api_key:{} not defined'.format(api_key))
189 if not api_host:
190 raise ValueError('api_host:{} not defined '.format(api_host))
191
192 def request(self, method, args):
193 id_ = random.randrange(1, 9999)
194 args = {
195 'id': id_,
196 'api_key': self.api_key,
197 'method': method,
198 'args': args
199 }
200 host = '{host}/_admin/api'.format(host=self.api_host)
201
202 log.debug('Doing API call to %s method:%s', host, method)
203 req = urllib2.Request(
204 host,
205 data=json.dumps(args),
206 headers={'content-type': 'text/plain'})
207 ret = urllib2.urlopen(req)
208 raw_json = ret.read()
209 json_data = json.loads(raw_json)
210 id_ret = json_data['id']
211
212 if id_ret != id_:
213 raise Exception('something went wrong. '
214 'ID mismatch got %s, expected %s | %s'
215 % (id_ret, id_, raw_json))
216
217 result = json_data['result']
218 error = json_data['error']
219 return result, error
220
221 def get_user_permissions(self, user, user_id):
222 result, error = self.request('get_user', {'userid': int(user_id)})
223 if result is None and error:
224 raise Exception(
225 'User "%s" not found or another error happened: %s!' % (
226 user, error))
227 log.debug(
228 'Given User: `%s` Fetched User: `%s`', user, result.get('username'))
229 return result.get('permissions').get('repositories')
230
231 def invalidate_cache(self, repo_name):
232 log.debug('Invalidate cache for repo:%s', repo_name)
233 return self.request('invalidate_cache', {'repoid': repo_name})
234
235 def get_repo_store(self):
236 result, error = self.request('get_repo_store', {})
237 return result
238
239
240 class VcsServer(object):
241
242 def __init__(self, user, user_permissions, config):
243 self.user = user
244 self.user_permissions = user_permissions
245 self.config = config
246 self.repo_name = None
247 self.repo_mode = None
248 self.store = {}
249 self.ini_path = ''
250
251 def run(self):
252 raise NotImplementedError()
253
254 def get_root_store(self):
255 root_store = self.store['path']
256 if not root_store.endswith('/'):
257 # always append trailing slash
258 root_store = root_store + '/'
259 return root_store
260
261
262 class MercurialServer(VcsServer):
263 read_only = False
264
265 def __init__(self, store, ini_path, repo_name,
266 user, user_permissions, config):
267 super(MercurialServer, self).__init__(user, user_permissions, config)
268 self.store = store
269 self.repo_name = repo_name
270 self.ini_path = ini_path
271 self.hg_path = config.get('app:main', 'ssh.executable.hg')
272
273 def run(self):
274 if not self._check_permissions():
275 return 2, False
276
277 tip_before = self.tip()
278 exit_code = os.system(self.command)
279 tip_after = self.tip()
280 return exit_code, tip_before != tip_after
281
282 def tip(self):
283 root = self.get_root_store()
284 command = (
285 'cd {root}; {hg_path} -R {root}{repo_name} tip --template "{{node}}\n"'
286 ''.format(
287 root=root, hg_path=self.hg_path, repo_name=self.repo_name))
288 try:
289 tip = check_output(command, shell=True).strip()
290 except CalledProcessError:
291 tip = None
292 return tip
293
294 @property
295 def command(self):
296 root = self.get_root_store()
297 arguments = (
298 '--config hooks.pretxnchangegroup=\"false\"'
299 if self.read_only else '')
300
301 command = (
302 "cd {root}; {hg_path} -R {root}{repo_name} serve --stdio"
303 " {arguments}".format(
304 root=root, hg_path=self.hg_path, repo_name=self.repo_name,
305 arguments=arguments))
306 log.debug("Final CMD: %s", command)
307 return command
308
309 def _check_permissions(self):
310 permission = self.user_permissions.get(self.repo_name)
311 if permission is None or permission == 'repository.none':
312 log.error('repo not found or no permissions')
313 return False
314
315 elif permission in ['repository.admin', 'repository.write']:
316 log.info(
317 'Write Permissions for User "%s" granted to repo "%s"!' % (
318 self.user, self.repo_name))
319 else:
320 self.read_only = True
321 log.info(
322 'Only Read Only access for User "%s" granted to repo "%s"!',
323 self.user, self.repo_name)
324 return True
325
326
327 class GitServer(VcsServer):
328 def __init__(self, store, ini_path, repo_name, repo_mode,
329 user, user_permissions, config):
330 super(GitServer, self).__init__(user, user_permissions, config)
331 self.store = store
332 self.ini_path = ini_path
333 self.repo_name = repo_name
334 self.repo_mode = repo_mode
335 self.git_path = config.get('app:main', 'ssh.executable.git')
336
337 def run(self):
338 exit_code = self._check_permissions()
339 if exit_code:
340 return exit_code, False
341
342 self._update_environment()
343 exit_code = os.system(self.command)
344 return exit_code, self.repo_mode == "receive-pack"
345
346 @property
347 def command(self):
348 root = self.get_root_store()
349 command = "cd {root}; {git_path}-{mode} '{root}{repo_name}'".format(
350 root=root, git_path=self.git_path, mode=self.repo_mode,
351 repo_name=self.repo_name)
352 log.debug("Final CMD: %s", command)
353 return command
354
355 def _update_environment(self):
356 action = "push" if self.repo_mode == "receive-pack" else "pull",
357 scm_data = {
358 "ip": os.environ["SSH_CLIENT"].split()[0],
359 "username": self.user,
360 "action": action,
361 "repository": self.repo_name,
362 "scm": "git",
363 "config": self.ini_path,
364 "make_lock": None,
365 "locked_by": [None, None]
366 }
367 os.putenv("RC_SCM_DATA", json.dumps(scm_data))
368
369 def _check_permissions(self):
370 permission = self.user_permissions.get(self.repo_name)
371 log.debug(
372 'permission for %s on %s are: %s',
373 self.user, self.repo_name, permission)
374
375 if permission is None or permission == 'repository.none':
376 log.error('repo not found or no permissions')
377 return 2
378 elif permission in ['repository.admin', 'repository.write']:
379 log.info(
380 'Write Permissions for User "%s" granted to repo "%s"!',
381 self.user, self.repo_name)
382 elif (permission == 'repository.read' and
383 self.repo_mode == 'upload-pack'):
384 log.info(
385 'Only Read Only access for User "%s" granted to repo "%s"!',
386 self.user, self.repo_name)
387 elif (permission == 'repository.read'
388 and self.repo_mode == 'receive-pack'):
389 log.error(
390 'Only Read Only access for User "%s" granted to repo "%s"!'
391 ' Failing!', self.user, self.repo_name)
392 return -3
393 else:
394 log.error('Cannot properly fetch user permission. '
395 'Return value is: %s', permission)
396 return -2
397
398
399 class SubversionServer(VcsServer):
400
401 def __init__(self, store, ini_path,
402 user, user_permissions, config):
403 super(SubversionServer, self).__init__(user, user_permissions, config)
404 self.store = store
405 self.ini_path = ini_path
406 # this is set in .run() from input stream
407 self.repo_name = None
408 self.svn_path = config.get('app:main', 'ssh.executable.svn')
409
410 def run(self):
411 root = self.get_root_store()
412 log.debug("Using subversion binaries from '%s'", self.svn_path)
413
414 self.tunnel = SubversionTunnelWrapper(
415 timeout=self.timeout, repositories_root=root, svn_path=self.svn_path)
416 self.tunnel.start()
417 first_response = self.tunnel.get_first_client_response()
418 if not first_response:
419 self.tunnel.fail("Repository name cannot be extracted")
420 return 1, False
421
422 url_parts = urlparse.urlparse(first_response['url'])
423 self.repo_name = url_parts.path.strip('/')
424 if not self._check_permissions():
425 self.tunnel.fail("Not enough permissions")
426 return 1, False
427
428 self.tunnel.patch_first_client_response(first_response)
429 self.tunnel.sync()
430 return self.tunnel.return_code, False
431
432 @property
433 def timeout(self):
434 timeout = 30
435 return timeout
436
437 def _check_permissions(self):
438 permission = self.user_permissions.get(self.repo_name)
439
440 if permission in ['repository.admin', 'repository.write']:
441 self.tunnel.read_only = False
442 return True
443
444 elif permission == 'repository.read':
445 self.tunnel.read_only = True
446 return True
447
448 else:
449 self.tunnel.fail("Not enough permissions for repository {}".format(
450 self.repo_name))
451 return False
452
453
454 class SshWrapper(object):
455
456 def __init__(self, command, mode, user, user_id, shell, ini_path):
457 self.command = command
458 self.mode = mode
459 self.user = user
460 self.user_id = user_id
461 self.shell = shell
462 self.ini_path = ini_path
463
464 self.config = self.parse_config(ini_path)
465 api_key = self.config.get('app:main', 'ssh.api_key')
466 api_host = self.config.get('app:main', 'ssh.api_host')
467 self.api = RhodeCodeApiClient(api_key, api_host)
468
469 def parse_config(self, config):
470 parser = ConfigParser.ConfigParser()
471 parser.read(config)
472 return parser
473
474 def get_repo_details(self, mode):
475 type_ = mode if mode in ['svn', 'hg', 'git'] else None
476 mode = mode
477 name = None
478
479 hg_pattern = r'^hg\s+\-R\s+(\S+)\s+serve\s+\-\-stdio$'
480 hg_match = re.match(hg_pattern, self.command)
481 if hg_match is not None:
482 type_ = 'hg'
483 name = hg_match.group(1).strip('/')
484 return type_, name, mode
485
486 git_pattern = (
487 r'^git-(receive-pack|upload-pack)\s\'[/]?(\S+?)(|\.git)\'$')
488 git_match = re.match(git_pattern, self.command)
489 if git_match is not None:
490 type_ = 'git'
491 name = git_match.group(2).strip('/')
492 mode = git_match.group(1)
493 return type_, name, mode
494
495 svn_pattern = r'^svnserve -t'
496 svn_match = re.match(svn_pattern, self.command)
497 if svn_match is not None:
498 type_ = 'svn'
499 # Repo name should be extracted from the input stream
500 return type_, name, mode
501
502 return type_, name, mode
503
504 def serve(self, vcs, repo, mode, user, permissions):
505 store = self.api.get_repo_store()
506
507 log.debug(
508 'VCS detected:`%s` mode: `%s` repo: %s', vcs, mode, repo)
509
510 if vcs == 'hg':
511 server = MercurialServer(
512 store=store, ini_path=self.ini_path,
513 repo_name=repo, user=user,
514 user_permissions=permissions, config=self.config)
515 return server.run()
516
517 elif vcs == 'git':
518 server = GitServer(
519 store=store, ini_path=self.ini_path,
520 repo_name=repo, repo_mode=mode, user=user,
521 user_permissions=permissions, config=self.config)
522 return server.run()
523
524 elif vcs == 'svn':
525 server = SubversionServer(
526 store=store, ini_path=self.ini_path,
527 user=user,
528 user_permissions=permissions, config=self.config)
529 return server.run()
530
531 else:
532 raise Exception('Unrecognised VCS: {}'.format(vcs))
533
534 def wrap(self):
535 mode = self.mode
536 user = self.user
537 user_id = self.user_id
538 shell = self.shell
539
540 scm_detected, scm_repo, scm_mode = self.get_repo_details(mode)
541 log.debug(
542 'Mode: `%s` User: `%s:%s` Shell: `%s` SSH Command: `\"%s\"` '
543 'SCM_DETECTED: `%s` SCM Mode: `%s` SCM Repo: `%s`',
544 mode, user, user_id, shell, self.command,
545 scm_detected, scm_mode, scm_repo)
546
547 try:
548 permissions = self.api.get_user_permissions(user, user_id)
549 except Exception as e:
550 log.exception('Failed to fetch user permissions')
551 return 1
552
553 if shell and self.command is None:
554 log.info(
555 'Dropping to shell, no command given and shell is allowed')
556 os.execl('/bin/bash', '-l')
557 exit_code = 1
558
559 elif scm_detected:
560 try:
561 exit_code, is_updated = self.serve(
562 scm_detected, scm_repo, scm_mode, user, permissions)
563 if exit_code == 0 and is_updated:
564 self.api.invalidate_cache(scm_repo)
565 except Exception:
566 log.exception('Error occurred during execution of SshWrapper')
567 exit_code = -1
568
569 elif self.command is None and shell is False:
570 log.error('No Command given.')
571 exit_code = -1
572
573 else:
574 log.error(
575 'Unhandled Command: "%s" Aborting.', self.command)
576 exit_code = -1
577
578 return exit_code
579
580
581 @click.command()
582 @click.argument('ini_path', type=click.Path(exists=True))
583 @click.option(
584 '--mode', '-m', required=False, default='auto',
585 type=click.Choice(['auto', 'vcs', 'git', 'hg', 'svn', 'test']),
586 help='mode of operation')
587 @click.option('--user', help='Username for which the command will be executed')
588 @click.option('--user-id', help='User ID for which the command will be executed')
589 @click.option('--shell', '-s', is_flag=True, help='Allow Shell')
590 @click.option('--debug', is_flag=True, help='Enabled detailed output logging')
591 def main(ini_path, mode, user, user_id, shell, debug):
592 setup_logging(ini_path, debug)
593
594 command = os.environ.get('SSH_ORIGINAL_COMMAND', '')
595 if not command and mode not in ['test']:
596 raise ValueError(
597 'Unable to fetch SSH_ORIGINAL_COMMAND from environment.'
598 'Please make sure this is set and available during execution '
599 'of this script.')
600
601 try:
602 ssh_wrapper = SshWrapper(command, mode, user, user_id, shell, ini_path)
603 except Exception:
604 log.exception('Failed to execute SshWrapper')
605 sys.exit(-5)
606
607 sys.exit(ssh_wrapper.wrap()) No newline at end of file
@@ -0,0 +1,195 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import json
22
23 import pytest
24 from mock import Mock, patch, call
25
26 from rhodecode.apps.ssh_support.lib.ssh_wrapper import GitServer
27
28
29 @pytest.fixture
30 def git_server():
31 return GitServerCreator()
32
33
34 class GitServerCreator(object):
35 root = '/tmp/repo/path/'
36 git_path = '/usr/local/bin/'
37 config_data = {
38 'app:main': {
39 'ssh.executable.git': git_path
40 }
41 }
42 repo_name = 'test_git'
43 repo_mode = 'receive-pack'
44 user = 'vcs'
45
46 def __init__(self):
47 def config_get(part, key):
48 return self.config_data.get(part, {}).get(key)
49 self.config_mock = Mock()
50 self.config_mock.get = Mock(side_effect=config_get)
51
52 def create(self, **kwargs):
53 parameters = {
54 'store': {'path': self.root},
55 'ini_path': '',
56 'user': self.user,
57 'repo_name': self.repo_name,
58 'repo_mode': self.repo_mode,
59 'user_permissions': {
60 self.repo_name: 'repo_admin'
61 },
62 'config': self.config_mock,
63 }
64 parameters.update(kwargs)
65 server = GitServer(**parameters)
66 return server
67
68
69 class TestGitServer(object):
70 def test_command(self, git_server):
71 server = git_server.create()
72 server.read_only = False
73 expected_command = (
74 'cd {root}; {git_path}-{repo_mode}'
75 ' \'{root}{repo_name}\''.format(
76 root=git_server.root, git_path=git_server.git_path,
77 repo_mode=git_server.repo_mode, repo_name=git_server.repo_name)
78 )
79 assert expected_command == server.command
80
81 def test_run_returns_exit_code_2_when_no_permissions(self, git_server, caplog):
82 server = git_server.create()
83 with patch.object(server, '_check_permissions') as permissions_mock:
84 with patch.object(server, '_update_environment'):
85 permissions_mock.return_value = 2
86 exit_code = server.run()
87
88 assert exit_code == (2, False)
89
90 def test_run_returns_executes_command(self, git_server, caplog):
91 server = git_server.create()
92 with patch.object(server, '_check_permissions') as permissions_mock:
93 with patch('os.system') as system_mock:
94 with patch.object(server, '_update_environment') as (
95 update_mock):
96 permissions_mock.return_value = 0
97 system_mock.return_value = 0
98 exit_code = server.run()
99
100 system_mock.assert_called_once_with(server.command)
101 update_mock.assert_called_once_with()
102
103 assert exit_code == (0, True)
104
105 @pytest.mark.parametrize(
106 'repo_mode, action', [
107 ['receive-pack', 'push'],
108 ['upload-pack', 'pull']
109 ])
110 def test_update_environment(self, git_server, repo_mode, action):
111 server = git_server.create(repo_mode=repo_mode)
112 with patch('os.environ', {'SSH_CLIENT': '10.10.10.10 b'}):
113 with patch('os.putenv') as putenv_mock:
114 server._update_environment()
115 expected_data = {
116 "username": git_server.user,
117 "scm": "git",
118 "repository": git_server.repo_name,
119 "make_lock": None,
120 "action": [action],
121 "ip": "10.10.10.10",
122 "locked_by": [None, None],
123 "config": ""
124 }
125 putenv_mock.assert_called_once_with(
126 'RC_SCM_DATA', json.dumps(expected_data))
127
128
129 class TestGitServerCheckPermissions(object):
130 def test_returns_2_when_no_permissions_found(self, git_server, caplog):
131 user_permissions = {}
132 server = git_server.create(user_permissions=user_permissions)
133 result = server._check_permissions()
134 assert result == 2
135
136 log_msg = 'permission for vcs on test_git are: None'
137 assert log_msg in [t[2] for t in caplog.record_tuples]
138
139 def test_returns_2_when_no_permissions(self, git_server, caplog):
140 user_permissions = {git_server.repo_name: 'repository.none'}
141 server = git_server.create(user_permissions=user_permissions)
142 result = server._check_permissions()
143 assert result == 2
144
145 log_msg = 'repo not found or no permissions'
146 assert log_msg in [t[2] for t in caplog.record_tuples]
147
148 @pytest.mark.parametrize(
149 'permission', ['repository.admin', 'repository.write'])
150 def test_access_allowed_when_user_has_write_permissions(
151 self, git_server, permission, caplog):
152 user_permissions = {git_server.repo_name: permission}
153 server = git_server.create(user_permissions=user_permissions)
154 result = server._check_permissions()
155 assert result is None
156
157 log_msg = 'Write Permissions for User "%s" granted to repo "%s"!' % (
158 git_server.user, git_server.repo_name)
159 assert log_msg in [t[2] for t in caplog.record_tuples]
160
161 def test_write_access_is_not_allowed_when_user_has_read_permission(
162 self, git_server, caplog):
163 user_permissions = {git_server.repo_name: 'repository.read'}
164 server = git_server.create(
165 user_permissions=user_permissions, repo_mode='receive-pack')
166 result = server._check_permissions()
167 assert result == -3
168
169 log_msg = 'Only Read Only access for User "%s" granted to repo "%s"! Failing!' % (
170 git_server.user, git_server.repo_name)
171 assert log_msg in [t[2] for t in caplog.record_tuples]
172
173 def test_read_access_allowed_when_user_has_read_permission(
174 self, git_server, caplog):
175 user_permissions = {git_server.repo_name: 'repository.read'}
176 server = git_server.create(
177 user_permissions=user_permissions, repo_mode='upload-pack')
178 result = server._check_permissions()
179 assert result is None
180
181 log_msg = 'Only Read Only access for User "%s" granted to repo "%s"!' % (
182 git_server.user, git_server.repo_name)
183 assert log_msg in [t[2] for t in caplog.record_tuples]
184
185 def test_returns_error_when_permission_not_recognised(
186 self, git_server, caplog):
187 user_permissions = {git_server.repo_name: 'repository.whatever'}
188 server = git_server.create(
189 user_permissions=user_permissions, repo_mode='upload-pack')
190 result = server._check_permissions()
191 assert result == -2
192
193 log_msg = 'Cannot properly fetch user permission. ' \
194 'Return value is: repository.whatever'
195 assert log_msg in [t[2] for t in caplog.record_tuples] No newline at end of file
@@ -0,0 +1,146 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import pytest
22 from mock import Mock, patch, call
23
24 from rhodecode.apps.ssh_support.lib.ssh_wrapper import MercurialServer
25
26
27 @pytest.fixture
28 def hg_server():
29 return MercurialServerCreator()
30
31
32 class MercurialServerCreator(object):
33 root = '/tmp/repo/path/'
34 hg_path = '/usr/local/bin/hg'
35
36 config_data = {
37 'app:main': {
38 'ssh.executable.hg': hg_path
39 }
40 }
41 repo_name = 'test_hg'
42 user = 'vcs'
43
44 def __init__(self):
45 def config_get(part, key):
46 return self.config_data.get(part, {}).get(key)
47 self.config_mock = Mock()
48 self.config_mock.get = Mock(side_effect=config_get)
49
50 def create(self, **kwargs):
51 parameters = {
52 'store': {'path': self.root},
53 'ini_path': '',
54 'user': self.user,
55 'repo_name': self.repo_name,
56 'user_permissions': {
57 'test_hg': 'repo_admin'
58 },
59 'config': self.config_mock,
60 }
61 parameters.update(kwargs)
62 server = MercurialServer(**parameters)
63 return server
64
65
66 class TestMercurialServer(object):
67 def test_read_only_command(self, hg_server):
68 server = hg_server.create()
69 server.read_only = True
70 expected_command = (
71 'cd {root}; {hg_path} -R {root}{repo_name} serve --stdio'
72 ' --config hooks.pretxnchangegroup="false"'.format(
73 root=hg_server.root, hg_path=hg_server.hg_path,
74 repo_name=hg_server.repo_name)
75 )
76 assert expected_command == server.command
77
78 def test_normal_command(self, hg_server):
79 server = hg_server.create()
80 server.read_only = False
81 expected_command = (
82 'cd {root}; {hg_path} -R {root}{repo_name} serve --stdio '.format(
83 root=hg_server.root, hg_path=hg_server.hg_path,
84 repo_name=hg_server.repo_name)
85 )
86 assert expected_command == server.command
87
88 def test_access_rejected_when_permissions_are_not_found(self, hg_server, caplog):
89 user_permissions = {}
90 server = hg_server.create(user_permissions=user_permissions)
91 result = server._check_permissions()
92 assert result is False
93
94 log_msg = 'repo not found or no permissions'
95 assert log_msg in [t[2] for t in caplog.record_tuples]
96
97 def test_access_rejected_when_no_permissions(self, hg_server, caplog):
98 user_permissions = {hg_server.repo_name: 'repository.none'}
99 server = hg_server.create(user_permissions=user_permissions)
100 result = server._check_permissions()
101 assert result is False
102
103 log_msg = 'repo not found or no permissions'
104 assert log_msg in [t[2] for t in caplog.record_tuples]
105
106 @pytest.mark.parametrize(
107 'permission', ['repository.admin', 'repository.write'])
108 def test_access_allowed_when_user_has_write_permissions(
109 self, hg_server, permission, caplog):
110 user_permissions = {hg_server.repo_name: permission}
111 server = hg_server.create(user_permissions=user_permissions)
112 result = server._check_permissions()
113 assert result is True
114
115 assert server.read_only is False
116 log_msg = 'Write Permissions for User "vcs" granted to repo "test_hg"!'
117 assert log_msg in [t[2] for t in caplog.record_tuples]
118
119 def test_access_allowed_when_user_has_read_permissions(self, hg_server, caplog):
120 user_permissions = {hg_server.repo_name: 'repository.read'}
121 server = hg_server.create(user_permissions=user_permissions)
122 result = server._check_permissions()
123 assert result is True
124
125 assert server.read_only is True
126 log_msg = 'Only Read Only access for User "%s" granted to repo "%s"!' % (
127 hg_server.user, hg_server.repo_name)
128 assert log_msg in [t[2] for t in caplog.record_tuples]
129
130 def test_run_returns_exit_code_2_when_no_permissions(self, hg_server, caplog):
131 server = hg_server.create()
132 with patch.object(server, '_check_permissions') as permissions_mock:
133 permissions_mock.return_value = False
134 exit_code = server.run()
135 assert exit_code == (2, False)
136
137 def test_run_returns_executes_command(self, hg_server, caplog):
138 server = hg_server.create()
139 with patch.object(server, '_check_permissions') as permissions_mock:
140 with patch('os.system') as system_mock:
141 permissions_mock.return_value = True
142 system_mock.return_value = 0
143 exit_code = server.run()
144
145 system_mock.assert_called_once_with(server.command)
146 assert exit_code == (0, False)
@@ -0,0 +1,136 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import pytest
22 from mock import Mock, patch, call
23
24 from rhodecode.apps.ssh_support.lib.ssh_wrapper import SubversionServer
25
26
27 @pytest.fixture
28 def svn_server():
29 return SubversionServerCreator()
30
31
32 class SubversionServerCreator(object):
33 root = '/tmp/repo/path/'
34 svn_path = '/usr/local/bin/svnserve'
35 config_data = {
36 'app:main': {
37 'ssh.executable.svn': svn_path
38 }
39 }
40 repo_name = 'test-svn'
41 user = 'vcs'
42
43 def __init__(self):
44 def config_get(part, key):
45 return self.config_data.get(part, {}).get(key)
46 self.config_mock = Mock()
47 self.config_mock.get = Mock(side_effect=config_get)
48
49 def create(self, **kwargs):
50 parameters = {
51 'store': {'path': self.root},
52 'ini_path': '',
53 'user': self.user,
54 'user_permissions': {
55 self.repo_name: 'repo_admin'
56 },
57 'config': self.config_mock,
58 }
59 parameters.update(kwargs)
60 server = SubversionServer(**parameters)
61 return server
62
63
64 class TestSubversionServer(object):
65 def test_timeout_returns_value_from_config(self, svn_server):
66 server = svn_server.create()
67 assert server.timeout == 30
68
69 @pytest.mark.parametrize(
70 'permission', ['repository.admin', 'repository.write'])
71 def test_check_permissions_with_write_permissions(
72 self, svn_server, permission):
73 user_permissions = {svn_server.repo_name: permission}
74 server = svn_server.create(user_permissions=user_permissions)
75 server.tunnel = Mock()
76 server.repo_name = svn_server.repo_name
77 result = server._check_permissions()
78 assert result is True
79 assert server.tunnel.read_only is False
80
81 def test_check_permissions_with_read_permissions(self, svn_server):
82 user_permissions = {svn_server.repo_name: 'repository.read'}
83 server = svn_server.create(user_permissions=user_permissions)
84 server.tunnel = Mock()
85 server.repo_name = svn_server.repo_name
86 result = server._check_permissions()
87 assert result is True
88 assert server.tunnel.read_only is True
89
90 def test_check_permissions_with_no_permissions(self, svn_server, caplog):
91 tunnel_mock = Mock()
92 user_permissions = {}
93 server = svn_server.create(user_permissions=user_permissions)
94 server.tunnel = tunnel_mock
95 server.repo_name = svn_server.repo_name
96 result = server._check_permissions()
97 assert result is False
98 tunnel_mock.fail.assert_called_once_with(
99 "Not enough permissions for repository {}".format(
100 svn_server.repo_name))
101
102 def test_run_returns_1_when_repository_name_cannot_be_extracted(
103 self, svn_server):
104 server = svn_server.create()
105 with patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.SubversionTunnelWrapper') as tunnel_mock:
106 tunnel_mock().get_first_client_response.return_value = None
107 exit_code = server.run()
108 assert exit_code == (1, False)
109 tunnel_mock().fail.assert_called_once_with(
110 'Repository name cannot be extracted')
111
112 def test_run_returns_tunnel_return_code(self, svn_server, caplog):
113 server = svn_server.create()
114 fake_response = {
115 'url': 'ssh+svn://test@example.com/test-svn/'
116 }
117 with patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.SubversionTunnelWrapper') as tunnel_mock:
118 with patch.object(server, '_check_permissions') as (
119 permissions_mock):
120 permissions_mock.return_value = True
121 tunnel = tunnel_mock()
122 tunnel.get_first_client_response.return_value = fake_response
123 tunnel.return_code = 0
124 exit_code = server.run()
125 permissions_mock.assert_called_once_with()
126
127 expected_log_calls = sorted([
128 "Using subversion binaries from '%s'" % svn_server.svn_path
129 ])
130
131 assert expected_log_calls == [t[2] for t in caplog.record_tuples]
132
133 assert exit_code == (0, False)
134 tunnel.patch_first_client_response.assert_called_once_with(
135 fake_response)
136 tunnel.sync.assert_called_once_with()
@@ -0,0 +1,204 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import os
21 import mock
22 import pytest
23 import ConfigParser
24
25 from rhodecode.apps.ssh_support.lib.ssh_wrapper import SshWrapper
26
27
28 @pytest.fixture
29 def dummy_conf(tmpdir):
30 conf = ConfigParser.ConfigParser()
31 conf.add_section('app:main')
32 conf.set('app:main', 'ssh.executable.hg', '/usr/bin/hg')
33 conf.set('app:main', 'ssh.executable.git', '/usr/bin/git')
34 conf.set('app:main', 'ssh.executable.svn', '/usr/bin/svnserve')
35
36 conf.set('app:main', 'ssh.api_key', 'xxx')
37 conf.set('app:main', 'ssh.api_host', 'http://localhost')
38
39 f_path = os.path.join(str(tmpdir), 'ssh_wrapper_test.ini')
40 with open(f_path, 'wb') as f:
41 conf.write(f)
42
43 return os.path.join(f_path)
44
45
46 class TestGetRepoDetails(object):
47 @pytest.mark.parametrize(
48 'command', [
49 'hg -R test-repo serve --stdio',
50 'hg -R test-repo serve --stdio'
51 ])
52 def test_hg_command_matched(self, command, dummy_conf):
53 wrapper = SshWrapper(command, 'auto', 'admin', '3', 'False', dummy_conf)
54 type_, name, mode = wrapper.get_repo_details('auto')
55 assert type_ == 'hg'
56 assert name == 'test-repo'
57 assert mode is 'auto'
58
59 @pytest.mark.parametrize(
60 'command', [
61 'hg test-repo serve --stdio',
62 'hg -R test-repo serve',
63 'hg serve --stdio',
64 'hg serve -R test-repo'
65 ])
66 def test_hg_command_not_matched(self, command, dummy_conf):
67 wrapper = SshWrapper(command, 'auto', 'admin', '3', 'False', dummy_conf)
68 type_, name, mode = wrapper.get_repo_details('auto')
69 assert type_ is None
70 assert name is None
71 assert mode is 'auto'
72
73
74 class TestServe(object):
75 def test_serve_raises_an_exception_when_vcs_is_not_recognized(self, dummy_conf):
76 with mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_repo_store'):
77 wrapper = SshWrapper('random command', 'auto', 'admin', '3', 'False', dummy_conf)
78
79 with pytest.raises(Exception) as exc_info:
80 wrapper.serve(
81 vcs='microsoft-tfs', repo='test-repo', mode=None, user='test',
82 permissions={})
83 assert exc_info.value.message == 'Unrecognised VCS: microsoft-tfs'
84
85
86 class TestServeHg(object):
87
88 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.invalidate_cache')
89 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_user_permissions')
90 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_repo_store')
91 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.MercurialServer.run')
92 def test_serve_creates_hg_instance(
93 self, mercurial_run_mock, get_repo_store_mock, get_user_mock,
94 invalidate_cache_mock, dummy_conf):
95
96 repo_name = None
97 mercurial_run_mock.return_value = 0, True
98 get_user_mock.return_value = {repo_name: 'repository.admin'}
99 get_repo_store_mock.return_value = {'path': '/tmp'}
100
101 wrapper = SshWrapper('date', 'hg', 'admin', '3', 'False',
102 dummy_conf)
103 exit_code = wrapper.wrap()
104 assert exit_code == 0
105 assert mercurial_run_mock.called
106
107 assert get_repo_store_mock.called
108 assert get_user_mock.called
109 invalidate_cache_mock.assert_called_once_with(repo_name)
110
111 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.invalidate_cache')
112 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_user_permissions')
113 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_repo_store')
114 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.MercurialServer.run')
115 def test_serve_hg_invalidates_cache(
116 self, mercurial_run_mock, get_repo_store_mock, get_user_mock,
117 invalidate_cache_mock, dummy_conf):
118
119 repo_name = None
120 mercurial_run_mock.return_value = 0, True
121 get_user_mock.return_value = {repo_name: 'repository.admin'}
122 get_repo_store_mock.return_value = {'path': '/tmp'}
123
124 wrapper = SshWrapper('date', 'hg', 'admin', '3', 'False',
125 dummy_conf)
126 exit_code = wrapper.wrap()
127 assert exit_code == 0
128 assert mercurial_run_mock.called
129
130 assert get_repo_store_mock.called
131 assert get_user_mock.called
132 invalidate_cache_mock.assert_called_once_with(repo_name)
133
134
135 class TestServeGit(object):
136
137 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.invalidate_cache')
138 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_user_permissions')
139 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_repo_store')
140 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.GitServer.run')
141 def test_serve_creates_git_instance(self, git_run_mock, get_repo_store_mock, get_user_mock,
142 invalidate_cache_mock, dummy_conf):
143 repo_name = None
144 git_run_mock.return_value = 0, True
145 get_user_mock.return_value = {repo_name: 'repository.admin'}
146 get_repo_store_mock.return_value = {'path': '/tmp'}
147
148 wrapper = SshWrapper('date', 'git', 'admin', '3', 'False',
149 dummy_conf)
150
151 exit_code = wrapper.wrap()
152 assert exit_code == 0
153 assert git_run_mock.called
154 assert get_repo_store_mock.called
155 assert get_user_mock.called
156 invalidate_cache_mock.assert_called_once_with(repo_name)
157
158 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.invalidate_cache')
159 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_user_permissions')
160 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_repo_store')
161 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.GitServer.run')
162 def test_serve_git_invalidates_cache(
163 self, git_run_mock, get_repo_store_mock, get_user_mock,
164 invalidate_cache_mock, dummy_conf):
165 repo_name = None
166 git_run_mock.return_value = 0, True
167 get_user_mock.return_value = {repo_name: 'repository.admin'}
168 get_repo_store_mock.return_value = {'path': '/tmp'}
169
170 wrapper = SshWrapper('date', 'git', 'admin', '3', 'False', dummy_conf)
171
172 exit_code = wrapper.wrap()
173 assert exit_code == 0
174 assert git_run_mock.called
175
176 assert get_repo_store_mock.called
177 assert get_user_mock.called
178 invalidate_cache_mock.assert_called_once_with(repo_name)
179
180
181 class TestServeSvn(object):
182
183 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.invalidate_cache')
184 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_user_permissions')
185 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.RhodeCodeApiClient.get_repo_store')
186 @mock.patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.SubversionServer.run')
187 def test_serve_creates_svn_instance(
188 self, svn_run_mock, get_repo_store_mock, get_user_mock,
189 invalidate_cache_mock, dummy_conf):
190
191 repo_name = None
192 svn_run_mock.return_value = 0, True
193 get_user_mock.return_value = {repo_name: 'repository.admin'}
194 get_repo_store_mock.return_value = {'path': '/tmp'}
195
196 wrapper = SshWrapper('date', 'svn', 'admin', '3', 'False', dummy_conf)
197
198 exit_code = wrapper.wrap()
199 assert exit_code == 0
200 assert svn_run_mock.called
201
202 assert get_repo_store_mock.called
203 assert get_user_mock.called
204 invalidate_cache_mock.assert_called_once_with(repo_name)
@@ -0,0 +1,285 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import subprocess
23 from io import BytesIO
24 from time import sleep
25
26 import pytest
27 from mock import patch, Mock, MagicMock, call
28
29 from rhodecode.apps.ssh_support.lib.ssh_wrapper import SubversionTunnelWrapper
30 from rhodecode.tests import no_newline_id_generator
31
32
33 class TestSubversionTunnelWrapper(object):
34 @pytest.mark.parametrize(
35 'input_string, output_string', [
36 [None, ''],
37 ['abcde', '5:abcde '],
38 ['abcdefghijk', '11:abcdefghijk ']
39 ])
40 def test_svn_string(self, input_string, output_string):
41 wrapper = SubversionTunnelWrapper(timeout=5)
42 assert wrapper._svn_string(input_string) == output_string
43
44 def test_read_first_client_response(self):
45 wrapper = SubversionTunnelWrapper(timeout=5)
46 buffer_ = '( abcd ( efg hij ) ) '
47 wrapper.stdin = BytesIO(buffer_)
48 result = wrapper._read_first_client_response()
49 assert result == buffer_
50
51 def test_parse_first_client_response_returns_dict(self):
52 response = (
53 '( 2 ( edit-pipeline svndiff1 absent-entries depth mergeinfo'
54 ' log-revprops ) 26:svn+ssh://vcs@vm/hello-svn 38:SVN/1.8.11'
55 ' (x86_64-apple-darwin14.1.0) ( ) ) ')
56 wrapper = SubversionTunnelWrapper(timeout=5)
57 result = wrapper._parse_first_client_response(response)
58 assert result['version'] == '2'
59 assert (
60 result['capabilities'] ==
61 'edit-pipeline svndiff1 absent-entries depth mergeinfo'
62 ' log-revprops')
63 assert result['url'] == 'svn+ssh://vcs@vm/hello-svn'
64 assert result['ra_client'] == 'SVN/1.8.11 (x86_64-apple-darwin14.1.0)'
65 assert result['client'] is None
66
67 def test_parse_first_client_response_returns_none_when_not_matched(self):
68 response = (
69 '( 2 ( edit-pipeline svndiff1 absent-entries depth mergeinfo'
70 ' log-revprops ) ) ')
71 wrapper = SubversionTunnelWrapper(timeout=5)
72 result = wrapper._parse_first_client_response(response)
73 assert result is None
74
75 def test_interrupt(self):
76 wrapper = SubversionTunnelWrapper(timeout=5)
77 with patch.object(wrapper, 'fail') as fail_mock:
78 wrapper.interrupt(1, 'frame')
79 fail_mock.assert_called_once_with("Exited by timeout")
80
81 def test_fail(self):
82 process_mock = Mock()
83 wrapper = SubversionTunnelWrapper(timeout=5)
84 with patch.object(wrapper, 'remove_configs') as remove_configs_mock:
85 with patch('sys.stdout', new_callable=BytesIO) as stdout_mock:
86 with patch.object(wrapper, 'process') as process_mock:
87 wrapper.fail('test message')
88 assert (
89 stdout_mock.getvalue() ==
90 '( failure ( ( 210005 12:test message 0: 0 ) ) )\n')
91 process_mock.kill.assert_called_once_with()
92 remove_configs_mock.assert_called_once_with()
93
94 @pytest.mark.parametrize(
95 'client, expected_client', [
96 ['test ', 'test '],
97 ['', ''],
98 [None, '']
99 ])
100 def test_client_in_patch_first_client_response(
101 self, client, expected_client):
102 response = {
103 'version': 2,
104 'capabilities': 'edit-pipeline svndiff1 absent-entries depth',
105 'url': 'svn+ssh://example.com/svn',
106 'ra_client': 'SVN/1.8.11 (x86_64-apple-darwin14.1.0)',
107 'client': client
108 }
109 wrapper = SubversionTunnelWrapper(timeout=5)
110 stdin = BytesIO()
111 with patch.object(wrapper, 'process') as process_mock:
112 process_mock.stdin = stdin
113 wrapper.patch_first_client_response(response)
114 assert (
115 stdin.getvalue() ==
116 '( 2 ( edit-pipeline svndiff1 absent-entries depth )'
117 ' 25:svn+ssh://example.com/svn 38:SVN/1.8.11'
118 ' (x86_64-apple-darwin14.1.0) ( {expected_client}) ) '.format(
119 expected_client=expected_client))
120
121 def test_kwargs_override_data_in_patch_first_client_response(self):
122 response = {
123 'version': 2,
124 'capabilities': 'edit-pipeline svndiff1 absent-entries depth',
125 'url': 'svn+ssh://example.com/svn',
126 'ra_client': 'SVN/1.8.11 (x86_64-apple-darwin14.1.0)',
127 'client': 'test'
128 }
129 wrapper = SubversionTunnelWrapper(timeout=5)
130 stdin = BytesIO()
131 with patch.object(wrapper, 'process') as process_mock:
132 process_mock.stdin = stdin
133 wrapper.patch_first_client_response(
134 response, version=3, client='abcde ',
135 capabilities='absent-entries depth',
136 url='svn+ssh://example.org/test',
137 ra_client='SVN/1.8.12 (ubuntu 14.04)')
138 assert (
139 stdin.getvalue() ==
140 '( 3 ( absent-entries depth ) 26:svn+ssh://example.org/test'
141 ' 25:SVN/1.8.12 (ubuntu 14.04) ( abcde ) ) ')
142
143 def test_patch_first_client_response_sets_environment(self):
144 response = {
145 'version': 2,
146 'capabilities': 'edit-pipeline svndiff1 absent-entries depth',
147 'url': 'svn+ssh://example.com/svn',
148 'ra_client': 'SVN/1.8.11 (x86_64-apple-darwin14.1.0)',
149 'client': 'test'
150 }
151 wrapper = SubversionTunnelWrapper(timeout=5)
152 stdin = BytesIO()
153 with patch.object(wrapper, 'create_hooks_env') as create_hooks_mock:
154 with patch.object(wrapper, 'process') as process_mock:
155 process_mock.stdin = stdin
156 wrapper.patch_first_client_response(response)
157 create_hooks_mock.assert_called_once_with()
158
159 def test_get_first_client_response_exits_by_signal(self):
160 wrapper = SubversionTunnelWrapper(timeout=1)
161 read_patch = patch.object(wrapper, '_read_first_client_response')
162 parse_patch = patch.object(wrapper, '_parse_first_client_response')
163 interrupt_patch = patch.object(wrapper, 'interrupt')
164
165 with read_patch as read_mock, parse_patch as parse_mock, \
166 interrupt_patch as interrupt_mock:
167 read_mock.side_effect = lambda: sleep(3)
168 wrapper.get_first_client_response()
169
170 assert parse_mock.call_count == 0
171 assert interrupt_mock.call_count == 1
172
173 def test_get_first_client_response_parses_data(self):
174 wrapper = SubversionTunnelWrapper(timeout=5)
175 response = (
176 '( 2 ( edit-pipeline svndiff1 absent-entries depth mergeinfo'
177 ' log-revprops ) 26:svn+ssh://vcs@vm/hello-svn 38:SVN/1.8.11'
178 ' (x86_64-apple-darwin14.1.0) ( ) ) ')
179 read_patch = patch.object(wrapper, '_read_first_client_response')
180 parse_patch = patch.object(wrapper, '_parse_first_client_response')
181
182 with read_patch as read_mock, parse_patch as parse_mock:
183 read_mock.return_value = response
184 wrapper.get_first_client_response()
185
186 parse_mock.assert_called_once_with(response)
187
188 def test_return_code(self):
189 wrapper = SubversionTunnelWrapper(timeout=5)
190 with patch.object(wrapper, 'process') as process_mock:
191 process_mock.returncode = 1
192 assert wrapper.return_code == 1
193
194 def test_sync_loop_breaks_when_process_cannot_be_polled(self):
195 self.counter = 0
196 buffer_ = 'abcdefghij'
197
198 wrapper = SubversionTunnelWrapper(timeout=5)
199 wrapper.stdin = BytesIO(buffer_)
200 with patch.object(wrapper, 'remove_configs') as remove_configs_mock:
201 with patch.object(wrapper, 'process') as process_mock:
202 process_mock.poll.side_effect = self._poll
203 process_mock.stdin = BytesIO()
204 wrapper.sync()
205 assert process_mock.stdin.getvalue() == 'abcde'
206 remove_configs_mock.assert_called_once_with()
207
208 def test_sync_loop_breaks_when_nothing_to_read(self):
209 self.counter = 0
210 buffer_ = 'abcdefghij'
211
212 wrapper = SubversionTunnelWrapper(timeout=5)
213 wrapper.stdin = BytesIO(buffer_)
214 with patch.object(wrapper, 'remove_configs') as remove_configs_mock:
215 with patch.object(wrapper, 'process') as process_mock:
216 process_mock.poll.return_value = None
217 process_mock.stdin = BytesIO()
218 wrapper.sync()
219 assert process_mock.stdin.getvalue() == buffer_
220 remove_configs_mock.assert_called_once_with()
221
222 def test_start_without_repositories_root(self):
223 svn_path = '/usr/local/bin/svnserve'
224 wrapper = SubversionTunnelWrapper(timeout=5, svn_path=svn_path)
225 with patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.Popen') as popen_mock:
226 wrapper.start()
227 expected_command = [
228 svn_path, '-t', '--config-file', wrapper.svn_conf_path]
229 popen_mock.assert_called_once_with(
230 expected_command, stdin=subprocess.PIPE)
231 assert wrapper.process == popen_mock()
232
233 def test_start_with_repositories_root(self):
234 svn_path = '/usr/local/bin/svnserve'
235 repositories_root = '/home/repos'
236 wrapper = SubversionTunnelWrapper(
237 timeout=5, svn_path=svn_path, repositories_root=repositories_root)
238 with patch('rhodecode.apps.ssh_support.lib.ssh_wrapper.Popen') as popen_mock:
239 wrapper.start()
240 expected_command = [
241 svn_path, '-t', '--config-file', wrapper.svn_conf_path,
242 '-r', repositories_root]
243 popen_mock.assert_called_once_with(
244 expected_command, stdin=subprocess.PIPE)
245 assert wrapper.process == popen_mock()
246
247 def test_create_svn_config(self):
248 wrapper = SubversionTunnelWrapper(timeout=5)
249 file_mock = MagicMock(spec=file)
250 with patch('os.fdopen', create=True) as open_mock:
251 open_mock.return_value = file_mock
252 wrapper.create_svn_config()
253 open_mock.assert_called_once_with(wrapper.svn_conf_fd, 'w')
254 expected_content = '[general]\nhooks-env = {}\n'.format(
255 wrapper.hooks_env_path)
256 file_handle = file_mock.__enter__.return_value
257 file_handle.write.assert_called_once_with(expected_content)
258
259 @pytest.mark.parametrize(
260 'read_only, expected_content', [
261 [True, '[default]\nLANG = en_US.UTF-8\nSSH_READ_ONLY = 1\n'],
262 [False, '[default]\nLANG = en_US.UTF-8\n']
263 ], ids=no_newline_id_generator)
264 def test_create_hooks_env(self, read_only, expected_content):
265 wrapper = SubversionTunnelWrapper(timeout=5)
266 wrapper.read_only = read_only
267 file_mock = MagicMock(spec=file)
268 with patch('os.fdopen', create=True) as open_mock:
269 open_mock.return_value = file_mock
270 wrapper.create_hooks_env()
271 open_mock.assert_called_once_with(wrapper.hooks_env_fd, 'w')
272 file_handle = file_mock.__enter__.return_value
273 file_handle.write.assert_called_once_with(expected_content)
274
275 def test_remove_configs(self):
276 wrapper = SubversionTunnelWrapper(timeout=5)
277 with patch('os.remove') as remove_mock:
278 wrapper.remove_configs()
279 expected_calls = [
280 call(wrapper.svn_conf_path), call(wrapper.hooks_env_path)]
281 assert sorted(remove_mock.call_args_list) == sorted(expected_calls)
282
283 def _poll(self):
284 self.counter += 1
285 return None if self.counter < 6 else 1
@@ -1,703 +1,732 b''
1
1
2
2
3 ################################################################################
3 ################################################################################
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10
10
11 ################################################################################
11 ################################################################################
12 ## EMAIL CONFIGURATION ##
12 ## EMAIL CONFIGURATION ##
13 ## Uncomment and replace with the email address which should receive ##
13 ## Uncomment and replace with the email address which should receive ##
14 ## any error reports after an application crash ##
14 ## any error reports after an application crash ##
15 ## Additionally these settings will be used by the RhodeCode mailing system ##
15 ## Additionally these settings will be used by the RhodeCode mailing system ##
16 ################################################################################
16 ################################################################################
17
17
18 ## prefix all emails subjects with given prefix, helps filtering out emails
18 ## prefix all emails subjects with given prefix, helps filtering out emails
19 #email_prefix = [RhodeCode]
19 #email_prefix = [RhodeCode]
20
20
21 ## email FROM address all mails will be sent
21 ## email FROM address all mails will be sent
22 #app_email_from = rhodecode-noreply@localhost
22 #app_email_from = rhodecode-noreply@localhost
23
23
24 ## Uncomment and replace with the address which should receive any error report
24 ## Uncomment and replace with the address which should receive any error report
25 ## note: using appenlight for error handling doesn't need this to be uncommented
25 ## note: using appenlight for error handling doesn't need this to be uncommented
26 #email_to = admin@localhost
26 #email_to = admin@localhost
27
27
28 ## in case of Application errors, sent an error email form
28 ## in case of Application errors, sent an error email form
29 #error_email_from = rhodecode_error@localhost
29 #error_email_from = rhodecode_error@localhost
30
30
31 ## additional error message to be send in case of server crash
31 ## additional error message to be send in case of server crash
32 #error_message =
32 #error_message =
33
33
34
34
35 #smtp_server = mail.server.com
35 #smtp_server = mail.server.com
36 #smtp_username =
36 #smtp_username =
37 #smtp_password =
37 #smtp_password =
38 #smtp_port =
38 #smtp_port =
39 #smtp_use_tls = false
39 #smtp_use_tls = false
40 #smtp_use_ssl = true
40 #smtp_use_ssl = true
41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
42 #smtp_auth =
42 #smtp_auth =
43
43
44 [server:main]
44 [server:main]
45 ## COMMON ##
45 ## COMMON ##
46 host = 127.0.0.1
46 host = 127.0.0.1
47 port = 5000
47 port = 5000
48
48
49 ##################################
49 ##################################
50 ## WAITRESS WSGI SERVER ##
50 ## WAITRESS WSGI SERVER ##
51 ## Recommended for Development ##
51 ## Recommended for Development ##
52 ##################################
52 ##################################
53
53
54 use = egg:waitress#main
54 use = egg:waitress#main
55 ## number of worker threads
55 ## number of worker threads
56 threads = 5
56 threads = 5
57 ## MAX BODY SIZE 100GB
57 ## MAX BODY SIZE 100GB
58 max_request_body_size = 107374182400
58 max_request_body_size = 107374182400
59 ## Use poll instead of select, fixes file descriptors limits problems.
59 ## Use poll instead of select, fixes file descriptors limits problems.
60 ## May not work on old windows systems.
60 ## May not work on old windows systems.
61 asyncore_use_poll = true
61 asyncore_use_poll = true
62
62
63
63
64 ##########################
64 ##########################
65 ## GUNICORN WSGI SERVER ##
65 ## GUNICORN WSGI SERVER ##
66 ##########################
66 ##########################
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
68
68
69 #use = egg:gunicorn#main
69 #use = egg:gunicorn#main
70 ## Sets the number of process workers. You must set `instance_id = *`
70 ## Sets the number of process workers. You must set `instance_id = *`
71 ## when this option is set to more than one worker, recommended
71 ## when this option is set to more than one worker, recommended
72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
73 ## The `instance_id = *` must be set in the [app:main] section below
73 ## The `instance_id = *` must be set in the [app:main] section below
74 #workers = 2
74 #workers = 2
75 ## number of threads for each of the worker, must be set to 1 for gevent
75 ## number of threads for each of the worker, must be set to 1 for gevent
76 ## generally recommened to be at 1
76 ## generally recommened to be at 1
77 #threads = 1
77 #threads = 1
78 ## process name
78 ## process name
79 #proc_name = rhodecode
79 #proc_name = rhodecode
80 ## type of worker class, one of sync, gevent
80 ## type of worker class, one of sync, gevent
81 ## recommended for bigger setup is using of of other than sync one
81 ## recommended for bigger setup is using of of other than sync one
82 #worker_class = sync
82 #worker_class = sync
83 ## The maximum number of simultaneous clients. Valid only for Gevent
83 ## The maximum number of simultaneous clients. Valid only for Gevent
84 #worker_connections = 10
84 #worker_connections = 10
85 ## max number of requests that worker will handle before being gracefully
85 ## max number of requests that worker will handle before being gracefully
86 ## restarted, could prevent memory leaks
86 ## restarted, could prevent memory leaks
87 #max_requests = 1000
87 #max_requests = 1000
88 #max_requests_jitter = 30
88 #max_requests_jitter = 30
89 ## amount of time a worker can spend with handling a request before it
89 ## amount of time a worker can spend with handling a request before it
90 ## gets killed and restarted. Set to 6hrs
90 ## gets killed and restarted. Set to 6hrs
91 #timeout = 21600
91 #timeout = 21600
92
92
93
93
94 ## prefix middleware for RhodeCode.
94 ## prefix middleware for RhodeCode.
95 ## recommended when using proxy setup.
95 ## recommended when using proxy setup.
96 ## allows to set RhodeCode under a prefix in server.
96 ## allows to set RhodeCode under a prefix in server.
97 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
97 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
98 ## And set your prefix like: `prefix = /custom_prefix`
98 ## And set your prefix like: `prefix = /custom_prefix`
99 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
99 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
100 ## to make your cookies only work on prefix url
100 ## to make your cookies only work on prefix url
101 [filter:proxy-prefix]
101 [filter:proxy-prefix]
102 use = egg:PasteDeploy#prefix
102 use = egg:PasteDeploy#prefix
103 prefix = /
103 prefix = /
104
104
105 [app:main]
105 [app:main]
106 use = egg:rhodecode-enterprise-ce
106 use = egg:rhodecode-enterprise-ce
107
107
108 ## enable proxy prefix middleware, defined above
108 ## enable proxy prefix middleware, defined above
109 #filter-with = proxy-prefix
109 #filter-with = proxy-prefix
110
110
111 # During development the we want to have the debug toolbar enabled
111 # During development the we want to have the debug toolbar enabled
112 pyramid.includes =
112 pyramid.includes =
113 pyramid_debugtoolbar
113 pyramid_debugtoolbar
114 rhodecode.utils.debugtoolbar
114 rhodecode.utils.debugtoolbar
115 rhodecode.lib.middleware.request_wrapper
115 rhodecode.lib.middleware.request_wrapper
116
116
117 pyramid.reload_templates = true
117 pyramid.reload_templates = true
118
118
119 debugtoolbar.hosts = 0.0.0.0/0
119 debugtoolbar.hosts = 0.0.0.0/0
120 debugtoolbar.exclude_prefixes =
120 debugtoolbar.exclude_prefixes =
121 /css
121 /css
122 /fonts
122 /fonts
123 /images
123 /images
124 /js
124 /js
125
125
126 ## RHODECODE PLUGINS ##
126 ## RHODECODE PLUGINS ##
127 rhodecode.includes =
127 rhodecode.includes =
128 rhodecode.api
128 rhodecode.api
129
129
130
130
131 # api prefix url
131 # api prefix url
132 rhodecode.api.url = /_admin/api
132 rhodecode.api.url = /_admin/api
133
133
134
134
135 ## END RHODECODE PLUGINS ##
135 ## END RHODECODE PLUGINS ##
136
136
137 ## encryption key used to encrypt social plugin tokens,
137 ## encryption key used to encrypt social plugin tokens,
138 ## remote_urls with credentials etc, if not set it defaults to
138 ## remote_urls with credentials etc, if not set it defaults to
139 ## `beaker.session.secret`
139 ## `beaker.session.secret`
140 #rhodecode.encrypted_values.secret =
140 #rhodecode.encrypted_values.secret =
141
141
142 ## decryption strict mode (enabled by default). It controls if decryption raises
142 ## decryption strict mode (enabled by default). It controls if decryption raises
143 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
143 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
144 #rhodecode.encrypted_values.strict = false
144 #rhodecode.encrypted_values.strict = false
145
145
146 ## return gzipped responses from Rhodecode (static files/application)
146 ## return gzipped responses from Rhodecode (static files/application)
147 gzip_responses = false
147 gzip_responses = false
148
148
149 ## autogenerate javascript routes file on startup
149 ## autogenerate javascript routes file on startup
150 generate_js_files = false
150 generate_js_files = false
151
151
152 ## Optional Languages
152 ## Optional Languages
153 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
153 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
154 lang = en
154 lang = en
155
155
156 ## perform a full repository scan on each server start, this should be
156 ## perform a full repository scan on each server start, this should be
157 ## set to false after first startup, to allow faster server restarts.
157 ## set to false after first startup, to allow faster server restarts.
158 startup.import_repos = false
158 startup.import_repos = false
159
159
160 ## Uncomment and set this path to use archive download cache.
160 ## Uncomment and set this path to use archive download cache.
161 ## Once enabled, generated archives will be cached at this location
161 ## Once enabled, generated archives will be cached at this location
162 ## and served from the cache during subsequent requests for the same archive of
162 ## and served from the cache during subsequent requests for the same archive of
163 ## the repository.
163 ## the repository.
164 #archive_cache_dir = /tmp/tarballcache
164 #archive_cache_dir = /tmp/tarballcache
165
165
166 ## change this to unique ID for security
166 ## change this to unique ID for security
167 app_instance_uuid = rc-production
167 app_instance_uuid = rc-production
168
168
169 ## cut off limit for large diffs (size in bytes)
169 ## cut off limit for large diffs (size in bytes)
170 cut_off_limit_diff = 1024000
170 cut_off_limit_diff = 1024000
171 cut_off_limit_file = 256000
171 cut_off_limit_file = 256000
172
172
173 ## use cache version of scm repo everywhere
173 ## use cache version of scm repo everywhere
174 vcs_full_cache = true
174 vcs_full_cache = true
175
175
176 ## force https in RhodeCode, fixes https redirects, assumes it's always https
176 ## force https in RhodeCode, fixes https redirects, assumes it's always https
177 ## Normally this is controlled by proper http flags sent from http server
177 ## Normally this is controlled by proper http flags sent from http server
178 force_https = false
178 force_https = false
179
179
180 ## use Strict-Transport-Security headers
180 ## use Strict-Transport-Security headers
181 use_htsts = false
181 use_htsts = false
182
182
183 ## number of commits stats will parse on each iteration
183 ## number of commits stats will parse on each iteration
184 commit_parse_limit = 25
184 commit_parse_limit = 25
185
185
186 ## git rev filter option, --all is the default filter, if you need to
186 ## git rev filter option, --all is the default filter, if you need to
187 ## hide all refs in changelog switch this to --branches --tags
187 ## hide all refs in changelog switch this to --branches --tags
188 git_rev_filter = --branches --tags
188 git_rev_filter = --branches --tags
189
189
190 # Set to true if your repos are exposed using the dumb protocol
190 # Set to true if your repos are exposed using the dumb protocol
191 git_update_server_info = false
191 git_update_server_info = false
192
192
193 ## RSS/ATOM feed options
193 ## RSS/ATOM feed options
194 rss_cut_off_limit = 256000
194 rss_cut_off_limit = 256000
195 rss_items_per_page = 10
195 rss_items_per_page = 10
196 rss_include_diff = false
196 rss_include_diff = false
197
197
198 ## gist URL alias, used to create nicer urls for gist. This should be an
198 ## gist URL alias, used to create nicer urls for gist. This should be an
199 ## url that does rewrites to _admin/gists/{gistid}.
199 ## url that does rewrites to _admin/gists/{gistid}.
200 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
200 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
201 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
201 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
202 gist_alias_url =
202 gist_alias_url =
203
203
204 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
204 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
205 ## used for access.
205 ## used for access.
206 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
206 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
207 ## came from the the logged in user who own this authentication token.
207 ## came from the the logged in user who own this authentication token.
208 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
208 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
209 ## authentication token. Such view would be only accessible when used together
209 ## authentication token. Such view would be only accessible when used together
210 ## with this authentication token
210 ## with this authentication token
211 ##
211 ##
212 ## list of all views can be found under `/_admin/permissions/auth_token_access`
212 ## list of all views can be found under `/_admin/permissions/auth_token_access`
213 ## The list should be "," separated and on a single line.
213 ## The list should be "," separated and on a single line.
214 ##
214 ##
215 ## Most common views to enable:
215 ## Most common views to enable:
216 # RepoCommitsView:repo_commit_download
216 # RepoCommitsView:repo_commit_download
217 # RepoCommitsView:repo_commit_patch
217 # RepoCommitsView:repo_commit_patch
218 # RepoCommitsView:repo_commit_raw
218 # RepoCommitsView:repo_commit_raw
219 # RepoCommitsView:repo_commit_raw@TOKEN
219 # RepoCommitsView:repo_commit_raw@TOKEN
220 # RepoFilesView:repo_files_diff
220 # RepoFilesView:repo_files_diff
221 # RepoFilesView:repo_archivefile
221 # RepoFilesView:repo_archivefile
222 # RepoFilesView:repo_file_raw
222 # RepoFilesView:repo_file_raw
223 # GistView:*
223 # GistView:*
224 api_access_controllers_whitelist =
224 api_access_controllers_whitelist =
225
225
226 ## default encoding used to convert from and to unicode
226 ## default encoding used to convert from and to unicode
227 ## can be also a comma separated list of encoding in case of mixed encodings
227 ## can be also a comma separated list of encoding in case of mixed encodings
228 default_encoding = UTF-8
228 default_encoding = UTF-8
229
229
230 ## instance-id prefix
230 ## instance-id prefix
231 ## a prefix key for this instance used for cache invalidation when running
231 ## a prefix key for this instance used for cache invalidation when running
232 ## multiple instances of rhodecode, make sure it's globally unique for
232 ## multiple instances of rhodecode, make sure it's globally unique for
233 ## all running rhodecode instances. Leave empty if you don't use it
233 ## all running rhodecode instances. Leave empty if you don't use it
234 instance_id =
234 instance_id =
235
235
236 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
236 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
237 ## of an authentication plugin also if it is disabled by it's settings.
237 ## of an authentication plugin also if it is disabled by it's settings.
238 ## This could be useful if you are unable to log in to the system due to broken
238 ## This could be useful if you are unable to log in to the system due to broken
239 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
239 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
240 ## module to log in again and fix the settings.
240 ## module to log in again and fix the settings.
241 ##
241 ##
242 ## Available builtin plugin IDs (hash is part of the ID):
242 ## Available builtin plugin IDs (hash is part of the ID):
243 ## egg:rhodecode-enterprise-ce#rhodecode
243 ## egg:rhodecode-enterprise-ce#rhodecode
244 ## egg:rhodecode-enterprise-ce#pam
244 ## egg:rhodecode-enterprise-ce#pam
245 ## egg:rhodecode-enterprise-ce#ldap
245 ## egg:rhodecode-enterprise-ce#ldap
246 ## egg:rhodecode-enterprise-ce#jasig_cas
246 ## egg:rhodecode-enterprise-ce#jasig_cas
247 ## egg:rhodecode-enterprise-ce#headers
247 ## egg:rhodecode-enterprise-ce#headers
248 ## egg:rhodecode-enterprise-ce#crowd
248 ## egg:rhodecode-enterprise-ce#crowd
249 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
249 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
250
250
251 ## alternative return HTTP header for failed authentication. Default HTTP
251 ## alternative return HTTP header for failed authentication. Default HTTP
252 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
252 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
253 ## handling that causing a series of failed authentication calls.
253 ## handling that causing a series of failed authentication calls.
254 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
254 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
255 ## This will be served instead of default 401 on bad authnetication
255 ## This will be served instead of default 401 on bad authnetication
256 auth_ret_code =
256 auth_ret_code =
257
257
258 ## use special detection method when serving auth_ret_code, instead of serving
258 ## use special detection method when serving auth_ret_code, instead of serving
259 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
259 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
260 ## and then serve auth_ret_code to clients
260 ## and then serve auth_ret_code to clients
261 auth_ret_code_detection = false
261 auth_ret_code_detection = false
262
262
263 ## locking return code. When repository is locked return this HTTP code. 2XX
263 ## locking return code. When repository is locked return this HTTP code. 2XX
264 ## codes don't break the transactions while 4XX codes do
264 ## codes don't break the transactions while 4XX codes do
265 lock_ret_code = 423
265 lock_ret_code = 423
266
266
267 ## allows to change the repository location in settings page
267 ## allows to change the repository location in settings page
268 allow_repo_location_change = true
268 allow_repo_location_change = true
269
269
270 ## allows to setup custom hooks in settings page
270 ## allows to setup custom hooks in settings page
271 allow_custom_hooks_settings = true
271 allow_custom_hooks_settings = true
272
272
273 ## generated license token, goto license page in RhodeCode settings to obtain
273 ## generated license token, goto license page in RhodeCode settings to obtain
274 ## new token
274 ## new token
275 license_token =
275 license_token =
276
276
277 ## supervisor connection uri, for managing supervisor and logs.
277 ## supervisor connection uri, for managing supervisor and logs.
278 supervisor.uri =
278 supervisor.uri =
279 ## supervisord group name/id we only want this RC instance to handle
279 ## supervisord group name/id we only want this RC instance to handle
280 supervisor.group_id = dev
280 supervisor.group_id = dev
281
281
282 ## Display extended labs settings
282 ## Display extended labs settings
283 labs_settings_active = true
283 labs_settings_active = true
284
284
285 ####################################
285 ####################################
286 ### CELERY CONFIG ####
286 ### CELERY CONFIG ####
287 ####################################
287 ####################################
288 use_celery = false
288 use_celery = false
289 broker.host = localhost
289 broker.host = localhost
290 broker.vhost = rabbitmqhost
290 broker.vhost = rabbitmqhost
291 broker.port = 5672
291 broker.port = 5672
292 broker.user = rabbitmq
292 broker.user = rabbitmq
293 broker.password = qweqwe
293 broker.password = qweqwe
294
294
295 celery.imports = rhodecode.lib.celerylib.tasks
295 celery.imports = rhodecode.lib.celerylib.tasks
296
296
297 celery.result.backend = amqp
297 celery.result.backend = amqp
298 celery.result.dburi = amqp://
298 celery.result.dburi = amqp://
299 celery.result.serialier = json
299 celery.result.serialier = json
300
300
301 #celery.send.task.error.emails = true
301 #celery.send.task.error.emails = true
302 #celery.amqp.task.result.expires = 18000
302 #celery.amqp.task.result.expires = 18000
303
303
304 celeryd.concurrency = 2
304 celeryd.concurrency = 2
305 #celeryd.log.file = celeryd.log
305 #celeryd.log.file = celeryd.log
306 celeryd.log.level = debug
306 celeryd.log.level = debug
307 celeryd.max.tasks.per.child = 1
307 celeryd.max.tasks.per.child = 1
308
308
309 ## tasks will never be sent to the queue, but executed locally instead.
309 ## tasks will never be sent to the queue, but executed locally instead.
310 celery.always.eager = false
310 celery.always.eager = false
311
311
312 ####################################
312 ####################################
313 ### BEAKER CACHE ####
313 ### BEAKER CACHE ####
314 ####################################
314 ####################################
315 # default cache dir for templates. Putting this into a ramdisk
315 # default cache dir for templates. Putting this into a ramdisk
316 ## can boost performance, eg. %(here)s/data_ramdisk
316 ## can boost performance, eg. %(here)s/data_ramdisk
317 cache_dir = %(here)s/data
317 cache_dir = %(here)s/data
318
318
319 ## locking and default file storage for Beaker. Putting this into a ramdisk
319 ## locking and default file storage for Beaker. Putting this into a ramdisk
320 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
320 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
321 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
321 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
322 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
322 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
323
323
324 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
324 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
325
325
326 beaker.cache.super_short_term.type = memory
326 beaker.cache.super_short_term.type = memory
327 beaker.cache.super_short_term.expire = 10
327 beaker.cache.super_short_term.expire = 10
328 beaker.cache.super_short_term.key_length = 256
328 beaker.cache.super_short_term.key_length = 256
329
329
330 beaker.cache.short_term.type = memory
330 beaker.cache.short_term.type = memory
331 beaker.cache.short_term.expire = 60
331 beaker.cache.short_term.expire = 60
332 beaker.cache.short_term.key_length = 256
332 beaker.cache.short_term.key_length = 256
333
333
334 beaker.cache.long_term.type = memory
334 beaker.cache.long_term.type = memory
335 beaker.cache.long_term.expire = 36000
335 beaker.cache.long_term.expire = 36000
336 beaker.cache.long_term.key_length = 256
336 beaker.cache.long_term.key_length = 256
337
337
338 beaker.cache.sql_cache_short.type = memory
338 beaker.cache.sql_cache_short.type = memory
339 beaker.cache.sql_cache_short.expire = 10
339 beaker.cache.sql_cache_short.expire = 10
340 beaker.cache.sql_cache_short.key_length = 256
340 beaker.cache.sql_cache_short.key_length = 256
341
341
342 ## default is memory cache, configure only if required
342 ## default is memory cache, configure only if required
343 ## using multi-node or multi-worker setup
343 ## using multi-node or multi-worker setup
344 #beaker.cache.auth_plugins.type = ext:database
344 #beaker.cache.auth_plugins.type = ext:database
345 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
345 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
346 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
346 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
347 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
347 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
348 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
348 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
349 #beaker.cache.auth_plugins.sa.pool_size = 10
349 #beaker.cache.auth_plugins.sa.pool_size = 10
350 #beaker.cache.auth_plugins.sa.max_overflow = 0
350 #beaker.cache.auth_plugins.sa.max_overflow = 0
351
351
352 beaker.cache.repo_cache_long.type = memorylru_base
352 beaker.cache.repo_cache_long.type = memorylru_base
353 beaker.cache.repo_cache_long.max_items = 4096
353 beaker.cache.repo_cache_long.max_items = 4096
354 beaker.cache.repo_cache_long.expire = 2592000
354 beaker.cache.repo_cache_long.expire = 2592000
355
355
356 ## default is memorylru_base cache, configure only if required
356 ## default is memorylru_base cache, configure only if required
357 ## using multi-node or multi-worker setup
357 ## using multi-node or multi-worker setup
358 #beaker.cache.repo_cache_long.type = ext:memcached
358 #beaker.cache.repo_cache_long.type = ext:memcached
359 #beaker.cache.repo_cache_long.url = localhost:11211
359 #beaker.cache.repo_cache_long.url = localhost:11211
360 #beaker.cache.repo_cache_long.expire = 1209600
360 #beaker.cache.repo_cache_long.expire = 1209600
361 #beaker.cache.repo_cache_long.key_length = 256
361 #beaker.cache.repo_cache_long.key_length = 256
362
362
363 ####################################
363 ####################################
364 ### BEAKER SESSION ####
364 ### BEAKER SESSION ####
365 ####################################
365 ####################################
366
366
367 ## .session.type is type of storage options for the session, current allowed
367 ## .session.type is type of storage options for the session, current allowed
368 ## types are file, ext:memcached, ext:database, and memory (default).
368 ## types are file, ext:memcached, ext:database, and memory (default).
369 beaker.session.type = file
369 beaker.session.type = file
370 beaker.session.data_dir = %(here)s/data/sessions/data
370 beaker.session.data_dir = %(here)s/data/sessions/data
371
371
372 ## db based session, fast, and allows easy management over logged in users
372 ## db based session, fast, and allows easy management over logged in users
373 #beaker.session.type = ext:database
373 #beaker.session.type = ext:database
374 #beaker.session.table_name = db_session
374 #beaker.session.table_name = db_session
375 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
375 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
376 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
376 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
377 #beaker.session.sa.pool_recycle = 3600
377 #beaker.session.sa.pool_recycle = 3600
378 #beaker.session.sa.echo = false
378 #beaker.session.sa.echo = false
379
379
380 beaker.session.key = rhodecode
380 beaker.session.key = rhodecode
381 beaker.session.secret = develop-rc-uytcxaz
381 beaker.session.secret = develop-rc-uytcxaz
382 beaker.session.lock_dir = %(here)s/data/sessions/lock
382 beaker.session.lock_dir = %(here)s/data/sessions/lock
383
383
384 ## Secure encrypted cookie. Requires AES and AES python libraries
384 ## Secure encrypted cookie. Requires AES and AES python libraries
385 ## you must disable beaker.session.secret to use this
385 ## you must disable beaker.session.secret to use this
386 #beaker.session.encrypt_key = key_for_encryption
386 #beaker.session.encrypt_key = key_for_encryption
387 #beaker.session.validate_key = validation_key
387 #beaker.session.validate_key = validation_key
388
388
389 ## sets session as invalid(also logging out user) if it haven not been
389 ## sets session as invalid(also logging out user) if it haven not been
390 ## accessed for given amount of time in seconds
390 ## accessed for given amount of time in seconds
391 beaker.session.timeout = 2592000
391 beaker.session.timeout = 2592000
392 beaker.session.httponly = true
392 beaker.session.httponly = true
393 ## Path to use for the cookie. Set to prefix if you use prefix middleware
393 ## Path to use for the cookie. Set to prefix if you use prefix middleware
394 #beaker.session.cookie_path = /custom_prefix
394 #beaker.session.cookie_path = /custom_prefix
395
395
396 ## uncomment for https secure cookie
396 ## uncomment for https secure cookie
397 beaker.session.secure = false
397 beaker.session.secure = false
398
398
399 ## auto save the session to not to use .save()
399 ## auto save the session to not to use .save()
400 beaker.session.auto = false
400 beaker.session.auto = false
401
401
402 ## default cookie expiration time in seconds, set to `true` to set expire
402 ## default cookie expiration time in seconds, set to `true` to set expire
403 ## at browser close
403 ## at browser close
404 #beaker.session.cookie_expires = 3600
404 #beaker.session.cookie_expires = 3600
405
405
406 ###################################
406 ###################################
407 ## SEARCH INDEXING CONFIGURATION ##
407 ## SEARCH INDEXING CONFIGURATION ##
408 ###################################
408 ###################################
409 ## Full text search indexer is available in rhodecode-tools under
409 ## Full text search indexer is available in rhodecode-tools under
410 ## `rhodecode-tools index` command
410 ## `rhodecode-tools index` command
411
411
412 ## WHOOSH Backend, doesn't require additional services to run
412 ## WHOOSH Backend, doesn't require additional services to run
413 ## it works good with few dozen repos
413 ## it works good with few dozen repos
414 search.module = rhodecode.lib.index.whoosh
414 search.module = rhodecode.lib.index.whoosh
415 search.location = %(here)s/data/index
415 search.location = %(here)s/data/index
416
416
417 ########################################
417 ########################################
418 ### CHANNELSTREAM CONFIG ####
418 ### CHANNELSTREAM CONFIG ####
419 ########################################
419 ########################################
420 ## channelstream enables persistent connections and live notification
420 ## channelstream enables persistent connections and live notification
421 ## in the system. It's also used by the chat system
421 ## in the system. It's also used by the chat system
422 channelstream.enabled = false
422 channelstream.enabled = false
423
423
424 ## server address for channelstream server on the backend
424 ## server address for channelstream server on the backend
425 channelstream.server = 127.0.0.1:9800
425 channelstream.server = 127.0.0.1:9800
426
426
427 ## location of the channelstream server from outside world
427 ## location of the channelstream server from outside world
428 ## use ws:// for http or wss:// for https. This address needs to be handled
428 ## use ws:// for http or wss:// for https. This address needs to be handled
429 ## by external HTTP server such as Nginx or Apache
429 ## by external HTTP server such as Nginx or Apache
430 ## see nginx/apache configuration examples in our docs
430 ## see nginx/apache configuration examples in our docs
431 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
431 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
432 channelstream.secret = secret
432 channelstream.secret = secret
433 channelstream.history.location = %(here)s/channelstream_history
433 channelstream.history.location = %(here)s/channelstream_history
434
434
435 ## Internal application path that Javascript uses to connect into.
435 ## Internal application path that Javascript uses to connect into.
436 ## If you use proxy-prefix the prefix should be added before /_channelstream
436 ## If you use proxy-prefix the prefix should be added before /_channelstream
437 channelstream.proxy_path = /_channelstream
437 channelstream.proxy_path = /_channelstream
438
438
439
439
440 ###################################
440 ###################################
441 ## APPENLIGHT CONFIG ##
441 ## APPENLIGHT CONFIG ##
442 ###################################
442 ###################################
443
443
444 ## Appenlight is tailored to work with RhodeCode, see
444 ## Appenlight is tailored to work with RhodeCode, see
445 ## http://appenlight.com for details how to obtain an account
445 ## http://appenlight.com for details how to obtain an account
446
446
447 ## appenlight integration enabled
447 ## appenlight integration enabled
448 appenlight = false
448 appenlight = false
449
449
450 appenlight.server_url = https://api.appenlight.com
450 appenlight.server_url = https://api.appenlight.com
451 appenlight.api_key = YOUR_API_KEY
451 appenlight.api_key = YOUR_API_KEY
452 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
452 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
453
453
454 # used for JS client
454 # used for JS client
455 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
455 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
456
456
457 ## TWEAK AMOUNT OF INFO SENT HERE
457 ## TWEAK AMOUNT OF INFO SENT HERE
458
458
459 ## enables 404 error logging (default False)
459 ## enables 404 error logging (default False)
460 appenlight.report_404 = false
460 appenlight.report_404 = false
461
461
462 ## time in seconds after request is considered being slow (default 1)
462 ## time in seconds after request is considered being slow (default 1)
463 appenlight.slow_request_time = 1
463 appenlight.slow_request_time = 1
464
464
465 ## record slow requests in application
465 ## record slow requests in application
466 ## (needs to be enabled for slow datastore recording and time tracking)
466 ## (needs to be enabled for slow datastore recording and time tracking)
467 appenlight.slow_requests = true
467 appenlight.slow_requests = true
468
468
469 ## enable hooking to application loggers
469 ## enable hooking to application loggers
470 appenlight.logging = true
470 appenlight.logging = true
471
471
472 ## minimum log level for log capture
472 ## minimum log level for log capture
473 appenlight.logging.level = WARNING
473 appenlight.logging.level = WARNING
474
474
475 ## send logs only from erroneous/slow requests
475 ## send logs only from erroneous/slow requests
476 ## (saves API quota for intensive logging)
476 ## (saves API quota for intensive logging)
477 appenlight.logging_on_error = false
477 appenlight.logging_on_error = false
478
478
479 ## list of additonal keywords that should be grabbed from environ object
479 ## list of additonal keywords that should be grabbed from environ object
480 ## can be string with comma separated list of words in lowercase
480 ## can be string with comma separated list of words in lowercase
481 ## (by default client will always send following info:
481 ## (by default client will always send following info:
482 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
482 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
483 ## start with HTTP* this list be extended with additional keywords here
483 ## start with HTTP* this list be extended with additional keywords here
484 appenlight.environ_keys_whitelist =
484 appenlight.environ_keys_whitelist =
485
485
486 ## list of keywords that should be blanked from request object
486 ## list of keywords that should be blanked from request object
487 ## can be string with comma separated list of words in lowercase
487 ## can be string with comma separated list of words in lowercase
488 ## (by default client will always blank keys that contain following words
488 ## (by default client will always blank keys that contain following words
489 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
489 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
490 ## this list be extended with additional keywords set here
490 ## this list be extended with additional keywords set here
491 appenlight.request_keys_blacklist =
491 appenlight.request_keys_blacklist =
492
492
493 ## list of namespaces that should be ignores when gathering log entries
493 ## list of namespaces that should be ignores when gathering log entries
494 ## can be string with comma separated list of namespaces
494 ## can be string with comma separated list of namespaces
495 ## (by default the client ignores own entries: appenlight_client.client)
495 ## (by default the client ignores own entries: appenlight_client.client)
496 appenlight.log_namespace_blacklist =
496 appenlight.log_namespace_blacklist =
497
497
498
498
499 ################################################################################
499 ################################################################################
500 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
500 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
501 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
501 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
502 ## execute malicious code after an exception is raised. ##
502 ## execute malicious code after an exception is raised. ##
503 ################################################################################
503 ################################################################################
504 #set debug = false
504 #set debug = false
505
505
506
506
507 ##############
507 ##############
508 ## STYLING ##
508 ## STYLING ##
509 ##############
509 ##############
510 debug_style = true
510 debug_style = true
511
511
512 ###########################################
512 ###########################################
513 ### MAIN RHODECODE DATABASE CONFIG ###
513 ### MAIN RHODECODE DATABASE CONFIG ###
514 ###########################################
514 ###########################################
515 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
515 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
516 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
516 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
517 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
517 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
518 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
518 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
519
519
520 # see sqlalchemy docs for other advanced settings
520 # see sqlalchemy docs for other advanced settings
521
521
522 ## print the sql statements to output
522 ## print the sql statements to output
523 sqlalchemy.db1.echo = false
523 sqlalchemy.db1.echo = false
524 ## recycle the connections after this amount of seconds
524 ## recycle the connections after this amount of seconds
525 sqlalchemy.db1.pool_recycle = 3600
525 sqlalchemy.db1.pool_recycle = 3600
526 sqlalchemy.db1.convert_unicode = true
526 sqlalchemy.db1.convert_unicode = true
527
527
528 ## the number of connections to keep open inside the connection pool.
528 ## the number of connections to keep open inside the connection pool.
529 ## 0 indicates no limit
529 ## 0 indicates no limit
530 #sqlalchemy.db1.pool_size = 5
530 #sqlalchemy.db1.pool_size = 5
531
531
532 ## the number of connections to allow in connection pool "overflow", that is
532 ## the number of connections to allow in connection pool "overflow", that is
533 ## connections that can be opened above and beyond the pool_size setting,
533 ## connections that can be opened above and beyond the pool_size setting,
534 ## which defaults to five.
534 ## which defaults to five.
535 #sqlalchemy.db1.max_overflow = 10
535 #sqlalchemy.db1.max_overflow = 10
536
536
537
537
538 ##################
538 ##################
539 ### VCS CONFIG ###
539 ### VCS CONFIG ###
540 ##################
540 ##################
541 vcs.server.enable = true
541 vcs.server.enable = true
542 vcs.server = localhost:9900
542 vcs.server = localhost:9900
543
543
544 ## Web server connectivity protocol, responsible for web based VCS operatations
544 ## Web server connectivity protocol, responsible for web based VCS operatations
545 ## Available protocols are:
545 ## Available protocols are:
546 ## `http` - use http-rpc backend (default)
546 ## `http` - use http-rpc backend (default)
547 vcs.server.protocol = http
547 vcs.server.protocol = http
548
548
549 ## Push/Pull operations protocol, available options are:
549 ## Push/Pull operations protocol, available options are:
550 ## `http` - use http-rpc backend (default)
550 ## `http` - use http-rpc backend (default)
551 ##
551 ##
552 vcs.scm_app_implementation = http
552 vcs.scm_app_implementation = http
553
553
554 ## Push/Pull operations hooks protocol, available options are:
554 ## Push/Pull operations hooks protocol, available options are:
555 ## `http` - use http-rpc backend (default)
555 ## `http` - use http-rpc backend (default)
556 vcs.hooks.protocol = http
556 vcs.hooks.protocol = http
557
557
558 vcs.server.log_level = debug
558 vcs.server.log_level = debug
559 ## Start VCSServer with this instance as a subprocess, usefull for development
559 ## Start VCSServer with this instance as a subprocess, usefull for development
560 vcs.start_server = true
560 vcs.start_server = true
561
561
562 ## List of enabled VCS backends, available options are:
562 ## List of enabled VCS backends, available options are:
563 ## `hg` - mercurial
563 ## `hg` - mercurial
564 ## `git` - git
564 ## `git` - git
565 ## `svn` - subversion
565 ## `svn` - subversion
566 vcs.backends = hg, git, svn
566 vcs.backends = hg, git, svn
567
567
568 vcs.connection_timeout = 3600
568 vcs.connection_timeout = 3600
569 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
569 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
570 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
570 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
571 #vcs.svn.compatible_version = pre-1.8-compatible
571 #vcs.svn.compatible_version = pre-1.8-compatible
572
572
573
573
574 ############################################################
574 ############################################################
575 ### Subversion proxy support (mod_dav_svn) ###
575 ### Subversion proxy support (mod_dav_svn) ###
576 ### Maps RhodeCode repo groups into SVN paths for Apache ###
576 ### Maps RhodeCode repo groups into SVN paths for Apache ###
577 ############################################################
577 ############################################################
578 ## Enable or disable the config file generation.
578 ## Enable or disable the config file generation.
579 svn.proxy.generate_config = false
579 svn.proxy.generate_config = false
580 ## Generate config file with `SVNListParentPath` set to `On`.
580 ## Generate config file with `SVNListParentPath` set to `On`.
581 svn.proxy.list_parent_path = true
581 svn.proxy.list_parent_path = true
582 ## Set location and file name of generated config file.
582 ## Set location and file name of generated config file.
583 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
583 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
584 ## Used as a prefix to the `Location` block in the generated config file.
584 ## Used as a prefix to the `Location` block in the generated config file.
585 ## In most cases it should be set to `/`.
585 ## In most cases it should be set to `/`.
586 svn.proxy.location_root = /
586 svn.proxy.location_root = /
587 ## Command to reload the mod dav svn configuration on change.
587 ## Command to reload the mod dav svn configuration on change.
588 ## Example: `/etc/init.d/apache2 reload`
588 ## Example: `/etc/init.d/apache2 reload`
589 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
589 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
590 ## If the timeout expires before the reload command finishes, the command will
590 ## If the timeout expires before the reload command finishes, the command will
591 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
591 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
592 #svn.proxy.reload_timeout = 10
592 #svn.proxy.reload_timeout = 10
593
593
594 ############################################################
594 ############################################################
595 ### SSH Support Settings ###
595 ### SSH Support Settings ###
596 ############################################################
596 ############################################################
597
597
598 ## Defines if the authorized_keys file should be written on any change of
598 ## Defines if the authorized_keys file should be written on any change of
599 ## user ssh keys
599 ## user ssh keys
600 ssh.generate_authorized_keyfile = false
600 ssh.generate_authorized_keyfile = false
601
601
602 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
602 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
603 # ssh.authorized_keys_ssh_opts =
603 # ssh.authorized_keys_ssh_opts =
604
604
605 ## File to generate the authorized keys together with options
605 ## File to generate the authorized keys together with options
606 ssh.authorized_keys_file_path = /home/USER/.ssh/authorized_keys
606 ## It is possible to have multiple key files specified in `sshd_config` e.g.
607 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
608 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
609
610 ## Command to execute the SSH wrapper. The binary is available in the
611 ## rhodecode installation directory.
612 ## e.g ~/.rccontrol/community-1/profile/bin/rcssh-wrapper
613 ssh.wrapper_cmd = ~/.rccontrol/community-1/rcssh-wrapper
614
615 ## Allow shell when executing the ssh-wrapper command
616 ssh.wrapper_cmd_allow_shell = false
607
617
608 ## Command to execute as an SSH wrapper, available from
618 ## Enables logging, and detailed output send back to the client. Usefull for
609 ## https://code.rhodecode.com/rhodecode-ssh
619 ## debugging, shouldn't be used in production.
610 ssh.wrapper_cmd = /home/USER/rhodecode-ssh/sshwrapper.py
620 ssh.enable_debug_logging = false
621
622 ## API KEY for user who has access to fetch other user permission information
623 ## most likely an super-admin account with some IP restrictions.
624 ssh.api_key =
611
625
612 ## Allow shell when executing the command
626 ## API Host, the server address of RhodeCode instance that the api_key will
613 ssh.wrapper_cmd_allow_shell = false
627 ## access
628 ssh.api_host = http://localhost
629
630 ## Paths to binary executrables, by default they are the names, but we can
631 ## override them if we want to use a custom one
632 ssh.executable.hg = ~/.rccontrol/vcsserver-1/profile/bin/hg
633 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
634 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
635
614
636
615 ## Dummy marker to add new entries after.
637 ## Dummy marker to add new entries after.
616 ## Add any custom entries below. Please don't remove.
638 ## Add any custom entries below. Please don't remove.
617 custom.conf = 1
639 custom.conf = 1
618
640
619
641
620 ################################
642 ################################
621 ### LOGGING CONFIGURATION ####
643 ### LOGGING CONFIGURATION ####
622 ################################
644 ################################
623 [loggers]
645 [loggers]
624 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
646 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, ssh_wrapper
625
647
626 [handlers]
648 [handlers]
627 keys = console, console_sql
649 keys = console, console_sql
628
650
629 [formatters]
651 [formatters]
630 keys = generic, color_formatter, color_formatter_sql
652 keys = generic, color_formatter, color_formatter_sql
631
653
632 #############
654 #############
633 ## LOGGERS ##
655 ## LOGGERS ##
634 #############
656 #############
635 [logger_root]
657 [logger_root]
636 level = NOTSET
658 level = NOTSET
637 handlers = console
659 handlers = console
638
660
639 [logger_routes]
661 [logger_routes]
640 level = DEBUG
662 level = DEBUG
641 handlers =
663 handlers =
642 qualname = routes.middleware
664 qualname = routes.middleware
643 ## "level = DEBUG" logs the route matched and routing variables.
665 ## "level = DEBUG" logs the route matched and routing variables.
644 propagate = 1
666 propagate = 1
645
667
646 [logger_beaker]
668 [logger_beaker]
647 level = DEBUG
669 level = DEBUG
648 handlers =
670 handlers =
649 qualname = beaker.container
671 qualname = beaker.container
650 propagate = 1
672 propagate = 1
651
673
652 [logger_templates]
674 [logger_templates]
653 level = INFO
675 level = INFO
654 handlers =
676 handlers =
655 qualname = pylons.templating
677 qualname = pylons.templating
656 propagate = 1
678 propagate = 1
657
679
658 [logger_rhodecode]
680 [logger_rhodecode]
659 level = DEBUG
681 level = DEBUG
660 handlers =
682 handlers =
661 qualname = rhodecode
683 qualname = rhodecode
662 propagate = 1
684 propagate = 1
663
685
664 [logger_sqlalchemy]
686 [logger_sqlalchemy]
665 level = INFO
687 level = INFO
666 handlers = console_sql
688 handlers = console_sql
667 qualname = sqlalchemy.engine
689 qualname = sqlalchemy.engine
668 propagate = 0
690 propagate = 0
669
691
692 [logger_ssh_wrapper]
693 level = DEBUG
694 handlers =
695 qualname = ssh_wrapper
696 propagate = 1
697
698
670 ##############
699 ##############
671 ## HANDLERS ##
700 ## HANDLERS ##
672 ##############
701 ##############
673
702
674 [handler_console]
703 [handler_console]
675 class = StreamHandler
704 class = StreamHandler
676 args = (sys.stderr, )
705 args = (sys.stderr, )
677 level = DEBUG
706 level = DEBUG
678 formatter = color_formatter
707 formatter = color_formatter
679
708
680 [handler_console_sql]
709 [handler_console_sql]
681 class = StreamHandler
710 class = StreamHandler
682 args = (sys.stderr, )
711 args = (sys.stderr, )
683 level = DEBUG
712 level = DEBUG
684 formatter = color_formatter_sql
713 formatter = color_formatter_sql
685
714
686 ################
715 ################
687 ## FORMATTERS ##
716 ## FORMATTERS ##
688 ################
717 ################
689
718
690 [formatter_generic]
719 [formatter_generic]
691 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
720 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
692 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
721 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
693 datefmt = %Y-%m-%d %H:%M:%S
722 datefmt = %Y-%m-%d %H:%M:%S
694
723
695 [formatter_color_formatter]
724 [formatter_color_formatter]
696 class = rhodecode.lib.logging_formatter.ColorFormatter
725 class = rhodecode.lib.logging_formatter.ColorFormatter
697 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
726 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
698 datefmt = %Y-%m-%d %H:%M:%S
727 datefmt = %Y-%m-%d %H:%M:%S
699
728
700 [formatter_color_formatter_sql]
729 [formatter_color_formatter_sql]
701 class = rhodecode.lib.logging_formatter.ColorFormatterSql
730 class = rhodecode.lib.logging_formatter.ColorFormatterSql
702 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
731 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
703 datefmt = %Y-%m-%d %H:%M:%S
732 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,672 +1,701 b''
1
1
2
2
3 ################################################################################
3 ################################################################################
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10
10
11 ################################################################################
11 ################################################################################
12 ## EMAIL CONFIGURATION ##
12 ## EMAIL CONFIGURATION ##
13 ## Uncomment and replace with the email address which should receive ##
13 ## Uncomment and replace with the email address which should receive ##
14 ## any error reports after an application crash ##
14 ## any error reports after an application crash ##
15 ## Additionally these settings will be used by the RhodeCode mailing system ##
15 ## Additionally these settings will be used by the RhodeCode mailing system ##
16 ################################################################################
16 ################################################################################
17
17
18 ## prefix all emails subjects with given prefix, helps filtering out emails
18 ## prefix all emails subjects with given prefix, helps filtering out emails
19 #email_prefix = [RhodeCode]
19 #email_prefix = [RhodeCode]
20
20
21 ## email FROM address all mails will be sent
21 ## email FROM address all mails will be sent
22 #app_email_from = rhodecode-noreply@localhost
22 #app_email_from = rhodecode-noreply@localhost
23
23
24 ## Uncomment and replace with the address which should receive any error report
24 ## Uncomment and replace with the address which should receive any error report
25 ## note: using appenlight for error handling doesn't need this to be uncommented
25 ## note: using appenlight for error handling doesn't need this to be uncommented
26 #email_to = admin@localhost
26 #email_to = admin@localhost
27
27
28 ## in case of Application errors, sent an error email form
28 ## in case of Application errors, sent an error email form
29 #error_email_from = rhodecode_error@localhost
29 #error_email_from = rhodecode_error@localhost
30
30
31 ## additional error message to be send in case of server crash
31 ## additional error message to be send in case of server crash
32 #error_message =
32 #error_message =
33
33
34
34
35 #smtp_server = mail.server.com
35 #smtp_server = mail.server.com
36 #smtp_username =
36 #smtp_username =
37 #smtp_password =
37 #smtp_password =
38 #smtp_port =
38 #smtp_port =
39 #smtp_use_tls = false
39 #smtp_use_tls = false
40 #smtp_use_ssl = true
40 #smtp_use_ssl = true
41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
42 #smtp_auth =
42 #smtp_auth =
43
43
44 [server:main]
44 [server:main]
45 ## COMMON ##
45 ## COMMON ##
46 host = 127.0.0.1
46 host = 127.0.0.1
47 port = 5000
47 port = 5000
48
48
49 ##################################
49 ##################################
50 ## WAITRESS WSGI SERVER ##
50 ## WAITRESS WSGI SERVER ##
51 ## Recommended for Development ##
51 ## Recommended for Development ##
52 ##################################
52 ##################################
53
53
54 #use = egg:waitress#main
54 #use = egg:waitress#main
55 ## number of worker threads
55 ## number of worker threads
56 #threads = 5
56 #threads = 5
57 ## MAX BODY SIZE 100GB
57 ## MAX BODY SIZE 100GB
58 #max_request_body_size = 107374182400
58 #max_request_body_size = 107374182400
59 ## Use poll instead of select, fixes file descriptors limits problems.
59 ## Use poll instead of select, fixes file descriptors limits problems.
60 ## May not work on old windows systems.
60 ## May not work on old windows systems.
61 #asyncore_use_poll = true
61 #asyncore_use_poll = true
62
62
63
63
64 ##########################
64 ##########################
65 ## GUNICORN WSGI SERVER ##
65 ## GUNICORN WSGI SERVER ##
66 ##########################
66 ##########################
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
68
68
69 use = egg:gunicorn#main
69 use = egg:gunicorn#main
70 ## Sets the number of process workers. You must set `instance_id = *`
70 ## Sets the number of process workers. You must set `instance_id = *`
71 ## when this option is set to more than one worker, recommended
71 ## when this option is set to more than one worker, recommended
72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
73 ## The `instance_id = *` must be set in the [app:main] section below
73 ## The `instance_id = *` must be set in the [app:main] section below
74 workers = 2
74 workers = 2
75 ## number of threads for each of the worker, must be set to 1 for gevent
75 ## number of threads for each of the worker, must be set to 1 for gevent
76 ## generally recommened to be at 1
76 ## generally recommened to be at 1
77 #threads = 1
77 #threads = 1
78 ## process name
78 ## process name
79 proc_name = rhodecode
79 proc_name = rhodecode
80 ## type of worker class, one of sync, gevent
80 ## type of worker class, one of sync, gevent
81 ## recommended for bigger setup is using of of other than sync one
81 ## recommended for bigger setup is using of of other than sync one
82 worker_class = sync
82 worker_class = sync
83 ## The maximum number of simultaneous clients. Valid only for Gevent
83 ## The maximum number of simultaneous clients. Valid only for Gevent
84 #worker_connections = 10
84 #worker_connections = 10
85 ## max number of requests that worker will handle before being gracefully
85 ## max number of requests that worker will handle before being gracefully
86 ## restarted, could prevent memory leaks
86 ## restarted, could prevent memory leaks
87 max_requests = 1000
87 max_requests = 1000
88 max_requests_jitter = 30
88 max_requests_jitter = 30
89 ## amount of time a worker can spend with handling a request before it
89 ## amount of time a worker can spend with handling a request before it
90 ## gets killed and restarted. Set to 6hrs
90 ## gets killed and restarted. Set to 6hrs
91 timeout = 21600
91 timeout = 21600
92
92
93
93
94 ## prefix middleware for RhodeCode.
94 ## prefix middleware for RhodeCode.
95 ## recommended when using proxy setup.
95 ## recommended when using proxy setup.
96 ## allows to set RhodeCode under a prefix in server.
96 ## allows to set RhodeCode under a prefix in server.
97 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
97 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
98 ## And set your prefix like: `prefix = /custom_prefix`
98 ## And set your prefix like: `prefix = /custom_prefix`
99 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
99 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
100 ## to make your cookies only work on prefix url
100 ## to make your cookies only work on prefix url
101 [filter:proxy-prefix]
101 [filter:proxy-prefix]
102 use = egg:PasteDeploy#prefix
102 use = egg:PasteDeploy#prefix
103 prefix = /
103 prefix = /
104
104
105 [app:main]
105 [app:main]
106 use = egg:rhodecode-enterprise-ce
106 use = egg:rhodecode-enterprise-ce
107
107
108 ## enable proxy prefix middleware, defined above
108 ## enable proxy prefix middleware, defined above
109 #filter-with = proxy-prefix
109 #filter-with = proxy-prefix
110
110
111 ## encryption key used to encrypt social plugin tokens,
111 ## encryption key used to encrypt social plugin tokens,
112 ## remote_urls with credentials etc, if not set it defaults to
112 ## remote_urls with credentials etc, if not set it defaults to
113 ## `beaker.session.secret`
113 ## `beaker.session.secret`
114 #rhodecode.encrypted_values.secret =
114 #rhodecode.encrypted_values.secret =
115
115
116 ## decryption strict mode (enabled by default). It controls if decryption raises
116 ## decryption strict mode (enabled by default). It controls if decryption raises
117 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
117 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
118 #rhodecode.encrypted_values.strict = false
118 #rhodecode.encrypted_values.strict = false
119
119
120 ## return gzipped responses from Rhodecode (static files/application)
120 ## return gzipped responses from Rhodecode (static files/application)
121 gzip_responses = false
121 gzip_responses = false
122
122
123 ## autogenerate javascript routes file on startup
123 ## autogenerate javascript routes file on startup
124 generate_js_files = false
124 generate_js_files = false
125
125
126 ## Optional Languages
126 ## Optional Languages
127 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
127 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
128 lang = en
128 lang = en
129
129
130 ## perform a full repository scan on each server start, this should be
130 ## perform a full repository scan on each server start, this should be
131 ## set to false after first startup, to allow faster server restarts.
131 ## set to false after first startup, to allow faster server restarts.
132 startup.import_repos = false
132 startup.import_repos = false
133
133
134 ## Uncomment and set this path to use archive download cache.
134 ## Uncomment and set this path to use archive download cache.
135 ## Once enabled, generated archives will be cached at this location
135 ## Once enabled, generated archives will be cached at this location
136 ## and served from the cache during subsequent requests for the same archive of
136 ## and served from the cache during subsequent requests for the same archive of
137 ## the repository.
137 ## the repository.
138 #archive_cache_dir = /tmp/tarballcache
138 #archive_cache_dir = /tmp/tarballcache
139
139
140 ## change this to unique ID for security
140 ## change this to unique ID for security
141 app_instance_uuid = rc-production
141 app_instance_uuid = rc-production
142
142
143 ## cut off limit for large diffs (size in bytes)
143 ## cut off limit for large diffs (size in bytes)
144 cut_off_limit_diff = 1024000
144 cut_off_limit_diff = 1024000
145 cut_off_limit_file = 256000
145 cut_off_limit_file = 256000
146
146
147 ## use cache version of scm repo everywhere
147 ## use cache version of scm repo everywhere
148 vcs_full_cache = true
148 vcs_full_cache = true
149
149
150 ## force https in RhodeCode, fixes https redirects, assumes it's always https
150 ## force https in RhodeCode, fixes https redirects, assumes it's always https
151 ## Normally this is controlled by proper http flags sent from http server
151 ## Normally this is controlled by proper http flags sent from http server
152 force_https = false
152 force_https = false
153
153
154 ## use Strict-Transport-Security headers
154 ## use Strict-Transport-Security headers
155 use_htsts = false
155 use_htsts = false
156
156
157 ## number of commits stats will parse on each iteration
157 ## number of commits stats will parse on each iteration
158 commit_parse_limit = 25
158 commit_parse_limit = 25
159
159
160 ## git rev filter option, --all is the default filter, if you need to
160 ## git rev filter option, --all is the default filter, if you need to
161 ## hide all refs in changelog switch this to --branches --tags
161 ## hide all refs in changelog switch this to --branches --tags
162 git_rev_filter = --branches --tags
162 git_rev_filter = --branches --tags
163
163
164 # Set to true if your repos are exposed using the dumb protocol
164 # Set to true if your repos are exposed using the dumb protocol
165 git_update_server_info = false
165 git_update_server_info = false
166
166
167 ## RSS/ATOM feed options
167 ## RSS/ATOM feed options
168 rss_cut_off_limit = 256000
168 rss_cut_off_limit = 256000
169 rss_items_per_page = 10
169 rss_items_per_page = 10
170 rss_include_diff = false
170 rss_include_diff = false
171
171
172 ## gist URL alias, used to create nicer urls for gist. This should be an
172 ## gist URL alias, used to create nicer urls for gist. This should be an
173 ## url that does rewrites to _admin/gists/{gistid}.
173 ## url that does rewrites to _admin/gists/{gistid}.
174 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
174 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
175 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
175 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
176 gist_alias_url =
176 gist_alias_url =
177
177
178 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
178 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
179 ## used for access.
179 ## used for access.
180 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
180 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
181 ## came from the the logged in user who own this authentication token.
181 ## came from the the logged in user who own this authentication token.
182 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
182 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
183 ## authentication token. Such view would be only accessible when used together
183 ## authentication token. Such view would be only accessible when used together
184 ## with this authentication token
184 ## with this authentication token
185 ##
185 ##
186 ## list of all views can be found under `/_admin/permissions/auth_token_access`
186 ## list of all views can be found under `/_admin/permissions/auth_token_access`
187 ## The list should be "," separated and on a single line.
187 ## The list should be "," separated and on a single line.
188 ##
188 ##
189 ## Most common views to enable:
189 ## Most common views to enable:
190 # RepoCommitsView:repo_commit_download
190 # RepoCommitsView:repo_commit_download
191 # RepoCommitsView:repo_commit_patch
191 # RepoCommitsView:repo_commit_patch
192 # RepoCommitsView:repo_commit_raw
192 # RepoCommitsView:repo_commit_raw
193 # RepoCommitsView:repo_commit_raw@TOKEN
193 # RepoCommitsView:repo_commit_raw@TOKEN
194 # RepoFilesView:repo_files_diff
194 # RepoFilesView:repo_files_diff
195 # RepoFilesView:repo_archivefile
195 # RepoFilesView:repo_archivefile
196 # RepoFilesView:repo_file_raw
196 # RepoFilesView:repo_file_raw
197 # GistView:*
197 # GistView:*
198 api_access_controllers_whitelist =
198 api_access_controllers_whitelist =
199
199
200 ## default encoding used to convert from and to unicode
200 ## default encoding used to convert from and to unicode
201 ## can be also a comma separated list of encoding in case of mixed encodings
201 ## can be also a comma separated list of encoding in case of mixed encodings
202 default_encoding = UTF-8
202 default_encoding = UTF-8
203
203
204 ## instance-id prefix
204 ## instance-id prefix
205 ## a prefix key for this instance used for cache invalidation when running
205 ## a prefix key for this instance used for cache invalidation when running
206 ## multiple instances of rhodecode, make sure it's globally unique for
206 ## multiple instances of rhodecode, make sure it's globally unique for
207 ## all running rhodecode instances. Leave empty if you don't use it
207 ## all running rhodecode instances. Leave empty if you don't use it
208 instance_id =
208 instance_id =
209
209
210 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
210 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
211 ## of an authentication plugin also if it is disabled by it's settings.
211 ## of an authentication plugin also if it is disabled by it's settings.
212 ## This could be useful if you are unable to log in to the system due to broken
212 ## This could be useful if you are unable to log in to the system due to broken
213 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
213 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
214 ## module to log in again and fix the settings.
214 ## module to log in again and fix the settings.
215 ##
215 ##
216 ## Available builtin plugin IDs (hash is part of the ID):
216 ## Available builtin plugin IDs (hash is part of the ID):
217 ## egg:rhodecode-enterprise-ce#rhodecode
217 ## egg:rhodecode-enterprise-ce#rhodecode
218 ## egg:rhodecode-enterprise-ce#pam
218 ## egg:rhodecode-enterprise-ce#pam
219 ## egg:rhodecode-enterprise-ce#ldap
219 ## egg:rhodecode-enterprise-ce#ldap
220 ## egg:rhodecode-enterprise-ce#jasig_cas
220 ## egg:rhodecode-enterprise-ce#jasig_cas
221 ## egg:rhodecode-enterprise-ce#headers
221 ## egg:rhodecode-enterprise-ce#headers
222 ## egg:rhodecode-enterprise-ce#crowd
222 ## egg:rhodecode-enterprise-ce#crowd
223 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
223 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
224
224
225 ## alternative return HTTP header for failed authentication. Default HTTP
225 ## alternative return HTTP header for failed authentication. Default HTTP
226 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
226 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
227 ## handling that causing a series of failed authentication calls.
227 ## handling that causing a series of failed authentication calls.
228 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
228 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
229 ## This will be served instead of default 401 on bad authnetication
229 ## This will be served instead of default 401 on bad authnetication
230 auth_ret_code =
230 auth_ret_code =
231
231
232 ## use special detection method when serving auth_ret_code, instead of serving
232 ## use special detection method when serving auth_ret_code, instead of serving
233 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
233 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
234 ## and then serve auth_ret_code to clients
234 ## and then serve auth_ret_code to clients
235 auth_ret_code_detection = false
235 auth_ret_code_detection = false
236
236
237 ## locking return code. When repository is locked return this HTTP code. 2XX
237 ## locking return code. When repository is locked return this HTTP code. 2XX
238 ## codes don't break the transactions while 4XX codes do
238 ## codes don't break the transactions while 4XX codes do
239 lock_ret_code = 423
239 lock_ret_code = 423
240
240
241 ## allows to change the repository location in settings page
241 ## allows to change the repository location in settings page
242 allow_repo_location_change = true
242 allow_repo_location_change = true
243
243
244 ## allows to setup custom hooks in settings page
244 ## allows to setup custom hooks in settings page
245 allow_custom_hooks_settings = true
245 allow_custom_hooks_settings = true
246
246
247 ## generated license token, goto license page in RhodeCode settings to obtain
247 ## generated license token, goto license page in RhodeCode settings to obtain
248 ## new token
248 ## new token
249 license_token =
249 license_token =
250
250
251 ## supervisor connection uri, for managing supervisor and logs.
251 ## supervisor connection uri, for managing supervisor and logs.
252 supervisor.uri =
252 supervisor.uri =
253 ## supervisord group name/id we only want this RC instance to handle
253 ## supervisord group name/id we only want this RC instance to handle
254 supervisor.group_id = prod
254 supervisor.group_id = prod
255
255
256 ## Display extended labs settings
256 ## Display extended labs settings
257 labs_settings_active = true
257 labs_settings_active = true
258
258
259 ####################################
259 ####################################
260 ### CELERY CONFIG ####
260 ### CELERY CONFIG ####
261 ####################################
261 ####################################
262 use_celery = false
262 use_celery = false
263 broker.host = localhost
263 broker.host = localhost
264 broker.vhost = rabbitmqhost
264 broker.vhost = rabbitmqhost
265 broker.port = 5672
265 broker.port = 5672
266 broker.user = rabbitmq
266 broker.user = rabbitmq
267 broker.password = qweqwe
267 broker.password = qweqwe
268
268
269 celery.imports = rhodecode.lib.celerylib.tasks
269 celery.imports = rhodecode.lib.celerylib.tasks
270
270
271 celery.result.backend = amqp
271 celery.result.backend = amqp
272 celery.result.dburi = amqp://
272 celery.result.dburi = amqp://
273 celery.result.serialier = json
273 celery.result.serialier = json
274
274
275 #celery.send.task.error.emails = true
275 #celery.send.task.error.emails = true
276 #celery.amqp.task.result.expires = 18000
276 #celery.amqp.task.result.expires = 18000
277
277
278 celeryd.concurrency = 2
278 celeryd.concurrency = 2
279 #celeryd.log.file = celeryd.log
279 #celeryd.log.file = celeryd.log
280 celeryd.log.level = debug
280 celeryd.log.level = debug
281 celeryd.max.tasks.per.child = 1
281 celeryd.max.tasks.per.child = 1
282
282
283 ## tasks will never be sent to the queue, but executed locally instead.
283 ## tasks will never be sent to the queue, but executed locally instead.
284 celery.always.eager = false
284 celery.always.eager = false
285
285
286 ####################################
286 ####################################
287 ### BEAKER CACHE ####
287 ### BEAKER CACHE ####
288 ####################################
288 ####################################
289 # default cache dir for templates. Putting this into a ramdisk
289 # default cache dir for templates. Putting this into a ramdisk
290 ## can boost performance, eg. %(here)s/data_ramdisk
290 ## can boost performance, eg. %(here)s/data_ramdisk
291 cache_dir = %(here)s/data
291 cache_dir = %(here)s/data
292
292
293 ## locking and default file storage for Beaker. Putting this into a ramdisk
293 ## locking and default file storage for Beaker. Putting this into a ramdisk
294 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
294 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
295 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
295 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
296 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
296 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
297
297
298 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
298 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
299
299
300 beaker.cache.super_short_term.type = memory
300 beaker.cache.super_short_term.type = memory
301 beaker.cache.super_short_term.expire = 10
301 beaker.cache.super_short_term.expire = 10
302 beaker.cache.super_short_term.key_length = 256
302 beaker.cache.super_short_term.key_length = 256
303
303
304 beaker.cache.short_term.type = memory
304 beaker.cache.short_term.type = memory
305 beaker.cache.short_term.expire = 60
305 beaker.cache.short_term.expire = 60
306 beaker.cache.short_term.key_length = 256
306 beaker.cache.short_term.key_length = 256
307
307
308 beaker.cache.long_term.type = memory
308 beaker.cache.long_term.type = memory
309 beaker.cache.long_term.expire = 36000
309 beaker.cache.long_term.expire = 36000
310 beaker.cache.long_term.key_length = 256
310 beaker.cache.long_term.key_length = 256
311
311
312 beaker.cache.sql_cache_short.type = memory
312 beaker.cache.sql_cache_short.type = memory
313 beaker.cache.sql_cache_short.expire = 10
313 beaker.cache.sql_cache_short.expire = 10
314 beaker.cache.sql_cache_short.key_length = 256
314 beaker.cache.sql_cache_short.key_length = 256
315
315
316 ## default is memory cache, configure only if required
316 ## default is memory cache, configure only if required
317 ## using multi-node or multi-worker setup
317 ## using multi-node or multi-worker setup
318 #beaker.cache.auth_plugins.type = ext:database
318 #beaker.cache.auth_plugins.type = ext:database
319 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
319 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
320 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
320 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
321 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
321 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
322 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
322 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
323 #beaker.cache.auth_plugins.sa.pool_size = 10
323 #beaker.cache.auth_plugins.sa.pool_size = 10
324 #beaker.cache.auth_plugins.sa.max_overflow = 0
324 #beaker.cache.auth_plugins.sa.max_overflow = 0
325
325
326 beaker.cache.repo_cache_long.type = memorylru_base
326 beaker.cache.repo_cache_long.type = memorylru_base
327 beaker.cache.repo_cache_long.max_items = 4096
327 beaker.cache.repo_cache_long.max_items = 4096
328 beaker.cache.repo_cache_long.expire = 2592000
328 beaker.cache.repo_cache_long.expire = 2592000
329
329
330 ## default is memorylru_base cache, configure only if required
330 ## default is memorylru_base cache, configure only if required
331 ## using multi-node or multi-worker setup
331 ## using multi-node or multi-worker setup
332 #beaker.cache.repo_cache_long.type = ext:memcached
332 #beaker.cache.repo_cache_long.type = ext:memcached
333 #beaker.cache.repo_cache_long.url = localhost:11211
333 #beaker.cache.repo_cache_long.url = localhost:11211
334 #beaker.cache.repo_cache_long.expire = 1209600
334 #beaker.cache.repo_cache_long.expire = 1209600
335 #beaker.cache.repo_cache_long.key_length = 256
335 #beaker.cache.repo_cache_long.key_length = 256
336
336
337 ####################################
337 ####################################
338 ### BEAKER SESSION ####
338 ### BEAKER SESSION ####
339 ####################################
339 ####################################
340
340
341 ## .session.type is type of storage options for the session, current allowed
341 ## .session.type is type of storage options for the session, current allowed
342 ## types are file, ext:memcached, ext:database, and memory (default).
342 ## types are file, ext:memcached, ext:database, and memory (default).
343 beaker.session.type = file
343 beaker.session.type = file
344 beaker.session.data_dir = %(here)s/data/sessions/data
344 beaker.session.data_dir = %(here)s/data/sessions/data
345
345
346 ## db based session, fast, and allows easy management over logged in users
346 ## db based session, fast, and allows easy management over logged in users
347 #beaker.session.type = ext:database
347 #beaker.session.type = ext:database
348 #beaker.session.table_name = db_session
348 #beaker.session.table_name = db_session
349 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
349 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
350 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
350 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
351 #beaker.session.sa.pool_recycle = 3600
351 #beaker.session.sa.pool_recycle = 3600
352 #beaker.session.sa.echo = false
352 #beaker.session.sa.echo = false
353
353
354 beaker.session.key = rhodecode
354 beaker.session.key = rhodecode
355 beaker.session.secret = production-rc-uytcxaz
355 beaker.session.secret = production-rc-uytcxaz
356 beaker.session.lock_dir = %(here)s/data/sessions/lock
356 beaker.session.lock_dir = %(here)s/data/sessions/lock
357
357
358 ## Secure encrypted cookie. Requires AES and AES python libraries
358 ## Secure encrypted cookie. Requires AES and AES python libraries
359 ## you must disable beaker.session.secret to use this
359 ## you must disable beaker.session.secret to use this
360 #beaker.session.encrypt_key = key_for_encryption
360 #beaker.session.encrypt_key = key_for_encryption
361 #beaker.session.validate_key = validation_key
361 #beaker.session.validate_key = validation_key
362
362
363 ## sets session as invalid(also logging out user) if it haven not been
363 ## sets session as invalid(also logging out user) if it haven not been
364 ## accessed for given amount of time in seconds
364 ## accessed for given amount of time in seconds
365 beaker.session.timeout = 2592000
365 beaker.session.timeout = 2592000
366 beaker.session.httponly = true
366 beaker.session.httponly = true
367 ## Path to use for the cookie. Set to prefix if you use prefix middleware
367 ## Path to use for the cookie. Set to prefix if you use prefix middleware
368 #beaker.session.cookie_path = /custom_prefix
368 #beaker.session.cookie_path = /custom_prefix
369
369
370 ## uncomment for https secure cookie
370 ## uncomment for https secure cookie
371 beaker.session.secure = false
371 beaker.session.secure = false
372
372
373 ## auto save the session to not to use .save()
373 ## auto save the session to not to use .save()
374 beaker.session.auto = false
374 beaker.session.auto = false
375
375
376 ## default cookie expiration time in seconds, set to `true` to set expire
376 ## default cookie expiration time in seconds, set to `true` to set expire
377 ## at browser close
377 ## at browser close
378 #beaker.session.cookie_expires = 3600
378 #beaker.session.cookie_expires = 3600
379
379
380 ###################################
380 ###################################
381 ## SEARCH INDEXING CONFIGURATION ##
381 ## SEARCH INDEXING CONFIGURATION ##
382 ###################################
382 ###################################
383 ## Full text search indexer is available in rhodecode-tools under
383 ## Full text search indexer is available in rhodecode-tools under
384 ## `rhodecode-tools index` command
384 ## `rhodecode-tools index` command
385
385
386 ## WHOOSH Backend, doesn't require additional services to run
386 ## WHOOSH Backend, doesn't require additional services to run
387 ## it works good with few dozen repos
387 ## it works good with few dozen repos
388 search.module = rhodecode.lib.index.whoosh
388 search.module = rhodecode.lib.index.whoosh
389 search.location = %(here)s/data/index
389 search.location = %(here)s/data/index
390
390
391 ########################################
391 ########################################
392 ### CHANNELSTREAM CONFIG ####
392 ### CHANNELSTREAM CONFIG ####
393 ########################################
393 ########################################
394 ## channelstream enables persistent connections and live notification
394 ## channelstream enables persistent connections and live notification
395 ## in the system. It's also used by the chat system
395 ## in the system. It's also used by the chat system
396 channelstream.enabled = false
396 channelstream.enabled = false
397
397
398 ## server address for channelstream server on the backend
398 ## server address for channelstream server on the backend
399 channelstream.server = 127.0.0.1:9800
399 channelstream.server = 127.0.0.1:9800
400
400
401 ## location of the channelstream server from outside world
401 ## location of the channelstream server from outside world
402 ## use ws:// for http or wss:// for https. This address needs to be handled
402 ## use ws:// for http or wss:// for https. This address needs to be handled
403 ## by external HTTP server such as Nginx or Apache
403 ## by external HTTP server such as Nginx or Apache
404 ## see nginx/apache configuration examples in our docs
404 ## see nginx/apache configuration examples in our docs
405 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
405 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
406 channelstream.secret = secret
406 channelstream.secret = secret
407 channelstream.history.location = %(here)s/channelstream_history
407 channelstream.history.location = %(here)s/channelstream_history
408
408
409 ## Internal application path that Javascript uses to connect into.
409 ## Internal application path that Javascript uses to connect into.
410 ## If you use proxy-prefix the prefix should be added before /_channelstream
410 ## If you use proxy-prefix the prefix should be added before /_channelstream
411 channelstream.proxy_path = /_channelstream
411 channelstream.proxy_path = /_channelstream
412
412
413
413
414 ###################################
414 ###################################
415 ## APPENLIGHT CONFIG ##
415 ## APPENLIGHT CONFIG ##
416 ###################################
416 ###################################
417
417
418 ## Appenlight is tailored to work with RhodeCode, see
418 ## Appenlight is tailored to work with RhodeCode, see
419 ## http://appenlight.com for details how to obtain an account
419 ## http://appenlight.com for details how to obtain an account
420
420
421 ## appenlight integration enabled
421 ## appenlight integration enabled
422 appenlight = false
422 appenlight = false
423
423
424 appenlight.server_url = https://api.appenlight.com
424 appenlight.server_url = https://api.appenlight.com
425 appenlight.api_key = YOUR_API_KEY
425 appenlight.api_key = YOUR_API_KEY
426 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
426 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
427
427
428 # used for JS client
428 # used for JS client
429 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
429 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
430
430
431 ## TWEAK AMOUNT OF INFO SENT HERE
431 ## TWEAK AMOUNT OF INFO SENT HERE
432
432
433 ## enables 404 error logging (default False)
433 ## enables 404 error logging (default False)
434 appenlight.report_404 = false
434 appenlight.report_404 = false
435
435
436 ## time in seconds after request is considered being slow (default 1)
436 ## time in seconds after request is considered being slow (default 1)
437 appenlight.slow_request_time = 1
437 appenlight.slow_request_time = 1
438
438
439 ## record slow requests in application
439 ## record slow requests in application
440 ## (needs to be enabled for slow datastore recording and time tracking)
440 ## (needs to be enabled for slow datastore recording and time tracking)
441 appenlight.slow_requests = true
441 appenlight.slow_requests = true
442
442
443 ## enable hooking to application loggers
443 ## enable hooking to application loggers
444 appenlight.logging = true
444 appenlight.logging = true
445
445
446 ## minimum log level for log capture
446 ## minimum log level for log capture
447 appenlight.logging.level = WARNING
447 appenlight.logging.level = WARNING
448
448
449 ## send logs only from erroneous/slow requests
449 ## send logs only from erroneous/slow requests
450 ## (saves API quota for intensive logging)
450 ## (saves API quota for intensive logging)
451 appenlight.logging_on_error = false
451 appenlight.logging_on_error = false
452
452
453 ## list of additonal keywords that should be grabbed from environ object
453 ## list of additonal keywords that should be grabbed from environ object
454 ## can be string with comma separated list of words in lowercase
454 ## can be string with comma separated list of words in lowercase
455 ## (by default client will always send following info:
455 ## (by default client will always send following info:
456 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
456 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
457 ## start with HTTP* this list be extended with additional keywords here
457 ## start with HTTP* this list be extended with additional keywords here
458 appenlight.environ_keys_whitelist =
458 appenlight.environ_keys_whitelist =
459
459
460 ## list of keywords that should be blanked from request object
460 ## list of keywords that should be blanked from request object
461 ## can be string with comma separated list of words in lowercase
461 ## can be string with comma separated list of words in lowercase
462 ## (by default client will always blank keys that contain following words
462 ## (by default client will always blank keys that contain following words
463 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
463 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
464 ## this list be extended with additional keywords set here
464 ## this list be extended with additional keywords set here
465 appenlight.request_keys_blacklist =
465 appenlight.request_keys_blacklist =
466
466
467 ## list of namespaces that should be ignores when gathering log entries
467 ## list of namespaces that should be ignores when gathering log entries
468 ## can be string with comma separated list of namespaces
468 ## can be string with comma separated list of namespaces
469 ## (by default the client ignores own entries: appenlight_client.client)
469 ## (by default the client ignores own entries: appenlight_client.client)
470 appenlight.log_namespace_blacklist =
470 appenlight.log_namespace_blacklist =
471
471
472
472
473 ################################################################################
473 ################################################################################
474 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
474 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
475 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
475 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
476 ## execute malicious code after an exception is raised. ##
476 ## execute malicious code after an exception is raised. ##
477 ################################################################################
477 ################################################################################
478 set debug = false
478 set debug = false
479
479
480
480
481 ###########################################
481 ###########################################
482 ### MAIN RHODECODE DATABASE CONFIG ###
482 ### MAIN RHODECODE DATABASE CONFIG ###
483 ###########################################
483 ###########################################
484 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
484 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
485 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
485 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
486 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
486 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
487 sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
487 sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
488
488
489 # see sqlalchemy docs for other advanced settings
489 # see sqlalchemy docs for other advanced settings
490
490
491 ## print the sql statements to output
491 ## print the sql statements to output
492 sqlalchemy.db1.echo = false
492 sqlalchemy.db1.echo = false
493 ## recycle the connections after this amount of seconds
493 ## recycle the connections after this amount of seconds
494 sqlalchemy.db1.pool_recycle = 3600
494 sqlalchemy.db1.pool_recycle = 3600
495 sqlalchemy.db1.convert_unicode = true
495 sqlalchemy.db1.convert_unicode = true
496
496
497 ## the number of connections to keep open inside the connection pool.
497 ## the number of connections to keep open inside the connection pool.
498 ## 0 indicates no limit
498 ## 0 indicates no limit
499 #sqlalchemy.db1.pool_size = 5
499 #sqlalchemy.db1.pool_size = 5
500
500
501 ## the number of connections to allow in connection pool "overflow", that is
501 ## the number of connections to allow in connection pool "overflow", that is
502 ## connections that can be opened above and beyond the pool_size setting,
502 ## connections that can be opened above and beyond the pool_size setting,
503 ## which defaults to five.
503 ## which defaults to five.
504 #sqlalchemy.db1.max_overflow = 10
504 #sqlalchemy.db1.max_overflow = 10
505
505
506
506
507 ##################
507 ##################
508 ### VCS CONFIG ###
508 ### VCS CONFIG ###
509 ##################
509 ##################
510 vcs.server.enable = true
510 vcs.server.enable = true
511 vcs.server = localhost:9900
511 vcs.server = localhost:9900
512
512
513 ## Web server connectivity protocol, responsible for web based VCS operatations
513 ## Web server connectivity protocol, responsible for web based VCS operatations
514 ## Available protocols are:
514 ## Available protocols are:
515 ## `http` - use http-rpc backend (default)
515 ## `http` - use http-rpc backend (default)
516 vcs.server.protocol = http
516 vcs.server.protocol = http
517
517
518 ## Push/Pull operations protocol, available options are:
518 ## Push/Pull operations protocol, available options are:
519 ## `http` - use http-rpc backend (default)
519 ## `http` - use http-rpc backend (default)
520 ##
520 ##
521 vcs.scm_app_implementation = http
521 vcs.scm_app_implementation = http
522
522
523 ## Push/Pull operations hooks protocol, available options are:
523 ## Push/Pull operations hooks protocol, available options are:
524 ## `http` - use http-rpc backend (default)
524 ## `http` - use http-rpc backend (default)
525 vcs.hooks.protocol = http
525 vcs.hooks.protocol = http
526
526
527 vcs.server.log_level = info
527 vcs.server.log_level = info
528 ## Start VCSServer with this instance as a subprocess, usefull for development
528 ## Start VCSServer with this instance as a subprocess, usefull for development
529 vcs.start_server = false
529 vcs.start_server = false
530
530
531 ## List of enabled VCS backends, available options are:
531 ## List of enabled VCS backends, available options are:
532 ## `hg` - mercurial
532 ## `hg` - mercurial
533 ## `git` - git
533 ## `git` - git
534 ## `svn` - subversion
534 ## `svn` - subversion
535 vcs.backends = hg, git, svn
535 vcs.backends = hg, git, svn
536
536
537 vcs.connection_timeout = 3600
537 vcs.connection_timeout = 3600
538 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
538 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
539 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
539 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
540 #vcs.svn.compatible_version = pre-1.8-compatible
540 #vcs.svn.compatible_version = pre-1.8-compatible
541
541
542
542
543 ############################################################
543 ############################################################
544 ### Subversion proxy support (mod_dav_svn) ###
544 ### Subversion proxy support (mod_dav_svn) ###
545 ### Maps RhodeCode repo groups into SVN paths for Apache ###
545 ### Maps RhodeCode repo groups into SVN paths for Apache ###
546 ############################################################
546 ############################################################
547 ## Enable or disable the config file generation.
547 ## Enable or disable the config file generation.
548 svn.proxy.generate_config = false
548 svn.proxy.generate_config = false
549 ## Generate config file with `SVNListParentPath` set to `On`.
549 ## Generate config file with `SVNListParentPath` set to `On`.
550 svn.proxy.list_parent_path = true
550 svn.proxy.list_parent_path = true
551 ## Set location and file name of generated config file.
551 ## Set location and file name of generated config file.
552 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
552 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
553 ## Used as a prefix to the `Location` block in the generated config file.
553 ## Used as a prefix to the `Location` block in the generated config file.
554 ## In most cases it should be set to `/`.
554 ## In most cases it should be set to `/`.
555 svn.proxy.location_root = /
555 svn.proxy.location_root = /
556 ## Command to reload the mod dav svn configuration on change.
556 ## Command to reload the mod dav svn configuration on change.
557 ## Example: `/etc/init.d/apache2 reload`
557 ## Example: `/etc/init.d/apache2 reload`
558 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
558 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
559 ## If the timeout expires before the reload command finishes, the command will
559 ## If the timeout expires before the reload command finishes, the command will
560 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
560 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
561 #svn.proxy.reload_timeout = 10
561 #svn.proxy.reload_timeout = 10
562
562
563 ############################################################
563 ############################################################
564 ### SSH Support Settings ###
564 ### SSH Support Settings ###
565 ############################################################
565 ############################################################
566
566
567 ## Defines if the authorized_keys file should be written on any change of
567 ## Defines if the authorized_keys file should be written on any change of
568 ## user ssh keys
568 ## user ssh keys
569 ssh.generate_authorized_keyfile = false
569 ssh.generate_authorized_keyfile = false
570
570
571 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
571 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
572 # ssh.authorized_keys_ssh_opts =
572 # ssh.authorized_keys_ssh_opts =
573
573
574 ## File to generate the authorized keys together with options
574 ## File to generate the authorized keys together with options
575 ssh.authorized_keys_file_path = /home/USER/.ssh/authorized_keys
575 ## It is possible to have multiple key files specified in `sshd_config` e.g.
576 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
577 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
578
579 ## Command to execute the SSH wrapper. The binary is available in the
580 ## rhodecode installation directory.
581 ## e.g ~/.rccontrol/community-1/profile/bin/rcssh-wrapper
582 ssh.wrapper_cmd = ~/.rccontrol/community-1/rcssh-wrapper
583
584 ## Allow shell when executing the ssh-wrapper command
585 ssh.wrapper_cmd_allow_shell = false
576
586
577 ## Command to execute as an SSH wrapper, available from
587 ## Enables logging, and detailed output send back to the client. Usefull for
578 ## https://code.rhodecode.com/rhodecode-ssh
588 ## debugging, shouldn't be used in production.
579 ssh.wrapper_cmd = /home/USER/rhodecode-ssh/sshwrapper.py
589 ssh.enable_debug_logging = false
590
591 ## API KEY for user who has access to fetch other user permission information
592 ## most likely an super-admin account with some IP restrictions.
593 ssh.api_key =
580
594
581 ## Allow shell when executing the command
595 ## API Host, the server address of RhodeCode instance that the api_key will
582 ssh.wrapper_cmd_allow_shell = false
596 ## access
597 ssh.api_host = http://localhost
598
599 ## Paths to binary executrables, by default they are the names, but we can
600 ## override them if we want to use a custom one
601 ssh.executable.hg = ~/.rccontrol/vcsserver-1/profile/bin/hg
602 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
603 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
604
583
605
584 ## Dummy marker to add new entries after.
606 ## Dummy marker to add new entries after.
585 ## Add any custom entries below. Please don't remove.
607 ## Add any custom entries below. Please don't remove.
586 custom.conf = 1
608 custom.conf = 1
587
609
588
610
589 ################################
611 ################################
590 ### LOGGING CONFIGURATION ####
612 ### LOGGING CONFIGURATION ####
591 ################################
613 ################################
592 [loggers]
614 [loggers]
593 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
615 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, ssh_wrapper
594
616
595 [handlers]
617 [handlers]
596 keys = console, console_sql
618 keys = console, console_sql
597
619
598 [formatters]
620 [formatters]
599 keys = generic, color_formatter, color_formatter_sql
621 keys = generic, color_formatter, color_formatter_sql
600
622
601 #############
623 #############
602 ## LOGGERS ##
624 ## LOGGERS ##
603 #############
625 #############
604 [logger_root]
626 [logger_root]
605 level = NOTSET
627 level = NOTSET
606 handlers = console
628 handlers = console
607
629
608 [logger_routes]
630 [logger_routes]
609 level = DEBUG
631 level = DEBUG
610 handlers =
632 handlers =
611 qualname = routes.middleware
633 qualname = routes.middleware
612 ## "level = DEBUG" logs the route matched and routing variables.
634 ## "level = DEBUG" logs the route matched and routing variables.
613 propagate = 1
635 propagate = 1
614
636
615 [logger_beaker]
637 [logger_beaker]
616 level = DEBUG
638 level = DEBUG
617 handlers =
639 handlers =
618 qualname = beaker.container
640 qualname = beaker.container
619 propagate = 1
641 propagate = 1
620
642
621 [logger_templates]
643 [logger_templates]
622 level = INFO
644 level = INFO
623 handlers =
645 handlers =
624 qualname = pylons.templating
646 qualname = pylons.templating
625 propagate = 1
647 propagate = 1
626
648
627 [logger_rhodecode]
649 [logger_rhodecode]
628 level = DEBUG
650 level = DEBUG
629 handlers =
651 handlers =
630 qualname = rhodecode
652 qualname = rhodecode
631 propagate = 1
653 propagate = 1
632
654
633 [logger_sqlalchemy]
655 [logger_sqlalchemy]
634 level = INFO
656 level = INFO
635 handlers = console_sql
657 handlers = console_sql
636 qualname = sqlalchemy.engine
658 qualname = sqlalchemy.engine
637 propagate = 0
659 propagate = 0
638
660
661 [logger_ssh_wrapper]
662 level = DEBUG
663 handlers =
664 qualname = ssh_wrapper
665 propagate = 1
666
667
639 ##############
668 ##############
640 ## HANDLERS ##
669 ## HANDLERS ##
641 ##############
670 ##############
642
671
643 [handler_console]
672 [handler_console]
644 class = StreamHandler
673 class = StreamHandler
645 args = (sys.stderr, )
674 args = (sys.stderr, )
646 level = INFO
675 level = INFO
647 formatter = generic
676 formatter = generic
648
677
649 [handler_console_sql]
678 [handler_console_sql]
650 class = StreamHandler
679 class = StreamHandler
651 args = (sys.stderr, )
680 args = (sys.stderr, )
652 level = WARN
681 level = WARN
653 formatter = generic
682 formatter = generic
654
683
655 ################
684 ################
656 ## FORMATTERS ##
685 ## FORMATTERS ##
657 ################
686 ################
658
687
659 [formatter_generic]
688 [formatter_generic]
660 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
689 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
661 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
690 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
662 datefmt = %Y-%m-%d %H:%M:%S
691 datefmt = %Y-%m-%d %H:%M:%S
663
692
664 [formatter_color_formatter]
693 [formatter_color_formatter]
665 class = rhodecode.lib.logging_formatter.ColorFormatter
694 class = rhodecode.lib.logging_formatter.ColorFormatter
666 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
695 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
667 datefmt = %Y-%m-%d %H:%M:%S
696 datefmt = %Y-%m-%d %H:%M:%S
668
697
669 [formatter_color_formatter_sql]
698 [formatter_color_formatter_sql]
670 class = rhodecode.lib.logging_formatter.ColorFormatterSql
699 class = rhodecode.lib.logging_formatter.ColorFormatterSql
671 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
700 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
672 datefmt = %Y-%m-%d %H:%M:%S
701 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,321 +1,351 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
3 # Copyright (C) 2011-2017 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 import inspect
21 import inspect
22 import logging
22 import logging
23 import itertools
23 import itertools
24
24
25 from rhodecode.api import (
25 from rhodecode.api import (
26 jsonrpc_method, JSONRPCError, JSONRPCForbidden, find_methods)
26 jsonrpc_method, JSONRPCError, JSONRPCForbidden, find_methods)
27
27
28 from rhodecode.api.utils import (
28 from rhodecode.api.utils import (
29 Optional, OAttr, has_superadmin_permission, get_user_or_error)
29 Optional, OAttr, has_superadmin_permission, get_user_or_error)
30 from rhodecode.lib.utils import repo2db_mapper
30 from rhodecode.lib.utils import repo2db_mapper
31 from rhodecode.lib import system_info
31 from rhodecode.lib import system_info
32 from rhodecode.lib import user_sessions
32 from rhodecode.lib import user_sessions
33 from rhodecode.lib.utils2 import safe_int
33 from rhodecode.lib.utils2 import safe_int
34 from rhodecode.model.db import UserIpMap
34 from rhodecode.model.db import UserIpMap
35 from rhodecode.model.scm import ScmModel
35 from rhodecode.model.scm import ScmModel
36 from rhodecode.model.settings import VcsSettingsModel
36
37
37 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
38
39
39
40
40 @jsonrpc_method()
41 @jsonrpc_method()
41 def get_server_info(request, apiuser):
42 def get_server_info(request, apiuser):
42 """
43 """
43 Returns the |RCE| server information.
44 Returns the |RCE| server information.
44
45
45 This includes the running version of |RCE| and all installed
46 This includes the running version of |RCE| and all installed
46 packages. This command takes the following options:
47 packages. This command takes the following options:
47
48
48 :param apiuser: This is filled automatically from the |authtoken|.
49 :param apiuser: This is filled automatically from the |authtoken|.
49 :type apiuser: AuthUser
50 :type apiuser: AuthUser
50
51
51 Example output:
52 Example output:
52
53
53 .. code-block:: bash
54 .. code-block:: bash
54
55
55 id : <id_given_in_input>
56 id : <id_given_in_input>
56 result : {
57 result : {
57 'modules': [<module name>,...]
58 'modules': [<module name>,...]
58 'py_version': <python version>,
59 'py_version': <python version>,
59 'platform': <platform type>,
60 'platform': <platform type>,
60 'rhodecode_version': <rhodecode version>
61 'rhodecode_version': <rhodecode version>
61 }
62 }
62 error : null
63 error : null
63 """
64 """
64
65
65 if not has_superadmin_permission(apiuser):
66 if not has_superadmin_permission(apiuser):
66 raise JSONRPCForbidden()
67 raise JSONRPCForbidden()
67
68
68 server_info = ScmModel().get_server_info(request.environ)
69 server_info = ScmModel().get_server_info(request.environ)
69 # rhodecode-index requires those
70 # rhodecode-index requires those
70
71
71 server_info['index_storage'] = server_info['search']['value']['location']
72 server_info['index_storage'] = server_info['search']['value']['location']
72 server_info['storage'] = server_info['storage']['value']['path']
73 server_info['storage'] = server_info['storage']['value']['path']
73
74
74 return server_info
75 return server_info
75
76
76
77
77 @jsonrpc_method()
78 @jsonrpc_method()
79 def get_repo_store(request, apiuser):
80 """
81 Returns the |RCE| repository storage information.
82
83 :param apiuser: This is filled automatically from the |authtoken|.
84 :type apiuser: AuthUser
85
86 Example output:
87
88 .. code-block:: bash
89
90 id : <id_given_in_input>
91 result : {
92 'modules': [<module name>,...]
93 'py_version': <python version>,
94 'platform': <platform type>,
95 'rhodecode_version': <rhodecode version>
96 }
97 error : null
98 """
99
100 if not has_superadmin_permission(apiuser):
101 raise JSONRPCForbidden()
102
103 path = VcsSettingsModel().get_repos_location()
104 return {"path": path}
105
106
107 @jsonrpc_method()
78 def get_ip(request, apiuser, userid=Optional(OAttr('apiuser'))):
108 def get_ip(request, apiuser, userid=Optional(OAttr('apiuser'))):
79 """
109 """
80 Displays the IP Address as seen from the |RCE| server.
110 Displays the IP Address as seen from the |RCE| server.
81
111
82 * This command displays the IP Address, as well as all the defined IP
112 * This command displays the IP Address, as well as all the defined IP
83 addresses for the specified user. If the ``userid`` is not set, the
113 addresses for the specified user. If the ``userid`` is not set, the
84 data returned is for the user calling the method.
114 data returned is for the user calling the method.
85
115
86 This command can only be run using an |authtoken| with admin rights to
116 This command can only be run using an |authtoken| with admin rights to
87 the specified repository.
117 the specified repository.
88
118
89 This command takes the following options:
119 This command takes the following options:
90
120
91 :param apiuser: This is filled automatically from |authtoken|.
121 :param apiuser: This is filled automatically from |authtoken|.
92 :type apiuser: AuthUser
122 :type apiuser: AuthUser
93 :param userid: Sets the userid for which associated IP Address data
123 :param userid: Sets the userid for which associated IP Address data
94 is returned.
124 is returned.
95 :type userid: Optional(str or int)
125 :type userid: Optional(str or int)
96
126
97 Example output:
127 Example output:
98
128
99 .. code-block:: bash
129 .. code-block:: bash
100
130
101 id : <id_given_in_input>
131 id : <id_given_in_input>
102 result : {
132 result : {
103 "server_ip_addr": "<ip_from_clien>",
133 "server_ip_addr": "<ip_from_clien>",
104 "user_ips": [
134 "user_ips": [
105 {
135 {
106 "ip_addr": "<ip_with_mask>",
136 "ip_addr": "<ip_with_mask>",
107 "ip_range": ["<start_ip>", "<end_ip>"],
137 "ip_range": ["<start_ip>", "<end_ip>"],
108 },
138 },
109 ...
139 ...
110 ]
140 ]
111 }
141 }
112
142
113 """
143 """
114 if not has_superadmin_permission(apiuser):
144 if not has_superadmin_permission(apiuser):
115 raise JSONRPCForbidden()
145 raise JSONRPCForbidden()
116
146
117 userid = Optional.extract(userid, evaluate_locals=locals())
147 userid = Optional.extract(userid, evaluate_locals=locals())
118 userid = getattr(userid, 'user_id', userid)
148 userid = getattr(userid, 'user_id', userid)
119
149
120 user = get_user_or_error(userid)
150 user = get_user_or_error(userid)
121 ips = UserIpMap.query().filter(UserIpMap.user == user).all()
151 ips = UserIpMap.query().filter(UserIpMap.user == user).all()
122 return {
152 return {
123 'server_ip_addr': request.rpc_ip_addr,
153 'server_ip_addr': request.rpc_ip_addr,
124 'user_ips': ips
154 'user_ips': ips
125 }
155 }
126
156
127
157
128 @jsonrpc_method()
158 @jsonrpc_method()
129 def rescan_repos(request, apiuser, remove_obsolete=Optional(False)):
159 def rescan_repos(request, apiuser, remove_obsolete=Optional(False)):
130 """
160 """
131 Triggers a rescan of the specified repositories.
161 Triggers a rescan of the specified repositories.
132
162
133 * If the ``remove_obsolete`` option is set, it also deletes repositories
163 * If the ``remove_obsolete`` option is set, it also deletes repositories
134 that are found in the database but not on the file system, so called
164 that are found in the database but not on the file system, so called
135 "clean zombies".
165 "clean zombies".
136
166
137 This command can only be run using an |authtoken| with admin rights to
167 This command can only be run using an |authtoken| with admin rights to
138 the specified repository.
168 the specified repository.
139
169
140 This command takes the following options:
170 This command takes the following options:
141
171
142 :param apiuser: This is filled automatically from the |authtoken|.
172 :param apiuser: This is filled automatically from the |authtoken|.
143 :type apiuser: AuthUser
173 :type apiuser: AuthUser
144 :param remove_obsolete: Deletes repositories from the database that
174 :param remove_obsolete: Deletes repositories from the database that
145 are not found on the filesystem.
175 are not found on the filesystem.
146 :type remove_obsolete: Optional(``True`` | ``False``)
176 :type remove_obsolete: Optional(``True`` | ``False``)
147
177
148 Example output:
178 Example output:
149
179
150 .. code-block:: bash
180 .. code-block:: bash
151
181
152 id : <id_given_in_input>
182 id : <id_given_in_input>
153 result : {
183 result : {
154 'added': [<added repository name>,...]
184 'added': [<added repository name>,...]
155 'removed': [<removed repository name>,...]
185 'removed': [<removed repository name>,...]
156 }
186 }
157 error : null
187 error : null
158
188
159 Example error output:
189 Example error output:
160
190
161 .. code-block:: bash
191 .. code-block:: bash
162
192
163 id : <id_given_in_input>
193 id : <id_given_in_input>
164 result : null
194 result : null
165 error : {
195 error : {
166 'Error occurred during rescan repositories action'
196 'Error occurred during rescan repositories action'
167 }
197 }
168
198
169 """
199 """
170 if not has_superadmin_permission(apiuser):
200 if not has_superadmin_permission(apiuser):
171 raise JSONRPCForbidden()
201 raise JSONRPCForbidden()
172
202
173 try:
203 try:
174 rm_obsolete = Optional.extract(remove_obsolete)
204 rm_obsolete = Optional.extract(remove_obsolete)
175 added, removed = repo2db_mapper(ScmModel().repo_scan(),
205 added, removed = repo2db_mapper(ScmModel().repo_scan(),
176 remove_obsolete=rm_obsolete)
206 remove_obsolete=rm_obsolete)
177 return {'added': added, 'removed': removed}
207 return {'added': added, 'removed': removed}
178 except Exception:
208 except Exception:
179 log.exception('Failed to run repo rescann')
209 log.exception('Failed to run repo rescann')
180 raise JSONRPCError(
210 raise JSONRPCError(
181 'Error occurred during rescan repositories action'
211 'Error occurred during rescan repositories action'
182 )
212 )
183
213
184
214
185 @jsonrpc_method()
215 @jsonrpc_method()
186 def cleanup_sessions(request, apiuser, older_then=Optional(60)):
216 def cleanup_sessions(request, apiuser, older_then=Optional(60)):
187 """
217 """
188 Triggers a session cleanup action.
218 Triggers a session cleanup action.
189
219
190 If the ``older_then`` option is set, only sessions that hasn't been
220 If the ``older_then`` option is set, only sessions that hasn't been
191 accessed in the given number of days will be removed.
221 accessed in the given number of days will be removed.
192
222
193 This command can only be run using an |authtoken| with admin rights to
223 This command can only be run using an |authtoken| with admin rights to
194 the specified repository.
224 the specified repository.
195
225
196 This command takes the following options:
226 This command takes the following options:
197
227
198 :param apiuser: This is filled automatically from the |authtoken|.
228 :param apiuser: This is filled automatically from the |authtoken|.
199 :type apiuser: AuthUser
229 :type apiuser: AuthUser
200 :param older_then: Deletes session that hasn't been accessed
230 :param older_then: Deletes session that hasn't been accessed
201 in given number of days.
231 in given number of days.
202 :type older_then: Optional(int)
232 :type older_then: Optional(int)
203
233
204 Example output:
234 Example output:
205
235
206 .. code-block:: bash
236 .. code-block:: bash
207
237
208 id : <id_given_in_input>
238 id : <id_given_in_input>
209 result: {
239 result: {
210 "backend": "<type of backend>",
240 "backend": "<type of backend>",
211 "sessions_removed": <number_of_removed_sessions>
241 "sessions_removed": <number_of_removed_sessions>
212 }
242 }
213 error : null
243 error : null
214
244
215 Example error output:
245 Example error output:
216
246
217 .. code-block:: bash
247 .. code-block:: bash
218
248
219 id : <id_given_in_input>
249 id : <id_given_in_input>
220 result : null
250 result : null
221 error : {
251 error : {
222 'Error occurred during session cleanup'
252 'Error occurred during session cleanup'
223 }
253 }
224
254
225 """
255 """
226 if not has_superadmin_permission(apiuser):
256 if not has_superadmin_permission(apiuser):
227 raise JSONRPCForbidden()
257 raise JSONRPCForbidden()
228
258
229 older_then = safe_int(Optional.extract(older_then)) or 60
259 older_then = safe_int(Optional.extract(older_then)) or 60
230 older_than_seconds = 60 * 60 * 24 * older_then
260 older_than_seconds = 60 * 60 * 24 * older_then
231
261
232 config = system_info.rhodecode_config().get_value()['value']['config']
262 config = system_info.rhodecode_config().get_value()['value']['config']
233 session_model = user_sessions.get_session_handler(
263 session_model = user_sessions.get_session_handler(
234 config.get('beaker.session.type', 'memory'))(config)
264 config.get('beaker.session.type', 'memory'))(config)
235
265
236 backend = session_model.SESSION_TYPE
266 backend = session_model.SESSION_TYPE
237 try:
267 try:
238 cleaned = session_model.clean_sessions(
268 cleaned = session_model.clean_sessions(
239 older_than_seconds=older_than_seconds)
269 older_than_seconds=older_than_seconds)
240 return {'sessions_removed': cleaned, 'backend': backend}
270 return {'sessions_removed': cleaned, 'backend': backend}
241 except user_sessions.CleanupCommand as msg:
271 except user_sessions.CleanupCommand as msg:
242 return {'cleanup_command': msg.message, 'backend': backend}
272 return {'cleanup_command': msg.message, 'backend': backend}
243 except Exception as e:
273 except Exception as e:
244 log.exception('Failed session cleanup')
274 log.exception('Failed session cleanup')
245 raise JSONRPCError(
275 raise JSONRPCError(
246 'Error occurred during session cleanup'
276 'Error occurred during session cleanup'
247 )
277 )
248
278
249
279
250 @jsonrpc_method()
280 @jsonrpc_method()
251 def get_method(request, apiuser, pattern=Optional('*')):
281 def get_method(request, apiuser, pattern=Optional('*')):
252 """
282 """
253 Returns list of all available API methods. By default match pattern
283 Returns list of all available API methods. By default match pattern
254 os "*" but any other pattern can be specified. eg *comment* will return
284 os "*" but any other pattern can be specified. eg *comment* will return
255 all methods with comment inside them. If just single method is matched
285 all methods with comment inside them. If just single method is matched
256 returned data will also include method specification
286 returned data will also include method specification
257
287
258 This command can only be run using an |authtoken| with admin rights to
288 This command can only be run using an |authtoken| with admin rights to
259 the specified repository.
289 the specified repository.
260
290
261 This command takes the following options:
291 This command takes the following options:
262
292
263 :param apiuser: This is filled automatically from the |authtoken|.
293 :param apiuser: This is filled automatically from the |authtoken|.
264 :type apiuser: AuthUser
294 :type apiuser: AuthUser
265 :param pattern: pattern to match method names against
295 :param pattern: pattern to match method names against
266 :type older_then: Optional("*")
296 :type older_then: Optional("*")
267
297
268 Example output:
298 Example output:
269
299
270 .. code-block:: bash
300 .. code-block:: bash
271
301
272 id : <id_given_in_input>
302 id : <id_given_in_input>
273 "result": [
303 "result": [
274 "changeset_comment",
304 "changeset_comment",
275 "comment_pull_request",
305 "comment_pull_request",
276 "comment_commit"
306 "comment_commit"
277 ]
307 ]
278 error : null
308 error : null
279
309
280 .. code-block:: bash
310 .. code-block:: bash
281
311
282 id : <id_given_in_input>
312 id : <id_given_in_input>
283 "result": [
313 "result": [
284 "comment_commit",
314 "comment_commit",
285 {
315 {
286 "apiuser": "<RequiredType>",
316 "apiuser": "<RequiredType>",
287 "comment_type": "<Optional:u'note'>",
317 "comment_type": "<Optional:u'note'>",
288 "commit_id": "<RequiredType>",
318 "commit_id": "<RequiredType>",
289 "message": "<RequiredType>",
319 "message": "<RequiredType>",
290 "repoid": "<RequiredType>",
320 "repoid": "<RequiredType>",
291 "request": "<RequiredType>",
321 "request": "<RequiredType>",
292 "resolves_comment_id": "<Optional:None>",
322 "resolves_comment_id": "<Optional:None>",
293 "status": "<Optional:None>",
323 "status": "<Optional:None>",
294 "userid": "<Optional:<OptionalAttr:apiuser>>"
324 "userid": "<Optional:<OptionalAttr:apiuser>>"
295 }
325 }
296 ]
326 ]
297 error : null
327 error : null
298 """
328 """
299 if not has_superadmin_permission(apiuser):
329 if not has_superadmin_permission(apiuser):
300 raise JSONRPCForbidden()
330 raise JSONRPCForbidden()
301
331
302 pattern = Optional.extract(pattern)
332 pattern = Optional.extract(pattern)
303
333
304 matches = find_methods(request.registry.jsonrpc_methods, pattern)
334 matches = find_methods(request.registry.jsonrpc_methods, pattern)
305
335
306 args_desc = []
336 args_desc = []
307 if len(matches) == 1:
337 if len(matches) == 1:
308 func = matches[matches.keys()[0]]
338 func = matches[matches.keys()[0]]
309
339
310 argspec = inspect.getargspec(func)
340 argspec = inspect.getargspec(func)
311 arglist = argspec[0]
341 arglist = argspec[0]
312 defaults = map(repr, argspec[3] or [])
342 defaults = map(repr, argspec[3] or [])
313
343
314 default_empty = '<RequiredType>'
344 default_empty = '<RequiredType>'
315
345
316 # kw arguments required by this method
346 # kw arguments required by this method
317 func_kwargs = dict(itertools.izip_longest(
347 func_kwargs = dict(itertools.izip_longest(
318 reversed(arglist), reversed(defaults), fillvalue=default_empty))
348 reversed(arglist), reversed(defaults), fillvalue=default_empty))
319 args_desc.append(func_kwargs)
349 args_desc.append(func_kwargs)
320
350
321 return matches.keys() + args_desc
351 return matches.keys() + args_desc
@@ -1,54 +1,70 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 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 import logging
21 import logging
22
22
23 from . import config_keys
23 from . import config_keys
24 from .events import SshKeyFileChangeEvent
24 from .events import SshKeyFileChangeEvent
25 from .subscribers import generate_ssh_authorized_keys_file_subscriber
25 from .subscribers import generate_ssh_authorized_keys_file_subscriber
26
26
27 from rhodecode.config.middleware import _bool_setting, _string_setting
27 from rhodecode.config.middleware import _bool_setting, _string_setting
28
28
29 log = logging.getLogger(__name__)
29 log = logging.getLogger(__name__)
30
30
31
31
32 def _sanitize_settings_and_apply_defaults(settings):
32 def _sanitize_settings_and_apply_defaults(settings):
33 """
33 """
34 Set defaults, convert to python types and validate settings.
34 Set defaults, convert to python types and validate settings.
35 """
35 """
36 _bool_setting(settings, config_keys.generate_authorized_keyfile, 'false')
36 _bool_setting(settings, config_keys.generate_authorized_keyfile, 'false')
37 _bool_setting(settings, config_keys.wrapper_allow_shell, 'false')
37 _bool_setting(settings, config_keys.wrapper_allow_shell, 'false')
38 _bool_setting(settings, config_keys.enable_debug_logging, 'false')
38
39
39 _string_setting(settings, config_keys.authorized_keys_file_path, '',
40 _string_setting(settings, config_keys.authorized_keys_file_path,
41 '~/.ssh/authorized_keys_rhodecode',
40 lower=False)
42 lower=False)
41 _string_setting(settings, config_keys.wrapper_cmd, '',
43 _string_setting(settings, config_keys.wrapper_cmd, '',
42 lower=False)
44 lower=False)
43 _string_setting(settings, config_keys.authorized_keys_line_ssh_opts, '',
45 _string_setting(settings, config_keys.authorized_keys_line_ssh_opts, '',
44 lower=False)
46 lower=False)
45
47
48 _string_setting(settings, config_keys.ssh_api_key, '',
49 lower=False)
50 _string_setting(settings, config_keys.ssh_api_host, '',
51 lower=False)
52 _string_setting(settings, config_keys.ssh_hg_bin,
53 '~/.rccontrol/vcsserver-1/profile/bin/hg',
54 lower=False)
55 _string_setting(settings, config_keys.ssh_git_bin,
56 '~/.rccontrol/vcsserver-1/profile/bin/git',
57 lower=False)
58 _string_setting(settings, config_keys.ssh_svn_bin,
59 '~/.rccontrol/vcsserver-1/profile/bin/svnserve',
60 lower=False)
61
46
62
47 def includeme(config):
63 def includeme(config):
48 settings = config.registry.settings
64 settings = config.registry.settings
49 _sanitize_settings_and_apply_defaults(settings)
65 _sanitize_settings_and_apply_defaults(settings)
50
66
51 # if we have enable generation of file, subscribe to event
67 # if we have enable generation of file, subscribe to event
52 if settings[config_keys.generate_authorized_keyfile]:
68 if settings[config_keys.generate_authorized_keyfile]:
53 config.add_subscriber(
69 config.add_subscriber(
54 generate_ssh_authorized_keys_file_subscriber, SshKeyFileChangeEvent)
70 generate_ssh_authorized_keys_file_subscriber, SshKeyFileChangeEvent)
@@ -1,28 +1,36 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 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 # Definition of setting keys used to configure this module. Defined here to
22 # Definition of setting keys used to configure this module. Defined here to
23 # avoid repetition of keys throughout the module.
23 # avoid repetition of keys throughout the module.
24 generate_authorized_keyfile = 'ssh.generate_authorized_keyfile'
24 generate_authorized_keyfile = 'ssh.generate_authorized_keyfile'
25 authorized_keys_file_path = 'ssh.authorized_keys_file_path'
25 authorized_keys_file_path = 'ssh.authorized_keys_file_path'
26 authorized_keys_line_ssh_opts = 'ssh.authorized_keys_ssh_opts'
26 authorized_keys_line_ssh_opts = 'ssh.authorized_keys_ssh_opts'
27 wrapper_cmd = 'ssh.wrapper_cmd'
27 wrapper_cmd = 'ssh.wrapper_cmd'
28 wrapper_allow_shell = 'ssh.wrapper_cmd_allow_shell'
28 wrapper_allow_shell = 'ssh.wrapper_cmd_allow_shell'
29 enable_debug_logging = 'ssh.enable_debug_logging'
30
31 ssh_api_key = 'ssh.api_key'
32 ssh_api_host = 'ssh.api_host'
33
34 ssh_hg_bin = 'ssh.executable.hg'
35 ssh_git_bin = 'ssh.executable.git'
36 ssh_svn_bin = 'ssh.executable.svn'
@@ -1,68 +1,73 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 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
22
23 import os
23 import os
24 import pytest
24 import pytest
25 import mock
25 import mock
26
26
27 from rhodecode.apps.ssh_support import utils
27 from rhodecode.apps.ssh_support import utils
28 from rhodecode.lib.utils2 import AttributeDict
28 from rhodecode.lib.utils2 import AttributeDict
29
29
30
30
31 class TestSshKeyFileGeneration(object):
31 class TestSshKeyFileGeneration(object):
32 @pytest.mark.parametrize('ssh_wrapper_cmd', ['/tmp/sshwrapper.py'])
32 @pytest.mark.parametrize('ssh_wrapper_cmd', ['/tmp/sshwrapper.py'])
33 @pytest.mark.parametrize('allow_shell', [True, False])
33 @pytest.mark.parametrize('allow_shell', [True, False])
34 @pytest.mark.parametrize('debug', [True, False])
34 @pytest.mark.parametrize('ssh_opts', [None, 'mycustom,option'])
35 @pytest.mark.parametrize('ssh_opts', [None, 'mycustom,option'])
35 def test_write_keyfile(self, tmpdir, ssh_wrapper_cmd, allow_shell, ssh_opts):
36 def test_write_keyfile(self, tmpdir, ssh_wrapper_cmd, allow_shell, debug, ssh_opts):
36
37
37 authorized_keys_file_path = os.path.join(str(tmpdir), 'authorized_keys')
38 authorized_keys_file_path = os.path.join(str(tmpdir), 'authorized_keys')
38
39
39 def keys():
40 def keys():
40 return [
41 return [
41 AttributeDict({'user': AttributeDict(username='admin'),
42 AttributeDict({'user': AttributeDict(username='admin'),
42 'ssh_key_data': 'ssh-rsa ADMIN_KEY'}),
43 'ssh_key_data': 'ssh-rsa ADMIN_KEY'}),
43 AttributeDict({'user': AttributeDict(username='user'),
44 AttributeDict({'user': AttributeDict(username='user'),
44 'ssh_key_data': 'ssh-rsa USER_KEY'}),
45 'ssh_key_data': 'ssh-rsa USER_KEY'}),
45 ]
46 ]
46
47 with mock.patch('rhodecode.apps.ssh_support.utils.get_all_active_keys',
47 with mock.patch('rhodecode.apps.ssh_support.utils.get_all_active_keys',
48 return_value=keys()):
48 return_value=keys()):
49 utils._generate_ssh_authorized_keys_file(
49 with mock.patch.dict('rhodecode.CONFIG', {'__file__': '/tmp/file.ini'}):
50 authorized_keys_file_path, ssh_wrapper_cmd,
50 utils._generate_ssh_authorized_keys_file(
51 allow_shell, ssh_opts
51 authorized_keys_file_path, ssh_wrapper_cmd,
52 )
52 allow_shell, ssh_opts, debug
53 )
53
54
54 assert os.path.isfile(authorized_keys_file_path)
55 assert os.path.isfile(authorized_keys_file_path)
55 with open(authorized_keys_file_path) as f:
56 with open(authorized_keys_file_path) as f:
56 content = f.read()
57 content = f.read()
57
58
58 assert 'command="/tmp/sshwrapper.py' in content
59 assert 'command="/tmp/sshwrapper.py' in content
59 assert 'This file is managed by RhodeCode, ' \
60 assert 'This file is managed by RhodeCode, ' \
60 'please do not edit it manually.' in content
61 'please do not edit it manually.' in content
62
63 if allow_shell:
64 assert '--shell' in content
61
65
62 if allow_shell:
66 if debug:
63 assert '--shell --user' in content
67 assert '--debug' in content
64 else:
68
65 assert '--user' in content
69 assert '--user' in content
70 assert '--user-id' in content
66
71
67 if ssh_opts:
72 if ssh_opts:
68 assert ssh_opts in content
73 assert ssh_opts in content
@@ -1,107 +1,119 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 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 import os
21 import os
22 import stat
22 import stat
23 import logging
23 import logging
24 import tempfile
24 import tempfile
25 import datetime
25 import datetime
26
26
27 from . import config_keys
27 from . import config_keys
28 from rhodecode.model.db import true, joinedload, User, UserSshKeys
28 from rhodecode.model.db import true, joinedload, User, UserSshKeys
29
29
30
30
31 log = logging.getLogger(__name__)
31 log = logging.getLogger(__name__)
32
32
33 HEADER = \
33 HEADER = \
34 "# This file is managed by RhodeCode, please do not edit it manually. # \n" \
34 "# This file is managed by RhodeCode, please do not edit it manually. # \n" \
35 "# Current entries: {}, create date: UTC:{}.\n"
35 "# Current entries: {}, create date: UTC:{}.\n"
36
36
37 # Default SSH options for authorized_keys file, can be override via .ini
37 # Default SSH options for authorized_keys file, can be override via .ini
38 SSH_OPTS = 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding'
38 SSH_OPTS = 'no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding'
39
39
40
40
41 def get_all_active_keys():
41 def get_all_active_keys():
42 result = UserSshKeys.query() \
42 result = UserSshKeys.query() \
43 .options(joinedload(UserSshKeys.user)) \
43 .options(joinedload(UserSshKeys.user)) \
44 .filter(UserSshKeys.user != User.get_default_user()) \
44 .filter(UserSshKeys.user != User.get_default_user()) \
45 .filter(User.active == true()) \
45 .filter(User.active == true()) \
46 .all()
46 .all()
47 return result
47 return result
48
48
49
49
50 def _generate_ssh_authorized_keys_file(
50 def _generate_ssh_authorized_keys_file(
51 authorized_keys_file_path, ssh_wrapper_cmd, allow_shell, ssh_opts):
51 authorized_keys_file_path, ssh_wrapper_cmd, allow_shell, ssh_opts, debug):
52
53 import rhodecode
52 all_active_keys = get_all_active_keys()
54 all_active_keys = get_all_active_keys()
53
55
54 if allow_shell:
56 if allow_shell:
55 ssh_wrapper_cmd = ssh_wrapper_cmd + ' --shell'
57 ssh_wrapper_cmd = ssh_wrapper_cmd + ' --shell'
58 if debug:
59 ssh_wrapper_cmd = ssh_wrapper_cmd + ' --debug'
56
60
57 if not os.path.isfile(authorized_keys_file_path):
61 if not os.path.isfile(authorized_keys_file_path):
58 with open(authorized_keys_file_path, 'w'):
62 with open(authorized_keys_file_path, 'w'):
59 pass
63 pass
60
64
61 if not os.access(authorized_keys_file_path, os.R_OK):
65 if not os.access(authorized_keys_file_path, os.R_OK):
62 raise OSError('Access to file {} is without read access'.format(
66 raise OSError('Access to file {} is without read access'.format(
63 authorized_keys_file_path))
67 authorized_keys_file_path))
64
68
65 line_tmpl = '{ssh_opts},command="{wrapper_command} --user {user}" {key}\n'
69 line_tmpl = '{ssh_opts},command="{wrapper_command} {ini_path} --user-id={user_id} --user={user}" {key}\n'
66
70
67 fd, tmp_authorized_keys = tempfile.mkstemp(
71 fd, tmp_authorized_keys = tempfile.mkstemp(
68 '.authorized_keys_write',
72 '.authorized_keys_write',
69 dir=os.path.dirname(authorized_keys_file_path))
73 dir=os.path.dirname(authorized_keys_file_path))
70
74
71 now = datetime.datetime.utcnow().isoformat()
75 now = datetime.datetime.utcnow().isoformat()
72 keys_file = os.fdopen(fd, 'wb')
76 keys_file = os.fdopen(fd, 'wb')
73 keys_file.write(HEADER.format(len(all_active_keys), now))
77 keys_file.write(HEADER.format(len(all_active_keys), now))
78 ini_path = rhodecode.CONFIG['__file__']
74
79
75 for user_key in all_active_keys:
80 for user_key in all_active_keys:
76 username = user_key.user.username
81 username = user_key.user.username
82 user_id = user_key.user.user_id
83
77 keys_file.write(
84 keys_file.write(
78 line_tmpl.format(
85 line_tmpl.format(
79 ssh_opts=ssh_opts or SSH_OPTS,
86 ssh_opts=ssh_opts or SSH_OPTS,
80 wrapper_command=ssh_wrapper_cmd,
87 wrapper_command=ssh_wrapper_cmd,
88 ini_path=ini_path,
89 user_id=user_id,
81 user=username, key=user_key.ssh_key_data))
90 user=username, key=user_key.ssh_key_data))
82 log.debug('addkey: Key added for user: `%s`', username)
91 log.debug('addkey: Key added for user: `%s`', username)
83 keys_file.close()
92 keys_file.close()
84
93
85 # Explicitly setting read-only permissions to authorized_keys
94 # Explicitly setting read-only permissions to authorized_keys
86 os.chmod(tmp_authorized_keys, stat.S_IRUSR | stat.S_IWUSR)
95 os.chmod(tmp_authorized_keys, stat.S_IRUSR | stat.S_IWUSR)
87 # Rename is atomic operation
96 # Rename is atomic operation
88 os.rename(tmp_authorized_keys, authorized_keys_file_path)
97 os.rename(tmp_authorized_keys, authorized_keys_file_path)
89
98
90
99
91 def generate_ssh_authorized_keys_file(registry):
100 def generate_ssh_authorized_keys_file(registry):
92 log.info('Generating new authorized key file')
101 log.info('Generating new authorized key file')
93
102
94 authorized_keys_file_path = registry.settings.get(
103 authorized_keys_file_path = registry.settings.get(
95 config_keys.authorized_keys_file_path)
104 config_keys.authorized_keys_file_path)
96
105
97 ssh_wrapper_cmd = registry.settings.get(
106 ssh_wrapper_cmd = registry.settings.get(
98 config_keys.wrapper_cmd)
107 config_keys.wrapper_cmd)
99 allow_shell = registry.settings.get(
108 allow_shell = registry.settings.get(
100 config_keys.wrapper_allow_shell)
109 config_keys.wrapper_allow_shell)
101 ssh_opts = registry.settings.get(
110 ssh_opts = registry.settings.get(
102 config_keys.authorized_keys_line_ssh_opts)
111 config_keys.authorized_keys_line_ssh_opts)
112 debug = registry.settings.get(
113 config_keys.enable_debug_logging)
103
114
104 _generate_ssh_authorized_keys_file(
115 _generate_ssh_authorized_keys_file(
105 authorized_keys_file_path, ssh_wrapper_cmd, allow_shell, ssh_opts)
116 authorized_keys_file_path, ssh_wrapper_cmd, allow_shell, ssh_opts,
117 debug)
106
118
107 return 0
119 return 0
@@ -1,722 +1,776 b''
1
1
2
2
3 ################################################################################
3 ################################################################################
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10
10
11 ################################################################################
11 ################################################################################
12 ## EMAIL CONFIGURATION ##
12 ## EMAIL CONFIGURATION ##
13 ## Uncomment and replace with the email address which should receive ##
13 ## Uncomment and replace with the email address which should receive ##
14 ## any error reports after an application crash ##
14 ## any error reports after an application crash ##
15 ## Additionally these settings will be used by the RhodeCode mailing system ##
15 ## Additionally these settings will be used by the RhodeCode mailing system ##
16 ################################################################################
16 ################################################################################
17
17
18 ## prefix all emails subjects with given prefix, helps filtering out emails
18 ## prefix all emails subjects with given prefix, helps filtering out emails
19 #email_prefix = [RhodeCode]
19 #email_prefix = [RhodeCode]
20
20
21 ## email FROM address all mails will be sent
21 ## email FROM address all mails will be sent
22 #app_email_from = rhodecode-noreply@localhost
22 #app_email_from = rhodecode-noreply@localhost
23
23
24 ## Uncomment and replace with the address which should receive any error report
24 ## Uncomment and replace with the address which should receive any error report
25 ## note: using appenlight for error handling doesn't need this to be uncommented
25 ## note: using appenlight for error handling doesn't need this to be uncommented
26 #email_to = admin@localhost
26 #email_to = admin@localhost
27
27
28 ## in case of Application errors, sent an error email form
28 ## in case of Application errors, sent an error email form
29 #error_email_from = rhodecode_error@localhost
29 #error_email_from = rhodecode_error@localhost
30
30
31 ## additional error message to be send in case of server crash
31 ## additional error message to be send in case of server crash
32 #error_message =
32 #error_message =
33
33
34
34
35 #smtp_server = mail.server.com
35 #smtp_server = mail.server.com
36 #smtp_username =
36 #smtp_username =
37 #smtp_password =
37 #smtp_password =
38 #smtp_port =
38 #smtp_port =
39 #smtp_use_tls = false
39 #smtp_use_tls = false
40 #smtp_use_ssl = true
40 #smtp_use_ssl = true
41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
41 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
42 #smtp_auth =
42 #smtp_auth =
43
43
44 [server:main]
44 [server:main]
45 ## COMMON ##
45 ## COMMON ##
46 host = 0.0.0.0
46 host = 0.0.0.0
47 port = 5000
47 port = 5000
48
48
49 ##################################
49 ##################################
50 ## WAITRESS WSGI SERVER ##
50 ## WAITRESS WSGI SERVER ##
51 ## Recommended for Development ##
51 ## Recommended for Development ##
52 ##################################
52 ##################################
53
53
54 use = egg:waitress#main
54 use = egg:waitress#main
55 ## number of worker threads
55 ## number of worker threads
56 threads = 5
56 threads = 5
57 ## MAX BODY SIZE 100GB
57 ## MAX BODY SIZE 100GB
58 max_request_body_size = 107374182400
58 max_request_body_size = 107374182400
59 ## Use poll instead of select, fixes file descriptors limits problems.
59 ## Use poll instead of select, fixes file descriptors limits problems.
60 ## May not work on old windows systems.
60 ## May not work on old windows systems.
61 asyncore_use_poll = true
61 asyncore_use_poll = true
62
62
63
63
64 ##########################
64 ##########################
65 ## GUNICORN WSGI SERVER ##
65 ## GUNICORN WSGI SERVER ##
66 ##########################
66 ##########################
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
67 ## run with gunicorn --log-config rhodecode.ini --paste rhodecode.ini
68
68
69 #use = egg:gunicorn#main
69 #use = egg:gunicorn#main
70 ## Sets the number of process workers. You must set `instance_id = *`
70 ## Sets the number of process workers. You must set `instance_id = *`
71 ## when this option is set to more than one worker, recommended
71 ## when this option is set to more than one worker, recommended
72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
72 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
73 ## The `instance_id = *` must be set in the [app:main] section below
73 ## The `instance_id = *` must be set in the [app:main] section below
74 #workers = 2
74 #workers = 2
75 ## number of threads for each of the worker, must be set to 1 for gevent
75 ## number of threads for each of the worker, must be set to 1 for gevent
76 ## generally recommened to be at 1
76 ## generally recommened to be at 1
77 #threads = 1
77 #threads = 1
78 ## process name
78 ## process name
79 #proc_name = rhodecode
79 #proc_name = rhodecode
80 ## type of worker class, one of sync, gevent
80 ## type of worker class, one of sync, gevent
81 ## recommended for bigger setup is using of of other than sync one
81 ## recommended for bigger setup is using of of other than sync one
82 #worker_class = sync
82 #worker_class = sync
83 ## The maximum number of simultaneous clients. Valid only for Gevent
83 ## The maximum number of simultaneous clients. Valid only for Gevent
84 #worker_connections = 10
84 #worker_connections = 10
85 ## max number of requests that worker will handle before being gracefully
85 ## max number of requests that worker will handle before being gracefully
86 ## restarted, could prevent memory leaks
86 ## restarted, could prevent memory leaks
87 #max_requests = 1000
87 #max_requests = 1000
88 #max_requests_jitter = 30
88 #max_requests_jitter = 30
89 ## amount of time a worker can spend with handling a request before it
89 ## amount of time a worker can spend with handling a request before it
90 ## gets killed and restarted. Set to 6hrs
90 ## gets killed and restarted. Set to 6hrs
91 #timeout = 21600
91 #timeout = 21600
92
92
93 ## UWSGI ##
93 ## UWSGI ##
94 ## run with uwsgi --ini-paste-logged <inifile.ini>
94 ## run with uwsgi --ini-paste-logged <inifile.ini>
95 #[uwsgi]
95 #[uwsgi]
96 #socket = /tmp/uwsgi.sock
96 #socket = /tmp/uwsgi.sock
97 #master = true
97 #master = true
98 #http = 127.0.0.1:5000
98 #http = 127.0.0.1:5000
99
99
100 ## set as deamon and redirect all output to file
100 ## set as deamon and redirect all output to file
101 #daemonize = ./uwsgi_rhodecode.log
101 #daemonize = ./uwsgi_rhodecode.log
102
102
103 ## master process PID
103 ## master process PID
104 #pidfile = ./uwsgi_rhodecode.pid
104 #pidfile = ./uwsgi_rhodecode.pid
105
105
106 ## stats server with workers statistics, use uwsgitop
106 ## stats server with workers statistics, use uwsgitop
107 ## for monitoring, `uwsgitop 127.0.0.1:1717`
107 ## for monitoring, `uwsgitop 127.0.0.1:1717`
108 #stats = 127.0.0.1:1717
108 #stats = 127.0.0.1:1717
109 #memory-report = true
109 #memory-report = true
110
110
111 ## log 5XX errors
111 ## log 5XX errors
112 #log-5xx = true
112 #log-5xx = true
113
113
114 ## Set the socket listen queue size.
114 ## Set the socket listen queue size.
115 #listen = 256
115 #listen = 256
116
116
117 ## Gracefully Reload workers after the specified amount of managed requests
117 ## Gracefully Reload workers after the specified amount of managed requests
118 ## (avoid memory leaks).
118 ## (avoid memory leaks).
119 #max-requests = 1000
119 #max-requests = 1000
120
120
121 ## enable large buffers
121 ## enable large buffers
122 #buffer-size=65535
122 #buffer-size=65535
123
123
124 ## socket and http timeouts ##
124 ## socket and http timeouts ##
125 #http-timeout=3600
125 #http-timeout=3600
126 #socket-timeout=3600
126 #socket-timeout=3600
127
127
128 ## Log requests slower than the specified number of milliseconds.
128 ## Log requests slower than the specified number of milliseconds.
129 #log-slow = 10
129 #log-slow = 10
130
130
131 ## Exit if no app can be loaded.
131 ## Exit if no app can be loaded.
132 #need-app = true
132 #need-app = true
133
133
134 ## Set lazy mode (load apps in workers instead of master).
134 ## Set lazy mode (load apps in workers instead of master).
135 #lazy = true
135 #lazy = true
136
136
137 ## scaling ##
137 ## scaling ##
138 ## set cheaper algorithm to use, if not set default will be used
138 ## set cheaper algorithm to use, if not set default will be used
139 #cheaper-algo = spare
139 #cheaper-algo = spare
140
140
141 ## minimum number of workers to keep at all times
141 ## minimum number of workers to keep at all times
142 #cheaper = 1
142 #cheaper = 1
143
143
144 ## number of workers to spawn at startup
144 ## number of workers to spawn at startup
145 #cheaper-initial = 1
145 #cheaper-initial = 1
146
146
147 ## maximum number of workers that can be spawned
147 ## maximum number of workers that can be spawned
148 #workers = 4
148 #workers = 4
149
149
150 ## how many workers should be spawned at a time
150 ## how many workers should be spawned at a time
151 #cheaper-step = 1
151 #cheaper-step = 1
152
152
153 ## prefix middleware for RhodeCode.
153 ## prefix middleware for RhodeCode.
154 ## recommended when using proxy setup.
154 ## recommended when using proxy setup.
155 ## allows to set RhodeCode under a prefix in server.
155 ## allows to set RhodeCode under a prefix in server.
156 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
156 ## eg https://server.com/custom_prefix. Enable `filter-with =` option below as well.
157 ## And set your prefix like: `prefix = /custom_prefix`
157 ## And set your prefix like: `prefix = /custom_prefix`
158 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
158 ## be sure to also set beaker.session.cookie_path = /custom_prefix if you need
159 ## to make your cookies only work on prefix url
159 ## to make your cookies only work on prefix url
160 [filter:proxy-prefix]
160 [filter:proxy-prefix]
161 use = egg:PasteDeploy#prefix
161 use = egg:PasteDeploy#prefix
162 prefix = /
162 prefix = /
163
163
164 [app:main]
164 [app:main]
165 is_test = True
165 is_test = True
166 use = egg:rhodecode-enterprise-ce
166 use = egg:rhodecode-enterprise-ce
167
167
168 ## enable proxy prefix middleware, defined above
168 ## enable proxy prefix middleware, defined above
169 #filter-with = proxy-prefix
169 #filter-with = proxy-prefix
170
170
171
171
172 ## RHODECODE PLUGINS ##
172 ## RHODECODE PLUGINS ##
173 rhodecode.includes = rhodecode.api
173 rhodecode.includes = rhodecode.api
174
174
175 # api prefix url
175 # api prefix url
176 rhodecode.api.url = /_admin/api
176 rhodecode.api.url = /_admin/api
177
177
178
178
179 ## END RHODECODE PLUGINS ##
179 ## END RHODECODE PLUGINS ##
180
180
181 ## encryption key used to encrypt social plugin tokens,
181 ## encryption key used to encrypt social plugin tokens,
182 ## remote_urls with credentials etc, if not set it defaults to
182 ## remote_urls with credentials etc, if not set it defaults to
183 ## `beaker.session.secret`
183 ## `beaker.session.secret`
184 #rhodecode.encrypted_values.secret =
184 #rhodecode.encrypted_values.secret =
185
185
186 ## decryption strict mode (enabled by default). It controls if decryption raises
186 ## decryption strict mode (enabled by default). It controls if decryption raises
187 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
187 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
188 #rhodecode.encrypted_values.strict = false
188 #rhodecode.encrypted_values.strict = false
189
189
190 ## return gzipped responses from Rhodecode (static files/application)
190 ## return gzipped responses from Rhodecode (static files/application)
191 gzip_responses = false
191 gzip_responses = false
192
192
193 ## autogenerate javascript routes file on startup
193 ## autogenerate javascript routes file on startup
194 generate_js_files = false
194 generate_js_files = false
195
195
196 ## Optional Languages
196 ## Optional Languages
197 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
197 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
198 lang = en
198 lang = en
199
199
200 ## perform a full repository scan on each server start, this should be
200 ## perform a full repository scan on each server start, this should be
201 ## set to false after first startup, to allow faster server restarts.
201 ## set to false after first startup, to allow faster server restarts.
202 startup.import_repos = true
202 startup.import_repos = true
203
203
204 ## Uncomment and set this path to use archive download cache.
204 ## Uncomment and set this path to use archive download cache.
205 ## Once enabled, generated archives will be cached at this location
205 ## Once enabled, generated archives will be cached at this location
206 ## and served from the cache during subsequent requests for the same archive of
206 ## and served from the cache during subsequent requests for the same archive of
207 ## the repository.
207 ## the repository.
208 #archive_cache_dir = /tmp/tarballcache
208 #archive_cache_dir = /tmp/tarballcache
209
209
210 ## change this to unique ID for security
210 ## change this to unique ID for security
211 app_instance_uuid = rc-production
211 app_instance_uuid = rc-production
212
212
213 ## cut off limit for large diffs (size in bytes)
213 ## cut off limit for large diffs (size in bytes)
214 cut_off_limit_diff = 1024000
214 cut_off_limit_diff = 1024000
215 cut_off_limit_file = 256000
215 cut_off_limit_file = 256000
216
216
217 ## use cache version of scm repo everywhere
217 ## use cache version of scm repo everywhere
218 vcs_full_cache = false
218 vcs_full_cache = false
219
219
220 ## force https in RhodeCode, fixes https redirects, assumes it's always https
220 ## force https in RhodeCode, fixes https redirects, assumes it's always https
221 ## Normally this is controlled by proper http flags sent from http server
221 ## Normally this is controlled by proper http flags sent from http server
222 force_https = false
222 force_https = false
223
223
224 ## use Strict-Transport-Security headers
224 ## use Strict-Transport-Security headers
225 use_htsts = false
225 use_htsts = false
226
226
227 ## number of commits stats will parse on each iteration
227 ## number of commits stats will parse on each iteration
228 commit_parse_limit = 25
228 commit_parse_limit = 25
229
229
230 ## git rev filter option, --all is the default filter, if you need to
230 ## git rev filter option, --all is the default filter, if you need to
231 ## hide all refs in changelog switch this to --branches --tags
231 ## hide all refs in changelog switch this to --branches --tags
232 git_rev_filter = --all
232 git_rev_filter = --all
233
233
234 # Set to true if your repos are exposed using the dumb protocol
234 # Set to true if your repos are exposed using the dumb protocol
235 git_update_server_info = false
235 git_update_server_info = false
236
236
237 ## RSS/ATOM feed options
237 ## RSS/ATOM feed options
238 rss_cut_off_limit = 256000
238 rss_cut_off_limit = 256000
239 rss_items_per_page = 10
239 rss_items_per_page = 10
240 rss_include_diff = false
240 rss_include_diff = false
241
241
242 ## gist URL alias, used to create nicer urls for gist. This should be an
242 ## gist URL alias, used to create nicer urls for gist. This should be an
243 ## url that does rewrites to _admin/gists/{gistid}.
243 ## url that does rewrites to _admin/gists/{gistid}.
244 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
244 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
245 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
245 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid}
246 gist_alias_url =
246 gist_alias_url =
247
247
248 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
248 ## List of views (using glob pattern syntax) that AUTH TOKENS could be
249 ## used for access.
249 ## used for access.
250 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
250 ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it
251 ## came from the the logged in user who own this authentication token.
251 ## came from the the logged in user who own this authentication token.
252 ## Additionally @TOKEN syntaxt can be used to bound the view to specific
253 ## authentication token. Such view would be only accessible when used together
254 ## with this authentication token
252 ##
255 ##
253 ## list of all views can be found under `_admin/permissions/auth_token_access`
256 ## list of all views can be found under `/_admin/permissions/auth_token_access`
254 ## The list should be "," separated and on a single line.
257 ## The list should be "," separated and on a single line.
255 ##
258 ##
256 ## Most common views to enable:
259 ## Most common views to enable:
257 # RepoCommitsView:repo_commit_download
260 # RepoCommitsView:repo_commit_download
258 # RepoCommitsView:repo_commit_patch
261 # RepoCommitsView:repo_commit_patch
259 # RepoCommitsView:repo_commit_raw
262 # RepoCommitsView:repo_commit_raw
263 # RepoCommitsView:repo_commit_raw@TOKEN
260 # RepoFilesView:repo_files_diff
264 # RepoFilesView:repo_files_diff
261 # RepoFilesView:repo_archivefile
265 # RepoFilesView:repo_archivefile
262 # RepoFilesView:repo_file_raw
266 # RepoFilesView:repo_file_raw
263 # GistView:*
267 # GistView:*
264 api_access_controllers_whitelist =
268 api_access_controllers_whitelist =
265
269
266 ## default encoding used to convert from and to unicode
270 ## default encoding used to convert from and to unicode
267 ## can be also a comma separated list of encoding in case of mixed encodings
271 ## can be also a comma separated list of encoding in case of mixed encodings
268 default_encoding = UTF-8
272 default_encoding = UTF-8
269
273
270 ## instance-id prefix
274 ## instance-id prefix
271 ## a prefix key for this instance used for cache invalidation when running
275 ## a prefix key for this instance used for cache invalidation when running
272 ## multiple instances of rhodecode, make sure it's globally unique for
276 ## multiple instances of rhodecode, make sure it's globally unique for
273 ## all running rhodecode instances. Leave empty if you don't use it
277 ## all running rhodecode instances. Leave empty if you don't use it
274 instance_id =
278 instance_id =
275
279
276 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
280 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
277 ## of an authentication plugin also if it is disabled by it's settings.
281 ## of an authentication plugin also if it is disabled by it's settings.
278 ## This could be useful if you are unable to log in to the system due to broken
282 ## This could be useful if you are unable to log in to the system due to broken
279 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
283 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
280 ## module to log in again and fix the settings.
284 ## module to log in again and fix the settings.
281 ##
285 ##
282 ## Available builtin plugin IDs (hash is part of the ID):
286 ## Available builtin plugin IDs (hash is part of the ID):
283 ## egg:rhodecode-enterprise-ce#rhodecode
287 ## egg:rhodecode-enterprise-ce#rhodecode
284 ## egg:rhodecode-enterprise-ce#pam
288 ## egg:rhodecode-enterprise-ce#pam
285 ## egg:rhodecode-enterprise-ce#ldap
289 ## egg:rhodecode-enterprise-ce#ldap
286 ## egg:rhodecode-enterprise-ce#jasig_cas
290 ## egg:rhodecode-enterprise-ce#jasig_cas
287 ## egg:rhodecode-enterprise-ce#headers
291 ## egg:rhodecode-enterprise-ce#headers
288 ## egg:rhodecode-enterprise-ce#crowd
292 ## egg:rhodecode-enterprise-ce#crowd
289 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
293 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
290
294
291 ## alternative return HTTP header for failed authentication. Default HTTP
295 ## alternative return HTTP header for failed authentication. Default HTTP
292 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
296 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
293 ## handling that causing a series of failed authentication calls.
297 ## handling that causing a series of failed authentication calls.
294 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
298 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
295 ## This will be served instead of default 401 on bad authnetication
299 ## This will be served instead of default 401 on bad authnetication
296 auth_ret_code =
300 auth_ret_code =
297
301
298 ## use special detection method when serving auth_ret_code, instead of serving
302 ## use special detection method when serving auth_ret_code, instead of serving
299 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
303 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
300 ## and then serve auth_ret_code to clients
304 ## and then serve auth_ret_code to clients
301 auth_ret_code_detection = false
305 auth_ret_code_detection = false
302
306
303 ## locking return code. When repository is locked return this HTTP code. 2XX
307 ## locking return code. When repository is locked return this HTTP code. 2XX
304 ## codes don't break the transactions while 4XX codes do
308 ## codes don't break the transactions while 4XX codes do
305 lock_ret_code = 423
309 lock_ret_code = 423
306
310
307 ## allows to change the repository location in settings page
311 ## allows to change the repository location in settings page
308 allow_repo_location_change = true
312 allow_repo_location_change = true
309
313
310 ## allows to setup custom hooks in settings page
314 ## allows to setup custom hooks in settings page
311 allow_custom_hooks_settings = true
315 allow_custom_hooks_settings = true
312
316
313 ## generated license token, goto license page in RhodeCode settings to obtain
317 ## generated license token, goto license page in RhodeCode settings to obtain
314 ## new token
318 ## new token
315 license_token = abra-cada-bra1-rce3
319 license_token = abra-cada-bra1-rce3
316
320
317 ## supervisor connection uri, for managing supervisor and logs.
321 ## supervisor connection uri, for managing supervisor and logs.
318 supervisor.uri =
322 supervisor.uri =
319 ## supervisord group name/id we only want this RC instance to handle
323 ## supervisord group name/id we only want this RC instance to handle
320 supervisor.group_id = dev
324 supervisor.group_id = dev
321
325
322 ## Display extended labs settings
326 ## Display extended labs settings
323 labs_settings_active = true
327 labs_settings_active = true
324
328
325 ####################################
329 ####################################
326 ### CELERY CONFIG ####
330 ### CELERY CONFIG ####
327 ####################################
331 ####################################
328 use_celery = false
332 use_celery = false
329 broker.host = localhost
333 broker.host = localhost
330 broker.vhost = rabbitmqhost
334 broker.vhost = rabbitmqhost
331 broker.port = 5672
335 broker.port = 5672
332 broker.user = rabbitmq
336 broker.user = rabbitmq
333 broker.password = qweqwe
337 broker.password = qweqwe
334
338
335 celery.imports = rhodecode.lib.celerylib.tasks
339 celery.imports = rhodecode.lib.celerylib.tasks
336
340
337 celery.result.backend = amqp
341 celery.result.backend = amqp
338 celery.result.dburi = amqp://
342 celery.result.dburi = amqp://
339 celery.result.serialier = json
343 celery.result.serialier = json
340
344
341 #celery.send.task.error.emails = true
345 #celery.send.task.error.emails = true
342 #celery.amqp.task.result.expires = 18000
346 #celery.amqp.task.result.expires = 18000
343
347
344 celeryd.concurrency = 2
348 celeryd.concurrency = 2
345 #celeryd.log.file = celeryd.log
349 #celeryd.log.file = celeryd.log
346 celeryd.log.level = debug
350 celeryd.log.level = debug
347 celeryd.max.tasks.per.child = 1
351 celeryd.max.tasks.per.child = 1
348
352
349 ## tasks will never be sent to the queue, but executed locally instead.
353 ## tasks will never be sent to the queue, but executed locally instead.
350 celery.always.eager = false
354 celery.always.eager = false
351
355
352 ####################################
356 ####################################
353 ### BEAKER CACHE ####
357 ### BEAKER CACHE ####
354 ####################################
358 ####################################
355 # default cache dir for templates. Putting this into a ramdisk
359 # default cache dir for templates. Putting this into a ramdisk
356 ## can boost performance, eg. %(here)s/data_ramdisk
360 ## can boost performance, eg. %(here)s/data_ramdisk
357 cache_dir = %(here)s/data
361 cache_dir = %(here)s/data
358
362
359 ## locking and default file storage for Beaker. Putting this into a ramdisk
363 ## locking and default file storage for Beaker. Putting this into a ramdisk
360 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
364 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
361 beaker.cache.data_dir = %(here)s/rc/data/cache/beaker_data
365 beaker.cache.data_dir = %(here)s/rc/data/cache/beaker_data
362 beaker.cache.lock_dir = %(here)s/rc/data/cache/beaker_lock
366 beaker.cache.lock_dir = %(here)s/rc/data/cache/beaker_lock
363
367
364 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
368 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
365
369
366 beaker.cache.super_short_term.type = memory
370 beaker.cache.super_short_term.type = memory
367 beaker.cache.super_short_term.expire = 1
371 beaker.cache.super_short_term.expire = 1
368 beaker.cache.super_short_term.key_length = 256
372 beaker.cache.super_short_term.key_length = 256
369
373
370 beaker.cache.short_term.type = memory
374 beaker.cache.short_term.type = memory
371 beaker.cache.short_term.expire = 60
375 beaker.cache.short_term.expire = 60
372 beaker.cache.short_term.key_length = 256
376 beaker.cache.short_term.key_length = 256
373
377
374 beaker.cache.long_term.type = memory
378 beaker.cache.long_term.type = memory
375 beaker.cache.long_term.expire = 36000
379 beaker.cache.long_term.expire = 36000
376 beaker.cache.long_term.key_length = 256
380 beaker.cache.long_term.key_length = 256
377
381
378 beaker.cache.sql_cache_short.type = memory
382 beaker.cache.sql_cache_short.type = memory
379 beaker.cache.sql_cache_short.expire = 1
383 beaker.cache.sql_cache_short.expire = 1
380 beaker.cache.sql_cache_short.key_length = 256
384 beaker.cache.sql_cache_short.key_length = 256
381
385
382 ## default is memory cache, configure only if required
386 ## default is memory cache, configure only if required
383 ## using multi-node or multi-worker setup
387 ## using multi-node or multi-worker setup
384 #beaker.cache.auth_plugins.type = ext:database
388 #beaker.cache.auth_plugins.type = ext:database
385 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
389 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
386 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
390 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
387 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
391 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
388 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
392 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
389 #beaker.cache.auth_plugins.sa.pool_size = 10
393 #beaker.cache.auth_plugins.sa.pool_size = 10
390 #beaker.cache.auth_plugins.sa.max_overflow = 0
394 #beaker.cache.auth_plugins.sa.max_overflow = 0
391
395
392 beaker.cache.repo_cache_long.type = memorylru_base
396 beaker.cache.repo_cache_long.type = memorylru_base
393 beaker.cache.repo_cache_long.max_items = 4096
397 beaker.cache.repo_cache_long.max_items = 4096
394 beaker.cache.repo_cache_long.expire = 2592000
398 beaker.cache.repo_cache_long.expire = 2592000
395
399
396 ## default is memorylru_base cache, configure only if required
400 ## default is memorylru_base cache, configure only if required
397 ## using multi-node or multi-worker setup
401 ## using multi-node or multi-worker setup
398 #beaker.cache.repo_cache_long.type = ext:memcached
402 #beaker.cache.repo_cache_long.type = ext:memcached
399 #beaker.cache.repo_cache_long.url = localhost:11211
403 #beaker.cache.repo_cache_long.url = localhost:11211
400 #beaker.cache.repo_cache_long.expire = 1209600
404 #beaker.cache.repo_cache_long.expire = 1209600
401 #beaker.cache.repo_cache_long.key_length = 256
405 #beaker.cache.repo_cache_long.key_length = 256
402
406
403 ####################################
407 ####################################
404 ### BEAKER SESSION ####
408 ### BEAKER SESSION ####
405 ####################################
409 ####################################
406
410
407 ## .session.type is type of storage options for the session, current allowed
411 ## .session.type is type of storage options for the session, current allowed
408 ## types are file, ext:memcached, ext:database, and memory (default).
412 ## types are file, ext:memcached, ext:database, and memory (default).
409 beaker.session.type = file
413 beaker.session.type = file
410 beaker.session.data_dir = %(here)s/rc/data/sessions/data
414 beaker.session.data_dir = %(here)s/rc/data/sessions/data
411
415
412 ## db based session, fast, and allows easy management over logged in users
416 ## db based session, fast, and allows easy management over logged in users
413 #beaker.session.type = ext:database
417 #beaker.session.type = ext:database
414 #beaker.session.table_name = db_session
418 #beaker.session.table_name = db_session
415 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
419 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
416 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
420 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
417 #beaker.session.sa.pool_recycle = 3600
421 #beaker.session.sa.pool_recycle = 3600
418 #beaker.session.sa.echo = false
422 #beaker.session.sa.echo = false
419
423
420 beaker.session.key = rhodecode
424 beaker.session.key = rhodecode
421 beaker.session.secret = test-rc-uytcxaz
425 beaker.session.secret = test-rc-uytcxaz
422 beaker.session.lock_dir = %(here)s/rc/data/sessions/lock
426 beaker.session.lock_dir = %(here)s/rc/data/sessions/lock
423
427
424 ## Secure encrypted cookie. Requires AES and AES python libraries
428 ## Secure encrypted cookie. Requires AES and AES python libraries
425 ## you must disable beaker.session.secret to use this
429 ## you must disable beaker.session.secret to use this
426 #beaker.session.encrypt_key = key_for_encryption
430 #beaker.session.encrypt_key = key_for_encryption
427 #beaker.session.validate_key = validation_key
431 #beaker.session.validate_key = validation_key
428
432
429 ## sets session as invalid(also logging out user) if it haven not been
433 ## sets session as invalid(also logging out user) if it haven not been
430 ## accessed for given amount of time in seconds
434 ## accessed for given amount of time in seconds
431 beaker.session.timeout = 2592000
435 beaker.session.timeout = 2592000
432 beaker.session.httponly = true
436 beaker.session.httponly = true
433 ## Path to use for the cookie. Set to prefix if you use prefix middleware
437 ## Path to use for the cookie. Set to prefix if you use prefix middleware
434 #beaker.session.cookie_path = /custom_prefix
438 #beaker.session.cookie_path = /custom_prefix
435
439
436 ## uncomment for https secure cookie
440 ## uncomment for https secure cookie
437 beaker.session.secure = false
441 beaker.session.secure = false
438
442
439 ## auto save the session to not to use .save()
443 ## auto save the session to not to use .save()
440 beaker.session.auto = false
444 beaker.session.auto = false
441
445
442 ## default cookie expiration time in seconds, set to `true` to set expire
446 ## default cookie expiration time in seconds, set to `true` to set expire
443 ## at browser close
447 ## at browser close
444 #beaker.session.cookie_expires = 3600
448 #beaker.session.cookie_expires = 3600
445
449
446 ###################################
450 ###################################
447 ## SEARCH INDEXING CONFIGURATION ##
451 ## SEARCH INDEXING CONFIGURATION ##
448 ###################################
452 ###################################
449 ## Full text search indexer is available in rhodecode-tools under
453 ## Full text search indexer is available in rhodecode-tools under
450 ## `rhodecode-tools index` command
454 ## `rhodecode-tools index` command
451
455
452 ## WHOOSH Backend, doesn't require additional services to run
456 ## WHOOSH Backend, doesn't require additional services to run
453 ## it works good with few dozen repos
457 ## it works good with few dozen repos
454 search.module = rhodecode.lib.index.whoosh
458 search.module = rhodecode.lib.index.whoosh
455 search.location = %(here)s/data/index
459 search.location = %(here)s/data/index
456
460
457 ########################################
461 ########################################
458 ### CHANNELSTREAM CONFIG ####
462 ### CHANNELSTREAM CONFIG ####
459 ########################################
463 ########################################
460 ## channelstream enables persistent connections and live notification
464 ## channelstream enables persistent connections and live notification
461 ## in the system. It's also used by the chat system
465 ## in the system. It's also used by the chat system
462
466
463 channelstream.enabled = false
467 channelstream.enabled = false
464
468
465 ## server address for channelstream server on the backend
469 ## server address for channelstream server on the backend
466 channelstream.server = 127.0.0.1:9800
470 channelstream.server = 127.0.0.1:9800
467 ## location of the channelstream server from outside world
471 ## location of the channelstream server from outside world
468 ## use ws:// for http or wss:// for https. This address needs to be handled
472 ## use ws:// for http or wss:// for https. This address needs to be handled
469 ## by external HTTP server such as Nginx or Apache
473 ## by external HTTP server such as Nginx or Apache
470 ## see nginx/apache configuration examples in our docs
474 ## see nginx/apache configuration examples in our docs
471 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
475 channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
472 channelstream.secret = secret
476 channelstream.secret = secret
473 channelstream.history.location = %(here)s/channelstream_history
477 channelstream.history.location = %(here)s/channelstream_history
474
478
475 ## Internal application path that Javascript uses to connect into.
479 ## Internal application path that Javascript uses to connect into.
476 ## If you use proxy-prefix the prefix should be added before /_channelstream
480 ## If you use proxy-prefix the prefix should be added before /_channelstream
477 channelstream.proxy_path = /_channelstream
481 channelstream.proxy_path = /_channelstream
478
482
479
483
480 ###################################
484 ###################################
481 ## APPENLIGHT CONFIG ##
485 ## APPENLIGHT CONFIG ##
482 ###################################
486 ###################################
483
487
484 ## Appenlight is tailored to work with RhodeCode, see
488 ## Appenlight is tailored to work with RhodeCode, see
485 ## http://appenlight.com for details how to obtain an account
489 ## http://appenlight.com for details how to obtain an account
486
490
487 ## appenlight integration enabled
491 ## appenlight integration enabled
488 appenlight = false
492 appenlight = false
489
493
490 appenlight.server_url = https://api.appenlight.com
494 appenlight.server_url = https://api.appenlight.com
491 appenlight.api_key = YOUR_API_KEY
495 appenlight.api_key = YOUR_API_KEY
492 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
496 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
493
497
494 # used for JS client
498 # used for JS client
495 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
499 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
496
500
497 ## TWEAK AMOUNT OF INFO SENT HERE
501 ## TWEAK AMOUNT OF INFO SENT HERE
498
502
499 ## enables 404 error logging (default False)
503 ## enables 404 error logging (default False)
500 appenlight.report_404 = false
504 appenlight.report_404 = false
501
505
502 ## time in seconds after request is considered being slow (default 1)
506 ## time in seconds after request is considered being slow (default 1)
503 appenlight.slow_request_time = 1
507 appenlight.slow_request_time = 1
504
508
505 ## record slow requests in application
509 ## record slow requests in application
506 ## (needs to be enabled for slow datastore recording and time tracking)
510 ## (needs to be enabled for slow datastore recording and time tracking)
507 appenlight.slow_requests = true
511 appenlight.slow_requests = true
508
512
509 ## enable hooking to application loggers
513 ## enable hooking to application loggers
510 appenlight.logging = true
514 appenlight.logging = true
511
515
512 ## minimum log level for log capture
516 ## minimum log level for log capture
513 appenlight.logging.level = WARNING
517 appenlight.logging.level = WARNING
514
518
515 ## send logs only from erroneous/slow requests
519 ## send logs only from erroneous/slow requests
516 ## (saves API quota for intensive logging)
520 ## (saves API quota for intensive logging)
517 appenlight.logging_on_error = false
521 appenlight.logging_on_error = false
518
522
519 ## list of additonal keywords that should be grabbed from environ object
523 ## list of additonal keywords that should be grabbed from environ object
520 ## can be string with comma separated list of words in lowercase
524 ## can be string with comma separated list of words in lowercase
521 ## (by default client will always send following info:
525 ## (by default client will always send following info:
522 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
526 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
523 ## start with HTTP* this list be extended with additional keywords here
527 ## start with HTTP* this list be extended with additional keywords here
524 appenlight.environ_keys_whitelist =
528 appenlight.environ_keys_whitelist =
525
529
526 ## list of keywords that should be blanked from request object
530 ## list of keywords that should be blanked from request object
527 ## can be string with comma separated list of words in lowercase
531 ## can be string with comma separated list of words in lowercase
528 ## (by default client will always blank keys that contain following words
532 ## (by default client will always blank keys that contain following words
529 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
533 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
530 ## this list be extended with additional keywords set here
534 ## this list be extended with additional keywords set here
531 appenlight.request_keys_blacklist =
535 appenlight.request_keys_blacklist =
532
536
533 ## list of namespaces that should be ignores when gathering log entries
537 ## list of namespaces that should be ignores when gathering log entries
534 ## can be string with comma separated list of namespaces
538 ## can be string with comma separated list of namespaces
535 ## (by default the client ignores own entries: appenlight_client.client)
539 ## (by default the client ignores own entries: appenlight_client.client)
536 appenlight.log_namespace_blacklist =
540 appenlight.log_namespace_blacklist =
537
541
538
542
539 ################################################################################
543 ################################################################################
540 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
544 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
541 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
545 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
542 ## execute malicious code after an exception is raised. ##
546 ## execute malicious code after an exception is raised. ##
543 ################################################################################
547 ################################################################################
544 set debug = false
548 set debug = false
545
549
546
550
547 ##############
551 ##############
548 ## STYLING ##
552 ## STYLING ##
549 ##############
553 ##############
550 debug_style = false
554 debug_style = false
551
555
552 ###########################################
556 ###########################################
553 ### MAIN RHODECODE DATABASE CONFIG ###
557 ### MAIN RHODECODE DATABASE CONFIG ###
554 ###########################################
558 ###########################################
555 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
559 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
556 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode_test
560 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode_test
557 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode_test
561 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode_test
558 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
562 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode_test.db?timeout=30
559
563
560 # see sqlalchemy docs for other advanced settings
564 # see sqlalchemy docs for other advanced settings
561
565
562 ## print the sql statements to output
566 ## print the sql statements to output
563 sqlalchemy.db1.echo = false
567 sqlalchemy.db1.echo = false
564 ## recycle the connections after this amount of seconds
568 ## recycle the connections after this amount of seconds
565 sqlalchemy.db1.pool_recycle = 3600
569 sqlalchemy.db1.pool_recycle = 3600
566 sqlalchemy.db1.convert_unicode = true
570 sqlalchemy.db1.convert_unicode = true
567
571
568 ## the number of connections to keep open inside the connection pool.
572 ## the number of connections to keep open inside the connection pool.
569 ## 0 indicates no limit
573 ## 0 indicates no limit
570 #sqlalchemy.db1.pool_size = 5
574 #sqlalchemy.db1.pool_size = 5
571
575
572 ## the number of connections to allow in connection pool "overflow", that is
576 ## the number of connections to allow in connection pool "overflow", that is
573 ## connections that can be opened above and beyond the pool_size setting,
577 ## connections that can be opened above and beyond the pool_size setting,
574 ## which defaults to five.
578 ## which defaults to five.
575 #sqlalchemy.db1.max_overflow = 10
579 #sqlalchemy.db1.max_overflow = 10
576
580
577
581
578 ##################
582 ##################
579 ### VCS CONFIG ###
583 ### VCS CONFIG ###
580 ##################
584 ##################
581 vcs.server.enable = true
585 vcs.server.enable = true
582 vcs.server = localhost:9901
586 vcs.server = localhost:9901
583
587
584 ## Web server connectivity protocol, responsible for web based VCS operatations
588 ## Web server connectivity protocol, responsible for web based VCS operatations
585 ## Available protocols are:
589 ## Available protocols are:
586 ## `http` - use http-rpc backend (default)
590 ## `http` - use http-rpc backend (default)
587 vcs.server.protocol = http
591 vcs.server.protocol = http
588
592
589 ## Push/Pull operations protocol, available options are:
593 ## Push/Pull operations protocol, available options are:
590 ## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended
594 ## `http` - use http-rpc backend (default)
591 ## `vcsserver.scm_app` - internal app (EE only)
595 ## `vcsserver.scm_app` - internal app (EE only)
592 vcs.scm_app_implementation = http
596 vcs.scm_app_implementation = http
593
597
594 ## Push/Pull operations hooks protocol, available options are:
598 ## Push/Pull operations hooks protocol, available options are:
595 ## `http` - use http-rpc backend (default)
599 ## `http` - use http-rpc backend (default)
596 vcs.hooks.protocol = http
600 vcs.hooks.protocol = http
597
601
598 vcs.server.log_level = debug
602 vcs.server.log_level = debug
599 ## Start VCSServer with this instance as a subprocess, usefull for development
603 ## Start VCSServer with this instance as a subprocess, usefull for development
600 vcs.start_server = false
604 vcs.start_server = false
601
605
602 ## List of enabled VCS backends, available options are:
606 ## List of enabled VCS backends, available options are:
603 ## `hg` - mercurial
607 ## `hg` - mercurial
604 ## `git` - git
608 ## `git` - git
605 ## `svn` - subversion
609 ## `svn` - subversion
606 vcs.backends = hg, git, svn
610 vcs.backends = hg, git, svn
607
611
608 vcs.connection_timeout = 3600
612 vcs.connection_timeout = 3600
609 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
613 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
610 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
614 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible, pre-1.9-compatible
611 #vcs.svn.compatible_version = pre-1.8-compatible
615 #vcs.svn.compatible_version = pre-1.8-compatible
612
616
613
617
614 ############################################################
618 ############################################################
615 ### Subversion proxy support (mod_dav_svn) ###
619 ### Subversion proxy support (mod_dav_svn) ###
616 ### Maps RhodeCode repo groups into SVN paths for Apache ###
620 ### Maps RhodeCode repo groups into SVN paths for Apache ###
617 ############################################################
621 ############################################################
618 ## Enable or disable the config file generation.
622 ## Enable or disable the config file generation.
619 svn.proxy.generate_config = false
623 svn.proxy.generate_config = false
620 ## Generate config file with `SVNListParentPath` set to `On`.
624 ## Generate config file with `SVNListParentPath` set to `On`.
621 svn.proxy.list_parent_path = true
625 svn.proxy.list_parent_path = true
622 ## Set location and file name of generated config file.
626 ## Set location and file name of generated config file.
623 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
627 svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
624 ## Used as a prefix to the `Location` block in the generated config file.
628 ## Used as a prefix to the `Location` block in the generated config file.
625 ## In most cases it should be set to `/`.
629 ## In most cases it should be set to `/`.
626 svn.proxy.location_root = /
630 svn.proxy.location_root = /
627 ## Command to reload the mod dav svn configuration on change.
631 ## Command to reload the mod dav svn configuration on change.
628 ## Example: `/etc/init.d/apache2 reload`
632 ## Example: `/etc/init.d/apache2 reload`
629 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
633 #svn.proxy.reload_cmd = /etc/init.d/apache2 reload
630 ## If the timeout expires before the reload command finishes, the command will
634 ## If the timeout expires before the reload command finishes, the command will
631 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
635 ## be killed. Setting it to zero means no timeout. Defaults to 10 seconds.
632 #svn.proxy.reload_timeout = 10
636 #svn.proxy.reload_timeout = 10
633
637
638 ############################################################
639 ### SSH Support Settings ###
640 ############################################################
641
642 ## Defines if the authorized_keys file should be written on any change of
643 ## user ssh keys
644 ssh.generate_authorized_keyfile = false
645
646 ## Options for ssh, default is `no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding`
647 # ssh.authorized_keys_ssh_opts =
648
649 ## File to generate the authorized keys together with options
650 ## It is possible to have multiple key files specified in `sshd_config` e.g.
651 ## AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys_rhodecode
652 ssh.authorized_keys_file_path = ~/.ssh/authorized_keys_rhodecode
653
654 ## Command to execute the SSH wrapper. The binary is available in the
655 ## rhodecode installation directory.
656 ## e.g ~/.rccontrol/community-1/profile/bin/rcssh-wrapper
657 ssh.wrapper_cmd = ~/.rccontrol/community-1/rcssh-wrapper
658
659 ## Allow shell when executing the ssh-wrapper command
660 ssh.wrapper_cmd_allow_shell = false
661
662 ## Enables logging, and detailed output send back to the client. Usefull for
663 ## debugging, shouldn't be used in production.
664 ssh.enable_debug_logging = false
665
666 ## API KEY for user who has access to fetch other user permission information
667 ## most likely an super-admin account with some IP restrictions.
668 ssh.api_key =
669
670 ## API Host, the server address of RhodeCode instance that the api_key will
671 ## access
672 ssh.api_host = http://localhost
673
674 ## Paths to binary executrables, by default they are the names, but we can
675 ## override them if we want to use a custom one
676 ssh.executable.hg = ~/.rccontrol/vcsserver-1/profile/bin/hg
677 ssh.executable.git = ~/.rccontrol/vcsserver-1/profile/bin/git
678 ssh.executable.svn = ~/.rccontrol/vcsserver-1/profile/bin/svnserve
679
680
634 ## Dummy marker to add new entries after.
681 ## Dummy marker to add new entries after.
635 ## Add any custom entries below. Please don't remove.
682 ## Add any custom entries below. Please don't remove.
636 custom.conf = 1
683 custom.conf = 1
637
684
638
685
639 ################################
686 ################################
640 ### LOGGING CONFIGURATION ####
687 ### LOGGING CONFIGURATION ####
641 ################################
688 ################################
642 [loggers]
689 [loggers]
643 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
690 keys = root, routes, rhodecode, sqlalchemy, beaker, templates, ssh_wrapper
644
691
645 [handlers]
692 [handlers]
646 keys = console, console_sql
693 keys = console, console_sql
647
694
648 [formatters]
695 [formatters]
649 keys = generic, color_formatter, color_formatter_sql
696 keys = generic, color_formatter, color_formatter_sql
650
697
651 #############
698 #############
652 ## LOGGERS ##
699 ## LOGGERS ##
653 #############
700 #############
654 [logger_root]
701 [logger_root]
655 level = NOTSET
702 level = NOTSET
656 handlers = console
703 handlers = console
657
704
658 [logger_routes]
705 [logger_routes]
659 level = DEBUG
706 level = DEBUG
660 handlers =
707 handlers =
661 qualname = routes.middleware
708 qualname = routes.middleware
662 ## "level = DEBUG" logs the route matched and routing variables.
709 ## "level = DEBUG" logs the route matched and routing variables.
663 propagate = 1
710 propagate = 1
664
711
665 [logger_beaker]
712 [logger_beaker]
666 level = DEBUG
713 level = DEBUG
667 handlers =
714 handlers =
668 qualname = beaker.container
715 qualname = beaker.container
669 propagate = 1
716 propagate = 1
670
717
671 [logger_templates]
718 [logger_templates]
672 level = INFO
719 level = INFO
673 handlers =
720 handlers =
674 qualname = pylons.templating
721 qualname = pylons.templating
675 propagate = 1
722 propagate = 1
676
723
677 [logger_rhodecode]
724 [logger_rhodecode]
678 level = DEBUG
725 level = DEBUG
679 handlers =
726 handlers =
680 qualname = rhodecode
727 qualname = rhodecode
681 propagate = 1
728 propagate = 1
682
729
683 [logger_sqlalchemy]
730 [logger_sqlalchemy]
684 level = ERROR
731 level = ERROR
685 handlers = console_sql
732 handlers = console_sql
686 qualname = sqlalchemy.engine
733 qualname = sqlalchemy.engine
687 propagate = 0
734 propagate = 0
688
735
736 [logger_ssh_wrapper]
737 level = DEBUG
738 handlers =
739 qualname = ssh_wrapper
740 propagate = 1
741
742
689 ##############
743 ##############
690 ## HANDLERS ##
744 ## HANDLERS ##
691 ##############
745 ##############
692
746
693 [handler_console]
747 [handler_console]
694 class = StreamHandler
748 class = StreamHandler
695 args = (sys.stderr,)
749 args = (sys.stderr,)
696 level = DEBUG
750 level = DEBUG
697 formatter = generic
751 formatter = generic
698
752
699 [handler_console_sql]
753 [handler_console_sql]
700 class = StreamHandler
754 class = StreamHandler
701 args = (sys.stderr,)
755 args = (sys.stderr,)
702 level = WARN
756 level = WARN
703 formatter = generic
757 formatter = generic
704
758
705 ################
759 ################
706 ## FORMATTERS ##
760 ## FORMATTERS ##
707 ################
761 ################
708
762
709 [formatter_generic]
763 [formatter_generic]
710 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
764 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
711 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
765 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
712 datefmt = %Y-%m-%d %H:%M:%S
766 datefmt = %Y-%m-%d %H:%M:%S
713
767
714 [formatter_color_formatter]
768 [formatter_color_formatter]
715 class = rhodecode.lib.logging_formatter.ColorFormatter
769 class = rhodecode.lib.logging_formatter.ColorFormatter
716 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
770 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
717 datefmt = %Y-%m-%d %H:%M:%S
771 datefmt = %Y-%m-%d %H:%M:%S
718
772
719 [formatter_color_formatter_sql]
773 [formatter_color_formatter_sql]
720 class = rhodecode.lib.logging_formatter.ColorFormatterSql
774 class = rhodecode.lib.logging_formatter.ColorFormatterSql
721 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
775 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
722 datefmt = %Y-%m-%d %H:%M:%S
776 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,260 +1,261 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 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 # Import early to make sure things are patched up properly
21 # Import early to make sure things are patched up properly
22 from setuptools import setup, find_packages
22 from setuptools import setup, find_packages
23
23
24 import os
24 import os
25 import sys
25 import sys
26 import pkgutil
26 import pkgutil
27 import platform
27 import platform
28
28
29 from pip.download import PipSession
29 from pip.download import PipSession
30 from pip.req import parse_requirements
30 from pip.req import parse_requirements
31
31
32 from codecs import open
32 from codecs import open
33
33
34
34
35 if sys.version_info < (2, 7):
35 if sys.version_info < (2, 7):
36 raise Exception('RhodeCode requires Python 2.7 or later')
36 raise Exception('RhodeCode requires Python 2.7 or later')
37
37
38 here = os.path.abspath(os.path.dirname(__file__))
38 here = os.path.abspath(os.path.dirname(__file__))
39
39
40 # defines current platform
40 # defines current platform
41 __platform__ = platform.system()
41 __platform__ = platform.system()
42 __license__ = 'AGPLv3, and Commercial License'
42 __license__ = 'AGPLv3, and Commercial License'
43 __author__ = 'RhodeCode GmbH'
43 __author__ = 'RhodeCode GmbH'
44 __url__ = 'https://code.rhodecode.com'
44 __url__ = 'https://code.rhodecode.com'
45 is_windows = __platform__ in ('Windows',)
45 is_windows = __platform__ in ('Windows',)
46
46
47
47
48 def _get_requirements(req_filename, exclude=None, extras=None):
48 def _get_requirements(req_filename, exclude=None, extras=None):
49 extras = extras or []
49 extras = extras or []
50 exclude = exclude or []
50 exclude = exclude or []
51
51
52 try:
52 try:
53 parsed = parse_requirements(
53 parsed = parse_requirements(
54 os.path.join(here, req_filename), session=PipSession())
54 os.path.join(here, req_filename), session=PipSession())
55 except TypeError:
55 except TypeError:
56 # try pip < 6.0.0, that doesn't support session
56 # try pip < 6.0.0, that doesn't support session
57 parsed = parse_requirements(os.path.join(here, req_filename))
57 parsed = parse_requirements(os.path.join(here, req_filename))
58
58
59 requirements = []
59 requirements = []
60 for ir in parsed:
60 for ir in parsed:
61 if ir.req and ir.name not in exclude:
61 if ir.req and ir.name not in exclude:
62 requirements.append(str(ir.req))
62 requirements.append(str(ir.req))
63 return requirements + extras
63 return requirements + extras
64
64
65
65
66 # requirements extract
66 # requirements extract
67 setup_requirements = ['PasteScript', 'pytest-runner']
67 setup_requirements = ['PasteScript', 'pytest-runner']
68 install_requirements = _get_requirements(
68 install_requirements = _get_requirements(
69 'requirements.txt', exclude=['setuptools'])
69 'requirements.txt', exclude=['setuptools'])
70 test_requirements = _get_requirements(
70 test_requirements = _get_requirements(
71 'requirements_test.txt', extras=['configobj'])
71 'requirements_test.txt', extras=['configobj'])
72
72
73 install_requirements = [
73 install_requirements = [
74 'Babel',
74 'Babel',
75 'Beaker',
75 'Beaker',
76 'FormEncode',
76 'FormEncode',
77 'Mako',
77 'Mako',
78 'Markdown',
78 'Markdown',
79 'MarkupSafe',
79 'MarkupSafe',
80 'MySQL-python',
80 'MySQL-python',
81 'Paste',
81 'Paste',
82 'PasteDeploy',
82 'PasteDeploy',
83 'PasteScript',
83 'PasteScript',
84 'Pygments',
84 'Pygments',
85 'pygments-markdown-lexer',
85 'pygments-markdown-lexer',
86 'Pylons',
86 'Pylons',
87 'Routes',
87 'Routes',
88 'SQLAlchemy',
88 'SQLAlchemy',
89 'Tempita',
89 'Tempita',
90 'URLObject',
90 'URLObject',
91 'WebError',
91 'WebError',
92 'WebHelpers',
92 'WebHelpers',
93 'WebHelpers2',
93 'WebHelpers2',
94 'WebOb',
94 'WebOb',
95 'WebTest',
95 'WebTest',
96 'Whoosh',
96 'Whoosh',
97 'alembic',
97 'alembic',
98 'amqplib',
98 'amqplib',
99 'anyjson',
99 'anyjson',
100 'appenlight-client',
100 'appenlight-client',
101 'authomatic',
101 'authomatic',
102 'cssselect',
102 'cssselect',
103 'celery',
103 'celery',
104 'channelstream',
104 'channelstream',
105 'colander',
105 'colander',
106 'decorator',
106 'decorator',
107 'deform',
107 'deform',
108 'docutils',
108 'docutils',
109 'gevent',
109 'gevent',
110 'gunicorn',
110 'gunicorn',
111 'infrae.cache',
111 'infrae.cache',
112 'ipython',
112 'ipython',
113 'iso8601',
113 'iso8601',
114 'kombu',
114 'kombu',
115 'lxml',
115 'lxml',
116 'msgpack-python',
116 'msgpack-python',
117 'nbconvert',
117 'nbconvert',
118 'packaging',
118 'packaging',
119 'psycopg2',
119 'psycopg2',
120 'py-gfm',
120 'py-gfm',
121 'pycrypto',
121 'pycrypto',
122 'pycurl',
122 'pycurl',
123 'pyparsing',
123 'pyparsing',
124 'pyramid',
124 'pyramid',
125 'pyramid-debugtoolbar',
125 'pyramid-debugtoolbar',
126 'pyramid-mako',
126 'pyramid-mako',
127 'pyramid-beaker',
127 'pyramid-beaker',
128 'pysqlite',
128 'pysqlite',
129 'python-dateutil',
129 'python-dateutil',
130 'python-ldap',
130 'python-ldap',
131 'python-memcached',
131 'python-memcached',
132 'python-pam',
132 'python-pam',
133 'recaptcha-client',
133 'recaptcha-client',
134 'repoze.lru',
134 'repoze.lru',
135 'requests',
135 'requests',
136 'simplejson',
136 'simplejson',
137 'sshpubkeys',
137 'sshpubkeys',
138 'subprocess32',
138 'subprocess32',
139 'waitress',
139 'waitress',
140 'zope.cachedescriptors',
140 'zope.cachedescriptors',
141 'dogpile.cache',
141 'dogpile.cache',
142 'dogpile.core',
142 'dogpile.core',
143 'psutil',
143 'psutil',
144 'py-bcrypt',
144 'py-bcrypt',
145 ]
145 ]
146
146
147
147
148 def get_version():
148 def get_version():
149 version = pkgutil.get_data('rhodecode', 'VERSION')
149 version = pkgutil.get_data('rhodecode', 'VERSION')
150 return version.strip()
150 return version.strip()
151
151
152
152
153 # additional files that goes into package itself
153 # additional files that goes into package itself
154 package_data = {
154 package_data = {
155 '': ['*.txt', '*.rst'],
155 '': ['*.txt', '*.rst'],
156 'configs': ['*.ini'],
156 'configs': ['*.ini'],
157 'rhodecode': ['VERSION', 'i18n/*/LC_MESSAGES/*.mo', ],
157 'rhodecode': ['VERSION', 'i18n/*/LC_MESSAGES/*.mo', ],
158 }
158 }
159
159
160 description = 'Source Code Management Platform'
160 description = 'Source Code Management Platform'
161 keywords = ' '.join([
161 keywords = ' '.join([
162 'rhodecode', 'mercurial', 'git', 'svn',
162 'rhodecode', 'mercurial', 'git', 'svn',
163 'code review',
163 'code review',
164 'repo groups', 'ldap', 'repository management', 'hgweb',
164 'repo groups', 'ldap', 'repository management', 'hgweb',
165 'hgwebdir', 'gitweb', 'serving hgweb',
165 'hgwebdir', 'gitweb', 'serving hgweb',
166 ])
166 ])
167
167
168
168
169 # README/DESCRIPTION generation
169 # README/DESCRIPTION generation
170 readme_file = 'README.rst'
170 readme_file = 'README.rst'
171 changelog_file = 'CHANGES.rst'
171 changelog_file = 'CHANGES.rst'
172 try:
172 try:
173 long_description = open(readme_file).read() + '\n\n' + \
173 long_description = open(readme_file).read() + '\n\n' + \
174 open(changelog_file).read()
174 open(changelog_file).read()
175 except IOError as err:
175 except IOError as err:
176 sys.stderr.write(
176 sys.stderr.write(
177 "[WARNING] Cannot find file specified as long_description (%s)\n "
177 "[WARNING] Cannot find file specified as long_description (%s)\n "
178 "or changelog (%s) skipping that file" % (readme_file, changelog_file))
178 "or changelog (%s) skipping that file" % (readme_file, changelog_file))
179 long_description = description
179 long_description = description
180
180
181
181
182 setup(
182 setup(
183 name='rhodecode-enterprise-ce',
183 name='rhodecode-enterprise-ce',
184 version=get_version(),
184 version=get_version(),
185 description=description,
185 description=description,
186 long_description=long_description,
186 long_description=long_description,
187 keywords=keywords,
187 keywords=keywords,
188 license=__license__,
188 license=__license__,
189 author=__author__,
189 author=__author__,
190 author_email='marcin@rhodecode.com',
190 author_email='marcin@rhodecode.com',
191 url=__url__,
191 url=__url__,
192 setup_requires=setup_requirements,
192 setup_requires=setup_requirements,
193 install_requires=install_requirements,
193 install_requires=install_requirements,
194 tests_require=test_requirements,
194 tests_require=test_requirements,
195 zip_safe=False,
195 zip_safe=False,
196 packages=find_packages(exclude=["docs", "tests*"]),
196 packages=find_packages(exclude=["docs", "tests*"]),
197 package_data=package_data,
197 package_data=package_data,
198 include_package_data=True,
198 include_package_data=True,
199 classifiers=[
199 classifiers=[
200 'Development Status :: 6 - Mature',
200 'Development Status :: 6 - Mature',
201 'Environment :: Web Environment',
201 'Environment :: Web Environment',
202 'Intended Audience :: Developers',
202 'Intended Audience :: Developers',
203 'Operating System :: OS Independent',
203 'Operating System :: OS Independent',
204 'Topic :: Software Development :: Version Control',
204 'Topic :: Software Development :: Version Control',
205 'License :: OSI Approved :: Affero GNU General Public License v3 or later (AGPLv3+)',
205 'License :: OSI Approved :: Affero GNU General Public License v3 or later (AGPLv3+)',
206 'Programming Language :: Python :: 2.7',
206 'Programming Language :: Python :: 2.7',
207 ],
207 ],
208 message_extractors={
208 message_extractors={
209 'rhodecode': [
209 'rhodecode': [
210 ('**.py', 'python', None),
210 ('**.py', 'python', None),
211 ('**.js', 'javascript', None),
211 ('**.js', 'javascript', None),
212 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
212 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
213 ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}),
213 ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}),
214 ('public/**', 'ignore', None),
214 ('public/**', 'ignore', None),
215 ]
215 ]
216 },
216 },
217 paster_plugins=['PasteScript', 'Pylons'],
217 paster_plugins=['PasteScript', 'Pylons'],
218 entry_points={
218 entry_points={
219 'enterprise.plugins1': [
219 'enterprise.plugins1': [
220 'crowd=rhodecode.authentication.plugins.auth_crowd:plugin_factory',
220 'crowd=rhodecode.authentication.plugins.auth_crowd:plugin_factory',
221 'headers=rhodecode.authentication.plugins.auth_headers:plugin_factory',
221 'headers=rhodecode.authentication.plugins.auth_headers:plugin_factory',
222 'jasig_cas=rhodecode.authentication.plugins.auth_jasig_cas:plugin_factory',
222 'jasig_cas=rhodecode.authentication.plugins.auth_jasig_cas:plugin_factory',
223 'ldap=rhodecode.authentication.plugins.auth_ldap:plugin_factory',
223 'ldap=rhodecode.authentication.plugins.auth_ldap:plugin_factory',
224 'pam=rhodecode.authentication.plugins.auth_pam:plugin_factory',
224 'pam=rhodecode.authentication.plugins.auth_pam:plugin_factory',
225 'rhodecode=rhodecode.authentication.plugins.auth_rhodecode:plugin_factory',
225 'rhodecode=rhodecode.authentication.plugins.auth_rhodecode:plugin_factory',
226 'token=rhodecode.authentication.plugins.auth_token:plugin_factory',
226 'token=rhodecode.authentication.plugins.auth_token:plugin_factory',
227 ],
227 ],
228 'paste.app_factory': [
228 'paste.app_factory': [
229 'main=rhodecode.config.middleware:make_pyramid_app',
229 'main=rhodecode.config.middleware:make_pyramid_app',
230 'pylons=rhodecode.config.middleware:make_app',
230 'pylons=rhodecode.config.middleware:make_app',
231 ],
231 ],
232 'paste.app_install': [
232 'paste.app_install': [
233 'main=pylons.util:PylonsInstaller',
233 'main=pylons.util:PylonsInstaller',
234 'pylons=pylons.util:PylonsInstaller',
234 'pylons=pylons.util:PylonsInstaller',
235 ],
235 ],
236 'paste.global_paster_command': [
236 'paste.global_paster_command': [
237 'make-config=rhodecode.lib.paster_commands.make_config:Command',
237 'make-config=rhodecode.lib.paster_commands.make_config:Command',
238 'setup-rhodecode=rhodecode.lib.paster_commands.setup_rhodecode:Command',
238 'setup-rhodecode=rhodecode.lib.paster_commands.setup_rhodecode:Command',
239 'ishell=rhodecode.lib.paster_commands.ishell:Command',
239 'ishell=rhodecode.lib.paster_commands.ishell:Command',
240 'upgrade-db=rhodecode.lib.dbmigrate:UpgradeDb',
240 'upgrade-db=rhodecode.lib.dbmigrate:UpgradeDb',
241 'celeryd=rhodecode.lib.celerypylons.commands:CeleryDaemonCommand',
241 'celeryd=rhodecode.lib.celerypylons.commands:CeleryDaemonCommand',
242 ],
242 ],
243 'pyramid.pshell_runner': [
243 'pyramid.pshell_runner': [
244 'ipython = rhodecode.lib.pyramid_shell:ipython_shell_runner',
244 'ipython = rhodecode.lib.pyramid_shell:ipython_shell_runner',
245 ],
245 ],
246 'pytest11': [
246 'pytest11': [
247 'pylons=rhodecode.tests.pylons_plugin',
247 'pylons=rhodecode.tests.pylons_plugin',
248 'enterprise=rhodecode.tests.plugin',
248 'enterprise=rhodecode.tests.plugin',
249 ],
249 ],
250 'console_scripts': [
250 'console_scripts': [
251 'rcserver=rhodecode.rcserver:main',
251 'rcserver=rhodecode.rcserver:main',
252 'rcsetup-app=rhodecode.lib.rc_commands.setup_rc:main',
252 'rcsetup-app=rhodecode.lib.rc_commands.setup_rc:main',
253 'rcupgrade-db=rhodecode.lib.rc_commands.upgrade_db:main',
253 'rcupgrade-db=rhodecode.lib.rc_commands.upgrade_db:main',
254 'rcssh-wrapper=rhodecode.apps.ssh_support.lib.ssh_wrapper:main',
254 ],
255 ],
255 'beaker.backends': [
256 'beaker.backends': [
256 'memorylru_base=rhodecode.lib.memory_lru_debug:MemoryLRUNamespaceManagerBase',
257 'memorylru_base=rhodecode.lib.memory_lru_debug:MemoryLRUNamespaceManagerBase',
257 'memorylru_debug=rhodecode.lib.memory_lru_debug:MemoryLRUNamespaceManagerDebug'
258 'memorylru_debug=rhodecode.lib.memory_lru_debug:MemoryLRUNamespaceManagerDebug'
258 ]
259 ]
259 },
260 },
260 )
261 )
General Comments 0
You need to be logged in to leave comments. Login now