##// END OF EJS Templates
release: Merge default into stable for release preparation
marcink -
r3294:4cc76f67 merge stable
parent child Browse files
Show More
@@ -0,0 +1,105 b''
1 .. _config-saml-duosecurity-ref:
2
3
4 SAML 2.0 with Duo Security
5 --------------------------
6
7 **This plugin is available only in EE Edition.**
8
9 |RCE| supports SAML 2.0 Authentication with Duo Security provider. This allows
10 users to log-in to RhodeCode via SSO mechanism of external identity provider
11 such as Duo. The login can be triggered either by the external IDP, or internally
12 by clicking specific authentication button on the log-in page.
13
14
15 Configuration steps
16 ^^^^^^^^^^^^^^^^^^^
17
18 To configure Duo Security SAML authentication, use the following steps:
19
20 1. From the |RCE| interface, select
21 :menuselection:`Admin --> Authentication`
22 2. Activate the `Duo Security` plugin and select :guilabel:`Save`
23 3. Go to newly available menu option called `Duo Security` on the left side.
24 4. Check the `enabled` check box in the plugin configuration section,
25 and fill in the required SAML information and :guilabel:`Save`, for more details,
26 see :ref:`config-saml-duosecurity`
27
28
29 .. _config-saml-duosecurity:
30
31
32 Example SAML Duo Security configuration
33 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34
35 Example configuration for SAML 2.0 with Duo Security provider::
36
37 *option*: `enabled` => `True`
38 # Enable or disable this authentication plugin.
39
40 *option*: `cache_ttl` => `0`
41 # Amount of seconds to cache the authentication and permissions check response call for this plugin.
42 # Useful for expensive calls like LDAP to improve the performance of the system (0 means disabled).
43
44 *option*: `debug` => `True`
45 # Enable or disable debug mode that shows SAML errors in the RhodeCode logs.
46
47 *option*: `entity_id` => `http://rc-app.com/dag/saml2/idp/metadata.php`
48 # Identity Provider entity/metadata URI.
49 # E.g. https://duo-gateway.com/dag/saml2/idp/metadata.php
50
51 *option*: `sso_service_url` => `http://rc-app.com/dag/saml2/idp/SSOService.php?spentityid=http://rc.local.pl/_admin/auth/duosecurity/saml-metadata`
52 # SSO (SingleSignOn) endpoint URL of the IdP. This can be used to initialize login
53 # E.g. https://duo-gateway.com/dag/saml2/idp/SSOService.php?spentityid=<metadata_entity_id>
54
55 *option*: `slo_service_url` => `http://rc-app.com/dag/saml2/idp/SingleLogoutService.php?ReturnTo=http://rc-app.com/dag/module.php/duosecurity/logout.php`
56 # SLO (SingleLogout) endpoint URL of the IdP.
57 # E.g. https://duo-gateway.com/dag/saml2/idp/SingleLogoutService.php?ReturnTo=http://duo-gateway.com/_admin/saml/sign-out-endpoint
58
59 *option*: `x509cert` => `<CERTIFICATE_STRING>`
60 # Identity provider public x509 certificate. It will be converted to single-line format without headers
61
62 *option*: `name_id_format` => `sha-1`
63 # The format that specifies how the NameID is sent to the service provider.
64
65 *option*: `signature_algo` => `sha-256`
66 # Type of Algorithm to use for verification of SAML signature on Identity provider side
67
68 *option*: `digest_algo` => `sha-256`
69 # Type of Algorithm to use for verification of SAML digest on Identity provider side
70
71 *option*: `cert_dir` => `/etc/saml/`
72 # Optional directory to store service provider certificate and private keys.
73 # Expected certs for the SP should be stored in this folder as:
74 # * sp.key Private Key
75 # * sp.crt Public cert
76 # * sp_new.crt Future Public cert
77 #
78 # Also you can use other cert to sign the metadata of the SP using the:
79 # * metadata.key
80 # * metadata.crt
81
82 *option*: `user_id_attribute` => `PersonImmutableID`
83 # User ID Attribute name. This defines which attribute in SAML response will be used to link accounts via unique id.
84 # Ensure this is returned from DuoSecurity for example via duo_username
85
86 *option*: `username_attribute` => `User.username`
87 # Username Attribute name. This defines which attribute in SAML response will map to an username.
88
89 *option*: `email_attribute` => `User.email`
90 # Email Attribute name. This defines which attribute in SAML response will map to an email address.
91
92
93 Below is example setup from DUO Administration page that can be used with above config.
94
95 .. image:: ../images/saml-duosecurity-service-provider-example.png
96 :alt: DUO Security SAML setup example
97 :scale: 50 %
98
99
100 Below is an example attribute mapping set for IDP provider required by the above config.
101
102
103 .. image:: ../images/saml-duosecurity-attributes-example.png
104 :alt: DUO Security SAML setup example
105 :scale: 50 % No newline at end of file
@@ -0,0 +1,18 b''
1 .. _config-saml-generic-ref:
2
3
4 SAML 2.0 Authentication
5 -----------------------
6
7
8 **This plugin is available only in EE Edition.**
9
10 RhodeCode Supports standard SAML 2.0 SSO for the web-application part.
11
12 Please check for reference two example providers:
13
14 .. toctree::
15
16 auth-saml-duosecurity
17 auth-saml-onelogin
18
@@ -0,0 +1,106 b''
1 .. _config-saml-onelogin-ref:
2
3
4 SAML 2.0 with One Login
5 -----------------------
6
7 **This plugin is available only in EE Edition.**
8
9 |RCE| supports SAML 2.0 Authentication with OneLogin provider. This allows
10 users to log-in to RhodeCode via SSO mechanism of external identity provider
11 such as OneLogin. The login can be triggered either by the external IDP, or internally
12 by clicking specific authentication button on the log-in page.
13
14
15 Configuration steps
16 ^^^^^^^^^^^^^^^^^^^
17
18 To configure OneLogin SAML authentication, use the following steps:
19
20 1. From the |RCE| interface, select
21 :menuselection:`Admin --> Authentication`
22 2. Activate the `OneLogin` plugin and select :guilabel:`Save`
23 3. Go to newly available menu option called `OneLogin` on the left side.
24 4. Check the `enabled` check box in the plugin configuration section,
25 and fill in the required SAML information and :guilabel:`Save`, for more details,
26 see :ref:`config-saml-onelogin`
27
28
29 .. _config-saml-onelogin:
30
31
32 Example SAML OneLogin configuration
33 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34
35 Example configuration for SAML 2.0 with OneLogin provider::
36
37 *option*: `enabled` => `True`
38 # Enable or disable this authentication plugin.
39
40 *option*: `cache_ttl` => `0`
41 # Amount of seconds to cache the authentication and permissions check response call for this plugin.
42 # Useful for expensive calls like LDAP to improve the performance of the system (0 means disabled).
43
44 *option*: `debug` => `True`
45 # Enable or disable debug mode that shows SAML errors in the RhodeCode logs.
46
47 *option*: `entity_id` => `https://app.onelogin.com/saml/metadata/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
48 # Identity Provider entity/metadata URI.
49 # E.g. https://app.onelogin.com/saml/metadata/<onelogin_connector_id>
50
51 *option*: `sso_service_url` => `https://customer-domain.onelogin.com/trust/saml2/http-post/sso/xxxxxx`
52 # SSO (SingleSignOn) endpoint URL of the IdP. This can be used to initialize login
53 # E.g. https://app.onelogin.com/trust/saml2/http-post/sso/<onelogin_connector_id>
54
55 *option*: `slo_service_url` => `https://customer-domain.onelogin.com/trust/saml2/http-redirect/slo/xxxxxx`
56 # SLO (SingleLogout) endpoint URL of the IdP.
57 # E.g. https://app.onelogin.com/trust/saml2/http-redirect/slo/<onelogin_connector_id>
58
59 *option*: `x509cert` => `<CERTIFICATE_STRING>`
60 # Identity provider public x509 certificate. It will be converted to single-line format without headers
61
62 *option*: `name_id_format` => `sha-1`
63 # The format that specifies how the NameID is sent to the service provider.
64
65 *option*: `signature_algo` => `sha-256`
66 # Type of Algorithm to use for verification of SAML signature on Identity provider side
67
68 *option*: `digest_algo` => `sha-256`
69 # Type of Algorithm to use for verification of SAML digest on Identity provider side
70
71 *option*: `cert_dir` => `/etc/saml/`
72 # Optional directory to store service provider certificate and private keys.
73 # Expected certs for the SP should be stored in this folder as:
74 # * sp.key Private Key
75 # * sp.crt Public cert
76 # * sp_new.crt Future Public cert
77 #
78 # Also you can use other cert to sign the metadata of the SP using the:
79 # * metadata.key
80 # * metadata.crt
81
82 *option*: `user_id_attribute` => `PersonImmutableID`
83 # User ID Attribute name. This defines which attribute in SAML response will be used to link accounts via unique id.
84 # Ensure this is returned from OneLogin for example via Internal ID
85
86 *option*: `username_attribute` => `User.username`
87 # Username Attribute name. This defines which attribute in SAML response will map to an username.
88
89 *option*: `email_attribute` => `User.email`
90 # Email Attribute name. This defines which attribute in SAML response will map to an email address.
91
92
93
94 Below is example setup that can be used with OneLogin SAML authentication that can be used with above config..
95
96 .. image:: ../images/saml-onelogin-config-example.png
97 :alt: OneLogin SAML setup example
98 :scale: 50 %
99
100
101 Below is an example attribute mapping set for IDP provider required by the above config.
102
103
104 .. image:: ../images/saml-onelogin-attributes-example.png
105 :alt: OneLogin SAML setup example
106 :scale: 50 % No newline at end of file
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,81 b''
1 |RCE| 4.15.0 |RNS|
2 ------------------
3
4 Release Date
5 ^^^^^^^^^^^^
6
7 - 2018-12-10
8
9
10 New Features
11 ^^^^^^^^^^^^
12
13 - Authentication: Added SAML 2.0 Authentication, with support of OneLogin and DUO Security.
14 - Core: add debug mode that switches logging to debug.
15 It's no longer required to reconfigure all logging. A `debug=true` set in .ini file
16 does it automatically.
17
18
19 General
20 ^^^^^^^
21
22 - Authentication: rename oauth to external identity as it would now be serving both
23 oAuth and SAML.
24 - Authentication: allow setting extern type with registration.
25 This will allow external identity plugins to define proper externs instead of always
26 using "rhodecode" one.
27 - Authentication: show if plugin is activated and enabled in the list.
28 - Authentication: add better logging for ldap related attributes to help track
29 LDAP connection problems more easily.
30 - Visual: add change logo header template
31 - UI: updated error pages style to be consistent with other pages.
32 - Utils: updated request generation so ishell can run some automation scripts.
33 - Docs: updated documentation for SVN 1.10 Wandisco repositories.
34 - System info: expose base_url set in .ini file.
35 - Style: update pygments template styling.
36 - Style: updated li style and markdown style.
37 - Dependencies: added python-saml library.
38 - Dependencies: bumped hgsubversion to 1.9.3 release.
39 - Dependencies: bumped gevent to 1.3.7 release.
40 - Dependencies: bumped lxml to 4.2.5 release.
41 - Dependencies: bumped gevent to 1.3.7 release.
42 - Dependencies: bumped alembic to 1.0.5 release.
43 - Dependencies: bumped peppercorn to 0.6 release.
44 - Dependencies: bumped pyotp to 2.2.7 release.
45 - Dependencies: bumped deform to 2.0.7 release
46 - Dependencies: bumped py-gfm to 0.1.4 release.
47 - Dependencies: bumped colander to 1.5.1 release
48 - Dependencies: bumped appenlight-client to 0.6.26 release.
49 - Dependencies: bumped bleach to 3.0.2 release.
50 - Dependencies: bumped pygments to 2.3.0
51
52
53 Security
54 ^^^^^^^^
55
56 - Mercurial: support evolve sub-commands when checking for permissions.
57 Those defaulted to write, while only read is required for evolve.
58 - auth/security: enforce that external users cannot reset their password.
59 External users don't use RhodeCode passwords, so resetting them shouldn't be allowed.
60
61
62 Performance
63 ^^^^^^^^^^^
64
65 - Markdown: use lazy loaded markdown initialization to speed up app startup.
66 - Gevent: changed DNS resolver to ares for better stability on long running processes.
67
68
69 Fixes
70 ^^^^^
71
72 - Default Reviewers: use target repo owner as default reviewer in case of CE edition.
73 - LDAP: ensure the proper cert files and dirs are set.
74 It's also now possible to specify custom paths for those.
75 - Markdown: fixed auto checkbox generation from markdown code
76
77
78 Upgrade notes
79 ^^^^^^^^^^^^^
80
81 - LDAP cert dirs No newline at end of file
@@ -0,0 +1,175 b''
1 # This code allows override the integrations templates. Put this into the __init__.py
2 # file of rcextensions
3
4
5 # EMAIL
6 from rhodecode.integrations import email
7 email.REPO_PUSH_TEMPLATE_HTML = email.Template('''
8 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
9 <html xmlns="http://www.w3.org/1999/xhtml">
10 <head>
11 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
12 <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
13 <title>${subject}</title>
14 <style type="text/css">
15 /* Based on The MailChimp Reset INLINE: Yes. */
16 #outlook a {padding:0;} /* Force Outlook to provide a "view in browser" menu link. */
17 body{width:100% !important; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%; margin:0; padding:0;}
18 /* Prevent Webkit and Windows Mobile platforms from changing default font sizes.*/
19 .ExternalClass {width:100%;} /* Force Hotmail to display emails at full width */
20 .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;}
21 /* Forces Hotmail to display normal line spacing. More on that: http://www.emailonacid.com/forum/viewthread/43/ */
22 #backgroundTable {margin:0; padding:0; line-height: 100% !important;}
23 /* End reset */
24
25 /* defaults for images*/
26 img {outline:none; text-decoration:none; -ms-interpolation-mode: bicubic;}
27 a img {border:none;}
28 .image_fix {display:block;}
29
30 body {line-height:1.2em;}
31 p {margin: 0 0 20px;}
32 h1, h2, h3, h4, h5, h6 {color:#323232!important;}
33 a {color:#427cc9;text-decoration:none;outline:none;cursor:pointer;}
34 a:focus {outline:none;}
35 a:hover {color: #305b91;}
36 h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {color:#427cc9!important;text-decoration:none!important;}
37 h1 a:active, h2 a:active, h3 a:active, h4 a:active, h5 a:active, h6 a:active {color: #305b91!important;}
38 h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited {color: #305b91!important;}
39 table {font-size:13px;border-collapse:collapse;mso-table-lspace:0pt;mso-table-rspace:0pt;}
40 table td {padding:.65em 1em .65em 0;border-collapse:collapse;vertical-align:top;text-align:left;}
41 input {display:inline;border-radius:2px;border-style:solid;border: 1px solid #dbd9da;padding:.5em;}
42 input:focus {outline: 1px solid #979797}
43 @media only screen and (-webkit-min-device-pixel-ratio: 2) {
44 /* Put your iPhone 4g styles in here */
45 }
46
47 /* Android targeting */
48 @media only screen and (-webkit-device-pixel-ratio:.75){
49 /* Put CSS for low density (ldpi) Android layouts in here */
50 }
51 @media only screen and (-webkit-device-pixel-ratio:1){
52 /* Put CSS for medium density (mdpi) Android layouts in here */
53 }
54 @media only screen and (-webkit-device-pixel-ratio:1.5){
55 /* Put CSS for high density (hdpi) Android layouts in here */
56 }
57 /* end Android targeting */
58
59 </style>
60
61 <!-- Targeting Windows Mobile -->
62 <!--[if IEMobile 7]>
63 <style type="text/css">
64
65 </style>
66 <![endif]-->
67
68 <!--[if gte mso 9]>
69 <style>
70 /* Target Outlook 2007 and 2010 */
71 </style>
72 <![endif]-->
73 </head>
74 <body>
75 <!-- Wrapper/Container Table: Use a wrapper table to control the width and the background color consistently of your email. Use this approach instead of setting attributes on the body tag. -->
76 <table cellpadding="0" cellspacing="0" border="0" id="backgroundTable" align="left" style="margin:1%;width:97%;padding:0;font-family:sans-serif;font-weight:100;border:1px solid #dbd9da">
77 <tr>
78 <td valign="top" style="padding:0;">
79 <table cellpadding="0" cellspacing="0" border="0" align="left" width="100%">
80 <tr><td style="width:100%;padding:7px;background-color:#202020" valign="top">
81 <a style="color:#eeeeee;text-decoration:none;" href="${instance_url}">
82 ${'RhodeCode'}
83 </a>
84 </td></tr>
85 <tr>
86 <td style="padding:15px;" valign="top">
87 % if data['push']['commits']:
88 % for commit in data['push']['commits']:
89 <a href="${commit['url']}">${commit['short_id']}</a> by ${commit['author']} at ${commit['date']} <br/>
90 ${commit['message_html']} <br/>
91 <br/>
92 % endfor
93 % else:
94 No commit data
95 % endif
96 </td>
97 </tr>
98 </table>
99 </td>
100 </tr>
101 </table>
102 <!-- End of wrapper table -->
103 <p><a style="margin-top:15px;margin-left:1%;font-family:sans-serif;font-weight:100;font-size:11px;color:#666666;text-decoration:none;" href="${instance_url}">
104 ${'This is a notification from RhodeCode. %(instance_url)s' % {'instance_url': instance_url}}
105 </a></p>
106 </body>
107 </html>
108 ''')
109
110
111 # JIRA (EE ONLY)
112 from rc_integrations import jira_tracker
113
114 jira_tracker.COMMENT_TEMPLATE_PULL_REQUEST = jira_tracker.Template('''
115 ${action} by ${author} (status: ${status}). \n
116 pull-request: ${url}
117 ''')
118
119
120 jira_tracker.COMMENT_TEMPLATE_COMMIT = jira_tracker.Template('''
121 Commit `${short_id}` by ${author} on `${branch}` branch references this issue. \n
122 ${url}\n
123
124 ## MODIFICATION add custom COMMIT message to the comment
125 ${commit['message']}
126 ''')
127
128
129 jira_tracker.COMMENT_TEMPLATE_COMMIT_WITH_STATUS = jira_tracker.Template('''
130 Commit `${short_id}` by ${author} on `${branch}` branch changed this issue. \n
131 '{url}\n
132
133 ## MODIFICATION add custom COMMIT message to the comment
134 ${commit['message']}
135 ''')
136
137
138 # REDMINE (EE ONLY)
139 from rc_integrations import redmine_tracker
140
141 redmine_tracker.COMMENT_TEMPLATE_COMMIT = redmine_tracker.Template('''
142 Commit `${short_id}` by ${author} on `${branch}` branch references this issue. \n
143 commit: ${url}\n
144
145 ## MODIFICATION add custom COMMIT message to the comment
146 message:
147 ```
148 ${commit['message']}
149 ```
150
151 ''')
152
153 redmine_tracker.COMMENT_TEMPLATE_COMMIT_WITH_STATUS = redmine_tracker.Template('''
154 Commit `${short_id}` by ${author} on `${branch}` branch changed this issue. \n
155 commit: ${url}\n
156
157 ## MODIFICATION add custom COMMIT message to the comment
158 message:
159 ```
160 ${commit['message']}
161 ```
162
163 ''')
164
165 redmine_tracker.COMMENT_TEMPLATE_PULL_REQUEST = redmine_tracker.Template('''
166 ${action} by ${author} (status: ${status}). \n'
167 ${url}\n
168
169 ## MODIFICATION add custom COMMIT message to the comment
170 message:
171 ```
172 ${commit['message']}
173 ```
174
175 ''')
@@ -0,0 +1,91 b''
1 # Example to validate commit message or author using some sort of rules
2
3
4 @has_kwargs({
5 'server_url': 'url of instance that triggered this hook',
6 'config': 'path to .ini config used',
7 'scm': 'type of version control "git", "hg", "svn"',
8 'username': 'username of actor who triggered this event',
9 'ip': 'ip address of actor who triggered this hook',
10 'action': '',
11 'repository': 'repository name',
12 'repo_store_path': 'full path to where repositories are stored',
13 'commit_ids': 'pre transaction metadata for commit ids',
14 'hook_type': '',
15 'user_agent': 'Client user agent, e.g git or mercurial CLI version',
16 })
17 @has_kwargs({
18 'server_url': 'url of instance that triggered this hook',
19 'config': 'path to .ini config used',
20 'scm': 'type of version control "git", "hg", "svn"',
21 'username': 'username of actor who triggered this event',
22 'ip': 'ip address of actor who triggered this hook',
23 'action': '',
24 'repository': 'repository name',
25 'repo_store_path': 'full path to where repositories are stored',
26 'commit_ids': 'pre transaction metadata for commit ids',
27 'hook_type': '',
28 'user_agent': 'Client user agent, e.g git or mercurial CLI version',
29 })
30 def _pre_push_hook(*args, **kwargs):
31 """
32 Post push hook
33 To stop version control from storing the transaction and send a message to user
34 use non-zero HookResponse with a message, e.g return HookResponse(1, 'Not allowed')
35
36 This message will be shown back to client during PUSH operation
37
38 Commit ids might look like that::
39
40 [{u'hg_env|git_env': ...,
41 u'multiple_heads': [],
42 u'name': u'default',
43 u'new_rev': u'd0befe0692e722e01d5677f27a104631cf798b69',
44 u'old_rev': u'd0befe0692e722e01d5677f27a104631cf798b69',
45 u'ref': u'',
46 u'total_commits': 2,
47 u'type': u'branch'}]
48 """
49 import re
50 from .helpers import extra_fields, extract_pre_commits
51 from .utils import str2bool
52
53 # returns list of dicts with key-val fetched from extra fields
54 repo_extra_fields = extra_fields.run(**kwargs)
55
56 # optionally use 'extra fields' to control the logic per repo
57 should_validate = str2bool(repo_extra_fields.get('validate_author', True))
58
59 # optionally store validation regex into extra fields
60 validation_regex = repo_extra_fields.get('validation_regex', '')
61
62 def validate_commit_message(commit_message, message_regex=None):
63 """
64 This function validates commit_message against some sort of rules.
65 It should return a valid boolean, and a reason for failure
66 """
67
68 if "secret_string" in commit_message:
69 msg = "!!Push forbidden: secret string found in commit messages"
70 return False, msg
71
72 if validation_regex:
73 regexp = re.compile(validation_regex)
74 if not regexp.match(message):
75 msg = "!!Push forbidden: commit message does not match regexp"
76 return False, msg
77
78 return True, ''
79
80 if should_validate:
81 # returns list of dicts with key-val fetched from extra fields
82 commit_list = extract_pre_commits.run(**kwargs)
83
84 for commit_data in commit_list:
85 message = commit_data['message']
86
87 message_valid, reason = validate_commit_message(message, validation_regex)
88 if not message_valid:
89 return HookResponse(1, reason)
90
91 return HookResponse(0, '')
@@ -1,5 +1,5 b''
1 1 [bumpversion]
2 current_version = 4.14.1
2 current_version = 4.15.0
3 3 message = release: Bump version {current_version} to {new_version}
4 4
5 5 [bumpversion:file:rhodecode/VERSION]
@@ -5,25 +5,20 b' done = false'
5 5 done = true
6 6
7 7 [task:rc_tools_pinned]
8 done = true
9 8
10 9 [task:fixes_on_stable]
11 done = true
12 10
13 11 [task:pip2nix_generated]
14 done = true
15 12
16 13 [task:changelog_updated]
17 done = true
18 14
19 15 [task:generate_api_docs]
20 done = true
16
17 [task:updated_translation]
21 18
22 19 [release]
23 state = prepared
24 version = 4.14.1
25
26 [task:updated_translation]
20 state = in_progress
21 version = 4.15.0
27 22
28 23 [task:generate_js_routes]
29 24
@@ -7,18 +7,20 b' About'
7 7
8 8 ``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_
9 9 and Subversion_ with a built in push/pull server, full text search,
10 pull requests and powerful code-review system. It works on http/https and
10 pull requests and powerful code-review system. It works on http/https, SSH and
11 11 has a few unique features like:
12 12
13 - plugable architecture
14 - advanced permission system with IP restrictions
15 - rich set of authentication plugins including LDAP,
16 ActiveDirectory, Atlassian Crowd, Http-Headers, Pam, Token-Auth.
17 - live code-review chat
18 - full web based file editing
19 - unified multi vcs support
20 - snippets (gist) system
21 - integration with all 3rd party issue trackers
13 - plugable architecture from Pyramid web-framework.
14 - advanced permission system with IP restrictions, inheritation, and user-groups.
15 - rich set of authentication plugins including LDAP, ActiveDirectory, SAML 2.0,
16 Atlassian Crowd, Http-Headers, Pam, Token-Auth, OAuth.
17 - live code-review chat, and reviewer rules.
18 - full web based file editing.
19 - unified multi vcs support.
20 - snippets (gist) system.
21 - integration framework for Slack, CI systems, Webhooks.
22 - integration with all 3rd party issue trackers.
23
22 24
23 25 RhodeCode also provides rich API, and multiple event hooks so it's easy
24 26 integrable with existing external systems.
@@ -1,10 +1,11 b''
1 1
2 2
3 3 ################################################################################
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 5 ################################################################################
6 6
7 7 [DEFAULT]
8 ## Debug flag sets all loggers to debug, and enables request tracking
8 9 debug = true
9 10
10 11 ################################################################################
@@ -414,6 +415,7 b' search.location = %(here)s/data/index'
414 415 ########################################
415 416 ## channelstream enables persistent connections and live notification
416 417 ## in the system. It's also used by the chat system
418
417 419 channelstream.enabled = false
418 420
419 421 ## server address for channelstream server on the backend
@@ -490,14 +492,6 b' appenlight.request_keys_blacklist ='
490 492 ## (by default the client ignores own entries: appenlight_client.client)
491 493 appenlight.log_namespace_blacklist =
492 494
493
494 ################################################################################
495 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
496 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
497 ## execute malicious code after an exception is raised. ##
498 ################################################################################
499 #set debug = false
500
501 495 # enable debug style page
502 496 debug_style = true
503 497
@@ -1,11 +1,12 b''
1 1
2 2
3 3 ################################################################################
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
4 ## RHODECODE COMMUNITY EDITION CONFIGURATION ##
5 5 ################################################################################
6 6
7 7 [DEFAULT]
8 debug = true
8 ## Debug flag sets all loggers to debug, and enables request tracking
9 debug = false
9 10
10 11 ################################################################################
11 12 ## EMAIL CONFIGURATION ##
@@ -389,6 +390,7 b' search.location = %(here)s/data/index'
389 390 ########################################
390 391 ## channelstream enables persistent connections and live notification
391 392 ## in the system. It's also used by the chat system
393
392 394 channelstream.enabled = false
393 395
394 396 ## server address for channelstream server on the backend
@@ -466,14 +468,6 b' appenlight.request_keys_blacklist ='
466 468 appenlight.log_namespace_blacklist =
467 469
468 470
469 ################################################################################
470 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
471 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
472 ## execute malicious code after an exception is raised. ##
473 ################################################################################
474 set debug = false
475
476
477 471 ###########################################
478 472 ### MAIN RHODECODE DATABASE CONFIG ###
479 473 ###########################################
@@ -524,6 +518,7 b' vcs.scm_app_implementation = http'
524 518 ## Push/Pull operations hooks protocol, available options are:
525 519 ## `http` - use http-rpc backend (default)
526 520 vcs.hooks.protocol = http
521
527 522 ## Host on which this instance is listening for hooks. If vcsserver is in other location
528 523 ## this should be adjusted.
529 524 vcs.hooks.host = 127.0.0.1
@@ -3,19 +3,19 b''
3 3 Anonymous Users
4 4 ---------------
5 5
6 By default, |RCM| provides |repo| access for registered users only. It can be
6 By default, |RCE| provides |repo| access for registered users only. It can be
7 7 configured to be **world-open** in terms of read and write permissions. This
8 configuration is called "Anonymous Access" and allows |RCM| to be used as a
8 configuration is called "Anonymous Access" and allows |RCE| to be used as a
9 9 public hub where unregistered users have access to your |repos|.
10 10
11 11 Anonymous access is useful for open source projects, universities,
12 12 or if running inside a restricted internal corporate network to serve
13 13 documents to all employees. Anonymous users get the default user permission
14 settings that are applied across the whole |RCM| system.
14 settings that are applied across the whole |RCE| system.
15 15
16 16 To enable anonymous access to your |repos|, use the following steps:
17 17
18 1. From the |RCM| interface, select :menuselection:`Admin --> Permissions`.
18 1. From the |RCE| interface, select :menuselection:`Admin --> Permissions`.
19 19 2. On the Application tab, check the :guilabel:`Allow anonymous access` box.
20 20 3. Select :guilabel:`Save`.
21 21 4. To set the anonymous user access permissions, which are based on the
@@ -166,7 +166,7 b' 2. Add your custom hook details, you can'
166 166 ``pretxnchangegroup.example`` with value ``python:/path/to/custom_hook.py:my_func_name``
167 167 3. Select :guilabel:`Save`
168 168
169 Also, see the |RC| Extensions section of the :ref:`rc-tools` guide. |RC|
169 Also, see the RhodeCode Extensions section of the :ref:`rc-tools` guide. RhodeCode
170 170 Extensions can be used to add additional hooks to your instance and comes
171 171 with a number of pre-built plugins if you chose to install them.
172 172
@@ -3,7 +3,7 b''
3 3 Apache WSGI Configuration
4 4 ^^^^^^^^^^^^^^^^^^^^^^^^^
5 5
6 |RCM| can also be set up with Apache under ``mod_wsgi``. To configure this
6 |RCE| can also be set up with Apache under ``mod_wsgi``. To configure this
7 7 use the following steps.
8 8
9 9 1. Install ``mod_wsgi`` using the following command:
@@ -50,6 +50,6 b' The following is an example ``wsgi`` dis'
50 50 .. note::
51 51
52 52 When using `mod_wsgi` the same version of |hg| must be running in your
53 system's |PY| environment and on |RCM|. To check the |RCM| version,
53 system's |PY| environment and on |RCE|. To check the |RCE| version,
54 54 on the interface go to
55 55 :menuselection:`Admin --> Settings --> System Info`
@@ -67,7 +67,7 b' sections.'
67 67 Default location: :file:`/home/{user}/.rccontrol/cache/MANIFEST`
68 68
69 69 |RCC| uses this file to source the latest available builds from the
70 secure |RC| download channels. The only reason to mess with this file
70 secure RhodeCode download channels. The only reason to mess with this file
71 71 is if you need to do an offline installation,
72 72 see the :ref:`Offline Installation<control:offline-installer-ref>`
73 73 instructions, otherwise |RCC| will completely manage this file.
@@ -3,6 +3,16 b''
3 3 Enabling Debug Mode
4 4 -------------------
5 5
6 Debug Mode will enable debug logging, and request tracking middleware. Debug Mode
7 enabled DEBUG log-level which allows tracking various information about authentication
8 failures, LDAP connection, email etc.
9
10 The request tracking will add a special
11 unique ID: `| req_id:00000000-0000-0000-0000-000000000000` at the end of each log line.
12 The req_id is the same for each individual requests, it means that if you want to
13 track particular user logs only, and exclude other concurrent ones
14 simply grep by `req_id` uuid which you'll have to find for the individual request.
15
6 16 To enable debug mode on a |RCE| instance you need to set the debug property
7 17 in the :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file. To
8 18 do this, use the following steps
@@ -11,14 +21,10 b' 1. Open the file and set the ``debug`` l'
11 21 2. Restart you instance using the ``rccontrol restart`` command,
12 22 see the following example:
13 23
14 You can also set the log level, the follow are the valid options;
15 ``debug``, ``info``, ``warning``, or ``fatal``.
16
17 24 .. code-block:: ini
18 25
19 26 [DEFAULT]
20 27 debug = true
21 pdebug = false
22 28
23 29 .. code-block:: bash
24 30
@@ -27,6 +33,7 b' You can also set the log level, the foll'
27 33 Instance "enterprise-1" successfully stopped.
28 34 Instance "enterprise-1" successfully started.
29 35
36
30 37 Debug and Logging Configuration
31 38 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 39
@@ -47,7 +54,7 b' the ``debug`` level.'
47 54 ### LOGGING CONFIGURATION ####
48 55 ################################
49 56 [loggers]
50 keys = root, sqlalchemy, rhodecode, ssh_wrapper
57 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
51 58
52 59 [handlers]
53 60 keys = console, console_sql, file, file_rotating
@@ -62,11 +69,16 b' the ``debug`` level.'
62 69 level = NOTSET
63 70 handlers = console
64 71
65 [logger_routes]
72 [logger_sqlalchemy]
73 level = INFO
74 handlers = console_sql
75 qualname = sqlalchemy.engine
76 propagate = 0
77
78 [logger_beaker]
66 79 level = DEBUG
67 80 handlers =
68 qualname = routes.middleware
69 ## "level = DEBUG" logs the route matched and routing variables.
81 qualname = beaker.container
70 82 propagate = 1
71 83
72 84 [logger_rhodecode]
@@ -75,11 +87,16 b' the ``debug`` level.'
75 87 qualname = rhodecode
76 88 propagate = 1
77 89
78 [logger_sqlalchemy]
79 level = INFO
80 handlers = console_sql
81 qualname = sqlalchemy.engine
82 propagate = 0
90 [logger_ssh_wrapper]
91 level = DEBUG
92 handlers =
93 qualname = ssh_wrapper
94 propagate = 1
95
96 [logger_celery]
97 level = DEBUG
98 handlers =
99 qualname = celery
83 100
84 101 ##############
85 102 ## HANDLERS ##
@@ -87,19 +104,19 b' the ``debug`` level.'
87 104
88 105 [handler_console]
89 106 class = StreamHandler
90 args = (sys.stderr,)
91 level = INFO
107 args = (sys.stderr, )
108 level = DEBUG
92 109 formatter = generic
93 110
94 111 [handler_console_sql]
95 112 class = StreamHandler
96 args = (sys.stderr,)
97 level = WARN
113 args = (sys.stderr, )
114 level = INFO
98 115 formatter = generic
99 116
100 117 [handler_file]
101 118 class = FileHandler
102 args = ('rhodecode.log', 'a',)
119 args = ('rhodecode_debug.log', 'a',)
103 120 level = INFO
104 121 formatter = generic
105 122
@@ -107,6 +124,25 b' the ``debug`` level.'
107 124 class = logging.handlers.TimedRotatingFileHandler
108 125 # 'D', 5 - rotate every 5days
109 126 # you can set 'h', 'midnight'
110 args = ('rhodecode.log', 'D', 5, 10,)
127 args = ('rhodecode_debug_rotated.log', 'D', 5, 10,)
111 128 level = INFO
112 129 formatter = generic
130
131 ################
132 ## FORMATTERS ##
133 ################
134
135 [formatter_generic]
136 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
137 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
138 datefmt = %Y-%m-%d %H:%M:%S
139
140 [formatter_color_formatter]
141 class = rhodecode.lib.logging_formatter.ColorFormatter
142 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
143 datefmt = %Y-%m-%d %H:%M:%S
144
145 [formatter_color_formatter_sql]
146 class = rhodecode.lib.logging_formatter.ColorFormatterSql
147 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
148 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
@@ -33,7 +33,7 b' Glossary'
33 33 Adding more machines or workers into your pool of resources.
34 34
35 35 Instance
36 A single installed version of one of the |RC| products. It could
36 A single installed version of one of the RhodeCode products. It could
37 37 refer to |RCE| or the VCS server depending on the context.
38 38
39 39 Plugin
@@ -3,7 +3,7 b''
3 3 Full-text Search
4 4 ----------------
5 5
6 By default |RC| is configured to use `Whoosh`_ to index |repos| and
6 By default RhodeCode is configured to use `Whoosh`_ to index |repos| and
7 7 provide full-text search.
8 8
9 9 |RCE| also provides support for `Elasticsearch`_ as a backend for scalable
@@ -46,7 +46,7 b' Configure the ``.rhoderc`` File'
46 46 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47 47
48 48 |RCT| uses the :file:`/home/{user}/.rhoderc` file for connection details
49 to |RCM| instances. If this file is not automatically created,
49 to |RCE| instances. If this file is not automatically created,
50 50 you can configure it using the following example. You need to configure the
51 51 details for each instance you want to index.
52 52
@@ -62,7 +62,7 b' details for each instance you want to in'
62 62 - VERSION: 1.5.0
63 63 - URL: http://127.0.0.1:10000
64 64
65 To get your API Token, on the |RCM| interface go to
65 To get your API Token, on the |RCE| interface go to
66 66 :menuselection:`username --> My Account --> Auth tokens`
67 67
68 68 .. code-block:: ini
@@ -3,7 +3,7 b''
3 3 Public Access
4 4 -------------
5 5
6 By default |RCM| allows users to read all **public** |repos|. User
6 By default |RCE| allows users to read all **public** |repos|. User
7 7 permissions and |repo| access can be configured explicitly,
8 8 and those permissions will override any default settings. The default
9 9 settings can be found under the following section:
@@ -7,7 +7,7 b' Extra fields attached to a |repo| allow '
7 7 each repository. This allows storing custom data per-repository.
8 8
9 9 It can be used in :ref:`integrations-webhook` or in |RCX|.
10 To install and read more about |RCX|, see the :ref:`install-rcx` section.
10 To read more about |RCX|, see the :ref:`integrations-rcextensions` section.
11 11
12 12
13 13 Enabling Extra Fields
@@ -46,11 +46,6 b' This is the complete list of |repos| hoo'
46 46 Using Repository Hooks
47 47 ----------------------
48 48
49 To use these hooks you need to install |RCX|. For more information, see the
50 :ref:`install-rcx` section.
49 To use these hooks you need to setup |RCX|. For more information, see the
50 :ref:`integrations-rcextensions` section.
51 51
52 Creating Extensions
53 -------------------
54
55 To create your own extensions using these hooks, see the :ref:`dev-plug`
56 section.
@@ -3,7 +3,7 b''
3 3 Setting Default Permissions
4 4 ---------------------------
5 5
6 Default permissions allow you to configure |RCM| so that when a new |repo|, user group,
6 Default permissions allow you to configure |RCE| so that when a new |repo|, user group,
7 7 or user is created their permissions are already defined. To set default permissions you need administrator
8 8 privileges. See the following sections for setting up your permissions system:
9 9
@@ -19,7 +19,7 b' Setting User defaults'
19 19
20 20 To set default user permissions, use the following steps.
21 21
22 1. From the |RCM| interface, select :menuselection:`Admin --> Permissions`
22 1. From the |RCE| interface, select :menuselection:`Admin --> Permissions`
23 23 2. Select the :guilabel:`Global` tab from the left-hand menu. The permissions
24 24 set on this screen apply to users and user-groups across the whole instance.
25 25 3. Save your changes
@@ -31,7 +31,7 b' Setting User Group defaults'
31 31
32 32 To set default user group permissions, use the following steps.
33 33
34 1. From the |RCM| interface, select :menuselection:`Admin --> User groups`
34 1. From the |RCE| interface, select :menuselection:`Admin --> User groups`
35 35 2. Select :guilabel:`Permissions`, and configure the default user
36 36 permissions. All users will get these permissions unless
37 37 individually set.
@@ -48,7 +48,7 b' Setting Repository defaults'
48 48
49 49 To set default |repo| permissions, use the following steps.
50 50
51 1. From the |RCM| interface, select :menuselection:`Admin --> Permissions`
51 1. From the |RCE| interface, select :menuselection:`Admin --> Permissions`
52 52 2. Select the :guilabel:`Object` tab from the left-hand menu and set the
53 53 |perm| permissions
54 54 3. Save your changes
@@ -60,7 +60,7 b' Setting Repository Group defaults'
60 60
61 61 To set default Repository Group permissions, use the following steps.
62 62
63 1. From the |RCM| interface, select :menuselection:`Admin --> Repository Groups`
63 1. From the |RCE| interface, select :menuselection:`Admin --> Repository Groups`
64 64 2. Select :guilabel:`Edit` beside the |repo| group you wish to configure
65 65 3. On the left-hand pane select :guilabel:`Permissions`
66 66 4. Set the default permissions for all |repos| created in this group
@@ -3,12 +3,12 b''
3 3 Repository Administration
4 4 =========================
5 5
6 Repository permissions in |RCM| can be managed in a number of different ways.
6 Repository permissions in |RCE| can be managed in a number of different ways.
7 7 This overview should give you an insight into how you could adopt particular
8 8 settings for your needs:
9 9
10 10 * Global |repo| permissions: This allows you to set the default permissions
11 for each new |repo| created within |RCM|, see :ref:`repo-default-ref`. All
11 for each new |repo| created within |RCE|, see :ref:`repo-default-ref`. All
12 12 |repos| created will inherit these permissions unless explicitly configured.
13 13 * Individual |repo| permissions: To set individual |repo| permissions,
14 14 see :ref:`set-repo-perms`.
@@ -18,13 +18,14 b' Prerequisites'
18 18 .. tip::
19 19
20 20 We recommend using Wandisco repositories which provide latest SVN versions
21 for most platforms.
21 for most platforms. If you skip this version you'll have to ensure the Client version
22 is compatible with installed SVN version which might differ depending on the operating system.
22 23 Here is an example how to add the Wandisco repositories for Ubuntu.
23 24
24 25 .. code-block:: bash
25 26
26 $ sudo sh -c 'echo "deb http://opensource.wandisco.com/ubuntu `lsb_release -cs` svn19" >> /etc/apt/sources.list.d/subversion19.list'
27 $ sudo wget -q http://opensource.wandisco.com/wandisco-debian.gpg -O- | sudo apt-key add -
27 $ sudo sh -c 'echo "deb http://opensource.wandisco.com/ubuntu `lsb_release -cs` svn110" >> /etc/apt/sources.list.d/subversion110.list'
28 $ sudo wget -q http://opensource.wandisco.com/wandisco-debian-new.gpg -O- | sudo apt-key add -
28 29 $ sudo apt-get update
29 30
30 31 Here is an example how to add the Wandisco repositories for Centos/Redhat. Using
@@ -46,7 +47,7 b' Example installation of required compone'
46 47 .. code-block:: bash
47 48
48 49 $ sudo apt-get install apache2
49 $ sudo apt-get install libapache2-mod-svn
50 $ sudo apt-get install libapache2-svn
50 51
51 52 Once installed you need to enable ``dav_svn`` on Ubuntu:
52 53
@@ -76,6 +77,12 b' Once installed you need to enable ``dav_'
76 77 LoadModule headers_module modules/mod_headers.so
77 78 LoadModule authn_anon_module modules/mod_authn_anon.so
78 79
80 .. tip::
81
82 To check the installed mod_dav_svn module version, you can use such command.
83
84 `strings /usr/lib/apache2/modules/mod_dav_svn.so | grep 'Powered by'`
85
79 86
80 87 Configuring Apache Setup
81 88 ========================
@@ -59,7 +59,7 b' Supported Browsers'
59 59 System Requirements
60 60 -------------------
61 61
62 |RCM| performs best on machines with ultra-fast hard disks. Generally disk
62 |RCE| performs best on machines with ultra-fast hard disks. Generally disk
63 63 performance is more important than CPU performance. In a corporate production
64 64 environment handling 1000s of users and |repos| you should deploy on a 12+
65 65 core 64GB RAM server. In short, the more RAM the better.
@@ -68,7 +68,7 b' core 64GB RAM server. In short, the more'
68 68 For example:
69 69
70 70 - for team of 1 - 5 active users you can run on 1GB RAM machine with 1CPU
71 - above 250 active users, |RCM| needs at least 8GB of memory.
71 - above 250 active users, |RCE| needs at least 8GB of memory.
72 72 Number of CPUs is less important, but recommended to have at least 2-3 CPUs
73 73
74 74
@@ -114,7 +114,7 b' Connection Methods'
114 114
115 115 * HTTPS
116 116 * SSH
117 * |RCM| API
117 * |RCE| API
118 118
119 119 Internationalization Support
120 120 ----------------------------
@@ -146,7 +146,7 b' persistent sessions across nodes. Please'
146 146
147 147 .. code-block:: ini
148 148
149 # use an unique generated long string
149 # use a unique generated long string
150 150 beaker.session.secret = 70e116cae2274656ba7265fd860aebbd
151 151
152 152 3) Configure stored cached/archive cache to our shared NFS `rc-node-1`
@@ -3,7 +3,7 b''
3 3 User Administration
4 4 ===================
5 5
6 |RCM| enables you to define permissions for the following entities within the
6 |RCE| enables you to define permissions for the following entities within the
7 7 system; **users**, **user groups**, **repositories**, **repository groups**.
8 8
9 9 Within each one of these entities you can set default settings,
@@ -3,13 +3,13 b''
3 3 VCS Server Management
4 4 ---------------------
5 5
6 The VCS Server handles |RCM| backend functionality. You need to configure
7 a VCS Server to run with a |RCM| instance. If you do not, you will be missing
8 the connection between |RCM| and its |repos|. This will cause error messages
6 The VCS Server handles |RCE| backend functionality. You need to configure
7 a VCS Server to run with a |RCE| instance. If you do not, you will be missing
8 the connection between |RCE| and its |repos|. This will cause error messages
9 9 on the web interface. You can run your setup in the following configurations,
10 10 currently the best performance is one of following:
11 11
12 * One VCS Server per |RCM| instance.
12 * One VCS Server per |RCE| instance.
13 13 * One VCS Server handling multiple instances.
14 14
15 15 .. important::
@@ -49,7 +49,7 b' To configure a |RCE| instance to use a V'
49 49 |RCE| VCS Server Options
50 50 ^^^^^^^^^^^^^^^^^^^^^^^^
51 51
52 The following list shows the available options on the |RCM| side of the
52 The following list shows the available options on the |RCE| side of the
53 53 connection to the VCS Server. The settings are configured per
54 54 instance in the
55 55 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
@@ -75,7 +75,7 b' instance in the'
75 75
76 76 \vcs.server <host:port>
77 77 Set the host, either hostname or IP Address, and port of the VCS server
78 you wish to run with your |RCM| instance.
78 you wish to run with your |RCE| instance.
79 79
80 80 .. code-block:: ini
81 81
@@ -22,12 +22,12 b' API access can also be turned on for eac'
22 22 decorated with a `@LoginRequired` decorator. To enable API access, change
23 23 the standard login decorator to `@LoginRequired(api_access=True)`.
24 24
25 From |RCM| version 1.7.0 you can configure a white list
25 From |RCE| version 1.7.0 you can configure a white list
26 26 of views that have API access enabled by default. To enable these,
27 edit the |RCM| configuration ``.ini`` file. The default location is:
27 edit the |RCE| configuration ``.ini`` file. The default location is:
28 28
29 * |RCM| Pre-2.2.7 :file:`root/rhodecode/data/production.ini`
30 * |RCM| 3.0 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
29 * |RCE| Pre-2.2.7 :file:`root/rhodecode/data/production.ini`
30 * |RCE| 3.0 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
31 31
32 32 To configure the white list, edit this section of the file. In this
33 33 configuration example, API access is granted to the patch/diff raw file and
@@ -5,8 +5,8 b' Crowd'
5 5
6 6 To enable Crowd authentication, use the following steps:
7 7
8 1. From the |RCM| interface, go to :menuselection:`Admin --> Authentication`
9 2. Enable the ``rhodecode.lib.auth_modules.auth_crowd`` library and select
8 1. From the |RCE| interface, go to :menuselection:`Admin --> Authentication`
9 2. Activate the ``rhodecode.lib.auth_modules.auth_crowd`` library and select
10 10 :guilabel:`Save`
11 11 3. On the Crowd plugin settings section, do the following:
12 12
@@ -3,25 +3,24 b''
3 3 LDAP/AD With User Groups Sync
4 4 -----------------------------
5 5
6 |RCM| supports LDAP (Lightweight Directory Access Protocol) or
6 **This plugin is available only in EE Edition.**
7
8 |RCE| supports LDAP (Lightweight Directory Access Protocol) or
7 9 AD (active Directory) authentication.
8 All LDAP versions are supported, with the following |RCM| plugins managing each:
9
10 * For LDAP/AD with user group sync use ``LDAP + User Groups (egg:rhodecode-enterprise-ee#ldap_group)``
10 All LDAP versions are currently supported.
11 11
12 12 RhodeCode reads all data defined from plugin and creates corresponding
13 13 accounts on local database after receiving data from LDAP. This is done on
14 14 every user log-in including operations like pushing/pulling/checkout.
15 15 In addition group membership is read from LDAP and following operations are done:
16 16
17 - automatic addition of user to |RCM| user group
18 - automatic removal of user from any other |RCM| user groups not specified in LDAP.
17 - automatic addition of user to |RCE| user group
18 - automatic removal of user from any other |RCE| user groups not specified in LDAP.
19 19 The removal is done *only* on groups that are marked to be synced from ldap.
20 20 This setting can be changed in advanced settings on user groups
21 - automatic creation of user groups if they aren't yet existing in |RCM|
21 - automatic creation of user groups if they aren't yet existing in |RCE|
22 22 - marking user as super-admins if he is a member of any admin group defined in plugin settings
23 23
24 This plugin is available only in EE Edition.
25 24
26 25 .. important::
27 26
@@ -39,11 +38,12 b' LDAP Configuration Steps'
39 38
40 39 To configure |LDAP|, use the following steps:
41 40
42 1. From the |RCM| interface, select
41 1. From the |RCE| interface, select
43 42 :menuselection:`Admin --> Authentication`
44 2. Enable the ldap+ groups plugin and select :guilabel:`Save`
45 3. Select the :guilabel:`Enabled` check box in the plugin configuration section
46 4. Add the required LDAP information and :guilabel:`Save`, for more details,
43 2. Activate the `LDAP + User Groups` plugin and select :guilabel:`Save`
44 3. Go to newly available menu option called `LDAP + User Groups` on the left side.
45 4. Check the `enabled` check box in the plugin configuration section,
46 and fill in the required LDAP information and :guilabel:`Save`, for more details,
47 47 see :ref:`config-ldap-groups-examples`
48 48
49 49 For a more detailed description of LDAP objects, see :ref:`ldap-gloss-ref`:
@@ -52,59 +52,107 b' For a more detailed description of LDAP '
52 52
53 53 Example LDAP configuration
54 54 ^^^^^^^^^^^^^^^^^^^^^^^^^^
55 .. code-block:: bash
55
56 Below is example setup that can be used with Active Directory and LDAP server with groups sync::
57
58 *option*: `enabled` => `True`
59 # Enable or disable this authentication plugin.
60
61 *option*: `cache_ttl` => `360`
62 # Amount of seconds to cache the authentication and permissions check response call for this plugin.
63 # Useful for expensive calls like LDAP to improve the performance of the system (0 means disabled).
64
65 *option*: `host` => `192.168.245.143,192.168.1.240`
66 # Host[s] of the LDAP Server
67 # (e.g., 192.168.2.154, or ldap-server.domain.com.
68 # Multiple servers can be specified using commas
69
70 *option*: `port` => `389`
71 # Custom port that the LDAP server is listening on. Default value is: 389, use 689 for LDAPS(SSL)
72
73 *option*: `timeout` => `300`
74 # Timeout for LDAP connection
75
76 *option*: `dn_user` => `Administrator@rhodecode.com`
77 # Optional user DN/account to connect to LDAP if authentication is required.
78 # e.g., cn=admin,dc=mydomain,dc=com, or uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com
79
80 *option*: `dn_pass` => `SomeSecret`
81 # Password to authenticate for given user DN.
82
83 *option*: `tls_kind` => `PLAIN`
84 # TLS Type
85
86 *option*: `tls_reqcert` => `NEVER`
87 # Require Cert over TLS?. Self-signed and custom certificates can be used when
88 # `RhodeCode Certificate` found in admin > settings > system info page is extended.
89
90 *option*: `tls_cert_file` => ``
91 # This specifies the PEM-format file path containing certificates for use in TLS connection.
92 # If not specified `TLS Cert dir` will be used
93
94 *option*: `tls_cert_dir` => `/etc/openldap/cacerts`
95 # This specifies the path of a directory that contains individual CA certificates in separate files.
96
97 *option*: `base_dn` => `dc=rhodecode,dc=com`
98 # Base DN to search. Dynamic bind is supported. Add `$login` marker in it to be replaced with current user credentials
99 # (e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)
100
101 *option*: `user_search_base` => `ou=RC-Users`
102 # User search base will extend the Base DN
103 # (e.g., ou=Users will result in ou=Users,dc=mydomain,dc=com root DN)
56 104
57 # Auth Cache TTL, Defines the caching for authentication to offload LDAP server.
58 # This means that cache result will be saved for 3600 before contacting LDAP server to verify the user access
59 3600
60 # Host, comma seperated format is optionally possible to specify more than 1 server
61 https://ldap1.server.com/ldap-admin/,https://ldap2.server.com/ldap-admin/
62 # Default LDAP Port, use 689 for LDAPS
63 389
64 # Account, used for SimpleBind if LDAP server requires an authentication
65 e.g admin@server.com
66 # Password used for simple bind
67 ldap-user-password
68 # LDAP connection security
69 LDAPS
70 # Certificate checks level
71 DEMAND
72 # Base DN
73 cn=Rufus Magillacuddy,ou=users,dc=rhodecode,dc=com
74 # User Search Base
75 ou=groups,ou=users
76 # LDAP search filter to narrow the results
77 (objectClass=person)
78 # LDAP search scope
79 SUBTREE
80 # Login attribute
81 sAMAccountName
82 # First Name Attribute to read
83 givenName
84 # Last Name Attribute to read
85 sn
86 # Email Attribute to read email address from
87 mail
88 # group extraction method
89 rfc2307bis
90 # Group search base
91 ou=RC-Groups
92 # Group Name Attribute, field to read the group name from
93 sAMAAccountName
94 # User Member of Attribute, field in which groups are stored
95 memberOf
96 # LDAP Group Search Filter, allows narrowing the results
105 *option*: `user_search_filter` => ``
106 # Filter to narrow results
107 # (e.g., (&(objectCategory=Person)(objectClass=user)), or
108 # (memberof=cn=rc-login,ou=groups,ou=company,dc=mydomain,dc=com)))
109
110 *option*: `search_scope` => `SUBTREE`
111 # How deep to search LDAP. If unsure set to SUBTREE
112
113 *option*: `attr_login` => `sAMAccountName`
114 # LDAP Attribute to map to user name (e.g., uid, or sAMAccountName)
115
116 *option*: `attr_email` => `mail`
117 # LDAP Attribute to map to email address (e.g., mail).
118 # Emails are a crucial part of RhodeCode.
119 # If possible add a valid email attribute to ldap users.
120
121 *option*: `attr_firstname` => `givenName`
122 # LDAP Attribute to map to first name (e.g., givenName)
123
124 *option*: `attr_lastname` => `sn`
125 # LDAP Attribute to map to last name (e.g., sn)
126
127 *option*: `group_extraction_type` => `rfc2307bis`
128 # With rfc2307, group members are listed by name in the memberUid attribute
129 # With rfc2307bis (Microsoft AD compatible) group members are listed by DN and stored in the member attribute
97 130
98 # Admin Groups. Comma separated list of groups. If user is member of
99 # any of those he will be marked as super-admin in RhodeCode
100 admins, management
131 *option*: `group_search_base` => `ou=RC-Groups`
132 # Group search base will extend the Base DN (e.g. ou=Groups will result in ou=Groups,dc=mydomain,dc=com)
101 133
134 *option*: `group_name_attr` => `sAMAccountName`
135 # LDAP Attribute to map to group name (e.g., cn, or sAMAccountName)
136
137 *option*: `user_member_of` => `memberOf`
138 # Users Attribute used to fetch the group membership.
139 # Use if users have stored group membership inside their attributes
140 # (e.g., memberOf, or userMemberOf)
102 141
103 Below is example setup that can be used with Active Directory and ldap groups.
142 *option*: `group_search_filter` => ``
143 # Filter to narrow results (e.g., (&(objectCategory=Group)(objectClass=group)), etc)
144
145 *option*: `group_member_of` => `memberOf`
146 # LDAP Attribute used to resolve the parent group (e.g., memberOf)
104 147
105 .. image:: ../images/ldap-groups-example.png
106 :alt: LDAP/AD setup example
107 :scale: 50 %
148 *option*: `admin_groups` => `Admins,Management`
149 # A comma separated list of group names that identify users as RhodeCode Administrators (e.g., admins)
150
151 *option*: `admin_groups_sync` => `full`
152 # Way to sync Admin groups.
153 # Full means admin flag is set to on or off according to membership in administrator group defined above.
154 # On-only means the flag is only set to on, and not turned off once user is no longer a member
155
108 156
109 157 .. toctree::
110 158
@@ -3,11 +3,9 b''
3 3 LDAP/AD
4 4 -------
5 5
6 |RCM| supports LDAP (Lightweight Directory Access Protocol) or
6 |RCE| supports LDAP (Lightweight Directory Access Protocol) or
7 7 AD (active Directory) authentication.
8 All LDAP versions are supported, with the following |RCM| plugins managing each:
9
10 * For LDAP or Active Directory use ``LDAP (egg:rhodecode-enterprise-ce#ldap)``
8 All LDAP versions are currently supported.
11 9
12 10 RhodeCode reads all data defined from plugin and creates corresponding
13 11 accounts on local database after receiving data from LDAP. This is done on
@@ -30,11 +28,12 b' LDAP Configuration Steps'
30 28
31 29 To configure |LDAP|, use the following steps:
32 30
33 1. From the |RCM| interface, select
31 1. From the |RCE| interface, select
34 32 :menuselection:`Admin --> Authentication`
35 2. Enable the ldap plugin and select :guilabel:`Save`
36 3. Select the :guilabel:`Enabled` check box in the plugin configuration section
37 4. Add the required LDAP information and :guilabel:`Save`, for more details,
33 2. Activate the `LDAP` plugin and select :guilabel:`Save`
34 3. Go to newly available menu option called `LDAP` on the left side.
35 4. Check the `enabled` check box in the plugin configuration section,
36 and fill in the required LDAP information and :guilabel:`Save`, for more details,
38 37 see :ref:`config-ldap-examples`
39 38
40 39 For a more detailed description of LDAP objects, see :ref:`ldap-gloss-ref`:
@@ -43,44 +42,73 b' For a more detailed description of LDAP '
43 42
44 43 Example LDAP configuration
45 44 ^^^^^^^^^^^^^^^^^^^^^^^^^^
46 .. code-block:: bash
45
46 Below is example setup that can be used with Active Directory/LDAP server::
47
48 *option*: `enabled` => `True`
49 # Enable or disable this authentication plugin.
50
51 *option*: `cache_ttl` => `360`
52 # Amount of seconds to cache the authentication and permissions check response call for this plugin.
53 # Useful for expensive calls like LDAP to improve the performance of the system (0 means disabled).
54
55 *option*: `host` => `192.168.245.143,192.168.1.240`
56 # Host[s] of the LDAP Server
57 # (e.g., 192.168.2.154, or ldap-server.domain.com.
58 # Multiple servers can be specified using commas
59
60 *option*: `port` => `389`
61 # Custom port that the LDAP server is listening on. Default value is: 389, use 689 for LDAPS(SSL)
62
63 *option*: `timeout` => `300`
64 # Timeout for LDAP connection
65
66 *option*: `dn_user` => `Administrator@rhodecode.com`
67 # Optional user DN/account to connect to LDAP if authentication is required.
68 # e.g., cn=admin,dc=mydomain,dc=com, or uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com
69
70 *option*: `dn_pass` => `SomeSecret`
71 # Password to authenticate for given user DN.
72
73 *option*: `tls_kind` => `PLAIN`
74 # TLS Type
47 75
48 # Auth Cache TTL, Defines the caching for authentication to offload LDAP server.
49 # This means that cache result will be saved for 3600 before contacting LDAP server to verify the user access
50 3600
51 # Host, comma seperated format is optionally possible to specify more than 1 server
52 https://ldap1.server.com/ldap-admin/,https://ldap2.server.com/ldap-admin/
53 # Default LDAP Port, use 689 for LDAPS
54 389
55 # Account, used for SimpleBind if LDAP server requires an authentication
56 e.g admin@server.com
57 # Password used for simple bind
58 ldap-user-password
59 # LDAP connection security
60 LDAPS
61 # Certificate checks level
62 DEMAND
63 # Base DN
64 cn=Rufus Magillacuddy,ou=users,dc=rhodecode,dc=com
65 # LDAP search filter to narrow the results
66 (objectClass=person)
67 # LDAP search scope
68 SUBTREE
69 # Login attribute
70 sAMAccountName
71 # First Name Attribute to read
72 givenName
73 # Last Name Attribute to read
74 sn
75 # Email Attribute to read email address from
76 mail
76 *option*: `tls_reqcert` => `NEVER`
77 # Require Cert over TLS?. Self-signed and custom certificates can be used when
78 # `RhodeCode Certificate` found in admin > settings > system info page is extended.
79
80 *option*: `tls_cert_file` => ``
81 # This specifies the PEM-format file path containing certificates for use in TLS connection.
82 # If not specified `TLS Cert dir` will be used
83
84 *option*: `tls_cert_dir` => `/etc/openldap/cacerts`
85 # This specifies the path of a directory that contains individual CA certificates in separate files.
86
87 *option*: `base_dn` => `cn=Rufus Magillacuddy,ou=users,dc=rhodecode,dc=com`
88 # Base DN to search. Dynamic bind is supported. Add `$login` marker in it to be replaced with current user credentials
89 # (e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)
77 90
91 *option*: `filter` => `(objectClass=person)`
92 # Filter to narrow results
93 # (e.g., (&(objectCategory=Person)(objectClass=user)), or
94 # (memberof=cn=rc-login,ou=groups,ou=company,dc=mydomain,dc=com)))
78 95
79 Below is example setup that can be used with Active Directory/LDAP server.
96 *option*: `search_scope` => `SUBTREE`
97 # How deep to search LDAP. If unsure set to SUBTREE
98
99 *option*: `attr_login` => `sAMAccountName`
100 # LDAP Attribute to map to user name (e.g., uid, or sAMAccountName)
80 101
81 .. image:: ../images/ldap-example.png
82 :alt: LDAP/AD setup example
83 :scale: 50 %
102 *option*: `attr_email` => `mail`
103 # LDAP Attribute to map to email address (e.g., mail).
104 # Emails are a crucial part of RhodeCode.
105 # If possible add a valid email attribute to ldap users.
106
107 *option*: `attr_firstname` => `givenName`
108 # LDAP Attribute to map to first name (e.g., givenName)
109
110 *option*: `attr_lastname` => `sn`
111 # LDAP Attribute to map to last name (e.g., sn)
84 112
85 113
86 114 .. toctree::
@@ -5,8 +5,8 b' PAM'
5 5
6 6 To enable PAM authentication, use the following steps:
7 7
8 1. From the |RCM| interface, go to :menuselection:`Admin --> Authentication`
9 2. Enable the ``rhodecode.lib.auth_modules.auth_pam`` library and select save
8 1. From the |RCE| interface, go to :menuselection:`Admin --> Authentication`
9 2. Activate the ``rhodecode.lib.auth_modules.auth_pam`` library and select save
10 10 3. On the PAM plugin settings section, do the following:
11 11
12 12 * Check the :guilabel:`Enable` checkbox
@@ -3,7 +3,10 b''
3 3 Authentication Tokens
4 4 ---------------------
5 5
6 |RCE| has 4 different kinds of authentication tokens.
6 |RCE| has 4 different kinds of authentication tokens. `API token`, `Feed tokens` work
7 without a need to enable any additional authentication. `VCS tokens` require dedicated
8 authentication plugin to be activated. `Web Interface tokens` are controlled by the
9 white_list configuration.
7 10
8 11 * *API tokens*: API tokens can only be used to execute |RCE| API operations.
9 12 You can store your API token and assign it to each instance in
@@ -11,15 +14,7 b' Authentication Tokens'
11 14 example in :ref:`indexing-ref` section for more details.
12 15
13 16 * *Feed tokens*: The feed token can only be used to access the RSS feed.
14 Usually those are safe to store inside your RSS feed reader.
15
16 * *VCS tokens*: You can use these to authenticate with |git|, |hg| and |svn|
17 operations instead of a password. They are designed to be used with
18 CI Servers or other third party tools that require |repo| access.
19 They are also a good replacement for SSH based access.
20 To use these tokens you need be enabled special authentication method on
21 |RCE|, as they are disabled by default.
22 See :ref:`enable-vcs-tokens`.
17 Usually those are safe to store inside your RSS feed reader.
23 18
24 19 * *Web Interface tokens*: These token allows users to access the web
25 20 interface of |RCE| without logging in.
@@ -41,7 +36,16 b' Authentication Tokens'
41 36 https://rhodecode.com/repo/archive/tip.zip?auth_token=<web-api-token>
42 37
43 38 # To show commit diff without logging into Web UI
44 https://rhodecode.com/repo/changeset-diff/<sha>?auth_token=<web-api-token>
39 https://rhodecode.com/repo/raw-diff/<sha>?auth_token=<web-api-token>
40
41 * *VCS tokens*: You can use these to authenticate with |git|, |hg| and |svn|
42 operations instead of a password. They are designed to be used with
43 CI Servers or other third party tools that require |repo| access.
44 They are also a good replacement for SSH based access.
45 To use these tokens you need be enabled special authentication method on
46 |RCE|, as they are disabled by default.
47 See :ref:`enable-vcs-tokens`.
48
45 49
46 50 .. _enable-vcs-tokens:
47 51
@@ -51,7 +55,7 b' Enabling VCS Tokens'
51 55 To enable VCS Tokens, use the following steps:
52 56
53 57 1. Go to :menuselection:`Admin --> Authentication`.
54 2. Enable the ``rhodecode.lib.auth_modules.auth_token`` plugin.
58 2. Activate the ``rhodecode.lib.auth_modules.auth_token`` plugin.
55 59 3. Click :guilabel:`Save`.
56 60
57 61 Authentication Token Tips
@@ -67,7 +71,7 b' Creating Tokens'
67 71
68 72 To create authentication tokens for an user, use the following steps:
69 73
70 1. From the |RCM| interface go to
74 1. From the |RCE| interface go to
71 75 :menuselection:`Username --> My Account --> Auth tokens`.
72 76
73 77 2. Label and Add the tokens you wish to use with |RCE|.
@@ -4,29 +4,31 b' Authentication Options'
4 4 ======================
5 5
6 6 |RCE| provides a built in authentication against its own database. This is
7 implemented using ``rhodecode.lib.auth_rhodecode`` plugin. This plugin is
8 enabled by default.
7 implemented using ``RhodeCode Internal`` plugin. This plugin is enabled by default.
9 8 Additionally, |RCE| provides a Pluggable Authentication System. This gives the
10 9 administrator greater control over how users authenticate with the system.
11 10
12 11 .. important::
13 12
14 You can disable the built in |RCM| authentication plugin
15 ``rhodecode.lib.auth_rhodecode`` and force all authentication to go
13 You can disable the built in |RCE| authentication plugin
14 ``RhodeCode Internal`` and force all authentication to go
16 15 through your authentication plugin of choice e.g LDAP only.
17 16 However, if you do this, and your external authentication tools fails,
18 you will be unable to access |RCM|.
17 accessing |RCE| will be blocked unless a fallback plugin is
18 enabled via :file: rhodecode.ini
19 19
20 |RCM| comes with the following user authentication management plugins:
20
21 |RCE| comes with the following user authentication management plugins:
21 22
22 23
23 24 .. toctree::
24 25
26 auth-token
25 27 auth-ldap
26 28 auth-ldap-groups
29 auth-saml-generic
30 auth-saml-onelogin
31 auth-saml-duosecurity
27 32 auth-crowd
28 33 auth-pam
29 auth-token
30 34 ssh-connection
31
32
@@ -3,27 +3,73 b''
3 3 Active Directory
4 4 ----------------
5 5
6 |RCM| can use Microsoft Active Directory for user authentication. This is
6 |RCE| can use Microsoft Active Directory for user authentication. This is
7 7 done through an LDAP or LDAPS connection to Active Directory. Use the
8 8 following example LDAP configuration setting to set your Active Directory
9 authentication.
10
11 .. code-block:: ini
12
13 # Set the Base DN
14 Base DN = OU=SBSUsers,OU=Users,OU=MyBusiness,DC=v3sys,DC=local
15 # Set the Active Directory SAM-Account-Name
16 Login Attribute = sAMAccountName
17 # Set the Active Directory user name
18 First Name Attribute = usernameame
19 # Set the Active Directory user surname
20 Last Name Attribute = user_surname
21 # Set the Active Directory user email
22 E-mail Attribute = userEmail
9 authentication::
23 10
24 11
25 Below is example setup that can be used with Active Directory and ldap groups.
12 *option*: `enabled` => `True`
13 # Enable or disable this authentication plugin.
14
15 *option*: `cache_ttl` => `360`
16 # Amount of seconds to cache the authentication and permissions check response call for this plugin.
17 # Useful for expensive calls like LDAP to improve the performance of the system (0 means disabled).
18
19 *option*: `host` => `192.168.245.143,192.168.1.240`
20 # Host[s] of the LDAP Server
21 # (e.g., 192.168.2.154, or ldap-server.domain.com.
22 # Multiple servers can be specified using commas
23
24 *option*: `port` => `389`
25 # Custom port that the LDAP server is listening on. Default value is: 389, use 689 for LDAPS(SSL)
26
27 *option*: `timeout` => `300`
28 # Timeout for LDAP connection
29
30 *option*: `dn_user` => `Administrator@rhodecode.com`
31 # Optional user DN/account to connect to LDAP if authentication is required.
32 # e.g., cn=admin,dc=mydomain,dc=com, or uid=root,cn=users,dc=mydomain,dc=com, or admin@mydomain.com
33
34 *option*: `dn_pass` => `SomeSecret`
35 # Password to authenticate for given user DN.
36
37 *option*: `tls_kind` => `PLAIN`
38 # TLS Type
39
40 *option*: `tls_reqcert` => `NEVER`
41 # Require Cert over TLS?. Self-signed and custom certificates can be used when
42 # `RhodeCode Certificate` found in admin > settings > system info page is extended.
26 43
27 .. image:: ../images/ldap-groups-example.png
28 :alt: LDAP/AD setup example
29 :scale: 50 % No newline at end of file
44 *option*: `tls_cert_file` => ``
45 # This specifies the PEM-format file path containing certificates for use in TLS connection.
46 # If not specified `TLS Cert dir` will be used
47
48 *option*: `tls_cert_dir` => `/etc/openldap/cacerts`
49 # This specifies the path of a directory that contains individual CA certificates in separate files.
50
51 *option*: `base_dn` => `OU=SBSUsers,OU=Users,OU=MyBusiness,DC=v3sys,DC=local`
52 # Base DN to search. Dynamic bind is supported. Add `$login` marker in it to be replaced with current user credentials
53 # (e.g., dc=mydomain,dc=com, or ou=Users,dc=mydomain,dc=com)
54
55 *option*: `filter` => `(objectClass=person)`
56 # Filter to narrow results
57 # (e.g., (&(objectCategory=Person)(objectClass=user)), or
58 # (memberof=cn=rc-login,ou=groups,ou=company,dc=mydomain,dc=com)))
59
60 *option*: `search_scope` => `SUBTREE`
61 # How deep to search LDAP. If unsure set to SUBTREE
62
63 *option*: `attr_login` => `sAMAccountName`
64 # LDAP Attribute to map to user name (e.g., uid, or sAMAccountName)
65
66 *option*: `attr_email` => `userEmail`
67 # LDAP Attribute to map to email address (e.g., mail).
68 # Emails are a crucial part of RhodeCode.
69 # If possible add a valid email attribute to ldap users.
70
71 *option*: `attr_firstname` => `user_firstname`
72 # LDAP Attribute to map to first name (e.g., givenName)
73
74 *option*: `attr_lastname` => `user_surname`
75 # LDAP Attribute to map to last name (e.g., sn)
@@ -46,7 +46,7 b' The following LDAP attributes are requir'
46 46 * The LDAP username or account used to connect to |RCE|. This will be added
47 47 to the LDAP filter for locating the user object.
48 48 * For example, if an LDAP filter is specified as `LDAPFILTER`,
49 the login attribute is specified as `uid`, and the user connects as
49 the login/username attribute is specified as `uid`, and the user connects as
50 50 `jsmith`, then the LDAP Filter will be like the following example.
51 51
52 52 .. code-block:: vim
@@ -68,7 +68,7 b' The following LDAP attributes are requir'
68 68 Optional settings
69 69 ^^^^^^^^^^^^^^^^^
70 70
71 The following are optional when enabling LDAP on |RCM|
71 The following are optional when enabling LDAP on |RCE|
72 72
73 73 * An LDAP account is only required if the LDAP server does not allow
74 74 anonymous browsing of records.
@@ -104,10 +104,4 b' The following are optional when enabling'
104 104 following directory: `/etc/openldap/cacerts`
105 105
106 106
107 Below is example setup that can be used with Active Directory and ldap groups.
108
109 .. image:: ../images/ldap-groups-example.png
110 :alt: LDAP/AD setup example
111 :scale: 50 %
112
113 107 .. _RFC 2254: http://www.rfc-base.org/rfc-2254.html No newline at end of file
@@ -3,7 +3,7 b''
3 3 Code Review
4 4 ===========
5 5
6 |RCM| provides two ways in which you can review code. You can review |prs| or
6 |RCE| provides two ways in which you can review code. You can review |prs| or
7 7 commits. To better understand |prs|, see the :ref:`pull-requests-ref`
8 8 and :ref:`collaborate-ref` sections. For more information about why
9 9 code review matters, see these posts on the topic:
@@ -16,7 +16,7 b' review purposes.'
16 16 Reviewing Changes
17 17 -----------------
18 18
19 |RCM| displays all code changes made with each commit. Removed content is
19 |RCE| displays all code changes made with each commit. Removed content is
20 20 marked in red and new content in green.
21 21
22 22 .. image:: ../images/plain-diff.png
@@ -10,7 +10,7 b' 3. Leave a commit message that outlines '
10 10 4. Set the review status to :guilabel:`Approved`
11 11 5. Select :guilabel:`Comment`
12 12
13 If you approve the |pr|, you will be able to merge automatically if |RCM|
13 If you approve the |pr|, you will be able to merge automatically if |RCE|
14 14 detects that it can do so safely. You will see this message:
15 15
16 16 :guilabel:`This pull request can be automatically merged.`
@@ -7,7 +7,7 b' Collaboration'
7 7
8 8 Forking and branching does not work with |svn| |repos|.
9 9
10 Collaboration in |RCM| is accomplished through a combination of the following
10 Collaboration in |RCE| is accomplished through a combination of the following
11 11 functions:
12 12
13 13 .. only:: latex
@@ -55,7 +55,7 b' on the web interface. To branch a |git| '
55 55 $ git commit -a -m "ghost script: initial file"
56 56 $ git push
57 57
58 Once it is pushed to the |RCM| server, you can switch to the newly created
58 Once it is pushed to the |RCE| server, you can switch to the newly created
59 59 branch using the following steps:
60 60
61 61 1. Select :menuselection:`Admin --> Repositories`.
@@ -4,7 +4,7 b' Using Notifications'
4 4 -------------------
5 5
6 6 To notify users of items that require their attention you can use the mention
7 function. The mention function allows you to use ``@username`` within |RCM|.
7 function. The mention function allows you to use ``@username`` within |RCE|.
8 8 The notification function can be used within the following
9 9 items to highlight their need for attention:
10 10
@@ -3,7 +3,7 b''
3 3 Merge a |pr|
4 4 ------------
5 5
6 |RCM| can detect if it can automatically merge the changes in a |pr|. If it
6 |RCE| can detect if it can automatically merge the changes in a |pr|. If it
7 7 can, you will see the following message:
8 8 :guilabel:`This pull request can be automatically merged.` To merge,
9 9 click the big blue button! To enable this feature, see :ref:`server-side-merge`.
@@ -21,7 +21,7 b' messages:'
21 21 Manual Merge a |PR|
22 22 ^^^^^^^^^^^^^^^^^^^
23 23
24 If |RCM| cannot safely merge the changes in a |pr|,
24 If |RCE| cannot safely merge the changes in a |pr|,
25 25 usually due to conflicts, you need to manually merge the changes on the
26 26 command line. You can see more information for each |repo| type at the
27 27 following links:
@@ -1,7 +1,7 b''
1 1 Notifications Overview
2 2 ----------------------
3 3
4 |RCM| has an integrated notification system which alerts users to requests
4 |RCE| has an integrated notification system which alerts users to requests
5 5 that they have received. Notifications can occur for the following reasons:
6 6
7 7 * Pull request reviews
@@ -3,7 +3,7 b' Pull request management'
3 3
4 4 .. only:: html
5 5
6 There are two ways of tracking |prs| within |RCM|.
6 There are two ways of tracking |prs| within |RCE|.
7 7
8 8 1. :ref:`prs-your-review`
9 9 2. :ref:`prs-per-repo`
@@ -15,7 +15,7 b' Pull requests for your review'
15 15
16 16 To view pull requests for your review, use the following steps:
17 17
18 1. From the |RCM| interface, Select
18 1. From the |RCE| interface, Select
19 19 :menuselection:`username --> Notifications`
20 20 2. Select :guilabel:`Pull Requests`
21 21
@@ -20,7 +20,7 b' 3. Set the review status from one of the'
20 20 4. Select Comment
21 21
22 22 When the |pr| is approved by all reviewers you will be able to merge
23 automatically if |RCM| detects that it can do so safely. You will see this
23 automatically if |RCE| detects that it can do so safely. You will see this
24 24 message: `This pull request can be automatically merged.`
25 25
26 26 If rejected, you can fix the issues raised during review and then update the
@@ -1,7 +1,7 b''
1 1 Supported Workflows
2 2 -------------------
3 3
4 |RCM| can be used to develop using a variety of different workflows.
4 |RCE| can be used to develop using a variety of different workflows.
5 5
6 6 * Centralized, using |svn|, |git|, or |hg| |repos|
7 7 * Feature-Branch, using |git| or |hg| |repos|
@@ -20,10 +20,7 b" rst_epilog = '''"
20 20 .. |psf| replace:: Python Software Foundation
21 21 .. |repo| replace:: repository
22 22 .. |repos| replace:: repositories
23 .. |RCI| replace:: RhodeCode Control
24 23 .. |RCC| replace:: RhodeCode Control
25 .. |RCV| replace:: RhodeCode Enterprise
26 .. |RCM| replace:: RhodeCode Enterprise
27 24 .. |RCE| replace:: RhodeCode Enterprise
28 25 .. |RCCE| replace:: RhodeCode Community
29 26 .. |RCEE| replace:: RhodeCode Enterprise
@@ -31,6 +28,5 b" rst_epilog = '''"
31 28 .. |RCT| replace:: RhodeCode Tools
32 29 .. |RCEBOLD| replace:: **RhodeCode Enterprise**
33 30 .. |RCEITALICS| replace:: `RhodeCode Enterprise`
34 .. |RC| replace:: RhodeCode
35 31 .. |RNS| replace:: Release Notes
36 32 '''
@@ -18,7 +18,7 b' so to clarify what is meant each time, r'
18 18 Hooks
19 19 -----
20 20
21 Within |RCM| there are two types of supported hooks.
21 Within |RCE| there are two types of supported hooks.
22 22
23 23 * **Internal built-in hooks**: The internal |hg|, |git| or |svn| hooks are
24 24 triggered by different VCS operations, like push, pull,
@@ -1,13 +1,13 b''
1 |RCM|
1 |RCE|
2 2 =====
3 3
4 |RCM| is a high-performance source code management and collaboration system.
4 |RCE| is a high-performance source code management and collaboration system.
5 5 It enables you to develop projects securely behind the firewall while
6 6 providing collaboration tools that work with |git|, |hg|,
7 7 and |svn| |repos|. The user interface allows you to create, edit,
8 8 and commit files and |repos| while managing their security permissions.
9 9
10 |RCM| provides the following features:
10 |RCE| provides the following features:
11 11
12 12 * Source code management.
13 13 * Extended permissions management.
@@ -18,7 +18,7 b' and commit files and |repos| while manag'
18 18 * Web-based hook management.
19 19 * Native |svn| support.
20 20 * Migration from existing databases.
21 * |RCM| SDK.
21 * |RCE| SDK.
22 22 * Built-in analytics
23 23 * Built in integrations including: Slack, Webhooks (used for Jenkins/TeamCity and other CIs), Jira, Redmine, Hipchat
24 24 * Pluggable authentication system.
@@ -5,8 +5,24 b' Supported Databases'
5 5
6 6 .. important::
7 7
8 We do not recommend using SQLite in a production environment. It is
9 supported by |RCE| for evaluation purposes.
8 We do not recommend using SQLite in a production environment of more than 5 people.
9 It is not suited for higher usage and mayb cause problems.
10
11
12 |RCE| supports the following databases. The recommended encoding is UTF-8.
13
14 .. only:: latex
15
16 * :ref:`install-sqlite-database`
17 * :ref:`install-mysql-database`
18 * :ref:`install-postgresql-database`
19
20 .. toctree::
21
22 using-mysql
23 using-postgresql
24 using-sqllite
25
10 26
11 27 Database Overview
12 28 -----------------
@@ -48,21 +64,3 b' following example to configure the corre'
48 64 # for the RCE instance you are installing
49 65 Database name: example-db-name-for-2xx # The 2xx version database
50 66 Database name: example-db-name-for-3xx # The 3xx version database
51
52 Supported Databases
53 -------------------
54
55 |RCM| supports the following databases. The recommended encoding is Unicode
56 UTF-8.
57
58 .. only:: latex
59
60 * :ref:`install-sqlite-database`
61 * :ref:`install-mysql-database`
62 * :ref:`install-postgresql-database`
63
64 .. toctree::
65
66 using-mysql
67 using-postgresql
68 using-sqllite
@@ -4,7 +4,7 b' Post Installation Tasks'
4 4 =======================
5 5
6 6 The following tasks are the most common post installation requirements. Use
7 the information in these sections to configure your instance of |RCM|.
7 the information in these sections to configure your instance of |RCE|.
8 8
9 9 .. toctree::
10 10
@@ -3,21 +3,21 b''
3 3 Migrating |repos|
4 4 -----------------
5 5
6 If you have installed |RCM| and have |repos| that you wish to migrate into
6 If you have installed |RCE| and have |repos| that you wish to migrate into
7 7 the system, use the following instructions.
8 8
9 1. On the |RCM| interface, check your |repo| storage location under
9 1. On the |RCE| interface, check your |repo| storage location under
10 10 :menuselection:`Admin --> Settings --> System Info`. For example,
11 11 Storage location: /home/{username}/repos.
12 12
13 2. Copy the |repos| that you want |RCM| to manage to this location.
13 2. Copy the |repos| that you want |RCE| to manage to this location.
14 14 3. Remap and rescan the |repos|, see :ref:`remap-rescan`
15 15
16 16 .. important::
17 17
18 Directories create |repo| groups inside |RCM|.
18 Directories create |repo| groups inside |RCE|.
19 19
20 Importing adds |RCM| git hooks to your |repos|.
20 Importing adds |RCE| git hooks to your |repos|.
21 21
22 22 You should verify if custom ``.hg`` or ``.hgrc`` files inside
23 repositories should be adjusted since |RCM| reads the content of them.
23 repositories should be adjusted since |RCE| reads the content of them.
@@ -27,9 +27,12 b' 2. Run the |RCC| installer and accept th'
27 27
28 28 .. code-block:: bash
29 29
30 $ chmod 755 RhodeCode-installer-linux-*
30 $ chmod +x RhodeCode-installer-linux-*
31 31 $ ./RhodeCode-installer-linux-*
32 32
33 Do you accept the RhodeCode Control license?
34 Press [Y] to accept license and [V] to view license text: y
35
33 36 3. Install a VCS Server, and configure it to start at boot.
34 37
35 38 .. code-block:: bash
@@ -3,12 +3,12 b''
3 3 Set up Email
4 4 ------------
5 5
6 To setup email with your |RCM| instance, open the default
6 To setup email with your |RCE| instance, open the default
7 7 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
8 8 file and uncomment and configure the email section. If it is not there,
9 9 use the below example to insert it.
10 10
11 Once configured you can check the settings for your |RCM| instance on the
11 Once configured you can check the settings for your |RCE| instance on the
12 12 :menuselection:`Admin --> Settings --> Email` page.
13 13
14 14 .. code-block:: ini
@@ -4,15 +4,15 b' MySQL or MariaDB'
4 4 ----------------
5 5
6 6 To use a MySQL or MariaDB database you should install and configure the
7 database before installing |RCM|. This is because during |RCM| installation
7 database before installing |RCE|. This is because during |RCE| installation
8 8 you will setup a connection to your MySQL or MariaDB database. To work with
9 9 either, use the following steps:
10 10
11 11 1. Depending on your |os|, install a MySQL or MariaDB database following the
12 12 appropriate instructions from the `MySQL website`_ or `MariaDB website`_.
13 13 2. Configure the database with a username and password which you will use
14 with |RCM|.
15 3. Install |RCM|, and during installation select MySQL as your database.
14 with |RCE|.
15 3. Install |RCE|, and during installation select MySQL as your database.
16 16 4. Enter the following information during the database setup:
17 17
18 18 * Your network IP Address
@@ -4,15 +4,15 b' PostgreSQL'
4 4 ----------
5 5
6 6 To use a PostgreSQL database, you should install and configure the database
7 before installing |RCV|. This is because during |RCV| installation you will
7 before installing |RCE|. This is because during |RCE| installation you will
8 8 setup the connection to your PostgreSQL database. To work with PostgreSQL,
9 9 use the following steps:
10 10
11 11 1. Depending on your |os|, install a PostgreSQL database following the
12 12 appropriate instructions from the `PostgreSQL website`_.
13 13 2. Configure the database with a username and password, which you will use
14 with |RCV|.
15 3. Install |RCV|, and during installation select PostgreSQL as your database.
14 with |RCE|.
15 3. Install |RCE|, and during installation select PostgreSQL as your database.
16 16 4. Enter the following information during the database setup:
17 17
18 18 * Your network IP Address
@@ -9,15 +9,15 b' SQLite'
9 9 as it has an internal locking mechanism which can become a performance
10 10 bottleneck when there are more than 5 concurrent users.
11 11
12 |RCM| installs SQLite as the default database if you do not specify another
12 |RCE| installs SQLite as the default database if you do not specify another
13 13 during installation. SQLite is suitable for small teams,
14 14 projects with a low load, and evaluation purposes since it is built into
15 |RCM| and does not require any additional database server.
15 |RCE| and does not require any additional database server.
16 16
17 17 Using MySQL or PostgreSQL in an large setup gives you much greater
18 18 performance, and while migration tools exist to move from one database type
19 19 to another, it is better to get it right first time and to immediately use
20 MySQL or PostgreSQL when you deploy |RCM| in a production environment.
20 MySQL or PostgreSQL when you deploy |RCE| in a production environment.
21 21
22 22 Migrating From SQLite to PostgreSQL
23 23 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,20 +11,20 b' different Slack channels, for example.'
11 11 Supported integrations
12 12 ^^^^^^^^^^^^^^^^^^^^^^
13 13
14 ================================ ============ ========================================
15 Type/Name |RC| Edition Description
16 ================================ ============ ========================================
17 :ref:`integrations-webhook` |RCCEshort| Trigger events as `json` to a custom url
18 :ref:`integrations-slack` |RCCEshort| Integrate with https://slack.com/
19 :ref:`integrations-hipchat` |RCCEshort| Integrate with https://www.hipchat.com/
20 :ref:`integrations-email` |RCCEshort| Send repo push commits by email
21 :ref:`integrations-ci` |RCCEshort| Trigger Builds for Common CI Systems
22 :ref:`integrations-rcextensions` |RCCEshort| Advanced low-level integration framework
14 ================================ ================== ========================================
15 Type/Name RhodeCode Edition Description
16 ================================ ================== ========================================
17 :ref:`integrations-webhook` |RCCEshort| Trigger events as `json` to a custom url
18 :ref:`integrations-slack` |RCCEshort| Integrate with https://slack.com/
19 :ref:`integrations-hipchat` |RCCEshort| Integrate with https://www.hipchat.com/
20 :ref:`integrations-email` |RCCEshort| Send repo push commits by email
21 :ref:`integrations-ci` |RCCEshort| Trigger Builds for Common CI Systems
22 :ref:`integrations-rcextensions` |RCCEshort| Advanced low-level integration framework
23 23
24 :ref:`integrations-jenkins` |RCEEshort| Trigger Builds for Jenkins CI System
25 :ref:`integrations-redmine` |RCEEshort| Close/Resolve/Reference Redmine issues
26 :ref:`integrations-jira` |RCEEshort| Close/Resolve/Reference JIRA issues
27 ================================ ============ ========================================
24 :ref:`integrations-jenkins` |RCEEshort| Trigger Builds for Jenkins CI System
25 :ref:`integrations-redmine` |RCEEshort| Close/Resolve/Reference Redmine issues
26 :ref:`integrations-jira` |RCEEshort| Close/Resolve/Reference JIRA issues
27 ================================ ================== ========================================
28 28
29 29 .. _creating-integrations:
30 30
@@ -9,7 +9,7 b' You can set an issue tracker connection '
9 9 * At the |repo| level, you can configure an integration with a different issue
10 10 tracker.
11 11
12 To integrate |RCM| with an issue tracker, you need to define a regular
12 To integrate |RCE| with an issue tracker, you need to define a regular
13 13 expression that will fetch the issue ID stored in commit messages, and replace
14 14 it with a URL. This enables |RCE| to generate a link matching each issue to the
15 15 target |repo|.
@@ -7,7 +7,7 b' Error Message'
7 7 Error creating repository repo-name
8 8
9 9 Cause
10 As of |RCM| 3.0, a VCS Server is required to run backend operations.
10 As of |RCE| 3.0, a VCS Server is required to run backend operations.
11 11
12 12 Solution
13 13 Install a VCS Server. See the `Install a VCS Server`_ section of |RCC|
@@ -3,7 +3,7 b''
3 3 Nix Packaging
4 4 =============
5 5
6 |RCM| is installed using |Nix Package Manager|. The Nix environment provides
6 |RCE| is installed using |Nix Package Manager|. The Nix environment provides
7 7 the following features for maintenance and deployment:
8 8
9 9 * Atomic upgrades and rollbacks
@@ -5,11 +5,11 b''
5 5
6 6 self: super: {
7 7 "alabaster" = super.buildPythonPackage {
8 name = "alabaster-0.7.11";
8 name = "alabaster-0.7.12";
9 9 doCheck = false;
10 10 src = fetchurl {
11 url = "https://files.pythonhosted.org/packages/3f/46/9346ea429931d80244ab7f11c4fce83671df0b7ae5a60247a2b588592c46/alabaster-0.7.11.tar.gz";
12 sha256 = "1mvm69xsn5xf1jc45kdq1mn0yq0pfn54mv2jcww4s1vwqx6iyfxn";
11 url = "https://files.pythonhosted.org/packages/cc/b4/ed8dcb0d67d5cfb7f83c4d5463a7614cb1d078ad7ae890c9143edebbf072/alabaster-0.7.12.tar.gz";
12 sha256 = "00nwwjj2d2ym4s2kk217x7jkx1hnczc3fvm8yxbqmsp6b0nxfqd6";
13 13 };
14 14 };
15 15 "babel" = super.buildPythonPackage {
@@ -24,11 +24,11 b' self: super: {'
24 24 };
25 25 };
26 26 "certifi" = super.buildPythonPackage {
27 name = "certifi-2018.8.24";
27 name = "certifi-2018.11.29";
28 28 doCheck = false;
29 29 src = fetchurl {
30 url = "https://files.pythonhosted.org/packages/e1/0f/f8d5e939184547b3bdc6128551b831a62832713aa98c2ccdf8c47ecc7f17/certifi-2018.8.24.tar.gz";
31 sha256 = "0f0nhrj9mlrf79iway4578wrsgmjh0fmacl9zv8zjckdy7b90rip";
30 url = "https://files.pythonhosted.org/packages/55/54/3ce77783acba5979ce16674fc98b1920d00b01d337cfaaf5db22543505ed/certifi-2018.11.29.tar.gz";
31 sha256 = "1dvccavd2fzq4j37w0sznylp92ps14zi6gvlxzm23in0yhzciya7";
32 32 };
33 33 };
34 34 "chardet" = super.buildPythonPackage {
@@ -83,31 +83,31 b' self: super: {'
83 83 };
84 84 };
85 85 "packaging" = super.buildPythonPackage {
86 name = "packaging-17.1";
86 name = "packaging-18.0";
87 87 doCheck = false;
88 88 propagatedBuildInputs = [
89 89 self."pyparsing"
90 90 self."six"
91 91 ];
92 92 src = fetchurl {
93 url = "https://files.pythonhosted.org/packages/77/32/439f47be99809c12ef2da8b60a2c47987786d2c6c9205549dd6ef95df8bd/packaging-17.1.tar.gz";
94 sha256 = "0nrpayk8kij1zm9sjnk38ldz3a6705ggvw8ljylqbrb4vmqbf6gh";
93 url = "https://files.pythonhosted.org/packages/cf/50/1f10d2626df0aa97ce6b62cf6ebe14f605f4e101234f7748b8da4138a8ed/packaging-18.0.tar.gz";
94 sha256 = "01wq9c53ix5rz6qg2c98gy8n4ff768rmanifm8m5jpjiaizj51h8";
95 95 };
96 96 };
97 97 "pygments" = super.buildPythonPackage {
98 name = "pygments-2.2.0";
98 name = "pygments-2.3.0";
99 99 doCheck = false;
100 100 src = fetchurl {
101 url = "https://files.pythonhosted.org/packages/71/2a/2e4e77803a8bd6408a2903340ac498cb0a2181811af7c9ec92cb70b0308a/Pygments-2.2.0.tar.gz";
102 sha256 = "1k78qdvir1yb1c634nkv6rbga8wv4289xarghmsbbvzhvr311bnv";
101 url = "https://files.pythonhosted.org/packages/63/a2/91c31c4831853dedca2a08a0f94d788fc26a48f7281c99a303769ad2721b/Pygments-2.3.0.tar.gz";
102 sha256 = "1z34ms51dh4jq4h3cizp7vd1dmsxcbvffkjsd2xxfav22nn6lrl2";
103 103 };
104 104 };
105 105 "pyparsing" = super.buildPythonPackage {
106 name = "pyparsing-2.2.0";
106 name = "pyparsing-2.3.0";
107 107 doCheck = false;
108 108 src = fetchurl {
109 url = "https://files.pythonhosted.org/packages/3c/ec/a94f8cf7274ea60b5413df054f82a8980523efd712ec55a59e7c3357cf7c/pyparsing-2.2.0.tar.gz";
110 sha256 = "016b9gh606aa44sq92jslm89bg874ia0yyiyb643fa6dgbsbqch8";
109 url = "https://files.pythonhosted.org/packages/d0/09/3e6a5eeb6e04467b737d55f8bba15247ac0876f98fae659e58cd744430c6/pyparsing-2.3.0.tar.gz";
110 sha256 = "14k5v7n3xqw8kzf42x06bzp184spnlkya2dpjyflax6l3yrallzk";
111 111 };
112 112 };
113 113 "pytz" = super.buildPythonPackage {
@@ -119,7 +119,7 b' self: super: {'
119 119 };
120 120 };
121 121 "requests" = super.buildPythonPackage {
122 name = "requests-2.19.1";
122 name = "requests-2.20.1";
123 123 doCheck = false;
124 124 propagatedBuildInputs = [
125 125 self."chardet"
@@ -128,16 +128,16 b' self: super: {'
128 128 self."certifi"
129 129 ];
130 130 src = fetchurl {
131 url = "https://files.pythonhosted.org/packages/54/1f/782a5734931ddf2e1494e4cd615a51ff98e1879cbe9eecbdfeaf09aa75e9/requests-2.19.1.tar.gz";
132 sha256 = "0snf8xxdzsgh1x2zv3vilvbrv9jbpmnfagzzb1rjmmvflckdh8pc";
131 url = "https://files.pythonhosted.org/packages/40/35/298c36d839547b50822985a2cf0611b3b978a5ab7a5af5562b8ebe3e1369/requests-2.20.1.tar.gz";
132 sha256 = "0qzj6cgv3k9wyj7wlxgz7xq0cfg4jbbkfm24pp8dnhczwl31527a";
133 133 };
134 134 };
135 135 "setuptools" = super.buildPythonPackage {
136 name = "setuptools-40.2.0";
136 name = "setuptools-40.6.2";
137 137 doCheck = false;
138 138 src = fetchurl {
139 url = "https://files.pythonhosted.org/packages/ef/1d/201c13e353956a1c840f5d0fbf0461bd45bbd678ea4843ebf25924e8984c/setuptools-40.2.0.zip";
140 sha256 = "19ng5m7kigllg3x96c91y3a2k28g6kwnbb1v4warrnp4xma1v227";
139 url = "https://files.pythonhosted.org/packages/b0/d1/8acb42f391cba52e35b131e442e80deffbb8d0676b93261d761b1f0ef8fb/setuptools-40.6.2.zip";
140 sha256 = "0r2c5hapirlzm34h7pl1lgkm6gk7bcrlrdj28qgsvaqg3f74vfw6";
141 141 };
142 142 };
143 143 "six" = super.buildPythonPackage {
@@ -157,7 +157,7 b' self: super: {'
157 157 };
158 158 };
159 159 "sphinx" = super.buildPythonPackage {
160 name = "sphinx-1.7.8";
160 name = "sphinx-1.8.2";
161 161 doCheck = false;
162 162 propagatedBuildInputs = [
163 163 self."six"
@@ -175,8 +175,8 b' self: super: {'
175 175 self."typing"
176 176 ];
177 177 src = fetchurl {
178 url = "https://files.pythonhosted.org/packages/ac/54/4ef326d0c654da1ed91341a7a1f43efc18a8c770ddd2b8e45df97cb79d82/Sphinx-1.7.8.tar.gz";
179 sha256 = "1ryz0w4c31930f1br2sjwrxwx9cmsy7cqdb0d81g98n9bj250w50";
178 url = "https://files.pythonhosted.org/packages/4c/ea/7388faba7cf02999e1bc42f6a8eb1ea0120aec3dd93474cee21cea2d693f/Sphinx-1.8.2.tar.gz";
179 sha256 = "1sia2h5rfzy76rbsd69ghr8bbidhsjzzinf3f523dcmivp5k41qj";
180 180 };
181 181 };
182 182 "sphinx-rtd-theme" = super.buildPythonPackage {
@@ -207,11 +207,11 b' self: super: {'
207 207 };
208 208 };
209 209 "urllib3" = super.buildPythonPackage {
210 name = "urllib3-1.23";
210 name = "urllib3-1.24.1";
211 211 doCheck = false;
212 212 src = fetchurl {
213 url = "https://files.pythonhosted.org/packages/3c/d2/dc5471622bd200db1cd9319e02e71bc655e9ea27b8e0ce65fc69de0dac15/urllib3-1.23.tar.gz";
214 sha256 = "1bvbd35q3zdcd7gsv38fwpizy7p06dr0154g5gfybrvnbvhwb2m6";
213 url = "https://files.pythonhosted.org/packages/b1/53/37d82ab391393565f2f831b8eedbffd57db5a718216f82f1a8b4d381a1c1/urllib3-1.24.1.tar.gz";
214 sha256 = "08lwd9f3hqznyf32vnzwvp87pchx062nkbgyrf67rwlkgj0jk5fy";
215 215 };
216 216 };
217 217
@@ -1,7 +1,7 b''
1 1 |RCE| 3.0.0 |RNS|
2 2 -----------------
3 3
4 As |RCM| 3.0 is a big release, the release notes have been split into the following sections:
4 As |RCE| 3.0 is a big release, the release notes have been split into the following sections:
5 5
6 6 * :ref:`general-rn-ref`
7 7 * :ref:`security-rn-ref`
@@ -9,6 +9,7 b' Release Notes'
9 9 .. toctree::
10 10 :maxdepth: 1
11 11
12 release-notes-4.15.0.rst
12 13 release-notes-4.14.1.rst
13 14 release-notes-4.14.0.rst
14 15 release-notes-4.13.3.rst
@@ -1,8 +1,8 b''
1 sphinx==1.7.8
1 sphinx==1.8.2
2 2 six==1.11.0
3 3 sphinx_rtd_theme==0.4.1
4 4 docutils==0.14.0
5 pygments==2.2.0
5 pygments==2.3.0
6 6 markupsafe==1.0.0
7 7 jinja2==2.9.6
8 8 pytz==2018.4
@@ -44,10 +44,10 b' following example:'
44 44 Installing |RCT|
45 45 ^^^^^^^^^^^^^^^^
46 46
47 |RCT| enable you to automate many of the most common |RCM| functions through
47 |RCT| enable you to automate many of the most common |RCE| functions through
48 48 the API. Installing them on a local machine lets you carry out maintenance on
49 49 the server remotely. Once installed you can use them to index your |repos|
50 to setup full-text search, strip commits, or install |RC| Extensions for
50 to setup full-text search, strip commits, or install RhodeCode Extensions for
51 51 additional functionality.
52 52
53 53 For more detailed instructions about using |RCT| for indexing and full-text
@@ -3,7 +3,7 b''
3 3 |RCT|
4 4 =====
5 5
6 |RCT| enable you to automate many of the most common |RCM| functions through
6 |RCT| enable you to automate many of the most common |RCE| functions through
7 7 the API.
8 8
9 9 .. toctree::
@@ -16,7 +16,7 b' rhodecode-tools'
16 16 ---------------
17 17
18 18 Use |RCT| to setup automation, run the indexer, and install extensions for
19 your |RCM| instances. Options:
19 your |RCE| instances. Options:
20 20
21 21 .. rst-class:: dl-horizontal
22 22
@@ -49,7 +49,7 b' Example usage:'
49 49 rhodecode-api
50 50 -------------
51 51
52 The |RC| API lets you connect to |RCE| and carry out management tasks from a
52 The RhodeCode API lets you connect to |RCE| and carry out management tasks from a
53 53 remote machine, for more information about the API, see the :ref:`api`. To
54 54 pass arguments on the command-line use the ``method:option`` syntax.
55 55
@@ -117,7 +117,7 b' Options:'
117 117 rhodecode-cleanup-gists
118 118 -----------------------
119 119
120 Use this to delete gists within |RCM|. Options:
120 Use this to delete gists within |RCE|. Options:
121 121
122 122 .. rst-class:: dl-horizontal
123 123
@@ -166,7 +166,7 b' Example usage:'
166 166 rhodecode-cleanup-repos
167 167 -----------------------
168 168
169 Use this to manage |repos| and |repo| groups within |RCM|. Options:
169 Use this to manage |repos| and |repo| groups within |RCE|. Options:
170 170
171 171 .. rst-class:: dl-horizontal
172 172
@@ -280,7 +280,7 b' the using :ref:`integrations-rcextension'
280 280 rhodecode-gist
281 281 --------------
282 282
283 Use this to create, list, show, or delete gists within |RCM|. Options:
283 Use this to create, list, show, or delete gists within |RCE|. Options:
284 284
285 285 .. rst-class:: dl-horizontal
286 286
@@ -7,7 +7,7 b' To install |RCT| correctly, see the inst'
7 7 :ref:`install-tools`, and :ref:`config-rhoderc`.
8 8
9 9 Once |RCT| is installed, and the :file:`/home/{user}/.rhoderc` file is
10 configured you can then use |RCT| on each |RCM| instance to carry out admin
10 configured you can then use |RCT| on each |RCE| instance to carry out admin
11 11 tasks. Use the following example to configure that file,
12 12 and once configured see the :ref:`tools-cli` for more details.
13 13
@@ -95,10 +95,10 b' but below is the example shortcut.'
95 95
96 96 # Check that the script is uploaded to your home directory
97 97 $ ls -1
98 RhodeCode-installer-linux-391_b1a804c4d69b_d6c087d520e3
98 RhodeCode-installer-linux-buildYYYYXXXX_ZZZZ
99 99
100 100 # Change the script permissions
101 $ chmod 755 RhodeCode-installer-linux*
101 $ chmod +x RhodeCode-installer-linux*
102 102
103 103 # Run the installer and accept the prompts
104 104 $ ./RhodeCode-installer-linux-*
@@ -7,13 +7,13 b''
7 7 Git Large File Storage (or LFS) is a new, open-source extension to Git that
8 8 aims to improve handling of large files. It does this by replacing large files
9 9 in your repository—such as graphics and videos—with simple text pointers.
10 |RC| Server includes an embedded LFS object store server, allowing storage of
10 RhodeCode Server includes an embedded LFS object store server, allowing storage of
11 11 large files without the need for an external object store.
12 12 Git LFS is disabled by default, globally, and for each individual repository.
13 13
14 14 .. note::
15 15
16 |RC| implements V2 API of Git LFS. Please make sure your git client is
16 RhodeCode implements V2 API of Git LFS. Please make sure your git client is
17 17 using the latest version (2.0.X recommended) to leverage full feature set
18 18 of the V2 API.
19 19
@@ -22,7 +22,7 b' Git LFS is disabled by default, globally'
22 22 Enabling Git LFS
23 23 ++++++++++++++++
24 24
25 Git LFS is disabled by default within |RC| Server.
25 Git LFS is disabled by default within RhodeCode Server.
26 26
27 27 To enable Git LFS Globally:
28 28
@@ -87,7 +87,7 b' size in bytes. For example::'
87 87
88 88
89 89 The object itself will be uploaded to a separate location via the Git LFS Batch API.
90 The transfer is validated and authorized by |RC| server itself.
90 The transfer is validated and authorized by RhodeCode server itself.
91 91
92 92 If give repository has Git LFS disabled, a proper message will be sent back to
93 93 the client and upload of LFS objects will be forbidden.
@@ -13,7 +13,7 b' of the current revision. This saves both'
13 13 Enabling HG Largefiles
14 14 ++++++++++++++++++++++
15 15
16 Mercurial Largefiles extension is disabled by default within |RC| Server.
16 Mercurial Largefiles extension is disabled by default within RhodeCode Server.
17 17
18 18 To enable Mercurial Largefiles Globally:
19 19
@@ -25,7 +25,7 b' Pre-requisites'
25 25 * For MySQL, do not use `localhost` in the database connection string of the
26 26 :file:`rhodecode.ini` file.
27 27 * InnoDB must be the database tables engine.
28 * Contact |RC| for a new licence Key/Token pair. If you don't, a trial licence
28 * Contact RhodeCode for a new licence Key/Token pair. If you don't, a trial licence
29 29 will be applied so you are not locked out of the upgraded instance.
30 30
31 31 You can find the specific instructions to carry out these pre-requisite steps
@@ -3,19 +3,19 b''
3 3 Getting Started with VCS
4 4 ------------------------
5 5
6 When using |RCM|, you will be working with |git|, |svn| or |hg| |repos| from the
6 When using |RCE|, you will be working with |git|, |svn| or |hg| |repos| from the
7 7 command line or using a GUI client such as Tortoise, Tower or SourceTree.
8 8
9 |RCM| uses a standard |git|, |svn| and |hg| protocols. So all tools that
9 |RCE| uses a standard |git|, |svn| and |hg| protocols. So all tools that
10 10 can interact with there protocols are supported, including Eclipse or PyCharm
11 11 plugins.
12 12
13 13
14 14 If you have never used either before, the following information should
15 15 help you set up your local machine so that you can sync changes with the
16 |RCM| server.
16 |RCE| server.
17 17
18 All of the following instructions assume you have a |RCM| account,
18 All of the following instructions assume you have a |RCE| account,
19 19 and you can access your |repos| from the web interface.
20 20
21 21 .. note::
@@ -3,14 +3,14 b' File Editing'
3 3
4 4 To edit files using the online editor, use the following steps.
5 5
6 1. From the |RCM| interface, select :menuselection:`Admin --> Repositories`
6 1. From the |RCE| interface, select :menuselection:`Admin --> Repositories`
7 7 2. Select the |repo| in which you want to edit a file.
8 8 3. Select the :guilabel:`file` view of the |repo|, and double-click on the file.
9 9 4. To open the editor, select the :guilabel:`edit on branch:default` button.
10 10
11 * If the filename has an extension |RCM| recognises,
11 * If the filename has an extension |RCE| recognises,
12 12 the syntax highlighting will appear automatically.
13 * If the filename does not have an extension |RCM| recognises,
13 * If the filename does not have an extension |RCE| recognises,
14 14 you can set the language syntax highlighter by
15 15 choosing from the file type drop down menu.
16 16 5. To save your changes, select :guilabel:`Commit changes`
@@ -4,7 +4,7 b' Gist Editing'
4 4 ^^^^^^^^^^^^
5 5
6 6 Gists are standalone files that only the creator can edit. To work with
7 gists, click on the :guilabel:`Gists` tab on the |RCM| header. The gist
7 gists, click on the :guilabel:`Gists` tab on the |RCE| header. The gist
8 8 editor also has syntax highlighting.
9 9
10 10 You can set the following properties for each gist:
@@ -13,7 +13,7 b' You can set the following properties for'
13 13 and will show up in searches.
14 14 * :guilabel:`Gist Lifetime`: You can set a gist to expire after a set
15 15 period by using the :guilabel:`Gist Lifetime` dropdown menu.
16 This means that when the gist expires it will be deleted from the |RCM|
16 This means that when the gist expires it will be deleted from the |RCE|
17 17 gist database.
18 18 * :guilabel:`Private`: This means that the gist will not show up in searches.
19 19 * :guilabel:`Gist access level`: If you create a private gist you can have
@@ -1,7 +1,7 b''
1 1 Online Editing
2 2 --------------
3 3
4 |RCM| has an integrated online editor, allowing you to edit files in the
4 |RCE| has an integrated online editor, allowing you to edit files in the
5 5 browser. The online editor has syntax highlighting and the ability to fork,
6 6 merge, and commit changes to files.
7 7
@@ -13,13 +13,13 b' let'
13 13 sha512 = "tx5TauYSmzsIvmSqepUPDYbs4/Ejz2XbZ1IkD7JEGqkdNUJlh+9KU85G56Tfdk/xjEZ8zorFfN09OSwiMrIQWA==";
14 14 };
15 15 };
16 "@polymer/iron-a11y-announcer-3.0.1" = {
16 "@polymer/iron-a11y-announcer-3.0.2" = {
17 17 name = "_at_polymer_slash_iron-a11y-announcer";
18 18 packageName = "@polymer/iron-a11y-announcer";
19 version = "3.0.1";
20 src = fetchurl {
21 url = "https://registry.npmjs.org/@polymer/iron-a11y-announcer/-/iron-a11y-announcer-3.0.1.tgz";
22 sha512 = "Xiqmpz0AEEbMNGYPpbrXBIrcI/xaR4tn77pmSLfxVKGGwjEUR/YrRgyIwXp4EN7lvst1dFC8kyl2hLga0uDIVQ==";
19 version = "3.0.2";
20 src = fetchurl {
21 url = "https://registry.npmjs.org/@polymer/iron-a11y-announcer/-/iron-a11y-announcer-3.0.2.tgz";
22 sha512 = "LqnMF39mXyxSSRbTHRzGbcJS8nU0NVTo2raBOgOlpxw5yfGJUVcwaTJ/qy5NtWCZLRfa4suycf0oAkuUjHTXHQ==";
23 23 };
24 24 };
25 25 "@polymer/iron-a11y-keys-3.0.1" = {
@@ -229,13 +229,13 b' let'
229 229 sha1 = "e7365648c1b42136a59c7d5040637b3b5c83b614";
230 230 };
231 231 };
232 "@types/node-6.14.0" = {
232 "@types/node-6.14.2" = {
233 233 name = "_at_types_slash_node";
234 234 packageName = "@types/node";
235 version = "6.14.0";
236 src = fetchurl {
237 url = "https://registry.npmjs.org/@types/node/-/node-6.14.0.tgz";
238 sha512 = "6tQyh4Q4B5pECcXBOQDZ5KjyBIxRZGzrweGPM47sAYTdVG4+7R+2EGMTmp0h6ZwgqHrFRCeg2gdhsG9xXEl2Sg==";
235 version = "6.14.2";
236 src = fetchurl {
237 url = "https://registry.npmjs.org/@types/node/-/node-6.14.2.tgz";
238 sha512 = "JWB3xaVfsfnFY8Ofc9rTB/op0fqqTSqy4vBcVk1LuRJvta7KTX+D//fCkiTMeLGhdr2EbFZzQjC97gvmPilk9Q==";
239 239 };
240 240 };
241 241 "@types/parse5-2.2.34" = {
@@ -409,22 +409,22 b' let'
409 409 sha512 = "mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==";
410 410 };
411 411 };
412 "@webcomponents/shadycss-1.5.2" = {
412 "@webcomponents/shadycss-1.6.0" = {
413 413 name = "_at_webcomponents_slash_shadycss";
414 414 packageName = "@webcomponents/shadycss";
415 version = "1.5.2";
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.5.2.tgz";
418 sha512 = "0OyrmVc7S+INtzoqP2ofAo+OdVn2Nj0Qvq4wD9FEGN7nMmLRxaD2mzy6hD6EslzxUSuGH302CDU4KXiY66SEqg==";
419 };
420 };
421 "@webcomponents/webcomponentsjs-2.1.3" = {
415 version = "1.6.0";
416 src = fetchurl {
417 url = "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.6.0.tgz";
418 sha512 = "iURGZZU6BaiRJtGgjMn208QxPkY11QwT/VmuHNa4Yb+kJxU/WODe4C8b0LDOtnk4KJzJg50hCfwvPRAjePEzbA==";
419 };
420 };
421 "@webcomponents/webcomponentsjs-2.2.1" = {
422 422 name = "_at_webcomponents_slash_webcomponentsjs";
423 423 packageName = "@webcomponents/webcomponentsjs";
424 version = "2.1.3";
425 src = fetchurl {
426 url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.1.3.tgz";
427 sha512 = "0UHJNY88lR3pnEYtBVT7F8cuuxOiITQGWJa0LxoELqkBSB7IabzJFOj5K99PajD3CGAsWpjB0CAeijfe376Y1w==";
424 version = "2.2.1";
425 src = fetchurl {
426 url = "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.2.1.tgz";
427 sha512 = "lZZ+Lkke6JhsJcQQqSVk1Pny6/8y4qhJ98LO7a/MwBSRO8WqHqK1X2vscfeL8vOnYGFnmBUyVG95lwYv/AXyLQ==";
428 428 };
429 429 };
430 430 "@xtuc/ieee754-1.2.0" = {
@@ -499,13 +499,13 b' let'
499 499 sha1 = "82ffb02b29e662ae53bdc20af15947706739c536";
500 500 };
501 501 };
502 "ajv-6.5.4" = {
502 "ajv-6.6.1" = {
503 503 name = "ajv";
504 504 packageName = "ajv";
505 version = "6.5.4";
506 src = fetchurl {
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz";
508 sha512 = "4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==";
505 version = "6.6.1";
506 src = fetchurl {
507 url = "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz";
508 sha512 = "ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==";
509 509 };
510 510 };
511 511 "ajv-keywords-3.2.0" = {
@@ -1454,13 +1454,13 b' let'
1454 1454 sha512 = "DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==";
1455 1455 };
1456 1456 };
1457 "bluebird-3.5.2" = {
1457 "bluebird-3.5.3" = {
1458 1458 name = "bluebird";
1459 1459 packageName = "bluebird";
1460 version = "3.5.2";
1461 src = fetchurl {
1462 url = "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz";
1463 sha512 = "dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==";
1460 version = "3.5.3";
1461 src = fetchurl {
1462 url = "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz";
1463 sha512 = "/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==";
1464 1464 };
1465 1465 };
1466 1466 "bn.js-4.11.8" = {
@@ -1661,13 +1661,13 b' let'
1661 1661 sha1 = "9bb5304d2e0b56698b2c758b08a3eaa9daa58a39";
1662 1662 };
1663 1663 };
1664 "camelcase-4.1.0" = {
1664 "camelcase-5.0.0" = {
1665 1665 name = "camelcase";
1666 1666 packageName = "camelcase";
1667 version = "4.1.0";
1668 src = fetchurl {
1669 url = "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz";
1670 sha1 = "d545635be1e33c542649c69173e5de6acfae34dd";
1667 version = "5.0.0";
1668 src = fetchurl {
1669 url = "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz";
1670 sha512 = "faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==";
1671 1671 };
1672 1672 };
1673 1673 "caniuse-api-1.6.1" = {
@@ -1679,22 +1679,22 b' let'
1679 1679 sha1 = "b534e7c734c4f81ec5fbe8aca2ad24354b962c6c";
1680 1680 };
1681 1681 };
1682 "caniuse-db-1.0.30000900" = {
1682 "caniuse-db-1.0.30000912" = {
1683 1683 name = "caniuse-db";
1684 1684 packageName = "caniuse-db";
1685 version = "1.0.30000900";
1686 src = fetchurl {
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000900.tgz";
1688 sha512 = "fvicVRDlhHIQpt/bmbLl3hDHKUZb5ZP8O2OuZLz2fSEPlUBbvwwbhhqhGS617ldN6bDoo9A3+MQKQyFq0p7UXA==";
1689 };
1690 };
1691 "caniuse-lite-1.0.30000900" = {
1685 version = "1.0.30000912";
1686 src = fetchurl {
1687 url = "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000912.tgz";
1688 sha512 = "uiepPdHcJ06Na9t15L5l+pp3NWQU4IETbmleghD6tqCqbIYqhHSu7nVfbK2gqPjfy+9jl/wHF1UQlyTszh9tJQ==";
1689 };
1690 };
1691 "caniuse-lite-1.0.30000912" = {
1692 1692 name = "caniuse-lite";
1693 1693 packageName = "caniuse-lite";
1694 version = "1.0.30000900";
1695 src = fetchurl {
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000900.tgz";
1697 sha512 = "xDVs8pBFr6bzq9pXUkLKpGQQnzsF/l6/yX38UnCkTcUcwC0rDl1NGZGildcJVTU+uGBxfsyniK/ZWagPNn1Oqw==";
1694 version = "1.0.30000912";
1695 src = fetchurl {
1696 url = "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000912.tgz";
1697 sha512 = "M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==";
1698 1698 };
1699 1699 };
1700 1700 "caseless-0.12.0" = {
@@ -1814,13 +1814,13 b' let'
1814 1814 sha1 = "22817534f24bfa4950c34d532d48ecbc621b8c14";
1815 1815 };
1816 1816 };
1817 "clipboard-2.0.1" = {
1817 "clipboard-2.0.4" = {
1818 1818 name = "clipboard";
1819 1819 packageName = "clipboard";
1820 version = "2.0.1";
1821 src = fetchurl {
1822 url = "https://registry.npmjs.org/clipboard/-/clipboard-2.0.1.tgz";
1823 sha512 = "7yhQBmtN+uYZmfRjjVjKa0dZdWuabzpSKGtyQZN+9C8xlC788SSJjOHWh7tzurfwTqTD5UDYAhIv5fRJg3sHjQ==";
1820 version = "2.0.4";
1821 src = fetchurl {
1822 url = "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz";
1823 sha512 = "Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==";
1824 1824 };
1825 1825 };
1826 1826 "cliui-2.1.0" = {
@@ -2093,13 +2093,13 b' let'
2093 2093 sha1 = "676f6eb3c39997c2ee1ac3a924fd6124748f578d";
2094 2094 };
2095 2095 };
2096 "copy-webpack-plugin-4.5.4" = {
2096 "copy-webpack-plugin-4.6.0" = {
2097 2097 name = "copy-webpack-plugin";
2098 2098 packageName = "copy-webpack-plugin";
2099 version = "4.5.4";
2100 src = fetchurl {
2101 url = "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.4.tgz";
2102 sha512 = "0lstlEyj74OAtYMrDxlNZsU7cwFijAI3Ofz2fD6Mpo9r4xCv4yegfa3uHIKvZY1NSuOtE9nvG6TAhJ+uz9gDaQ==";
2099 version = "4.6.0";
2100 src = fetchurl {
2101 url = "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz";
2102 sha512 = "Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==";
2103 2103 };
2104 2104 };
2105 2105 "core-js-2.5.7" = {
@@ -2201,13 +2201,13 b' let'
2201 2201 sha1 = "2b3a110539c5355f1cd8d314623e870b121ec858";
2202 2202 };
2203 2203 };
2204 "css-selector-tokenizer-0.7.0" = {
2204 "css-selector-tokenizer-0.7.1" = {
2205 2205 name = "css-selector-tokenizer";
2206 2206 packageName = "css-selector-tokenizer";
2207 version = "0.7.0";
2208 src = fetchurl {
2209 url = "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz";
2210 sha1 = "e6988474ae8c953477bf5e7efecfceccd9cf4c86";
2207 version = "0.7.1";
2208 src = fetchurl {
2209 url = "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz";
2210 sha512 = "xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==";
2211 2211 };
2212 2212 };
2213 2213 "css-what-2.1.2" = {
@@ -2318,15 +2318,6 b' let'
2318 2318 sha1 = "f6534d15148269b20352e7bee26f501f9a191290";
2319 2319 };
2320 2320 };
2321 "decamelize-2.0.0" = {
2322 name = "decamelize";
2323 packageName = "decamelize";
2324 version = "2.0.0";
2325 src = fetchurl {
2326 url = "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz";
2327 sha512 = "Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==";
2328 };
2329 };
2330 2321 "decode-uri-component-0.2.0" = {
2331 2322 name = "decode-uri-component";
2332 2323 packageName = "decode-uri-component";
@@ -2561,13 +2552,13 b' let'
2561 2552 sha1 = "3a83a904e54353287874c564b7549386849a98c9";
2562 2553 };
2563 2554 };
2564 "electron-to-chromium-1.3.82" = {
2555 "electron-to-chromium-1.3.85" = {
2565 2556 name = "electron-to-chromium";
2566 2557 packageName = "electron-to-chromium";
2567 version = "1.3.82";
2568 src = fetchurl {
2569 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz";
2570 sha512 = "NI4nB2IWGcU4JVT1AE8kBb/dFor4zjLHMLsOROPahppeHrR0FG5uslxMmkp/thO1MvPjM2xhlKoY29/I60s0ew==";
2558 version = "1.3.85";
2559 src = fetchurl {
2560 url = "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.85.tgz";
2561 sha512 = "kWSDVVF9t3mft2OHVZy4K85X2beP6c6mFm3teFS/mLSDJpQwuFIWHrULCX+w6H1E55ZYmFRlT+ATAFRwhrYzsw==";
2571 2562 };
2572 2563 };
2573 2564 "elliptic-6.4.1" = {
@@ -2912,13 +2903,13 b' let'
2912 2903 sha1 = "d5142c0caee6b1189f87d3a76111064f86c8bbf2";
2913 2904 };
2914 2905 };
2915 "fastparse-1.1.1" = {
2906 "fastparse-1.1.2" = {
2916 2907 name = "fastparse";
2917 2908 packageName = "fastparse";
2918 version = "1.1.1";
2919 src = fetchurl {
2920 url = "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz";
2921 sha1 = "d1e2643b38a94d7583b479060e6c4affc94071f8";
2909 version = "1.1.2";
2910 src = fetchurl {
2911 url = "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz";
2912 sha512 = "483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==";
2922 2913 };
2923 2914 };
2924 2915 "favico.js-0.3.10" = {
@@ -3308,13 +3299,13 b' let'
3308 3299 sha1 = "15a4806a57547cb2d2dbf27f42e89a8c3451b364";
3309 3300 };
3310 3301 };
3311 "graceful-fs-4.1.11" = {
3302 "graceful-fs-4.1.15" = {
3312 3303 name = "graceful-fs";
3313 3304 packageName = "graceful-fs";
3314 version = "4.1.11";
3315 src = fetchurl {
3316 url = "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz";
3317 sha1 = "0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658";
3305 version = "4.1.15";
3306 src = fetchurl {
3307 url = "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz";
3308 sha512 = "6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==";
3318 3309 };
3319 3310 };
3320 3311 "grunt-0.4.5" = {
@@ -3326,13 +3317,13 b' let'
3326 3317 sha1 = "56937cd5194324adff6d207631832a9d6ba4e7f0";
3327 3318 };
3328 3319 };
3329 "grunt-cli-1.3.1" = {
3320 "grunt-cli-1.3.2" = {
3330 3321 name = "grunt-cli";
3331 3322 packageName = "grunt-cli";
3332 version = "1.3.1";
3333 src = fetchurl {
3334 url = "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.1.tgz";
3335 sha512 = "UwBRu/QpAjDc53DRLEkyilFdL0zenpxu+fddTIlsF/KJqdNcHaQmvyu1W3cDesZ9rqqZdKK5A8+QDIyLUEWoZQ==";
3323 version = "1.3.2";
3324 src = fetchurl {
3325 url = "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz";
3326 sha512 = "8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==";
3336 3327 };
3337 3328 };
3338 3329 "grunt-contrib-concat-0.5.1" = {
@@ -4631,13 +4622,13 b' let'
4631 4622 sha1 = "6d4524e8b955f95d4f5b58851ce21dd72fb4e952";
4632 4623 };
4633 4624 };
4634 "lru-cache-4.1.3" = {
4625 "lru-cache-4.1.5" = {
4635 4626 name = "lru-cache";
4636 4627 packageName = "lru-cache";
4637 version = "4.1.3";
4638 src = fetchurl {
4639 url = "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz";
4640 sha512 = "fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==";
4628 version = "4.1.5";
4629 src = fetchurl {
4630 url = "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz";
4631 sha512 = "sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==";
4641 4632 };
4642 4633 };
4643 4634 "make-dir-1.3.0" = {
@@ -4658,13 +4649,13 b' let'
4658 4649 sha512 = "pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==";
4659 4650 };
4660 4651 };
4661 "map-age-cleaner-0.1.2" = {
4652 "map-age-cleaner-0.1.3" = {
4662 4653 name = "map-age-cleaner";
4663 4654 packageName = "map-age-cleaner";
4664 version = "0.1.2";
4665 src = fetchurl {
4666 url = "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz";
4667 sha512 = "UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==";
4655 version = "0.1.3";
4656 src = fetchurl {
4657 url = "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz";
4658 sha512 = "bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==";
4668 4659 };
4669 4660 };
4670 4661 "map-cache-0.2.2" = {
@@ -5261,13 +5252,13 b' let'
5261 5252 sha512 = "hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==";
5262 5253 };
5263 5254 };
5264 "pako-1.0.6" = {
5255 "pako-1.0.7" = {
5265 5256 name = "pako";
5266 5257 packageName = "pako";
5267 version = "1.0.6";
5268 src = fetchurl {
5269 url = "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz";
5270 sha512 = "lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==";
5258 version = "1.0.7";
5259 src = fetchurl {
5260 url = "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz";
5261 sha512 = "3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==";
5271 5262 };
5272 5263 };
5273 5264 "parallel-transform-1.1.0" = {
@@ -5711,13 +5702,13 b' let'
5711 5702 sha1 = "b2c6a98c0072cf91b932d1a496508114311735bf";
5712 5703 };
5713 5704 };
5714 "postcss-modules-extract-imports-1.2.0" = {
5705 "postcss-modules-extract-imports-1.2.1" = {
5715 5706 name = "postcss-modules-extract-imports";
5716 5707 packageName = "postcss-modules-extract-imports";
5717 version = "1.2.0";
5718 src = fetchurl {
5719 url = "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz";
5720 sha1 = "66140ecece38ef06bf0d3e355d69bf59d141ea85";
5708 version = "1.2.1";
5709 src = fetchurl {
5710 url = "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz";
5711 sha512 = "6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==";
5721 5712 };
5722 5713 };
5723 5714 "postcss-modules-local-by-default-1.2.0" = {
@@ -6737,13 +6728,13 b' let'
6737 6728 sha1 = "04e6926f662895354f3dd015203633b857297e2c";
6738 6729 };
6739 6730 };
6740 "sshpk-1.15.1" = {
6731 "sshpk-1.15.2" = {
6741 6732 name = "sshpk";
6742 6733 packageName = "sshpk";
6743 version = "1.15.1";
6744 src = fetchurl {
6745 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz";
6746 sha512 = "mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==";
6734 version = "1.15.2";
6735 src = fetchurl {
6736 url = "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz";
6737 sha512 = "Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==";
6747 6738 };
6748 6739 };
6749 6740 "ssri-5.3.0" = {
@@ -6863,6 +6854,15 b' let'
6863 6854 sha512 = "n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==";
6864 6855 };
6865 6856 };
6857 "string_decoder-1.2.0" = {
6858 name = "string_decoder";
6859 packageName = "string_decoder";
6860 version = "1.2.0";
6861 src = fetchurl {
6862 url = "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz";
6863 sha512 = "6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==";
6864 };
6865 };
6866 6866 "stringstream-0.0.6" = {
6867 6867 name = "stringstream";
6868 6868 packageName = "stringstream";
@@ -6971,22 +6971,22 b' let'
6971 6971 sha1 = "9f5772413952135c6fefbf40afe6a4faa88b4bb5";
6972 6972 };
6973 6973 };
6974 "tapable-0.2.8" = {
6974 "tapable-0.2.9" = {
6975 6975 name = "tapable";
6976 6976 packageName = "tapable";
6977 version = "0.2.8";
6978 src = fetchurl {
6979 url = "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz";
6980 sha1 = "99372a5c999bf2df160afc0d74bed4f47948cd22";
6981 };
6982 };
6983 "tapable-1.1.0" = {
6977 version = "0.2.9";
6978 src = fetchurl {
6979 url = "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz";
6980 sha512 = "2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==";
6981 };
6982 };
6983 "tapable-1.1.1" = {
6984 6984 name = "tapable";
6985 6985 packageName = "tapable";
6986 version = "1.1.0";
6987 src = fetchurl {
6988 url = "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz";
6989 sha512 = "IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==";
6986 version = "1.1.1";
6987 src = fetchurl {
6988 url = "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz";
6989 sha512 = "9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==";
6990 6990 };
6991 6991 };
6992 6992 "throttleit-1.0.0" = {
@@ -7007,13 +7007,13 b' let'
7007 7007 sha1 = "0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5";
7008 7008 };
7009 7009 };
7010 "through2-2.0.3" = {
7010 "through2-2.0.5" = {
7011 7011 name = "through2";
7012 7012 packageName = "through2";
7013 version = "2.0.3";
7014 src = fetchurl {
7015 url = "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz";
7016 sha1 = "0004569b37c7c74ba39c43f3ced78d1ad94140be";
7013 version = "2.0.5";
7014 src = fetchurl {
7015 url = "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz";
7016 sha512 = "/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==";
7017 7017 };
7018 7018 };
7019 7019 "timers-browserify-2.0.10" = {
@@ -7439,13 +7439,13 b' let'
7439 7439 sha512 = "1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==";
7440 7440 };
7441 7441 };
7442 "v8flags-3.0.2" = {
7442 "v8flags-3.1.1" = {
7443 7443 name = "v8flags";
7444 7444 packageName = "v8flags";
7445 version = "3.0.2";
7446 src = fetchurl {
7447 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.0.2.tgz";
7448 sha512 = "6sgSKoFw1UpUPd3cFdF7QGnrH6tDeBgW1F3v9gy8gLY0mlbiBXq8soy8aQpY6xeeCjH5K+JvC62Acp7gtl7wWA==";
7445 version = "3.1.1";
7446 src = fetchurl {
7447 url = "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz";
7448 sha512 = "iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==";
7449 7449 };
7450 7450 };
7451 7451 "vendors-1.0.2" = {
@@ -7628,15 +7628,6 b' let'
7628 7628 sha1 = "b5243d8f3ec1aa35f1364605bc0d1036e30ab69f";
7629 7629 };
7630 7630 };
7631 "xregexp-4.0.0" = {
7632 name = "xregexp";
7633 packageName = "xregexp";
7634 version = "4.0.0";
7635 src = fetchurl {
7636 url = "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz";
7637 sha512 = "PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==";
7638 };
7639 };
7640 7631 "xtend-4.0.1" = {
7641 7632 name = "xtend";
7642 7633 packageName = "xtend";
@@ -7664,13 +7655,13 b' let'
7664 7655 sha1 = "1c11f9218f076089a47dd512f93c6699a6a81d52";
7665 7656 };
7666 7657 };
7667 "yargs-12.0.2" = {
7658 "yargs-12.0.5" = {
7668 7659 name = "yargs";
7669 7660 packageName = "yargs";
7670 version = "12.0.2";
7671 src = fetchurl {
7672 url = "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz";
7673 sha512 = "e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==";
7661 version = "12.0.5";
7662 src = fetchurl {
7663 url = "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz";
7664 sha512 = "Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==";
7674 7665 };
7675 7666 };
7676 7667 "yargs-3.10.0" = {
@@ -7682,13 +7673,13 b' let'
7682 7673 sha1 = "f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1";
7683 7674 };
7684 7675 };
7685 "yargs-parser-10.1.0" = {
7676 "yargs-parser-11.1.1" = {
7686 7677 name = "yargs-parser";
7687 7678 packageName = "yargs-parser";
7688 version = "10.1.0";
7689 src = fetchurl {
7690 url = "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz";
7691 sha512 = "VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==";
7679 version = "11.1.1";
7680 src = fetchurl {
7681 url = "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz";
7682 sha512 = "C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==";
7692 7683 };
7693 7684 };
7694 7685 "yauzl-2.4.1" = {
@@ -7708,7 +7699,7 b' let'
7708 7699 src = ./..;
7709 7700 dependencies = [
7710 7701 sources."@polymer/font-roboto-3.0.2"
7711 sources."@polymer/iron-a11y-announcer-3.0.1"
7702 sources."@polymer/iron-a11y-announcer-3.0.2"
7712 7703 sources."@polymer/iron-a11y-keys-3.0.1"
7713 7704 sources."@polymer/iron-a11y-keys-behavior-3.0.1"
7714 7705 sources."@polymer/iron-ajax-3.0.1"
@@ -7732,7 +7723,7 b' let'
7732 7723 sources."@polymer/paper-tooltip-3.0.1"
7733 7724 sources."@polymer/polymer-3.1.0"
7734 7725 sources."@types/clone-0.1.30"
7735 sources."@types/node-6.14.0"
7726 sources."@types/node-6.14.2"
7736 7727 sources."@types/parse5-2.2.34"
7737 7728 sources."@webassemblyjs/ast-1.7.10"
7738 7729 sources."@webassemblyjs/floating-point-hex-parser-1.7.10"
@@ -7752,8 +7743,8 b' let'
7752 7743 sources."@webassemblyjs/wasm-parser-1.7.10"
7753 7744 sources."@webassemblyjs/wast-parser-1.7.10"
7754 7745 sources."@webassemblyjs/wast-printer-1.7.10"
7755 sources."@webcomponents/shadycss-1.5.2"
7756 sources."@webcomponents/webcomponentsjs-2.1.3"
7746 sources."@webcomponents/shadycss-1.6.0"
7747 sources."@webcomponents/webcomponentsjs-2.2.1"
7757 7748 sources."@xtuc/ieee754-1.2.0"
7758 7749 sources."@xtuc/long-4.2.1"
7759 7750 sources."abbrev-1.1.1"
@@ -7927,7 +7918,7 b' let'
7927 7918 sources."bcrypt-pbkdf-1.0.2"
7928 7919 sources."big.js-3.2.0"
7929 7920 sources."binary-extensions-1.12.0"
7930 sources."bluebird-3.5.2"
7921 sources."bluebird-3.5.3"
7931 7922 sources."bn.js-4.11.8"
7932 7923 sources."boolbase-1.0.0"
7933 7924 sources."boom-2.10.1"
@@ -7952,22 +7943,22 b' let'
7952 7943 (sources."cacache-10.0.4" // {
7953 7944 dependencies = [
7954 7945 sources."glob-7.1.3"
7955 sources."graceful-fs-4.1.11"
7956 sources."lru-cache-4.1.3"
7946 sources."graceful-fs-4.1.15"
7947 sources."lru-cache-4.1.5"
7957 7948 sources."minimatch-3.0.4"
7958 7949 sources."rimraf-2.6.2"
7959 7950 ];
7960 7951 })
7961 7952 sources."cache-base-1.0.1"
7962 7953 sources."camel-case-3.0.0"
7963 sources."camelcase-4.1.0"
7954 sources."camelcase-5.0.0"
7964 7955 (sources."caniuse-api-1.6.1" // {
7965 7956 dependencies = [
7966 7957 sources."browserslist-1.7.7"
7967 7958 ];
7968 7959 })
7969 sources."caniuse-db-1.0.30000900"
7970 sources."caniuse-lite-1.0.30000900"
7960 sources."caniuse-db-1.0.30000912"
7961 sources."caniuse-lite-1.0.30000912"
7971 7962 sources."caseless-0.12.0"
7972 7963 sources."center-align-0.1.3"
7973 7964 sources."chalk-0.5.1"
@@ -8017,7 +8008,7 b' let'
8017 8008 sources."minimatch-3.0.4"
8018 8009 ];
8019 8010 })
8020 sources."clipboard-2.0.1"
8011 sources."clipboard-2.0.4"
8021 8012 (sources."cliui-4.1.0" // {
8022 8013 dependencies = [
8023 8014 sources."ansi-regex-3.0.0"
@@ -8058,7 +8049,7 b' let'
8058 8049 ];
8059 8050 })
8060 8051 sources."copy-descriptor-0.1.1"
8061 (sources."copy-webpack-plugin-4.5.4" // {
8052 (sources."copy-webpack-plugin-4.6.0" // {
8062 8053 dependencies = [
8063 8054 sources."is-glob-4.0.0"
8064 8055 sources."minimatch-3.0.4"
@@ -8079,18 +8070,14 b' let'
8079 8070 sources."css-color-names-0.0.4"
8080 8071 sources."css-loader-0.28.11"
8081 8072 sources."css-select-1.2.0"
8082 (sources."css-selector-tokenizer-0.7.0" // {
8073 (sources."css-selector-tokenizer-0.7.1" // {
8083 8074 dependencies = [
8084 8075 sources."regexpu-core-1.0.0"
8085 8076 ];
8086 8077 })
8087 8078 sources."css-what-2.1.2"
8088 8079 sources."cssesc-0.1.0"
8089 (sources."cssnano-3.10.0" // {
8090 dependencies = [
8091 sources."decamelize-1.2.0"
8092 ];
8093 })
8080 sources."cssnano-3.10.0"
8094 8081 sources."csso-2.3.2"
8095 8082 sources."cycle-1.0.3"
8096 8083 sources."cyclist-0.2.2"
@@ -8102,7 +8089,7 b' let'
8102 8089 sources."date-now-0.1.4"
8103 8090 sources."dateformat-1.0.2-1.2.3"
8104 8091 sources."debug-2.6.9"
8105 sources."decamelize-2.0.0"
8092 sources."decamelize-1.2.0"
8106 8093 sources."decode-uri-component-0.2.0"
8107 8094 sources."deep-for-each-2.0.3"
8108 8095 sources."define-properties-1.1.3"
@@ -8139,13 +8126,13 b' let'
8139 8126 ];
8140 8127 })
8141 8128 sources."ecc-jsbn-0.1.2"
8142 sources."electron-to-chromium-1.3.82"
8129 sources."electron-to-chromium-1.3.85"
8143 8130 sources."elliptic-6.4.1"
8144 8131 sources."emojis-list-2.1.0"
8145 8132 sources."end-of-stream-1.4.1"
8146 8133 (sources."enhanced-resolve-4.1.0" // {
8147 8134 dependencies = [
8148 sources."graceful-fs-4.1.11"
8135 sources."graceful-fs-4.1.15"
8149 8136 ];
8150 8137 })
8151 8138 sources."entities-1.0.0"
@@ -8203,7 +8190,7 b' let'
8203 8190 sources."eyes-0.1.8"
8204 8191 sources."fast-deep-equal-2.0.1"
8205 8192 sources."fast-json-stable-stringify-2.0.0"
8206 sources."fastparse-1.1.1"
8193 sources."fastparse-1.1.2"
8207 8194 sources."favico.js-0.3.10"
8208 8195 sources."faye-websocket-0.4.4"
8209 8196 sources."fd-slicer-1.0.1"
@@ -8244,12 +8231,12 b' let'
8244 8231 })
8245 8232 (sources."fs-extra-1.0.0" // {
8246 8233 dependencies = [
8247 sources."graceful-fs-4.1.11"
8234 sources."graceful-fs-4.1.15"
8248 8235 ];
8249 8236 })
8250 8237 (sources."fs-write-stream-atomic-1.0.10" // {
8251 8238 dependencies = [
8252 sources."graceful-fs-4.1.11"
8239 sources."graceful-fs-4.1.15"
8253 8240 ];
8254 8241 })
8255 8242 sources."fs.realpath-1.0.0"
@@ -8293,7 +8280,7 b' let'
8293 8280 sources."good-listener-1.2.2"
8294 8281 sources."graceful-fs-1.2.3"
8295 8282 sources."grunt-0.4.5"
8296 (sources."grunt-cli-1.3.1" // {
8283 (sources."grunt-cli-1.3.2" // {
8297 8284 dependencies = [
8298 8285 sources."nopt-4.0.1"
8299 8286 ];
@@ -8477,7 +8464,7 b' let'
8477 8464 sources."json5-0.5.1"
8478 8465 (sources."jsonfile-2.4.0" // {
8479 8466 dependencies = [
8480 sources."graceful-fs-4.1.11"
8467 sources."graceful-fs-4.1.15"
8481 8468 ];
8482 8469 })
8483 8470 sources."jsonify-0.0.0"
@@ -8490,14 +8477,14 b' let'
8490 8477 sources."kind-of-6.0.2"
8491 8478 (sources."klaw-1.3.1" // {
8492 8479 dependencies = [
8493 sources."graceful-fs-4.1.11"
8480 sources."graceful-fs-4.1.15"
8494 8481 ];
8495 8482 })
8496 8483 sources."lazy-cache-1.0.4"
8497 8484 sources."lcid-2.0.0"
8498 8485 (sources."less-2.7.3" // {
8499 8486 dependencies = [
8500 sources."graceful-fs-4.1.11"
8487 sources."graceful-fs-4.1.15"
8501 8488 ];
8502 8489 })
8503 8490 (sources."liftoff-2.5.0" // {
@@ -8520,7 +8507,7 b' let'
8520 8507 sources."lru-cache-2.7.3"
8521 8508 sources."make-dir-1.3.0"
8522 8509 sources."make-iterator-1.0.1"
8523 sources."map-age-cleaner-0.1.2"
8510 sources."map-age-cleaner-0.1.3"
8524 8511 sources."map-cache-0.2.2"
8525 8512 sources."map-visit-1.0.0"
8526 8513 sources."math-expression-evaluator-1.2.17"
@@ -8566,8 +8553,12 b' let'
8566 8553 sources."no-case-2.3.2"
8567 8554 (sources."node-libs-browser-2.1.0" // {
8568 8555 dependencies = [
8569 sources."readable-stream-2.3.6"
8570 sources."string_decoder-1.1.1"
8556 (sources."readable-stream-2.3.6" // {
8557 dependencies = [
8558 sources."string_decoder-1.1.1"
8559 ];
8560 })
8561 sources."string_decoder-1.2.0"
8571 8562 ];
8572 8563 })
8573 8564 sources."nopt-1.0.10"
@@ -8616,7 +8607,7 b' let'
8616 8607 sources."p-limit-1.3.0"
8617 8608 sources."p-locate-2.0.0"
8618 8609 sources."p-try-1.0.0"
8619 sources."pako-1.0.6"
8610 sources."pako-1.0.7"
8620 8611 (sources."parallel-transform-1.1.0" // {
8621 8612 dependencies = [
8622 8613 sources."readable-stream-2.3.6"
@@ -8706,7 +8697,7 b' let'
8706 8697 sources."postcss-minify-gradients-1.0.5"
8707 8698 sources."postcss-minify-params-1.2.2"
8708 8699 sources."postcss-minify-selectors-2.1.1"
8709 (sources."postcss-modules-extract-imports-1.2.0" // {
8700 (sources."postcss-modules-extract-imports-1.2.1" // {
8710 8701 dependencies = [
8711 8702 sources."ansi-styles-3.2.1"
8712 8703 sources."chalk-2.4.1"
@@ -8783,7 +8774,7 b' let'
8783 8774 })
8784 8775 (sources."readdirp-2.2.1" // {
8785 8776 dependencies = [
8786 sources."graceful-fs-4.1.11"
8777 sources."graceful-fs-4.1.15"
8787 8778 sources."readable-stream-2.3.6"
8788 8779 sources."string_decoder-1.1.1"
8789 8780 ];
@@ -8851,7 +8842,7 b' let'
8851 8842 sources."sax-1.2.4"
8852 8843 (sources."schema-utils-0.4.7" // {
8853 8844 dependencies = [
8854 sources."ajv-6.5.4"
8845 sources."ajv-6.6.1"
8855 8846 ];
8856 8847 })
8857 8848 sources."select-1.1.2"
@@ -8909,7 +8900,7 b' let'
8909 8900 sources."split-1.0.1"
8910 8901 sources."split-string-3.1.0"
8911 8902 sources."sprintf-js-1.0.3"
8912 (sources."sshpk-1.15.1" // {
8903 (sources."sshpk-1.15.2" // {
8913 8904 dependencies = [
8914 8905 sources."assert-plus-1.0.0"
8915 8906 ];
@@ -8971,10 +8962,10 b' let'
8971 8962 sources."js-yaml-3.7.0"
8972 8963 ];
8973 8964 })
8974 sources."tapable-1.1.0"
8965 sources."tapable-1.1.1"
8975 8966 sources."throttleit-1.0.0"
8976 8967 sources."through-2.3.8"
8977 (sources."through2-2.0.3" // {
8968 (sources."through2-2.0.5" // {
8978 8969 dependencies = [
8979 8970 sources."readable-stream-2.3.6"
8980 8971 sources."string_decoder-1.1.1"
@@ -9004,9 +8995,9 b' let'
9004 8995 dependencies = [
9005 8996 sources."colors-1.3.2"
9006 8997 sources."enhanced-resolve-3.4.1"
9007 sources."graceful-fs-4.1.11"
8998 sources."graceful-fs-4.1.15"
9008 8999 sources."loader-utils-0.2.17"
9009 sources."tapable-0.2.8"
9000 sources."tapable-0.2.9"
9010 9001 ];
9011 9002 })
9012 9003 sources."tslib-1.9.3"
@@ -9075,7 +9066,7 b' let'
9075 9066 sources."utila-0.4.0"
9076 9067 sources."uuid-3.3.2"
9077 9068 sources."v8-compile-cache-2.0.2"
9078 sources."v8flags-3.0.2"
9069 sources."v8flags-3.1.1"
9079 9070 sources."vendors-1.0.2"
9080 9071 (sources."verror-1.10.0" // {
9081 9072 dependencies = [
@@ -9085,13 +9076,13 b' let'
9085 9076 sources."vm-browserify-0.0.4"
9086 9077 (sources."watchpack-1.6.0" // {
9087 9078 dependencies = [
9088 sources."graceful-fs-4.1.11"
9079 sources."graceful-fs-4.1.15"
9089 9080 ];
9090 9081 })
9091 9082 sources."waypoints-4.0.1"
9092 9083 (sources."webpack-4.23.1" // {
9093 9084 dependencies = [
9094 sources."ajv-6.5.4"
9085 sources."ajv-6.6.1"
9095 9086 ];
9096 9087 })
9097 9088 (sources."webpack-cli-3.1.2" // {
@@ -9119,7 +9110,6 b' let'
9119 9110 sources."camelcase-1.2.1"
9120 9111 sources."chalk-1.1.3"
9121 9112 sources."cliui-2.1.0"
9122 sources."decamelize-1.2.0"
9123 9113 sources."has-ansi-2.0.0"
9124 9114 sources."strip-ansi-3.0.1"
9125 9115 sources."supports-color-2.0.0"
@@ -9147,11 +9137,10 b' let'
9147 9137 ];
9148 9138 })
9149 9139 sources."wrappy-1.0.2"
9150 sources."xregexp-4.0.0"
9151 9140 sources."xtend-4.0.1"
9152 9141 sources."y18n-4.0.0"
9153 9142 sources."yallist-2.1.2"
9154 (sources."yargs-12.0.2" // {
9143 (sources."yargs-12.0.5" // {
9155 9144 dependencies = [
9156 9145 sources."find-up-3.0.0"
9157 9146 sources."locate-path-3.0.0"
@@ -9160,7 +9149,7 b' let'
9160 9149 sources."p-try-2.0.0"
9161 9150 ];
9162 9151 })
9163 sources."yargs-parser-10.1.0"
9152 sources."yargs-parser-11.1.1"
9164 9153 sources."yauzl-2.4.1"
9165 9154 ];
9166 9155 buildInputs = globalBuildInputs;
@@ -72,7 +72,7 b' self: super: {'
72 72 ];
73 73 });
74 74
75 "nbconvert" = super."nbconvert".override (attrs: {
75 "nbconvert" = super."nbconvert".override (attrs: {
76 76 propagatedBuildInputs = attrs.propagatedBuildInputs ++ [
77 77 # marcink: plug in jupyter-client for notebook rendering
78 78 self."jupyter-client"
@@ -120,10 +120,12 b' self: super: {'
120 120 pkgs.curl
121 121 pkgs.openssl
122 122 ];
123
123 124 preConfigure = ''
124 125 substituteInPlace setup.py --replace '--static-libs' '--libs'
125 126 export PYCURL_SSL_LIBRARY=openssl
126 127 '';
128
127 129 meta = {
128 130 license = pkgs.lib.licenses.mit;
129 131 };
@@ -168,14 +170,32 b' self: super: {'
168 170 propagatedBuildInputs = [
169 171 pkgs.pam
170 172 ];
173
171 174 # TODO: johbo: Check if this can be avoided, or transform into
172 175 # a real patch
173 176 patchPhase = ''
174 177 substituteInPlace pam.py \
175 178 --replace 'find_library("pam")' '"${pkgs.pam}/lib/libpam.so.0"'
176 179 '';
180
177 181 });
178 182
183 "python-saml" = super."python-saml".override (attrs: {
184 buildInputs = [
185 pkgs.libxml2
186 pkgs.libxslt
187 ];
188 });
189
190 "dm.xmlsec.binding" = super."dm.xmlsec.binding".override (attrs: {
191 buildInputs = [
192 pkgs.libxml2
193 pkgs.libxslt
194 pkgs.xmlsec
195 pkgs.libtool
196 ];
197 });
198
179 199 "pyzmq" = super."pyzmq".override (attrs: {
180 200 buildInputs = [
181 201 pkgs.czmq
@@ -5,7 +5,7 b''
5 5
6 6 self: super: {
7 7 "alembic" = super.buildPythonPackage {
8 name = "alembic-0.9.9";
8 name = "alembic-1.0.5";
9 9 doCheck = false;
10 10 propagatedBuildInputs = [
11 11 self."sqlalchemy"
@@ -14,8 +14,8 b' self: super: {'
14 14 self."python-dateutil"
15 15 ];
16 16 src = fetchurl {
17 url = "https://files.pythonhosted.org/packages/89/03/756d5b8e1c90bf283c3f435766aa3f20208d1c3887579dd8f2122e01d5f4/alembic-0.9.9.tar.gz";
18 sha256 = "0bmkq6isjbmy4p7nxfvfpknjsx7rb3xn9g00169y891hcfkkxgc5";
17 url = "https://files.pythonhosted.org/packages/1c/65/b8e4f5b2f345bb13b5e0a3fddd892b0b3f0e8ad4880e954fdc6a50d00d84/alembic-1.0.5.tar.gz";
18 sha256 = "0rpjqp2iq6p49x1nli18ivak1izz547nnjxi110mzrgc1v7dxzz9";
19 19 };
20 20 meta = {
21 21 license = [ pkgs.lib.licenses.mit ];
@@ -36,7 +36,7 b' self: super: {'
36 36 };
37 37 };
38 38 "appenlight-client" = super.buildPythonPackage {
39 name = "appenlight-client-0.6.25";
39 name = "appenlight-client-0.6.26";
40 40 doCheck = false;
41 41 propagatedBuildInputs = [
42 42 self."webob"
@@ -44,8 +44,8 b' self: super: {'
44 44 self."six"
45 45 ];
46 46 src = fetchurl {
47 url = "https://files.pythonhosted.org/packages/fa/44/2911ef85ea4f4fe65058fd22959d8dad598fab6a3c84e5bcb569d15c8783/appenlight_client-0.6.25.tar.gz";
48 sha256 = "1r9l2rfg677nxhamdbyb9y4fs1zgy2dy1p19c68fnvqkxz40y627";
47 url = "https://files.pythonhosted.org/packages/2e/56/418fc10379b96e795ee39a15e69a730c222818af04c3821fa354eaa859ec/appenlight_client-0.6.26.tar.gz";
48 sha256 = "0s9xw3sb8s3pk73k78nnq4jil3q4mk6bczfa1fmgfx61kdxl2712";
49 49 };
50 50 meta = {
51 51 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -146,15 +146,15 b' self: super: {'
146 146 };
147 147 };
148 148 "bleach" = super.buildPythonPackage {
149 name = "bleach-2.1.4";
149 name = "bleach-3.0.2";
150 150 doCheck = false;
151 151 propagatedBuildInputs = [
152 152 self."six"
153 self."html5lib"
153 self."webencodings"
154 154 ];
155 155 src = fetchurl {
156 url = "https://files.pythonhosted.org/packages/7a/b7/fa555afb61462b030abaf9ed1479b8ea031510f58c7706b06113be9f82ea/bleach-2.1.4.tar.gz";
157 sha256 = "1n337zbdml6z6zia0b1qgv6xiddx3qlwmcg9vk2mk60jcxhmzs8f";
156 url = "https://files.pythonhosted.org/packages/ae/31/680afc7d44040004296a2d8f0584983c2f2386448cd9d0964197e6c1160e/bleach-3.0.2.tar.gz";
157 sha256 = "06474zg7f73hv8h1xw2wcsmvn2ygj73zxgxxqg8zcx8ap1srdls8";
158 158 };
159 159 meta = {
160 160 license = [ pkgs.lib.licenses.asl20 ];
@@ -230,15 +230,16 b' self: super: {'
230 230 };
231 231 };
232 232 "colander" = super.buildPythonPackage {
233 name = "colander-1.4";
233 name = "colander-1.5.1";
234 234 doCheck = false;
235 235 propagatedBuildInputs = [
236 236 self."translationstring"
237 237 self."iso8601"
238 self."enum34"
238 239 ];
239 240 src = fetchurl {
240 url = "https://files.pythonhosted.org/packages/cc/e2/c4e716ac4a426d8ad4dfe306c34f0018a22275d2420815784005bf771c84/colander-1.4.tar.gz";
241 sha256 = "0wjfphyr5aakv5hw73q287lbc15cbm0aardajv7i2mqf377rl3p2";
241 url = "https://files.pythonhosted.org/packages/ec/d1/fcca811a0a692c69d27e36b4d11a73acb98b4bab48323442642b6fd4386d/colander-1.5.1.tar.gz";
242 sha256 = "18ah4cwwxnpm6qxi6x9ipy51dal4spd343h44s5wd01cnhgrwsyq";
242 243 };
243 244 meta = {
244 245 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -317,7 +318,7 b' self: super: {'
317 318 };
318 319 };
319 320 "deform" = super.buildPythonPackage {
320 name = "deform-2.0.5";
321 name = "deform-2.0.7";
321 322 doCheck = false;
322 323 propagatedBuildInputs = [
323 324 self."chameleon"
@@ -328,11 +329,37 b' self: super: {'
328 329 self."zope.deprecation"
329 330 ];
330 331 src = fetchurl {
331 url = "https://files.pythonhosted.org/packages/0c/b1/ba711d5808c12538c8504f534d79c124ed834f19ac36f0ac5391c3bbd1c1/deform-2.0.5.tar.gz";
332 sha256 = "0ybg9zsnfac1kaxrjanmkjk0xaklf4d3piywxwr08l1cl1336kc7";
332 url = "https://files.pythonhosted.org/packages/cf/a1/bc234527b8f181de9acd80e796483c00007658d1e32b7de78f1c2e004d9a/deform-2.0.7.tar.gz";
333 sha256 = "0jnpi0zr2hjvbmiz6nm33yqv976dn9lf51vhlzqc0i75xcr9rwig";
334 };
335 meta = {
336 license = [ { fullName = "Repoze Public License"; } { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
337 };
338 };
339 "defusedxml" = super.buildPythonPackage {
340 name = "defusedxml-0.5.0";
341 doCheck = false;
342 src = fetchurl {
343 url = "https://files.pythonhosted.org/packages/74/ba/4ba4e89e21b5a2e267d80736ea674609a0a33cc4435a6d748ef04f1f9374/defusedxml-0.5.0.tar.gz";
344 sha256 = "1x54n0h8hl92vvwyymx883fbqpqjwn2mc8fb383bcg3z9zwz5mr4";
333 345 };
334 346 meta = {
335 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
347 license = [ pkgs.lib.licenses.psfl ];
348 };
349 };
350 "dm.xmlsec.binding" = super.buildPythonPackage {
351 name = "dm.xmlsec.binding-1.3.7";
352 doCheck = false;
353 propagatedBuildInputs = [
354 self."setuptools"
355 self."lxml"
356 ];
357 src = fetchurl {
358 url = "https://files.pythonhosted.org/packages/2c/9e/7651982d50252692991acdae614af821fd6c79bc8dcd598ad71d55be8fc7/dm.xmlsec.binding-1.3.7.tar.gz";
359 sha256 = "03jjjscx1pz2nc0dwiw9nia02qbz1c6f0f9zkyr8fmvys2n5jkb3";
360 };
361 meta = {
362 license = [ pkgs.lib.licenses.bsdOriginal ];
336 363 };
337 364 };
338 365 "docutils" = super.buildPythonPackage {
@@ -490,14 +517,14 b' self: super: {'
490 517 };
491 518 };
492 519 "gevent" = super.buildPythonPackage {
493 name = "gevent-1.3.6";
520 name = "gevent-1.3.7";
494 521 doCheck = false;
495 522 propagatedBuildInputs = [
496 523 self."greenlet"
497 524 ];
498 525 src = fetchurl {
499 url = "https://files.pythonhosted.org/packages/49/13/aa4bb3640b5167fe58875d3d7e65390cdb14f9682a41a741a566bb560842/gevent-1.3.6.tar.gz";
500 sha256 = "1ih4k73dqz2zb561hda99vbanja3m6cdch3mgxxn1mla3qwkqhbv";
526 url = "https://files.pythonhosted.org/packages/10/c1/9499b146bfa43aa4f1e0ed1bab1bd3209a4861d25650c11725036c731cf5/gevent-1.3.7.tar.gz";
527 sha256 = "0b0fr04qdk1p4sniv87fh8z5psac60x01pv054kpgi94520g81iz";
501 528 };
502 529 meta = {
503 530 license = [ pkgs.lib.licenses.mit ];
@@ -547,27 +574,12 b' self: super: {'
547 574 license = [ pkgs.lib.licenses.mit ];
548 575 };
549 576 };
550 "html5lib" = super.buildPythonPackage {
551 name = "html5lib-1.0.1";
552 doCheck = false;
553 propagatedBuildInputs = [
554 self."six"
555 self."webencodings"
556 ];
557 src = fetchurl {
558 url = "https://files.pythonhosted.org/packages/85/3e/cf449cf1b5004e87510b9368e7a5f1acd8831c2d6691edd3c62a0823f98f/html5lib-1.0.1.tar.gz";
559 sha256 = "0dipzfrycv6j1jw82v9b7d8lzggx3x8xngx6l4xrqkxwvg7hvjv6";
560 };
561 meta = {
562 license = [ pkgs.lib.licenses.mit ];
563 };
564 };
565 577 "hupper" = super.buildPythonPackage {
566 name = "hupper-1.3.1";
578 name = "hupper-1.4.2";
567 579 doCheck = false;
568 580 src = fetchurl {
569 url = "https://files.pythonhosted.org/packages/cf/4b/467b826a84c8594b81f414b5ab6794e981951dac90ca40abaf9ea1cb36b0/hupper-1.3.1.tar.gz";
570 sha256 = "03mf13n6i4dd60wlb9m99ddl4m3lmly70cjp7f82vdkibfl1v6l9";
581 url = "https://files.pythonhosted.org/packages/f1/75/1915dc7650b4867fa3049256e24ca8eddb5989998fcec788cf52b9812dfc/hupper-1.4.2.tar.gz";
582 sha256 = "16vb9fkiaakdpcp6pn56h3w0dwvm67bxq2k2dv4i382qhqwphdzb";
571 583 };
572 584 meta = {
573 585 license = [ pkgs.lib.licenses.mit ];
@@ -671,6 +683,20 b' self: super: {'
671 683 license = [ pkgs.lib.licenses.mit ];
672 684 };
673 685 };
686 "isodate" = super.buildPythonPackage {
687 name = "isodate-0.6.0";
688 doCheck = false;
689 propagatedBuildInputs = [
690 self."six"
691 ];
692 src = fetchurl {
693 url = "https://files.pythonhosted.org/packages/b1/80/fb8c13a4cd38eb5021dc3741a9e588e4d1de88d895c1910c6fc8a08b7a70/isodate-0.6.0.tar.gz";
694 sha256 = "1n7jkz68kk5pwni540pr5zdh99bf6ywydk1p5pdrqisrawylldif";
695 };
696 meta = {
697 license = [ pkgs.lib.licenses.bsdOriginal ];
698 };
699 };
674 700 "itsdangerous" = super.buildPythonPackage {
675 701 name = "itsdangerous-0.24";
676 702 doCheck = false;
@@ -756,11 +782,11 b' self: super: {'
756 782 };
757 783 };
758 784 "lxml" = super.buildPythonPackage {
759 name = "lxml-3.7.3";
785 name = "lxml-4.2.5";
760 786 doCheck = false;
761 787 src = fetchurl {
762 url = "https://files.pythonhosted.org/packages/39/e8/a8e0b1fa65dd021d48fe21464f71783655f39a41f218293c1c590d54eb82/lxml-3.7.3.tar.gz";
763 sha256 = "1iv1jgkqn1hdh1xyxri6g0y1s67h01jzjkw2nhkx3rqylmw2sl5a";
788 url = "https://files.pythonhosted.org/packages/4b/20/ddf5eb3bd5c57582d2b4652b4bbcf8da301bdfe5d805cb94e805f4d7464d/lxml-4.2.5.tar.gz";
789 sha256 = "0zw0y9hs0nflxhl9cs6ipwwh53szi3w2x06wl0k9cylyqac0cwin";
764 790 };
765 791 meta = {
766 792 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -990,11 +1016,11 b' self: super: {'
990 1016 };
991 1017 };
992 1018 "peppercorn" = super.buildPythonPackage {
993 name = "peppercorn-0.5";
1019 name = "peppercorn-0.6";
994 1020 doCheck = false;
995 1021 src = fetchurl {
996 url = "https://files.pythonhosted.org/packages/45/ec/a62ec317d1324a01567c5221b420742f094f05ee48097e5157d32be3755c/peppercorn-0.5.tar.gz";
997 sha256 = "0jvp144zn7yqk9kbpxc059167mlqk85i5lpvl1niw8gsa5fvl74j";
1022 url = "https://files.pythonhosted.org/packages/e4/77/93085de7108cdf1a0b092ff443872a8f9442c736d7ddebdf2f27627935f4/peppercorn-0.6.tar.gz";
1023 sha256 = "1ip4bfwcpwkq9hz2dai14k2cyabvwrnvcvrcmzxmqm04g8fnimwn";
998 1024 };
999 1025 meta = {
1000 1026 license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
@@ -1139,15 +1165,15 b' self: super: {'
1139 1165 };
1140 1166 };
1141 1167 "py-gfm" = super.buildPythonPackage {
1142 name = "py-gfm-0.1.3";
1168 name = "py-gfm-0.1.4";
1143 1169 doCheck = false;
1144 1170 propagatedBuildInputs = [
1145 1171 self."setuptools"
1146 1172 self."markdown"
1147 1173 ];
1148 1174 src = fetchurl {
1149 url = "https://files.pythonhosted.org/packages/12/e4/6b3d8678da04f97d7490d8264d8de51c2dc9fb91209ccee9c515c95e14c5/py-gfm-0.1.3.tar.gz";
1150 sha256 = "162ggwwj0af9g3s1k8m4bfwbvis03x9pinnf35mj79pb90rf81zi";
1175 url = "https://files.pythonhosted.org/packages/06/ee/004a03a1d92bb386dae44f6dd087db541bc5093374f1637d4d4ae5596cc2/py-gfm-0.1.4.tar.gz";
1176 sha256 = "0zip06g2isivx8fzgqd4n9qzsa22c25jas1rsb7m2rnjg72m0rzg";
1151 1177 };
1152 1178 meta = {
1153 1179 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1212,11 +1238,11 b' self: super: {'
1212 1238 };
1213 1239 };
1214 1240 "pygments" = super.buildPythonPackage {
1215 name = "pygments-2.2.0";
1241 name = "pygments-2.3.0";
1216 1242 doCheck = false;
1217 1243 src = fetchurl {
1218 url = "https://files.pythonhosted.org/packages/71/2a/2e4e77803a8bd6408a2903340ac498cb0a2181811af7c9ec92cb70b0308a/Pygments-2.2.0.tar.gz";
1219 sha256 = "1k78qdvir1yb1c634nkv6rbga8wv4289xarghmsbbvzhvr311bnv";
1244 url = "https://files.pythonhosted.org/packages/63/a2/91c31c4831853dedca2a08a0f94d788fc26a48f7281c99a303769ad2721b/Pygments-2.3.0.tar.gz";
1245 sha256 = "1z34ms51dh4jq4h3cizp7vd1dmsxcbvffkjsd2xxfav22nn6lrl2";
1220 1246 };
1221 1247 meta = {
1222 1248 license = [ pkgs.lib.licenses.bsdOriginal ];
@@ -1248,14 +1274,14 b' self: super: {'
1248 1274 };
1249 1275 };
1250 1276 "pyotp" = super.buildPythonPackage {
1251 name = "pyotp-2.2.6";
1277 name = "pyotp-2.2.7";
1252 1278 doCheck = false;
1253 1279 src = fetchurl {
1254 url = "https://files.pythonhosted.org/packages/67/69/131f5ad63de40c30f3be88d891e4a2ea1b69398528db99bc1e5c543422fa/pyotp-2.2.6.tar.gz";
1255 sha256 = "0sdxxvr3j4j0pk26v258jpxhgpbnpmyqhvzhl24hsd50j7fk14fx";
1280 url = "https://files.pythonhosted.org/packages/b1/ab/477cda97b6ca7baced5106471cb1ac1fe698d1b035983b9f8ee3422989eb/pyotp-2.2.7.tar.gz";
1281 sha256 = "00p69nw431f0s2ilg0hnd77p1l22m06p9rq4f8zfapmavnmzw3xy";
1256 1282 };
1257 1283 meta = {
1258 license = [ pkgs.lib.licenses.bsdOriginal ];
1284 license = [ pkgs.lib.licenses.mit ];
1259 1285 };
1260 1286 };
1261 1287 "pyparsing" = super.buildPythonPackage {
@@ -1479,14 +1505,14 b' self: super: {'
1479 1505 };
1480 1506 };
1481 1507 "python-dateutil" = super.buildPythonPackage {
1482 name = "python-dateutil-2.7.3";
1508 name = "python-dateutil-2.7.5";
1483 1509 doCheck = false;
1484 1510 propagatedBuildInputs = [
1485 1511 self."six"
1486 1512 ];
1487 1513 src = fetchurl {
1488 url = "https://files.pythonhosted.org/packages/a0/b0/a4e3241d2dee665fea11baec21389aec6886655cd4db7647ddf96c3fad15/python-dateutil-2.7.3.tar.gz";
1489 sha256 = "1f7h54lg0w2ckch7592xpjkh8dg87k2br256h0iw49zn6bg02w72";
1514 url = "https://files.pythonhosted.org/packages/0e/01/68747933e8d12263d41ce08119620d9a7e5eb72c876a3442257f74490da0/python-dateutil-2.7.5.tar.gz";
1515 sha256 = "00ngwcdw36w5b37b51mdwn3qxid9zdf3kpffv2q6n9kl05y2iyc8";
1490 1516 };
1491 1517 meta = {
1492 1518 license = [ pkgs.lib.licenses.bsdOriginal pkgs.lib.licenses.asl20 { fullName = "Dual License"; } ];
@@ -1543,6 +1569,22 b' self: super: {'
1543 1569 license = [ { fullName = "License :: OSI Approved :: MIT License"; } pkgs.lib.licenses.mit ];
1544 1570 };
1545 1571 };
1572 "python-saml" = super.buildPythonPackage {
1573 name = "python-saml-2.4.2";
1574 doCheck = false;
1575 propagatedBuildInputs = [
1576 self."dm.xmlsec.binding"
1577 self."isodate"
1578 self."defusedxml"
1579 ];
1580 src = fetchurl {
1581 url = "https://files.pythonhosted.org/packages/79/a8/a6611017e0883102fd5e2b73c9d90691b8134e38247c04ee1531d3dc647c/python-saml-2.4.2.tar.gz";
1582 sha256 = "0dls4hwvf13yg7x5yfjrghbywg8g38vn5vr0rsf70hli3ydbfm43";
1583 };
1584 meta = {
1585 license = [ pkgs.lib.licenses.mit ];
1586 };
1587 };
1546 1588 "pytz" = super.buildPythonPackage {
1547 1589 name = "pytz-2018.4";
1548 1590 doCheck = false;
@@ -1615,7 +1657,7 b' self: super: {'
1615 1657 };
1616 1658 };
1617 1659 "rhodecode-enterprise-ce" = super.buildPythonPackage {
1618 name = "rhodecode-enterprise-ce-4.14.1";
1660 name = "rhodecode-enterprise-ce-4.15.0";
1619 1661 buildInputs = [
1620 1662 self."pytest"
1621 1663 self."py"
@@ -1640,6 +1682,7 b' self: super: {'
1640 1682 self."attrs"
1641 1683 self."babel"
1642 1684 self."beaker"
1685 self."bleach"
1643 1686 self."celery"
1644 1687 self."chameleon"
1645 1688 self."channelstream"
@@ -1668,8 +1711,6 b' self: super: {'
1668 1711 self."markdown"
1669 1712 self."markupsafe"
1670 1713 self."msgpack-python"
1671 self."mysql-python"
1672 self."pymysql"
1673 1714 self."pyotp"
1674 1715 self."packaging"
1675 1716 self."paste"
@@ -1678,7 +1719,6 b' self: super: {'
1678 1719 self."pathlib2"
1679 1720 self."peppercorn"
1680 1721 self."psutil"
1681 self."psycopg2"
1682 1722 self."py-bcrypt"
1683 1723 self."pycrypto"
1684 1724 self."pycurl"
@@ -1692,11 +1732,11 b' self: super: {'
1692 1732 self."pyramid-mako"
1693 1733 self."pyramid"
1694 1734 self."pyramid-mailer"
1695 self."pysqlite"
1696 1735 self."python-dateutil"
1697 1736 self."python-ldap"
1698 1737 self."python-memcached"
1699 1738 self."python-pam"
1739 self."python-saml"
1700 1740 self."pytz"
1701 1741 self."tzlocal"
1702 1742 self."pyzmq"
@@ -1713,7 +1753,6 b' self: super: {'
1713 1753 self."supervisor"
1714 1754 self."tempita"
1715 1755 self."translationstring"
1716 self."trollius"
1717 1756 self."urllib3"
1718 1757 self."urlobject"
1719 1758 self."venusian"
@@ -1727,8 +1766,11 b' self: super: {'
1727 1766 self."zope.deprecation"
1728 1767 self."zope.event"
1729 1768 self."zope.interface"
1769 self."mysql-python"
1770 self."pymysql"
1771 self."pysqlite"
1772 self."psycopg2"
1730 1773 self."nbconvert"
1731 self."bleach"
1732 1774 self."nbformat"
1733 1775 self."jupyter-client"
1734 1776 self."alembic"
@@ -1822,11 +1864,11 b' self: super: {'
1822 1864 };
1823 1865 };
1824 1866 "setuptools" = super.buildPythonPackage {
1825 name = "setuptools-40.4.3";
1867 name = "setuptools-40.6.2";
1826 1868 doCheck = false;
1827 1869 src = fetchurl {
1828 url = "https://files.pythonhosted.org/packages/6e/9c/6a003320b00ef237f94aa74e4ad66c57a7618f6c79d67527136e2544b728/setuptools-40.4.3.zip";
1829 sha256 = "058v6zns4634n4al2nmmvp15j8nrgwn8wjrbdks47wk3vm05gg5c";
1870 url = "https://files.pythonhosted.org/packages/b0/d1/8acb42f391cba52e35b131e442e80deffbb8d0676b93261d761b1f0ef8fb/setuptools-40.6.2.zip";
1871 sha256 = "0r2c5hapirlzm34h7pl1lgkm6gk7bcrlrdj28qgsvaqg3f74vfw6";
1830 1872 };
1831 1873 meta = {
1832 1874 license = [ pkgs.lib.licenses.mit ];
@@ -2002,20 +2044,6 b' self: super: {'
2002 2044 license = [ { fullName = "BSD-like (http://repoze.org/license.html)"; } ];
2003 2045 };
2004 2046 };
2005 "trollius" = super.buildPythonPackage {
2006 name = "trollius-1.0.4";
2007 doCheck = false;
2008 propagatedBuildInputs = [
2009 self."futures"
2010 ];
2011 src = fetchurl {
2012 url = "https://files.pythonhosted.org/packages/aa/e6/4141db437f55e6ee7a3fb69663239e3fde7841a811b4bef293145ad6c836/trollius-1.0.4.tar.gz";
2013 sha256 = "0xny8y12x3wrflmyn6xi8a7n3m3ac80fgmgzphx5jbbaxkjcm148";
2014 };
2015 meta = {
2016 license = [ pkgs.lib.licenses.asl20 ];
2017 };
2018 };
2019 2047 "tzlocal" = super.buildPythonPackage {
2020 2048 name = "tzlocal-1.5.1";
2021 2049 doCheck = false;
@@ -32,6 +32,11 b' pkgs.stdenv.mkDerivation {'
32 32 # We need postgresql to be around
33 33 pkgs.postgresql
34 34
35 # we need the below for saml
36 pkgs.libxml2
37 pkgs.libxslt
38 pkgs.xmlsec
39
35 40 # Curl is needed for pycurl
36 41 pkgs.curl
37 42 ];
@@ -8,16 +8,17 b' atomicwrites==1.2.1'
8 8 attrs==18.2.0
9 9 babel==1.3
10 10 beaker==1.9.1
11 bleach==3.0.2
11 12 celery==4.1.1
12 13 chameleon==2.24
13 14 channelstream==0.5.2
14 15 click==6.6
15 colander==1.4.0
16 colander==1.5.1
16 17 # our custom configobj
17 18 https://code.rhodecode.com/upstream/configobj/archive/a11ff0a0bd4fbda9e3a91267e720f88329efb4a6.tar.gz?md5=9916c524ea11a6c418217af6b28d4b3c#egg=configobj==5.0.6
18 19 cssselect==1.0.3
19 20 decorator==4.1.2
20 deform==2.0.5
21 deform==2.0.7
21 22 docutils==0.14.0
22 23 dogpile.cache==0.6.7
23 24 dogpile.core==0.4.1
@@ -32,28 +33,25 b' itsdangerous==0.24'
32 33 jinja2==2.9.6
33 34 billiard==3.5.0.3
34 35 kombu==4.2.0
35 lxml==3.7.3
36 lxml==4.2.5
36 37 mako==1.0.7
37 38 markdown==2.6.11
38 39 markupsafe==1.0.0
39 40 msgpack-python==0.5.6
40 mysql-python==1.2.5
41 pymysql==0.8.1
42 pyotp==2.2.6
41 pyotp==2.2.7
43 42 packaging==15.2
44 43 paste==2.0.3
45 44 pastedeploy==1.5.2
46 45 pastescript==2.0.2
47 46 pathlib2==2.3.2
48 peppercorn==0.5
47 peppercorn==0.6
49 48 psutil==5.4.7
50 psycopg2==2.7.5
51 49 py-bcrypt==0.4
52 50 pycrypto==2.6.1
53 51 pycurl==7.43.0.2
54 52 pyflakes==0.8.1
55 53 pygments-markdown-lexer==0.1.0.dev39
56 pygments==2.2.0
54 pygments==2.3.0
57 55 pyparsing==1.5.7
58 56 pyramid-beaker==0.8
59 57 pyramid-debugtoolbar==4.4.0
@@ -61,15 +59,15 b' pyramid-jinja2==2.7'
61 59 pyramid-mako==1.0.2
62 60 pyramid==1.9.2
63 61 pyramid_mailer==0.15.1
64 pysqlite==2.8.3
65 62 python-dateutil
66 63 python-ldap==3.1.0
67 64 python-memcached==1.59
68 65 python-pam==1.8.4
66 python-saml
69 67 pytz==2018.4
70 68 tzlocal==1.5.1
71 69 pyzmq==14.6.0
72 py-gfm==0.1.3
70 py-gfm==0.1.4
73 71 redis==2.10.6
74 72 repoze.lru==0.7
75 73 requests==2.9.1
@@ -82,7 +80,6 b' subprocess32==3.5.2'
82 80 supervisor==3.3.4
83 81 tempita==0.5.2
84 82 translationstring==1.3
85 trollius==1.0.4
86 83 urllib3==1.21
87 84 urlobject==2.4.3
88 85 venusian==1.1.0
@@ -97,22 +94,26 b' zope.deprecation==4.3.0'
97 94 zope.event==4.3.0
98 95 zope.interface==4.5.0
99 96
97 # DB drivers
98 mysql-python==1.2.5
99 pymysql==0.8.1
100 pysqlite==2.8.3
101 psycopg2==2.7.5
100 102
101 103 # IPYTHON RENDERING
102 104 # entrypoints backport, pypi version doesn't support egg installs
103 105 https://code.rhodecode.com/upstream/entrypoints/archive/96e6d645684e1af3d7df5b5272f3fe85a546b233.tar.gz?md5=7db37771aea9ac9fefe093e5d6987313#egg=entrypoints==0.2.2.rhodecode-upstream1
104 106 nbconvert==5.3.1
105 bleach==2.1.4
106 107 nbformat==4.4.0
107 108 jupyter_client==5.0.0
108 109
109 110 ## cli tools
110 alembic==0.9.9
111 alembic==1.0.5
111 112 invoke==0.13.0
112 113 bumpversion==0.5.3
113 114
114 115 ## http servers
115 gevent==1.3.6
116 gevent==1.3.7
116 117 greenlet==0.4.15
117 118 gunicorn==19.9.0
118 119 waitress==1.1.0
@@ -126,7 +127,7 b' ipython==5.1.0'
126 127 https://code.rhodecode.com/rhodecode-tools-ce/archive/v1.0.1.tar.gz?md5=ffb5d6bcb855305b93cfe23ad42e500b#egg=rhodecode-tools==1.0.1
127 128
128 129 ## appenlight
129 appenlight-client==0.6.25
130 appenlight-client==0.6.26
130 131
131 132 ## test related requirements
132 133 -r requirements_test.txt
@@ -1,1 +1,1 b''
1 4.14.1 No newline at end of file
1 4.15.0 No newline at end of file
@@ -66,7 +66,7 b' class TestCreatePullRequestApi(object):'
66 66 expected_message = "Created new pull request `{title}`".format(
67 67 title=data['title'])
68 68 result = response.json
69 assert result['error'] == None
69 assert result['error'] is None
70 70 assert result['result']['msg'] == expected_message
71 71 pull_request_id = result['result']['pull_request_id']
72 72 pull_request = PullRequestModel().get(pull_request_id)
@@ -89,7 +89,7 b' class TestCreatePullRequestApi(object):'
89 89 expected_message = "Created new pull request `{title}`".format(
90 90 title=data['title'])
91 91 result = response.json
92 assert result['error'] == None
92 assert result['error'] is None
93 93 assert result['result']['msg'] == expected_message
94 94 pull_request_id = result['result']['pull_request_id']
95 95 pull_request = PullRequestModel().get(pull_request_id)
@@ -129,7 +129,7 b' class TestCreatePullRequestApi(object):'
129 129 expected_message = "Created new pull request `{title}`".format(
130 130 title=data['title'])
131 131 result = response.json
132 assert result['error'] == None
132 assert result['error'] is None
133 133 assert result['result']['msg'] == expected_message
134 134 pull_request_id = result['result']['pull_request_id']
135 135 pull_request = PullRequestModel().get(pull_request_id)
@@ -144,11 +144,15 b' class TestCreatePullRequestApi(object):'
144 144 entry['mandatory'] = rev.mandatory
145 145 actual_reviewers.append(entry)
146 146
147 # default reviewer will be added who is an owner of the repo
148 reviewers.append(
149 {'username': pull_request.author.username,
150 'reasons': [u'Default reviewer', u'Repository owner']},
151 )
147 owner_username = pull_request.target_repo.user.username
148 for spec_reviewer in reviewers[::]:
149 # default reviewer will be added who is an owner of the repo
150 # this get's overridden by a add owner to reviewers rule
151 if spec_reviewer['username'] == owner_username:
152 spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner']
153 # since owner is more important, we don't inherit mandatory flag
154 del spec_reviewer['mandatory']
155
152 156 assert sorted(actual_reviewers, key=lambda e: e['username']) \
153 157 == sorted(reviewers, key=lambda e: e['username'])
154 158
@@ -173,7 +177,7 b' class TestCreatePullRequestApi(object):'
173 177 expected_message = "Created new pull request `{title}`".format(
174 178 title=data['title'])
175 179 result = response.json
176 assert result['error'] == None
180 assert result['error'] is None
177 181 assert result['result']['msg'] == expected_message
178 182 pull_request_id = result['result']['pull_request_id']
179 183 pull_request = PullRequestModel().get(pull_request_id)
@@ -187,11 +191,14 b' class TestCreatePullRequestApi(object):'
187 191 if rev.mandatory:
188 192 entry['mandatory'] = rev.mandatory
189 193 actual_reviewers.append(entry)
190 # default reviewer will be added who is an owner of the repo
191 reviewers.append(
192 {'username': pull_request.author.user_id,
193 'reasons': [u'Default reviewer', u'Repository owner']},
194 )
194
195 owner_user_id = pull_request.target_repo.user.user_id
196 for spec_reviewer in reviewers[::]:
197 # default reviewer will be added who is an owner of the repo
198 # this get's overridden by a add owner to reviewers rule
199 if spec_reviewer['username'] == owner_user_id:
200 spec_reviewer['reasons'] = [u'Default reviewer', u'Repository owner']
201
195 202 assert sorted(actual_reviewers, key=lambda e: e['username']) \
196 203 == sorted(reviewers, key=lambda e: e['username'])
197 204
1 NO CONTENT: file renamed from rhodecode/apps/admin/interfaces.py to rhodecode/apps/_base/interfaces.py
@@ -24,7 +24,7 b' import collections'
24 24
25 25 from zope.interface import implementer
26 26
27 from rhodecode.apps.admin.interfaces import IAdminNavigationRegistry
27 from rhodecode.apps._base.interfaces import IAdminNavigationRegistry
28 28 from rhodecode.lib.utils2 import str2bool
29 29 from rhodecode.translation import _
30 30
@@ -117,10 +117,11 b' class NavigationRegistry(object):'
117 117 self._registered_entries[entry.key] = entry
118 118
119 119 def get_navlist(self, request):
120 navlist = [NavListEntry(i.key, i.get_localized_name(request),
121 i.generate_url(request), i.active_list)
122 for i in self._registered_entries.values()]
123 return navlist
120 nav_list = [
121 NavListEntry(i.key, i.get_localized_name(request),
122 i.generate_url(request), i.active_list)
123 for i in self._registered_entries.values()]
124 return nav_list
124 125
125 126
126 127 def navigation_registry(request, registry=None):
@@ -143,5 +144,5 b' def includeme(config):'
143 144 # Create admin navigation registry and add it to the pyramid registry.
144 145 settings = config.get_settings()
145 146 labs_active = str2bool(settings.get('labs_settings_active', False))
146 navigation_registry = NavigationRegistry(labs_active=labs_active)
147 config.registry.registerUtility(navigation_registry) No newline at end of file
147 navigation_registry_instance = NavigationRegistry(labs_active=labs_active)
148 config.registry.registerUtility(navigation_registry_instance)
1 NO CONTENT: file renamed from rhodecode/apps/admin/subscribers.py to rhodecode/apps/_base/subscribers.py
@@ -429,7 +429,7 b' def admin_routes(config):'
429 429
430 430
431 431 def includeme(config):
432 from rhodecode.apps.admin.navigation import includeme as nav_includeme
432 from rhodecode.apps._base.navigation import includeme as nav_includeme
433 433
434 434 # Create admin navigation registry and add it to the pyramid registry.
435 435 nav_includeme(config)
@@ -438,7 +438,5 b' def includeme(config):'
438 438 config.add_route(name='admin_home', pattern=ADMIN_PREFIX)
439 439 config.include(admin_routes, route_prefix=ADMIN_PREFIX)
440 440
441 config.include('.subscribers')
442
443 441 # Scan module for configuration decorators.
444 442 config.scan('.views', ignore='.tests')
@@ -89,7 +89,7 b' class TestAuthSettingsView(object):'
89 89 'timeout': 3600,
90 90 'tls_kind': 'PLAIN',
91 91 'tls_reqcert': 'NEVER',
92
92 'tls_cert_dir':'/etc/openldap/cacerts',
93 93 'dn_user': 'test_user',
94 94 'dn_pass': 'test_pass',
95 95 'base_dn': 'test_base_dn',
@@ -24,7 +24,7 b' from pyramid.httpexceptions import HTTPF'
24 24 from pyramid.view import view_config
25 25
26 26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps.admin.navigation import navigation_list
27 from rhodecode.apps._base.navigation import navigation_list
28 28 from rhodecode.lib import helpers as h
29 29 from rhodecode.lib.auth import (
30 30 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
@@ -24,7 +24,7 b' import logging'
24 24 from pyramid.view import view_config
25 25
26 26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps.admin.navigation import navigation_list
27 from rhodecode.apps._base.navigation import navigation_list
28 28 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
29 29 from rhodecode.lib.utils import read_opensource_licenses
30 30
@@ -25,7 +25,7 b' import signal'
25 25 from pyramid.view import view_config
26 26
27 27 from rhodecode.apps._base import BaseAppView
28 from rhodecode.apps.admin.navigation import navigation_list
28 from rhodecode.apps._base.navigation import navigation_list
29 29 from rhodecode.lib import system_info
30 30 from rhodecode.lib.auth import (
31 31 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
@@ -24,7 +24,7 b' from pyramid.view import view_config'
24 24 from pyramid.httpexceptions import HTTPFound
25 25
26 26 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps.admin.navigation import navigation_list
27 from rhodecode.apps._base.navigation import navigation_list
28 28 from rhodecode.lib.auth import (
29 29 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
30 30 from rhodecode.lib.utils2 import safe_int
@@ -33,7 +33,7 b' from pyramid.renderers import render'
33 33 from pyramid.response import Response
34 34
35 35 from rhodecode.apps._base import BaseAppView
36 from rhodecode.apps.admin.navigation import navigation_list
36 from rhodecode.apps._base.navigation import navigation_list
37 37 from rhodecode.apps.svn_support.config_keys import generate_config
38 38 from rhodecode.lib import helpers as h
39 39 from rhodecode.lib.auth import (
@@ -175,8 +175,7 b' class AdminSettingsView(BaseAppView):'
175 175
176 176 try:
177 177 if c.visual.allow_repo_location_change:
178 model.update_global_path_setting(
179 form_result['paths_root_path'])
178 model.update_global_path_setting(form_result['paths_root_path'])
180 179
181 180 model.update_global_ssl_setting(form_result['web_push_ssl'])
182 181 model.update_global_hook_settings(form_result)
@@ -25,7 +25,7 b' from pyramid.view import view_config'
25 25
26 26 import rhodecode
27 27 from rhodecode.apps._base import BaseAppView
28 from rhodecode.apps.admin.navigation import navigation_list
28 from rhodecode.apps._base.navigation import navigation_list
29 29 from rhodecode.lib import helpers as h
30 30 from rhodecode.lib.auth import (LoginRequired, HasPermissionAllDecorator)
31 31 from rhodecode.lib.utils2 import str2bool
@@ -96,6 +96,7 b' class AdminSystemInfoSettingsView(BaseAp'
96 96 # RhodeCode specific
97 97 (_('RhodeCode Version'), val('rhodecode_app')['text'], state('rhodecode_app')),
98 98 (_('Latest version'), version, update_state),
99 (_('RhodeCode Base URL'), val('rhodecode_config')['config'].get('app.base_url'), state('rhodecode_config')),
99 100 (_('RhodeCode Server IP'), val('server')['server_ip'], state('server')),
100 101 (_('RhodeCode Server ID'), val('server')['server_id'], state('server')),
101 102 (_('RhodeCode Configuration'), val('rhodecode_config')['path'], state('rhodecode_config')),
@@ -185,7 +185,7 b' class AdminUsersView(BaseAppView, DataGr'
185 185 def users_new(self):
186 186 _ = self.request.translate
187 187 c = self.load_default_context()
188 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
188 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid
189 189 self._set_personal_repo_group_template_vars(c)
190 190 return self._get_template_context(c)
191 191
@@ -198,7 +198,7 b' class AdminUsersView(BaseAppView, DataGr'
198 198 def users_create(self):
199 199 _ = self.request.translate
200 200 c = self.load_default_context()
201 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
201 c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid
202 202 user_model = UserModel()
203 203 user_form = UserForm(self.request.translate)()
204 204 try:
@@ -63,7 +63,7 b' def maybe_create_history_store(event):'
63 63 settings = event.app.registry.settings
64 64 history_dir = settings.get('channelstream.history.location', '')
65 65 if history_dir and not os.path.exists(history_dir):
66 os.makedirs(history_dir, 0750)
66 os.makedirs(history_dir, 0o750)
67 67
68 68
69 69 def includeme(config):
@@ -32,6 +32,7 b' from pyramid.view import view_config'
32 32
33 33 from rhodecode.apps._base import BaseAppView
34 34 from rhodecode.authentication.base import authenticate, HTTP_TYPE
35 from rhodecode.authentication.plugins import auth_rhodecode
35 36 from rhodecode.events import UserRegistered, trigger
36 37 from rhodecode.lib import helpers as h
37 38 from rhodecode.lib import audit_logger
@@ -55,7 +56,7 b' CaptchaData = collections.namedtuple('
55 56 'CaptchaData', 'active, private_key, public_key')
56 57
57 58
58 def _store_user_in_session(session, username, remember=False):
59 def store_user_in_session(session, username, remember=False):
59 60 user = User.get_by_username(username, case_insensitive=True)
60 61 auth_user = AuthUser(user.user_id)
61 62 auth_user.set_authenticated()
@@ -165,7 +166,7 b' class LoginView(BaseAppView):'
165 166 auth_info = authenticate(
166 167 '', '', self.request.environ, HTTP_TYPE, skip_missing=True)
167 168 if auth_info:
168 headers = _store_user_in_session(
169 headers = store_user_in_session(
169 170 self.session, auth_info.get('username'))
170 171 raise HTTPFound(c.came_from, headers=headers)
171 172 except UserCreationError as e:
@@ -186,7 +187,7 b' class LoginView(BaseAppView):'
186 187 self.session.invalidate()
187 188 form_result = login_form.to_python(self.request.POST)
188 189 # form checks for username/password, now we're authenticated
189 headers = _store_user_in_session(
190 headers = store_user_in_session(
190 191 self.session,
191 192 username=form_result['username'],
192 193 remember=form_result['remember'])
@@ -273,16 +274,26 b' class LoginView(BaseAppView):'
273 274 route_name='register', request_method='POST',
274 275 renderer='rhodecode:templates/register.mako')
275 276 def register_post(self):
277 from rhodecode.authentication.plugins import auth_rhodecode
278
276 279 self.load_default_context()
277 280 captcha = self._get_captcha_data()
278 281 auto_active = 'hg.register.auto_activate' in User.get_default_user()\
279 282 .AuthUser().permissions['global']
280 283
284 extern_name = auth_rhodecode.RhodeCodeAuthPlugin.uid
285 extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid
286
281 287 register_form = RegisterForm(self.request.translate)()
282 288 try:
283 289
284 290 form_result = register_form.to_python(self.request.POST)
285 291 form_result['active'] = auto_active
292 external_identity = self.request.POST.get('external_identity')
293
294 if external_identity:
295 extern_name = external_identity
296 extern_type = external_identity
286 297
287 298 if captcha.active:
288 299 captcha_status, captcha_message = self.validate_captcha(
@@ -295,11 +306,17 b' class LoginView(BaseAppView):'
295 306 raise formencode.Invalid(
296 307 _msg, _value, None, error_dict=error_dict)
297 308
298 new_user = UserModel().create_registration(form_result)
309 new_user = UserModel().create_registration(
310 form_result, extern_name=extern_name, extern_type=extern_type)
299 311
300 312 action_data = {'data': new_user.get_api_data(),
301 313 'user_agent': self.request.user_agent}
302 314
315
316
317 if external_identity:
318 action_data['external_identity'] = external_identity
319
303 320 audit_user = audit_logger.UserWrap(
304 321 username=new_user.username,
305 322 user_id=new_user.user_id,
@@ -351,15 +368,24 b' class LoginView(BaseAppView):'
351 368 # matching emails
352 369 msg = _('If such email exists, a password reset link was sent to it.')
353 370
371 def default_response():
372 log.debug('faking response on invalid password reset')
373 # make this take 2s, to prevent brute forcing.
374 time.sleep(2)
375 h.flash(msg, category='success')
376 return HTTPFound(self.request.route_path('reset_password'))
377
354 378 if self.request.POST:
355 379 if h.HasPermissionAny('hg.password_reset.disabled')():
356 380 _email = self.request.POST.get('email', '')
357 381 log.error('Failed attempt to reset password for `%s`.', _email)
358 h.flash(_('Password reset has been disabled.'),
359 category='error')
382 h.flash(_('Password reset has been disabled.'), category='error')
360 383 return HTTPFound(self.request.route_path('reset_password'))
361 384
362 385 password_reset_form = PasswordResetForm(self.request.translate)()
386 description = u'Generated token for password reset from {}'.format(
387 datetime.datetime.now().isoformat())
388
363 389 try:
364 390 form_result = password_reset_form.to_python(
365 391 self.request.POST)
@@ -379,10 +405,14 b' class LoginView(BaseAppView):'
379 405 # Generate reset URL and send mail.
380 406 user = User.get_by_email(user_email)
381 407
408 # only allow rhodecode based users to reset their password
409 # external auth shouldn't allow password reset
410 if user and user.extern_type != auth_rhodecode.RhodeCodeAuthPlugin.uid:
411 log.warning('User %s with external type `%s` tried a password reset. '
412 'This try was rejected', user, user.extern_type)
413 return default_response()
414
382 415 # generate password reset token that expires in 10 minutes
383 description = u'Generated token for password reset from {}'.format(
384 datetime.datetime.now().isoformat())
385
386 416 reset_token = UserModel().add_auth_token(
387 417 user=user, lifetime_minutes=10,
388 418 role=UserModel.auth_token_role.ROLE_PASSWORD_RESET,
@@ -395,15 +425,14 b' class LoginView(BaseAppView):'
395 425 _query={'key': reset_token.api_key})
396 426 UserModel().reset_password_link(
397 427 form_result, password_reset_url)
398 # Display success message and redirect.
399 h.flash(msg, category='success')
400 428
401 429 action_data = {'email': user_email,
402 430 'user_agent': self.request.user_agent}
403 431 audit_logger.store_web(
404 432 'user.password.reset_request', action_data=action_data,
405 433 user=self._rhodecode_user, commit=True)
406 return HTTPFound(self.request.route_path('reset_password'))
434
435 return default_response()
407 436
408 437 except formencode.Invalid as errors:
409 438 template_context.update({
@@ -418,11 +447,7 b' class LoginView(BaseAppView):'
418 447 # case of failed captcha
419 448 return self._get_template_context(c, **template_context)
420 449
421 log.debug('faking response on invalid password reset')
422 # make this take 2s, to prevent brute forcing.
423 time.sleep(2)
424 h.flash(msg, category='success')
425 return HTTPFound(self.request.route_path('reset_password'))
450 return default_response()
426 451
427 452 return self._get_template_context(c, **template_context)
428 453
@@ -51,12 +51,12 b' def get_default_reviewers_data('
51 51 """ Return json for default reviewers of a repository """
52 52
53 53 reasons = ['Default reviewer', 'Repository owner']
54 default = reviewer_as_json(
55 user=current_user, reasons=reasons, mandatory=False)
54 json_reviewers = [reviewer_as_json(
55 user=target_repo.user, reasons=reasons, mandatory=False, rules=None)]
56 56
57 57 return {
58 58 'api_ver': 'v1', # define version for later possible schema upgrade
59 'reviewers': [default],
59 'reviewers': json_reviewers,
60 60 'rules': {},
61 61 'rules_data': {},
62 62 }
@@ -211,7 +211,7 b' class RepoChangelogView(RepoAppView):'
211 211 base_commit = self.rhodecode_vcs_repo.get_commit(commit_id)
212 212
213 213 try:
214 collection = base_commit.get_file_history(
214 collection = base_commit.get_path_history(
215 215 f_path, limit=hist_limit, pre_load=pre_load)
216 216 if collection and partial_xhr:
217 217 # for ajax call we remove first one since we're looking
@@ -221,7 +221,7 b' class RepoChangelogView(RepoAppView):'
221 221 # this node is not present at tip!
222 222 try:
223 223 commit = self._get_commit_or_redirect(commit_id)
224 collection = commit.get_file_history(f_path)
224 collection = commit.get_path_history(f_path)
225 225 except RepositoryError as e:
226 226 h.flash(safe_str(e), category='warning')
227 227 redirect_url = h.route_path(
@@ -315,7 +315,7 b' class RepoChangelogView(RepoAppView):'
315 315 raise HTTPFound(
316 316 h.route_path('repo_changelog', repo_name=self.db_repo_name))
317 317
318 collection = base_commit.get_file_history(
318 collection = base_commit.get_path_history(
319 319 f_path, limit=hist_limit, pre_load=pre_load)
320 320 collection = list(reversed(collection))
321 321 else:
@@ -663,7 +663,7 b' class RepoFilesView(RepoAppView):'
663 663 pass
664 664
665 665 if is_file:
666 history = commit.get_file_history(f_path)
666 history = commit.get_path_history(f_path)
667 667 prev_commit_id = history[1].raw_id \
668 668 if len(history) > 1 else prev_commit_id
669 669 prev_url = h.route_path(
@@ -897,10 +897,10 b' class RepoFilesView(RepoAppView):'
897 897 if commits is None:
898 898 pre_load = ["author", "branch"]
899 899 try:
900 commits = tip.get_file_history(f_path, pre_load=pre_load)
900 commits = tip.get_path_history(f_path, pre_load=pre_load)
901 901 except (NodeDoesNotExistError, CommitError):
902 902 # this node is not present at tip!
903 commits = commit_obj.get_file_history(f_path, pre_load=pre_load)
903 commits = commit_obj.get_path_history(f_path, pre_load=pre_load)
904 904
905 905 history = []
906 906 commits_group = ([], _("Changesets"))
@@ -25,6 +25,7 b' from pyramid.view import view_config'
25 25 from rhodecode.apps._base import RepoAppView
26 26 from rhodecode.apps.repository.utils import get_default_reviewers_data
27 27 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
28 from rhodecode.model.db import Repository
28 29
29 30 log = logging.getLogger(__name__)
30 31
@@ -53,8 +54,8 b' class RepoReviewRulesView(RepoAppView):'
53 54 renderer='json_ext')
54 55 def repo_default_reviewers_data(self):
55 56 self.load_default_context()
57 target_repo_name = self.request.GET.get('target_repo', self.db_repo.repo_name)
58 target_repo = Repository.get_by_repo_name(target_repo_name)
56 59 review_data = get_default_reviewers_data(
57 self.db_repo.user, None, None, None, None)
60 self.db_repo.user, None, None, target_repo, None)
58 61 return review_data
59
60
@@ -35,15 +35,8 b' from .events import ModDavSvnConfigChang'
35 35 log = logging.getLogger(__name__)
36 36
37 37
38 def generate_mod_dav_svn_config(registry):
39 """
40 Generate the configuration file for use with subversion's mod_dav_svn
41 module. The configuration has to contain a <Location> block for each
42 available repository group because the mod_dav_svn module does not support
43 repositories organized in sub folders.
44 """
45 settings = registry.settings
46 use_ssl = str2bool(registry.settings['force_https'])
38 def write_mod_dav_svn_config(settings):
39 use_ssl = str2bool(settings['force_https'])
47 40
48 41 config = _render_mod_dav_svn_config(
49 42 use_ssl=use_ssl,
@@ -54,6 +47,17 b' def generate_mod_dav_svn_config(registry'
54 47 realm=get_rhodecode_realm(), template=settings[config_keys.template])
55 48 _write_mod_dav_svn_config(config, settings[config_keys.config_file_path])
56 49
50
51 def generate_mod_dav_svn_config(registry):
52 """
53 Generate the configuration file for use with subversion's mod_dav_svn
54 module. The configuration has to contain a <Location> block for each
55 available repository group because the mod_dav_svn module does not support
56 repositories organized in sub folders.
57 """
58 settings = registry.settings
59 write_mod_dav_svn_config(settings)
60
57 61 # Trigger an event on mod dav svn configuration change.
58 62 trigger(ModDavSvnConfigChange(), registry)
59 63
@@ -19,7 +19,7 b''
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 from rhodecode.apps.admin.navigation import NavigationRegistry
22 from rhodecode.apps._base.navigation import NavigationRegistry
23 23 from rhodecode.apps._base import ADMIN_PREFIX
24 24 from rhodecode.lib.utils2 import str2bool
25 25
@@ -18,11 +18,9 b''
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 import os
22 21 import logging
23 22 import importlib
24 23
25 from pkg_resources import iter_entry_points
26 24 from pyramid.authentication import SessionAuthenticationPolicy
27 25
28 26 from rhodecode.authentication.registry import AuthenticationPluginRegistry
@@ -31,48 +29,26 b' from rhodecode.authentication.routes imp'
31 29 from rhodecode.apps._base import ADMIN_PREFIX
32 30 from rhodecode.model.settings import SettingsModel
33 31
34
35 32 log = logging.getLogger(__name__)
36 33
37 # Plugin ID prefixes to distinct between normal and legacy plugins.
38 plugin_prefix = 'egg:'
39 34 legacy_plugin_prefix = 'py:'
40 35 plugin_default_auth_ttl = 30
41 36
42 37
43 # TODO: Currently this is only used to discover the authentication plugins.
44 # Later on this may be used in a generic way to look up and include all kinds
45 # of supported enterprise plugins. Therefore this has to be moved and
46 # refactored to a real 'plugin look up' machinery.
47 # TODO: When refactoring this think about splitting it up into distinct
48 # discover, load and include phases.
49 def _discover_plugins(config, entry_point='enterprise.plugins1'):
50 for ep in iter_entry_points(entry_point):
51 plugin_id = '{}{}#{}'.format(
52 plugin_prefix, ep.dist.project_name, ep.name)
53 log.debug('Plugin discovered: "%s"', plugin_id)
54 try:
55 module = ep.load()
56 plugin = module(plugin_id=plugin_id)
57 config.include(plugin.includeme)
58 except Exception as e:
59 log.exception(
60 'Exception while loading authentication plugin '
61 '"{}": {}'.format(plugin_id, e.message))
62
63
64 38 def _import_legacy_plugin(plugin_id):
65 39 module_name = plugin_id.split(legacy_plugin_prefix, 1)[-1]
66 40 module = importlib.import_module(module_name)
67 41 return module.plugin_factory(plugin_id=plugin_id)
68 42
69 43
70 def _discover_legacy_plugins(config, prefix=legacy_plugin_prefix):
44 def discover_legacy_plugins(config, prefix=legacy_plugin_prefix):
71 45 """
72 46 Function that imports the legacy plugins stored in the 'auth_plugins'
73 47 setting in database which are using the specified prefix. Normally 'py:' is
74 48 used for the legacy plugins.
75 49 """
50 log.debug('authentication: running legacy plugin discovery for prefix %s',
51 legacy_plugin_prefix)
76 52 try:
77 53 auth_plugins = SettingsModel().get_setting_by_name('auth_plugins')
78 54 enabled_plugins = auth_plugins.app_settings_value
@@ -121,12 +97,3 b' def includeme(config):'
121 97 request_method='POST',
122 98 route_name='auth_home',
123 99 context=AuthnRootResource)
124
125 for key in ['RC_CMD_SETUP_RC', 'RC_CMD_UPGRADE_DB', 'RC_CMD_SSH_WRAPPER']:
126 if os.environ.get(key):
127 # skip this heavy step below on certain CLI commands
128 return
129
130 # Auto discover authentication plugins and include their configuration.
131 _discover_plugins(config)
132 _discover_legacy_plugins(config)
@@ -38,7 +38,8 b' from rhodecode.authentication.schema imp'
38 38 from rhodecode.lib import rc_cache
39 39 from rhodecode.lib.auth import PasswordGenerator, _RhodeCodeCryptoBCrypt
40 40 from rhodecode.lib.utils2 import safe_int, safe_str
41 from rhodecode.lib.exceptions import LdapConnectionError
41 from rhodecode.lib.exceptions import LdapConnectionError, LdapUsernameError, \
42 LdapPasswordError
42 43 from rhodecode.model.db import User
43 44 from rhodecode.model.meta import Session
44 45 from rhodecode.model.settings import SettingsModel
@@ -52,6 +53,8 b' log = logging.getLogger(__name__)'
52 53 VCS_TYPE = 'vcs'
53 54 HTTP_TYPE = 'http'
54 55
56 external_auth_session_key = 'rhodecode.external_auth'
57
55 58
56 59 class hybrid_property(object):
57 60 """
@@ -93,6 +96,9 b' class LazyFormencode(object):'
93 96
94 97
95 98 class RhodeCodeAuthPluginBase(object):
99 # UID is used to register plugin to the registry
100 uid = None
101
96 102 # cache the authentication request for N amount of seconds. Some kind
97 103 # of authentication methods are very heavy and it's very efficient to cache
98 104 # the result of a call. If it's set to None (default) cache is off
@@ -113,7 +119,7 b' class RhodeCodeAuthPluginBase(object):'
113 119 "active":
114 120 'True|False defines active state of user internally for RhodeCode',
115 121 "active_from_extern":
116 "True|False\None, active state from the external auth, "
122 "True|False|None, active state from the external auth, "
117 123 "None means use definition from RhodeCode extern_type active value"
118 124
119 125 }
@@ -171,6 +177,20 b' class RhodeCodeAuthPluginBase(object):'
171 177 db_type = '{}.encrypted'.format(db_type)
172 178 return db_type
173 179
180 @classmethod
181 def docs(cls):
182 """
183 Defines documentation url which helps with plugin setup
184 """
185 return ''
186
187 @classmethod
188 def icon(cls):
189 """
190 Defines ICON in SVG format for authentication method
191 """
192 return ''
193
174 194 def is_enabled(self):
175 195 """
176 196 Returns true if this plugin is enabled. An enabled plugin can be
@@ -563,7 +583,8 b' class RhodeCodeExternalAuthPlugin(RhodeC'
563 583 class AuthLdapBase(object):
564 584
565 585 @classmethod
566 def _build_servers(cls, ldap_server_type, ldap_server, port):
586 def _build_servers(cls, ldap_server_type, ldap_server, port, use_resolver=True):
587
567 588 def host_resolver(host, port, full_resolve=True):
568 589 """
569 590 Main work for this function is to prevent ldap connection issues,
@@ -602,7 +623,7 b' class AuthLdapBase(object):'
602 623 return ', '.join(
603 624 ["{}://{}".format(
604 625 ldap_server_type,
605 host_resolver(host, port, full_resolve=full_resolve))
626 host_resolver(host, port, full_resolve=use_resolver and full_resolve))
606 627 for host in ldap_server])
607 628
608 629 @classmethod
@@ -616,6 +637,19 b' class AuthLdapBase(object):'
616 637 uid = chop_at(username, "@%s" % server_addr)
617 638 return uid
618 639
640 @classmethod
641 def validate_username(cls, username):
642 if "," in username:
643 raise LdapUsernameError(
644 "invalid character `,` in username: `{}`".format(username))
645
646 @classmethod
647 def validate_password(cls, username, password):
648 if not password:
649 msg = "Authenticating user %s with blank password not allowed"
650 log.warning(msg, username)
651 raise LdapPasswordError(msg)
652
619 653
620 654 def loadplugin(plugin_id):
621 655 """
@@ -40,7 +40,7 b' from rhodecode.model.db import User'
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 def plugin_factory(plugin_id, *args, **kwds):
43 def plugin_factory(plugin_id, *args, **kwargs):
44 44 """
45 45 Factory function that is called during plugin discovery.
46 46 It returns the plugin instance.
@@ -189,6 +189,7 b' class CrowdServer(object):'
189 189
190 190
191 191 class RhodeCodeAuthPlugin(RhodeCodeExternalAuthPlugin):
192 uid = 'crowd'
192 193 _settings_unsafe_keys = ['app_password']
193 194
194 195 def includeme(self, config):
@@ -215,9 +216,13 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
215 216 def get_display_name(self):
216 217 return _('CROWD')
217 218
219 @classmethod
220 def docs(cls):
221 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-crowd.html"
222
218 223 @hybrid_property
219 224 def name(self):
220 return "crowd"
225 return u"crowd"
221 226
222 227 def use_fake_password(self):
223 228 return True
@@ -283,3 +288,8 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
283 288 log.debug("Final crowd user object: \n%s", formatted_json(user_attrs))
284 289 log.info('user `%s` authenticated correctly', user_attrs['username'])
285 290 return user_attrs
291
292
293 def includeme(config):
294 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
295 plugin_factory(plugin_id).includeme(config)
@@ -34,7 +34,7 b' from rhodecode.model.db import User'
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 def plugin_factory(plugin_id, *args, **kwds):
37 def plugin_factory(plugin_id, *args, **kwargs):
38 38 """
39 39 Factory function that is called during plugin discovery.
40 40 It returns the plugin instance.
@@ -75,7 +75,7 b' class HeadersSettingsSchema(AuthnPluginS'
75 75
76 76
77 77 class RhodeCodeAuthPlugin(RhodeCodeExternalAuthPlugin):
78
78 uid = 'headers'
79 79 def includeme(self, config):
80 80 config.add_authn_plugin(self)
81 81 config.add_authn_resource(self.get_id(), HeadersAuthnResource(self))
@@ -102,7 +102,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
102 102
103 103 @hybrid_property
104 104 def name(self):
105 return 'headers'
105 return u"headers"
106 106
107 107 @property
108 108 def is_headers_auth(self):
@@ -223,3 +223,8 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
223 223
224 224 log.info('user `%s` authenticated correctly', user_attrs['username'])
225 225 return user_attrs
226
227
228 def includeme(config):
229 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
230 plugin_factory(plugin_id).includeme(config)
@@ -42,7 +42,7 b' from rhodecode.model.db import User'
42 42 log = logging.getLogger(__name__)
43 43
44 44
45 def plugin_factory(plugin_id, *args, **kwds):
45 def plugin_factory(plugin_id, *args, **kwargs):
46 46 """
47 47 Factory function that is called during plugin discovery.
48 48 It returns the plugin instance.
@@ -66,6 +66,7 b' class JasigCasSettingsSchema(AuthnPlugin'
66 66
67 67
68 68 class RhodeCodeAuthPlugin(RhodeCodeExternalAuthPlugin):
69 uid = 'jasig_cas'
69 70
70 71 def includeme(self, config):
71 72 config.add_authn_plugin(self)
@@ -93,7 +94,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
93 94
94 95 @hybrid_property
95 96 def name(self):
96 return "jasig-cas"
97 return u"jasig-cas"
97 98
98 99 @property
99 100 def is_headers_auth(self):
@@ -165,3 +166,8 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
165 166
166 167 log.info('user `%s` authenticated correctly', user_attrs['username'])
167 168 return user_attrs
169
170
171 def includeme(config):
172 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
173 plugin_factory(plugin_id).includeme(config)
@@ -53,7 +53,7 b' class LdapError(Exception):'
53 53 pass
54 54
55 55
56 def plugin_factory(plugin_id, *args, **kwds):
56 def plugin_factory(plugin_id, *args, **kwargs):
57 57 """
58 58 Factory function that is called during plugin discovery.
59 59 It returns the plugin instance.
@@ -66,6 +66,171 b' class LdapAuthnResource(AuthnPluginResou'
66 66 pass
67 67
68 68
69 class AuthLdap(AuthLdapBase):
70 default_tls_cert_dir = '/etc/openldap/cacerts'
71
72 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
73 tls_kind='PLAIN', tls_reqcert='DEMAND', tls_cert_file=None,
74 tls_cert_dir=None, ldap_version=3,
75 search_scope='SUBTREE', attr_login='uid',
76 ldap_filter='', timeout=None):
77 if ldap == Missing:
78 raise LdapImportError("Missing or incompatible ldap library")
79
80 self.debug = False
81 self.timeout = timeout or 60 * 5
82 self.ldap_version = ldap_version
83 self.ldap_server_type = 'ldap'
84
85 self.TLS_KIND = tls_kind
86
87 if self.TLS_KIND == 'LDAPS':
88 port = port or 689
89 self.ldap_server_type += 's'
90
91 OPT_X_TLS_DEMAND = 2
92 self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, OPT_X_TLS_DEMAND)
93 self.TLS_CERT_FILE = tls_cert_file or ''
94 self.TLS_CERT_DIR = tls_cert_dir or self.default_tls_cert_dir
95
96 # split server into list
97 self.SERVER_ADDRESSES = self._get_server_list(server)
98 self.LDAP_SERVER_PORT = port
99
100 # USE FOR READ ONLY BIND TO LDAP SERVER
101 self.attr_login = attr_login
102
103 self.LDAP_BIND_DN = safe_str(bind_dn)
104 self.LDAP_BIND_PASS = safe_str(bind_pass)
105
106 self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope)
107 self.BASE_DN = safe_str(base_dn)
108 self.LDAP_FILTER = safe_str(ldap_filter)
109
110 def _get_ldap_conn(self):
111
112 if self.debug:
113 ldap.set_option(ldap.OPT_DEBUG_LEVEL, 255)
114
115 if self.TLS_CERT_FILE and hasattr(ldap, 'OPT_X_TLS_CACERTFILE'):
116 ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, self.TLS_CERT_FILE)
117
118 elif hasattr(ldap, 'OPT_X_TLS_CACERTDIR'):
119 ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, self.TLS_CERT_DIR)
120
121 if self.TLS_KIND != 'PLAIN':
122 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
123
124 ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
125 ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
126
127 # init connection now
128 ldap_servers = self._build_servers(
129 self.ldap_server_type, self.SERVER_ADDRESSES, self.LDAP_SERVER_PORT)
130 log.debug('initializing LDAP connection to:%s', ldap_servers)
131 ldap_conn = ldap.initialize(ldap_servers)
132 ldap_conn.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)
133 ldap_conn.set_option(ldap.OPT_TIMEOUT, self.timeout)
134 ldap_conn.timeout = self.timeout
135
136 if self.ldap_version == 2:
137 ldap_conn.protocol = ldap.VERSION2
138 else:
139 ldap_conn.protocol = ldap.VERSION3
140
141 if self.TLS_KIND == 'START_TLS':
142 ldap_conn.start_tls_s()
143
144 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
145 log.debug('Trying simple_bind with password and given login DN: %r',
146 self.LDAP_BIND_DN)
147 ldap_conn.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
148
149 return ldap_conn
150
151 def fetch_attrs_from_simple_bind(self, server, dn, username, password):
152 try:
153 log.debug('Trying simple bind with %r', dn)
154 server.simple_bind_s(dn, safe_str(password))
155 user = server.search_ext_s(
156 dn, ldap.SCOPE_BASE, '(objectClass=*)', )[0]
157 _, attrs = user
158 return attrs
159
160 except ldap.INVALID_CREDENTIALS:
161 log.debug(
162 "LDAP rejected password for user '%s': %s, org_exc:",
163 username, dn, exc_info=True)
164
165 def authenticate_ldap(self, username, password):
166 """
167 Authenticate a user via LDAP and return his/her LDAP properties.
168
169 Raises AuthenticationError if the credentials are rejected, or
170 EnvironmentError if the LDAP server can't be reached.
171
172 :param username: username
173 :param password: password
174 """
175
176 uid = self.get_uid(username, self.SERVER_ADDRESSES)
177 user_attrs = {}
178 dn = ''
179
180 self.validate_password(username, password)
181 self.validate_username(username)
182
183 ldap_conn = None
184 try:
185 ldap_conn = self._get_ldap_conn()
186 filter_ = '(&%s(%s=%s))' % (
187 self.LDAP_FILTER, self.attr_login, username)
188 log.debug("Authenticating %r filter %s", self.BASE_DN, filter_)
189
190 lobjects = ldap_conn.search_ext_s(
191 self.BASE_DN, self.SEARCH_SCOPE, filter_)
192
193 if not lobjects:
194 log.debug("No matching LDAP objects for authentication "
195 "of UID:'%s' username:(%s)", uid, username)
196 raise ldap.NO_SUCH_OBJECT()
197
198 log.debug('Found matching ldap object, trying to authenticate')
199 for (dn, _attrs) in lobjects:
200 if dn is None:
201 continue
202
203 user_attrs = self.fetch_attrs_from_simple_bind(
204 ldap_conn, dn, username, password)
205 if user_attrs:
206 break
207 else:
208 raise LdapPasswordError(
209 'Failed to authenticate user `{}`'
210 'with given password'.format(username))
211
212 except ldap.NO_SUCH_OBJECT:
213 log.debug("LDAP says no such user '%s' (%s), org_exc:",
214 uid, username, exc_info=True)
215 raise LdapUsernameError('Unable to find user')
216 except ldap.SERVER_DOWN:
217 org_exc = traceback.format_exc()
218 raise LdapConnectionError(
219 "LDAP can't access authentication "
220 "server, org_exc:%s" % org_exc)
221 finally:
222 if ldap_conn:
223 log.debug('ldap: connection release')
224 try:
225 ldap_conn.unbind_s()
226 except Exception:
227 # for any reason this can raise exception we must catch it
228 # to not crush the server
229 pass
230
231 return dn, user_attrs
232
233
69 234 class LdapSettingsSchema(AuthnPluginSettingsSchemaBase):
70 235 tls_kind_choices = ['PLAIN', 'LDAPS', 'START_TLS']
71 236 tls_reqcert_choices = ['NEVER', 'ALLOW', 'TRY', 'DEMAND', 'HARD']
@@ -84,7 +249,7 b' class LdapSettingsSchema(AuthnPluginSett'
84 249 colander.Int(),
85 250 default=389,
86 251 description=_('Custom port that the LDAP server is listening on. '
87 'Default value is: 389'),
252 'Default value is: 389, use 689 for LDAPS(SSL)'),
88 253 preparer=strip_whitespace,
89 254 title=_('Port'),
90 255 validator=colander.Range(min=0, max=65536),
@@ -133,6 +298,22 b' class LdapSettingsSchema(AuthnPluginSett'
133 298 title=_('Certificate Checks'),
134 299 validator=colander.OneOf(tls_reqcert_choices),
135 300 widget='select')
301 tls_cert_file = colander.SchemaNode(
302 colander.String(),
303 default='',
304 description=_('This specifies the PEM-format file path containing '
305 'certificates for use in TLS connection.\n'
306 'If not specified `TLS Cert dir` will be used'),
307 title=_('TLS Cert file'),
308 missing='',
309 widget='string')
310 tls_cert_dir = colander.SchemaNode(
311 colander.String(),
312 default=AuthLdap.default_tls_cert_dir,
313 description=_('This specifies the path of a directory that contains individual '
314 'CA certificates in separate files.'),
315 title=_('TLS Cert dir'),
316 widget='string')
136 317 base_dn = colander.SchemaNode(
137 318 colander.String(),
138 319 default='',
@@ -169,6 +350,16 b' class LdapSettingsSchema(AuthnPluginSett'
169 350 title=_('Login Attribute'),
170 351 missing_msg=_('The LDAP Login attribute of the CN must be specified'),
171 352 widget='string')
353 attr_email = colander.SchemaNode(
354 colander.String(),
355 default='',
356 description=_('LDAP Attribute to map to email address (e.g., mail).\n'
357 'Emails are a crucial part of RhodeCode. \n'
358 'If possible add a valid email attribute to ldap users.'),
359 missing='',
360 preparer=strip_whitespace,
361 title=_('Email Attribute'),
362 widget='string')
172 363 attr_firstname = colander.SchemaNode(
173 364 colander.String(),
174 365 default='',
@@ -185,182 +376,10 b' class LdapSettingsSchema(AuthnPluginSett'
185 376 preparer=strip_whitespace,
186 377 title=_('Last Name Attribute'),
187 378 widget='string')
188 attr_email = colander.SchemaNode(
189 colander.String(),
190 default='',
191 description=_('LDAP Attribute to map to email address (e.g., mail).\n'
192 'Emails are a crucial part of RhodeCode. \n'
193 'If possible add a valid email attribute to ldap users.'),
194 missing='',
195 preparer=strip_whitespace,
196 title=_('Email Attribute'),
197 widget='string')
198
199
200 class AuthLdap(AuthLdapBase):
201
202 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
203 tls_kind='PLAIN', tls_reqcert='DEMAND', ldap_version=3,
204 search_scope='SUBTREE', attr_login='uid',
205 ldap_filter='', timeout=None):
206 if ldap == Missing:
207 raise LdapImportError("Missing or incompatible ldap library")
208
209 self.debug = False
210 self.timeout = timeout or 60 * 5
211 self.ldap_version = ldap_version
212 self.ldap_server_type = 'ldap'
213
214 self.TLS_KIND = tls_kind
215
216 if self.TLS_KIND == 'LDAPS':
217 port = port or 689
218 self.ldap_server_type += 's'
219
220 OPT_X_TLS_DEMAND = 2
221 self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert,
222 OPT_X_TLS_DEMAND)
223 self.LDAP_SERVER = server
224 # split server into list
225 self.SERVER_ADDRESSES = self._get_server_list(server)
226 self.LDAP_SERVER_PORT = port
227
228 # USE FOR READ ONLY BIND TO LDAP SERVER
229 self.attr_login = attr_login
230
231 self.LDAP_BIND_DN = safe_str(bind_dn)
232 self.LDAP_BIND_PASS = safe_str(bind_pass)
233
234 self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope)
235 self.BASE_DN = safe_str(base_dn)
236 self.LDAP_FILTER = safe_str(ldap_filter)
237
238 def _get_ldap_conn(self):
239
240 if self.debug:
241 ldap.set_option(ldap.OPT_DEBUG_LEVEL, 255)
242
243 if hasattr(ldap, 'OPT_X_TLS_CACERTDIR'):
244 ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
245 if self.TLS_KIND != 'PLAIN':
246 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
247
248 ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
249 ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
250
251 # init connection now
252 ldap_servers = self._build_servers(
253 self.ldap_server_type, self.SERVER_ADDRESSES, self.LDAP_SERVER_PORT)
254 log.debug('initializing LDAP connection to:%s', ldap_servers)
255 ldap_conn = ldap.initialize(ldap_servers)
256 ldap_conn.set_option(ldap.OPT_NETWORK_TIMEOUT, self.timeout)
257 ldap_conn.set_option(ldap.OPT_TIMEOUT, self.timeout)
258 ldap_conn.timeout = self.timeout
259
260 if self.ldap_version == 2:
261 ldap_conn.protocol = ldap.VERSION2
262 else:
263 ldap_conn.protocol = ldap.VERSION3
264
265 if self.TLS_KIND == 'START_TLS':
266 ldap_conn.start_tls_s()
267
268 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
269 log.debug('Trying simple_bind with password and given login DN: %s',
270 self.LDAP_BIND_DN)
271 ldap_conn.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
272
273 return ldap_conn
274
275 def fetch_attrs_from_simple_bind(self, server, dn, username, password):
276 try:
277 log.debug('Trying simple bind with %s', dn)
278 server.simple_bind_s(dn, safe_str(password))
279 user = server.search_ext_s(
280 dn, ldap.SCOPE_BASE, '(objectClass=*)', )[0]
281 _, attrs = user
282 return attrs
283
284 except ldap.INVALID_CREDENTIALS:
285 log.debug(
286 "LDAP rejected password for user '%s': %s, org_exc:",
287 username, dn, exc_info=True)
288
289 def authenticate_ldap(self, username, password):
290 """
291 Authenticate a user via LDAP and return his/her LDAP properties.
292
293 Raises AuthenticationError if the credentials are rejected, or
294 EnvironmentError if the LDAP server can't be reached.
295
296 :param username: username
297 :param password: password
298 """
299
300 uid = self.get_uid(username, self.SERVER_ADDRESSES)
301 user_attrs = {}
302 dn = ''
303
304 if not password:
305 msg = "Authenticating user %s with blank password not allowed"
306 log.warning(msg, username)
307 raise LdapPasswordError(msg)
308 if "," in username:
309 raise LdapUsernameError(
310 "invalid character `,` in username: `{}`".format(username))
311 ldap_conn = None
312 try:
313 ldap_conn = self._get_ldap_conn()
314 filter_ = '(&%s(%s=%s))' % (
315 self.LDAP_FILTER, self.attr_login, username)
316 log.debug(
317 "Authenticating %r filter %s", self.BASE_DN, filter_)
318 lobjects = ldap_conn.search_ext_s(
319 self.BASE_DN, self.SEARCH_SCOPE, filter_)
320
321 if not lobjects:
322 log.debug("No matching LDAP objects for authentication "
323 "of UID:'%s' username:(%s)", uid, username)
324 raise ldap.NO_SUCH_OBJECT()
325
326 log.debug('Found matching ldap object, trying to authenticate')
327 for (dn, _attrs) in lobjects:
328 if dn is None:
329 continue
330
331 user_attrs = self.fetch_attrs_from_simple_bind(
332 ldap_conn, dn, username, password)
333 if user_attrs:
334 break
335
336 else:
337 raise LdapPasswordError(
338 'Failed to authenticate user `{}`'
339 'with given password'.format(username))
340
341 except ldap.NO_SUCH_OBJECT:
342 log.debug("LDAP says no such user '%s' (%s), org_exc:",
343 uid, username, exc_info=True)
344 raise LdapUsernameError('Unable to find user')
345 except ldap.SERVER_DOWN:
346 org_exc = traceback.format_exc()
347 raise LdapConnectionError(
348 "LDAP can't access authentication "
349 "server, org_exc:%s" % org_exc)
350 finally:
351 if ldap_conn:
352 log.debug('ldap: connection release')
353 try:
354 ldap_conn.unbind_s()
355 except Exception:
356 # for any reason this can raise exception we must catch it
357 # to not crush the server
358 pass
359
360 return dn, user_attrs
361 379
362 380
363 381 class RhodeCodeAuthPlugin(RhodeCodeExternalAuthPlugin):
382 uid = 'ldap'
364 383 # used to define dynamic binding in the
365 384 DYNAMIC_BIND_VAR = '$login'
366 385 _settings_unsafe_keys = ['dn_pass']
@@ -389,9 +408,13 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
389 408 def get_display_name(self):
390 409 return _('LDAP')
391 410
411 @classmethod
412 def docs(cls):
413 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-ldap.html"
414
392 415 @hybrid_property
393 416 def name(self):
394 return "ldap"
417 return u"ldap"
395 418
396 419 def use_fake_password(self):
397 420 return True
@@ -448,6 +471,8 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
448 471 'bind_pass': settings.get('dn_pass'),
449 472 'tls_kind': settings.get('tls_kind'),
450 473 'tls_reqcert': settings.get('tls_reqcert'),
474 'tls_cert_file': settings.get('tls_cert_file'),
475 'tls_cert_dir': settings.get('tls_cert_dir'),
451 476 'search_scope': settings.get('search_scope'),
452 477 'attr_login': settings.get('attr_login'),
453 478 'ldap_version': 3,
@@ -477,12 +502,11 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
477 502 extern_type = getattr(userobj, 'extern_type', '')
478 503
479 504 groups = []
505
480 506 user_attrs = {
481 507 'username': username,
482 'firstname': safe_unicode(
483 get_ldap_attr('attr_firstname') or firstname),
484 'lastname': safe_unicode(
485 get_ldap_attr('attr_lastname') or lastname),
508 'firstname': safe_unicode(get_ldap_attr('attr_firstname') or firstname),
509 'lastname': safe_unicode(get_ldap_attr('attr_lastname') or lastname),
486 510 'groups': groups,
487 511 'user_group_sync': False,
488 512 'email': get_ldap_attr('attr_email') or email,
@@ -492,6 +516,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
492 516 'extern_name': user_dn,
493 517 'extern_type': extern_type,
494 518 }
519
495 520 log.debug('ldap user: %s', user_attrs)
496 521 log.info('user `%s` authenticated correctly', user_attrs['username'])
497 522
@@ -504,3 +529,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
504 529 log.exception("Other exception")
505 530 return None
506 531
532
533 def includeme(config):
534 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
535 plugin_factory(plugin_id).includeme(config)
@@ -40,7 +40,7 b' from rhodecode.lib.colander_utils import'
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 def plugin_factory(plugin_id, *args, **kwds):
43 def plugin_factory(plugin_id, *args, **kwargs):
44 44 """
45 45 Factory function that is called during plugin discovery.
46 46 It returns the plugin instance.
@@ -72,6 +72,7 b' class PamSettingsSchema(AuthnPluginSetti'
72 72
73 73
74 74 class RhodeCodeAuthPlugin(RhodeCodeExternalAuthPlugin):
75 uid = 'pam'
75 76 # PAM authentication can be slow. Repository operations involve a lot of
76 77 # auth calls. Little caching helps speedup push/pull operations significantly
77 78 AUTH_CACHE_TTL = 4
@@ -97,9 +98,13 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
97 98 def get_display_name(self):
98 99 return _('PAM')
99 100
101 @classmethod
102 def docs(cls):
103 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-pam.html"
104
100 105 @hybrid_property
101 106 def name(self):
102 return "pam"
107 return u"pam"
103 108
104 109 def get_settings_schema(self):
105 110 return PamSettingsSchema()
@@ -159,3 +164,8 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
159 164 log.debug("pamuser: %s", user_attrs)
160 165 log.info('user `%s` authenticated correctly', user_attrs['username'])
161 166 return user_attrs
167
168
169 def includeme(config):
170 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
171 plugin_factory(plugin_id).includeme(config)
@@ -34,7 +34,7 b' from rhodecode.model.db import User'
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 def plugin_factory(plugin_id, *args, **kwds):
37 def plugin_factory(plugin_id, *args, **kwargs):
38 38 plugin = RhodeCodeAuthPlugin(plugin_id)
39 39 return plugin
40 40
@@ -44,6 +44,7 b' class RhodecodeAuthnResource(AuthnPlugin'
44 44
45 45
46 46 class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
47 uid = 'rhodecode'
47 48
48 49 def includeme(self, config):
49 50 config.add_authn_plugin(self)
@@ -64,11 +65,15 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
64 65 context=RhodecodeAuthnResource)
65 66
66 67 def get_display_name(self):
67 return _('Rhodecode')
68 return _('RhodeCode Internal')
69
70 @classmethod
71 def docs(cls):
72 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth.html"
68 73
69 74 @hybrid_property
70 75 def name(self):
71 return "rhodecode"
76 return u"rhodecode"
72 77
73 78 def user_activation_state(self):
74 79 def_user_perms = User.get_default_user().AuthUser().permissions['global']
@@ -141,3 +146,8 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
141 146 'user `%s` failed to authenticate via %s, reason: account not '
142 147 'active.', username, self.name)
143 148 return None
149
150
151 def includeme(config):
152 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
153 plugin_factory(plugin_id).includeme(config)
@@ -34,7 +34,7 b' from rhodecode.model.db import User, Use'
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 def plugin_factory(plugin_id, *args, **kwds):
37 def plugin_factory(plugin_id, *args, **kwargs):
38 38 plugin = RhodeCodeAuthPlugin(plugin_id)
39 39 return plugin
40 40
@@ -47,6 +47,7 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
47 47 """
48 48 Enables usage of authentication tokens for vcs operations.
49 49 """
50 uid = 'token'
50 51
51 52 def includeme(self, config):
52 53 config.add_authn_plugin(self)
@@ -67,11 +68,15 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
67 68 context=RhodecodeAuthnResource)
68 69
69 70 def get_display_name(self):
70 return _('Rhodecode Token Auth')
71 return _('Rhodecode Token')
72
73 @classmethod
74 def docs(cls):
75 return "https://docs.rhodecode.com/RhodeCode-Enterprise/auth/auth-token.html"
71 76
72 77 @hybrid_property
73 78 def name(self):
74 return "authtoken"
79 return u"authtoken"
75 80
76 81 def user_activation_state(self):
77 82 def_user_perms = User.get_default_user().AuthUser().permissions['global']
@@ -145,3 +150,8 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP'
145 150 'user `%s` failed to authenticate via %s, reason: account not '
146 151 'active.', username, self.name)
147 152 return None
153
154
155 def includeme(config):
156 plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid)
157 plugin_factory(plugin_id).includeme(config)
@@ -19,6 +19,7 b''
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 import collections
22 23
23 24 from pyramid.exceptions import ConfigurationError
24 25
@@ -55,9 +56,9 b' class AuthnRootResource(AuthnResourceBas'
55 56 """
56 57
57 58 def __init__(self):
58 self._store = {}
59 self._store = collections.OrderedDict()
59 60 self._resource_name_map = {}
60 self.display_name = _('Global')
61 self.display_name = _('Authentication Plugins')
61 62
62 63 def __getitem__(self, key):
63 64 """
@@ -87,23 +88,27 b' class AuthnRootResource(AuthnResourceBas'
87 88 # TODO: Store this info in the resource element.
88 89 return self._resource_name_map[resource_name]
89 90
90 def get_sorted_list(self):
91 def get_sorted_list(self, sort_key=None):
91 92 """
92 93 Returns a sorted list of sub resources for displaying purposes.
93 94 """
94 def sort_key(resource):
95 def default_sort_key(resource):
95 96 return str.lower(safe_str(resource.display_name))
96 97
97 98 active = [item for item in self]
98 return sorted(active, key=sort_key)
99 return sorted(active, key=sort_key or default_sort_key)
99 100
100 def get_nav_list(self):
101 def get_nav_list(self, sort=True):
101 102 """
102 103 Returns a sorted list of resources for displaying the navigation.
103 104 """
104 list = self.get_sorted_list()
105 list.insert(0, self)
106 return list
105 if sort:
106 nav_list = self.get_sorted_list()
107 else:
108 nav_list = [item for item in self]
109
110 nav_list.insert(0, self)
111 return nav_list
107 112
108 113 def add_authn_resource(self, config, plugin_id, resource):
109 114 """
@@ -23,6 +23,7 b' import sys'
23 23 import logging
24 24 import collections
25 25 import tempfile
26 import time
26 27
27 28 from paste.gzipper import make_gzip_middleware
28 29 import pyramid.events
@@ -63,6 +64,14 b' def is_http_error(response):'
63 64 return response.status_code > 499
64 65
65 66
67 def should_load_all():
68 """
69 Returns if all application components should be loaded. In some cases it's
70 desired to skip apps loading for faster shell script execution
71 """
72 return True
73
74
66 75 def make_pyramid_app(global_config, **settings):
67 76 """
68 77 Constructs the WSGI application based on Pyramid.
@@ -78,8 +87,13 b' def make_pyramid_app(global_config, **se'
78 87
79 88 # Allows to use format style "{ENV_NAME}" placeholders in the configuration. It
80 89 # will be replaced by the value of the environment variable "NAME" in this case.
81 environ = {
82 'ENV_{}'.format(key): value for key, value in os.environ.items()}
90 start_time = time.time()
91
92 debug = asbool(global_config.get('debug'))
93 if debug:
94 enable_debug()
95
96 environ = {'ENV_{}'.format(key): value for key, value in os.environ.items()}
83 97
84 98 global_config = _substitute_values(global_config, environ)
85 99 settings = _substitute_values(settings, environ)
@@ -105,8 +119,10 b' def make_pyramid_app(global_config, **se'
105 119 config.configure_celery(global_config['__file__'])
106 120 # creating the app uses a connection - return it after we are done
107 121 meta.Session.remove()
122 total_time = time.time() - start_time
123 log.info('Pyramid app `%s` created and configured in %.2fs',
124 pyramid_app.func_name, total_time)
108 125
109 log.info('Pyramid app %s created and configured.', pyramid_app)
110 126 return pyramid_app
111 127
112 128
@@ -215,6 +231,7 b' def includeme_first(config):'
215 231
216 232
217 233 def includeme(config):
234 log.debug('Initializing main includeme from %s', os.path.basename(__file__))
218 235 settings = config.registry.settings
219 236 config.set_request_factory(Request)
220 237
@@ -229,41 +246,58 b' def includeme(config):'
229 246 if asbool(settings.get('appenlight', 'false')):
230 247 config.include('appenlight_client.ext.pyramid_tween')
231 248
249 load_all = should_load_all()
250
232 251 # Includes which are required. The application would fail without them.
233 252 config.include('pyramid_mako')
234 253 config.include('pyramid_beaker')
235 254 config.include('rhodecode.lib.rc_cache')
236 255
256 config.include('rhodecode.apps._base.navigation')
257 config.include('rhodecode.apps._base.subscribers')
258 config.include('rhodecode.tweens')
259
260 config.include('rhodecode.integrations')
237 261 config.include('rhodecode.authentication')
238 config.include('rhodecode.integrations')
262
263 if load_all:
264 from rhodecode.authentication import discover_legacy_plugins
265 # load CE authentication plugins
266 config.include('rhodecode.authentication.plugins.auth_crowd')
267 config.include('rhodecode.authentication.plugins.auth_headers')
268 config.include('rhodecode.authentication.plugins.auth_jasig_cas')
269 config.include('rhodecode.authentication.plugins.auth_ldap')
270 config.include('rhodecode.authentication.plugins.auth_pam')
271 config.include('rhodecode.authentication.plugins.auth_rhodecode')
272 config.include('rhodecode.authentication.plugins.auth_token')
273
274 # Auto discover authentication plugins and include their configuration.
275 discover_legacy_plugins(config)
239 276
240 277 # apps
241 278 config.include('rhodecode.apps._base')
242 config.include('rhodecode.apps.ops')
243 279
244 config.include('rhodecode.apps.admin')
245 config.include('rhodecode.apps.channelstream')
246 config.include('rhodecode.apps.login')
247 config.include('rhodecode.apps.home')
248 config.include('rhodecode.apps.journal')
249 config.include('rhodecode.apps.repository')
250 config.include('rhodecode.apps.repo_group')
251 config.include('rhodecode.apps.user_group')
252 config.include('rhodecode.apps.search')
253 config.include('rhodecode.apps.user_profile')
254 config.include('rhodecode.apps.user_group_profile')
255 config.include('rhodecode.apps.my_account')
256 config.include('rhodecode.apps.svn_support')
257 config.include('rhodecode.apps.ssh_support')
258 config.include('rhodecode.apps.gist')
280 if load_all:
281 config.include('rhodecode.apps.ops')
282 config.include('rhodecode.apps.admin')
283 config.include('rhodecode.apps.channelstream')
284 config.include('rhodecode.apps.login')
285 config.include('rhodecode.apps.home')
286 config.include('rhodecode.apps.journal')
287 config.include('rhodecode.apps.repository')
288 config.include('rhodecode.apps.repo_group')
289 config.include('rhodecode.apps.user_group')
290 config.include('rhodecode.apps.search')
291 config.include('rhodecode.apps.user_profile')
292 config.include('rhodecode.apps.user_group_profile')
293 config.include('rhodecode.apps.my_account')
294 config.include('rhodecode.apps.svn_support')
295 config.include('rhodecode.apps.ssh_support')
296 config.include('rhodecode.apps.gist')
297 config.include('rhodecode.apps.debug_style')
298 config.include('rhodecode.api')
259 299
260 config.include('rhodecode.apps.debug_style')
261 config.include('rhodecode.tweens')
262 config.include('rhodecode.api')
263
264 config.add_route(
265 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
266
300 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
267 301 config.add_translation_dirs('rhodecode:i18n/')
268 302 settings['default_locale_name'] = settings.get('lang', 'en')
269 303
@@ -403,6 +437,114 b' def sanitize_settings_and_apply_defaults'
403 437 return settings
404 438
405 439
440 def enable_debug():
441 """
442 Helper to enable debug on running instance
443 :return:
444 """
445 import tempfile
446 import textwrap
447 import logging.config
448
449 ini_template = textwrap.dedent("""
450 #####################################
451 ### DEBUG LOGGING CONFIGURATION ####
452 #####################################
453 [loggers]
454 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
455
456 [handlers]
457 keys = console, console_sql
458
459 [formatters]
460 keys = generic, color_formatter, color_formatter_sql
461
462 #############
463 ## LOGGERS ##
464 #############
465 [logger_root]
466 level = NOTSET
467 handlers = console
468
469 [logger_sqlalchemy]
470 level = INFO
471 handlers = console_sql
472 qualname = sqlalchemy.engine
473 propagate = 0
474
475 [logger_beaker]
476 level = DEBUG
477 handlers =
478 qualname = beaker.container
479 propagate = 1
480
481 [logger_rhodecode]
482 level = DEBUG
483 handlers =
484 qualname = rhodecode
485 propagate = 1
486
487 [logger_ssh_wrapper]
488 level = DEBUG
489 handlers =
490 qualname = ssh_wrapper
491 propagate = 1
492
493 [logger_celery]
494 level = DEBUG
495 handlers =
496 qualname = celery
497
498
499 ##############
500 ## HANDLERS ##
501 ##############
502
503 [handler_console]
504 class = StreamHandler
505 args = (sys.stderr, )
506 level = DEBUG
507 formatter = color_formatter
508
509 [handler_console_sql]
510 # "level = DEBUG" logs SQL queries and results.
511 # "level = INFO" logs SQL queries.
512 # "level = WARN" logs neither. (Recommended for production systems.)
513 class = StreamHandler
514 args = (sys.stderr, )
515 level = WARN
516 formatter = color_formatter_sql
517
518 ################
519 ## FORMATTERS ##
520 ################
521
522 [formatter_generic]
523 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
524 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
525 datefmt = %Y-%m-%d %H:%M:%S
526
527 [formatter_color_formatter]
528 class = rhodecode.lib.logging_formatter.ColorRequestTrackingFormatter
529 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
530 datefmt = %Y-%m-%d %H:%M:%S
531
532 [formatter_color_formatter_sql]
533 class = rhodecode.lib.logging_formatter.ColorFormatterSql
534 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
535 datefmt = %Y-%m-%d %H:%M:%S
536 """)
537
538 with tempfile.NamedTemporaryFile(prefix='rc_debug_logging_', suffix='.ini',
539 delete=False) as f:
540 log.info('Saved Temporary DEBUG config at %s', f.name)
541 f.write(ini_template)
542
543 logging.config.fileConfig(f.name)
544 log.debug('DEBUG MODE ON')
545 os.remove(f.name)
546
547
406 548 def _sanitize_appenlight_settings(settings):
407 549 _bool_setting(settings, 'appenlight', 'false')
408 550
@@ -447,7 +589,7 b' def _sanitize_cache_settings(settings):'
447 589
448 590 # ensure we have our dir created
449 591 if not os.path.isdir(default_cache_dir):
450 os.makedirs(default_cache_dir, mode=0755)
592 os.makedirs(default_cache_dir, mode=0o755)
451 593
452 594 # exception store cache
453 595 _string_setting(
@@ -578,5 +720,8 b' def _substitute_values(mapping, substitu'
578 720 raise ValueError(
579 721 'Failed to substitute env variable: {}. '
580 722 'Make sure you have specified this env variable without ENV_ prefix'.format(e))
723 except ValueError as e:
724 log.warning('Failed to substitute ENV variable: %s', e)
725 result = mapping
581 726
582 727 return result
@@ -27,6 +27,7 b' us in hooks::'
27 27 """
28 28 import re
29 29 import collections
30 import json
30 31
31 32
32 33 def get_hg_commits(repo, refs):
@@ -36,6 +37,31 b' def get_hg_commits(repo, refs):'
36 37
37 38 def get_git_commits(repo, refs):
38 39 commits = []
40
41 for data in refs:
42 # we should now extract commit data
43 old_rev = data['old_rev']
44 new_rev = data['new_rev']
45
46 if '00000000' in old_rev:
47 # new branch, we don't need to extract nothing
48 return commits
49
50 git_env = dict(data['git_env'])
51 cmd = [
52 'log',
53 '--pretty=format:{"commit_id": "%H", "author": "%aN <%aE>", "date": "%ad", "message": "%f"}',
54 '{}...{}'.format(old_rev, new_rev)
55 ]
56
57 stdout, stderr = repo.run_git_command(cmd, extra_env=git_env)
58 for line in stdout.splitlines():
59 try:
60 data = json.loads(line)
61 commits.append(data)
62 except Exception:
63 print('Failed to load data from GIT line')
64
39 65 return commits
40 66
41 67
@@ -51,13 +77,14 b' def run(*args, **kwargs):'
51 77
52 78 commits = []
53 79
54 for rev_data in kwargs['commit_ids']:
55 new_environ = dict((k, v) for k, v in rev_data['hg_env'])
56
57 80 if vcs_type == 'git':
81 for rev_data in kwargs['commit_ids']:
82 new_environ = dict((k, v) for k, v in rev_data['git_env'])
58 83 commits = get_git_commits(vcs_repo, kwargs['commit_ids'])
59 84
60 85 if vcs_type == 'hg':
86 for rev_data in kwargs['commit_ids']:
87 new_environ = dict((k, v) for k, v in rev_data['hg_env'])
61 88 commits = get_hg_commits(vcs_repo, kwargs['commit_ids'])
62 89
63 90 return commits
@@ -145,3 +145,41 b' def maybe_log_call(name, args, kwargs):'
145 145 if hasattr(rcextensions, 'calls'):
146 146 calls = rcextensions.calls
147 147 calls[name].append((args, kwargs))
148
149
150 def str2bool(_str):
151 """
152 returns True/False value from given string, it tries to translate the
153 string into boolean
154
155 :param _str: string value to translate into boolean
156 :rtype: boolean
157 :returns: boolean from given string
158 """
159 if _str is None:
160 return False
161 if _str in (True, False):
162 return _str
163 _str = str(_str).strip().lower()
164 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
165
166
167 def aslist(obj, sep=None, strip=True):
168 """
169 Returns given string separated by sep as list
170
171 :param obj:
172 :param sep:
173 :param strip:
174 """
175 if isinstance(obj, (basestring,)):
176 lst = obj.split(sep)
177 if strip:
178 lst = [v.strip() for v in lst]
179 return lst
180 elif isinstance(obj, (list, tuple)):
181 return obj
182 elif obj is None:
183 return []
184 else:
185 return [obj] No newline at end of file
@@ -43,7 +43,7 b' then you can retrieve the url by simply '
43 43 The redirection must be first implemented in our servers before
44 44 you can see it working.
45 45 """
46 # flake8: noqa
46 # pragma: no cover
47 47 from __future__ import unicode_literals
48 48
49 49 link_config = [
@@ -44,7 +44,7 b' def trigger(event, registry=None):'
44 44 integrations_event_handler(event)
45 45
46 46
47 from rhodecode.events.user import ( # noqa
47 from rhodecode.events.user import ( # pragma: no cover
48 48 UserPreCreate,
49 49 UserPostCreate,
50 50 UserPreUpdate,
@@ -52,7 +52,7 b' from rhodecode.events.user import ( # n'
52 52 UserPermissionsChange,
53 53 )
54 54
55 from rhodecode.events.repo import ( # noqa
55 from rhodecode.events.repo import ( # pragma: no cover
56 56 RepoEvent,
57 57 RepoPreCreateEvent, RepoCreateEvent,
58 58 RepoPreDeleteEvent, RepoDeleteEvent,
@@ -60,14 +60,14 b' from rhodecode.events.repo import ( # n'
60 60 RepoPrePullEvent, RepoPullEvent,
61 61 )
62 62
63 from rhodecode.events.repo_group import ( # noqa
63 from rhodecode.events.repo_group import ( # pragma: no cover
64 64 RepoGroupEvent,
65 65 RepoGroupCreateEvent,
66 66 RepoGroupUpdateEvent,
67 67 RepoGroupDeleteEvent,
68 68 )
69 69
70 from rhodecode.events.pullrequest import ( # noqa
70 from rhodecode.events.pullrequest import ( # pragma: no cover
71 71 PullRequestEvent,
72 72 PullRequestCreateEvent,
73 73 PullRequestUpdateEvent,
@@ -32,6 +32,6 b' class IntegrationTypeRegistry(collection'
32 32 if key in self:
33 33 log.debug(
34 34 'Overriding existing integration type %s (%s) with %s',
35 self[key], key, IntegrationType)
35 self[key].__class__, key, IntegrationType)
36 36
37 37 self[key] = IntegrationType
@@ -36,6 +36,26 b' from rhodecode.integrations.types.base i'
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 REPO_PUSH_TEMPLATE = Template('''
40 <b>${data['actor']['username']}</b> pushed to repo <a href="${data['repo']['url']}">${data['repo']['repo_name']}</a>:
41 <br>
42 <ul>
43 %for branch, branch_commits in branches_commits.items():
44 <li>
45 % if branch:
46 <a href="${branch_commits['branch']['url']}">branch: ${branch_commits['branch']['name']}</a>
47 % else:
48 to trunk
49 % endif
50 <ul>
51 % for commit in branch_commits['commits']:
52 <li><a href="${commit['url']}">${commit['short_id']}</a> - ${commit['message_html']}</li>
53 % endfor
54 </ul>
55 </li>
56 %endfor
57 ''')
58
39 59
40 60 class HipchatSettingsSchema(colander.Schema):
41 61 color_choices = [
@@ -76,27 +96,6 b' class HipchatSettingsSchema(colander.Sch'
76 96 )
77 97
78 98
79 repo_push_template = Template('''
80 <b>${data['actor']['username']}</b> pushed to repo <a href="${data['repo']['url']}">${data['repo']['repo_name']}</a>:
81 <br>
82 <ul>
83 %for branch, branch_commits in branches_commits.items():
84 <li>
85 % if branch:
86 <a href="${branch_commits['branch']['url']}">branch: ${branch_commits['branch']['name']}</a>
87 % else:
88 to trunk
89 % endif
90 <ul>
91 % for commit in branch_commits['commits']:
92 <li><a href="${commit['url']}">${commit['short_id']}</a> - ${commit['message_html']}</li>
93 % endfor
94 </ul>
95 </li>
96 %endfor
97 ''')
98
99
100 99 class HipchatIntegrationType(IntegrationTypeBase, CommitParsingDataHandler):
101 100 key = 'hipchat'
102 101 display_name = _('Hipchat')
@@ -226,7 +225,7 b' class HipchatIntegrationType(Integration'
226 225 data['push']['branches'], data['push']['commits'])
227 226
228 227 result = render_with_traceback(
229 repo_push_template,
228 REPO_PUSH_TEMPLATE,
230 229 data=data,
231 230 branches_commits=branches_commits,
232 231 )
@@ -41,6 +41,30 b' from rhodecode.integrations.types.base i'
41 41 log = logging.getLogger(__name__)
42 42
43 43
44 def html_to_slack_links(message):
45 return re.compile(r'<a .*?href=["\'](.+?)".*?>(.+?)</a>').sub(
46 r'<\1|\2>', message)
47
48
49 REPO_PUSH_TEMPLATE = Template('''
50 <%
51 def branch_text(branch):
52 if branch:
53 return 'on branch: <{}|{}>'.format(branch_commits['branch']['url'], branch_commits['branch']['name'])
54 else:
55 ## case for SVN no branch push...
56 return 'to trunk'
57 %> \
58
59 % for branch, branch_commits in branches_commits.items():
60 ${len(branch_commits['commits'])} ${'commit' if len(branch_commits['commits']) == 1 else 'commits'} ${branch_text(branch)}
61 % for commit in branch_commits['commits']:
62 `<${commit['url']}|${commit['short_id']}>` - ${commit['message_html']|html_to_slack_links}
63 % endfor
64 % endfor
65 ''')
66
67
44 68 class SlackSettingsSchema(colander.Schema):
45 69 service = colander.SchemaNode(
46 70 colander.String(),
@@ -258,7 +282,6 b' class SlackIntegrationType(IntegrationTy'
258 282 return title, text
259 283
260 284 def format_repo_push_event(self, data):
261
262 285 branches_commits = self.aggregate_branch_data(
263 286 data['push']['branches'], data['push']['commits'])
264 287
@@ -267,25 +290,8 b' class SlackIntegrationType(IntegrationTy'
267 290 ''')
268 291 title = render_with_traceback(template, data=data)
269 292
270 repo_push_template = Template(textwrap.dedent(r'''
271 <%
272 def branch_text(branch):
273 if branch:
274 return 'on branch: <{}|{}>'.format(branch_commits['branch']['url'], branch_commits['branch']['name'])
275 else:
276 ## case for SVN no branch push...
277 return 'to trunk'
278 %> \
279 % for branch, branch_commits in branches_commits.items():
280 ${len(branch_commits['commits'])} ${'commit' if len(branch_commits['commits']) == 1 else 'commits'} ${branch_text(branch)}
281 % for commit in branch_commits['commits']:
282 `<${commit['url']}|${commit['short_id']}>` - ${commit['message_html']|html_to_slack_links}
283 % endfor
284 % endfor
285 '''))
286
287 293 text = render_with_traceback(
288 repo_push_template,
294 REPO_PUSH_TEMPLATE,
289 295 data=data,
290 296 branches_commits=branches_commits,
291 297 html_to_slack_links=html_to_slack_links,
@@ -308,11 +314,6 b' class SlackIntegrationType(IntegrationTy'
308 314 return title, text
309 315
310 316
311 def html_to_slack_links(message):
312 return re.compile(r'<a .*?href=["\'](.+?)".*?>(.+?)</a>').sub(
313 r'<\1|\2>', message)
314
315
316 317 @async_task(ignore_result=True, base=RequestContextTask)
317 318 def post_text_to_slack(settings, title, text, fields=None, overrides=None):
318 319 log.debug('sending %s (%s) to slack %s', title, text, settings['service'])
@@ -25,9 +25,9 b' import webhelpers.paginate'
25 25
26 26 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPNotFound
27 27
28 from rhodecode.integrations import integration_type_registry
28 29 from rhodecode.apps._base import BaseAppView
29 from rhodecode.integrations import integration_type_registry
30 from rhodecode.apps.admin.navigation import navigation_list
30 from rhodecode.apps._base.navigation import navigation_list
31 31 from rhodecode.lib.auth import (
32 32 LoginRequired, CSRFRequired, HasPermissionAnyDecorator,
33 33 HasRepoPermissionAnyDecorator, HasRepoGroupPermissionAnyDecorator)
@@ -60,6 +60,7 b' markdown_tags = ['
60 60 "table", "thead", "tbody", "tfoot", "tr", "th", "td",
61 61 "img",
62 62 "a",
63 "input",
63 64 ]
64 65
65 66 markdown_attrs = {
@@ -68,7 +69,8 b' markdown_attrs = {'
68 69 "a": ["href", "alt", "title", "name"],
69 70 "abbr": ["title"],
70 71 "acronym": ["title"],
71 "pre": ["lang"]
72 "pre": ["lang"],
73 "input": ["type", "disabled"]
72 74 }
73 75
74 76 standard_styles = [
@@ -33,7 +33,7 b' import importlib'
33 33 from celery import Celery
34 34 from celery import signals
35 35 from celery import Task
36 from celery import exceptions # noqa
36 from celery import exceptions # pragma: no cover
37 37 from kombu.serialization import register
38 38 from pyramid.threadlocal import get_current_request
39 39
@@ -40,12 +40,12 b' from sqlalchemy import ('
40 40 Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
41 41 Text, Float, PickleType)
42 42 from sqlalchemy.sql.expression import true, false
43 from sqlalchemy.sql.functions import coalesce, count # noqa
43 from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
44 44 from sqlalchemy.orm import (
45 45 relationship, joinedload, class_mapper, validates, aliased)
46 46 from sqlalchemy.ext.declarative import declared_attr
47 47 from sqlalchemy.ext.hybrid import hybrid_property
48 from sqlalchemy.exc import IntegrityError # noqa
48 from sqlalchemy.exc import IntegrityError # pragma: no cover
49 49 from sqlalchemy.dialects.mysql import LONGTEXT
50 50 from beaker.cache import cache_region
51 51 from zope.cachedescriptors.property import Lazy as LazyProperty
@@ -40,12 +40,12 b' from sqlalchemy import ('
40 40 Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
41 41 Text, Float, PickleType)
42 42 from sqlalchemy.sql.expression import true, false
43 from sqlalchemy.sql.functions import coalesce, count # noqa
43 from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
44 44 from sqlalchemy.orm import (
45 45 relationship, joinedload, class_mapper, validates, aliased)
46 46 from sqlalchemy.ext.declarative import declared_attr
47 47 from sqlalchemy.ext.hybrid import hybrid_property
48 from sqlalchemy.exc import IntegrityError # noqa
48 from sqlalchemy.exc import IntegrityError # pragma: no cover
49 49 from sqlalchemy.dialects.mysql import LONGTEXT
50 50 from beaker.cache import cache_region
51 51 from zope.cachedescriptors.property import Lazy as LazyProperty
@@ -41,7 +41,7 b' from sqlalchemy.ext.hybrid import hybrid'
41 41 from sqlalchemy.orm import (
42 42 relationship, joinedload, class_mapper, validates, aliased)
43 43 from sqlalchemy.sql.expression import true
44 from sqlalchemy.sql.functions import coalesce, count # noqa
44 from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
45 45 from beaker.cache import cache_region
46 46 from zope.cachedescriptors.property import Lazy as LazyProperty
47 47
@@ -95,7 +95,7 b' class diff_match_patch:'
95 95 Array of changes.
96 96 """
97 97 # Set a deadline by which time the diff must be complete.
98 if deadline == None:
98 if deadline is None:
99 99 # Unlike in most languages, Python counts time in seconds.
100 100 if self.Diff_Timeout <= 0:
101 101 deadline = sys.maxint
@@ -103,7 +103,7 b' class diff_match_patch:'
103 103 deadline = time.time() + self.Diff_Timeout
104 104
105 105 # Check for null inputs.
106 if text1 == None or text2 == None:
106 if text1 is None or text2 is None:
107 107 raise ValueError("Null inputs. (diff_main)")
108 108
109 109 # Check for equality (speedup).
@@ -1227,7 +1227,7 b' class diff_match_patch:'
1227 1227 Best match index or -1.
1228 1228 """
1229 1229 # Check for null inputs.
1230 if text == None or pattern == None:
1230 if text is None or pattern is None:
1231 1231 raise ValueError("Null inputs. (match_main)")
1232 1232
1233 1233 loc = max(0, min(loc, len(text)))
@@ -1018,7 +1018,7 b' def style_metatag(tag_type, value):'
1018 1018 return html_value
1019 1019
1020 1020
1021 def bool2icon(value):
1021 def bool2icon(value, show_at_false=True):
1022 1022 """
1023 1023 Returns boolean value of a given value, represented as html element with
1024 1024 classes that will represent icons
@@ -1029,8 +1029,9 b' def bool2icon(value):'
1029 1029 if value: # does bool conversion
1030 1030 return HTML.tag('i', class_="icon-true")
1031 1031 else: # not true as bool
1032 return HTML.tag('i', class_="icon-false")
1033
1032 if show_at_false:
1033 return HTML.tag('i', class_="icon-false")
1034 return HTML.tag('i')
1034 1035
1035 1036 #==============================================================================
1036 1037 # PERMS
@@ -264,7 +264,7 b' class WhooshResultWrapper(object):'
264 264 # inside hit object, and we don't need all
265 265 res = dict(hit)
266 266
267 f_path = '' # noqa
267 f_path = '' # pragma: no cover
268 268 if self.search_type in ['content', 'path']:
269 269 f_path = res['path'][len(res['repository']):]
270 270 f_path = f_path.lstrip(os.sep)
@@ -126,7 +126,8 b' class ColorFormatter(ExceptionAwareForma'
126 126 def _inject_req_id(record):
127 127 from pyramid.threadlocal import get_current_request
128 128 req = get_current_request()
129 req_id = 'req_id:%-36s ' % (getattr(req, 'req_id', None))
129 dummy = '00000000-0000-0000-0000-000000000000'
130 req_id = 'req_id:%-36s' % (getattr(req, 'req_id', dummy))
130 131 record.req_id = req_id
131 132
132 133
@@ -22,36 +22,7 b' import re'
22 22
23 23 import markdown
24 24
25 from mdx_gfm import GithubFlavoredMarkdownExtension # noqa
26
27
28 class FlavoredCheckboxExtension(markdown.Extension):
29
30 def extendMarkdown(self, md, md_globals):
31 md.preprocessors.add('checklist',
32 FlavoredCheckboxPreprocessor(md), '<reference')
33 md.postprocessors.add('checklist',
34 FlavoredCheckboxPostprocessor(md), '>unescape')
35
36
37 class FlavoredCheckboxPreprocessor(markdown.preprocessors.Preprocessor):
38 """
39 Replaces occurrences of [ ] or [x] to checkbox input
40 """
41
42 pattern = re.compile(r'^([*-]) \[([ x])\]')
43
44 def run(self, lines):
45 return [self._transform_line(line) for line in lines]
46
47 def _transform_line(self, line):
48 return self.pattern.sub(self._replacer, line)
49
50 def _replacer(self, match):
51 list_prefix, state = match.groups()
52 checked = '' if state == ' ' else ' checked="checked"'
53 return '%s <input type="checkbox" disabled="disabled"%s>' % (list_prefix,
54 checked)
25 from mdx_gfm import GithubFlavoredMarkdownExtension # pragma: no cover
55 26
56 27
57 28 class FlavoredCheckboxPostprocessor(markdown.postprocessors.Postprocessor):
@@ -40,8 +40,7 b' from docutils.writers import html4css1'
40 40 import markdown
41 41
42 42 from rhodecode.lib.markdown_ext import GithubFlavoredMarkdownExtension
43 from rhodecode.lib.utils2 import (
44 safe_str, safe_unicode, md5_safe, MENTIONS_REGEX)
43 from rhodecode.lib.utils2 import (safe_unicode, md5_safe, MENTIONS_REGEX)
45 44
46 45 log = logging.getLogger(__name__)
47 46
@@ -172,6 +171,32 b' def relative_path(path, request_path, is'
172 171 return u'/' + final_path
173 172
174 173
174 _cached_markdown_renderer = None
175
176
177 def get_markdown_renderer(extensions, output_format):
178 global _cached_markdown_renderer
179
180 if _cached_markdown_renderer is None:
181 _cached_markdown_renderer = markdown.Markdown(
182 extensions=extensions,
183 enable_attributes=False, output_format=output_format)
184 return _cached_markdown_renderer
185
186
187 _cached_markdown_renderer_flavored = None
188
189
190 def get_markdown_renderer_flavored(extensions, output_format):
191 global _cached_markdown_renderer_flavored
192
193 if _cached_markdown_renderer_flavored is None:
194 _cached_markdown_renderer_flavored = markdown.Markdown(
195 extensions=extensions + [GithubFlavoredMarkdownExtension()],
196 enable_attributes=False, output_format=output_format)
197 return _cached_markdown_renderer_flavored
198
199
175 200 class MarkupRenderer(object):
176 201 RESTRUCTUREDTEXT_DISALLOWED_DIRECTIVES = ['include', 'meta', 'raw']
177 202
@@ -183,14 +208,10 b' class MarkupRenderer(object):'
183 208 URL_PAT = re.compile(r'(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'
184 209 r'|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)')
185 210
186 extensions = ['codehilite', 'extra', 'def_list', 'sane_lists']
211 extensions = ['markdown.extensions.codehilite', 'markdown.extensions.extra',
212 'markdown.extensions.def_list', 'markdown.extensions.sane_lists']
213
187 214 output_format = 'html4'
188 markdown_renderer = markdown.Markdown(
189 extensions, enable_attributes=False, output_format=output_format)
190
191 markdown_renderer_flavored = markdown.Markdown(
192 extensions + [GithubFlavoredMarkdownExtension()],
193 enable_attributes=False, output_format=output_format)
194 215
195 216 # extension together with weights. Lower is first means we control how
196 217 # extensions are attached to readme names with those.
@@ -346,9 +367,11 b' class MarkupRenderer(object):'
346 367 """
347 368
348 369 if flavored:
349 markdown_renderer = cls.markdown_renderer_flavored
370 markdown_renderer = get_markdown_renderer_flavored(
371 cls.extensions, cls.output_format)
350 372 else:
351 markdown_renderer = cls.markdown_renderer
373 markdown_renderer = get_markdown_renderer(
374 cls.extensions, cls.output_format)
352 375
353 376 if mentions:
354 377 mention_pat = re.compile(MENTIONS_REGEX)
@@ -452,7 +475,7 b' class MarkupRenderer(object):'
452 475
453 476 return nb, resources
454 477
455 def _sanitize_resources(resources):
478 def _sanitize_resources(input_resources):
456 479 """
457 480 Skip/sanitize some of the CSS generated and included in jupyter
458 481 so it doesn't messes up UI so much
@@ -464,8 +487,8 b' class MarkupRenderer(object):'
464 487 # _default_template_path_default, to achieve that
465 488
466 489 # strip the reset CSS
467 resources[0] = resources[0][resources[0].find('/*! Source'):]
468 return resources
490 input_resources[0] = input_resources[0][input_resources[0].find('/*! Source'):]
491 return input_resources
469 492
470 493 def as_html(notebook):
471 494 conf = Config()
@@ -69,6 +69,11 b' class SimpleHg(simplevcs.SimpleVCS):'
69 69 'statlfile': 'pull',
70 70 'lheads': 'pull',
71 71
72 # evolve
73 'evoext_obshashrange_v1': 'pull',
74 'evoext_obshash': 'pull',
75 'evoext_obshash1': 'pull',
76
72 77 'unbundle': 'push',
73 78 'pushkey': 'push',
74 79 }
@@ -20,7 +20,7 b''
20 20
21 21 import os
22 22 from pyramid.compat import configparser
23 from pyramid.paster import bootstrap as pyramid_bootstrap, setup_logging # noqa
23 from pyramid.paster import bootstrap as pyramid_bootstrap, setup_logging # pragma: no cover
24 24 from pyramid.scripting import prepare
25 25
26 26 from rhodecode.lib.request import Request
@@ -37,6 +37,23 b' def get_app_config(ini_path):'
37 37 return appconfig('config:{}'.format(ini_path), relative_to=os.getcwd())
38 38
39 39
40 class BootstrappedRequest(Request):
41 """
42 Special version of Request Which has some available methods like in pyramid.
43 Some code (used for template rendering) requires this, and we unsure it's present.
44 """
45
46 def translate(self, msg):
47 return msg
48
49 def plularize(self, singular, plural, n):
50 return singular
51
52 def get_partial_renderer(self, tmpl_name):
53 from rhodecode.lib.partial_renderer import get_partial_renderer
54 return get_partial_renderer(request=self, tmpl_name=tmpl_name)
55
56
40 57 def bootstrap(config_uri, request=None, options=None, env=None):
41 58 if env:
42 59 os.environ.update(env)
@@ -48,7 +65,7 b' def bootstrap(config_uri, request=None, '
48 65 except (configparser.NoSectionError, configparser.NoOptionError):
49 66 pass
50 67
51 request = request or Request.blank('/', base_url=base_url)
68 request = request or BootstrappedRequest.blank('/', base_url=base_url)
52 69
53 70 return pyramid_bootstrap(config_uri, request=request, options=options)
54 71
@@ -50,8 +50,8 b' from rhodecode.lib.vcs.exceptions import'
50 50 log = logging.getLogger(__name__)
51 51
52 52
53 FILEMODE_DEFAULT = 0100644
54 FILEMODE_EXECUTABLE = 0100755
53 FILEMODE_DEFAULT = 0o100644
54 FILEMODE_EXECUTABLE = 0o100755
55 55
56 56 Reference = collections.namedtuple('Reference', ('type', 'name', 'commit_id'))
57 57 MergeResponse = collections.namedtuple(
@@ -209,7 +209,7 b' class BaseRepository(object):'
209 209 def get_create_shadow_cache_pr_path(self, db_repo):
210 210 path = db_repo.cached_diffs_dir
211 211 if not os.path.exists(path):
212 os.makedirs(path, 0755)
212 os.makedirs(path, 0o755)
213 213 return path
214 214
215 215 @classmethod
@@ -942,13 +942,13 b' class BaseCommit(object):'
942 942 """
943 943 raise NotImplementedError
944 944
945 def get_file_commit(self, path, pre_load=None):
945 def get_path_commit(self, path, pre_load=None):
946 946 """
947 947 Returns last commit of the file at the given `path`.
948 948
949 949 :param pre_load: Optional. List of commit attributes to load.
950 950 """
951 commits = self.get_file_history(path, limit=1, pre_load=pre_load)
951 commits = self.get_path_history(path, limit=1, pre_load=pre_load)
952 952 if not commits:
953 953 raise RepositoryError(
954 954 'Failed to fetch history for path {}. '
@@ -956,7 +956,7 b' class BaseCommit(object):'
956 956 path))
957 957 return commits[0]
958 958
959 def get_file_history(self, path, limit=None, pre_load=None):
959 def get_path_history(self, path, limit=None, pre_load=None):
960 960 """
961 961 Returns history of file as reversed list of :class:`BaseCommit`
962 962 objects for which file at given `path` has been modified.
@@ -1046,7 +1046,7 b' class BaseCommit(object):'
1046 1046 ('tags', ','.join(self.tags)),
1047 1047 ]
1048 1048 meta = ["%s:%s" % (f_name, value) for f_name, value in metadata]
1049 file_info.append(('.archival.txt', 0644, False, '\n'.join(meta)))
1049 file_info.append(('.archival.txt', 0o644, False, '\n'.join(meta)))
1050 1050
1051 1051 connection.Hg.archive_repo(file_path, mtime, file_info, kind)
1052 1052
@@ -1194,8 +1194,8 b' class BaseCommit(object):'
1194 1194 self.idx = value
1195 1195
1196 1196 def get_file_changeset(self, path):
1197 warnings.warn("Use get_file_commit instead", DeprecationWarning)
1198 return self.get_file_commit(path)
1197 warnings.warn("Use get_path_commit instead", DeprecationWarning)
1198 return self.get_path_commit(path)
1199 1199
1200 1200
1201 1201 class BaseChangesetClass(type):
@@ -1502,7 +1502,7 b' class EmptyCommit(BaseCommit):'
1502 1502 def id(self):
1503 1503 return self.raw_id
1504 1504
1505 def get_file_commit(self, path):
1505 def get_path_commit(self, path):
1506 1506 return self
1507 1507
1508 1508 def get_file_content(self, path):
@@ -298,7 +298,7 b' class GitCommit(base.BaseCommit):'
298 298 id_, _ = self._get_id_for_path(path)
299 299 return self._remote.blob_raw_length(id_)
300 300
301 def get_file_history(self, path, limit=None, pre_load=None):
301 def get_path_history(self, path, limit=None, pre_load=None):
302 302 """
303 303 Returns history of file as reversed list of `GitCommit` objects for
304 304 which file at given `path` has been modified.
@@ -321,21 +321,6 b' class GitCommit(base.BaseCommit):'
321 321 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
322 322 for commit_id in commit_ids]
323 323
324 # TODO: unused for now potential replacement for subprocess
325 def get_file_history_2(self, path, limit=None, pre_load=None):
326 """
327 Returns history of file as reversed list of `Commit` objects for
328 which file at given `path` has been modified.
329 """
330 self._get_filectx(path)
331 f_path = safe_str(path)
332
333 commit_ids = self._remote.get_file_history(f_path, self.id, limit)
334
335 return [
336 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
337 for commit_id in commit_ids]
338
339 324 def get_file_annotate(self, path, pre_load=None):
340 325 """
341 326 Returns a generator of four element tuples with
@@ -161,7 +161,7 b' class GitRepository(BaseRepository):'
161 161 GitRepository.check_url(src_url, self.config)
162 162
163 163 if create:
164 os.makedirs(self.path, mode=0755)
164 os.makedirs(self.path, mode=0o755)
165 165
166 166 if bare:
167 167 self._remote.init_bare()
@@ -252,13 +252,13 b' class MercurialCommit(base.BaseCommit):'
252 252 path = self._get_filectx(path)
253 253 return self._remote.fctx_size(self.idx, path)
254 254
255 def get_file_history(self, path, limit=None, pre_load=None):
255 def get_path_history(self, path, limit=None, pre_load=None):
256 256 """
257 257 Returns history of file as reversed list of `MercurialCommit` objects
258 258 for which file at given ``path`` has been modified.
259 259 """
260 260 path = self._get_filectx(path)
261 hist = self._remote.file_history(self.idx, path, limit)
261 hist = self._remote.node_history(self.idx, path, limit)
262 262 return [
263 263 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
264 264 for commit_id in hist]
@@ -355,7 +355,7 b' class MercurialRepository(BaseRepository'
355 355 create = False
356 356
357 357 if create:
358 os.makedirs(self.path, mode=0755)
358 os.makedirs(self.path, mode=0o755)
359 359
360 360 self._remote.localrepository(create)
361 361
@@ -121,7 +121,7 b' class SubversionCommit(base.BaseCommit):'
121 121 path = self._fix_path(path)
122 122 return self._remote.get_file_size(safe_str(path), self._svn_rev)
123 123
124 def get_file_history(self, path, limit=None, pre_load=None):
124 def get_path_history(self, path, limit=None, pre_load=None):
125 125 path = safe_str(self._fix_path(path))
126 126 history = self._remote.node_history(path, self._svn_rev, limit)
127 127 return [
@@ -31,7 +31,7 b' import greenlet'
31 31
32 32 # Import everything from pycurl.
33 33 # This allows us to use this module as a drop in replacement of pycurl.
34 from pycurl import * # noqa
34 from pycurl import * # pragma: no cover
35 35
36 36 from gevent import core
37 37 from gevent.hub import Waiter
@@ -404,7 +404,7 b' class FileNode(Node):'
404 404 def last_commit(self):
405 405 if self.commit:
406 406 pre_load = ["author", "date", "message"]
407 return self.commit.get_file_commit(self.path, pre_load=pre_load)
407 return self.commit.get_path_commit(self.path, pre_load=pre_load)
408 408 raise NodeError(
409 409 "Cannot retrieve last commit of the file without "
410 410 "related commit attribute")
@@ -510,7 +510,7 b' class FileNode(Node):'
510 510 """
511 511 if self.commit is None:
512 512 raise NodeError('Unable to get commit for this FileNode')
513 return self.commit.get_file_history(self.path)
513 return self.commit.get_path_history(self.path)
514 514
515 515 @LazyProperty
516 516 def annotate(self):
@@ -724,6 +724,15 b' class DirNode(Node):'
724 724
725 725 return size
726 726
727 @LazyProperty
728 def last_commit(self):
729 if self.commit:
730 pre_load = ["author", "date", "message"]
731 return self.commit.get_path_commit(self.path, pre_load=pre_load)
732 raise NodeError(
733 "Cannot retrieve last commit of the file without "
734 "related commit attribute")
735
727 736 def __repr__(self):
728 737 return '<%s %r @ %s>' % (self.__class__.__name__, self.path,
729 738 getattr(self.commit, 'short_id', ''))
@@ -21,6 +21,7 b''
21 21
22 22 import logging
23 23
24 import rhodecode
24 25 from rhodecode.model import meta, db
25 26 from rhodecode.lib.utils2 import obfuscate_url_pw, get_encryption_key
26 27
@@ -36,7 +37,7 b' def init_model(engine, encryption_key=No'
36 37 :param engine: engine to bind to
37 38 """
38 39 engine_str = obfuscate_url_pw(str(engine.url))
39 log.info("initializing db for %s", engine_str)
40 log.info("RhodeCode %s initializing db for %s", rhodecode.__version__, engine_str)
40 41 meta.Base.metadata.bind = engine
41 42 db.ENCRYPTION_KEY = encryption_key
42 43
@@ -40,12 +40,12 b' from sqlalchemy import ('
40 40 Boolean, String, Unicode, UnicodeText, DateTime, Integer, LargeBinary,
41 41 Text, Float, PickleType)
42 42 from sqlalchemy.sql.expression import true, false
43 from sqlalchemy.sql.functions import coalesce, count # noqa
43 from sqlalchemy.sql.functions import coalesce, count # pragma: no cover
44 44 from sqlalchemy.orm import (
45 45 relationship, joinedload, class_mapper, validates, aliased)
46 46 from sqlalchemy.ext.declarative import declared_attr
47 47 from sqlalchemy.ext.hybrid import hybrid_property
48 from sqlalchemy.exc import IntegrityError # noqa
48 from sqlalchemy.exc import IntegrityError # pragma: no cover
49 49 from sqlalchemy.dialects.mysql import LONGTEXT
50 50 from zope.cachedescriptors.property import Lazy as LazyProperty
51 51
@@ -377,6 +377,12 b' class RhodeCodeSetting(Base, BaseModel):'
377 377 % (self.SETTINGS_TYPES.keys(), val))
378 378 self._app_settings_type = val
379 379
380 @classmethod
381 def get_by_prefix(cls, prefix):
382 return RhodeCodeSetting.query()\
383 .filter(RhodeCodeSetting.app_settings_name.startswith(prefix))\
384 .all()
385
380 386 def __unicode__(self):
381 387 return u"<%s('%s:%s[%s]')>" % (
382 388 self.__class__.__name__,
@@ -4143,20 +4149,16 b' class ExternalIdentity(Base, BaseModel):'
4143 4149 base_table_args
4144 4150 )
4145 4151
4146 external_id = Column('external_id', Unicode(255), default=u'',
4147 primary_key=True)
4152 external_id = Column('external_id', Unicode(255), default=u'', primary_key=True)
4148 4153 external_username = Column('external_username', Unicode(1024), default=u'')
4149 local_user_id = Column('local_user_id', Integer(),
4150 ForeignKey('users.user_id'), primary_key=True)
4151 provider_name = Column('provider_name', Unicode(255), default=u'',
4152 primary_key=True)
4154 local_user_id = Column('local_user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
4155 provider_name = Column('provider_name', Unicode(255), default=u'', primary_key=True)
4153 4156 access_token = Column('access_token', String(1024), default=u'')
4154 4157 alt_token = Column('alt_token', String(1024), default=u'')
4155 4158 token_secret = Column('token_secret', String(1024), default=u'')
4156 4159
4157 4160 @classmethod
4158 def by_external_id_and_provider(cls, external_id, provider_name,
4159 local_user_id=None):
4161 def by_external_id_and_provider(cls, external_id, provider_name, local_user_id=None):
4160 4162 """
4161 4163 Returns ExternalIdentity instance based on search params
4162 4164
@@ -4198,6 +4200,13 b' class ExternalIdentity(Base, BaseModel):'
4198 4200 query = query.filter(cls.local_user_id == local_user_id)
4199 4201 return query
4200 4202
4203 @classmethod
4204 def load_provider_plugin(cls, plugin_id):
4205 from rhodecode.authentication.base import loadplugin
4206 _plugin_id = 'egg:rhodecode-enterprise-ee#{}'.format(plugin_id)
4207 auth_plugin = loadplugin(_plugin_id)
4208 return auth_plugin
4209
4201 4210
4202 4211 class Integration(Base, BaseModel):
4203 4212 __tablename__ = 'integrations'
@@ -95,15 +95,14 b' class NotificationModel(BaseModel):'
95 95 log.debug('sending notifications %s to admins: %s',
96 96 notification_type, recipients_objs)
97 97 else:
98 recipients_objs = []
98 recipients_objs = set()
99 99 for u in recipients:
100 100 obj = self._get_user(u)
101 101 if obj:
102 recipients_objs.append(obj)
102 recipients_objs.add(obj)
103 103 else: # we didn't find this user, log the error and carry on
104 104 log.error('cannot notify unknown user %r', u)
105 105
106 recipients_objs = set(recipients_objs)
107 106 if not recipients_objs:
108 107 raise Exception('no valid recipients specified')
109 108
@@ -122,7 +121,7 b' class NotificationModel(BaseModel):'
122 121 return notification
123 122
124 123 # don't send email to person who created this comment
125 rec_objs = set(recipients_objs).difference(set([created_by_obj]))
124 rec_objs = set(recipients_objs).difference({created_by_obj})
126 125
127 126 # now notify all recipients in question
128 127
@@ -1576,10 +1576,8 b' class PullRequestModel(BaseModel):'
1576 1576 from rc_reviewers.utils import get_default_reviewers_data
1577 1577 from rc_reviewers.utils import validate_default_reviewers
1578 1578 except ImportError:
1579 from rhodecode.apps.repository.utils import \
1580 get_default_reviewers_data
1581 from rhodecode.apps.repository.utils import \
1582 validate_default_reviewers
1579 from rhodecode.apps.repository.utils import get_default_reviewers_data
1580 from rhodecode.apps.repository.utils import validate_default_reviewers
1583 1581
1584 1582 return get_default_reviewers_data, validate_default_reviewers
1585 1583
@@ -181,7 +181,7 b' class RepoGroupModel(BaseModel):'
181 181 self.check_exist_filesystem(group_name)
182 182 create_path = os.path.join(self.repos_path, group_name)
183 183 log.debug('creating new group in %s', create_path)
184 os.makedirs(create_path, mode=0755)
184 os.makedirs(create_path, mode=0o755)
185 185 log.debug('created group in %s', create_path)
186 186
187 187 def _rename_group(self, old, new):
@@ -582,7 +582,6 b' class VcsSettingsModel(object):'
582 582 self._create_or_update_ui(
583 583 self.repo_settings, *phases, value=safe_str(data[phases_key]))
584 584
585
586 585 def create_or_update_global_hg_settings(self, data):
587 586 largefiles, largefiles_store, phases, hgsubversion, evolve \
588 587 = self.GLOBAL_HG_SETTINGS
@@ -344,8 +344,8 b' class UserModel(BaseModel):'
344 344 new_user.is_new_user = not edit
345 345 # for users that didn's specify auth type, we use RhodeCode built in
346 346 from rhodecode.authentication.plugins import auth_rhodecode
347 extern_name = extern_name or auth_rhodecode.RhodeCodeAuthPlugin.name
348 extern_type = extern_type or auth_rhodecode.RhodeCodeAuthPlugin.name
347 extern_name = extern_name or auth_rhodecode.RhodeCodeAuthPlugin.uid
348 extern_type = extern_type or auth_rhodecode.RhodeCodeAuthPlugin.uid
349 349
350 350 try:
351 351 new_user.username = username
@@ -392,14 +392,15 b' class UserModel(BaseModel):'
392 392 log.error(traceback.format_exc())
393 393 raise
394 394
395 def create_registration(self, form_data):
395 def create_registration(self, form_data,
396 extern_name='rhodecode', extern_type='rhodecode'):
396 397 from rhodecode.model.notification import NotificationModel
397 398 from rhodecode.model.notification import EmailNotificationModel
398 399
399 400 try:
400 401 form_data['admin'] = False
401 form_data['extern_name'] = 'rhodecode'
402 form_data['extern_type'] = 'rhodecode'
402 form_data['extern_name'] = extern_name
403 form_data['extern_type'] = extern_type
403 404 new_user = self.create(form_data)
404 405
405 406 self.sa.add(new_user)
@@ -20,5 +20,5 b''
20 20
21 21 import colander
22 22
23 from colander import Invalid # noqa, don't remove this
23 from colander import Invalid # pragma: no cover
24 24
@@ -27,10 +27,7 b''
27 27 padding-left: 10px;
28 28 }
29 29 li {
30 list-style-type: none;
31 }
32 li:before {
33 content: "\2014\00A0";
30 list-style-type: disc;
34 31 }
35 32 .error_message {
36 33 font-weight: normal;
@@ -89,7 +86,9 b''
89 86 </div>
90 87 <div class="main">
91 88 <h1>
92 502 Bad Gateway | <span class="error_message">Backend server is unreachable</span>
89 502 Bad Gateway
90 <br/>
91 <span class="error_message">Backend server is unreachable</span>
93 92 </h1>
94 93 <div class="inner-column">
95 94 <h4>Possible Causes</h4>
@@ -254,7 +254,7 b' input[type="button"] {'
254 254 .btn-social {
255 255 &:extend(.btn-default);
256 256 margin: 5px 5px 5px 0px;
257 min-width: 150px;
257 min-width: 160px;
258 258 }
259 259
260 260 // TODO: johbo: check these exceptions
@@ -570,14 +570,17 b' div.annotatediv { margin-left: 2px; marg'
570 570
571 571 .code { display: block; border:0px !important; }
572 572 .code-highlight, /* TODO: dan: merge codehilite into code-highlight */
573 /* This can be generated with `pygmentize -S default -f html` */
573 574 .codehilite {
574 575 .hll { background-color: #ffffcc }
575 576 .c { color: #408080; font-style: italic } /* Comment */
576 577 .err, .codehilite .err { border: none } /* Error */
577 578 .k { color: #008000; font-weight: bold } /* Keyword */
578 579 .o { color: #666666 } /* Operator */
580 .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
579 581 .cm { color: #408080; font-style: italic } /* Comment.Multiline */
580 582 .cp { color: #BC7A00 } /* Comment.Preproc */
583 .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
581 584 .c1 { color: #408080; font-style: italic } /* Comment.Single */
582 585 .cs { color: #408080; font-style: italic } /* Comment.Special */
583 586 .gd { color: #A00000 } /* Generic.Deleted */
@@ -585,11 +588,11 b' div.annotatediv { margin-left: 2px; marg'
585 588 .gr { color: #FF0000 } /* Generic.Error */
586 589 .gh { color: #000080; font-weight: bold } /* Generic.Heading */
587 590 .gi { color: #00A000 } /* Generic.Inserted */
588 .go { color: #808080 } /* Generic.Output */
591 .go { color: #888888 } /* Generic.Output */
589 592 .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
590 593 .gs { font-weight: bold } /* Generic.Strong */
591 594 .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
592 .gt { color: #0040D0 } /* Generic.Traceback */
595 .gt { color: #0044DD } /* Generic.Traceback */
593 596 .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
594 597 .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
595 598 .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
@@ -612,12 +615,15 b' div.annotatediv { margin-left: 2px; marg'
612 615 .nv { color: #19177C } /* Name.Variable */
613 616 .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
614 617 .w { color: #bbbbbb } /* Text.Whitespace */
618 .mb { color: #666666 } /* Literal.Number.Bin */
615 619 .mf { color: #666666 } /* Literal.Number.Float */
616 620 .mh { color: #666666 } /* Literal.Number.Hex */
617 621 .mi { color: #666666 } /* Literal.Number.Integer */
618 622 .mo { color: #666666 } /* Literal.Number.Oct */
623 .sa { color: #BA2121 } /* Literal.String.Affix */
619 624 .sb { color: #BA2121 } /* Literal.String.Backtick */
620 625 .sc { color: #BA2121 } /* Literal.String.Char */
626 .dl { color: #BA2121 } /* Literal.String.Delimiter */
621 627 .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
622 628 .s2 { color: #BA2121 } /* Literal.String.Double */
623 629 .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
@@ -628,9 +634,11 b' div.annotatediv { margin-left: 2px; marg'
628 634 .s1 { color: #BA2121 } /* Literal.String.Single */
629 635 .ss { color: #19177C } /* Literal.String.Symbol */
630 636 .bp { color: #008000 } /* Name.Builtin.Pseudo */
637 .fm { color: #0000FF } /* Name.Function.Magic */
631 638 .vc { color: #19177C } /* Name.Variable.Class */
632 639 .vg { color: #19177C } /* Name.Variable.Global */
633 640 .vi { color: #19177C } /* Name.Variable.Instance */
641 .vm { color: #19177C } /* Name.Variable.Magic */
634 642 .il { color: #666666 } /* Literal.Number.Integer.Long */
635 643 }
636 644
@@ -548,10 +548,9 b' form.comment-form {'
548 548 }
549 549 .nav-links li {
550 550 display: inline-block;
551 list-style-type: none;
551 552 }
552 .nav-links li:before {
553 content: "";
554 }
553
555 554 .nav-links li a.disabled {
556 555 cursor: not-allowed;
557 556 }
@@ -219,7 +219,6 b' form.rcform {'
219 219 li {
220 220 list-style-type: none;
221 221
222 &:before { content:none; }
223 222 &:after {
224 223 content: "";
225 224 float: left;
@@ -43,7 +43,9 b' a { cursor: pointer; }'
43 43 float: right;
44 44 clear: right;
45 45
46 li:before { content:none; }
46 li {
47 list-style-type: none;
48 }
47 49 }
48 50
49 51 //--- DEVICE-SPECIFIC CLASSES ---------------//
@@ -126,6 +126,11 b' div.markdown-block h6 {'
126 126 overflow: visible !important;
127 127 }
128 128
129 div.markdown-block h1,
130 div.markdown-block h2 {
131 border-bottom: 1px #e6e5e5 solid !important;
132 }
133
129 134 div.markdown-block h1 {
130 135 font-size: 32px;
131 136 margin: 15px 0 15px 0 !important;
@@ -135,7 +140,6 b' div.markdown-block h1 {'
135 140 div.markdown-block h2 {
136 141 font-size: 24px !important;
137 142 margin: 34px 0 10px 0 !important;
138 border-top: 3px #e6e5e5 solid !important;
139 143 padding-top: 15px !important;
140 144 padding-bottom: 8px !important;
141 145 }
@@ -199,6 +203,7 b' div.markdown-block pre {'
199 203 div.markdown-block img {
200 204 border-style: none;
201 205 background-color: #fff;
206 padding-right: 20px;
202 207 }
203 208
204 209
@@ -317,9 +322,13 b' div.rst-block h3 {'
317 322 margin: 1em 0 !important;
318 323 }
319 324
325 div.rst-block h1,
326 div.rst-block h2 {
327 border-bottom: 1px #e6e5e5 solid !important;
328 }
329
320 330 div.rst-block h2 {
321 331 margin-top: 1.5em !important;
322 border-top: 4px solid #e0e0e0 !important;
323 332 padding-top: .5em !important;
324 333 }
325 334
@@ -196,6 +196,16 b''
196 196 .text-as-placeholder {
197 197 padding-top: @input-padding-px + @border-thickness-inputs;
198 198 }
199
200 .no-border {
201 border: 1px;
202 }
203
204 .no-horizontal-padding {
205 padding-left: 0;
206 padding-right: 0;
207 }
208
199 209 }
200 210
201 211 // TODO: johbo: Try to find a better integration of this bit.
@@ -315,7 +315,6 b' ul.auth_plugins {'
315 315 margin-right: @padding;
316 316 }
317 317
318 &:before { content: none; }
319 318 }
320 319 }
321 320
@@ -1325,6 +1324,7 b' table.integrations {'
1325 1324 position: relative;
1326 1325 width: 100%;
1327 1326 padding-bottom: 8px;
1327 list-style-type: none;
1328 1328 }
1329 1329
1330 1330 .reviewer_entry {
@@ -1719,8 +1719,8 b' BIN_FILENODE = 7'
1719 1719 padding: 0px 0px;
1720 1720 }
1721 1721
1722 .pull-request-merge li:before{
1723 content:none;
1722 .pull-request-merge li {
1723 list-style-type: none;
1724 1724 }
1725 1725
1726 1726 .pull-request-merge .pull-request-wrap {
@@ -1957,7 +1957,7 b' BIN_FILENODE = 7'
1957 1957 font-size: @journal-fontsize;
1958 1958 line-height: 1em;
1959 1959
1960 &:before { content: none; }
1960 list-style-type: none;
1961 1961 }
1962 1962 }
1963 1963 }
@@ -201,8 +201,7 b''
201 201 padding: 0 2px;
202 202 }
203 203 }
204
205 &:before { content: none; }
204 list-style-type: none;
206 205 }
207 206
208 207 > li {
@@ -305,8 +304,7 b''
305 304 line-height: 1em;
306 305 color: @grey3;
307 306 background-color: @grey6;
308
309 &:before { content: none; }
307 list-style-type: none;
310 308
311 309 a {
312 310 display: block;
@@ -398,8 +396,6 b''
398 396 line-height: 1em;
399 397 list-style-type: none;
400 398
401 &:before { content: none; }
402
403 399 a {
404 400 display: block;
405 401 height: 16px;
@@ -461,8 +457,6 b''
461 457 line-height: 1em;
462 458 color: @grey6;
463 459
464 &:before { content: none; }
465
466 460 &>.select2-result-label {
467 461 padding: 8px 0;
468 462 border-bottom: @border-thickness solid @grey3;
@@ -494,8 +488,7 b''
494 488 line-height: 1em;
495 489 font-family: @text-light;
496 490 color: @grey2;
497
498 &:before { content: none; }
491 list-style-type: none;
499 492
500 493 &:hover {
501 494 background-color: @grey3;
@@ -520,8 +513,7 b''
520 513 ul#context-pages {
521 514 li {
522 515 line-height: 1em;
523
524 &:before { content: none; }
516 list-style-type: none;
525 517
526 518 a {
527 519 color: @grey3;
@@ -622,6 +614,7 b' ul#context-pages {'
622 614 padding-bottom: @menupadding;
623 615 line-height: 1em;
624 616 color: @grey4;
617 list-style-type: none;
625 618
626 619 &.active a {
627 620 color: @grey2;
@@ -630,8 +623,6 b' ul#context-pages {'
630 623 a {
631 624 color: @grey4;
632 625 }
633
634 &:before { content: none; }
635 626 }
636 627
637 628 }
@@ -17,6 +17,11 b' div.readme_box h6 {'
17 17 overflow: visible !important;
18 18 }
19 19
20 div.readme_box h1,
21 div.readme_box h2 {
22 border-bottom: 1px #e6e5e5 solid !important;
23 }
24
20 25 div.readme_box h1 {
21 26 font-size: 32px;
22 27 margin: 15px 0 15px 0 !important;
@@ -26,7 +31,6 b' div.readme_box h1 {'
26 31 div.readme_box h2 {
27 32 font-size: 24px !important;
28 33 margin: 34px 0 10px 0 !important;
29 border-top: 3px #e6e5e5 solid !important;
30 34 padding-top: 15px !important;
31 35 padding-bottom: 8px !important;
32 36 }
@@ -90,6 +94,7 b' div.readme_box pre {'
90 94 div.readme_box img {
91 95 border-style: none;
92 96 background-color: #fff;
97 padding-right: 20px;
93 98 }
94 99
95 100
@@ -107,7 +112,7 b' div.readme_box ol {'
107 112
108 113 div.readme_box ul li,
109 114 div.readme_box ol li {
110 list-style: bullet !important;
115 list-style: disc !important;
111 116 margin: 6px !important;
112 117 padding: 0 !important;
113 118 }
@@ -174,8 +174,6 b' select.select2{height:28px;visibility:hi'
174 174 line-height: 1em;
175 175 list-style-type: none;
176 176
177 &:before { content: none; }
178
179 177 &:hover,
180 178 &.select2-highlighted {
181 179 background-color: @rclightblue;
@@ -104,11 +104,7 b''
104 104 padding-left: 0;
105 105
106 106 li {
107
108 &:before {
109 content: none;
110 width: 0;
111 }
107 list-style-type: none;
112 108 }
113 109 }
114 110 }
@@ -64,7 +64,9 b' table.dataTable {'
64 64 .expired td {
65 65 background-color: @grey7;
66 66 }
67
67 .inactive td {
68 background-color: @grey6;
69 }
68 70 th {
69 71 text-align: left;
70 72 font-weight: @text-semibold-weight;
@@ -49,8 +49,6 b''
49 49 margin: 0 0 @padding;
50 50 line-height: 1em;
51 51 list-style-type: none;
52
53 &:before { content: none; }
54 52 }
55 53 }
56 54
@@ -274,8 +274,11 b' mark,'
274 274 list-style: none;
275 275 text-align: right;
276 276
277 li:before { content: none; }
278 li { float: right; }
277 li {
278 float: right;
279 list-style-type: none;
280 }
281
279 282 a {
280 283 display: inline-block;
281 284 margin-left: @textmargin/2;
@@ -338,15 +341,7 b' li {'
338 341
339 342 ul li {
340 343 position: relative;
341 display: block;
342 list-style-type: none;
343
344 &:before {
345 content: "\2014\00A0";
346 position: absolute;
347 top: 0;
348 left: -1.25em;
349 }
344 list-style-type: disc;
350 345
351 346 p:first-child {
352 347 display:inline;
@@ -539,7 +534,7 b' address {'
539 534 color: @grey4;
540 535 font-family: @text-light;
541 536 &.pre-formatting {
542 white-space: pre;
537 white-space: pre-wrap;
543 538 }
544 539 }
545 540
@@ -125,7 +125,7 b''
125 125 @label-summary-minwidth: 80px;
126 126 @search-form-width: 400px;
127 127 @fields-input-m: 400px;
128 @fields-input-l: 800px;
128 @fields-input-l: 720px;
129 129
130 130 // BUTTONS
131 131 @button-padding: .9em;
@@ -14,7 +14,6 b' function registerRCRoutes() {'
14 14 // routes registration
15 15 pyroutes.register('favicon', '/favicon.ico', []);
16 16 pyroutes.register('robots', '/robots.txt', []);
17 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
18 17 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
19 18 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
20 19 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
@@ -30,6 +29,7 b' function registerRCRoutes() {'
30 29 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
31 30 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
32 31 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
32 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
33 33 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
34 34 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
35 35 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
@@ -475,11 +475,10 b' class RcServerCommand(object):'
475 475 msg = ''
476 476 self.out('Exiting%s (-v to see traceback)' % msg)
477 477
478
479 478 def loadapp(self, app_spec, name, relative_to, **kw): # pragma: no cover
480 479 return loadapp(app_spec, name=name, relative_to=relative_to, **kw)
481 480
482 def loadserver(self, server_spec, name, relative_to, **kw): # pragma:no cover
481 def loadserver(self, server_spec, name, relative_to, **kw): # pragma: no cover
483 482 return loadserver(
484 483 server_spec, name=name, relative_to=relative_to, **kw)
485 484
@@ -39,48 +39,56 b''
39 39
40 40 <div class="main-content-full-width">
41 41 ${h.secure_form(request.resource_path(resource, route_name='auth_home'), request=request)}
42 <div class="form">
43
44 42 <div class="panel panel-default">
45 43
46 44 <div class="panel-heading">
47 45 <h3 class="panel-title">${_("Enabled and Available Plugins")}</h3>
48 46 </div>
49 47
50 <div class="fields panel-body">
48 <div class="panel-body">
51 49
52 <div class="field">
53 <div class="label">${_("Enabled Plugins")}</div>
50
51 <div class="label">${_("Ordered Activated Plugins")}</div>
54 52 <div class="textarea text-area editor">
55 ${h.textarea('auth_plugins',cols=23,rows=5,class_="medium")}
53 ${h.textarea('auth_plugins',cols=120,rows=20,class_="medium")}
56 54 </div>
57 <p class="help-block pre-formatting">${_('List of plugins, separated by commas.'
55 <div class="field">
56 <p class="help-block pre-formatting">${_('List of plugins, separated by commas.'
58 57 '\nThe order of the plugins is also the order in which '
59 'RhodeCode Enterprise will try to authenticate a user.')}</p>
60 </div>
58 'RhodeCode Enterprise will try to authenticate a user.')}
59 </p>
60 </div>
61 61
62 <div class="field">
63 <div class="label">${_('Available Built-in Plugins')}</div>
64 <ul class="auth_plugins">
65 %for plugin in available_plugins:
66 <li>
67 <div class="auth_buttons">
68 <span plugin_id="${plugin.get_id()}" class="toggle-plugin btn ${'btn-success' if plugin.get_id() in enabled_plugins else ''}">
69 ${_('enabled') if plugin.get_id() in enabled_plugins else _('disabled')}
70 </span>
71 ${plugin.get_display_name()} (${plugin.get_id()})
72 </div>
73 </li>
74 %endfor
75 </ul>
76 </div>
62 <table class="rctable">
63 <th>${_('Activate')}</th>
64 <th>${_('Plugin Name')}</th>
65 <th>${_('Documentation')}</th>
66 <th>${_('Plugin ID')}</th>
67 <th>${_('Enabled')}</th>
68 %for plugin in available_plugins:
69 <tr class="${'inactive' if (not plugin.is_active() and plugin.get_id() in enabled_plugins) else ''}">
70 <td>
71 <span plugin_id="${plugin.get_id()}" class="toggle-plugin btn ${'btn-success' if plugin.get_id() in enabled_plugins else ''}">
72 ${_('activated') if plugin.get_id() in enabled_plugins else _('not active')}
73 </span>
74 </td>
75 <td>${plugin.get_display_name()}</td>
76 <td>
77 % if plugin.docs():
78 <a href="${plugin.docs()}">docs</a>
79 % endif
80 </td>
81 <td>${plugin.get_id()}</td>
82 <td>${h.bool2icon(plugin.is_active(),show_at_false=False)}</td>
83 </tr>
84 %endfor
85 </table>
77 86
78 87 <div class="buttons">
79 88 ${h.submit('save',_('Save'),class_="btn")}
80 89 </div>
81 90 </div>
82 91 </div>
83 </div>
84 92 ${h.end_form()}
85 93 </div>
86 94 </div>
@@ -103,15 +111,15 b''
103 111 elems.splice(elems.indexOf(plugin_id), 1);
104 112 auth_plugins_input.val(elems.join(',\n'));
105 113 $(cur_button).removeClass('btn-success');
106 cur_button.innerHTML = _gettext('disabled');
114 cur_button.innerHTML = _gettext('not active');
107 115 }
108 116 else{
109 if(elems.indexOf(plugin_id) == -1){
110 elems.push(plugin_id);
117 if (elems.indexOf(plugin_id) === -1) {
118 elems.push(plugin_id);
111 119 }
112 120 auth_plugins_input.val(elems.join(',\n'));
113 121 $(cur_button).addClass('btn-success');
114 cur_button.innerHTML = _gettext('enabled');
122 cur_button.innerHTML = _gettext('activated');
115 123 }
116 124 });
117 125 </script>
@@ -51,23 +51,29 b''
51 51 <div class="form">
52 52
53 53 %for node in plugin.get_settings_schema():
54 <% label_css_class = ("label-checkbox" if (node.widget == "bool") else "") %>
54 <%
55 label_to_type = {'label-checkbox': 'bool', 'label-textarea': 'textarea'}
56 %>
57
55 58 <div class="field">
56 <div class="label ${label_css_class}"><label for="${node.name}">${node.title}</label></div>
59 <div class="label ${label_to_type.get(node.widget)}"><label for="${node.name}">${node.title}</label></div>
57 60 <div class="input">
58 61 %if node.widget in ["string", "int", "unicode"]:
59 ${h.text(node.name, defaults.get(node.name), class_="medium")}
62 ${h.text(node.name, defaults.get(node.name), class_="large")}
60 63 %elif node.widget == "password":
61 ${h.password(node.name, defaults.get(node.name), class_="medium")}
64 ${h.password(node.name, defaults.get(node.name), class_="large")}
62 65 %elif node.widget == "bool":
63 66 <div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div>
64 67 %elif node.widget == "select":
65 ${h.select(node.name, defaults.get(node.name), node.validator.choices)}
68 ${h.select(node.name, defaults.get(node.name), node.validator.choices, class_="select2AuthSetting")}
69 %elif node.widget == "textarea":
70 <div class="textarea" style="margin-left: 0px">${h.textarea(node.name, defaults.get(node.name), rows=10)}</div>
66 71 %elif node.widget == "readonly":
67 72 ${node.default}
68 73 %else:
69 74 This field is of type ${node.typ}, which cannot be displayed. Must be one of [string|int|bool|select].
70 75 %endif
76
71 77 %if node.name in errors:
72 78 <span class="error-message">${errors.get(node.name)}</span>
73 79 <br />
@@ -91,6 +97,18 b''
91 97 ${h.end_form()}
92 98 </div>
93 99 </div>
100
101 % if request.GET.get('schema'):
102 ## this is for development and creation of example configurations for documentation
103 <pre>
104 % for node in plugin.get_settings_schema():
105 *option*: `${node.name}` => `${defaults.get(node.name)}`${'\n # '.join(['']+node.description.splitlines())}
106
107 % endfor
108 </pre>
109
110 % endif
111
94 112 </div>
95 113 </div>
96 114 </div>
@@ -98,8 +116,7 b''
98 116 </div>
99 117 </div>
100 118
101 ## TODO: Ugly hack to get ldap select elements to work.
102 ## Find a solution to integrate this nicely.
119
103 120 <script>
104 121 $(document).ready(function() {
105 122 var select2Options = {
@@ -107,12 +124,9 b''
107 124 dropdownCssClass: 'drop-menu-dropdown',
108 125 dropdownAutoWidth: true,
109 126 minimumResultsForSearch: -1
110 };
111 $("#tls_kind").select2(select2Options);
112 $("#tls_reqcert").select2(select2Options);
113 $("#search_scope").select2(select2Options);
114 $("#group_extraction_type").select2(select2Options);
115 $("#admin_groups_sync").select2(select2Options);
127 };
128 $('.select2AuthSetting').select2(select2Options);
129
116 130 });
117 131 </script>
118 132 </%def>
@@ -32,10 +32,10 b''
32 32 <li class="${'active' if c.active in ['ssh_keys', 'ssh_keys_generate'] else ''}"><a href="${h.route_path('my_account_ssh_keys')}">${_('SSH Keys')}</a></li>
33 33 <li class="${'active' if c.active=='user_group_membership' else ''}"><a href="${h.route_path('my_account_user_group_membership')}">${_('User Group Membership')}</a></li>
34 34
35 ## TODO: Find a better integration of oauth views into navigation.
36 <% my_account_oauth_url = h.route_path_or_none('my_account_oauth') %>
37 % if my_account_oauth_url:
38 <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li>
35 ## TODO: Find a better integration of oauth/saml views into navigation.
36 <% my_account_external_url = h.route_path_or_none('my_account_external_identity') %>
37 % if my_account_external_url:
38 <li class="${'active' if c.active=='external_identity' else ''}"><a href="${my_account_external_url}">${_('External Identities')}</a></li>
39 39 % endif
40 40 <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('my_account_emails')}">${_('Emails')}</a></li>
41 41 <li class="${'active' if c.active=='repos' else ''}"><a href="${h.route_path('my_account_repos')}">${_('Repositories')}</a></li>
@@ -49,9 +49,7 b' Currently the following views are set:'
49 49 % for route_name, view_fqn, view_url, active in c.view_data:
50 50 <tr>
51 51 <td class="td-x">
52 % if active:
53 ${h.bool2icon(active)}
54 % endif
52 ${h.bool2icon(active, show_at_false=False)}
55 53 </td>
56 54 <td class="td-x">${view_fqn}</td>
57 55 <td class="td-x" title="${route_name}">${view_url}</td>
@@ -102,6 +102,7 b''
102 102 <option value="clicky">Clicky</option>
103 103 <option value="server_announce">${_('Server Announcement')}</option>
104 104 <option value="flash_filtering">${_('Flash message filtering')}</option>
105 <option value="custom_logo">${_('Custom logos')}</option>
105 106 </select>
106 107 </div>
107 108 <div style="padding: 10px 0px"></div>
@@ -212,7 +213,7 b''
212 213 // This can be used to send a global maintenance messages or other
213 214 // important messages to all users of the RhodeCode Enterprise system.
214 215
215 $(document).ready(function(e){
216 $(document).ready(function(e) {
216 217
217 218 // EDIT - put your message below
218 219 var message = "TYPE YOUR MESSAGE HERE";
@@ -248,6 +249,32 b''
248 249 </%text>
249 250 </script>
250 251
252
253 <script id="custom_logo_tmpl" type='text/x-template'>
254 <%text filter="h">
255 <script>
256
257 $(document).ready(function(e) {
258 // 1) Set custom logo on login/register pages.
259
260 // external URL, custom company logo
261 //$('.sign-in-image').attr("src", "http://server.com/logo_path/custom_logo.png");
262
263 // Alternative logo from static folder
264 $('.sign-in-image').attr("src", "/_static/rhodecode/images/RhodeCode_Logo_Black.png");
265
266 // option to set width/height, adjust if required to make your image look good.
267 $('.sign-in-image').css({"width": "300px", "height": "345px"});
268
269 // 2) Header logo on top bar
270 $('.logo-wrapper').find('img').attr('src', 'http://server.com/logo_path/custom_header_logo.png')
271
272 });
273 </script>
274 </%text>
275 </script>
276
277
251 278 <script>
252 279 var pre_cm = initCodeMirror('rhodecode_pre_code', '', false);
253 280 var pre_old = pre_cm.getValue();
@@ -255,7 +282,7 b' var pre_old = pre_cm.getValue();'
255 282 var post_cm = initCodeMirror('rhodecode_post_code', '', false);
256 283 var post_old = post_cm.getValue();
257 284
258 var get_data = function(type, old){
285 var get_data = function(type, old) {
259 286 var get_tmpl = function(tmpl_name){
260 287 // unescape some stuff
261 288 return htmlEnDeCode.htmlDecode($('#'+tmpl_name+'_tmpl').html());
@@ -265,7 +292,8 b' var get_data = function(type, old){'
265 292 'ga': get_tmpl('ga'),
266 293 'clicky': get_tmpl('clicky'),
267 294 'server_announce': get_tmpl('server_announce'),
268 'flash_filtering': get_tmpl('flash_filtering')
295 'flash_filtering': get_tmpl('flash_filtering'),
296 'custom_logo': get_tmpl('custom_logo')
269 297 }[type]
270 298 };
271 299
@@ -103,11 +103,12 b''
103 103 </div>
104 104 <div class="field">
105 105 <div class="label-text">
106 ${_('Source of Record')}:
106 ${_('Authentication type')}:
107 107 </div>
108 108 <div class="input">
109 109 <p>${c.extern_type}</p>
110 110 ${h.hidden('extern_type', readonly="readonly")}
111 <p class="help-block">${_('User was created using an external source. He is bound to authentication using this method.')}</p>
111 112 </div>
112 113 </div>
113 114 <div class="field">
@@ -127,7 +128,7 b''
127 128 ## allowed_languages is defined in the users.py
128 129 ## c.language comes from base.py as a default language
129 130 ${h.select('language', c.language, c.allowed_languages)}
130 <p class="help-block">${h.literal(_('Help translate %(rc_link)s into your language.') % {'rc_link': h.link_to('RhodeCode Enterprise', h.route_url('rhodecode_translations'))})}</p>
131 <p class="help-block">${h.literal(_('User interface language. Help translate %(rc_link)s into your language.') % {'rc_link': h.link_to('RhodeCode Enterprise', h.route_url('rhodecode_translations'))})}</p>
131 132 </div>
132 133 </div>
133 134 <div class="buttons">
@@ -4,7 +4,8 b''
4 4 </div>
5 5 <div class="panel-body">
6 6 <p>
7 ${_('Below is a 2048 bit generated SSH RSA key. You can use it to access RhodeCode via the SSH wrapper.')}
7 ${_('Below is a 2048 bit generated SSH RSA key.')}<br/>
8 ${_('If You wish to use it to access RhodeCode via the SSH please save the private key and click `Use this generated key` at the bottom.')}
8 9 </p>
9 10 <h4>${_('Private key')}</h4>
10 11 <pre>
@@ -27,9 +27,6 b" c.template_context['default_user'] = {"
27 27 %>
28 28 <html xmlns="http://www.w3.org/1999/xhtml">
29 29 <head>
30
31 <script src="${h.asset('js/vendors/webcomponentsjs/custom-elements-es5-adapter.js', ver=c.rhodecode_version_hash)}"></script>
32 <script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-bundle.js', ver=c.rhodecode_version_hash)}"></script>
33 30 <title>${self.title()}</title>
34 31 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
35 32
@@ -46,6 +43,8 b" c.template_context['default_user'] = {"
46 43 </%def>
47 44 ${self.robots()}
48 45 <link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
46 <script src="${h.asset('js/vendors/webcomponentsjs/custom-elements-es5-adapter.js', ver=c.rhodecode_version_hash)}"></script>
47 <script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-bundle.js', ver=c.rhodecode_version_hash)}"></script>
49 48
50 49 ## CSS definitions
51 50 <%def name="css()">
@@ -5,13 +5,16 b''
5 5 <title>Error - ${c.error_message}</title>
6 6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 7 <meta name="robots" content="index, nofollow"/>
8 <link rel="icon" href="${h.asset('images/favicon.ico')}" sizes="16x16 32x32" type="image/png" />
9 8
10 9 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
11 10 %if c.redirect_time:
12 11 <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
13 12 %endif
14 13
14 <link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
15 <script src="${h.asset('js/vendors/webcomponentsjs/custom-elements-es5-adapter.js', ver=c.rhodecode_version_hash)}"></script>
16 <script src="${h.asset('js/vendors/webcomponentsjs/webcomponents-bundle.js', ver=c.rhodecode_version_hash)}"></script>
17
15 18 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
16 19 <style>body { background:#eeeeee; }</style>
17 20 <script type="text/javascript">
@@ -31,7 +34,9 b''
31 34 <span class="error-branding">
32 35 ${h.branding(c.rhodecode_name)}
33 36 </span><br/>
34 ${c.error_message} | <span class="error_message">${c.error_explanation}</span>
37 ${c.error_message}
38 <br/>
39 <span class="error_message">${c.error_explanation}</span>
35 40 </h1>
36 41 % if c.messages:
37 42 % for message in c.messages:
@@ -32,8 +32,8 b''
32 32 <div id="register" class="right-column">
33 33 <!-- login -->
34 34 <div class="sign-in-title">
35 % if social_auth_provider:
36 <h1>${_('Create an account linked with {}').format(social_auth_provider)}</h1>
35 % if external_auth_provider:
36 <h1>${_('Create an account linked with {}').format(external_auth_provider)}</h1>
37 37 % else:
38 38 <h1>${_('Create an account')}</h1>
39 39 % endif
@@ -50,7 +50,9 b''
50 50 <br />
51 51 %endif
52 52
53 % if social_auth_provider:
53 % if external_auth_provider:
54 ## store internal marker about external identity
55 ${h.hidden('external_identity', external_auth_provider)}
54 56 ## hide password prompts for social auth
55 57 <div style="display: none">
56 58 % endif
@@ -69,7 +71,7 b''
69 71 <br />
70 72 %endif
71 73
72 % if social_auth_provider:
74 % if external_auth_provider:
73 75 ## hide password prompts for social auth
74 76 </div>
75 77 % endif
@@ -45,7 +45,7 b' class RhodeCodeAuthPlugin(RhodeCodeExter'
45 45
46 46 @hybrid_property
47 47 def name(self):
48 return "external_test"
48 return u"external_test"
49 49
50 50 def settings(self):
51 51 settings = [
@@ -30,7 +30,7 b' from rhodecode.model import db'
30 30 class RcTestAuthPlugin(RhodeCodeAuthPluginBase):
31 31
32 32 def name(self):
33 return 'stub_auth'
33 return u'stub_auth'
34 34
35 35
36 36 def test_authenticate_returns_from_auth(stub_auth_data):
@@ -77,6 +77,8 b' class StubVCSController(simplevcs.Simple'
77 77 def vcscontroller(baseapp, config_stub, request_stub):
78 78 config_stub.testing_securitypolicy()
79 79 config_stub.include('rhodecode.authentication')
80 config_stub.include('rhodecode.authentication.plugins.auth_rhodecode')
81 config_stub.include('rhodecode.authentication.plugins.auth_token')
80 82
81 83 controller = StubVCSController(
82 84 baseapp.config.get_settings(), request_stub.registry)
@@ -46,7 +46,7 b' class ReviewerMock(object):'
46 46 class MemberMock(object):
47 47 def __init__(self, reviewer_def):
48 48 self.reviewer_def = reviewer_def
49 self.user_id = random.randint(1, 1024)
49 self.user_id = random.randint(1, 1024*1024)
50 50
51 51
52 52 class Statuses(object):
@@ -193,6 +193,8 b' def test_ValidPasswordsMatch(localizer):'
193 193 def test_ValidAuth(localizer, config_stub):
194 194 config_stub.testing_securitypolicy()
195 195 config_stub.include('rhodecode.authentication')
196 config_stub.include('rhodecode.authentication.plugins.auth_rhodecode')
197 config_stub.include('rhodecode.authentication.plugins.auth_token')
196 198
197 199 validator = v.ValidAuth(localizer)
198 200 valid_creds = {
@@ -310,9 +310,9 b' class TestCommits(BackendTestMixin):'
310 310 with pytest.raises(CommitDoesNotExistError):
311 311 commit.next()
312 312
313 def test_get_file_commit(self):
313 def test_get_path_commit(self):
314 314 commit = self.repo.get_commit()
315 commit.get_file_commit('file_4.txt')
315 commit.get_path_commit('file_4.txt')
316 316 assert commit.message == 'Commit 4'
317 317
318 318 def test_get_filenodes_generator(self):
@@ -571,19 +571,19 b' class TestCommitsChanges(BackendTestMixi'
571 571 assert FILEMODE_DEFAULT == commit.get_file_mode('foo/bał')
572 572 assert FILEMODE_DEFAULT == commit.get_file_mode(u'foo/bał')
573 573
574 def test_get_file_history(self):
574 def test_get_path_history(self):
575 575 commit = self.repo.get_commit()
576 history = commit.get_file_history('foo/bar')
576 history = commit.get_path_history('foo/bar')
577 577 assert len(history) == 2
578 578
579 def test_get_file_history_with_limit(self):
579 def test_get_path_history_with_limit(self):
580 580 commit = self.repo.get_commit()
581 history = commit.get_file_history('foo/bar', limit=1)
581 history = commit.get_path_history('foo/bar', limit=1)
582 582 assert len(history) == 1
583 583
584 def test_get_file_history_first_commit(self):
584 def test_get_path_history_first_commit(self):
585 585 commit = self.repo[0]
586 history = commit.get_file_history('foo/bar')
586 history = commit.get_path_history('foo/bar')
587 587 assert len(history) == 1
588 588
589 589
@@ -538,7 +538,7 b' TODO: To be written...'
538 538 'sys.exit(1)',
539 539 ]
540 540 f.write('\n'.join(script_lines))
541 os.chmod(hook_path, 0755)
541 os.chmod(hook_path, 0o755)
542 542
543 543 def test_local_push_does_not_execute_hook(self):
544 544 target_repo = self.get_empty_repo()
@@ -1061,7 +1061,7 b' class TestGitSpecificWithRepo(BackendTes'
1061 1061 FileNode('foobar/static/js/admin/base.js', content='base'),
1062 1062 FileNode(
1063 1063 'foobar/static/admin', content='admin',
1064 mode=0120000), # this is a link
1064 mode=0o120000), # this is a link
1065 1065 FileNode('foo', content='foo'),
1066 1066 ],
1067 1067 },
@@ -190,13 +190,13 b' class TestNodeBasics:'
190 190 assert not mode & stat.S_IXOTH
191 191
192 192 def test_file_node_is_executable(self):
193 node = FileNode('foobar', 'empty... almost', mode=0100755)
193 node = FileNode('foobar', 'empty... almost', mode=0o100755)
194 194 assert node.is_executable
195 195
196 node = FileNode('foobar', 'empty... almost', mode=0100500)
196 node = FileNode('foobar', 'empty... almost', mode=0o100500)
197 197 assert node.is_executable
198 198
199 node = FileNode('foobar', 'empty... almost', mode=0100644)
199 node = FileNode('foobar', 'empty... almost', mode=0o100644)
200 200 assert not node.is_executable
201 201
202 202 def test_file_node_is_not_symlink(self):
@@ -259,13 +259,13 b' class TestRepositoryGetCommonAncestor:'
259 259 commit_id1=original[0].raw_id,
260 260 commit_id2=unrelated[0].raw_id,
261 261 repo2=unrelated
262 ) == None
262 ) is None
263 263
264 264 assert original.get_common_ancestor(
265 265 commit_id1=original[-1].raw_id,
266 266 commit_id2=unrelated[-1].raw_id,
267 267 repo2=unrelated
268 ) == None
268 ) is None
269 269
270 270
271 271 @pytest.mark.backends("git", "hg")
@@ -148,15 +148,6 b' setup('
148 148 },
149 149 paster_plugins=['PasteScript'],
150 150 entry_points={
151 'enterprise.plugins1': [
152 'crowd=rhodecode.authentication.plugins.auth_crowd:plugin_factory',
153 'headers=rhodecode.authentication.plugins.auth_headers:plugin_factory',
154 'jasig_cas=rhodecode.authentication.plugins.auth_jasig_cas:plugin_factory',
155 'ldap=rhodecode.authentication.plugins.auth_ldap:plugin_factory',
156 'pam=rhodecode.authentication.plugins.auth_pam:plugin_factory',
157 'rhodecode=rhodecode.authentication.plugins.auth_rhodecode:plugin_factory',
158 'token=rhodecode.authentication.plugins.auth_token:plugin_factory',
159 ],
160 151 'paste.app_factory': [
161 152 'main=rhodecode.config.middleware:make_pyramid_app',
162 153 ],
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now