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