release: Merge default into stable for release preparation
This commit is contained in:
commit
0bf319bc22
393 changed files with 21780 additions and 9081 deletions
|
|
@ -1,5 +1,5 @@
|
|||
[bumpversion]
|
||||
current_version = 4.2.1
|
||||
current_version = 4.3.0
|
||||
message = release: Bump version {current_version} to {new_version}
|
||||
|
||||
[bumpversion:file:rhodecode/VERSION]
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ syntax: regexp
|
|||
^build/
|
||||
^coverage\.xml$
|
||||
^data$
|
||||
^\.eggs/
|
||||
^configs/data$
|
||||
^dev.ini$
|
||||
^acceptance_tests/dev.*\.ini$
|
||||
|
|
|
|||
17
.release.cfg
17
.release.cfg
|
|
@ -4,27 +4,22 @@ done = false
|
|||
[task:bump_version]
|
||||
done = true
|
||||
|
||||
[task:rc_tools_pinned]
|
||||
done = true
|
||||
|
||||
[task:fixes_on_stable]
|
||||
done = true
|
||||
|
||||
[task:pip2nix_generated]
|
||||
done = true
|
||||
|
||||
[task:changelog_updated]
|
||||
done = true
|
||||
|
||||
[task:generate_api_docs]
|
||||
done = true
|
||||
|
||||
[release]
|
||||
state = prepared
|
||||
version = 4.2.1
|
||||
|
||||
[task:updated_translation]
|
||||
|
||||
[release]
|
||||
state = in_progress
|
||||
version = 4.3.0
|
||||
|
||||
[task:rc_tools_pinned]
|
||||
|
||||
[task:generate_js_routes]
|
||||
|
||||
[task:updated_trial_license]
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ module.exports = function(grunt) {
|
|||
'<%= dirs.js.src %>/moment.js',
|
||||
'<%= dirs.js.src %>/appenlight-client-0.4.1.min.js',
|
||||
'<%= dirs.js.src %>/i18n_utils.js',
|
||||
'<%= dirs.js.src %>/deform.js',
|
||||
|
||||
// Plugins
|
||||
'<%= dirs.js.src %>/plugins/jquery.pjax.js',
|
||||
|
|
@ -31,6 +32,7 @@ module.exports = function(grunt) {
|
|||
'<%= dirs.js.src %>/plugins/jquery.mark.js',
|
||||
'<%= dirs.js.src %>/plugins/jquery.timeago.js',
|
||||
'<%= dirs.js.src %>/plugins/jquery.timeago-extension.js',
|
||||
'<%= dirs.js.src %>/plugins/toastr.js',
|
||||
|
||||
// Select2
|
||||
'<%= dirs.js.src %>/select2/select2.js',
|
||||
|
|
@ -56,12 +58,14 @@ module.exports = function(grunt) {
|
|||
'<%= dirs.js.src %>/rhodecode/utils/colorgenerator.js',
|
||||
'<%= dirs.js.src %>/rhodecode/utils/ie.js',
|
||||
'<%= dirs.js.src %>/rhodecode/utils/os.js',
|
||||
'<%= dirs.js.src %>/rhodecode/utils/topics.js',
|
||||
|
||||
// Rhodecode widgets
|
||||
'<%= dirs.js.src %>/rhodecode/widgets/multiselect.js',
|
||||
|
||||
// Rhodecode components
|
||||
'<%= dirs.js.src %>/rhodecode/init.js',
|
||||
'<%= dirs.js.src %>/rhodecode/connection_controller.js',
|
||||
'<%= dirs.js.src %>/rhodecode/codemirror.js',
|
||||
'<%= dirs.js.src %>/rhodecode/comments.js',
|
||||
'<%= dirs.js.src %>/rhodecode/constants.js',
|
||||
|
|
@ -76,6 +80,7 @@ module.exports = function(grunt) {
|
|||
'<%= dirs.js.src %>/rhodecode/select2_widgets.js',
|
||||
'<%= dirs.js.src %>/rhodecode/tooltips.js',
|
||||
'<%= dirs.js.src %>/rhodecode/users.js',
|
||||
'<%= dirs.js.src %>/rhodecode/utils/notifications.js',
|
||||
'<%= dirs.js.src %>/rhodecode/appenlight.js',
|
||||
|
||||
// Rhodecode main module
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ permission notice:
|
|||
file:
|
||||
Copyright (c) 2008-2011 - msgpack-python
|
||||
file:licenses/msgpack_license.txt
|
||||
Copyright (c) 2009 - tornado
|
||||
file:licenses/tornado_license.txt
|
||||
|
||||
Both licensed under the Apache License, Version 2.0 (the "License");
|
||||
All licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
|
|
|
|||
10
MANIFEST.in
10
MANIFEST.in
|
|
@ -2,20 +2,20 @@
|
|||
include test.ini
|
||||
include MANIFEST.in
|
||||
include README.rst
|
||||
include CHANGES.rst
|
||||
include LICENSE.txt
|
||||
|
||||
include rhodecode/VERSION
|
||||
|
||||
# docs
|
||||
recursive-include docs *
|
||||
|
||||
# init.d
|
||||
recursive-include init.d *
|
||||
# all config files
|
||||
recursive-include configs *
|
||||
|
||||
# translations
|
||||
recursive-include rhodecode/i18n *
|
||||
|
||||
# bin stuff
|
||||
recursive-include rhodecode/bin *
|
||||
|
||||
# hook templates
|
||||
recursive-include rhodecode/config/hook_templates *
|
||||
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -20,7 +20,7 @@ ci-docs: docs;
|
|||
clean: test-clean
|
||||
find . -type f \( -iname '*.c' -o -iname '*.pyc' -o -iname '*.so' \) -exec rm '{}' ';'
|
||||
|
||||
test: test-clean test-lint test-only
|
||||
test: test-clean test-only
|
||||
|
||||
test-clean:
|
||||
rm -rf coverage.xml htmlcov junit.xml pylint.log result
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
README - Quickstart
|
||||
===================
|
||||
|
||||
This folder contains the functional tests and automation of specification
|
||||
examples. Details about testing can be found in
|
||||
`/docs-internal/testing/index.rst`.
|
||||
|
||||
|
||||
Setting up your Rhodecode Enterprise instance
|
||||
---------------------------------------------
|
||||
|
||||
The tests will create users and repositories as needed, so you can start with a
|
||||
new and empty instance.
|
||||
|
||||
Use the following example call for the database setup of Enterprise::
|
||||
|
||||
paster setup-rhodecode \
|
||||
--user=admin \
|
||||
--email=admin@example.com \
|
||||
--password=secret \
|
||||
--api-key=9999999999999999999999999999999999999999 \
|
||||
your-enterprise-config.ini
|
||||
|
||||
This way the username, password, and auth token of the admin user will match the
|
||||
defaults from the test run.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
1. Make sure your Rhodecode Enterprise instance is running at
|
||||
http://localhost:5000.
|
||||
|
||||
2. Enter `nix-shell` from the acceptance_tests folder::
|
||||
|
||||
cd acceptance_tests
|
||||
nix-shell
|
||||
|
||||
Make sure that `rcpkgs` and `rcnixpkgs` are available on the nix path.
|
||||
|
||||
3. Run the tests::
|
||||
|
||||
py.test -c example.ini -vs
|
||||
|
||||
The parameter ``-vs`` allows you to see debugging output during the test
|
||||
run. Check ``py.test --help`` and the documentation at http://pytest.org to
|
||||
learn all details about the test runner.
|
||||
|
|
@ -1,24 +1,37 @@
|
|||
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
# RhodeCode Enterprise - configuration file #
|
||||
# Built-in functions and variables #
|
||||
## RHODECODE ENTERPRISE CONFIGURATION ##
|
||||
# The %(here)s variable will be replaced with the parent directory of this file#
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
[DEFAULT]
|
||||
debug = true
|
||||
|
||||
################################################################################
|
||||
## EMAIL CONFIGURATION ##
|
||||
## Uncomment and replace with the email address which should receive ##
|
||||
## any error reports after an application crash ##
|
||||
## Additionally these settings will be used by the RhodeCode mailing system ##
|
||||
################################################################################
|
||||
#email_to = admin@localhost
|
||||
#error_email_from = paste_error@localhost
|
||||
#app_email_from = rhodecode-noreply@localhost
|
||||
#error_message =
|
||||
|
||||
## prefix all emails subjects with given prefix, helps filtering out emails
|
||||
#email_prefix = [RhodeCode]
|
||||
|
||||
## email FROM address all mails will be sent
|
||||
#app_email_from = rhodecode-noreply@localhost
|
||||
|
||||
## Uncomment and replace with the address which should receive any error report
|
||||
## note: using appenlight for error handling doesn't need this to be uncommented
|
||||
#email_to = admin@localhost
|
||||
|
||||
## in case of Application errors, sent an error email form
|
||||
#error_email_from = rhodecode_error@localhost
|
||||
|
||||
## additional error message to be send in case of server crash
|
||||
#error_message =
|
||||
|
||||
|
||||
#smtp_server = mail.server.com
|
||||
#smtp_username =
|
||||
#smtp_password =
|
||||
|
|
@ -37,6 +50,7 @@ port = 5000
|
|||
## WAITRESS WSGI SERVER ##
|
||||
## Recommended for Development ##
|
||||
##################################
|
||||
|
||||
use = egg:waitress#main
|
||||
## number of worker threads
|
||||
threads = 5
|
||||
|
|
@ -51,6 +65,7 @@ asyncore_use_poll = true
|
|||
## GUNICORN WSGI SERVER ##
|
||||
##########################
|
||||
## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
|
||||
|
||||
#use = egg:gunicorn#main
|
||||
## Sets the number of process workers. You must set `instance_id = *`
|
||||
## when this option is set to more than one worker, recommended
|
||||
|
|
@ -77,15 +92,18 @@ asyncore_use_poll = true
|
|||
|
||||
|
||||
## prefix middleware for RhodeCode, disables force_https flag.
|
||||
## recommended when using proxy setup.
|
||||
## allows to set RhodeCode under a prefix in server.
|
||||
## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
|
||||
#[filter:proxy-prefix]
|
||||
#use = egg:PasteDeploy#prefix
|
||||
#prefix = /<your-prefix>
|
||||
## optionally set prefix like: `prefix = /<your-prefix>`
|
||||
[filter:proxy-prefix]
|
||||
use = egg:PasteDeploy#prefix
|
||||
prefix = /
|
||||
|
||||
[app:main]
|
||||
use = egg:rhodecode-enterprise-ce
|
||||
## enable proxy prefix middleware, defined below
|
||||
|
||||
## enable proxy prefix middleware, defined above
|
||||
#filter-with = proxy-prefix
|
||||
|
||||
# During development the we want to have the debug toolbar enabled
|
||||
|
|
@ -123,12 +141,10 @@ rhodecode.api.url = /_admin/api
|
|||
## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
|
||||
#rhodecode.encrypted_values.strict = false
|
||||
|
||||
full_stack = true
|
||||
## return gzipped responses from Rhodecode (static files/application)
|
||||
gzip_responses = false
|
||||
|
||||
## Serve static files via RhodeCode, disable to serve them via HTTP server
|
||||
static_files = true
|
||||
|
||||
# autogenerate javascript routes file on startup
|
||||
## autogenerate javascript routes file on startup
|
||||
generate_js_files = false
|
||||
|
||||
## Optional Languages
|
||||
|
|
@ -317,8 +333,8 @@ beaker.cache.sql_cache_short.type = memory
|
|||
beaker.cache.sql_cache_short.expire = 10
|
||||
beaker.cache.sql_cache_short.key_length = 256
|
||||
|
||||
# default is memory cache, configure only if required
|
||||
# using multi-node or multi-worker setup
|
||||
## default is memory cache, configure only if required
|
||||
## using multi-node or multi-worker setup
|
||||
#beaker.cache.auth_plugins.type = ext:database
|
||||
#beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
|
||||
#beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
|
||||
|
|
@ -331,8 +347,8 @@ beaker.cache.repo_cache_long.type = memorylru_base
|
|||
beaker.cache.repo_cache_long.max_items = 4096
|
||||
beaker.cache.repo_cache_long.expire = 2592000
|
||||
|
||||
# default is memorylru_base cache, configure only if required
|
||||
# using multi-node or multi-worker setup
|
||||
## default is memorylru_base cache, configure only if required
|
||||
## using multi-node or multi-worker setup
|
||||
#beaker.cache.repo_cache_long.type = ext:memcached
|
||||
#beaker.cache.repo_cache_long.url = localhost:11211
|
||||
#beaker.cache.repo_cache_long.expire = 1209600
|
||||
|
|
@ -347,7 +363,7 @@ beaker.cache.repo_cache_long.expire = 2592000
|
|||
beaker.session.type = file
|
||||
beaker.session.data_dir = %(here)s/data/sessions/data
|
||||
|
||||
## db based session, fast, and allows easy management over logged in users ##
|
||||
## db based session, fast, and allows easy management over logged in users
|
||||
#beaker.session.type = ext:database
|
||||
#beaker.session.table_name = db_session
|
||||
#beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
|
||||
|
|
@ -368,6 +384,7 @@ beaker.session.lock_dir = %(here)s/data/sessions/lock
|
|||
## accessed for given amount of time in seconds
|
||||
beaker.session.timeout = 2592000
|
||||
beaker.session.httponly = true
|
||||
## Path to use for the cookie.
|
||||
#beaker.session.cookie_path = /<your-prefix>
|
||||
|
||||
## uncomment for https secure cookie
|
||||
|
|
@ -391,6 +408,23 @@ beaker.session.auto = false
|
|||
search.module = rhodecode.lib.index.whoosh
|
||||
search.location = %(here)s/data/index
|
||||
|
||||
########################################
|
||||
### CHANNELSTREAM CONFIG ####
|
||||
########################################
|
||||
## channelstream enables persistent connections and live notification
|
||||
## in the system. It's also used by the chat system
|
||||
|
||||
channelstream.enabled = true
|
||||
## location of channelstream server on the backend
|
||||
channelstream.server = 127.0.0.1:9800
|
||||
## location of the channelstream server from outside world
|
||||
## most likely this would be an http server special backend URL, that handles
|
||||
## websocket connections see nginx example for config
|
||||
channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
|
||||
channelstream.secret = secret
|
||||
channelstream.history.location = %(here)s/channelstream_history
|
||||
|
||||
|
||||
###################################
|
||||
## APPENLIGHT CONFIG ##
|
||||
###################################
|
||||
|
|
@ -466,9 +500,10 @@ debug_style = true
|
|||
#########################################################
|
||||
### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
|
||||
#########################################################
|
||||
sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
|
||||
#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
|
||||
#sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
|
||||
#sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
|
||||
sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
|
||||
|
||||
# see sqlalchemy docs for other advanced settings
|
||||
|
||||
|
|
@ -498,28 +533,53 @@ vcs.server = localhost:9900
|
|||
## Available protocols are:
|
||||
## `pyro4` - using pyro4 server
|
||||
## `http` - using http-rpc backend
|
||||
#vcs.server.protocol = http
|
||||
vcs.server.protocol = http
|
||||
|
||||
## Push/Pull operations protocol, available options are:
|
||||
## `pyro4` - using pyro4 server
|
||||
## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended
|
||||
## `vcsserver.scm_app` - internal app (EE only)
|
||||
#vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http
|
||||
vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http
|
||||
|
||||
## Push/Pull operations hooks protocol, available options are:
|
||||
## `pyro4` - using pyro4 server
|
||||
## `http` - using http-rpc backend
|
||||
#vcs.hooks.protocol = http
|
||||
vcs.hooks.protocol = http
|
||||
|
||||
vcs.server.log_level = debug
|
||||
## Start VCSServer with this instance as a subprocess, usefull for development
|
||||
vcs.start_server = true
|
||||
|
||||
## List of enabled VCS backends, available options are:
|
||||
## `hg` - mercurial
|
||||
## `git` - git
|
||||
## `svn` - subversion
|
||||
vcs.backends = hg, git, svn
|
||||
|
||||
vcs.connection_timeout = 3600
|
||||
## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
|
||||
## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
|
||||
#vcs.svn.compatible_version = pre-1.8-compatible
|
||||
|
||||
|
||||
############################################################
|
||||
### Subversion proxy support (mod_dav_svn) ###
|
||||
### Maps RhodeCode repo groups into SVN paths for Apache ###
|
||||
############################################################
|
||||
## Enable or disable the config file generation.
|
||||
svn.proxy.generate_config = false
|
||||
## Generate config file with `SVNListParentPath` set to `On`.
|
||||
svn.proxy.list_parent_path = true
|
||||
## Set location and file name of generated config file.
|
||||
svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
|
||||
## File system path to the directory containing the repositories served by
|
||||
## RhodeCode.
|
||||
svn.proxy.parent_path_root = /path/to/repo_store
|
||||
## Used as a prefix to the <Location> block in the generated config file. In
|
||||
## most cases it should be set to `/`.
|
||||
svn.proxy.location_root = /
|
||||
|
||||
|
||||
################################
|
||||
### LOGGING CONFIGURATION ####
|
||||
################################
|
||||
|
|
|
|||
|
|
@ -1,24 +1,37 @@
|
|||
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
# RhodeCode Enterprise - configuration file #
|
||||
# Built-in functions and variables #
|
||||
## RHODECODE ENTERPRISE CONFIGURATION ##
|
||||
# The %(here)s variable will be replaced with the parent directory of this file#
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
[DEFAULT]
|
||||
debug = true
|
||||
|
||||
################################################################################
|
||||
## EMAIL CONFIGURATION ##
|
||||
## Uncomment and replace with the email address which should receive ##
|
||||
## any error reports after an application crash ##
|
||||
## Additionally these settings will be used by the RhodeCode mailing system ##
|
||||
################################################################################
|
||||
#email_to = admin@localhost
|
||||
#error_email_from = paste_error@localhost
|
||||
#app_email_from = rhodecode-noreply@localhost
|
||||
#error_message =
|
||||
|
||||
## prefix all emails subjects with given prefix, helps filtering out emails
|
||||
#email_prefix = [RhodeCode]
|
||||
|
||||
## email FROM address all mails will be sent
|
||||
#app_email_from = rhodecode-noreply@localhost
|
||||
|
||||
## Uncomment and replace with the address which should receive any error report
|
||||
## note: using appenlight for error handling doesn't need this to be uncommented
|
||||
#email_to = admin@localhost
|
||||
|
||||
## in case of Application errors, sent an error email form
|
||||
#error_email_from = rhodecode_error@localhost
|
||||
|
||||
## additional error message to be send in case of server crash
|
||||
#error_message =
|
||||
|
||||
|
||||
#smtp_server = mail.server.com
|
||||
#smtp_username =
|
||||
#smtp_password =
|
||||
|
|
@ -37,6 +50,7 @@ port = 5000
|
|||
## WAITRESS WSGI SERVER ##
|
||||
## Recommended for Development ##
|
||||
##################################
|
||||
|
||||
#use = egg:waitress#main
|
||||
## number of worker threads
|
||||
#threads = 5
|
||||
|
|
@ -51,6 +65,7 @@ port = 5000
|
|||
## GUNICORN WSGI SERVER ##
|
||||
##########################
|
||||
## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
|
||||
|
||||
use = egg:gunicorn#main
|
||||
## Sets the number of process workers. You must set `instance_id = *`
|
||||
## when this option is set to more than one worker, recommended
|
||||
|
|
@ -77,15 +92,18 @@ timeout = 21600
|
|||
|
||||
|
||||
## prefix middleware for RhodeCode, disables force_https flag.
|
||||
## recommended when using proxy setup.
|
||||
## allows to set RhodeCode under a prefix in server.
|
||||
## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
|
||||
#[filter:proxy-prefix]
|
||||
#use = egg:PasteDeploy#prefix
|
||||
#prefix = /<your-prefix>
|
||||
## optionally set prefix like: `prefix = /<your-prefix>`
|
||||
[filter:proxy-prefix]
|
||||
use = egg:PasteDeploy#prefix
|
||||
prefix = /
|
||||
|
||||
[app:main]
|
||||
use = egg:rhodecode-enterprise-ce
|
||||
## enable proxy prefix middleware, defined below
|
||||
|
||||
## enable proxy prefix middleware, defined above
|
||||
#filter-with = proxy-prefix
|
||||
|
||||
## encryption key used to encrypt social plugin tokens,
|
||||
|
|
@ -97,12 +115,10 @@ use = egg:rhodecode-enterprise-ce
|
|||
## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
|
||||
#rhodecode.encrypted_values.strict = false
|
||||
|
||||
full_stack = true
|
||||
## return gzipped responses from Rhodecode (static files/application)
|
||||
gzip_responses = false
|
||||
|
||||
## Serve static files via RhodeCode, disable to serve them via HTTP server
|
||||
static_files = true
|
||||
|
||||
# autogenerate javascript routes file on startup
|
||||
## autogenerate javascript routes file on startup
|
||||
generate_js_files = false
|
||||
|
||||
## Optional Languages
|
||||
|
|
@ -291,8 +307,8 @@ beaker.cache.sql_cache_short.type = memory
|
|||
beaker.cache.sql_cache_short.expire = 10
|
||||
beaker.cache.sql_cache_short.key_length = 256
|
||||
|
||||
# default is memory cache, configure only if required
|
||||
# using multi-node or multi-worker setup
|
||||
## default is memory cache, configure only if required
|
||||
## using multi-node or multi-worker setup
|
||||
#beaker.cache.auth_plugins.type = ext:database
|
||||
#beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
|
||||
#beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
|
||||
|
|
@ -305,8 +321,8 @@ beaker.cache.repo_cache_long.type = memorylru_base
|
|||
beaker.cache.repo_cache_long.max_items = 4096
|
||||
beaker.cache.repo_cache_long.expire = 2592000
|
||||
|
||||
# default is memorylru_base cache, configure only if required
|
||||
# using multi-node or multi-worker setup
|
||||
## default is memorylru_base cache, configure only if required
|
||||
## using multi-node or multi-worker setup
|
||||
#beaker.cache.repo_cache_long.type = ext:memcached
|
||||
#beaker.cache.repo_cache_long.url = localhost:11211
|
||||
#beaker.cache.repo_cache_long.expire = 1209600
|
||||
|
|
@ -321,7 +337,7 @@ beaker.cache.repo_cache_long.expire = 2592000
|
|||
beaker.session.type = file
|
||||
beaker.session.data_dir = %(here)s/data/sessions/data
|
||||
|
||||
## db based session, fast, and allows easy management over logged in users ##
|
||||
## db based session, fast, and allows easy management over logged in users
|
||||
#beaker.session.type = ext:database
|
||||
#beaker.session.table_name = db_session
|
||||
#beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
|
||||
|
|
@ -342,6 +358,7 @@ beaker.session.lock_dir = %(here)s/data/sessions/lock
|
|||
## accessed for given amount of time in seconds
|
||||
beaker.session.timeout = 2592000
|
||||
beaker.session.httponly = true
|
||||
## Path to use for the cookie.
|
||||
#beaker.session.cookie_path = /<your-prefix>
|
||||
|
||||
## uncomment for https secure cookie
|
||||
|
|
@ -365,6 +382,23 @@ beaker.session.auto = false
|
|||
search.module = rhodecode.lib.index.whoosh
|
||||
search.location = %(here)s/data/index
|
||||
|
||||
########################################
|
||||
### CHANNELSTREAM CONFIG ####
|
||||
########################################
|
||||
## channelstream enables persistent connections and live notification
|
||||
## in the system. It's also used by the chat system
|
||||
|
||||
channelstream.enabled = true
|
||||
## location of channelstream server on the backend
|
||||
channelstream.server = 127.0.0.1:9800
|
||||
## location of the channelstream server from outside world
|
||||
## most likely this would be an http server special backend URL, that handles
|
||||
## websocket connections see nginx example for config
|
||||
channelstream.ws_url = ws://rhodecode.yourserver.com/_channelstream
|
||||
channelstream.secret = secret
|
||||
channelstream.history.location = %(here)s/channelstream_history
|
||||
|
||||
|
||||
###################################
|
||||
## APPENLIGHT CONFIG ##
|
||||
###################################
|
||||
|
|
@ -436,8 +470,9 @@ set debug = false
|
|||
### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
|
||||
#########################################################
|
||||
#sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
|
||||
sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
|
||||
#sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
|
||||
#sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
|
||||
sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
|
||||
|
||||
# see sqlalchemy docs for other advanced settings
|
||||
|
||||
|
|
@ -483,12 +518,37 @@ vcs.server = localhost:9900
|
|||
vcs.server.log_level = info
|
||||
## Start VCSServer with this instance as a subprocess, usefull for development
|
||||
vcs.start_server = false
|
||||
|
||||
## List of enabled VCS backends, available options are:
|
||||
## `hg` - mercurial
|
||||
## `git` - git
|
||||
## `svn` - subversion
|
||||
vcs.backends = hg, git, svn
|
||||
|
||||
vcs.connection_timeout = 3600
|
||||
## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
|
||||
## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
|
||||
#vcs.svn.compatible_version = pre-1.8-compatible
|
||||
|
||||
|
||||
############################################################
|
||||
### Subversion proxy support (mod_dav_svn) ###
|
||||
### Maps RhodeCode repo groups into SVN paths for Apache ###
|
||||
############################################################
|
||||
## Enable or disable the config file generation.
|
||||
svn.proxy.generate_config = false
|
||||
## Generate config file with `SVNListParentPath` set to `On`.
|
||||
svn.proxy.list_parent_path = true
|
||||
## Set location and file name of generated config file.
|
||||
svn.proxy.config_file_path = %(here)s/mod_dav_svn.conf
|
||||
## File system path to the directory containing the repositories served by
|
||||
## RhodeCode.
|
||||
svn.proxy.parent_path_root = /path/to/repo_store
|
||||
## Used as a prefix to the <Location> block in the generated config file. In
|
||||
## most cases it should be set to `/`.
|
||||
svn.proxy.location_root = /
|
||||
|
||||
|
||||
################################
|
||||
### LOGGING CONFIGURATION ####
|
||||
################################
|
||||
|
|
|
|||
|
|
@ -123,8 +123,9 @@ let
|
|||
# pkgs/default.nix?
|
||||
passthru = {
|
||||
inherit
|
||||
pythonLocalOverrides
|
||||
myPythonPackagesUnfix;
|
||||
linkNodeModules
|
||||
myPythonPackagesUnfix
|
||||
pythonLocalOverrides;
|
||||
pythonPackages = self;
|
||||
};
|
||||
|
||||
|
|
@ -165,6 +166,7 @@ let
|
|||
ln -s ${self.supervisor}/bin/supervisor* $out/bin/
|
||||
ln -s ${self.gunicorn}/bin/gunicorn $out/bin/
|
||||
ln -s ${self.PasteScript}/bin/paster $out/bin/
|
||||
ln -s ${self.channelstream}/bin/channelstream $out/bin/
|
||||
ln -s ${self.pyramid}/bin/* $out/bin/ #*/
|
||||
|
||||
# rhodecode-tools
|
||||
|
|
|
|||
6
docs/_templates/footer.html
vendored
Normal file
6
docs/_templates/footer.html
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "!footer.html" %}
|
||||
|
||||
{% block extrafooter %}
|
||||
<br/>
|
||||
Documentation defects and suggestions can be submitted <a href="https://issues.rhodecode.com/projects/documentation">here</a>
|
||||
{% endblock %}
|
||||
|
|
@ -9,9 +9,9 @@ Here is a sample configuration file for using Apache as a reverse proxy.
|
|||
ServerName hg.myserver.com
|
||||
ServerAlias hg.myserver.com
|
||||
|
||||
## uncomment root directive if you want to serve static files by
|
||||
## Apache requires static_files = false in .ini file
|
||||
#DocumentRoot /path/to/rhodecode/installation/public
|
||||
## uncomment to serve static files by Apache
|
||||
## ProxyPass /_static/rhodecode !
|
||||
## Alias /_static/rhodecode /path/to/.rccontrol/enterprise-1/static
|
||||
|
||||
<Proxy *>
|
||||
Order allow,deny
|
||||
|
|
|
|||
|
|
@ -16,17 +16,18 @@ Use the following example to configure Apache to use a URL prefix.
|
|||
In addition to the regular Apache setup you will need to add the following
|
||||
lines into the ``rhodecode.ini`` file.
|
||||
|
||||
* In the the ``[app:main]`` section of your ``rhodecode.ini`` file add the
|
||||
following line.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
filter-with = proxy-prefix
|
||||
|
||||
* At the end of the ``rhodecode.ini`` file add the following section.
|
||||
* Above ``[app:main]`` section of the ``rhodecode.ini`` file add the
|
||||
following section if it doesn't exist yet.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[filter:proxy-prefix]
|
||||
use = egg:PasteDeploy#prefix
|
||||
prefix = /<someprefix> # Change <someprefix> into your chosen prefix
|
||||
|
||||
* In the the ``[app:main]`` section of your ``rhodecode.ini`` file add the
|
||||
following line.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
filter-with = proxy-prefix
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ then work on restoring any specific setup changes you had made.
|
|||
:ref:`indexing-ref` section for details.
|
||||
* To reconfigure any extensions, copy the backed up extensions into the
|
||||
:file:`/home/{user}/.rccontrol/{instance-id}/rcextensions` and also specify
|
||||
any custom hooks if necessary. See the :ref:`integrations-ref` section for
|
||||
any custom hooks if necessary. See the :ref:`extensions-hooks-ref` section for
|
||||
details.
|
||||
|
||||
.. _Schrödinger's Backup: http://novabackup.novastor.com/blog/schrodingers-backup-good-bad-backup/
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ Use the following example to configure Nginx as a your web server.
|
|||
|
||||
.. code-block:: nginx
|
||||
|
||||
log_format log_custom '$remote_addr - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" '
|
||||
'$request_time $upstream_response_time $pipe';
|
||||
|
||||
upstream rc {
|
||||
|
||||
server 127.0.0.1:10002;
|
||||
|
|
@ -14,12 +19,12 @@ Use the following example to configure Nginx as a your web server.
|
|||
# server 127.0.0.1:10004;
|
||||
}
|
||||
|
||||
## gist alias
|
||||
## gist alias server, for serving nicer GIST urls
|
||||
|
||||
server {
|
||||
listen 443;
|
||||
server_name gist.myserver.com;
|
||||
access_log /var/log/nginx/gist.access.log;
|
||||
access_log /var/log/nginx/gist.access.log log_custom;
|
||||
error_log /var/log/nginx/gist.error.log;
|
||||
|
||||
ssl on;
|
||||
|
|
@ -28,23 +33,36 @@ Use the following example to configure Nginx as a your web server.
|
|||
|
||||
ssl_session_timeout 5m;
|
||||
|
||||
ssl_protocols SSLv3 TLSv1;
|
||||
ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
|
||||
|
||||
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
|
||||
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
|
||||
#ssl_dhparam /etc/nginx/ssl/dhparam.pem;
|
||||
|
||||
rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1;
|
||||
rewrite (.*) https://rhodecode.myserver.com/_admin/gists;
|
||||
}
|
||||
|
||||
## HTTP to HTTPS rewrite
|
||||
server {
|
||||
listen 443;
|
||||
listen 80;
|
||||
server_name rhodecode.myserver.com;
|
||||
access_log /var/log/nginx/rhodecode.access.log;
|
||||
error_log /var/log/nginx/rhodecode.error.log;
|
||||
|
||||
if ($http_host = rhodecode.myserver.com) {
|
||||
rewrite (.*) https://rhodecode.myserver.com$1 permanent;
|
||||
}
|
||||
}
|
||||
|
||||
## MAIN SSL enabled server
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name rhodecode.myserver.com;
|
||||
|
||||
access_log /var/log/nginx/rhodecode.access.log log_custom;
|
||||
error_log /var/log/nginx/rhodecode.error.log;
|
||||
|
||||
ssl on;
|
||||
ssl_certificate rhodecode.myserver.com.crt;
|
||||
|
|
@ -52,21 +70,51 @@ Use the following example to configure Nginx as a your web server.
|
|||
|
||||
ssl_session_timeout 5m;
|
||||
|
||||
ssl_protocols SSLv3 TLSv1;
|
||||
ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
|
||||
|
||||
## uncomment root directive if you want to serve static files by nginx
|
||||
## requires static_files = false in .ini file
|
||||
# root /path/to/rhodecode/installation/public;
|
||||
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
|
||||
#ssl_dhparam /etc/nginx/ssl/dhparam.pem;
|
||||
|
||||
include /etc/nginx/proxy.conf;
|
||||
include /etc/nginx/proxy.conf;
|
||||
|
||||
## serve static files by nginx, recommended
|
||||
# location /_static/rhodecode {
|
||||
# alias /path/to/.rccontrol/enterprise-1/static;
|
||||
# }
|
||||
|
||||
## channel stream live components
|
||||
location /_channelstream {
|
||||
rewrite /_channelstream/(.*) /$1 break;
|
||||
proxy_pass http://127.0.0.1:9800;
|
||||
|
||||
proxy_connect_timeout 10;
|
||||
proxy_send_timeout 10m;
|
||||
proxy_read_timeout 10m;
|
||||
tcp_nodelay off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Url-Scheme $scheme;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
gzip off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri @rhode;
|
||||
}
|
||||
|
||||
location @rhode {
|
||||
proxy_pass http://rc;
|
||||
}
|
||||
}
|
||||
location @rhode {
|
||||
proxy_pass http://rc;
|
||||
}
|
||||
|
||||
## custom 502 error page
|
||||
error_page 502 /502.html;
|
||||
location = /502.html {
|
||||
root /path/to/.rccontrol/enterprise-1/static;
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,16 @@ Use the following example to configure Nginx to use a URL prefix.
|
|||
}
|
||||
|
||||
In addition to the Nginx configuration you will need to add the following
|
||||
lines into the ``rhodecode.ini`` file.
|
||||
lines (if they not exist) into the ``rhodecode.ini`` file.
|
||||
|
||||
* Above ``[app:main]`` section of the ``rhodecode.ini`` file add the
|
||||
following section if it doesn't exist yet.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[filter:proxy-prefix]
|
||||
use = egg:PasteDeploy#prefix
|
||||
prefix = /<someprefix> # Change <someprefix> into your chosen prefix
|
||||
|
||||
* In the the ``[app:main]`` section of your ``rhodecode.ini`` file add the
|
||||
following line.
|
||||
|
|
@ -24,10 +33,4 @@ lines into the ``rhodecode.ini`` file.
|
|||
|
||||
filter-with = proxy-prefix
|
||||
|
||||
* At the end of the ``rhodecode.ini`` file add the following section.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[filter:proxy-prefix]
|
||||
use = egg:PasteDeploy#prefix
|
||||
prefix = /<someprefix> # Change <someprefix> into your chosen prefix
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ Example Usage
|
|||
-------------
|
||||
|
||||
To use the extra fields in an extension, see the example below. For more
|
||||
information and examples, see the :ref:`integrations-ref` section.
|
||||
information and examples, see the :ref:`extensions-hooks-ref` section.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ account permissions.
|
|||
# Use this example to change user permissions
|
||||
In [1]: adminuser = User.get_by_username('username')
|
||||
In [2]: adminuser.admin = True
|
||||
In [3]: Session.add(adminuser);Session().commit()
|
||||
In [3]: Session().add(adminuser);Session().commit()
|
||||
In [4]: exit()
|
||||
|
||||
Set to read global ``.hgrc`` file
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ following examples. For more |svn| information, see the `Subversion Red Book`_
|
|||
.. code-block:: bash
|
||||
|
||||
# To clone a repository
|
||||
svn clone http://my-svn-server.example.com/my-svn-repo
|
||||
svn checkout http://my-svn-server.example.com/my-svn-repo
|
||||
|
||||
# svn commit
|
||||
svn commit
|
||||
|
|
|
|||
2639
docs/api/api.rst
2639
docs/api/api.rst
File diff suppressed because it is too large
Load diff
77
docs/api/methods/deprecated-methods.rst
Normal file
77
docs/api/methods/deprecated-methods.rst
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
.. _deprecated-methods-ref:
|
||||
|
||||
deprecated methods
|
||||
=================
|
||||
|
||||
changeset_comment
|
||||
-----------------
|
||||
|
||||
.. py:function:: changeset_comment(apiuser, repoid, revision, message, userid=<Optional:<OptionalAttr:apiuser>>, status=<Optional:None>)
|
||||
|
||||
.. deprecated:: 3.4.0
|
||||
|
||||
Please use method `comment_commit` instead.
|
||||
|
||||
|
||||
Set a changeset comment, and optionally change the status of the
|
||||
changeset.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param revision: Specify the revision for which to set a comment.
|
||||
:type revision: str
|
||||
:param message: The comment text.
|
||||
:type message: str
|
||||
:param userid: Set the user name of the comment creator.
|
||||
:type userid: Optional(str or int)
|
||||
:param status: Set the comment status. The following are valid options:
|
||||
* not_reviewed
|
||||
* approved
|
||||
* rejected
|
||||
* under_review
|
||||
:type status: str
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"id" : <id_given_in_input>,
|
||||
"result" : {
|
||||
"msg": "Commented on commit `<revision>` for repository `<repoid>`",
|
||||
"status_change": null or <status>,
|
||||
"success": true
|
||||
},
|
||||
"error" : null
|
||||
}
|
||||
|
||||
|
||||
get_locks
|
||||
---------
|
||||
|
||||
.. py:function:: get_locks(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
.. deprecated:: 4.0.0
|
||||
|
||||
Please use method `get_user_locks` instead.
|
||||
|
||||
None
|
||||
|
||||
|
||||
show_ip
|
||||
-------
|
||||
|
||||
.. py:function:: show_ip(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
.. deprecated:: 4.0.0
|
||||
|
||||
Please use method `get_ip` instead.
|
||||
|
||||
None
|
||||
|
||||
|
||||
121
docs/api/methods/gist-methods.rst
Normal file
121
docs/api/methods/gist-methods.rst
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
.. _gist-methods-ref:
|
||||
|
||||
gist methods
|
||||
=================
|
||||
|
||||
create_gist
|
||||
-----------
|
||||
|
||||
.. py:function:: create_gist(apiuser, files, gistid=<Optional:None>, owner=<Optional:<OptionalAttr:apiuser>>, gist_type=<Optional:u'public'>, lifetime=<Optional:-1>, acl_level=<Optional:u'acl_public'>, description=<Optional:''>)
|
||||
|
||||
Creates a new Gist.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param files: files to be added to the gist. The data structure has
|
||||
to match the following example::
|
||||
|
||||
{'filename1': {'content':'...'}, 'filename2': {'content':'...'}}
|
||||
|
||||
:type files: dict
|
||||
:param gistid: Set a custom id for the gist
|
||||
:type gistid: Optional(str)
|
||||
:param owner: Set the gist owner, defaults to api method caller
|
||||
:type owner: Optional(str or int)
|
||||
:param gist_type: type of gist ``public`` or ``private``
|
||||
:type gist_type: Optional(str)
|
||||
:param lifetime: time in minutes of gist lifetime
|
||||
:type lifetime: Optional(int)
|
||||
:param acl_level: acl level for this gist, can be
|
||||
``acl_public`` or ``acl_private`` If the value is set to
|
||||
``acl_private`` only logged in users are able to access this gist.
|
||||
If not set it defaults to ``acl_public``.
|
||||
:type acl_level: Optional(str)
|
||||
:param description: gist description
|
||||
:type description: Optional(str)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "created new gist",
|
||||
"gist": {}
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to create gist"
|
||||
}
|
||||
|
||||
|
||||
delete_gist
|
||||
-----------
|
||||
|
||||
.. py:function:: delete_gist(apiuser, gistid)
|
||||
|
||||
Deletes existing gist
|
||||
|
||||
:param apiuser: filled automatically from apikey
|
||||
:type apiuser: AuthUser
|
||||
:param gistid: id of gist to delete
|
||||
:type gistid: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"deleted gist ID: <gist_id>",
|
||||
"gist": null
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to delete gist ID:<gist_id>"
|
||||
}
|
||||
|
||||
|
||||
get_gist
|
||||
--------
|
||||
|
||||
.. py:function:: get_gist(apiuser, gistid, content=<Optional:False>)
|
||||
|
||||
Get the specified gist, based on the gist ID.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param gistid: Set the id of the private or public gist
|
||||
:type gistid: str
|
||||
:param content: Return the gist content. Default is false.
|
||||
:type content: Optional(bool)
|
||||
|
||||
|
||||
get_gists
|
||||
---------
|
||||
|
||||
.. py:function:: get_gists(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Get all gists for given user. If userid is empty returned gists
|
||||
are for user who called the api
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param userid: user to get gists for
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
|
||||
71
docs/api/methods/license-methods.rst
Normal file
71
docs/api/methods/license-methods.rst
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
.. _license-methods-ref:
|
||||
|
||||
license methods
|
||||
=================
|
||||
|
||||
get_license_info (EE only)
|
||||
----------------
|
||||
|
||||
.. py:function:: get_license_info(apiuser)
|
||||
|
||||
Returns the |RCE| license information.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
'rhodecode_version': <rhodecode version>,
|
||||
'token': <license token>,
|
||||
'issued_to': <license owner>,
|
||||
'issued_on': <license issue date>,
|
||||
'expires_on': <license expiration date>,
|
||||
'type': <license type>,
|
||||
'users_limit': <license users limit>,
|
||||
'key': <license key>
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
set_license_key (EE only)
|
||||
---------------
|
||||
|
||||
.. py:function:: set_license_key(apiuser, key)
|
||||
|
||||
Sets the |RCE| license key.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param key: This is the license key to be set.
|
||||
:type key: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "updated license information",
|
||||
"key": <key>
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"license key is not valid"
|
||||
or
|
||||
"trial licenses cannot be uploaded"
|
||||
or
|
||||
"error occurred while updating license"
|
||||
}
|
||||
|
||||
|
||||
344
docs/api/methods/pull-request-methods.rst
Normal file
344
docs/api/methods/pull-request-methods.rst
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
.. _pull-request-methods-ref:
|
||||
|
||||
pull_request methods
|
||||
=================
|
||||
|
||||
close_pull_request
|
||||
------------------
|
||||
|
||||
.. py:function:: close_pull_request(apiuser, repoid, pullrequestid, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Close the pull request specified by `pullrequestid`.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Repository name or repository ID to which the pull
|
||||
request belongs.
|
||||
:type repoid: str or int
|
||||
:param pullrequestid: ID of the pull request to be closed.
|
||||
:type pullrequestid: int
|
||||
:param userid: Close the pull request as this user.
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"id": <id_given_in_input>,
|
||||
"result":
|
||||
{
|
||||
"pull_request_id": "<int>",
|
||||
"closed": "<bool>"
|
||||
},
|
||||
"error": null
|
||||
|
||||
|
||||
comment_pull_request
|
||||
--------------------
|
||||
|
||||
.. py:function:: comment_pull_request(apiuser, repoid, pullrequestid, message=<Optional:None>, status=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Comment on the pull request specified with the `pullrequestid`,
|
||||
in the |repo| specified by the `repoid`, and optionally change the
|
||||
review status.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param pullrequestid: The pull request ID.
|
||||
:type pullrequestid: int
|
||||
:param message: The text content of the comment.
|
||||
:type message: str
|
||||
:param status: (**Optional**) Set the approval status of the pull
|
||||
request. Valid options are:
|
||||
* not_reviewed
|
||||
* approved
|
||||
* rejected
|
||||
* under_review
|
||||
:type status: str
|
||||
:param userid: Comment on the pull request as this user
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result :
|
||||
{
|
||||
"pull_request_id": "<Integer>",
|
||||
"comment_id": "<Integer>"
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
create_pull_request
|
||||
-------------------
|
||||
|
||||
.. py:function:: create_pull_request(apiuser, source_repo, target_repo, source_ref, target_ref, title, description=<Optional:''>, reviewers=<Optional:None>)
|
||||
|
||||
Creates a new pull request.
|
||||
|
||||
Accepts refs in the following formats:
|
||||
|
||||
* branch:<branch_name>:<sha>
|
||||
* branch:<branch_name>
|
||||
* bookmark:<bookmark_name>:<sha> (Mercurial only)
|
||||
* bookmark:<bookmark_name> (Mercurial only)
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param source_repo: Set the source repository name.
|
||||
:type source_repo: str
|
||||
:param target_repo: Set the target repository name.
|
||||
:type target_repo: str
|
||||
:param source_ref: Set the source ref name.
|
||||
:type source_ref: str
|
||||
:param target_ref: Set the target ref name.
|
||||
:type target_ref: str
|
||||
:param title: Set the pull request title.
|
||||
:type title: str
|
||||
:param description: Set the pull request description.
|
||||
:type description: Optional(str)
|
||||
:param reviewers: Set the new pull request reviewers list.
|
||||
:type reviewers: Optional(list)
|
||||
|
||||
|
||||
get_pull_request
|
||||
----------------
|
||||
|
||||
.. py:function:: get_pull_request(apiuser, repoid, pullrequestid)
|
||||
|
||||
Get a pull request based on the given ID.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Repository name or repository ID from where the pull
|
||||
request was opened.
|
||||
:type repoid: str or int
|
||||
:param pullrequestid: ID of the requested pull request.
|
||||
:type pullrequestid: int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"id": <id_given_in_input>,
|
||||
"result":
|
||||
{
|
||||
"pull_request_id": "<pull_request_id>",
|
||||
"url": "<url>",
|
||||
"title": "<title>",
|
||||
"description": "<description>",
|
||||
"status" : "<status>",
|
||||
"created_on": "<date_time_created>",
|
||||
"updated_on": "<date_time_updated>",
|
||||
"commit_ids": [
|
||||
...
|
||||
"<commit_id>",
|
||||
"<commit_id>",
|
||||
...
|
||||
],
|
||||
"review_status": "<review_status>",
|
||||
"mergeable": {
|
||||
"status": "<bool>",
|
||||
"message": "<message>",
|
||||
},
|
||||
"source": {
|
||||
"clone_url": "<clone_url>",
|
||||
"repository": "<repository_name>",
|
||||
"reference":
|
||||
{
|
||||
"name": "<name>",
|
||||
"type": "<type>",
|
||||
"commit_id": "<commit_id>",
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"clone_url": "<clone_url>",
|
||||
"repository": "<repository_name>",
|
||||
"reference":
|
||||
{
|
||||
"name": "<name>",
|
||||
"type": "<type>",
|
||||
"commit_id": "<commit_id>",
|
||||
}
|
||||
},
|
||||
"author": <user_obj>,
|
||||
"reviewers": [
|
||||
...
|
||||
{
|
||||
"user": "<user_obj>",
|
||||
"review_status": "<review_status>",
|
||||
}
|
||||
...
|
||||
]
|
||||
},
|
||||
"error": null
|
||||
|
||||
|
||||
get_pull_requests
|
||||
-----------------
|
||||
|
||||
.. py:function:: get_pull_requests(apiuser, repoid, status=<Optional:'new'>)
|
||||
|
||||
Get all pull requests from the repository specified in `repoid`.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param status: Only return pull requests with the specified status.
|
||||
Valid options are.
|
||||
* ``new`` (default)
|
||||
* ``open``
|
||||
* ``closed``
|
||||
:type status: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"id": <id_given_in_input>,
|
||||
"result":
|
||||
[
|
||||
...
|
||||
{
|
||||
"pull_request_id": "<pull_request_id>",
|
||||
"url": "<url>",
|
||||
"title" : "<title>",
|
||||
"description": "<description>",
|
||||
"status": "<status>",
|
||||
"created_on": "<date_time_created>",
|
||||
"updated_on": "<date_time_updated>",
|
||||
"commit_ids": [
|
||||
...
|
||||
"<commit_id>",
|
||||
"<commit_id>",
|
||||
...
|
||||
],
|
||||
"review_status": "<review_status>",
|
||||
"mergeable": {
|
||||
"status": "<bool>",
|
||||
"message: "<message>",
|
||||
},
|
||||
"source": {
|
||||
"clone_url": "<clone_url>",
|
||||
"reference":
|
||||
{
|
||||
"name": "<name>",
|
||||
"type": "<type>",
|
||||
"commit_id": "<commit_id>",
|
||||
}
|
||||
},
|
||||
"target": {
|
||||
"clone_url": "<clone_url>",
|
||||
"reference":
|
||||
{
|
||||
"name": "<name>",
|
||||
"type": "<type>",
|
||||
"commit_id": "<commit_id>",
|
||||
}
|
||||
},
|
||||
"author": <user_obj>,
|
||||
"reviewers": [
|
||||
...
|
||||
{
|
||||
"user": "<user_obj>",
|
||||
"review_status": "<review_status>",
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
...
|
||||
],
|
||||
"error": null
|
||||
|
||||
|
||||
merge_pull_request
|
||||
------------------
|
||||
|
||||
.. py:function:: merge_pull_request(apiuser, repoid, pullrequestid, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Merge the pull request specified by `pullrequestid` into its target
|
||||
repository.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The Repository name or repository ID of the
|
||||
target repository to which the |pr| is to be merged.
|
||||
:type repoid: str or int
|
||||
:param pullrequestid: ID of the pull request which shall be merged.
|
||||
:type pullrequestid: int
|
||||
:param userid: Merge the pull request as this user.
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
"id": <id_given_in_input>,
|
||||
"result":
|
||||
{
|
||||
"executed": "<bool>",
|
||||
"failure_reason": "<int>",
|
||||
"merge_commit_id": "<merge_commit_id>",
|
||||
"possible": "<bool>"
|
||||
},
|
||||
"error": null
|
||||
|
||||
|
||||
update_pull_request
|
||||
-------------------
|
||||
|
||||
.. py:function:: update_pull_request(apiuser, repoid, pullrequestid, title=<Optional:''>, description=<Optional:''>, reviewers=<Optional:None>, update_commits=<Optional:None>, close_pull_request=<Optional:None>)
|
||||
|
||||
Updates a pull request.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param pullrequestid: The pull request ID.
|
||||
:type pullrequestid: int
|
||||
:param title: Set the pull request title.
|
||||
:type title: str
|
||||
:param description: Update pull request description.
|
||||
:type description: Optional(str)
|
||||
:param reviewers: Update pull request reviewers list with new value.
|
||||
:type reviewers: Optional(list)
|
||||
:param update_commits: Trigger update of commits for this pull request
|
||||
:type: update_commits: Optional(bool)
|
||||
:param close_pull_request: Close this pull request with rejected state
|
||||
:type: close_pull_request: Optional(bool)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result :
|
||||
{
|
||||
"msg": "Updated pull request `63`",
|
||||
"pull_request": <pull_request_object>,
|
||||
"updated_reviewers": {
|
||||
"added": [
|
||||
"username"
|
||||
],
|
||||
"removed": []
|
||||
},
|
||||
"updated_commits": {
|
||||
"added": [
|
||||
"<sha1_hash>"
|
||||
],
|
||||
"common": [
|
||||
"<sha1_hash>",
|
||||
"<sha1_hash>",
|
||||
],
|
||||
"removed": []
|
||||
}
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
350
docs/api/methods/repo-group-methods.rst
Normal file
350
docs/api/methods/repo-group-methods.rst
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
.. _repo-group-methods-ref:
|
||||
|
||||
repo_group methods
|
||||
=================
|
||||
|
||||
create_repo_group
|
||||
-----------------
|
||||
|
||||
.. py:function:: create_repo_group(apiuser, group_name, description=<Optional:''>, owner=<Optional:<OptionalAttr:apiuser>>, copy_permissions=<Optional:False>)
|
||||
|
||||
Creates a repository group.
|
||||
|
||||
* If the repository group name contains "/", all the required repository
|
||||
groups will be created.
|
||||
|
||||
For example "foo/bar/baz" will create |repo| groups "foo" and "bar"
|
||||
(with "foo" as parent). It will also create the "baz" repository
|
||||
with "bar" as |repo| group.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param group_name: Set the repository group name.
|
||||
:type group_name: str
|
||||
:param description: Set the |repo| group description.
|
||||
:type description: str
|
||||
:param owner: Set the |repo| group owner.
|
||||
:type owner: str
|
||||
:param copy_permissions:
|
||||
:type copy_permissions:
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "Created new repo group `<repo_group_name>`"
|
||||
"repo_group": <repogroup_object>
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
failed to create repo group `<repogroupid>`
|
||||
}
|
||||
|
||||
|
||||
delete_repo_group
|
||||
-----------------
|
||||
|
||||
.. py:function:: delete_repo_group(apiuser, repogroupid)
|
||||
|
||||
Deletes a |repo| group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: Set the name or ID of repository group to be
|
||||
deleted.
|
||||
:type repogroupid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
'msg': 'deleted repo group ID:<repogroupid> <repogroupname>
|
||||
'repo_group': null
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to delete repo group ID:<repogroupid> <repogroupname>"
|
||||
}
|
||||
|
||||
|
||||
get_repo_group
|
||||
--------------
|
||||
|
||||
.. py:function:: get_repo_group(apiuser, repogroupid)
|
||||
|
||||
Return the specified |repo| group, along with permissions,
|
||||
and repositories inside the group
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: Specify the name of ID of the repository group.
|
||||
:type repogroupid: str or int
|
||||
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": repo-group-id,
|
||||
"result": {
|
||||
"group_description": "repo group description",
|
||||
"group_id": 14,
|
||||
"group_name": "group name",
|
||||
"members": [
|
||||
{
|
||||
"name": "super-admin-username",
|
||||
"origin": "super-admin",
|
||||
"permission": "group.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "owner-name",
|
||||
"origin": "owner",
|
||||
"permission": "group.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "user-group-name",
|
||||
"origin": "permission",
|
||||
"permission": "group.write",
|
||||
"type": "user_group"
|
||||
}
|
||||
],
|
||||
"owner": "owner-name",
|
||||
"parent_group": null,
|
||||
"repositories": [ repo-list ]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get_repo_groups
|
||||
---------------
|
||||
|
||||
.. py:function:: get_repo_groups(apiuser)
|
||||
|
||||
Returns all repository groups.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
||||
|
||||
grant_user_group_permission_to_repo_group
|
||||
-----------------------------------------
|
||||
|
||||
.. py:function:: grant_user_group_permission_to_repo_group(apiuser, repogroupid, usergroupid, perm, apply_to_children=<Optional:'none'>)
|
||||
|
||||
Grant permission for a user group on given repository group, or update
|
||||
existing permissions if found.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo| group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: Set the name or id of repository group
|
||||
:type repogroupid: str or int
|
||||
:param usergroupid: id of usergroup
|
||||
:type usergroupid: str or int
|
||||
:param perm: (group.(none|read|write|admin))
|
||||
:type perm: str
|
||||
:param apply_to_children: 'none', 'repos', 'groups', 'all'
|
||||
:type apply_to_children: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`",
|
||||
"success": true
|
||||
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`"
|
||||
}
|
||||
|
||||
|
||||
grant_user_permission_to_repo_group
|
||||
-----------------------------------
|
||||
|
||||
.. py:function:: grant_user_permission_to_repo_group(apiuser, repogroupid, userid, perm, apply_to_children=<Optional:'none'>)
|
||||
|
||||
Grant permission for a user on the given repository group, or update
|
||||
existing permissions if found.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: Set the name or ID of repository group.
|
||||
:type repogroupid: str or int
|
||||
:param userid: Set the user name.
|
||||
:type userid: str
|
||||
:param perm: (group.(none|read|write|admin))
|
||||
:type perm: str
|
||||
:param apply_to_children: 'none', 'repos', 'groups', 'all'
|
||||
:type apply_to_children: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "Granted perm: `<perm>` (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`"
|
||||
}
|
||||
|
||||
|
||||
revoke_user_group_permission_from_repo_group
|
||||
--------------------------------------------
|
||||
|
||||
.. py:function:: revoke_user_group_permission_from_repo_group(apiuser, repogroupid, usergroupid, apply_to_children=<Optional:'none'>)
|
||||
|
||||
Revoke permission for user group on given repository.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo| group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: name or id of repository group
|
||||
:type repogroupid: str or int
|
||||
:param usergroupid:
|
||||
:param apply_to_children: 'none', 'repos', 'groups', 'all'
|
||||
:type apply_to_children: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "Revoked perm (recursive:<apply_to_children>) for user group: `<usersgroupname>` in repo group: `<repo_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to edit permission for user group: `<usergroup>` in repo group: `<repo_group_name>`"
|
||||
}
|
||||
|
||||
|
||||
revoke_user_permission_from_repo_group
|
||||
--------------------------------------
|
||||
|
||||
.. py:function:: revoke_user_permission_from_repo_group(apiuser, repogroupid, userid, apply_to_children=<Optional:'none'>)
|
||||
|
||||
Revoke permission for a user in a given repository group.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo| group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: Set the name or ID of the repository group.
|
||||
:type repogroupid: str or int
|
||||
:param userid: Set the user name to revoke.
|
||||
:type userid: str
|
||||
:param apply_to_children: 'none', 'repos', 'groups', 'all'
|
||||
:type apply_to_children: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "Revoked perm (recursive:<apply_to_children>) for user: `<username>` in repo group: `<repo_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to edit permission for user: `<userid>` in repo group: `<repo_group_name>`"
|
||||
}
|
||||
|
||||
|
||||
update_repo_group
|
||||
-----------------
|
||||
|
||||
.. py:function:: update_repo_group(apiuser, repogroupid, group_name=<Optional:''>, description=<Optional:''>, owner=<Optional:<OptionalAttr:apiuser>>, parent=<Optional:None>, enable_locking=<Optional:False>)
|
||||
|
||||
Updates repository group with the details given.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repogroupid: Set the ID of repository group.
|
||||
:type repogroupid: str or int
|
||||
:param group_name: Set the name of the |repo| group.
|
||||
:type group_name: str
|
||||
:param description: Set a description for the group.
|
||||
:type description: str
|
||||
:param owner: Set the |repo| group owner.
|
||||
:type owner: str
|
||||
:param parent: Set the |repo| group parent.
|
||||
:type parent: str or int
|
||||
:param enable_locking: Enable |repo| locking. The default is false.
|
||||
:type enable_locking: bool
|
||||
|
||||
|
||||
967
docs/api/methods/repo-methods.rst
Normal file
967
docs/api/methods/repo-methods.rst
Normal file
|
|
@ -0,0 +1,967 @@
|
|||
.. _repo-methods-ref:
|
||||
|
||||
repo methods
|
||||
=================
|
||||
|
||||
add_field_to_repo
|
||||
-----------------
|
||||
|
||||
.. py:function:: add_field_to_repo(apiuser, repoid, key, label=<Optional:''>, description=<Optional:''>)
|
||||
|
||||
Adds an extra field to a repository.
|
||||
|
||||
This command can only be run using an |authtoken| with at least
|
||||
write permissions to the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository id.
|
||||
:type repoid: str or int
|
||||
:param key: Create a unique field key for this repository.
|
||||
:type key: str
|
||||
:param label:
|
||||
:type label: Optional(str)
|
||||
:param description:
|
||||
:type description: Optional(str)
|
||||
|
||||
|
||||
comment_commit
|
||||
--------------
|
||||
|
||||
.. py:function:: comment_commit(apiuser, repoid, commit_id, message, userid=<Optional:<OptionalAttr:apiuser>>, status=<Optional:None>)
|
||||
|
||||
Set a commit comment, and optionally change the status of the commit.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param commit_id: Specify the commit_id for which to set a comment.
|
||||
:type commit_id: str
|
||||
:param message: The comment text.
|
||||
:type message: str
|
||||
:param userid: Set the user name of the comment creator.
|
||||
:type userid: Optional(str or int)
|
||||
:param status: status, one of 'not_reviewed', 'approved', 'rejected',
|
||||
'under_review'
|
||||
:type status: str
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"id" : <id_given_in_input>,
|
||||
"result" : {
|
||||
"msg": "Commented on commit `<commit_id>` for repository `<repoid>`",
|
||||
"status_change": null or <status>,
|
||||
"success": true
|
||||
},
|
||||
"error" : null
|
||||
}
|
||||
|
||||
|
||||
create_repo
|
||||
-----------
|
||||
|
||||
.. py:function:: create_repo(apiuser, repo_name, repo_type, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, copy_permissions=<Optional:False>)
|
||||
|
||||
Creates a repository.
|
||||
|
||||
* If the repository name contains "/", all the required repository
|
||||
groups will be created.
|
||||
|
||||
For example "foo/bar/baz" will create |repo| groups "foo" and "bar"
|
||||
(with "foo" as parent). It will also create the "baz" repository
|
||||
with "bar" as |repo| group.
|
||||
|
||||
This command can only be run using an |authtoken| with at least
|
||||
write permissions to the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repo_name: Set the repository name.
|
||||
:type repo_name: str
|
||||
:param repo_type: Set the repository type; 'hg','git', or 'svn'.
|
||||
:type repo_type: str
|
||||
:param owner: user_id or username
|
||||
:type owner: Optional(str)
|
||||
:param description: Set the repository description.
|
||||
:type description: Optional(str)
|
||||
:param private:
|
||||
:type private: bool
|
||||
:param clone_uri:
|
||||
:type clone_uri: str
|
||||
:param landing_rev: <rev_type>:<rev>
|
||||
:type landing_rev: str
|
||||
:param enable_locking:
|
||||
:type enable_locking: bool
|
||||
:param enable_downloads:
|
||||
:type enable_downloads: bool
|
||||
:param enable_statistics:
|
||||
:type enable_statistics: bool
|
||||
:param copy_permissions: Copy permission from group in which the
|
||||
repository is being created.
|
||||
:type copy_permissions: bool
|
||||
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg": "Created new repository `<reponame>`",
|
||||
"success": true,
|
||||
"task": "<celery task id or None if done sync>"
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
'failed to create repository `<repo_name>`
|
||||
}
|
||||
|
||||
|
||||
delete_repo
|
||||
-----------
|
||||
|
||||
.. py:function:: delete_repo(apiuser, repoid, forks=<Optional:''>)
|
||||
|
||||
Deletes a repository.
|
||||
|
||||
* When the `forks` parameter is set it's possible to detach or delete
|
||||
forks of deleted repository.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param forks: Set to `detach` or `delete` forks from the |repo|.
|
||||
:type forks: Optional(str)
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg": "Deleted repository `<reponame>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
fork_repo
|
||||
---------
|
||||
|
||||
.. py:function:: fork_repo(apiuser, repoid, fork_name, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, copy_permissions=<Optional:False>, private=<Optional:False>, landing_rev=<Optional:'rev:tip'>)
|
||||
|
||||
Creates a fork of the specified |repo|.
|
||||
|
||||
* If using |RCE| with Celery this will immediately return a success
|
||||
message, even though the fork will be created asynchronously.
|
||||
|
||||
This command can only be run using an |authtoken| with fork
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param fork_name: Set the fork name.
|
||||
:type fork_name: str
|
||||
:param owner: Set the fork owner.
|
||||
:type owner: str
|
||||
:param description: Set the fork descripton.
|
||||
:type description: str
|
||||
:param copy_permissions: Copy permissions from parent |repo|. The
|
||||
default is False.
|
||||
:type copy_permissions: bool
|
||||
:param private: Make the fork private. The default is False.
|
||||
:type private: bool
|
||||
:param landing_rev: Set the landing revision. The default is tip.
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_for_response>
|
||||
api_key : "<api_key>"
|
||||
args: {
|
||||
"repoid" : "<reponame or repo_id>",
|
||||
"fork_name": "<forkname>",
|
||||
"owner": "<username or user_id = Optional(=apiuser)>",
|
||||
"description": "<description>",
|
||||
"copy_permissions": "<bool>",
|
||||
"private": "<bool>",
|
||||
"landing_rev": "<landing_rev>"
|
||||
}
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg": "Created fork of `<reponame>` as `<forkname>`",
|
||||
"success": true,
|
||||
"task": "<celery task id or None if done sync>"
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
get_repo
|
||||
--------
|
||||
|
||||
.. py:function:: get_repo(apiuser, repoid, cache=<Optional:True>)
|
||||
|
||||
Gets an existing repository by its name or repository_id.
|
||||
|
||||
The members section so the output returns users groups or users
|
||||
associated with that repository.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights,
|
||||
or users with at least read rights to the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository id.
|
||||
:type repoid: str or int
|
||||
:param cache: use the cached value for last changeset
|
||||
:type: cache: Optional(bool)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": <repo_id>,
|
||||
"result": {
|
||||
"clone_uri": null,
|
||||
"created_on": "timestamp",
|
||||
"description": "repo description",
|
||||
"enable_downloads": false,
|
||||
"enable_locking": false,
|
||||
"enable_statistics": false,
|
||||
"followers": [
|
||||
{
|
||||
"active": true,
|
||||
"admin": false,
|
||||
"api_key": "****************************************",
|
||||
"api_keys": [
|
||||
"****************************************"
|
||||
],
|
||||
"email": "user@example.com",
|
||||
"emails": [
|
||||
"user@example.com"
|
||||
],
|
||||
"extern_name": "rhodecode",
|
||||
"extern_type": "rhodecode",
|
||||
"firstname": "username",
|
||||
"ip_addresses": [],
|
||||
"language": null,
|
||||
"last_login": "2015-09-16T17:16:35.854",
|
||||
"lastname": "surname",
|
||||
"user_id": <user_id>,
|
||||
"username": "name"
|
||||
}
|
||||
],
|
||||
"fork_of": "parent-repo",
|
||||
"landing_rev": [
|
||||
"rev",
|
||||
"tip"
|
||||
],
|
||||
"last_changeset": {
|
||||
"author": "User <user@example.com>",
|
||||
"branch": "default",
|
||||
"date": "timestamp",
|
||||
"message": "last commit message",
|
||||
"parents": [
|
||||
{
|
||||
"raw_id": "commit-id"
|
||||
}
|
||||
],
|
||||
"raw_id": "commit-id",
|
||||
"revision": <revision number>,
|
||||
"short_id": "short id"
|
||||
},
|
||||
"lock_reason": null,
|
||||
"locked_by": null,
|
||||
"locked_date": null,
|
||||
"members": [
|
||||
{
|
||||
"name": "super-admin-name",
|
||||
"origin": "super-admin",
|
||||
"permission": "repository.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "owner-name",
|
||||
"origin": "owner",
|
||||
"permission": "repository.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "user-group-name",
|
||||
"origin": "permission",
|
||||
"permission": "repository.write",
|
||||
"type": "user_group"
|
||||
}
|
||||
],
|
||||
"owner": "owner-name",
|
||||
"permissions": [
|
||||
{
|
||||
"name": "super-admin-name",
|
||||
"origin": "super-admin",
|
||||
"permission": "repository.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "owner-name",
|
||||
"origin": "owner",
|
||||
"permission": "repository.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "user-group-name",
|
||||
"origin": "permission",
|
||||
"permission": "repository.write",
|
||||
"type": "user_group"
|
||||
}
|
||||
],
|
||||
"private": true,
|
||||
"repo_id": 676,
|
||||
"repo_name": "user-group/repo-name",
|
||||
"repo_type": "hg"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get_repo_changeset
|
||||
------------------
|
||||
|
||||
.. py:function:: get_repo_changeset(apiuser, repoid, revision, details=<Optional:'basic'>)
|
||||
|
||||
Returns information about a changeset.
|
||||
|
||||
Additionally parameters define the amount of details returned by
|
||||
this function.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights,
|
||||
or users with at least read rights to the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository id
|
||||
:type repoid: str or int
|
||||
:param revision: revision for which listing should be done
|
||||
:type revision: str
|
||||
:param details: details can be 'basic|extended|full' full gives diff
|
||||
info details like the diff itself, and number of changed files etc.
|
||||
:type details: Optional(str)
|
||||
|
||||
|
||||
get_repo_changesets
|
||||
-------------------
|
||||
|
||||
.. py:function:: get_repo_changesets(apiuser, repoid, start_rev, limit, details=<Optional:'basic'>)
|
||||
|
||||
Returns a set of commits limited by the number starting
|
||||
from the `start_rev` option.
|
||||
|
||||
Additional parameters define the amount of details returned by this
|
||||
function.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights,
|
||||
or users with at least read rights to |repos|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param start_rev: The starting revision from where to get changesets.
|
||||
:type start_rev: str
|
||||
:param limit: Limit the number of commits to this amount
|
||||
:type limit: str or int
|
||||
:param details: Set the level of detail returned. Valid option are:
|
||||
``basic``, ``extended`` and ``full``.
|
||||
:type details: Optional(str)
|
||||
|
||||
.. note::
|
||||
|
||||
Setting the parameter `details` to the value ``full`` is extensive
|
||||
and returns details like the diff itself, and the number
|
||||
of changed files.
|
||||
|
||||
|
||||
get_repo_nodes
|
||||
--------------
|
||||
|
||||
.. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=<Optional:'all'>, details=<Optional:'basic'>, max_file_bytes=<Optional:None>)
|
||||
|
||||
Returns a list of nodes and children in a flat list for a given
|
||||
path at given revision.
|
||||
|
||||
It's possible to specify ret_type to show only `files` or `dirs`.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights,
|
||||
or users with at least read rights to |repos|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param revision: The revision for which listing should be done.
|
||||
:type revision: str
|
||||
:param root_path: The path from which to start displaying.
|
||||
:type root_path: str
|
||||
:param ret_type: Set the return type. Valid options are
|
||||
``all`` (default), ``files`` and ``dirs``.
|
||||
:type ret_type: Optional(str)
|
||||
:param details: Returns extended information about nodes, such as
|
||||
md5, binary, and or content. The valid options are ``basic`` and
|
||||
``full``.
|
||||
:type details: Optional(str)
|
||||
:param max_file_bytes: Only return file content under this file size bytes
|
||||
:type details: Optional(int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: [
|
||||
{
|
||||
"name" : "<name>"
|
||||
"type" : "<type>",
|
||||
"binary": "<true|false>" (only in extended mode)
|
||||
"md5" : "<md5 of file content>" (only in extended mode)
|
||||
},
|
||||
...
|
||||
]
|
||||
error: null
|
||||
|
||||
|
||||
get_repo_refs
|
||||
-------------
|
||||
|
||||
.. py:function:: get_repo_refs(apiuser, repoid)
|
||||
|
||||
Returns a dictionary of current references. It returns
|
||||
bookmarks, branches, closed_branches, and tags for given repository
|
||||
|
||||
It's possible to specify ret_type to show only `files` or `dirs`.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights,
|
||||
or users with at least read rights to |repos|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: [
|
||||
TODO...
|
||||
]
|
||||
error: null
|
||||
|
||||
|
||||
get_repo_settings
|
||||
-----------------
|
||||
|
||||
.. py:function:: get_repo_settings(apiuser, repoid, key=<Optional:None>)
|
||||
|
||||
Returns all settings for a repository. If key is given it only returns the
|
||||
setting identified by the key or null.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository id.
|
||||
:type repoid: str or int
|
||||
:param key: Key of the setting to return.
|
||||
:type: key: Optional(str)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": 237,
|
||||
"result": {
|
||||
"extensions_largefiles": true,
|
||||
"hooks_changegroup_push_logger": true,
|
||||
"hooks_changegroup_repo_size": false,
|
||||
"hooks_outgoing_pull_logger": true,
|
||||
"phases_publish": "True",
|
||||
"rhodecode_hg_use_rebase_for_merging": true,
|
||||
"rhodecode_pr_merge_enabled": true,
|
||||
"rhodecode_use_outdated_comments": true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get_repos
|
||||
---------
|
||||
|
||||
.. py:function:: get_repos(apiuser)
|
||||
|
||||
Lists all existing repositories.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights,
|
||||
or users with at least read rights to |repos|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: [
|
||||
{
|
||||
"repo_id" : "<repo_id>",
|
||||
"repo_name" : "<reponame>"
|
||||
"repo_type" : "<repo_type>",
|
||||
"clone_uri" : "<clone_uri>",
|
||||
"private": : "<bool>",
|
||||
"created_on" : "<datetimecreated>",
|
||||
"description" : "<description>",
|
||||
"landing_rev": "<landing_rev>",
|
||||
"owner": "<repo_owner>",
|
||||
"fork_of": "<name_of_fork_parent>",
|
||||
"enable_downloads": "<bool>",
|
||||
"enable_locking": "<bool>",
|
||||
"enable_statistics": "<bool>",
|
||||
},
|
||||
...
|
||||
]
|
||||
error: null
|
||||
|
||||
|
||||
grant_user_group_permission
|
||||
---------------------------
|
||||
|
||||
.. py:function:: grant_user_group_permission(apiuser, repoid, usergroupid, perm)
|
||||
|
||||
Grant permission for a user group on the specified repository,
|
||||
or update existing permissions.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param usergroupid: Specify the ID of the user group.
|
||||
:type usergroupid: str or int
|
||||
:param perm: Set the user group permissions using the following
|
||||
format: (repository.(none|read|write|admin))
|
||||
:type perm: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
|
||||
"success": true
|
||||
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
|
||||
}
|
||||
|
||||
|
||||
grant_user_permission
|
||||
---------------------
|
||||
|
||||
.. py:function:: grant_user_permission(apiuser, repoid, userid, perm)
|
||||
|
||||
Grant permissions for the specified user on the given repository,
|
||||
or update existing permissions if found.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param userid: Set the user name.
|
||||
:type userid: str
|
||||
:param perm: Set the user permissions, using the following format
|
||||
``(repository.(none|read|write|admin))``
|
||||
:type perm: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
invalidate_cache
|
||||
----------------
|
||||
|
||||
.. py:function:: invalidate_cache(apiuser, repoid, delete_keys=<Optional:False>)
|
||||
|
||||
Invalidates the cache for the specified repository.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Sets the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param delete_keys: This deletes the invalidated keys instead of
|
||||
just flagging them.
|
||||
:type delete_keys: Optional(``True`` | ``False``)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
'msg': Cache for repository `<repository name>` was invalidated,
|
||||
'repository': <repository name>
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
'Error occurred during cache invalidation action'
|
||||
}
|
||||
|
||||
|
||||
lock
|
||||
----
|
||||
|
||||
.. py:function:: lock(apiuser, repoid, locked=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Sets the lock state of the specified |repo| by the given user.
|
||||
From more information, see :ref:`repo-locking`.
|
||||
|
||||
* If the ``userid`` option is not set, the repository is locked to the
|
||||
user who called the method.
|
||||
* If the ``locked`` parameter is not set, the current lock state of the
|
||||
repository is displayed.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Sets the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param locked: Sets the lock state.
|
||||
:type locked: Optional(``True`` | ``False``)
|
||||
:param userid: Set the repository lock to this user.
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
'repo': '<reponame>',
|
||||
'locked': <bool: lock state>,
|
||||
'locked_since': <int: lock timestamp>,
|
||||
'locked_by': <username of person who made the lock>,
|
||||
'lock_reason': <str: reason for locking>,
|
||||
'lock_state_changed': <bool: True if lock state has been changed in this request>,
|
||||
'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
|
||||
or
|
||||
'msg': 'Repo `<repository name>` not locked.'
|
||||
or
|
||||
'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
'Error occurred locking repository `<reponame>`
|
||||
}
|
||||
|
||||
|
||||
pull
|
||||
----
|
||||
|
||||
.. py:function:: pull(apiuser, repoid)
|
||||
|
||||
Triggers a pull on the given repository from a remote location. You
|
||||
can use this to keep remote repositories up-to-date.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
rights to the specified repository. For more information,
|
||||
see :ref:`config-token-ref`.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "Pulled from `<repository name>`"
|
||||
"repository": "<repository name>"
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"Unable to pull changes from `<reponame>`"
|
||||
}
|
||||
|
||||
|
||||
remove_field_from_repo
|
||||
----------------------
|
||||
|
||||
.. py:function:: remove_field_from_repo(apiuser, repoid, key)
|
||||
|
||||
Removes an extra field from a repository.
|
||||
|
||||
This command can only be run using an |authtoken| with at least
|
||||
write permissions to the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param key: Set the unique field key for this repository.
|
||||
:type key: str
|
||||
|
||||
|
||||
revoke_user_group_permission
|
||||
----------------------------
|
||||
|
||||
.. py:function:: revoke_user_group_permission(apiuser, repoid, usergroupid)
|
||||
|
||||
Revoke the permissions of a user group on a given repository.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param usergroupid: Specify the user group ID.
|
||||
:type usergroupid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
revoke_user_permission
|
||||
----------------------
|
||||
|
||||
.. py:function:: revoke_user_permission(apiuser, repoid, userid)
|
||||
|
||||
Revoke permission for a user on the specified repository.
|
||||
|
||||
This command can only be run using an |authtoken| with admin
|
||||
permissions on the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: Set the repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param userid: Set the user name of revoked user.
|
||||
:type userid: str or int
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
|
||||
"success": true
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
set_repo_settings
|
||||
-----------------
|
||||
|
||||
.. py:function:: set_repo_settings(apiuser, repoid, settings)
|
||||
|
||||
Update repository settings. Returns true on success.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository id.
|
||||
:type repoid: str or int
|
||||
:param settings: The new settings for the repository.
|
||||
:type: settings: dict
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": 237,
|
||||
"result": true
|
||||
}
|
||||
|
||||
|
||||
strip
|
||||
-----
|
||||
|
||||
.. py:function:: strip(apiuser, repoid, revision, branch)
|
||||
|
||||
Strips the given revision from the specified repository.
|
||||
|
||||
* This will remove the revision and all of its decendants.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param revision: The revision you wish to strip.
|
||||
:type revision: str
|
||||
:param branch: The branch from which to strip the revision.
|
||||
:type branch: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "'Stripped commit <commit_hash> from repo `<repository name>`'"
|
||||
"repository": "<repository name>"
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"Unable to strip commit <commit_hash> from repo `<repository name>`"
|
||||
}
|
||||
|
||||
|
||||
update_repo
|
||||
-----------
|
||||
|
||||
.. py:function:: update_repo(apiuser, repoid, name=<Optional:None>, owner=<Optional:<OptionalAttr:apiuser>>, group=<Optional:None>, fork_of=<Optional:None>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, fields=<Optional:''>)
|
||||
|
||||
Updates a repository with the given information.
|
||||
|
||||
This command can only be run using an |authtoken| with at least
|
||||
write permissions to the |repo|.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: repository name or repository ID.
|
||||
:type repoid: str or int
|
||||
:param name: Update the |repo| name.
|
||||
:type name: str
|
||||
:param owner: Set the |repo| owner.
|
||||
:type owner: str
|
||||
:param group: Set the |repo| group the |repo| belongs to.
|
||||
:type group: str
|
||||
:param fork_of: Set the master |repo| name.
|
||||
:type fork_of: str
|
||||
:param description: Update the |repo| description.
|
||||
:type description: str
|
||||
:param private: Set the |repo| as private. (True | False)
|
||||
:type private: bool
|
||||
:param clone_uri: Update the |repo| clone URI.
|
||||
:type clone_uri: str
|
||||
:param landing_rev: Set the |repo| landing revision. Default is
|
||||
``tip``.
|
||||
:type landing_rev: str
|
||||
:param enable_statistics: Enable statistics on the |repo|,
|
||||
(True | False).
|
||||
:type enable_statistics: bool
|
||||
:param enable_locking: Enable |repo| locking.
|
||||
:type enable_locking: bool
|
||||
:param enable_downloads: Enable downloads from the |repo|,
|
||||
(True | False).
|
||||
:type enable_downloads: bool
|
||||
:param fields: Add extra fields to the |repo|. Use the following
|
||||
example format: ``field_key=field_val,field_key2=fieldval2``.
|
||||
Escape ', ' with \,
|
||||
:type fields: str
|
||||
|
||||
|
||||
115
docs/api/methods/server-methods.rst
Normal file
115
docs/api/methods/server-methods.rst
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
.. _server-methods-ref:
|
||||
|
||||
server methods
|
||||
=================
|
||||
|
||||
get_ip
|
||||
------
|
||||
|
||||
.. py:function:: get_ip(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Displays the IP Address as seen from the |RCE| server.
|
||||
|
||||
* This command displays the IP Address, as well as all the defined IP
|
||||
addresses for the specified user. If the ``userid`` is not set, the
|
||||
data returned is for the user calling the method.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param userid: Sets the userid for which associated IP Address data
|
||||
is returned.
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"server_ip_addr": "<ip_from_clien>",
|
||||
"user_ips": [
|
||||
{
|
||||
"ip_addr": "<ip_with_mask>",
|
||||
"ip_range": ["<start_ip>", "<end_ip>"],
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
get_server_info
|
||||
---------------
|
||||
|
||||
.. py:function:: get_server_info(apiuser)
|
||||
|
||||
Returns the |RCE| server information.
|
||||
|
||||
This includes the running version of |RCE| and all installed
|
||||
packages. This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
'modules': [<module name>,...]
|
||||
'py_version': <python version>,
|
||||
'platform': <platform type>,
|
||||
'rhodecode_version': <rhodecode version>
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
rescan_repos
|
||||
------------
|
||||
|
||||
.. py:function:: rescan_repos(apiuser, remove_obsolete=<Optional:False>)
|
||||
|
||||
Triggers a rescan of the specified repositories.
|
||||
|
||||
* If the ``remove_obsolete`` option is set, it also deletes repositories
|
||||
that are found in the database but not on the file system, so called
|
||||
"clean zombies".
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param remove_obsolete: Deletes repositories from the database that
|
||||
are not found on the filesystem.
|
||||
:type remove_obsolete: Optional(``True`` | ``False``)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
'added': [<added repository name>,...]
|
||||
'removed': [<removed repository name>,...]
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
'Error occurred during rescan repositories action'
|
||||
}
|
||||
|
||||
|
||||
406
docs/api/methods/user-group-methods.rst
Normal file
406
docs/api/methods/user-group-methods.rst
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
.. _user-group-methods-ref:
|
||||
|
||||
user_group methods
|
||||
=================
|
||||
|
||||
add_user_to_user_group
|
||||
----------------------
|
||||
|
||||
.. py:function:: add_user_to_user_group(apiuser, usergroupid, userid)
|
||||
|
||||
Adds a user to a `user group`. If the user already exists in the group
|
||||
this command will return false.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified user group.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the name of the `user group` to which a
|
||||
user will be added.
|
||||
:type usergroupid: int
|
||||
:param userid: Set the `user_id` of the user to add to the group.
|
||||
:type userid: int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"success": True|False # depends on if member is in group
|
||||
"msg": "added member `<username>` to user group `<groupname>` |
|
||||
User is already in that group"
|
||||
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to add member to user group `<user_group_name>`"
|
||||
}
|
||||
|
||||
|
||||
create_user_group
|
||||
-----------------
|
||||
|
||||
.. py:function:: create_user_group(apiuser, group_name, description=<Optional:''>, owner=<Optional:<OptionalAttr:apiuser>>, active=<Optional:True>)
|
||||
|
||||
Creates a new user group.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param group_name: Set the name of the new user group.
|
||||
:type group_name: str
|
||||
:param description: Give a description of the new user group.
|
||||
:type description: str
|
||||
:param owner: Set the owner of the new user group.
|
||||
If not set, the owner is the |authtoken| user.
|
||||
:type owner: Optional(str or int)
|
||||
:param active: Set this group as active.
|
||||
:type active: Optional(``True`` | ``False``)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg": "created new user group `<groupname>`",
|
||||
"user_group": <user_group_object>
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"user group `<group name>` already exist"
|
||||
or
|
||||
"failed to create group `<group name>`"
|
||||
}
|
||||
|
||||
|
||||
delete_user_group
|
||||
-----------------
|
||||
|
||||
.. py:function:: delete_user_group(apiuser, usergroupid)
|
||||
|
||||
Deletes the specified `user group`.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: filled automatically from apikey
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid:
|
||||
:type usergroupid: int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "deleted user group ID:<user_group_id> <user_group_name>"
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to delete user group ID:<user_group_id> <user_group_name>"
|
||||
or
|
||||
"RepoGroup assigned to <repo_groups_list>"
|
||||
}
|
||||
|
||||
|
||||
get_user_group
|
||||
--------------
|
||||
|
||||
.. py:function:: get_user_group(apiuser, usergroupid)
|
||||
|
||||
Returns the data of an existing user group.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the user group from which to return data.
|
||||
:type usergroupid: str or int
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": <id>,
|
||||
"result": {
|
||||
"active": true,
|
||||
"group_description": "group description",
|
||||
"group_name": "group name",
|
||||
"members": [
|
||||
{
|
||||
"name": "owner-name",
|
||||
"origin": "owner",
|
||||
"permission": "usergroup.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
{
|
||||
"name": "user name",
|
||||
"origin": "permission",
|
||||
"permission": "usergroup.admin",
|
||||
"type": "user"
|
||||
},
|
||||
{
|
||||
"name": "user group name",
|
||||
"origin": "permission",
|
||||
"permission": "usergroup.write",
|
||||
"type": "user_group"
|
||||
}
|
||||
],
|
||||
"owner": "owner name",
|
||||
"users": [],
|
||||
"users_group_id": 2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get_user_groups
|
||||
---------------
|
||||
|
||||
.. py:function:: get_user_groups(apiuser)
|
||||
|
||||
Lists all the existing user groups within RhodeCode.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : [<user_group_obj>,...]
|
||||
error : null
|
||||
|
||||
|
||||
grant_user_group_permission_to_user_group
|
||||
-----------------------------------------
|
||||
|
||||
.. py:function:: grant_user_group_permission_to_user_group(apiuser, usergroupid, sourceusergroupid, perm)
|
||||
|
||||
Give one user group permissions to another user group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the user group on which to edit permissions.
|
||||
:type usergroupid: str or int
|
||||
:param sourceusergroupid: Set the source user group to which
|
||||
access/permissions will be granted.
|
||||
:type sourceusergroupid: str or int
|
||||
:param perm: (usergroup.(none|read|write|admin))
|
||||
:type perm: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "Granted perm: `<perm_name>` for user group: `<source_user_group_name>` in user group: `<user_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
grant_user_permission_to_user_group
|
||||
-----------------------------------
|
||||
|
||||
.. py:function:: grant_user_permission_to_user_group(apiuser, usergroupid, userid, perm)
|
||||
|
||||
Set permissions for a user in a user group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the user group to edit permissions on.
|
||||
:type usergroupid: str or int
|
||||
:param userid: Set the user from whom you wish to set permissions.
|
||||
:type userid: str
|
||||
:param perm: (usergroup.(none|read|write|admin))
|
||||
:type perm: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "Granted perm: `<perm_name>` for user: `<username>` in user group: `<user_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
remove_user_from_user_group
|
||||
---------------------------
|
||||
|
||||
.. py:function:: remove_user_from_user_group(apiuser, usergroupid, userid)
|
||||
|
||||
Removes a user from a user group.
|
||||
|
||||
* If the specified user is not in the group, this command will return
|
||||
`false`.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified user group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Sets the user group name.
|
||||
:type usergroupid: str or int
|
||||
:param userid: The user you wish to remove from |RCE|.
|
||||
:type userid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"success": True|False, # depends on if member is in group
|
||||
"msg": "removed member <username> from user group <groupname> |
|
||||
User wasn't in group"
|
||||
}
|
||||
error: null
|
||||
|
||||
|
||||
revoke_user_group_permission_from_user_group
|
||||
--------------------------------------------
|
||||
|
||||
.. py:function:: revoke_user_group_permission_from_user_group(apiuser, usergroupid, sourceusergroupid)
|
||||
|
||||
Revoke the permissions that one user group has to another.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the user group on which to edit permissions.
|
||||
:type usergroupid: str or int
|
||||
:param sourceusergroupid: Set the user group from which permissions
|
||||
are revoked.
|
||||
:type sourceusergroupid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "Revoked perm for user group: `<user_group_name>` in user group: `<target_user_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
revoke_user_permission_from_user_group
|
||||
--------------------------------------
|
||||
|
||||
.. py:function:: revoke_user_permission_from_user_group(apiuser, usergroupid, userid)
|
||||
|
||||
Revoke a users permissions in a user group.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the user group from which to revoke the user
|
||||
permissions.
|
||||
:type: usergroupid: str or int
|
||||
:param userid: Set the userid of the user whose permissions will be
|
||||
revoked.
|
||||
:type userid: str
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": "Revoked perm for user: `<username>` in user group: `<user_group_name>`",
|
||||
"success": true
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
update_user_group
|
||||
-----------------
|
||||
|
||||
.. py:function:: update_user_group(apiuser, usergroupid, group_name=<Optional:''>, description=<Optional:''>, owner=<Optional:None>, active=<Optional:True>)
|
||||
|
||||
Updates the specified `user group` with the details provided.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param usergroupid: Set the id of the `user group` to update.
|
||||
:type usergroupid: str or int
|
||||
:param group_name: Set the new name the `user group`
|
||||
:type group_name: str
|
||||
:param description: Give a description for the `user group`
|
||||
:type description: str
|
||||
:param owner: Set the owner of the `user group`.
|
||||
:type owner: Optional(str or int)
|
||||
:param active: Set the group as active.
|
||||
:type active: Optional(``True`` | ``False``)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
"msg": 'updated user group ID:<user group id> <user group name>',
|
||||
"user_group": <user_group_object>
|
||||
}
|
||||
error : null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to update user group `<user group name>`"
|
||||
}
|
||||
|
||||
|
||||
295
docs/api/methods/user-methods.rst
Normal file
295
docs/api/methods/user-methods.rst
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
.. _user-methods-ref:
|
||||
|
||||
user methods
|
||||
=================
|
||||
|
||||
create_user
|
||||
-----------
|
||||
|
||||
.. py:function:: create_user(apiuser, username, email, password=<Optional:''>, firstname=<Optional:''>, lastname=<Optional:''>, active=<Optional:True>, admin=<Optional:False>, extern_name=<Optional:'rhodecode'>, extern_type=<Optional:'rhodecode'>, force_password_change=<Optional:False>)
|
||||
|
||||
Creates a new user and returns the new user object.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param username: Set the new username.
|
||||
:type username: str or int
|
||||
:param email: Set the user email address.
|
||||
:type email: str
|
||||
:param password: Set the new user password.
|
||||
:type password: Optional(str)
|
||||
:param firstname: Set the new user firstname.
|
||||
:type firstname: Optional(str)
|
||||
:param lastname: Set the new user surname.
|
||||
:type lastname: Optional(str)
|
||||
:param active: Set the user as active.
|
||||
:type active: Optional(``True`` | ``False``)
|
||||
:param admin: Give the new user admin rights.
|
||||
:type admin: Optional(``True`` | ``False``)
|
||||
:param extern_name: Set the authentication plugin name.
|
||||
Using LDAP this is filled with LDAP UID.
|
||||
:type extern_name: Optional(str)
|
||||
:param extern_type: Set the new user authentication plugin.
|
||||
:type extern_type: Optional(str)
|
||||
:param force_password_change: Force the new user to change password
|
||||
on next login.
|
||||
:type force_password_change: Optional(``True`` | ``False``)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "created new user `<username>`",
|
||||
"user": <user_obj>
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"user `<username>` already exist"
|
||||
or
|
||||
"email `<email>` already exist"
|
||||
or
|
||||
"failed to create user `<username>`"
|
||||
}
|
||||
|
||||
|
||||
delete_user
|
||||
-----------
|
||||
|
||||
.. py:function:: delete_user(apiuser, userid)
|
||||
|
||||
Deletes the specified user from the |RCE| user database.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
.. important::
|
||||
|
||||
Ensure all open pull requests and open code review
|
||||
requests to this user are close.
|
||||
|
||||
Also ensure all repositories, or repository groups owned by this
|
||||
user are reassigned before deletion.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param userid: Set the user to delete.
|
||||
:type userid: str or int
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "deleted user ID:<userid> <username>",
|
||||
"user": null
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to delete user ID:<userid> <username>"
|
||||
}
|
||||
|
||||
|
||||
get_user
|
||||
--------
|
||||
|
||||
.. py:function:: get_user(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Returns the information associated with a username or userid.
|
||||
|
||||
* If the ``userid`` is not set, this command returns the information
|
||||
for the ``userid`` calling the method.
|
||||
|
||||
.. note::
|
||||
|
||||
Normal users may only run this command against their ``userid``. For
|
||||
full privileges you must run this command using an |authtoken| with
|
||||
admin rights.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param userid: Sets the userid for which data will be returned.
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": <id>,
|
||||
"result": {
|
||||
"active": true,
|
||||
"admin": false,
|
||||
"api_key": "api-key",
|
||||
"api_keys": [ list of keys ],
|
||||
"email": "user@example.com",
|
||||
"emails": [
|
||||
"user@example.com"
|
||||
],
|
||||
"extern_name": "rhodecode",
|
||||
"extern_type": "rhodecode",
|
||||
"firstname": "username",
|
||||
"ip_addresses": [],
|
||||
"language": null,
|
||||
"last_login": "Timestamp",
|
||||
"lastname": "surnae",
|
||||
"permissions": {
|
||||
"global": [
|
||||
"hg.inherit_default_perms.true",
|
||||
"usergroup.read",
|
||||
"hg.repogroup.create.false",
|
||||
"hg.create.none",
|
||||
"hg.extern_activate.manual",
|
||||
"hg.create.write_on_repogroup.false",
|
||||
"hg.usergroup.create.false",
|
||||
"group.none",
|
||||
"repository.none",
|
||||
"hg.register.none",
|
||||
"hg.fork.repository"
|
||||
],
|
||||
"repositories": { "username/example": "repository.write"},
|
||||
"repositories_groups": { "user-group/repo": "group.none" },
|
||||
"user_groups": { "user_group_name": "usergroup.read" }
|
||||
},
|
||||
"user_id": 32,
|
||||
"username": "username"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get_user_locks
|
||||
--------------
|
||||
|
||||
.. py:function:: get_user_locks(apiuser, userid=<Optional:<OptionalAttr:apiuser>>)
|
||||
|
||||
Displays all repositories locked by the specified user.
|
||||
|
||||
* If this command is run by a non-admin user, it returns
|
||||
a list of |repos| locked by that user.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param userid: Sets the userid whose list of locked |repos| will be
|
||||
displayed.
|
||||
:type userid: Optional(str or int)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : {
|
||||
[repo_object, repo_object,...]
|
||||
}
|
||||
error : null
|
||||
|
||||
|
||||
get_users
|
||||
---------
|
||||
|
||||
.. py:function:: get_users(apiuser)
|
||||
|
||||
Lists all users in the |RCE| user database.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: [<user_object>, ...]
|
||||
error: null
|
||||
|
||||
|
||||
update_user
|
||||
-----------
|
||||
|
||||
.. py:function:: update_user(apiuser, userid, username=<Optional:None>, email=<Optional:None>, password=<Optional:None>, firstname=<Optional:None>, lastname=<Optional:None>, active=<Optional:None>, admin=<Optional:None>, extern_type=<Optional:None>, extern_name=<Optional:None>)
|
||||
|
||||
Updates the details for the specified user, if that user exists.
|
||||
|
||||
This command can only be run using an |authtoken| with admin rights to
|
||||
the specified repository.
|
||||
|
||||
This command takes the following options:
|
||||
|
||||
:param apiuser: This is filled automatically from |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param userid: Set the ``userid`` to update.
|
||||
:type userid: str or int
|
||||
:param username: Set the new username.
|
||||
:type username: str or int
|
||||
:param email: Set the new email.
|
||||
:type email: str
|
||||
:param password: Set the new password.
|
||||
:type password: Optional(str)
|
||||
:param firstname: Set the new first name.
|
||||
:type firstname: Optional(str)
|
||||
:param lastname: Set the new surname.
|
||||
:type lastname: Optional(str)
|
||||
:param active: Set the new user as active.
|
||||
:type active: Optional(``True`` | ``False``)
|
||||
:param admin: Give the user admin rights.
|
||||
:type admin: Optional(``True`` | ``False``)
|
||||
:param extern_name: Set the authentication plugin user name.
|
||||
Using LDAP this is filled with LDAP UID.
|
||||
:type extern_name: Optional(str)
|
||||
:param extern_type: Set the authentication plugin type.
|
||||
:type extern_type: Optional(str)
|
||||
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result: {
|
||||
"msg" : "updated user ID:<userid> <username>",
|
||||
"user": <user_object>,
|
||||
}
|
||||
error: null
|
||||
|
||||
Example error output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
id : <id_given_in_input>
|
||||
result : null
|
||||
error : {
|
||||
"failed to update user `<username>`"
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ code review matters, see these posts on the topic:
|
|||
|
||||
You can also use the |RCE| API set up continuous integration servers to leave
|
||||
comments from a test suite. See the :ref:`api` and
|
||||
:ref:`integrations-ref` sections for examples on how to set this up.
|
||||
:ref:`extensions-hooks-ref` sections for examples on how to set this up.
|
||||
|
||||
.. toctree::
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ rst_epilog = '''
|
|||
.. |AE| replace:: Appenlight
|
||||
.. |authtoken| replace:: Authentication Token
|
||||
.. |authtokens| replace:: **Auth Tokens**
|
||||
.. |RCCEshort| replace:: Community
|
||||
.. |RCEEshort| replace:: Enterprise
|
||||
.. |git| replace:: Git
|
||||
.. |hg| replace:: Mercurial
|
||||
.. |svn| replace:: Subversion
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ following command from inside the cloned repository::
|
|||
|
||||
On the first run, this will take a while to download and optionally compile
|
||||
a few things. The following runs will be faster. The development shell works
|
||||
fine on MacOS and Linux platforms.
|
||||
fine on both MacOS and Linux platforms.
|
||||
|
||||
|
||||
|
||||
|
|
@ -91,9 +91,9 @@ use the following steps:
|
|||
1. Create a copy of `~/rhodecode-enterprise-ce/configs/development.ini`
|
||||
2. Adjust the configuration settings to your needs
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
It is recommended to use the name `dev.ini`.
|
||||
It is recommended to use the name `dev.ini`.
|
||||
|
||||
|
||||
Setup the Development Database
|
||||
|
|
@ -108,32 +108,37 @@ time operation::
|
|||
--repos=~/my_dev_repos
|
||||
|
||||
|
||||
Compile CSS and JavaScript
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To use the application's frontend, you will need to compile the CSS and
|
||||
JavaScript with Grunt. This is easily done from within the nix-shell using the
|
||||
following command::
|
||||
|
||||
make web-build
|
||||
|
||||
You will need to recompile following any changes made to the CSS or JavaScript
|
||||
files.
|
||||
|
||||
|
||||
Start the Development Server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When starting the development server, you should start the vcsserver as a
|
||||
separate process. To do this, use one of the following examples:
|
||||
From the rhodecode-vcsserver directory, start the development server in another
|
||||
nix-shell, using the following command::
|
||||
|
||||
1. Set the `start.vcs_server` flag in the ``dev.ini`` file to true. For example:
|
||||
pserve configs/development.ini http_port=9900
|
||||
|
||||
.. code-block:: python
|
||||
In the adjacent nix-shell which you created for your development server, you may
|
||||
now start CE with the following command::
|
||||
|
||||
### VCS CONFIG ###
|
||||
##################
|
||||
vcs.start_server = true
|
||||
vcs.server = localhost:9900
|
||||
vcs.server.log_level = debug
|
||||
|
||||
Then start the server using the following command: ``rcserver dev.ini``
|
||||
rcserver dev.ini
|
||||
|
||||
2. Start the development server using the following example::
|
||||
.. note::
|
||||
|
||||
rcserver --with-vcsserver dev.ini
|
||||
|
||||
3. Start the development server in a different terminal using the following
|
||||
example::
|
||||
|
||||
vcsserver
|
||||
To automatically refresh - and recompile the frontend assets - when changes
|
||||
are made in the source code, you can use the option `--reload`.
|
||||
|
||||
|
||||
Run the Environment Tests
|
||||
|
|
@ -141,4 +146,12 @@ Run the Environment Tests
|
|||
|
||||
Please make sure that the tests are passing to verify that your environment is
|
||||
set up correctly. RhodeCode uses py.test to run tests.
|
||||
Please simply run ``make test`` to run the basic test suite.
|
||||
While your instance is running, start a new nix-shell and simply run
|
||||
``make test`` to run the basic test suite.
|
||||
|
||||
|
||||
Need Help?
|
||||
^^^^^^^^^^
|
||||
|
||||
Join us on Slack via https://rhodecode.com/join or post questions in our
|
||||
Community Portal at https://community.rhodecode.com
|
||||
|
|
|
|||
|
|
@ -86,14 +86,11 @@ Sign the Contributor License Agreement
|
|||
======================================
|
||||
|
||||
If your contribution is approved, you will need to virtually sign the license
|
||||
agreement in order for it to be merged into the project's codebase. You can read
|
||||
it on our website here: https://rhodecode.com/static/pdf/RhodeCode-CLA.pdf
|
||||
agreement in order for it to be merged into the project's codebase.
|
||||
|
||||
To sign, go to code.rhodecode.com
|
||||
and clone the CLA repository. Add your name and make a pull request to add it to
|
||||
the contributor agreement; this serves as your virtual signature. Once your
|
||||
signature is merged, add a link to the relevant commit to your contribution
|
||||
pull request.
|
||||
You can read it on our website at https://rhodecode.com/rhodecode-cla
|
||||
|
||||
To sign electronically, go to https://rhodecode.com/sign-cla
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,11 @@ let
|
|||
};
|
||||
|
||||
Pygments = buildPythonPackage rec {
|
||||
name = "Pygments-2.0.2";
|
||||
name = "Pygments-2.1.3";
|
||||
doCheck = false;
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/source/P/Pygments/${name}.tar.gz";
|
||||
md5 = "238587a1370d62405edabd0794b3ec4a";
|
||||
url = "https://pypi.python.org/packages/b8/67/ab177979be1c81bc99c8d0592ef22d547e70bb4c6815c383286ed5dec504/Pygments-2.1.3.tar.gz";
|
||||
md5 = "ed3fba2467c8afcda4d317e4ef2c6150";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -78,11 +79,19 @@ let
|
|||
];
|
||||
};
|
||||
|
||||
Sphinx = buildPythonPackage (rec {
|
||||
name = "Sphinx-1.3.1";
|
||||
imagesize = buildPythonPackage rec {
|
||||
name = "imagesize-0.7.1";
|
||||
src = fetchurl {
|
||||
url = "http://pypi.python.org/packages/source/S/Sphinx/${name}.tar.gz";
|
||||
md5 = "8786a194acf9673464c5455b11fd4332";
|
||||
url = "https://pypi.python.org/packages/53/72/6c6f1e787d9cab2cc733cf042f125abec07209a58308831c9f292504e826/${name}.tar.gz";
|
||||
md5 = "976148283286a6ba5f69b0f81aef8052";
|
||||
};
|
||||
};
|
||||
|
||||
Sphinx = buildPythonPackage (rec {
|
||||
name = "Sphinx-1.4.4";
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/20/a2/72f44c84f6c4115e3fef58d36d657ec311d80196eab9fd5ec7bcde76143b/${name}.tar.gz";
|
||||
md5 = "64ce2ec08d37ed56313a98232cbe2aee";
|
||||
};
|
||||
propagatedBuildInputs = [
|
||||
docutils
|
||||
|
|
@ -93,6 +102,7 @@ let
|
|||
snowballstemmer
|
||||
pytz
|
||||
babel
|
||||
imagesize
|
||||
|
||||
# TODO: johbo: Had to include it here so that can be imported
|
||||
sphinx_rtd_theme
|
||||
|
|
|
|||
25
docs/extensions/extensions-hooks.rst
Normal file
25
docs/extensions/extensions-hooks.rst
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
.. _extensions-hooks-ref:
|
||||
|
||||
Extensions & Hooks
|
||||
==================
|
||||
|
||||
The extensions & hooks section references three concepts regularly,
|
||||
so to clarify what is meant each time, read the following definitions:
|
||||
|
||||
* **Plugin**: A Plugin is software that adds a specific feature to
|
||||
an existing software application.
|
||||
* **Extension**: An extension extends the capabilities of,
|
||||
or the data available to, an existing software application.
|
||||
* **Hook**: A hook intercepts function calls, messages, or events passed
|
||||
between software components and can be used to trigger plugins, or their
|
||||
extensions.
|
||||
|
||||
.. toctree::
|
||||
|
||||
rcx
|
||||
install-ext
|
||||
config-ext
|
||||
extensions
|
||||
hooks
|
||||
full-blown-example
|
||||
int-slack
|
||||
|
|
@ -58,6 +58,7 @@ and commit files and |repos| while managing their security permissions.
|
|||
collaboration/review-notifications
|
||||
collaboration/pull-requests
|
||||
code-review/code-review
|
||||
integrations/integrations
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
|
@ -65,7 +66,7 @@ and commit files and |repos| while managing their security permissions.
|
|||
|
||||
api/api
|
||||
tools/rhodecode-tools
|
||||
integrations/integrations
|
||||
extensions/extensions-hooks
|
||||
contributing/contributing
|
||||
|
||||
.. toctree::
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.. _quick-start:
|
||||
|
||||
Quick Start Guide
|
||||
=================
|
||||
Quick Start Installation Guide
|
||||
==============================
|
||||
|
||||
.. important::
|
||||
|
||||
|
|
|
|||
23
docs/integrations/email.rst
Normal file
23
docs/integrations/email.rst
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
.. _integrations-email:
|
||||
|
||||
Email integration
|
||||
=================
|
||||
|
||||
The email integration allows you to send the summary of repo pushes to a
|
||||
list of email recipients in the format:
|
||||
|
||||
An example::
|
||||
|
||||
User: johndoe
|
||||
Branches: default
|
||||
Repository: http://rhodecode.company.com/repo
|
||||
Commit: 8eab60a44a612e331edfcd59b8d96b2f6a935cd9
|
||||
URL: http://rhodecode.company.com/repo/changeset/8eab60a44a612e331edfcd59b8d96b2f6a935cd9
|
||||
Author: John Doe
|
||||
Date: 2016-03-01 11:20:44
|
||||
Commit Message:
|
||||
|
||||
fixed bug with thing
|
||||
|
||||
|
||||
To create one, create a ``email`` integration in `creating-integrations`.
|
||||
14
docs/integrations/hipchat.rst
Normal file
14
docs/integrations/hipchat.rst
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
.. _integrations-hipchat:
|
||||
|
||||
Hipchat integration
|
||||
===================
|
||||
|
||||
In order to set a Hipchat integration up, it is necessary to obtain the Hipchat
|
||||
service url by:
|
||||
|
||||
1. Log into Hipchat (https://your-hipchat.hipchat.com/)
|
||||
2. Go to *Integrations* -> *Build your own*
|
||||
3. Select a room to post notifications to and save it
|
||||
|
||||
Hipchat will create a URL for you to use in your integration as outlined in
|
||||
:ref:`creating-integrations`.
|
||||
|
|
@ -1,25 +1,52 @@
|
|||
.. _integrations-ref:
|
||||
.. _integrations:
|
||||
|
||||
Integrations and Extensions
|
||||
===========================
|
||||
Integrations
|
||||
------------
|
||||
|
||||
The integrations section references three concepts regularly,
|
||||
so to clarify what is meant each time, read the following definitions:
|
||||
Rhodecode supports integrations with external services for various events,
|
||||
such as commit pushes and pull requests. Multiple integrations of the same type
|
||||
can be added at the same time; this is useful for posting different events to
|
||||
different Slack channels, for example.
|
||||
|
||||
* **Plugin**: A Plugin is software that adds a specific feature to
|
||||
an existing software application.
|
||||
* **Extension**: An extension extends the capabilities of,
|
||||
or the data available to, an existing software application.
|
||||
* **Hook**: A hook intercepts function calls, messages, or events passed
|
||||
between software components and can be used to trigger plugins, or their
|
||||
extensions.
|
||||
Supported integrations
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
============================ ============ =====================================
|
||||
Type/Name |RC| Edition Description
|
||||
============================ ============ =====================================
|
||||
:ref:`integrations-slack` |RCCEshort| https://slack.com/
|
||||
:ref:`integrations-hipchat` |RCCEshort| https://www.hipchat.com/
|
||||
:ref:`integrations-webhook` |RCCEshort| POST events as `json` to a custom url
|
||||
:ref:`integrations-email` |RCEEshort| Send repo push commits by email
|
||||
:ref:`integrations-redmine` |RCEEshort| Close/Resolve/Reference redmine issues
|
||||
:ref:`integrations-jira` |RCEEshort| Close/Resolve/Reference JIRA issues
|
||||
============================ ============ =====================================
|
||||
|
||||
.. _creating-integrations:
|
||||
|
||||
Creating an Integration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Integrations can be added globally via the admin UI:
|
||||
|
||||
:menuselection:`Admin --> Integrations`
|
||||
|
||||
or per repository in each repository's settings:
|
||||
|
||||
:menuselection:`Admin --> Repositories --> Edit --> Integrations`
|
||||
|
||||
To create an integration, select the type from the list in the *Create New
|
||||
Integration* section.
|
||||
|
||||
The *Current Integrations* section shows existing integrations that have been
|
||||
created along with their type (eg. Slack) and enabled status.
|
||||
|
||||
See pages specific to each type of integration for more instructions:
|
||||
|
||||
.. toctree::
|
||||
|
||||
rcx
|
||||
install-ext
|
||||
config-ext
|
||||
extensions
|
||||
hooks
|
||||
full-blown-example
|
||||
int-slack
|
||||
slack
|
||||
hipchat
|
||||
redmine
|
||||
jira
|
||||
webhook
|
||||
|
|
|
|||
27
docs/integrations/jira.rst
Normal file
27
docs/integrations/jira.rst
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
.. _integrations-jira:
|
||||
|
||||
JIRA integration
|
||||
================
|
||||
|
||||
.. important::
|
||||
|
||||
JIRA integration is only available in |RCEE|.
|
||||
|
||||
|
||||
.. important::
|
||||
|
||||
In order to make issue numbers clickable in commit messages, see the
|
||||
:ref:`rhodecode-issue-trackers-ref` section. The JIRA integration
|
||||
only deals with altering JIRA issues.
|
||||
|
||||
|
||||
The JIRA integration allows you to reference and change issue statuses in
|
||||
JIRA directly from commit messages using commit message patterns such as
|
||||
``fixes #JIRA-235`` in order to change the status of issue JIRA-235 to
|
||||
eg. "Resolved".
|
||||
|
||||
In order to apply a status to a JIRA issue, it is necessary to find the
|
||||
transition status id in the *Workflow* section of JIRA.
|
||||
|
||||
Once you have the transition status id, you can create a JIRA integration
|
||||
as outlined in :ref:`creating-integrations`.
|
||||
28
docs/integrations/redmine.rst
Normal file
28
docs/integrations/redmine.rst
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.. _integrations-redmine:
|
||||
|
||||
Redmine integration
|
||||
===================
|
||||
|
||||
.. important::
|
||||
|
||||
Redmine integration is only available in |RCEE|.
|
||||
|
||||
|
||||
.. important::
|
||||
|
||||
In order to make issue numbers clickable in commit messages, see the section
|
||||
:ref:`rhodecode-issue-trackers-ref`. Redmine integration is specifically for
|
||||
altering Redmine issues.
|
||||
|
||||
|
||||
Redmine integration allows you to reference and change issue statuses in
|
||||
Redmine directly from commit messages, using commit message patterns such as
|
||||
``fixes #235`` in order to change the status of issue 235 to eg. "Resolved".
|
||||
|
||||
To set a Redmine integration up, it is first necessary to obtain a Redmine API
|
||||
key. This can be found under *My Account* in the Redmine application.
|
||||
You may have to enable API Access in Redmine settings if it is not already
|
||||
available.
|
||||
|
||||
Once you have the API key, create a Redmine integration as outlined in
|
||||
:ref:`creating-integrations`.
|
||||
21
docs/integrations/slack.rst
Normal file
21
docs/integrations/slack.rst
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
.. _integrations-slack:
|
||||
|
||||
Slack integration
|
||||
=================
|
||||
|
||||
To set a Slack integration up, it is first necessary to set up a Slack webhook
|
||||
API endpoint for your Slack channel. This can be done at:
|
||||
|
||||
https://my.slack.com/services/new/incoming-webhook/
|
||||
|
||||
Select the channel you would like to use, and Slack will provide you with the
|
||||
webhook URL for configuration.
|
||||
|
||||
You can now create a Slack integration as outlined in
|
||||
:ref:`creating-integrations`.
|
||||
|
||||
.. note::
|
||||
Some settings in the RhodeCode admin are identical to the options within the
|
||||
Slack integration. For example, if notifications are to be sent in a private
|
||||
chat, leave the "Channel" field blank. Likewise, the Emoji option within
|
||||
RhodeCode can override the one set in the Slack admin.
|
||||
12
docs/integrations/webhook.rst
Normal file
12
docs/integrations/webhook.rst
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
.. _integrations-webhook:
|
||||
|
||||
Webhook integration
|
||||
===================
|
||||
|
||||
The Webhook integration allows you to POST events such as repository pushes
|
||||
or pull requests to a custom http endpoint as a json dict with details of the
|
||||
event.
|
||||
|
||||
To create a webhook integration, select "webhook" in the integration settings
|
||||
and use the url and key from your custom webhook. See
|
||||
:ref:`creating-integrations` for additional instructions.
|
||||
|
|
@ -5,12 +5,12 @@ Issue Tracker Integration
|
|||
|
||||
You can set an issue tracker connection in two ways with |RCE|.
|
||||
|
||||
* At instance level you can set a default issue tracker.
|
||||
* At |repo| level you can configure an integration with a different issue
|
||||
* At the instance level, you can set a default issue tracker.
|
||||
* At the |repo| level, you can configure an integration with a different issue
|
||||
tracker.
|
||||
|
||||
To integrate |RCM| with an issue tracker you need to define a regular
|
||||
expression that will fetch the issue ID stored in commit messages and replace
|
||||
To integrate |RCM| with an issue tracker, you need to define a regular
|
||||
expression that will fetch the issue ID stored in commit messages, and replace
|
||||
it with a URL. This enables |RCE| to generate a link matching each issue to the
|
||||
target |repo|.
|
||||
|
||||
|
|
@ -33,9 +33,8 @@ To integrate your issue tracker, use the following steps:
|
|||
Repository Issue Tracker Configuration
|
||||
--------------------------------------
|
||||
|
||||
You can configure specific |repos| to use a different issue tracker if
|
||||
you need to connect to a non-default one. See the instructions in
|
||||
:ref:`repo-it`
|
||||
You can configure specific |repos| to use a different issue tracker than the
|
||||
default one. See the instructions in :ref:`repo-it`
|
||||
|
||||
.. _issue-tr-eg-ref:
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ Release Date
|
|||
Fixes
|
||||
^^^^^
|
||||
|
||||
- ui: fixed empty labels caused by missing translation of JS components
|
||||
- login: fixed bad routing URL in comments when user is not logged in.
|
||||
- celery: make sure to run tasks in sync mode if connection to celery is lost.
|
||||
- UI: fixed empty labels caused by missing translation of JS components.
|
||||
- Login: fixed bad routing URL in comments when user is not logged in.
|
||||
- Celery: make sure to run tasks in sync mode if connection to celery is lost.
|
||||
|
|
|
|||
121
docs/release-notes/release-notes-4.3.0.rst
Normal file
121
docs/release-notes/release-notes-4.3.0.rst
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
|RCE| 4.3.0 |RNS|
|
||||
-----------------
|
||||
|
||||
Release Date
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- 2016-08-12
|
||||
|
||||
|
||||
General
|
||||
^^^^^^^
|
||||
|
||||
- Subversion: detect requests also based on magic path.
|
||||
This adds subversion 1.9 support for SVN backend.
|
||||
- Summary/changelog: unified how data is displayed for those pages.
|
||||
* use consistent order of columns
|
||||
* fix the link to commit status
|
||||
* fix order of displaying comments
|
||||
- Live-chat: refactor live chat system for code review based on
|
||||
latest channelstream changes.
|
||||
- SVN: Add template to generate the apache mod_dav_svn config for all
|
||||
repository groups. Repository groups can now be automatically mapped to be
|
||||
supported by SVN backend. Set `svn.proxy.generate_config = true` and similar
|
||||
options found inside .ini config.
|
||||
- Readme/markup: improved order of generating readme files. Fixes #4050
|
||||
* we now use order based on default system renderer
|
||||
* having multiple readme files will pick correct one as set renderer
|
||||
- Api: add a max_file_bytes parameter to get_nodes so that large files
|
||||
can be skipped.
|
||||
- Auth-ldap: added flag to set debug mode for LDAP connections.
|
||||
- Labs: moved rebase-merge option from labs settings into VCS settings.
|
||||
- System: send platform type and version to upgrade endpoint when checking
|
||||
for new versions.
|
||||
- Packaging: update rhodecode-tools from 0.8.3 to 0.10.0
|
||||
- Packaging: update codemirror from 5.4.0 to 5.11.0
|
||||
- Packaging: updated pygments to 2.1.3
|
||||
- Packaging: bumped supervisor to 3.3.0
|
||||
- Packaging: bumped psycopg2 to 2.6.1
|
||||
- Packaging: bumped mercurial to 3.8.4
|
||||
|
||||
|
||||
New Features
|
||||
^^^^^^^^^^^^
|
||||
|
||||
- Integrations: created new event based integration framework.
|
||||
Allows to configure global, or per repo: Slack, Hipchat, Webhooks, Email
|
||||
integrations. This also deprecated usage of rcextensions for those.
|
||||
- Integrations (EE only): added smart commits for Jira and Redmine with
|
||||
ability to map keywords into issue tracker actions.
|
||||
`Fixes #123 -> resolves issues`, `Closes #123 -> closes issue` etc.
|
||||
- Markdown: added improved support for Github flavored markdown.
|
||||
- Labs: enable labs setting by default. Labs are new experimental features in
|
||||
RhodeCode that can be used to test new upcomming features.
|
||||
- Api: Add api methods to get/set repository settings, implements #4021.
|
||||
- Gravatars: commit emails are now displayed based on the actual email
|
||||
used inside commit rather then the main one of associated account
|
||||
inside RhodeCode, #4037.
|
||||
- Emails: All emails got new styling. They look now consistent
|
||||
to UI of application. We also added bunch of usefull information into
|
||||
email body, #4087.
|
||||
- Pull requests: add show/hide comment functionality inside diffs, #4106.
|
||||
- Notifications: added real-time notifications with via channelstream
|
||||
about new comments when reviewing the code. Never miss someone replies
|
||||
onto comments you submitted while doing a code-review.
|
||||
|
||||
|
||||
Security
|
||||
^^^^^^^^
|
||||
|
||||
- Api: make `comment_commits` api call have consistent permissions
|
||||
with web interface.
|
||||
- Files: fixes display of "Add File" button missing or present despite
|
||||
permissions, because of cached version of the page was rendered, fixes #4083.
|
||||
- Login/Registration: fixed flash message problem on login/registration
|
||||
pages, fixes #4043.
|
||||
- Auth-token: allow other authentication types to use auth-token.
|
||||
Accounts associated with other types like LDAP, or PAM can
|
||||
now use auth-tokens to authenticate via RhodeCode.
|
||||
|
||||
|
||||
Performance
|
||||
^^^^^^^^^^^
|
||||
|
||||
- Core: made all RhodeCode components gevent compatible. RhodeCode can now make
|
||||
use of async workers. You can handle dozens of concurrent operations using a
|
||||
single worker. This works only with new HTTP backend.
|
||||
- Core: added new very efficient HTTP backend can be used to replace pyro4.
|
||||
- Core: Set 'gzip_responses' to false by default. We no longer require any
|
||||
gzip computations on backed, thus speeding up large file transfers.
|
||||
- UI: optimized events system for JavaScript to boost performance on
|
||||
large html pages.
|
||||
- VCS: moved VCSMiddleware up to pyramid layer as wrapper around pylons app.
|
||||
Skips few calls, and allows slightly faster clones/pulls and pushes.
|
||||
|
||||
|
||||
Fixes
|
||||
^^^^^
|
||||
|
||||
- VCS: add vcsserver cache invalidation to mercurial backend.
|
||||
Fixes multi-process problems after Mercurial 3.8.X release with server
|
||||
side merges.
|
||||
- VCS: clear caches on remap-and-rescan option.
|
||||
- VCS: improved logic of updating commit caches in cases of rebases.
|
||||
- Caches: Add an argument to make the cache context thread scoped. Brings
|
||||
support to gevent compatible handling.
|
||||
- Diff2way: fixed unicode problem on non-ascii files.
|
||||
- Full text search: whoosh schema uses now bigger ints, fixes #4035
|
||||
- File-browser: optimized cached tree calculation, reduced load times by
|
||||
50% on complex file trees.
|
||||
- Styling: #4086 fixing bug where long commit messages did not wrap in file view.
|
||||
- SVN: Ignore the content length header from response, fixes #4112.
|
||||
Fixes the "svn: E120106: ra_serf: The server sent a truncated HTTP response body."
|
||||
- Auth: Fix password_changed function, fixes #4043.
|
||||
- UI/tables: better message when tables are empty #685 #1832.
|
||||
- UX: put gravatar and username together in user list #3203.
|
||||
- Gists: use colander schema to validate input data.
|
||||
* brings consistent validation acros API and web
|
||||
* use nicer and stricter schemas to validate data
|
||||
* fixes #4118
|
||||
- Appenlight: error reporting can now also report VCSMiddleware errors.
|
||||
- Users: hash email key for User.get_by_email() fixes #4132
|
||||
|
|
@ -9,6 +9,7 @@ Release Notes
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
release-notes-4.3.0.rst
|
||||
release-notes-4.2.1.rst
|
||||
release-notes-4.2.0.rst
|
||||
release-notes-4.1.2.rst
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ used to send signals to build-bots such as jenkins. Options:
|
|||
|
||||
\ - -plugins
|
||||
Add plugins to your |RCE| installation. See the
|
||||
:ref:`integrations-ref` section for more details.
|
||||
:ref:`extensions-hooks-ref` section for more details.
|
||||
|
||||
\ - -version
|
||||
Display your |RCT| version.
|
||||
|
|
|
|||
13
licenses/tornado_license.txt
Normal file
13
licenses/tornado_license.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Copyright 2009 Facebook
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
diff --git a/requirements.txt b/requirements.txt
|
||||
--- a/requirements.txt
|
||||
+++ b/requirements.txt
|
||||
@@ -3,7 +3,7 @@future==0.14.3
|
||||
@@ -3,7 +3,7 @@ future==0.14.3
|
||||
six==1.9.0
|
||||
mako==1.0.1
|
||||
markupsafe==0.23
|
||||
-requests==2.5.1
|
||||
+requests
|
||||
#responses
|
||||
whoosh==2.7.0
|
||||
elasticsearch==2.3.0
|
||||
elasticsearch==2.3.0
|
||||
elasticsearch-dsl==2.0.0
|
||||
|
|
@ -95,6 +95,14 @@ self: super: {
|
|||
};
|
||||
});
|
||||
|
||||
py-gfm = super.py-gfm.override {
|
||||
src = pkgs.fetchgit {
|
||||
url = "https://code.rhodecode.com/upstream/py-gfm";
|
||||
rev = "0d66a19bc16e3d49de273c0f797d4e4781e8c0f2";
|
||||
sha256 = "0ryp74jyihd3ckszq31bml5jr3bciimhfp7va7kw6ld92930ksv3";
|
||||
};
|
||||
};
|
||||
|
||||
pycurl = super.pycurl.override (attrs: {
|
||||
propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
|
||||
pkgs.curl
|
||||
|
|
|
|||
|
|
@ -38,6 +38,19 @@
|
|||
license = [ pkgs.lib.licenses.mit ];
|
||||
};
|
||||
};
|
||||
Chameleon = super.buildPythonPackage {
|
||||
name = "Chameleon-2.24";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/5a/9e/637379ffa13c5172b5c0e704833ffea6bf51cec7567f93fd6e903d53ed74/Chameleon-2.24.tar.gz";
|
||||
md5 = "1b01f1f6533a8a11d0d2f2366dec5342";
|
||||
};
|
||||
meta = {
|
||||
license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
|
||||
};
|
||||
};
|
||||
Fabric = super.buildPythonPackage {
|
||||
name = "Fabric-1.10.0";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -169,13 +182,13 @@
|
|||
};
|
||||
};
|
||||
Pygments = super.buildPythonPackage {
|
||||
name = "Pygments-2.0.2";
|
||||
name = "Pygments-2.1.3";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/f4/c6/bdbc5a8a112256b2b6136af304dbae93d8b1ef8738ff2d12a51018800e46/Pygments-2.0.2.tar.gz";
|
||||
md5 = "238587a1370d62405edabd0794b3ec4a";
|
||||
url = "https://pypi.python.org/packages/b8/67/ab177979be1c81bc99c8d0592ef22d547e70bb4c6815c383286ed5dec504/Pygments-2.1.3.tar.gz";
|
||||
md5 = "ed3fba2467c8afcda4d317e4ef2c6150";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
|
|
@ -467,6 +480,19 @@
|
|||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
channelstream = super.buildPythonPackage {
|
||||
name = "channelstream-0.5.2";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [gevent ws4py pyramid pyramid-jinja2 itsdangerous requests six];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/2b/31/29a8e085cf5bf97fa88e7b947adabfc581a18a3463adf77fb6dada34a65f/channelstream-0.5.2.tar.gz";
|
||||
md5 = "1c5eb2a8a405be6f1073da94da6d81d3";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
click = super.buildPythonPackage {
|
||||
name = "click-5.1";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -558,6 +584,19 @@
|
|||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
deform = super.buildPythonPackage {
|
||||
name = "deform-2.0a2";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [Chameleon colander peppercorn translationstring zope.deprecation];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/8d/b3/aab57e81da974a806dc9c5fa024a6404720f890a6dcf2e80885e3cb4609a/deform-2.0a2.tar.gz";
|
||||
md5 = "7a90d41f7fbc18002ce74f39bd90a5e4";
|
||||
};
|
||||
meta = {
|
||||
license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
|
||||
};
|
||||
};
|
||||
docutils = super.buildPythonPackage {
|
||||
name = "docutils-0.12";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -572,13 +611,13 @@
|
|||
};
|
||||
};
|
||||
dogpile.cache = super.buildPythonPackage {
|
||||
name = "dogpile.cache-0.5.7";
|
||||
name = "dogpile.cache-0.6.1";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [dogpile.core];
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/07/74/2a83bedf758156d9c95d112691bbad870d3b77ccbcfb781b4ef836ea7d96/dogpile.cache-0.5.7.tar.gz";
|
||||
md5 = "3e58ce41af574aab41d78e9c4190f194";
|
||||
url = "https://pypi.python.org/packages/f6/a0/6f2142c58c6588d17c734265b103ae1cd0741e1681dd9483a63f22033375/dogpile.cache-0.6.1.tar.gz";
|
||||
md5 = "35d7fb30f22bbd0685763d894dd079a9";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
|
|
@ -688,6 +727,19 @@
|
|||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
gevent = super.buildPythonPackage {
|
||||
name = "gevent-1.1.1";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [greenlet];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/12/dc/0b2e57823225de86f6e111a65d212c9e3b64847dddaa19691a6cb94b0b2e/gevent-1.1.1.tar.gz";
|
||||
md5 = "1532f5396ab4d07a231f1935483be7c3";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.mit ];
|
||||
};
|
||||
};
|
||||
gnureadline = super.buildPythonPackage {
|
||||
name = "gnureadline-6.3.3";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -702,7 +754,7 @@
|
|||
};
|
||||
};
|
||||
gprof2dot = super.buildPythonPackage {
|
||||
name = "gprof2dot-2015.12.1";
|
||||
name = "gprof2dot-2015.12.01";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
|
|
@ -714,6 +766,19 @@
|
|||
license = [ { fullName = "LGPL"; } ];
|
||||
};
|
||||
};
|
||||
greenlet = super.buildPythonPackage {
|
||||
name = "greenlet-0.4.9";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/4e/3d/9d421539b74e33608b245092870156b2e171fb49f2b51390aa4641eecb4a/greenlet-0.4.9.zip";
|
||||
md5 = "c6659cdb2a5e591723e629d2eef22e82";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.mit ];
|
||||
};
|
||||
};
|
||||
gunicorn = super.buildPythonPackage {
|
||||
name = "gunicorn-19.6.0";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -948,6 +1013,19 @@
|
|||
license = [ { fullName = "Expat license"; } pkgs.lib.licenses.mit ];
|
||||
};
|
||||
};
|
||||
peppercorn = super.buildPythonPackage {
|
||||
name = "peppercorn-0.5";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/45/ec/a62ec317d1324a01567c5221b420742f094f05ee48097e5157d32be3755c/peppercorn-0.5.tar.gz";
|
||||
md5 = "f08efbca5790019ab45d76b7244abd40";
|
||||
};
|
||||
meta = {
|
||||
license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
|
||||
};
|
||||
};
|
||||
psutil = super.buildPythonPackage {
|
||||
name = "psutil-2.2.1";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -962,13 +1040,13 @@
|
|||
};
|
||||
};
|
||||
psycopg2 = super.buildPythonPackage {
|
||||
name = "psycopg2-2.6";
|
||||
name = "psycopg2-2.6.1";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/dd/c7/9016ff8ff69da269b1848276eebfb264af5badf6b38caad805426771f04d/psycopg2-2.6.tar.gz";
|
||||
md5 = "fbbb039a8765d561a1c04969bbae7c74";
|
||||
url = "https://pypi.python.org/packages/86/fd/cc8315be63a41fe000cce20482a917e874cdc1151e62cb0141f5e55f711e/psycopg2-2.6.1.tar.gz";
|
||||
md5 = "842b44f8c95517ed5b792081a2370da1";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.zpt21 { fullName = "GNU Library or Lesser General Public License (LGPL)"; } { fullName = "LGPL with exceptions or ZPL"; } ];
|
||||
|
|
@ -1000,6 +1078,19 @@
|
|||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
py-gfm = super.buildPythonPackage {
|
||||
name = "py-gfm-0.1.3";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [setuptools Markdown];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/12/e4/6b3d8678da04f97d7490d8264d8de51c2dc9fb91209ccee9c515c95e14c5/py-gfm-0.1.3.tar.gz";
|
||||
md5 = "e588d9e69640a241b97e2c59c22527a6";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
pycrypto = super.buildPythonPackage {
|
||||
name = "pycrypto-2.6.1";
|
||||
buildInputs = with self; [];
|
||||
|
|
@ -1339,23 +1430,23 @@
|
|||
};
|
||||
};
|
||||
rhodecode-enterprise-ce = super.buildPythonPackage {
|
||||
name = "rhodecode-enterprise-ce-4.2.1";
|
||||
name = "rhodecode-enterprise-ce-4.3.0";
|
||||
buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner];
|
||||
doCheck = true;
|
||||
propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors psutil py-bcrypt];
|
||||
propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery channelstream colander decorator deform docutils gevent gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt];
|
||||
src = ./.;
|
||||
meta = {
|
||||
license = [ { fullName = "AGPLv3, and Commercial License"; } ];
|
||||
};
|
||||
};
|
||||
rhodecode-tools = super.buildPythonPackage {
|
||||
name = "rhodecode-tools-0.8.3";
|
||||
name = "rhodecode-tools-0.10.0";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [click future six Mako MarkupSafe requests Whoosh elasticsearch elasticsearch-dsl];
|
||||
src = fetchurl {
|
||||
url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.8.3.zip";
|
||||
md5 = "9acdfd71b8ddf4056057065f37ab9ccb";
|
||||
url = "https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.10.0.zip";
|
||||
md5 = "4762391473ded761bead3aa58c748044";
|
||||
};
|
||||
meta = {
|
||||
license = [ { fullName = "AGPLv3 and Proprietary"; } ];
|
||||
|
|
@ -1453,13 +1544,13 @@
|
|||
};
|
||||
};
|
||||
supervisor = super.buildPythonPackage {
|
||||
name = "supervisor-3.1.3";
|
||||
name = "supervisor-3.3.0";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [meld3];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/a6/41/65ad5bd66230b173eb4d0b8810230f3a9c59ef52ae066e540b6b99895db7/supervisor-3.1.3.tar.gz";
|
||||
md5 = "aad263c4fbc070de63dd354864d5e552";
|
||||
url = "https://pypi.python.org/packages/44/80/d28047d120bfcc8158b4e41127706731ee6a3419c661e0a858fb0e7c4b2d/supervisor-3.3.0.tar.gz";
|
||||
md5 = "46bac00378d1eddb616752b990c67416";
|
||||
};
|
||||
meta = {
|
||||
license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
|
||||
|
|
@ -1556,6 +1647,19 @@
|
|||
license = [ pkgs.lib.licenses.zpt21 ];
|
||||
};
|
||||
};
|
||||
ws4py = super.buildPythonPackage {
|
||||
name = "ws4py-0.3.5";
|
||||
buildInputs = with self; [];
|
||||
doCheck = false;
|
||||
propagatedBuildInputs = with self; [];
|
||||
src = fetchurl {
|
||||
url = "https://pypi.python.org/packages/b6/4f/34af703be86939629479e74d6e650e39f3bd73b3b09212c34e5125764cbc/ws4py-0.3.5.zip";
|
||||
md5 = "a261b75c20b980e55ce7451a3576a867";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
};
|
||||
};
|
||||
wsgiref = super.buildPythonPackage {
|
||||
name = "wsgiref-0.1.2";
|
||||
buildInputs = with self; [];
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ MySQL-python==1.2.5
|
|||
Paste==2.0.2
|
||||
PasteDeploy==1.5.2
|
||||
PasteScript==1.7.5
|
||||
Pygments==2.0.2
|
||||
Pygments==2.1.3
|
||||
|
||||
# TODO: This version is not available on PyPI
|
||||
# Pylons==1.0.2.dev20160108
|
||||
|
|
@ -24,10 +24,6 @@ Pyro4==4.41
|
|||
# TODO: This should probably not be in here
|
||||
# -e hg+https://johbo@code.rhodecode.com/johbo/rhodecode-fork@3a454bd1f17c0b2b2a951cf2b111e0320d7942a9#egg=RhodeCodeEnterprise-dev
|
||||
|
||||
# TODO: This is not really a dependency, we should add it only
|
||||
# into the development environment, since there it is useful.
|
||||
# RhodeCodeVCSServer==3.9.0
|
||||
|
||||
Routes==1.13
|
||||
SQLAlchemy==0.9.9
|
||||
Sphinx==1.2.2
|
||||
|
|
@ -53,6 +49,7 @@ backport-ipaddress==0.1
|
|||
bottle==0.12.8
|
||||
bumpversion==0.5.3
|
||||
celery==2.2.10
|
||||
channelstream==0.5.2
|
||||
click==5.1
|
||||
colander==1.2
|
||||
configobj==5.0.6
|
||||
|
|
@ -60,15 +57,18 @@ cov-core==1.15.0
|
|||
coverage==3.7.1
|
||||
cssselect==0.9.1
|
||||
decorator==3.4.2
|
||||
deform==2.0a2
|
||||
docutils==0.12
|
||||
dogpile.cache==0.5.7
|
||||
dogpile.cache==0.6.1
|
||||
dogpile.core==0.4.1
|
||||
dulwich==0.12.0
|
||||
ecdsa==0.11
|
||||
flake8==2.4.1
|
||||
future==0.14.3
|
||||
futures==3.0.2
|
||||
gevent==1.1.1
|
||||
gprof2dot==2015.12.1
|
||||
greenlet==0.4.9
|
||||
gunicorn==19.6.0
|
||||
|
||||
# TODO: Needs subvertpy and blows up without Subversion headers,
|
||||
|
|
@ -94,9 +94,10 @@ packaging==15.2
|
|||
paramiko==1.15.1
|
||||
pep8==1.5.7
|
||||
psutil==2.2.1
|
||||
psycopg2==2.6
|
||||
psycopg2==2.6.1
|
||||
py==1.4.29
|
||||
py-bcrypt==0.4
|
||||
py-gfm==0.1.3
|
||||
pycrypto==2.6.1
|
||||
pycurl==7.19.5
|
||||
pyflakes==0.8.1
|
||||
|
|
@ -123,7 +124,7 @@ pyzmq==14.6.0
|
|||
# TODO: This is not available in public
|
||||
# rc-testdata==0.2.0
|
||||
|
||||
https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.8.3.zip#md5=9acdfd71b8ddf4056057065f37ab9ccb
|
||||
https://code.rhodecode.com/rhodecode-tools-ce/archive/v0.10.0.zip#md5=4762391473ded761bead3aa58c748044
|
||||
|
||||
|
||||
recaptcha-client==1.0.6
|
||||
|
|
@ -136,7 +137,7 @@ setuptools-scm==1.11.0
|
|||
simplejson==3.7.2
|
||||
six==1.9.0
|
||||
subprocess32==3.2.6
|
||||
supervisor==3.1.3
|
||||
supervisor==3.3.0
|
||||
transifex-client==0.10
|
||||
translationstring==1.3
|
||||
trollius==1.0.4
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
4.2.1
|
||||
4.3.0
|
||||
|
|
@ -43,11 +43,15 @@ CELERY_EAGER = False
|
|||
# link to config for pylons
|
||||
CONFIG = {}
|
||||
|
||||
# Populated with the settings dictionary from application init in
|
||||
# rhodecode.conf.environment.load_pyramid_environment
|
||||
PYRAMID_SETTINGS = {}
|
||||
|
||||
# Linked module for extensions
|
||||
EXTENSIONS = {}
|
||||
|
||||
__version__ = ('.'.join((str(each) for each in VERSION[:3])))
|
||||
__dbversion__ = 54 # defines current db version for migrations
|
||||
__dbversion__ = 55 # defines current db version for migrations
|
||||
__platform__ = platform.system()
|
||||
__license__ = 'AGPLv3, and Commercial License'
|
||||
__author__ = 'RhodeCode GmbH'
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ class NavigationRegistry(object):
|
|||
NavEntry('email', _('Email'), 'admin_settings_email'),
|
||||
NavEntry('hooks', _('Hooks'), 'admin_settings_hooks'),
|
||||
NavEntry('search', _('Full Text Search'), 'admin_settings_search'),
|
||||
NavEntry('integrations', _('Integrations'),
|
||||
'global_integrations_home', pyramid=True),
|
||||
NavEntry('system', _('System Info'), 'admin_settings_system'),
|
||||
NavEntry('open_source', _('Open Source Licenses'),
|
||||
'admin_settings_open_source', pyramid=True),
|
||||
|
|
|
|||
|
|
@ -25,12 +25,15 @@ import types
|
|||
|
||||
import decorator
|
||||
import venusian
|
||||
from collections import OrderedDict
|
||||
|
||||
from pyramid.exceptions import ConfigurationError
|
||||
from pyramid.renderers import render
|
||||
from pyramid.response import Response
|
||||
from pyramid.httpexceptions import HTTPNotFound
|
||||
|
||||
from rhodecode.api.exc import JSONRPCBaseError, JSONRPCError, JSONRPCForbidden
|
||||
from rhodecode.api.exc import (
|
||||
JSONRPCBaseError, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
|
||||
from rhodecode.lib.auth import AuthUser
|
||||
from rhodecode.lib.base import get_ip_addr
|
||||
from rhodecode.lib.ext_json import json
|
||||
|
|
@ -127,6 +130,11 @@ def exception_view(exc, request):
|
|||
if isinstance(exc, JSONRPCError):
|
||||
fault_message = exc.message
|
||||
log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
|
||||
elif isinstance(exc, JSONRPCValidationError):
|
||||
colander_exc = exc.colander_exception
|
||||
#TODO: think maybe of nicer way to serialize errors ?
|
||||
fault_message = colander_exc.asdict()
|
||||
log.debug('json-rpc error rpc_id:%s "%s"', rpc_id, fault_message)
|
||||
elif isinstance(exc, JSONRPCForbidden):
|
||||
fault_message = 'Access was denied to this resource.'
|
||||
log.warning('json-rpc forbidden call rpc_id:%s "%s"', rpc_id, fault_message)
|
||||
|
|
@ -474,7 +482,7 @@ def includeme(config):
|
|||
plugin_module, config.registry.settings)
|
||||
|
||||
if not hasattr(config.registry, 'jsonrpc_methods'):
|
||||
config.registry.jsonrpc_methods = {}
|
||||
config.registry.jsonrpc_methods = OrderedDict()
|
||||
|
||||
# match filter by given method only
|
||||
config.add_view_predicate(
|
||||
|
|
|
|||
|
|
@ -27,5 +27,13 @@ class JSONRPCError(JSONRPCBaseError):
|
|||
pass
|
||||
|
||||
|
||||
class JSONRPCValidationError(JSONRPCBaseError):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.colander_exception = kwargs.pop('colander_exc')
|
||||
super(JSONRPCValidationError, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class JSONRPCForbidden(JSONRPCBaseError):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class TestApiCreateGist(object):
|
|||
description='foobar-gist',
|
||||
gist_type=gist_type,
|
||||
acl_level=gist_acl_level,
|
||||
files={'foobar': {'content': 'foo'}})
|
||||
files={'foobar_ąć': {'content': 'foo'}})
|
||||
response = api_call(self.app, params)
|
||||
response_json = response.json
|
||||
gist = response_json['result']['gist']
|
||||
|
|
@ -68,6 +68,32 @@ class TestApiCreateGist(object):
|
|||
finally:
|
||||
Fixture().destroy_gists()
|
||||
|
||||
@pytest.mark.parametrize("expected, lifetime, gist_type, gist_acl_level, files", [
|
||||
({'gist_type': '"ups" is not one of private, public'},
|
||||
10, 'ups', Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}),
|
||||
|
||||
({'lifetime': '-120 is less than minimum value -1'},
|
||||
-120, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'content': 'f'}}),
|
||||
|
||||
({'0.content': 'Required'},
|
||||
10, Gist.GIST_PUBLIC, Gist.ACL_LEVEL_PUBLIC, {'f': {'x': 'f'}}),
|
||||
])
|
||||
def test_api_try_create_gist(
|
||||
self, expected, lifetime, gist_type, gist_acl_level, files):
|
||||
id_, params = build_data(
|
||||
self.apikey_regular, 'create_gist',
|
||||
lifetime=lifetime,
|
||||
description='foobar-gist',
|
||||
gist_type=gist_type,
|
||||
acl_level=gist_acl_level,
|
||||
files=files)
|
||||
response = api_call(self.app, params)
|
||||
|
||||
try:
|
||||
assert_error(id_, expected, given=response.body)
|
||||
finally:
|
||||
Fixture().destroy_gists()
|
||||
|
||||
@mock.patch.object(GistModel, 'create', crash)
|
||||
def test_api_create_gist_exception_occurred(self):
|
||||
id_, params = build_data(self.apikey_regular, 'create_gist', files={})
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from rhodecode.api.views import depracated_api
|
||||
from rhodecode.api.views import deprecated_api
|
||||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.api.tests.utils import (
|
||||
build_data, api_call)
|
||||
|
|
@ -30,7 +30,7 @@ from rhodecode.api.tests.utils import (
|
|||
@pytest.mark.usefixtures("testuser_api", "app")
|
||||
class TestCommitComment(object):
|
||||
def test_deprecated_message_in_docstring(self):
|
||||
docstring = depracated_api.changeset_comment.__doc__
|
||||
docstring = deprecated_api.changeset_comment.__doc__
|
||||
assert '.. deprecated:: 3.4.0' in docstring
|
||||
assert 'Please use method `comment_commit` instead.' in docstring
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,29 @@ class TestGetRepoNodes(object):
|
|||
expected = 'failed to get repo: `%s` nodes' % (backend.repo_name,)
|
||||
assert_error(id_, expected, given=response.body)
|
||||
|
||||
def test_api_get_repo_nodes_max_file_bytes(self, backend):
|
||||
commit_id = 'tip'
|
||||
path = '/'
|
||||
max_file_bytes = 500
|
||||
|
||||
id_, params = build_data(
|
||||
self.apikey, 'get_repo_nodes',
|
||||
repoid=backend.repo_name, revision=commit_id, details='full',
|
||||
root_path=path)
|
||||
response = api_call(self.app, params)
|
||||
assert any(file['content'] and len(file['content']) > max_file_bytes
|
||||
for file in response.json['result'])
|
||||
|
||||
id_, params = build_data(
|
||||
self.apikey, 'get_repo_nodes',
|
||||
repoid=backend.repo_name, revision=commit_id,
|
||||
root_path=path, details='full',
|
||||
max_file_bytes=max_file_bytes)
|
||||
response = api_call(self.app, params)
|
||||
assert all(
|
||||
file['content'] is None if file['size'] > max_file_bytes else True
|
||||
for file in response.json['result'])
|
||||
|
||||
def test_api_get_repo_nodes_bad_ret_type(self, backend):
|
||||
commit_id = 'tip'
|
||||
path = '/'
|
||||
|
|
|
|||
|
|
@ -47,9 +47,14 @@ class TestApiUpdateRepo(object):
|
|||
({'enable_statistics': True}, SAME_AS_UPDATES),
|
||||
({'enable_locking': True}, SAME_AS_UPDATES),
|
||||
({'enable_downloads': True}, SAME_AS_UPDATES),
|
||||
({'name': 'new_repo_name'}, {'repo_name': 'new_repo_name'}),
|
||||
({'group': 'test_group_for_update'},
|
||||
{'repo_name': 'test_group_for_update/%s' % UPDATE_REPO_NAME}),
|
||||
({'name': 'new_repo_name'}, {
|
||||
'repo_name': 'new_repo_name',
|
||||
'url': 'http://test.example.com:80/new_repo_name',
|
||||
}),
|
||||
({'group': 'test_group_for_update'}, {
|
||||
'repo_name': 'test_group_for_update/%s' % UPDATE_REPO_NAME,
|
||||
'url': 'http://test.example.com:80/test_group_for_update/%s' % UPDATE_REPO_NAME
|
||||
}),
|
||||
])
|
||||
def test_api_update_repo(self, updates, expected, backend):
|
||||
repo_name = UPDATE_REPO_NAME
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ from rhodecode.lib.vcs.exceptions import RepositoryError
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
|
||||
class OAttr(object):
|
||||
"""
|
||||
Special Option that defines other attribute, and can default to them
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import logging
|
|||
import time
|
||||
|
||||
from rhodecode.api import jsonrpc_method, JSONRPCError
|
||||
from rhodecode.api.exc import JSONRPCValidationError
|
||||
from rhodecode.api.utils import (
|
||||
Optional, OAttr, get_gist_or_error, get_user_or_error,
|
||||
has_superadmin_permission)
|
||||
|
|
@ -96,7 +97,8 @@ def get_gists(request, apiuser, userid=Optional(OAttr('apiuser'))):
|
|||
|
||||
@jsonrpc_method()
|
||||
def create_gist(
|
||||
request, apiuser, files, owner=Optional(OAttr('apiuser')),
|
||||
request, apiuser, files, gistid=Optional(None),
|
||||
owner=Optional(OAttr('apiuser')),
|
||||
gist_type=Optional(Gist.GIST_PUBLIC), lifetime=Optional(-1),
|
||||
acl_level=Optional(Gist.ACL_LEVEL_PUBLIC),
|
||||
description=Optional('')):
|
||||
|
|
@ -108,10 +110,11 @@ def create_gist(
|
|||
:param files: files to be added to the gist. The data structure has
|
||||
to match the following example::
|
||||
|
||||
{'filename': {'content':'...', 'lexer': null},
|
||||
'filename2': {'content':'...', 'lexer': null}}
|
||||
{'filename1': {'content':'...'}, 'filename2': {'content':'...'}}
|
||||
|
||||
:type files: dict
|
||||
:param gistid: Set a custom id for the gist
|
||||
:type gistid: Optional(str)
|
||||
:param owner: Set the gist owner, defaults to api method caller
|
||||
:type owner: Optional(str or int)
|
||||
:param gist_type: type of gist ``public`` or ``private``
|
||||
|
|
@ -148,23 +151,49 @@ def create_gist(
|
|||
}
|
||||
|
||||
"""
|
||||
from rhodecode.model import validation_schema
|
||||
from rhodecode.model.validation_schema.schemas import gist_schema
|
||||
|
||||
if isinstance(owner, Optional):
|
||||
owner = apiuser.user_id
|
||||
|
||||
owner = get_user_or_error(owner)
|
||||
|
||||
lifetime = Optional.extract(lifetime)
|
||||
schema = gist_schema.GistSchema().bind(
|
||||
# bind the given values if it's allowed, however the deferred
|
||||
# validator will still validate it according to other rules
|
||||
lifetime_options=[lifetime])
|
||||
|
||||
try:
|
||||
if isinstance(owner, Optional):
|
||||
owner = apiuser.user_id
|
||||
nodes = gist_schema.nodes_to_sequence(
|
||||
files, colander_node=schema.get('nodes'))
|
||||
|
||||
owner = get_user_or_error(owner)
|
||||
description = Optional.extract(description)
|
||||
gist_type = Optional.extract(gist_type)
|
||||
lifetime = Optional.extract(lifetime)
|
||||
acl_level = Optional.extract(acl_level)
|
||||
schema_data = schema.deserialize(dict(
|
||||
gistid=Optional.extract(gistid),
|
||||
description=Optional.extract(description),
|
||||
gist_type=Optional.extract(gist_type),
|
||||
lifetime=lifetime,
|
||||
gist_acl_level=Optional.extract(acl_level),
|
||||
nodes=nodes
|
||||
))
|
||||
|
||||
gist = GistModel().create(description=description,
|
||||
owner=owner,
|
||||
gist_mapping=files,
|
||||
gist_type=gist_type,
|
||||
lifetime=lifetime,
|
||||
gist_acl_level=acl_level)
|
||||
# convert to safer format with just KEYs so we sure no duplicates
|
||||
schema_data['nodes'] = gist_schema.sequence_to_nodes(
|
||||
schema_data['nodes'], colander_node=schema.get('nodes'))
|
||||
|
||||
except validation_schema.Invalid as err:
|
||||
raise JSONRPCValidationError(colander_exc=err)
|
||||
|
||||
try:
|
||||
gist = GistModel().create(
|
||||
owner=owner,
|
||||
gist_id=schema_data['gistid'],
|
||||
description=schema_data['description'],
|
||||
gist_mapping=schema_data['nodes'],
|
||||
gist_type=schema_data['gist_type'],
|
||||
lifetime=schema_data['lifetime'],
|
||||
gist_acl_level=schema_data['gist_acl_level'])
|
||||
Session().commit()
|
||||
return {
|
||||
'msg': 'created new gist',
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ def merge_pull_request(request, apiuser, repoid, pullrequestid,
|
|||
PullRequestModel().close_pull_request(
|
||||
pull_request.pull_request_id, apiuser)
|
||||
|
||||
Session.commit()
|
||||
Session().commit()
|
||||
return data
|
||||
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ def close_pull_request(request, apiuser, repoid, pullrequestid,
|
|||
|
||||
PullRequestModel().close_pull_request(
|
||||
pull_request.pull_request_id, apiuser)
|
||||
Session.commit()
|
||||
Session().commit()
|
||||
data = {
|
||||
'pull_request_id': pull_request.pull_request_id,
|
||||
'closed': True,
|
||||
|
|
@ -408,6 +408,8 @@ def comment_pull_request(request, apiuser, repoid, pullrequestid,
|
|||
line_no=None,
|
||||
status_change=(ChangesetStatus.get_status_lbl(status)
|
||||
if status and allowed_to_change_status else None),
|
||||
status_change_type=(status
|
||||
if status and allowed_to_change_status else None),
|
||||
closing_pr=False,
|
||||
renderer=renderer
|
||||
)
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ from rhodecode.model.db import (
|
|||
from rhodecode.model.repo import RepoModel
|
||||
from rhodecode.model.repo_group import RepoGroupModel
|
||||
from rhodecode.model.scm import ScmModel, RepoList
|
||||
from rhodecode.model.settings import SettingsModel
|
||||
from rhodecode.model.validation_schema import RepoSchema
|
||||
from rhodecode.model.settings import SettingsModel, VcsSettingsModel
|
||||
from rhodecode.model.validation_schema.schemas import repo_schema
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -400,7 +400,8 @@ def get_repo_changesets(request, apiuser, repoid, start_rev, limit,
|
|||
|
||||
@jsonrpc_method()
|
||||
def get_repo_nodes(request, apiuser, repoid, revision, root_path,
|
||||
ret_type=Optional('all'), details=Optional('basic')):
|
||||
ret_type=Optional('all'), details=Optional('basic'),
|
||||
max_file_bytes=Optional(None)):
|
||||
"""
|
||||
Returns a list of nodes and children in a flat list for a given
|
||||
path at given revision.
|
||||
|
|
@ -425,6 +426,8 @@ def get_repo_nodes(request, apiuser, repoid, revision, root_path,
|
|||
md5, binary, and or content. The valid options are ``basic`` and
|
||||
``full``.
|
||||
:type details: Optional(str)
|
||||
:param max_file_bytes: Only return file content under this file size bytes
|
||||
:type details: Optional(int)
|
||||
|
||||
Example output:
|
||||
|
||||
|
|
@ -472,7 +475,8 @@ def get_repo_nodes(request, apiuser, repoid, revision, root_path,
|
|||
|
||||
_d, _f = ScmModel().get_nodes(
|
||||
repo, revision, root_path, flat=False,
|
||||
extended_info=extended_info, content=content)
|
||||
extended_info=extended_info, content=content,
|
||||
max_file_bytes=max_file_bytes)
|
||||
_map = {
|
||||
'all': _d + _f,
|
||||
'files': _f,
|
||||
|
|
@ -606,7 +610,7 @@ def create_repo(request, apiuser, repo_name, repo_type,
|
|||
}
|
||||
|
||||
"""
|
||||
schema = RepoSchema()
|
||||
schema = repo_schema.RepoSchema()
|
||||
try:
|
||||
data = schema.deserialize({
|
||||
'repo_name': repo_name
|
||||
|
|
@ -1310,8 +1314,6 @@ def comment_commit(
|
|||
userid=Optional(OAttr('apiuser')), status=Optional(None)):
|
||||
"""
|
||||
Set a commit comment, and optionally change the status of the commit.
|
||||
This command can be executed only using api_key belonging to user
|
||||
with admin rights, or repository administrator.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
|
|
@ -1344,7 +1346,7 @@ def comment_commit(
|
|||
"""
|
||||
repo = get_repo_or_error(repoid)
|
||||
if not has_superadmin_permission(apiuser):
|
||||
_perms = ('repository.admin',)
|
||||
_perms = ('repository.read', 'repository.write', 'repository.admin')
|
||||
has_repo_permissions(apiuser, repoid, repo, _perms)
|
||||
|
||||
if isinstance(userid, Optional):
|
||||
|
|
@ -1361,9 +1363,11 @@ def comment_commit(
|
|||
try:
|
||||
rc_config = SettingsModel().get_all_settings()
|
||||
renderer = rc_config.get('rhodecode_markup_renderer', 'rst')
|
||||
|
||||
status_change_label = ChangesetStatus.get_status_lbl(status)
|
||||
comm = ChangesetCommentsModel().create(
|
||||
message, repo, user, revision=commit_id, status_change=status,
|
||||
message, repo, user, revision=commit_id,
|
||||
status_change=status_change_label,
|
||||
status_change_type=status,
|
||||
renderer=renderer)
|
||||
if status:
|
||||
# also do a status change
|
||||
|
|
@ -1775,3 +1779,110 @@ def strip(request, apiuser, repoid, revision, branch):
|
|||
'Unable to strip commit %s from repo `%s`' % (
|
||||
revision, repo.repo_name)
|
||||
)
|
||||
|
||||
|
||||
@jsonrpc_method()
|
||||
def get_repo_settings(request, apiuser, repoid, key=Optional(None)):
|
||||
"""
|
||||
Returns all settings for a repository. If key is given it only returns the
|
||||
setting identified by the key or null.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository id.
|
||||
:type repoid: str or int
|
||||
:param key: Key of the setting to return.
|
||||
:type: key: Optional(str)
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": 237,
|
||||
"result": {
|
||||
"extensions_largefiles": true,
|
||||
"hooks_changegroup_push_logger": true,
|
||||
"hooks_changegroup_repo_size": false,
|
||||
"hooks_outgoing_pull_logger": true,
|
||||
"phases_publish": "True",
|
||||
"rhodecode_hg_use_rebase_for_merging": true,
|
||||
"rhodecode_pr_merge_enabled": true,
|
||||
"rhodecode_use_outdated_comments": true
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
# Restrict access to this api method to admins only.
|
||||
if not has_superadmin_permission(apiuser):
|
||||
raise JSONRPCForbidden()
|
||||
|
||||
try:
|
||||
repo = get_repo_or_error(repoid)
|
||||
settings_model = VcsSettingsModel(repo=repo)
|
||||
settings = settings_model.get_global_settings()
|
||||
settings.update(settings_model.get_repo_settings())
|
||||
|
||||
# If only a single setting is requested fetch it from all settings.
|
||||
key = Optional.extract(key)
|
||||
if key is not None:
|
||||
settings = settings.get(key, None)
|
||||
except Exception:
|
||||
msg = 'Failed to fetch settings for repository `{}`'.format(repoid)
|
||||
log.exception(msg)
|
||||
raise JSONRPCError(msg)
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
@jsonrpc_method()
|
||||
def set_repo_settings(request, apiuser, repoid, settings):
|
||||
"""
|
||||
Update repository settings. Returns true on success.
|
||||
|
||||
:param apiuser: This is filled automatically from the |authtoken|.
|
||||
:type apiuser: AuthUser
|
||||
:param repoid: The repository name or repository id.
|
||||
:type repoid: str or int
|
||||
:param settings: The new settings for the repository.
|
||||
:type: settings: dict
|
||||
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"error": null,
|
||||
"id": 237,
|
||||
"result": true
|
||||
}
|
||||
"""
|
||||
# Restrict access to this api method to admins only.
|
||||
if not has_superadmin_permission(apiuser):
|
||||
raise JSONRPCForbidden()
|
||||
|
||||
if type(settings) is not dict:
|
||||
raise JSONRPCError('Settings have to be a JSON Object.')
|
||||
|
||||
try:
|
||||
settings_model = VcsSettingsModel(repo=repoid)
|
||||
|
||||
# Merge global, repo and incoming settings.
|
||||
new_settings = settings_model.get_global_settings()
|
||||
new_settings.update(settings_model.get_repo_settings())
|
||||
new_settings.update(settings)
|
||||
|
||||
# Update the settings.
|
||||
inherit_global_settings = new_settings.get(
|
||||
'inherit_global_settings', False)
|
||||
settings_model.create_or_update_repo_settings(
|
||||
new_settings, inherit_global_settings=inherit_global_settings)
|
||||
Session().commit()
|
||||
except Exception:
|
||||
msg = 'Failed to update settings for repository `{}`'.format(repoid)
|
||||
log.exception(msg)
|
||||
raise JSONRPCError(msg)
|
||||
|
||||
# Indicate success.
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ from rhodecode.lib.auth import (
|
|||
from rhodecode.model.db import Session, RepoGroup
|
||||
from rhodecode.model.repo_group import RepoGroupModel
|
||||
from rhodecode.model.scm import RepoGroupList
|
||||
from rhodecode.model.validation_schema import RepoGroupSchema
|
||||
from rhodecode.model.validation_schema.schemas import repo_group_schema
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
@ -193,7 +193,7 @@ def create_repo_group(request, apiuser, group_name, description=Optional(''),
|
|||
|
||||
"""
|
||||
|
||||
schema = RepoGroupSchema()
|
||||
schema = repo_group_schema.RepoGroupSchema()
|
||||
try:
|
||||
data = schema.deserialize({
|
||||
'group_name': group_name
|
||||
|
|
|
|||
|
|
@ -490,20 +490,26 @@ def loadplugin(plugin_id):
|
|||
or None on failure.
|
||||
"""
|
||||
# TODO: Disusing pyramids thread locals to retrieve the registry.
|
||||
authn_registry = get_current_registry().getUtility(IAuthnPluginRegistry)
|
||||
authn_registry = get_authn_registry()
|
||||
plugin = authn_registry.get_plugin(plugin_id)
|
||||
if plugin is None:
|
||||
log.error('Authentication plugin not found: "%s"', plugin_id)
|
||||
return plugin
|
||||
|
||||
|
||||
def get_authn_registry(registry=None):
|
||||
registry = registry or get_current_registry()
|
||||
authn_registry = registry.getUtility(IAuthnPluginRegistry)
|
||||
return authn_registry
|
||||
|
||||
|
||||
def get_auth_cache_manager(custom_ttl=None):
|
||||
return caches.get_cache_manager(
|
||||
'auth_plugins', 'rhodecode.authentication', custom_ttl)
|
||||
|
||||
|
||||
def authenticate(username, password, environ=None, auth_type=None,
|
||||
skip_missing=False):
|
||||
skip_missing=False, registry=None):
|
||||
"""
|
||||
Authentication function used for access control,
|
||||
It tries to authenticate based on enabled authentication modules.
|
||||
|
|
@ -520,7 +526,7 @@ def authenticate(username, password, environ=None, auth_type=None,
|
|||
% auth_type)
|
||||
headers_only = environ and not (username and password)
|
||||
|
||||
authn_registry = get_current_registry().getUtility(IAuthnPluginRegistry)
|
||||
authn_registry = get_authn_registry(registry)
|
||||
for plugin in authn_registry.get_plugins_for_authentication():
|
||||
plugin.set_auth_type(auth_type)
|
||||
user = plugin.get_user(username)
|
||||
|
|
@ -559,16 +565,16 @@ def authenticate(username, password, environ=None, auth_type=None,
|
|||
if isinstance(plugin.AUTH_CACHE_TTL, (int, long)):
|
||||
# plugin cache set inside is more important than the settings value
|
||||
_cache_ttl = plugin.AUTH_CACHE_TTL
|
||||
elif plugin_settings.get('auth_cache_ttl'):
|
||||
_cache_ttl = safe_int(plugin_settings.get('auth_cache_ttl'), 0)
|
||||
elif plugin_settings.get('cache_ttl'):
|
||||
_cache_ttl = safe_int(plugin_settings.get('cache_ttl'), 0)
|
||||
|
||||
plugin_cache_active = bool(_cache_ttl and _cache_ttl > 0)
|
||||
|
||||
# get instance of cache manager configured for a namespace
|
||||
cache_manager = get_auth_cache_manager(custom_ttl=_cache_ttl)
|
||||
|
||||
log.debug('Cache for plugin `%s` active: %s', plugin.get_id(),
|
||||
plugin_cache_active)
|
||||
log.debug('AUTH_CACHE_TTL for plugin `%s` active: %s (TTL: %s)',
|
||||
plugin.get_id(), plugin_cache_active, _cache_ttl)
|
||||
|
||||
# for environ based password can be empty, but then the validation is
|
||||
# on the server that fills in the env data needed for authentication
|
||||
|
|
@ -581,8 +587,7 @@ def authenticate(username, password, environ=None, auth_type=None,
|
|||
# to RhodeCode database. If this function returns data
|
||||
# then auth is correct.
|
||||
start = time.time()
|
||||
log.debug('Running plugin `%s` _authenticate method',
|
||||
plugin.get_id())
|
||||
log.debug('Running plugin `%s` _authenticate method', plugin.get_id())
|
||||
|
||||
def auth_func():
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -141,9 +141,9 @@ class LdapSettingsSchema(AuthnPluginSettingsSchemaBase):
|
|||
colander.String(),
|
||||
default='',
|
||||
description=_('LDAP Attribute to map to user name'),
|
||||
missing_msg=_('The LDAP Login attribute of the CN must be specified'),
|
||||
preparer=strip_whitespace,
|
||||
title=_('Login Attribute'),
|
||||
missing_msg=_('The LDAP Login attribute of the CN must be specified'),
|
||||
widget='string')
|
||||
attr_firstname = colander.SchemaNode(
|
||||
colander.String(),
|
||||
|
|
@ -186,6 +186,7 @@ class AuthLdap(object):
|
|||
if ldap == Missing:
|
||||
raise LdapImportError("Missing or incompatible ldap library")
|
||||
|
||||
self.debug = False
|
||||
self.ldap_version = ldap_version
|
||||
self.ldap_server_type = 'ldap'
|
||||
|
||||
|
|
@ -213,6 +214,8 @@ class AuthLdap(object):
|
|||
self.LDAP_FILTER = safe_str(ldap_filter)
|
||||
|
||||
def _get_ldap_server(self):
|
||||
if self.debug:
|
||||
ldap.set_option(ldap.OPT_DEBUG_LEVEL, 255)
|
||||
if hasattr(ldap, 'OPT_X_TLS_CACERTDIR'):
|
||||
ldap.set_option(ldap.OPT_X_TLS_CACERTDIR,
|
||||
'/etc/openldap/cacerts')
|
||||
|
|
|
|||
|
|
@ -137,5 +137,7 @@ class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
|
|||
"authenticating on this plugin", userobj)
|
||||
return None
|
||||
else:
|
||||
log.warning('user %s tried auth but is disabled', userobj)
|
||||
log.warning(
|
||||
'user `%s` failed to authenticate via %s, reason: account not '
|
||||
'active.', username, self.name)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -83,13 +83,17 @@ class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
|
|||
allowed_auth_plugins=None, allowed_auth_sources=None):
|
||||
"""
|
||||
Custom method for this auth that doesn't accept empty users. And also
|
||||
allows rhodecode and authtoken extern_type to auth with this. But only
|
||||
via vcs mode
|
||||
allows users from all other active plugins to use it and also
|
||||
authenticate against it. But only via vcs mode
|
||||
"""
|
||||
# only this and rhodecode plugins can use this type
|
||||
from rhodecode.authentication.plugins import auth_rhodecode
|
||||
allowed_auth_plugins = [
|
||||
self.name, auth_rhodecode.RhodeCodeAuthPlugin.name]
|
||||
from rhodecode.authentication.base import get_authn_registry
|
||||
authn_registry = get_authn_registry()
|
||||
|
||||
active_plugins = set(
|
||||
[x.name for x in authn_registry.get_plugins_for_authentication()])
|
||||
active_plugins.discard(self.name)
|
||||
|
||||
allowed_auth_plugins = [self.name] + list(active_plugins)
|
||||
# only for vcs operations
|
||||
allowed_auth_sources = [VCS_TYPE]
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ from pyramid.httpexceptions import HTTPFound
|
|||
from pyramid.renderers import render
|
||||
from pyramid.response import Response
|
||||
|
||||
from rhodecode.authentication.base import get_auth_cache_manager
|
||||
from rhodecode.authentication.interface import IAuthnPluginRegistry
|
||||
from rhodecode.authentication.base import (
|
||||
get_auth_cache_manager, get_authn_registry)
|
||||
from rhodecode.lib import auth
|
||||
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
|
||||
from rhodecode.model.forms import AuthSettingsForm
|
||||
|
|
@ -96,7 +96,7 @@ class AuthnPluginViewBase(object):
|
|||
# Store validated data.
|
||||
for name, value in valid_data.items():
|
||||
self.plugin.create_or_update_setting(name, value)
|
||||
Session.commit()
|
||||
Session().commit()
|
||||
|
||||
# Display success message and redirect.
|
||||
self.request.session.flash(
|
||||
|
|
@ -125,7 +125,7 @@ class AuthSettingsView(object):
|
|||
@HasPermissionAllDecorator('hg.admin')
|
||||
def index(self, defaults=None, errors=None, prefix_error=False):
|
||||
defaults = defaults or {}
|
||||
authn_registry = self.request.registry.getUtility(IAuthnPluginRegistry)
|
||||
authn_registry = get_authn_registry(self.request.registry)
|
||||
enabled_plugins = SettingsModel().get_auth_plugins()
|
||||
|
||||
# Create template context and render it.
|
||||
|
|
|
|||
79
rhodecode/channelstream/__init__.py
Normal file
79
rhodecode/channelstream/__init__.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2010-2016 RhodeCode GmbH
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License, version 3
|
||||
# (only), as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# This program is dual-licensed. If you wish to learn more about the
|
||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
|
||||
import os
|
||||
|
||||
from pyramid.settings import asbool
|
||||
|
||||
from rhodecode.config.routing import ADMIN_PREFIX
|
||||
from rhodecode.lib.ext_json import json
|
||||
|
||||
|
||||
def url_gen(request):
|
||||
urls = {
|
||||
'connect': request.route_url('channelstream_connect'),
|
||||
'subscribe': request.route_url('channelstream_subscribe')
|
||||
}
|
||||
return json.dumps(urls)
|
||||
|
||||
|
||||
PLUGIN_DEFINITION = {
|
||||
'name': 'channelstream',
|
||||
'config': {
|
||||
'javascript': [],
|
||||
'css': [],
|
||||
'template_hooks': {
|
||||
'plugin_init_template': 'rhodecode:templates/channelstream/plugin_init.html'
|
||||
},
|
||||
'url_gen': url_gen,
|
||||
'static': None,
|
||||
'enabled': False,
|
||||
'server': '',
|
||||
'secret': ''
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def includeme(config):
|
||||
settings = config.registry.settings
|
||||
PLUGIN_DEFINITION['config']['enabled'] = asbool(
|
||||
settings.get('channelstream.enabled'))
|
||||
PLUGIN_DEFINITION['config']['server'] = settings.get(
|
||||
'channelstream.server', '')
|
||||
PLUGIN_DEFINITION['config']['secret'] = settings.get(
|
||||
'channelstream.secret', '')
|
||||
PLUGIN_DEFINITION['config']['history.location'] = settings.get(
|
||||
'channelstream.history.location', '')
|
||||
config.register_rhodecode_plugin(
|
||||
PLUGIN_DEFINITION['name'],
|
||||
PLUGIN_DEFINITION['config']
|
||||
)
|
||||
# create plugin history location
|
||||
history_dir = PLUGIN_DEFINITION['config']['history.location']
|
||||
if history_dir and not os.path.exists(history_dir):
|
||||
os.makedirs(history_dir, 0750)
|
||||
|
||||
config.add_route(
|
||||
name='channelstream_connect',
|
||||
pattern=ADMIN_PREFIX + '/channelstream/connect')
|
||||
config.add_route(
|
||||
name='channelstream_subscribe',
|
||||
pattern=ADMIN_PREFIX + '/channelstream/subscribe')
|
||||
config.scan('rhodecode.channelstream')
|
||||
177
rhodecode/channelstream/views.py
Normal file
177
rhodecode/channelstream/views.py
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2010-2016 RhodeCode GmbH
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License, version 3
|
||||
# (only), as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# This program is dual-licensed. If you wish to learn more about the
|
||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
|
||||
"""
|
||||
Channel Stream controller for rhodecode
|
||||
|
||||
:created_on: Oct 10, 2015
|
||||
:author: marcinl
|
||||
:copyright: (c) 2013-2015 RhodeCode GmbH.
|
||||
:license: Commercial License, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from pylons import tmpl_context as c
|
||||
from pyramid.settings import asbool
|
||||
from pyramid.view import view_config
|
||||
from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPBadGateway
|
||||
|
||||
from rhodecode.lib.channelstream import (
|
||||
channelstream_request,
|
||||
ChannelstreamConnectionException,
|
||||
ChannelstreamPermissionException,
|
||||
check_channel_permissions,
|
||||
get_connection_validators,
|
||||
get_user_data,
|
||||
parse_channels_info,
|
||||
update_history_from_logs,
|
||||
STATE_PUBLIC_KEYS)
|
||||
from rhodecode.lib.auth import NotAnonymous
|
||||
from rhodecode.lib.utils2 import str2bool
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ChannelstreamView(object):
|
||||
def __init__(self, context, request):
|
||||
self.context = context
|
||||
self.request = request
|
||||
|
||||
# Some of the decorators rely on this attribute to be present
|
||||
# on the class of the decorated method.
|
||||
self._rhodecode_user = request.user
|
||||
registry = request.registry
|
||||
self.channelstream_config = registry.rhodecode_plugins['channelstream']
|
||||
if not self.channelstream_config.get('enabled'):
|
||||
log.exception('Channelstream plugin is disabled')
|
||||
raise HTTPBadRequest()
|
||||
|
||||
@NotAnonymous()
|
||||
@view_config(route_name='channelstream_connect', renderer='json')
|
||||
def connect(self):
|
||||
""" handle authorization of users trying to connect """
|
||||
try:
|
||||
json_body = self.request.json_body
|
||||
except Exception:
|
||||
log.exception('Failed to decode json from request')
|
||||
raise HTTPBadRequest()
|
||||
try:
|
||||
channels = check_channel_permissions(
|
||||
json_body.get('channels'),
|
||||
get_connection_validators(self.request.registry))
|
||||
except ChannelstreamPermissionException:
|
||||
log.error('Incorrect permissions for requested channels')
|
||||
raise HTTPForbidden()
|
||||
|
||||
user = c.rhodecode_user
|
||||
if user.user_id:
|
||||
user_data = get_user_data(user.user_id)
|
||||
else:
|
||||
user_data = {
|
||||
'id': None,
|
||||
'username': None,
|
||||
'first_name': None,
|
||||
'last_name': None,
|
||||
'icon_link': None,
|
||||
'display_name': None,
|
||||
'display_link': None,
|
||||
}
|
||||
payload = {
|
||||
'username': user.username,
|
||||
'user_state': user_data,
|
||||
'conn_id': str(uuid.uuid4()),
|
||||
'channels': channels,
|
||||
'channel_configs': {},
|
||||
'state_public_keys': STATE_PUBLIC_KEYS,
|
||||
'info': {
|
||||
'exclude_channels': ['broadcast']
|
||||
}
|
||||
}
|
||||
filtered_channels = [channel for channel in channels
|
||||
if channel != 'broadcast']
|
||||
for channel in filtered_channels:
|
||||
payload['channel_configs'][channel] = {
|
||||
'notify_presence': True,
|
||||
'history_size': 100,
|
||||
'store_history': True,
|
||||
'broadcast_presence_with_user_lists': True
|
||||
}
|
||||
# connect user to server
|
||||
try:
|
||||
connect_result = channelstream_request(self.channelstream_config,
|
||||
payload, '/connect')
|
||||
except ChannelstreamConnectionException:
|
||||
log.exception('Channelstream service is down')
|
||||
return HTTPBadGateway()
|
||||
|
||||
connect_result['channels'] = channels
|
||||
connect_result['channels_info'] = parse_channels_info(
|
||||
connect_result['channels_info'],
|
||||
include_channel_info=filtered_channels)
|
||||
update_history_from_logs(self.channelstream_config,
|
||||
filtered_channels, connect_result)
|
||||
return connect_result
|
||||
|
||||
@NotAnonymous()
|
||||
@view_config(route_name='channelstream_subscribe', renderer='json')
|
||||
def subscribe(self):
|
||||
""" can be used to subscribe specific connection to other channels """
|
||||
try:
|
||||
json_body = self.request.json_body
|
||||
except Exception:
|
||||
log.exception('Failed to decode json from request')
|
||||
raise HTTPBadRequest()
|
||||
try:
|
||||
channels = check_channel_permissions(
|
||||
json_body.get('channels'),
|
||||
get_connection_validators(self.request.registry))
|
||||
except ChannelstreamPermissionException:
|
||||
log.error('Incorrect permissions for requested channels')
|
||||
raise HTTPForbidden()
|
||||
payload = {'conn_id': json_body.get('conn_id', ''),
|
||||
'channels': channels,
|
||||
'channel_configs': {},
|
||||
'info': {
|
||||
'exclude_channels': ['broadcast']}
|
||||
}
|
||||
filtered_channels = [chan for chan in channels if chan != 'broadcast']
|
||||
for channel in filtered_channels:
|
||||
payload['channel_configs'][channel] = {
|
||||
'notify_presence': True,
|
||||
'history_size': 100,
|
||||
'store_history': True,
|
||||
'broadcast_presence_with_user_lists': True
|
||||
}
|
||||
try:
|
||||
connect_result = channelstream_request(
|
||||
self.channelstream_config, payload, '/subscribe')
|
||||
except ChannelstreamConnectionException:
|
||||
log.exception('Channelstream service is down')
|
||||
return HTTPBadGateway()
|
||||
# include_channel_info will limit history only to new channel
|
||||
# to not overwrite histories on other channels in client
|
||||
connect_result['channels_info'] = parse_channels_info(
|
||||
connect_result['channels_info'],
|
||||
include_channel_info=filtered_channels)
|
||||
update_history_from_logs(self.channelstream_config,
|
||||
filtered_channels, connect_result)
|
||||
return connect_result
|
||||
|
|
@ -30,36 +30,6 @@ from rhodecode.lib.utils2 import __get_lem
|
|||
# extensions will index it's content
|
||||
LANGUAGES_EXTENSIONS_MAP = __get_lem()
|
||||
|
||||
# list of readme files to search in file tree and display in summary
|
||||
# attached weights defines the search order lower is first
|
||||
ALL_READMES = [
|
||||
('readme', 0), ('README', 0), ('Readme', 0),
|
||||
('doc/readme', 1), ('doc/README', 1), ('doc/Readme', 1),
|
||||
('Docs/readme', 2), ('Docs/README', 2), ('Docs/Readme', 2),
|
||||
('DOCS/readme', 2), ('DOCS/README', 2), ('DOCS/Readme', 2),
|
||||
('docs/readme', 2), ('docs/README', 2), ('docs/Readme', 2),
|
||||
]
|
||||
|
||||
# extension together with weights to search lower is first
|
||||
RST_EXTS = [
|
||||
('', 0), ('.rst', 1), ('.rest', 1),
|
||||
('.RST', 2), ('.REST', 2)
|
||||
]
|
||||
|
||||
MARKDOWN_EXTS = [
|
||||
('.md', 1), ('.MD', 1),
|
||||
('.mkdn', 2), ('.MKDN', 2),
|
||||
('.mdown', 3), ('.MDOWN', 3),
|
||||
('.markdown', 4), ('.MARKDOWN', 4)
|
||||
]
|
||||
|
||||
PLAIN_EXTS = [
|
||||
('.text', 2), ('.TEXT', 2),
|
||||
('.txt', 3), ('.TXT', 3)
|
||||
]
|
||||
|
||||
ALL_EXTS = MARKDOWN_EXTS + RST_EXTS + PLAIN_EXTS
|
||||
|
||||
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
DATE_FORMAT = "%Y-%m-%d"
|
||||
|
|
|
|||
|
|
@ -34,11 +34,16 @@ from pylons.configuration import PylonsConfig
|
|||
from pylons.error import handle_mako_error
|
||||
from pyramid.settings import asbool
|
||||
|
||||
# don't remove this import it does magic for celery
|
||||
from rhodecode.lib import celerypylons # noqa
|
||||
# ------------------------------------------------------------------------------
|
||||
# CELERY magic until refactor - issue #4163 - import order matters here:
|
||||
from rhodecode.lib import celerypylons # this must be first, celerypylons
|
||||
# sets config settings upon import
|
||||
|
||||
import rhodecode.lib.app_globals as app_globals
|
||||
import rhodecode.integrations # any modules using celery task
|
||||
# decorators should be added afterwards:
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from rhodecode.lib import app_globals
|
||||
from rhodecode.config import utils
|
||||
from rhodecode.config.routing import make_map
|
||||
from rhodecode.config.jsroutes import generate_jsroutes_content
|
||||
|
|
@ -112,25 +117,12 @@ def load_environment(global_conf, app_conf, initial=False,
|
|||
# sets the c attribute access when don't existing attribute are accessed
|
||||
config['pylons.strict_tmpl_context'] = True
|
||||
|
||||
# Limit backends to "vcs.backends" from configuration
|
||||
backends = config['vcs.backends'] = aslist(
|
||||
config.get('vcs.backends', 'hg,git'), sep=',')
|
||||
for alias in rhodecode.BACKENDS.keys():
|
||||
if alias not in backends:
|
||||
del rhodecode.BACKENDS[alias]
|
||||
log.info("Enabled backends: %s", backends)
|
||||
|
||||
# initialize vcs client and optionally run the server if enabled
|
||||
vcs_server_uri = config.get('vcs.server', '')
|
||||
vcs_server_enabled = str2bool(config.get('vcs.server.enable', 'true'))
|
||||
start_server = (
|
||||
str2bool(config.get('vcs.start_server', 'false')) and
|
||||
not int(os.environ.get('RC_VCSSERVER_TEST_DISABLE', '0')))
|
||||
if vcs_server_enabled and start_server:
|
||||
log.info("Starting vcsserver")
|
||||
start_vcs_server(server_and_port=vcs_server_uri,
|
||||
protocol=utils.get_vcs_server_protocol(config),
|
||||
log_level=config['vcs.server.log_level'])
|
||||
# configure channelstream
|
||||
config['channelstream_config'] = {
|
||||
'enabled': asbool(config.get('channelstream.enabled', False)),
|
||||
'server': config.get('channelstream.server'),
|
||||
'secret': config.get('channelstream.secret')
|
||||
}
|
||||
|
||||
set_available_permissions(config)
|
||||
db_cfg = make_db_config(clear_session=True)
|
||||
|
|
@ -138,9 +130,6 @@ def load_environment(global_conf, app_conf, initial=False,
|
|||
repos_path = list(db_cfg.items('paths'))[0][1]
|
||||
config['base_path'] = repos_path
|
||||
|
||||
config['vcs.hooks.direct_calls'] = _use_direct_hook_calls(config)
|
||||
config['vcs.hooks.protocol'] = _get_vcs_hooks_protocol(config)
|
||||
|
||||
# store db config also in main global CONFIG
|
||||
set_rhodecode_config(config)
|
||||
|
||||
|
|
@ -153,34 +142,17 @@ def load_environment(global_conf, app_conf, initial=False,
|
|||
# store config reference into our module to skip import magic of pylons
|
||||
rhodecode.CONFIG.update(config)
|
||||
|
||||
utils.configure_pyro4(config)
|
||||
utils.configure_vcs(config)
|
||||
if vcs_server_enabled:
|
||||
connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(config))
|
||||
|
||||
import_on_startup = str2bool(config.get('startup.import_repos', False))
|
||||
if vcs_server_enabled and import_on_startup:
|
||||
repo2db_mapper(ScmModel().repo_scan(repos_path), remove_obsolete=False)
|
||||
return config
|
||||
|
||||
|
||||
def _use_direct_hook_calls(config):
|
||||
default_direct_hook_calls = 'false'
|
||||
direct_hook_calls = str2bool(
|
||||
config.get('vcs.hooks.direct_calls', default_direct_hook_calls))
|
||||
return direct_hook_calls
|
||||
|
||||
|
||||
def _get_vcs_hooks_protocol(config):
|
||||
protocol = config.get('vcs.hooks.protocol', 'pyro4').lower()
|
||||
return protocol
|
||||
|
||||
|
||||
def load_pyramid_environment(global_config, settings):
|
||||
# Some parts of the code expect a merge of global and app settings.
|
||||
settings_merged = global_config.copy()
|
||||
settings_merged.update(settings)
|
||||
|
||||
# Store the settings to make them available to other modules.
|
||||
rhodecode.PYRAMID_SETTINGS = settings_merged
|
||||
|
||||
# If this is a test run we prepare the test environment like
|
||||
# creating a test database, test search index and test repositories.
|
||||
# This has to be done before the database connection is initialized.
|
||||
|
|
@ -190,3 +162,27 @@ def load_pyramid_environment(global_config, settings):
|
|||
|
||||
# Initialize the database connection.
|
||||
utils.initialize_database(settings_merged)
|
||||
|
||||
# Limit backends to `vcs.backends` from configuration
|
||||
for alias in rhodecode.BACKENDS.keys():
|
||||
if alias not in settings['vcs.backends']:
|
||||
del rhodecode.BACKENDS[alias]
|
||||
log.info('Enabled VCS backends: %s', rhodecode.BACKENDS.keys())
|
||||
|
||||
# initialize vcs client and optionally run the server if enabled
|
||||
vcs_server_uri = settings['vcs.server']
|
||||
vcs_server_enabled = settings['vcs.server.enable']
|
||||
start_server = (
|
||||
settings['vcs.start_server'] and
|
||||
not int(os.environ.get('RC_VCSSERVER_TEST_DISABLE', '0')))
|
||||
|
||||
if vcs_server_enabled and start_server:
|
||||
log.info("Starting vcsserver")
|
||||
start_vcs_server(server_and_port=vcs_server_uri,
|
||||
protocol=utils.get_vcs_server_protocol(settings),
|
||||
log_level=settings['vcs.server.log_level'])
|
||||
|
||||
utils.configure_pyro4(settings)
|
||||
utils.configure_vcs(settings)
|
||||
if vcs_server_enabled:
|
||||
connect_vcs(vcs_server_uri, utils.get_vcs_server_protocol(settings))
|
||||
|
|
|
|||
|
|
@ -22,23 +22,25 @@
|
|||
Pylons middleware initialization
|
||||
"""
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from paste.registry import RegistryManager
|
||||
from paste.gzipper import make_gzip_middleware
|
||||
from pylons.wsgiapp import PylonsApp
|
||||
from pyramid.authorization import ACLAuthorizationPolicy
|
||||
from pyramid.config import Configurator
|
||||
from pyramid.static import static_view
|
||||
from pyramid.settings import asbool, aslist
|
||||
from pyramid.wsgi import wsgiapp
|
||||
from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
|
||||
from pyramid.httpexceptions import HTTPError, HTTPInternalServerError, HTTPFound
|
||||
from pyramid.events import ApplicationCreated
|
||||
import pyramid.httpexceptions as httpexceptions
|
||||
from pyramid.renderers import render_to_response, render
|
||||
from pyramid.renderers import render_to_response
|
||||
from routes.middleware import RoutesMiddleware
|
||||
import routes.util
|
||||
|
||||
import rhodecode
|
||||
from rhodecode.config import patches
|
||||
from rhodecode.config.routing import STATIC_FILE_PREFIX
|
||||
from rhodecode.config.environment import (
|
||||
load_environment, load_pyramid_environment)
|
||||
from rhodecode.lib.middleware import csrf
|
||||
|
|
@ -47,24 +49,45 @@ from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
|
|||
from rhodecode.lib.middleware.https_fixup import HttpsFixup
|
||||
from rhodecode.lib.middleware.vcs import VCSMiddleware
|
||||
from rhodecode.lib.plugins.utils import register_rhodecode_plugin
|
||||
from rhodecode.lib.utils2 import aslist as rhodecode_aslist
|
||||
from rhodecode.subscribers import scan_repositories_if_enabled
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
|
||||
# this is used to avoid avoid the route lookup overhead in routesmiddleware
|
||||
# for certain routes which won't go to pylons to - eg. static files, debugger
|
||||
# it is only needed for the pylons migration and can be removed once complete
|
||||
class SkippableRoutesMiddleware(RoutesMiddleware):
|
||||
""" Routes middleware that allows you to skip prefixes """
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
self.skip_prefixes = kw.pop('skip_prefixes', [])
|
||||
super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
for prefix in self.skip_prefixes:
|
||||
if environ['PATH_INFO'].startswith(prefix):
|
||||
# added to avoid the case when a missing /_static route falls
|
||||
# through to pylons and causes an exception as pylons is
|
||||
# expecting wsgiorg.routingargs to be set in the environ
|
||||
# by RoutesMiddleware.
|
||||
if 'wsgiorg.routing_args' not in environ:
|
||||
environ['wsgiorg.routing_args'] = (None, {})
|
||||
return self.app(environ, start_response)
|
||||
|
||||
return super(SkippableRoutesMiddleware, self).__call__(
|
||||
environ, start_response)
|
||||
|
||||
|
||||
def make_app(global_conf, static_files=True, **app_conf):
|
||||
"""Create a Pylons WSGI application and return it
|
||||
|
||||
``global_conf``
|
||||
The inherited configuration for this application. Normally from
|
||||
the [DEFAULT] section of the Paste ini file.
|
||||
|
||||
``full_stack``
|
||||
Whether or not this application provides a full WSGI stack (by
|
||||
default, meaning it handles its own exceptions and errors).
|
||||
Disable full_stack when this application is "managed" by
|
||||
another WSGI middleware.
|
||||
|
||||
``app_conf``
|
||||
The application's local configuration. Normally specified in
|
||||
the [app:<name>] section of the Paste ini file (where <name>
|
||||
|
|
@ -89,16 +112,6 @@ def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
|
|||
app = csrf.OriginChecker(app, expected_origin,
|
||||
skip_urls=[routes.util.url_for('api')])
|
||||
|
||||
|
||||
if asbool(full_stack):
|
||||
|
||||
# Appenlight monitoring and error handler
|
||||
app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
|
||||
|
||||
# we want our low level middleware to get to the request ASAP. We don't
|
||||
# need any pylons stack middleware in them
|
||||
app = VCSMiddleware(app, config, appenlight_client)
|
||||
|
||||
# Establish the Registry for this application
|
||||
app = RegistryManager(app)
|
||||
|
||||
|
|
@ -140,13 +153,78 @@ def make_pyramid_app(global_config, **settings):
|
|||
|
||||
load_pyramid_environment(global_config, settings)
|
||||
|
||||
includeme_first(config)
|
||||
includeme(config)
|
||||
includeme_last(config)
|
||||
pyramid_app = config.make_wsgi_app()
|
||||
pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
|
||||
pyramid_app.config = config
|
||||
return pyramid_app
|
||||
|
||||
|
||||
def make_not_found_view(config):
|
||||
"""
|
||||
This creates the view which should be registered as not-found-view to
|
||||
pyramid. Basically it contains of the old pylons app, converted to a view.
|
||||
Additionally it is wrapped by some other middlewares.
|
||||
"""
|
||||
settings = config.registry.settings
|
||||
vcs_server_enabled = settings['vcs.server.enable']
|
||||
|
||||
# Make pylons app from unprepared settings.
|
||||
pylons_app = make_app(
|
||||
config.registry._pylons_compat_global_config,
|
||||
**config.registry._pylons_compat_settings)
|
||||
config.registry._pylons_compat_config = pylons_app.config
|
||||
|
||||
# Appenlight monitoring.
|
||||
pylons_app, appenlight_client = wrap_in_appenlight_if_enabled(
|
||||
pylons_app, settings)
|
||||
|
||||
# The VCSMiddleware shall operate like a fallback if pyramid doesn't find
|
||||
# a view to handle the request. Therefore we wrap it around the pylons app.
|
||||
if vcs_server_enabled:
|
||||
pylons_app = VCSMiddleware(
|
||||
pylons_app, settings, appenlight_client, registry=config.registry)
|
||||
|
||||
pylons_app_as_view = wsgiapp(pylons_app)
|
||||
|
||||
# Protect from VCS Server error related pages when server is not available
|
||||
if not vcs_server_enabled:
|
||||
pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
|
||||
|
||||
def pylons_app_with_error_handler(context, request):
|
||||
"""
|
||||
Handle exceptions from rc pylons app:
|
||||
|
||||
- old webob type exceptions get converted to pyramid exceptions
|
||||
- pyramid exceptions are passed to the error handler view
|
||||
"""
|
||||
def is_vcs_response(response):
|
||||
return 'X-RhodeCode-Backend' in response.headers
|
||||
|
||||
def is_http_error(response):
|
||||
# webob type error responses
|
||||
return (400 <= response.status_int <= 599)
|
||||
|
||||
def is_error_handling_needed(response):
|
||||
return is_http_error(response) and not is_vcs_response(response)
|
||||
|
||||
try:
|
||||
response = pylons_app_as_view(context, request)
|
||||
if is_error_handling_needed(response):
|
||||
response = webob_to_pyramid_http_response(response)
|
||||
return error_handler(response, request)
|
||||
except HTTPError as e: # pyramid type exceptions
|
||||
return error_handler(e, request)
|
||||
except Exception:
|
||||
if settings.get('debugtoolbar.enabled', False):
|
||||
raise
|
||||
return error_handler(HTTPInternalServerError(), request)
|
||||
return response
|
||||
|
||||
return pylons_app_with_error_handler
|
||||
|
||||
|
||||
def add_pylons_compat_data(registry, global_config, settings):
|
||||
"""
|
||||
Attach data to the registry to support the Pylons integration.
|
||||
|
|
@ -205,20 +283,32 @@ def error_handler(exception, request):
|
|||
def includeme(config):
|
||||
settings = config.registry.settings
|
||||
|
||||
# plugin information
|
||||
config.registry.rhodecode_plugins = OrderedDict()
|
||||
|
||||
config.add_directive(
|
||||
'register_rhodecode_plugin', register_rhodecode_plugin)
|
||||
|
||||
if asbool(settings.get('appenlight', 'false')):
|
||||
config.include('appenlight_client.ext.pyramid_tween')
|
||||
|
||||
# Includes which are required. The application would fail without them.
|
||||
config.include('pyramid_mako')
|
||||
config.include('pyramid_beaker')
|
||||
config.include('rhodecode.channelstream')
|
||||
config.include('rhodecode.admin')
|
||||
config.include('rhodecode.authentication')
|
||||
config.include('rhodecode.integrations')
|
||||
config.include('rhodecode.login')
|
||||
config.include('rhodecode.tweens')
|
||||
config.include('rhodecode.api')
|
||||
config.include('rhodecode.svn_support')
|
||||
config.add_route(
|
||||
'rhodecode_support', 'https://rhodecode.com/help/', static=True)
|
||||
|
||||
# Add subscribers.
|
||||
config.add_subscriber(scan_repositories_if_enabled, ApplicationCreated)
|
||||
|
||||
# Set the authorization policy.
|
||||
authz_policy = ACLAuthorizationPolicy()
|
||||
config.set_authorization_policy(authz_policy)
|
||||
|
|
@ -226,86 +316,37 @@ def includeme(config):
|
|||
# Set the default renderer for HTML templates to mako.
|
||||
config.add_mako_renderer('.html')
|
||||
|
||||
# plugin information
|
||||
config.registry.rhodecode_plugins = {}
|
||||
|
||||
config.add_directive(
|
||||
'register_rhodecode_plugin', register_rhodecode_plugin)
|
||||
# include RhodeCode plugins
|
||||
includes = aslist(settings.get('rhodecode.includes', []))
|
||||
for inc in includes:
|
||||
config.include(inc)
|
||||
|
||||
pylons_app = make_app(
|
||||
config.registry._pylons_compat_global_config,
|
||||
**config.registry._pylons_compat_settings)
|
||||
config.registry._pylons_compat_config = pylons_app.config
|
||||
|
||||
pylons_app_as_view = wsgiapp(pylons_app)
|
||||
|
||||
# Protect from VCS Server error related pages when server is not available
|
||||
vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
|
||||
if not vcs_server_enabled:
|
||||
pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
|
||||
|
||||
|
||||
def pylons_app_with_error_handler(context, request):
|
||||
"""
|
||||
Handle exceptions from rc pylons app:
|
||||
|
||||
- old webob type exceptions get converted to pyramid exceptions
|
||||
- pyramid exceptions are passed to the error handler view
|
||||
"""
|
||||
try:
|
||||
response = pylons_app_as_view(context, request)
|
||||
if 400 <= response.status_int <= 599: # webob type error responses
|
||||
return error_handler(
|
||||
webob_to_pyramid_http_response(response), request)
|
||||
except HTTPError as e: # pyramid type exceptions
|
||||
return error_handler(e, request)
|
||||
except Exception:
|
||||
if settings.get('debugtoolbar.enabled', False):
|
||||
raise
|
||||
return error_handler(HTTPInternalServerError(), request)
|
||||
return response
|
||||
|
||||
# This is the glue which allows us to migrate in chunks. By registering the
|
||||
# pylons based application as the "Not Found" view in Pyramid, we will
|
||||
# fallback to the old application each time the new one does not yet know
|
||||
# how to handle a request.
|
||||
config.add_notfound_view(pylons_app_with_error_handler)
|
||||
config.add_notfound_view(make_not_found_view(config))
|
||||
|
||||
if settings.get('debugtoolbar.enabled', False):
|
||||
# if toolbar, then only http type exceptions get caught and rendered
|
||||
ExcClass = HTTPError
|
||||
else:
|
||||
if not settings.get('debugtoolbar.enabled', False):
|
||||
# if no toolbar, then any exception gets caught and rendered
|
||||
ExcClass = Exception
|
||||
config.add_view(error_handler, context=ExcClass)
|
||||
config.add_view(error_handler, context=Exception)
|
||||
|
||||
config.add_view(error_handler, context=HTTPError)
|
||||
|
||||
|
||||
def includeme_last(config):
|
||||
"""
|
||||
The static file catchall needs to be last in the view configuration.
|
||||
"""
|
||||
settings = config.registry.settings
|
||||
def includeme_first(config):
|
||||
# redirect automatic browser favicon.ico requests to correct place
|
||||
def favicon_redirect(context, request):
|
||||
return HTTPFound(
|
||||
request.static_path('rhodecode:public/images/favicon.ico'))
|
||||
|
||||
# Note: johbo: I would prefer to register a prefix for static files at some
|
||||
# point, e.g. move them under '_static/'. This would fully avoid that we
|
||||
# can have name clashes with a repository name. Imaging someone calling his
|
||||
# repo "css" ;-) Also having an external web server to serve out the static
|
||||
# files seems to be easier to set up if they have a common prefix.
|
||||
#
|
||||
# Example: config.add_static_view('_static', path='rhodecode:public')
|
||||
#
|
||||
# It might be an option to register both paths for a while and then migrate
|
||||
# over to the new location.
|
||||
config.add_view(favicon_redirect, route_name='favicon')
|
||||
config.add_route('favicon', '/favicon.ico')
|
||||
|
||||
# Serving static files with a catchall.
|
||||
if settings['static_files']:
|
||||
config.add_route('catchall_static', '/*subpath')
|
||||
config.add_view(
|
||||
static_view('rhodecode:public'), route_name='catchall_static')
|
||||
config.add_static_view(
|
||||
'_static/deform', 'deform:static')
|
||||
config.add_static_view(
|
||||
'_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
|
||||
|
||||
|
||||
def wrap_app_in_wsgi_middlewares(pyramid_app, config):
|
||||
|
|
@ -322,19 +363,14 @@ def wrap_app_in_wsgi_middlewares(pyramid_app, config):
|
|||
pyramid_app = HttpsFixup(pyramid_app, settings)
|
||||
|
||||
# Add RoutesMiddleware to support the pylons compatibility tween during
|
||||
|
||||
# migration to pyramid.
|
||||
pyramid_app = RoutesMiddleware(
|
||||
pyramid_app, config.registry._pylons_compat_config['routes.map'])
|
||||
pyramid_app = SkippableRoutesMiddleware(
|
||||
pyramid_app, config.registry._pylons_compat_config['routes.map'],
|
||||
skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
|
||||
|
||||
if asbool(settings.get('appenlight', 'false')):
|
||||
pyramid_app, _ = wrap_in_appenlight_if_enabled(
|
||||
pyramid_app, config.registry._pylons_compat_config)
|
||||
pyramid_app, _ = wrap_in_appenlight_if_enabled(pyramid_app, settings)
|
||||
|
||||
# TODO: johbo: Don't really see why we enable the gzip middleware when
|
||||
# serving static files, might be something that should have its own setting
|
||||
# as well?
|
||||
if settings['static_files']:
|
||||
if settings['gzip_responses']:
|
||||
pyramid_app = make_gzip_middleware(
|
||||
pyramid_app, settings, compress_level=1)
|
||||
|
||||
|
|
@ -376,12 +412,63 @@ def sanitize_settings_and_apply_defaults(settings):
|
|||
# should allow to pass in a prefix.
|
||||
settings.setdefault('rhodecode.api.url', '/_admin/api')
|
||||
|
||||
_bool_setting(settings, 'vcs.server.enable', 'true')
|
||||
_bool_setting(settings, 'static_files', 'true')
|
||||
# Sanitize generic settings.
|
||||
_list_setting(settings, 'default_encoding', 'UTF-8')
|
||||
_bool_setting(settings, 'is_test', 'false')
|
||||
_bool_setting(settings, 'gzip_responses', 'false')
|
||||
|
||||
# Call split out functions that sanitize settings for each topic.
|
||||
_sanitize_appenlight_settings(settings)
|
||||
_sanitize_vcs_settings(settings)
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def _sanitize_appenlight_settings(settings):
|
||||
_bool_setting(settings, 'appenlight', 'false')
|
||||
|
||||
|
||||
def _sanitize_vcs_settings(settings):
|
||||
"""
|
||||
Applies settings defaults and does type conversion for all VCS related
|
||||
settings.
|
||||
"""
|
||||
_string_setting(settings, 'vcs.svn.compatible_version', '')
|
||||
_string_setting(settings, 'git_rev_filter', '--all')
|
||||
_string_setting(settings, 'vcs.hooks.protocol', 'pyro4')
|
||||
_string_setting(settings, 'vcs.server', '')
|
||||
_string_setting(settings, 'vcs.server.log_level', 'debug')
|
||||
_string_setting(settings, 'vcs.server.protocol', 'pyro4')
|
||||
_bool_setting(settings, 'startup.import_repos', 'false')
|
||||
_bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
|
||||
_bool_setting(settings, 'vcs.server.enable', 'true')
|
||||
_bool_setting(settings, 'vcs.start_server', 'false')
|
||||
_list_setting(settings, 'vcs.backends', 'hg, git, svn')
|
||||
_int_setting(settings, 'vcs.connection_timeout', 3600)
|
||||
|
||||
|
||||
def _int_setting(settings, name, default):
|
||||
settings[name] = int(settings.get(name, default))
|
||||
|
||||
|
||||
def _bool_setting(settings, name, default):
|
||||
settings[name] = asbool(settings.get(name, default))
|
||||
input = settings.get(name, default)
|
||||
if isinstance(input, unicode):
|
||||
input = input.encode('utf8')
|
||||
settings[name] = asbool(input)
|
||||
|
||||
|
||||
def _list_setting(settings, name, default):
|
||||
raw_value = settings.get(name, default)
|
||||
|
||||
old_separator = ','
|
||||
if old_separator in raw_value:
|
||||
# If we get a comma separated list, pass it to our own function.
|
||||
settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
|
||||
else:
|
||||
# Otherwise we assume it uses pyramids space/newline separation.
|
||||
settings[name] = aslist(raw_value)
|
||||
|
||||
|
||||
def _string_setting(settings, name, default):
|
||||
settings[name] = settings.get(name, default).lower()
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ from rhodecode.config import routing_links
|
|||
|
||||
# prefix for non repository related links needs to be prefixed with `/`
|
||||
ADMIN_PREFIX = '/_admin'
|
||||
STATIC_FILE_PREFIX = '/_static'
|
||||
|
||||
# Default requirements for URL parts
|
||||
URL_NAME_REQUIREMENTS = {
|
||||
|
|
@ -51,6 +52,19 @@ URL_NAME_REQUIREMENTS = {
|
|||
}
|
||||
|
||||
|
||||
def add_route_requirements(route_path, requirements):
|
||||
"""
|
||||
Adds regex requirements to pyramid routes using a mapping dict
|
||||
|
||||
>>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
|
||||
'/{action}/{id:\d+}'
|
||||
|
||||
"""
|
||||
for key, regex in requirements.items():
|
||||
route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
|
||||
return route_path
|
||||
|
||||
|
||||
class JSRoutesMapper(Mapper):
|
||||
"""
|
||||
Wrapper for routes.Mapper to make pyroutes compatible url definitions
|
||||
|
|
@ -546,6 +560,13 @@ def make_map(config):
|
|||
action='my_account_auth_tokens_add', conditions={'method': ['POST']})
|
||||
m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
|
||||
action='my_account_auth_tokens_delete', conditions={'method': ['DELETE']})
|
||||
m.connect('my_account_notifications', '/my_account/notifications',
|
||||
action='my_notifications',
|
||||
conditions={'method': ['GET']})
|
||||
m.connect('my_account_notifications_toggle_visibility',
|
||||
'/my_account/toggle_visibility',
|
||||
action='my_notifications_toggle_visibility',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
# NOTIFICATION REST ROUTES
|
||||
with rmap.submapper(path_prefix=ADMIN_PREFIX,
|
||||
|
|
@ -554,7 +575,6 @@ def make_map(config):
|
|||
action='index', conditions={'method': ['GET']})
|
||||
m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
|
||||
action='mark_all_read', conditions={'method': ['POST']})
|
||||
|
||||
m.connect('/notifications/{notification_id}',
|
||||
action='update', conditions={'method': ['PUT']})
|
||||
m.connect('/notifications/{notification_id}',
|
||||
|
|
@ -850,7 +870,7 @@ def make_map(config):
|
|||
conditions={'function': check_repo, 'method': ['DELETE']},
|
||||
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
|
||||
|
||||
rmap.connect('changeset_info', '/changeset_info/{repo_name}/{revision}',
|
||||
rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
|
||||
controller='changeset', action='changeset_info',
|
||||
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
|
||||
|
||||
|
|
@ -1090,9 +1110,9 @@ def make_map(config):
|
|||
conditions={'function': check_repo},
|
||||
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
|
||||
|
||||
rmap.connect('files_metadata_list_home',
|
||||
'/{repo_name}/metadata_list/{revision}/{f_path}',
|
||||
controller='files', action='metadata_list',
|
||||
rmap.connect('files_nodetree_full',
|
||||
'/{repo_name}/nodetree_full/{commit_id}/{f_path}',
|
||||
controller='files', action='nodetree_full',
|
||||
conditions={'function': check_repo},
|
||||
requirements=URL_NAME_REQUIREMENTS, jsroute=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -49,22 +49,18 @@ def configure_vcs(config):
|
|||
Patch VCS config with some RhodeCode specific stuff
|
||||
"""
|
||||
from rhodecode.lib.vcs import conf
|
||||
from rhodecode.lib.utils2 import aslist
|
||||
conf.settings.BACKENDS = {
|
||||
'hg': 'rhodecode.lib.vcs.backends.hg.MercurialRepository',
|
||||
'git': 'rhodecode.lib.vcs.backends.git.GitRepository',
|
||||
'svn': 'rhodecode.lib.vcs.backends.svn.SubversionRepository',
|
||||
}
|
||||
|
||||
conf.settings.HG_USE_REBASE_FOR_MERGING = config.get(
|
||||
'rhodecode_hg_use_rebase_for_merging', False)
|
||||
conf.settings.GIT_REV_FILTER = shlex.split(
|
||||
config.get('git_rev_filter', '--all').strip())
|
||||
conf.settings.DEFAULT_ENCODINGS = aslist(config.get('default_encoding',
|
||||
'UTF-8'), sep=',')
|
||||
conf.settings.ALIASES[:] = config.get('vcs.backends')
|
||||
conf.settings.SVN_COMPATIBLE_VERSION = config.get(
|
||||
'vcs.svn.compatible_version')
|
||||
conf.settings.HOOKS_PROTOCOL = config['vcs.hooks.protocol']
|
||||
conf.settings.HOOKS_DIRECT_CALLS = config['vcs.hooks.direct_calls']
|
||||
conf.settings.GIT_REV_FILTER = shlex.split(config['git_rev_filter'])
|
||||
conf.settings.DEFAULT_ENCODINGS = config['default_encoding']
|
||||
conf.settings.ALIASES[:] = config['vcs.backends']
|
||||
conf.settings.SVN_COMPATIBLE_VERSION = config['vcs.svn.compatible_version']
|
||||
|
||||
|
||||
def initialize_database(config):
|
||||
|
|
@ -90,8 +86,7 @@ def initialize_test_environment(settings, test_env=None):
|
|||
|
||||
|
||||
def get_vcs_server_protocol(config):
|
||||
protocol = config.get('vcs.server.protocol', 'pyro4')
|
||||
return protocol
|
||||
return config['vcs.server.protocol']
|
||||
|
||||
|
||||
def set_instance_id(config):
|
||||
|
|
|
|||
|
|
@ -25,15 +25,18 @@ gist controller for RhodeCode
|
|||
|
||||
import time
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
import formencode
|
||||
import peppercorn
|
||||
from formencode import htmlfill
|
||||
|
||||
from pylons import request, response, tmpl_context as c, url
|
||||
from pylons.controllers.util import abort, redirect
|
||||
from pylons.i18n.translation import _
|
||||
from webob.exc import HTTPNotFound, HTTPForbidden
|
||||
from sqlalchemy.sql.expression import or_
|
||||
|
||||
|
||||
from rhodecode.model.forms import GistForm
|
||||
from rhodecode.model.gist import GistModel
|
||||
from rhodecode.model.meta import Session
|
||||
from rhodecode.model.db import Gist, User
|
||||
|
|
@ -44,9 +47,10 @@ from rhodecode.lib.auth import LoginRequired, NotAnonymous
|
|||
from rhodecode.lib.utils import jsonify
|
||||
from rhodecode.lib.utils2 import safe_str, safe_int, time_to_datetime
|
||||
from rhodecode.lib.ext_json import json
|
||||
from webob.exc import HTTPNotFound, HTTPForbidden
|
||||
from sqlalchemy.sql.expression import or_
|
||||
from rhodecode.lib.vcs.exceptions import VCSError, NodeNotChangedError
|
||||
from rhodecode.model import validation_schema
|
||||
from rhodecode.model.validation_schema.schemas import gist_schema
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -56,11 +60,11 @@ class GistsController(BaseController):
|
|||
|
||||
def __load_defaults(self, extra_values=None):
|
||||
c.lifetime_values = [
|
||||
(str(-1), _('forever')),
|
||||
(str(5), _('5 minutes')),
|
||||
(str(60), _('1 hour')),
|
||||
(str(60 * 24), _('1 day')),
|
||||
(str(60 * 24 * 30), _('1 month')),
|
||||
(-1, _('forever')),
|
||||
(5, _('5 minutes')),
|
||||
(60, _('1 hour')),
|
||||
(60 * 24, _('1 day')),
|
||||
(60 * 24 * 30, _('1 month')),
|
||||
]
|
||||
if extra_values:
|
||||
c.lifetime_values.append(extra_values)
|
||||
|
|
@ -136,40 +140,56 @@ class GistsController(BaseController):
|
|||
"""POST /admin/gists: Create a new item"""
|
||||
# url('gists')
|
||||
self.__load_defaults()
|
||||
gist_form = GistForm([x[0] for x in c.lifetime_values],
|
||||
[x[0] for x in c.acl_options])()
|
||||
|
||||
data = dict(request.POST)
|
||||
data['filename'] = data.get('filename') or Gist.DEFAULT_FILENAME
|
||||
data['nodes'] = [{
|
||||
'filename': data['filename'],
|
||||
'content': data.get('content'),
|
||||
'mimetype': data.get('mimetype') # None is autodetect
|
||||
}]
|
||||
|
||||
data['gist_type'] = (
|
||||
Gist.GIST_PUBLIC if data.get('public') else Gist.GIST_PRIVATE)
|
||||
data['gist_acl_level'] = (
|
||||
data.get('gist_acl_level') or Gist.ACL_LEVEL_PRIVATE)
|
||||
|
||||
schema = gist_schema.GistSchema().bind(
|
||||
lifetime_options=[x[0] for x in c.lifetime_values])
|
||||
|
||||
try:
|
||||
form_result = gist_form.to_python(dict(request.POST))
|
||||
# TODO: multiple files support, from the form
|
||||
filename = form_result['filename'] or Gist.DEFAULT_FILENAME
|
||||
nodes = {
|
||||
filename: {
|
||||
'content': form_result['content'],
|
||||
'lexer': form_result['mimetype'] # None is autodetect
|
||||
}
|
||||
}
|
||||
_public = form_result['public']
|
||||
gist_type = Gist.GIST_PUBLIC if _public else Gist.GIST_PRIVATE
|
||||
gist_acl_level = form_result.get(
|
||||
'acl_level', Gist.ACL_LEVEL_PRIVATE)
|
||||
|
||||
schema_data = schema.deserialize(data)
|
||||
# convert to safer format with just KEYs so we sure no duplicates
|
||||
schema_data['nodes'] = gist_schema.sequence_to_nodes(
|
||||
schema_data['nodes'])
|
||||
|
||||
gist = GistModel().create(
|
||||
description=form_result['description'],
|
||||
gist_id=schema_data['gistid'], # custom access id not real ID
|
||||
description=schema_data['description'],
|
||||
owner=c.rhodecode_user.user_id,
|
||||
gist_mapping=nodes,
|
||||
gist_type=gist_type,
|
||||
lifetime=form_result['lifetime'],
|
||||
gist_id=form_result['gistid'],
|
||||
gist_acl_level=gist_acl_level
|
||||
gist_mapping=schema_data['nodes'],
|
||||
gist_type=schema_data['gist_type'],
|
||||
lifetime=schema_data['lifetime'],
|
||||
gist_acl_level=schema_data['gist_acl_level']
|
||||
)
|
||||
Session().commit()
|
||||
new_gist_id = gist.gist_access_id
|
||||
except formencode.Invalid as errors:
|
||||
defaults = errors.value
|
||||
except validation_schema.Invalid as errors:
|
||||
defaults = data
|
||||
errors = errors.asdict()
|
||||
|
||||
if 'nodes.0.content' in errors:
|
||||
errors['content'] = errors['nodes.0.content']
|
||||
del errors['nodes.0.content']
|
||||
if 'nodes.0.filename' in errors:
|
||||
errors['filename'] = errors['nodes.0.filename']
|
||||
del errors['nodes.0.filename']
|
||||
|
||||
return formencode.htmlfill.render(
|
||||
render('admin/gists/new.html'),
|
||||
defaults=defaults,
|
||||
errors=errors.error_dict or {},
|
||||
errors=errors,
|
||||
prefix_error=False,
|
||||
encoding="UTF-8",
|
||||
force_defaults=False
|
||||
|
|
@ -243,7 +263,8 @@ class GistsController(BaseController):
|
|||
log.exception("Exception in gist show")
|
||||
raise HTTPNotFound()
|
||||
if format == 'raw':
|
||||
content = '\n\n'.join([f.content for f in c.files if (f_path is None or f.path == f_path)])
|
||||
content = '\n\n'.join([f.content for f in c.files
|
||||
if (f_path is None or f.path == f_path)])
|
||||
response.content_type = 'text/plain'
|
||||
return content
|
||||
return render('admin/gists/show.html')
|
||||
|
|
@ -252,32 +273,35 @@ class GistsController(BaseController):
|
|||
@NotAnonymous()
|
||||
@auth.CSRFRequired()
|
||||
def edit(self, gist_id):
|
||||
self.__load_defaults()
|
||||
self._add_gist_to_context(gist_id)
|
||||
|
||||
owner = c.gist.gist_owner == c.rhodecode_user.user_id
|
||||
if not (h.HasPermissionAny('hg.admin')() or owner):
|
||||
raise HTTPForbidden()
|
||||
|
||||
rpost = request.POST
|
||||
nodes = {}
|
||||
_file_data = zip(rpost.getall('org_files'), rpost.getall('files'),
|
||||
rpost.getall('mimetypes'), rpost.getall('contents'))
|
||||
for org_filename, filename, mimetype, content in _file_data:
|
||||
nodes[org_filename] = {
|
||||
'org_filename': org_filename,
|
||||
'filename': filename,
|
||||
'content': content,
|
||||
'lexer': mimetype,
|
||||
}
|
||||
data = peppercorn.parse(request.POST.items())
|
||||
|
||||
schema = gist_schema.GistSchema()
|
||||
schema = schema.bind(
|
||||
# '0' is special value to leave lifetime untouched
|
||||
lifetime_options=[x[0] for x in c.lifetime_values] + [0],
|
||||
)
|
||||
|
||||
try:
|
||||
schema_data = schema.deserialize(data)
|
||||
# convert to safer format with just KEYs so we sure no duplicates
|
||||
schema_data['nodes'] = gist_schema.sequence_to_nodes(
|
||||
schema_data['nodes'])
|
||||
|
||||
GistModel().update(
|
||||
gist=c.gist,
|
||||
description=rpost['description'],
|
||||
description=schema_data['description'],
|
||||
owner=c.gist.owner,
|
||||
gist_mapping=nodes,
|
||||
gist_type=c.gist.gist_type,
|
||||
lifetime=rpost['lifetime'],
|
||||
gist_acl_level=rpost['acl_level']
|
||||
gist_mapping=schema_data['nodes'],
|
||||
gist_type=schema_data['gist_type'],
|
||||
lifetime=schema_data['lifetime'],
|
||||
gist_acl_level=schema_data['gist_acl_level']
|
||||
)
|
||||
|
||||
Session().commit()
|
||||
|
|
@ -287,6 +311,10 @@ class GistsController(BaseController):
|
|||
# store only DB stuff for gist
|
||||
Session().commit()
|
||||
h.flash(_('Successfully updated gist data'), category='success')
|
||||
except validation_schema.Invalid as errors:
|
||||
errors = errors.asdict()
|
||||
h.flash(_('Error occurred during update of gist {}: {}').format(
|
||||
gist_id, errors), category='error')
|
||||
except Exception:
|
||||
log.exception("Exception in gist edit")
|
||||
h.flash(_('Error occurred during update of gist %s') % gist_id,
|
||||
|
|
@ -317,7 +345,7 @@ class GistsController(BaseController):
|
|||
# this cannot use timeago, since it's used in select2 as a value
|
||||
expiry = h.age(h.time_to_datetime(c.gist.gist_expires))
|
||||
self.__load_defaults(
|
||||
extra_values=('0', _('%(expiry)s - current value') % {'expiry': expiry}))
|
||||
extra_values=(0, _('%(expiry)s - current value') % {'expiry': expiry}))
|
||||
return render('admin/gists/edit.html')
|
||||
|
||||
@LoginRequired()
|
||||
|
|
|
|||
|
|
@ -346,3 +346,17 @@ class MyAccountController(BaseController):
|
|||
h.flash(_("Auth token successfully deleted"), category='success')
|
||||
|
||||
return redirect(url('my_account_auth_tokens'))
|
||||
|
||||
def my_notifications(self):
|
||||
c.active = 'notifications'
|
||||
return render('admin/my_account/my_account.html')
|
||||
|
||||
@auth.CSRFRequired()
|
||||
def my_notifications_toggle_visibility(self):
|
||||
user = c.rhodecode_user.get_instance()
|
||||
user_data = user.user_data
|
||||
status = user_data.get('notification_status', False)
|
||||
user_data['notification_status'] = not status
|
||||
user.user_data = user_data
|
||||
Session().commit()
|
||||
return redirect(url('my_account_notifications'))
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ class NotificationsController(BaseController):
|
|||
|
||||
return render('admin/notifications/notifications.html')
|
||||
|
||||
|
||||
@auth.CSRFRequired()
|
||||
def mark_all_read(self):
|
||||
if request.is_xhr:
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ from pylons.controllers.util import redirect
|
|||
from pylons.i18n.translation import _
|
||||
from webob.exc import HTTPForbidden, HTTPNotFound, HTTPBadRequest
|
||||
|
||||
import rhodecode
|
||||
from rhodecode.lib import auth, helpers as h
|
||||
from rhodecode.lib.auth import (
|
||||
LoginRequired, HasPermissionAllDecorator,
|
||||
|
|
@ -42,7 +43,7 @@ from rhodecode.lib.base import BaseRepoController, render
|
|||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.lib.exceptions import AttachedForksError
|
||||
from rhodecode.lib.utils import action_logger, repo_name_slug, jsonify
|
||||
from rhodecode.lib.utils2 import safe_int
|
||||
from rhodecode.lib.utils2 import safe_int, str2bool
|
||||
from rhodecode.lib.vcs import RepositoryError
|
||||
from rhodecode.model.db import (
|
||||
User, Repository, UserFollowing, RepoGroup, RepositoryField)
|
||||
|
|
@ -779,6 +780,8 @@ class ReposController(BaseRepoController):
|
|||
c.repo_info = self._load_repo(repo_name)
|
||||
defaults = self._vcs_form_defaults(repo_name)
|
||||
c.inherit_global_settings = defaults['inherit_global_settings']
|
||||
c.labs_active = str2bool(
|
||||
rhodecode.CONFIG.get('labs_settings_active', 'true'))
|
||||
|
||||
return htmlfill.render(
|
||||
render('admin/repos/repo_edit.html'),
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class SettingsController(BaseController):
|
|||
def __before__(self):
|
||||
super(SettingsController, self).__before__()
|
||||
c.labs_active = str2bool(
|
||||
rhodecode.CONFIG.get('labs_settings_active', 'false'))
|
||||
rhodecode.CONFIG.get('labs_settings_active', 'true'))
|
||||
c.navlist = navigation_list(request)
|
||||
|
||||
def _get_hg_ui_settings(self):
|
||||
|
|
@ -789,13 +789,6 @@ LabSetting = collections.namedtuple(
|
|||
# This list has to be kept in sync with the form
|
||||
# rhodecode.model.forms.LabsSettingsForm.
|
||||
_LAB_SETTINGS = [
|
||||
LabSetting(
|
||||
key='rhodecode_hg_use_rebase_for_merging',
|
||||
type='bool',
|
||||
group=lazy_ugettext('Mercurial server-side merge'),
|
||||
label=lazy_ugettext('Use rebase instead of creating a merge commit when merging via web interface'),
|
||||
help='' # Do not translate the empty string!
|
||||
),
|
||||
LabSetting(
|
||||
key='rhodecode_proxy_subversion_http_requests',
|
||||
type='bool',
|
||||
|
|
|
|||
|
|
@ -83,9 +83,6 @@ class UsersController(BaseController):
|
|||
from rhodecode.lib.utils import PartialRenderer
|
||||
_render = PartialRenderer('data_table/_dt_elements.html')
|
||||
|
||||
def grav_tmpl(user_email, size):
|
||||
return _render("user_gravatar", user_email, size)
|
||||
|
||||
def username(user_id, username):
|
||||
return _render("user_name", user_id, username)
|
||||
|
||||
|
|
@ -100,9 +97,7 @@ class UsersController(BaseController):
|
|||
users_data = []
|
||||
for user in c.users_list:
|
||||
users_data.append({
|
||||
"gravatar": grav_tmpl(user.email, 20),
|
||||
"username": h.link_to(
|
||||
user.username, h.url('user_profile', username=user.username)),
|
||||
"username": h.gravatar_with_user(user.username),
|
||||
"username_raw": user.username,
|
||||
"email": user.email,
|
||||
"first_name": h.escape(user.name),
|
||||
|
|
|
|||
|
|
@ -351,7 +351,8 @@ class ChangesetController(BaseRepoController):
|
|||
f_path=request.POST.get('f_path'),
|
||||
line_no=request.POST.get('line'),
|
||||
status_change=(ChangesetStatus.get_status_lbl(status)
|
||||
if status else None)
|
||||
if status else None),
|
||||
status_change_type=status
|
||||
)
|
||||
# get status if set !
|
||||
if status:
|
||||
|
|
|
|||
|
|
@ -136,11 +136,13 @@ class FilesController(BaseRepoController):
|
|||
_namespace = caches.get_repo_namespace_key(namespace_type, repo_name)
|
||||
return caches.get_cache_manager('repo_cache_long', _namespace)
|
||||
|
||||
def _get_tree_at_commit(self, repo_name, commit_id, f_path):
|
||||
def _get_tree_at_commit(self, repo_name, commit_id, f_path,
|
||||
full_load=False, force=False):
|
||||
def _cached_tree():
|
||||
log.debug('Generating cached file tree for %s, %s, %s',
|
||||
repo_name, commit_id, f_path)
|
||||
return render('files/files_browser.html')
|
||||
c.full_load = full_load
|
||||
return render('files/files_browser_tree.html')
|
||||
|
||||
cache_manager = self.__get_tree_cache_manager(
|
||||
repo_name, caches.FILE_TREE)
|
||||
|
|
@ -148,6 +150,10 @@ class FilesController(BaseRepoController):
|
|||
cache_key = caches.compute_key_from_params(
|
||||
repo_name, commit_id, f_path)
|
||||
|
||||
if force:
|
||||
# we want to force recompute of caches
|
||||
cache_manager.remove_value(cache_key)
|
||||
|
||||
return cache_manager.get(cache_key, createfunc=_cached_tree)
|
||||
|
||||
def _get_nodelist_at_commit(self, repo_name, commit_id, f_path):
|
||||
|
|
@ -165,22 +171,6 @@ class FilesController(BaseRepoController):
|
|||
repo_name, commit_id, f_path)
|
||||
return cache_manager.get(cache_key, createfunc=_cached_nodes)
|
||||
|
||||
def _get_metadata_at_commit(self, repo_name, commit, dir_node):
|
||||
def _cached_metadata():
|
||||
log.debug('Generating cached metadata for %s, %s, %s',
|
||||
repo_name, commit.raw_id, safe_str(dir_node.path))
|
||||
|
||||
data = ScmModel().get_dirnode_metadata(commit, dir_node)
|
||||
return data
|
||||
|
||||
cache_manager = self.__get_tree_cache_manager(
|
||||
repo_name, caches.FILE_TREE_META)
|
||||
|
||||
cache_key = caches.compute_key_from_params(
|
||||
repo_name, commit.raw_id, safe_str(dir_node.path))
|
||||
|
||||
return cache_manager.get(cache_key, createfunc=_cached_metadata)
|
||||
|
||||
@LoginRequired()
|
||||
@HasRepoPermissionAnyDecorator(
|
||||
'repository.read', 'repository.write', 'repository.admin')
|
||||
|
|
@ -246,6 +236,7 @@ class FilesController(BaseRepoController):
|
|||
c.authors = []
|
||||
c.file_tree = self._get_tree_at_commit(
|
||||
repo_name, c.commit.raw_id, f_path)
|
||||
|
||||
except RepositoryError as e:
|
||||
h.flash(safe_str(e), category='error')
|
||||
raise HTTPNotFound()
|
||||
|
|
@ -1092,23 +1083,32 @@ class FilesController(BaseRepoController):
|
|||
@XHRRequired()
|
||||
@HasRepoPermissionAnyDecorator(
|
||||
'repository.read', 'repository.write', 'repository.admin')
|
||||
@jsonify
|
||||
def metadata_list(self, repo_name, revision, f_path):
|
||||
def nodetree_full(self, repo_name, commit_id, f_path):
|
||||
"""
|
||||
Returns a json dict that contains commit date, author, revision
|
||||
and id for the specified repo, revision and file path
|
||||
Returns rendered html of file tree that contains commit date,
|
||||
author, revision for the specified combination of
|
||||
repo, commit_id and file path
|
||||
|
||||
:param repo_name: name of the repository
|
||||
:param revision: revision of files
|
||||
:param commit_id: commit_id of file tree
|
||||
:param f_path: file path of the requested directory
|
||||
"""
|
||||
|
||||
commit = self.__get_commit_or_redirect(revision, repo_name)
|
||||
commit = self.__get_commit_or_redirect(commit_id, repo_name)
|
||||
try:
|
||||
file_node = commit.get_node(f_path)
|
||||
dir_node = commit.get_node(f_path)
|
||||
except RepositoryError as e:
|
||||
return {'error': safe_str(e)}
|
||||
return 'error {}'.format(safe_str(e))
|
||||
|
||||
metadata = self._get_metadata_at_commit(
|
||||
repo_name, commit, file_node)
|
||||
return {'metadata': metadata}
|
||||
if dir_node.is_file():
|
||||
return ''
|
||||
|
||||
c.file = dir_node
|
||||
c.commit = commit
|
||||
|
||||
# using force=True here, make a little trick. We flush the cache and
|
||||
# compute it using the same key as without full_load, so the fully
|
||||
# loaded cached tree is now returned instead of partial
|
||||
return self._get_tree_at_commit(
|
||||
repo_name, commit.raw_id, dir_node.path, full_load=True,
|
||||
force=True)
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ class JournalController(BaseController):
|
|||
try:
|
||||
self.scm_model.toggle_following_user(
|
||||
user_id, c.rhodecode_user.user_id)
|
||||
Session.commit()
|
||||
Session().commit()
|
||||
return 'ok'
|
||||
except Exception:
|
||||
raise HTTPBadRequest()
|
||||
|
|
@ -254,7 +254,7 @@ class JournalController(BaseController):
|
|||
try:
|
||||
self.scm_model.toggle_following_repo(
|
||||
repo_id, c.rhodecode_user.user_id)
|
||||
Session.commit()
|
||||
Session().commit()
|
||||
return 'ok'
|
||||
except Exception:
|
||||
raise HTTPBadRequest()
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ from pylons.i18n.translation import _
|
|||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.sql.expression import or_
|
||||
|
||||
from rhodecode import events
|
||||
from rhodecode.lib import auth, diffs, helpers as h
|
||||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.lib.base import (
|
||||
|
|
@ -640,6 +641,9 @@ class PullrequestsController(BaseRepoController):
|
|||
pull_request_id = safe_int(pull_request_id)
|
||||
c.pull_request = PullRequest.get_or_404(pull_request_id)
|
||||
|
||||
c.template_context['pull_request_data']['pull_request_id'] = \
|
||||
pull_request_id
|
||||
|
||||
# pull_requests repo_name we opened it against
|
||||
# ie. target_repo must match
|
||||
if repo_name != c.pull_request.target_repo.repo_name:
|
||||
|
|
@ -758,9 +762,13 @@ class PullrequestsController(BaseRepoController):
|
|||
line_no=request.POST.get('line'),
|
||||
status_change=(ChangesetStatus.get_status_lbl(status)
|
||||
if status and allowed_to_change_status else None),
|
||||
status_change_type=(status
|
||||
if status and allowed_to_change_status else None),
|
||||
closing_pr=close_pr
|
||||
)
|
||||
|
||||
|
||||
|
||||
if allowed_to_change_status:
|
||||
old_calculated_status = pull_request.calculated_review_status()
|
||||
# get status if set !
|
||||
|
|
@ -774,6 +782,7 @@ class PullrequestsController(BaseRepoController):
|
|||
)
|
||||
|
||||
Session().flush()
|
||||
events.trigger(events.PullRequestCommentEvent(pull_request, comm))
|
||||
# we now calculate the status of pull request, and based on that
|
||||
# calculation we set the commits status
|
||||
calculated_status = pull_request.calculated_review_status()
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue