diff --git a/.bumpversion.cfg b/.bumpversion.cfg
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 4.11.6
+current_version = 4.12.0
message = release: Bump version {current_version} to {new_version}
[bumpversion:file:rhodecode/VERSION]
diff --git a/.release.cfg b/.release.cfg
--- a/.release.cfg
+++ b/.release.cfg
@@ -5,25 +5,20 @@ done = false
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
+
+[task:updated_translation]
[release]
-state = prepared
-version = 4.11.6
-
-[task:updated_translation]
+state = in_progress
+version = 4.12.0
[task:generate_js_routes]
diff --git a/MANIFEST.in b/MANIFEST.in
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -16,9 +16,6 @@ recursive-include configs *
# translations
recursive-include rhodecode/i18n *
-# hook templates
-recursive-include rhodecode/config/hook_templates *
-
# non-python core stuff
recursive-include rhodecode *.cfg
recursive-include rhodecode *.json
diff --git a/configs/development.ini b/configs/development.ini
--- a/configs/development.ini
+++ b/configs/development.ini
@@ -190,9 +190,6 @@ force_https = false
## use Strict-Transport-Security headers
use_htsts = false
-## number of commits stats will parse on each iteration
-commit_parse_limit = 25
-
## git rev filter option, --all is the default filter, if you need to
## hide all refs in changelog switch this to --branches --tags
git_rev_filter = --branches --tags
@@ -708,12 +705,12 @@ formatter = color_formatter_sql
[formatter_generic]
class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
-format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
+format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_color_formatter]
class = rhodecode.lib.logging_formatter.ColorFormatter
-format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
+format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_color_formatter_sql]
diff --git a/configs/gunicorn_config.py b/configs/gunicorn_config.py
--- a/configs/gunicorn_config.py
+++ b/configs/gunicorn_config.py
@@ -55,12 +55,13 @@ keepalive = 2
# SERVER MECHANICS
# None == system temp dir
+# worker_tmp_dir is recommended to be set to some tmpfs
worker_tmp_dir = None
tmp_upload_dir = None
# Custom log format
access_log_format = (
- '%(t)s GNCRN %(p)-8s %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
+ '%(t)s [%(p)-8s] GNCRN %(h)-15s rqt:%(L)s %(s)s %(b)-6s "%(m)s:%(U)s %(q)s" usr:%(u)s "%(f)s" "%(a)s"')
# self adjust workers based on CPU count
# workers = multiprocessing.cpu_count() * 2 + 1
@@ -119,16 +120,16 @@ def child_exit(server, worker):
def pre_request(worker, req):
- return
- worker.log.debug("[<%-10s>] PRE WORKER: %s %s",
- worker.pid, req.method, req.path)
+ worker.start_time = time.time()
+ worker.log.debug(
+ "GNCRN PRE WORKER [cnt:%s]: %s %s", worker.nr, req.method, req.path)
def post_request(worker, req, environ, resp):
- return
- worker.log.debug("[<%-10s>] POST WORKER: %s %s resp: %s", worker.pid,
- req.method, req.path, resp.status_code)
-
+ total_time = time.time() - worker.start_time
+ worker.log.debug(
+ "GNCRN POST WORKER [cnt:%s]: %s %s resp: %s, Load Time: %.3fs",
+ worker.nr, req.method, req.path, resp.status_code, total_time)
class RhodeCodeLogger(Logger):
diff --git a/configs/production.ini b/configs/production.ini
--- a/configs/production.ini
+++ b/configs/production.ini
@@ -165,9 +165,6 @@ force_https = false
## use Strict-Transport-Security headers
use_htsts = false
-## number of commits stats will parse on each iteration
-commit_parse_limit = 25
-
## git rev filter option, --all is the default filter, if you need to
## hide all refs in changelog switch this to --branches --tags
git_rev_filter = --branches --tags
@@ -678,12 +675,12 @@ formatter = generic
[formatter_generic]
class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
-format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
+format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_color_formatter]
class = rhodecode.lib.logging_formatter.ColorFormatter
-format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
+format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %Y-%m-%d %H:%M:%S
[formatter_color_formatter_sql]
diff --git a/docs/admin/sec-sophos-umc.rst b/docs/admin/sec-sophos-umc.rst
--- a/docs/admin/sec-sophos-umc.rst
+++ b/docs/admin/sec-sophos-umc.rst
@@ -1,4 +1,4 @@
-.. _sec-your-server:
+.. _sec-sophos-umc:
Securing Your Server via Sophos UTM 9
-------------------------------------
diff --git a/docs/admin/svn-path-permissions.rst b/docs/admin/svn-path-permissions.rst
new file mode 100644
--- /dev/null
+++ b/docs/admin/svn-path-permissions.rst
@@ -0,0 +1,80 @@
+.. _svn-path-permissions:
+
+|svn| Enabling Path Permissions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Because |RCEE| uses standard svn apache mod_svn we can take advantage of the
+authz configuration to protect paths and branches.
+
+
+Configuring RhodeCode
+=====================
+
+
+1. To configure path based permissions first we need to use a customized
+ mod_dav_svn.conf.
+
+ Open :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
+ And find `svn.proxy.config_template` setting. Now set a new path to read
+ the template from. For example:
+
+ .. code-block:: ini
+
+ svn.proxy.config_template = /home/ubuntu/rhodecode/custom_mod_dav_svn.conf.mako
+
+
+2. Create the file as in example: `/home/ubuntu/rhodecode/custom_mod_dav_svn.conf.mako`
+ You can download one from:
+
+ ``_
+
+3. Add (if not yet exists) a section `AuthzSVNReposRelativeAccessFile` in order
+ to read the path auth file.
+
+ Example modified config section enabling reading the authz file relative
+ to repository path. Means located in `/storage_dir/repo_name/conf/authz`
+
+ .. code-block:: text
+
+
+ # snip ...
+
+ # use specific SVN conf/authz file for each repository
+ AuthzSVNReposRelativeAccessFile authz
+
+ Allow from all
+ # snip ...
+
+ .. note::
+
+ The `AuthzSVNReposRelativeAccessFile` should go above the `Allow from all`
+ directive.
+
+
+4. Restart RhodeCode, Go to
+ the :menuselection:`Admin --> Settings --> VCS` page, and
+ click :guilabel:`Generate Apache Config`.
+ This will now generate a new configuration with enabled changes to read
+ the authz file. You can verify if changes were made by checking the generated
+ mod_dav_svn.conf file which is included in your apache configuration.
+
+5. Specify new rules in the repository authz configuration.
+ edit a file in :file:`repo_name/conf/authz`. For example, we specify that
+ only admin is allowed to push to develop branch
+
+ .. code-block:: ini
+
+ [/branches/develop]
+ * = r
+ admin = rw
+
+
+ For more example see:
+ ``_
+
+ Those rules also work for paths, so not only branches but all different
+ paths inside the repository can be specified.
+
+6. Reload Apache. If all is configured correctly it should not be allowed to
+ commit according to specified rules.
+
diff --git a/docs/admin/system-admin.rst b/docs/admin/system-admin.rst
--- a/docs/admin/system-admin.rst
+++ b/docs/admin/system-admin.rst
@@ -19,6 +19,7 @@ The following are the most common system
config-files-overview
vcs-server
svn-http
+ svn-path-permissions
gunicorn-ssl-support
apache-config
nginx-config
diff --git a/docs/api/api.rst b/docs/api/api.rst
--- a/docs/api/api.rst
+++ b/docs/api/api.rst
@@ -196,6 +196,7 @@ are not required in args.
.. --- API DEFS MARKER ---
.. toctree::
+ methods/views
methods/license-methods
methods/deprecated-methods
methods/gist-methods
diff --git a/docs/api/methods/repo-methods.rst b/docs/api/methods/repo-methods.rst
--- a/docs/api/methods/repo-methods.rst
+++ b/docs/api/methods/repo-methods.rst
@@ -66,7 +66,7 @@ comment_commit
create_repo
-----------
-.. py:function:: create_repo(apiuser, repo_name, repo_type, owner=>, description=, private=, clone_uri=, landing_rev=, enable_statistics=, enable_locking=, enable_downloads=, copy_permissions=)
+.. py:function:: create_repo(apiuser, repo_name, repo_type, owner=>, description=, private=, clone_uri=, push_uri=, landing_rev=, enable_statistics=, enable_locking=, enable_downloads=, copy_permissions=)
Creates a repository.
@@ -95,6 +95,8 @@ create_repo
:type private: bool
:param clone_uri: set clone_uri
:type clone_uri: str
+ :param push_uri: set push_uri
+ :type push_uri: str
:param landing_rev: :
:type landing_rev: str
:param enable_locking:
@@ -789,7 +791,7 @@ maintenance
pull
----
-.. py:function:: pull(apiuser, repoid)
+.. py:function:: pull(apiuser, repoid, remote_uri=)
Triggers a pull on the given repository from a remote location. You
can use this to keep remote repositories up-to-date.
@@ -804,6 +806,8 @@ pull
:type apiuser: AuthUser
:param repoid: The repository name or repository ID.
:type repoid: str or int
+ :param remote_uri: Optional remote URI to pass in for pull
+ :type remote_uri: str
Example output:
@@ -811,7 +815,7 @@ pull
id :
result : {
- "msg": "Pulled from ``"
+ "msg": "Pulled from url `` on repo ``"
"repository": ""
}
error : null
@@ -823,7 +827,7 @@ pull
id :
result : null
error : {
- "Unable to pull changes from ``"
+ "Unable to push changes from ``"
}
@@ -976,7 +980,7 @@ strip
update_repo
-----------
-.. py:function:: update_repo(apiuser, repoid, repo_name=, owner=>, description=, private=, clone_uri=, landing_rev=, fork_of=, enable_statistics=, enable_locking=, enable_downloads=, fields=)
+.. py:function:: update_repo(apiuser, repoid, repo_name=, owner=>, description=, private=, clone_uri=, push_uri=, landing_rev=, fork_of=, enable_statistics=, enable_locking=, enable_downloads=, fields=)
Updates a repository with the given information.
diff --git a/docs/api/methods/user-group-methods.rst b/docs/api/methods/user-group-methods.rst
--- a/docs/api/methods/user-group-methods.rst
+++ b/docs/api/methods/user-group-methods.rst
@@ -51,7 +51,7 @@ add_user_to_user_group
create_user_group
-----------------
-.. py:function:: create_user_group(apiuser, group_name, description=, owner=>, active=)
+.. py:function:: create_user_group(apiuser, group_name, description=, owner=>, active=, sync=)
Creates a new user group.
@@ -71,6 +71,9 @@ create_user_group
:type owner: Optional(str or int)
:param active: Set this group as active.
:type active: Optional(``True`` | ``False``)
+ :param sync: Set enabled or disabled the automatically sync from
+ external authentication types like ldap.
+ :type sync: Optional(``True`` | ``False``)
Example output:
@@ -368,7 +371,7 @@ revoke_user_permission_from_user_group
update_user_group
-----------------
-.. py:function:: update_user_group(apiuser, usergroupid, group_name=, description=, owner=, active=)
+.. py:function:: update_user_group(apiuser, usergroupid, group_name=, description=, owner=, active=, sync=)
Updates the specified `user group` with the details provided.
@@ -387,6 +390,9 @@ update_user_group
:type owner: Optional(str or int)
:param active: Set the group as active.
:type active: Optional(``True`` | ``False``)
+ :param sync: Set enabled or disabled the automatically sync from
+ external authentication types like ldap.
+ :type sync: Optional(``True`` | ``False``)
Example output:
diff --git a/docs/api/methods/views.rst b/docs/api/methods/views.rst
new file mode 100644
--- /dev/null
+++ b/docs/api/methods/views.rst
@@ -0,0 +1,48 @@
+.. _views-ref:
+
+views
+=====
+
+push (EE only)
+--------------
+
+.. py:function:: push(apiuser, repoid, remote_uri=)
+
+ Triggers a push 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
+ :param remote_uri: Optional remote URI to pass in for push
+ :type remote_uri: str
+
+ Example output:
+
+ .. code-block:: bash
+
+ id :
+ result : {
+ "msg": "Pushed to url `` on repo ``"
+ "repository": ""
+ }
+ error : null
+
+ Example error output:
+
+ .. code-block:: bash
+
+ id :
+ result : null
+ error : {
+ "Unable to push changes to ``"
+ }
+
+
diff --git a/docs/auth/crowd-auth.rst b/docs/auth/auth-crowd.rst
rename from docs/auth/crowd-auth.rst
rename to docs/auth/auth-crowd.rst
diff --git a/docs/auth/auth-ldap-groups.rst b/docs/auth/auth-ldap-groups.rst
new file mode 100644
--- /dev/null
+++ b/docs/auth/auth-ldap-groups.rst
@@ -0,0 +1,112 @@
+.. _config-ldap-groups-ref:
+
+LDAP/AD With User Groups Sync
+-----------------------------
+
+|RCM| supports LDAP (Lightweight Directory Access Protocol) or
+AD (active Directory) authentication.
+All LDAP versions are supported, with the following |RCM| plugins managing each:
+
+* For LDAP/AD with user group sync use ``LDAP + User Groups (egg:rhodecode-enterprise-ee#ldap_group)``
+
+RhodeCode reads all data defined from plugin and creates corresponding
+accounts on local database after receiving data from LDAP. This is done on
+every user log-in including operations like pushing/pulling/checkout.
+In addition group membership is read from LDAP and following operations are done:
+
+- automatic addition of user to |RCM| user group
+- automatic removal of user from any other |RCM| user groups not specified in LDAP.
+ The removal is done *only* on groups that are marked to be synced from ldap.
+ This setting can be changed in advanced settings on user groups
+- automatic creation of user groups if they aren't yet existing in |RCM|
+- marking user as super-admins if he is a member of any admin group defined in plugin settings
+
+This plugin is available only in EE Edition.
+
+.. important::
+
+ The email used with your |RCE| super-admin account needs to match the email
+ address attached to your admin profile in LDAP. This is because
+ within |RCE| the user email needs to be unique, and multiple users
+ cannot share an email account.
+
+ Likewise, if as an admin you also have a user account, the email address
+ attached to the user account needs to be different.
+
+
+LDAP Configuration Steps
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+To configure |LDAP|, use the following steps:
+
+1. From the |RCM| interface, select
+ :menuselection:`Admin --> Authentication`
+2. Enable the ldap+ groups plugin and select :guilabel:`Save`
+3. Select the :guilabel:`Enabled` check box in the plugin configuration section
+4. Add the required LDAP information and :guilabel:`Save`, for more details,
+ see :ref:`config-ldap-groups-examples`
+
+For a more detailed description of LDAP objects, see :ref:`ldap-gloss-ref`:
+
+.. _config-ldap-groups-examples:
+
+Example LDAP configuration
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. code-block:: bash
+
+ # Auth Cache TTL, Defines the caching for authentication to offload LDAP server.
+ # This means that cache result will be saved for 3600 before contacting LDAP server to verify the user access
+ 3600
+ # Host, comma seperated format is optionally possible to specify more than 1 server
+ https://ldap1.server.com/ldap-admin/,https://ldap2.server.com/ldap-admin/
+ # Default LDAP Port, use 689 for LDAPS
+ 389
+ # Account, used for SimpleBind if LDAP server requires an authentication
+ e.g admin@server.com
+ # Password used for simple bind
+ ldap-user-password
+ # LDAP connection security
+ LDAPS
+ # Certificate checks level
+ DEMAND
+ # Base DN
+ cn=Rufus Magillacuddy,ou=users,dc=rhodecode,dc=com
+ # User Search Base
+ ou=groups,ou=users
+ # LDAP search filter to narrow the results
+ (objectClass=person)
+ # LDAP search scope
+ SUBTREE
+ # Login attribute
+ sAMAccountName
+ # First Name Attribute to read
+ givenName
+ # Last Name Attribute to read
+ sn
+ # Email Attribute to read email address from
+ mail
+ # group extraction method
+ rfc2307bis
+ # Group search base
+ ou=RC-Groups
+ # Group Name Attribute, field to read the group name from
+ sAMAAccountName
+ # User Member of Attribute, field in which groups are stored
+ memberOf
+ # LDAP Group Search Filter, allows narrowing the results
+
+ # Admin Groups. Comma separated list of groups. If user is member of
+ # any of those he will be marked as super-admin in RhodeCode
+ admins, management
+
+
+Below is example setup that can be used with Active Directory and ldap groups.
+
+.. image:: ../images/ldap-groups-example.png
+ :alt: LDAP/AD setup example
+ :scale: 50 %
+
+.. toctree::
+
+ ldap-active-directory
+ ldap-authentication
\ No newline at end of file
diff --git a/docs/auth/ldap-config-steps.rst b/docs/auth/auth-ldap.rst
rename from docs/auth/ldap-config-steps.rst
rename to docs/auth/auth-ldap.rst
--- a/docs/auth/ldap-config-steps.rst
+++ b/docs/auth/auth-ldap.rst
@@ -1,14 +1,17 @@
.. _config-ldap-ref:
-LDAP
-----
+LDAP/AD
+-------
|RCM| supports LDAP (Lightweight Directory Access Protocol) or
AD (active Directory) authentication.
All LDAP versions are supported, with the following |RCM| plugins managing each:
-* For LDAPv3 use ``LDAP (egg:rhodecode-enterprise-ce#ldap)``
-* For LDAPv3 with user group sync use ``LDAP + User Groups (egg:rhodecode-enterprise-ee#ldap_group)``
+* For LDAP or Active Directory use ``LDAP (egg:rhodecode-enterprise-ce#ldap)``
+
+RhodeCode reads all data defined from plugin and creates corresponding
+accounts on local database after receiving data from LDAP. This is done on
+every user log-in including operations like pushing/pulling/checkout.
.. important::
@@ -21,6 +24,7 @@ All LDAP versions are supported, with th
Likewise, if as an admin you also have a user account, the email address
attached to the user account needs to be different.
+
LDAP Configuration Steps
^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +32,7 @@ To configure |LDAP|, use the following s
1. From the |RCM| interface, select
:menuselection:`Admin --> Authentication`
-2. Enable the required plugin and select :guilabel:`Save`
+2. Enable the ldap plugin and select :guilabel:`Save`
3. Select the :guilabel:`Enabled` check box in the plugin configuration section
4. Add the required LDAP information and :guilabel:`Save`, for more details,
see :ref:`config-ldap-examples`
@@ -41,15 +45,16 @@ Example LDAP configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
- # Auth Cache TTL
+ # Auth Cache TTL, Defines the caching for authentication to offload LDAP server.
+ # This means that cache result will be saved for 3600 before contacting LDAP server to verify the user access
3600
- # Host
+ # Host, comma seperated format is optionally possible to specify more than 1 server
https://ldap1.server.com/ldap-admin/,https://ldap2.server.com/ldap-admin/
- # Port
+ # Default LDAP Port, use 689 for LDAPS
389
- # Account
- cn=admin,dc=rhodecode,dc=com
- # Password
+ # Account, used for SimpleBind if LDAP server requires an authentication
+ e.g admin@server.com
+ # Password used for simple bind
ldap-user-password
# LDAP connection security
LDAPS
@@ -57,32 +62,26 @@ Example LDAP configuration
DEMAND
# Base DN
cn=Rufus Magillacuddy,ou=users,dc=rhodecode,dc=com
- # User Search Base
- ou=groups,ou=users
- # LDAP search filter
+ # LDAP search filter to narrow the results
(objectClass=person)
# LDAP search scope
SUBTREE
# Login attribute
- rmagillacuddy
- # First Name Attribute
- Rufus
- # Last Name Attribute
- Magillacuddy
- # Email Attribute
- LDAP-Registered@email.ac
- # User Member of Attribute
- Organizational Role
- # Group search base
- cn=users,ou=groups,dc=rhodecode,dc=com
- # LDAP Group Search Filter
- (objectclass=posixGroup)
- # Group Name Attribute
- users
- # Group Member Of Attribute
- cn
- # Admin Groups
- admin,devops,qa
+ sAMAccountName
+ # First Name Attribute to read
+ givenName
+ # Last Name Attribute to read
+ sn
+ # Email Attribute to read email address from
+ mail
+
+
+Below is example setup that can be used with Active Directory/LDAP server.
+
+.. image:: ../images/ldap-example.png
+ :alt: LDAP/AD setup example
+ :scale: 50 %
+
.. toctree::
diff --git a/docs/auth/pam-auth.rst b/docs/auth/auth-pam.rst
rename from docs/auth/pam-auth.rst
rename to docs/auth/auth-pam.rst
diff --git a/docs/auth/token-auth.rst b/docs/auth/auth-token.rst
rename from docs/auth/token-auth.rst
rename to docs/auth/auth-token.rst
diff --git a/docs/auth/auth.rst b/docs/auth/auth.rst
--- a/docs/auth/auth.rst
+++ b/docs/auth/auth.rst
@@ -3,35 +3,30 @@
Authentication Options
======================
-|RCE| provides a built in authentication plugin
-``rhodecode.lib.auth_rhodecode``. This is enabled by default and accessed
-through the administrative interface. Additionally,
-|RCE| provides a Pluggable Authentication System (PAS). This gives the
+|RCE| provides a built in authentication against its own database. This is
+implemented using ``rhodecode.lib.auth_rhodecode`` plugin. This plugin is
+enabled by default.
+Additionally, |RCE| provides a Pluggable Authentication System. This gives the
administrator greater control over how users authenticate with the system.
.. important::
You can disable the built in |RCM| authentication plugin
``rhodecode.lib.auth_rhodecode`` and force all authentication to go
- through your authentication plugin. However, if you do this,
- and your external authentication tools fails, you will be unable to
- access |RCM|.
+ through your authentication plugin of choice e.g LDAP only.
+ However, if you do this, and your external authentication tools fails,
+ you will be unable to access |RCM|.
|RCM| comes with the following user authentication management plugins:
-.. only:: latex
-
- * :ref:`config-ldap-ref`
- * :ref:`config-pam-ref`
- * :ref:`config-crowd-ref`
- * :ref:`config-token-ref`
.. toctree::
- ldap-config-steps
- crowd-auth
- pam-auth
- token-auth
+ auth-ldap
+ auth-ldap-groups
+ auth-crowd
+ auth-pam
+ auth-token
ssh-connection
diff --git a/docs/auth/ldap-configuration-example.rst b/docs/auth/ldap-configuration-example.rst
deleted file mode 100644
--- a/docs/auth/ldap-configuration-example.rst
+++ /dev/null
@@ -1,13 +0,0 @@
- LDAP Host hostname1,hostname2 # testing here
- Port port
- Account: `uid=admin,cn=users,cn=accounts,dc=localdomain,dc=tld`
- Password: userpassword #Testing this here
- Connection Security LDAPS
- Certificate Checks ``NEVER``
- Base DN cn=users,cn=accounts,dc=localdomain,dc=tld
- LDAP Search Filter (objectClass=person)
- LDAP Search Scope SUBTREE
- Login Attribute uid
- First Name Attribute givenname
- Last Name Attribute sn
- Email Attribute mail
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -34,7 +34,7 @@ import common
extensions = [
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
- 'sphinx.ext.pngmath'
+ 'sphinx.ext.imgmath'
]
intersphinx_mapping = {
@@ -104,7 +104,6 @@ exclude_patterns = [
# Other RST files
'admin/rhodecode-backup.rst',
- 'auth/ldap-configuration-example.rst',
'issue-trackers/redmine.rst',
'known-issues/error-msg-guide.rst',
'tutorials/docs-build.rst',
diff --git a/docs/contributing/dev-setup.rst b/docs/contributing/dev-setup.rst
--- a/docs/contributing/dev-setup.rst
+++ b/docs/contributing/dev-setup.rst
@@ -34,6 +34,13 @@ following commands:
Update your channels frequently by running ``nix-channel --update``.
+.. note::
+
+ To uninstall nix run the following:
+
+ remove the . "$HOME/.nix-profile/etc/profile.d/nix.sh" line in your ~/.profile or ~/.bash_profile
+ rm -rf $HOME/{.nix-channels,.nix-defexpr,.nix-profile,.config/nixpkgs}
+ sudo rm -rf /nix
Switch nix to the latest STABLE channel
---------------------------------------
diff --git a/docs/default.nix b/docs/default.nix
--- a/docs/default.nix
+++ b/docs/default.nix
@@ -169,17 +169,6 @@ let
};
};
- setuptools = buildPythonPackage {
- name = "setuptools-36.6.0";
- buildInputs = [];
- doCheck = false;
- propagatedBuildInputs = [];
- src = fetchurl {
- url = "https://pypi.python.org/packages/45/29/8814bf414e7cd1031e1a3c8a4169218376e284ea2553cc0822a6ea1c2d78/setuptools-36.6.0.zip";
- md5 = "74663b15117d9a2cc5295d76011e6fd1";
- };
- };
-
six = buildPythonPackage {
name = "six-1.11.0";
buildInputs = [];
@@ -259,6 +248,9 @@ let
};
+ # Avoid that setuptools is replaced, this leads to trouble
+ # with buildPythonPackage.
+ setuptools = pkgs.python27Packages.setuptools;
in python.buildEnv.override {
inherit python;
diff --git a/docs/images/ldap-example.png b/docs/images/ldap-example.png
new file mode 100644
index 0000000000000000000000000000000000000000..418d6d27feb2f71a13afaec03cc20c306dfed58f
GIT binary patch
literal 215397
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