Show More
@@ -1,33 +1,33 b'' | |||
|
1 | 1 | Apache Reverse Proxy |
|
2 | 2 | ^^^^^^^^^^^^^^^^^^^^ |
|
3 | 3 | |
|
4 | 4 | Here is a sample configuration file for using Apache as a reverse proxy. |
|
5 | 5 | |
|
6 | 6 | .. code-block:: apache |
|
7 | 7 | |
|
8 | 8 | <VirtualHost *:80> |
|
9 | 9 | ServerName hg.myserver.com |
|
10 | 10 | ServerAlias hg.myserver.com |
|
11 | 11 | |
|
12 | 12 | ## uncomment to serve static files by Apache |
|
13 | ## ProxyPass /_static ! | |
|
14 | ## Alias /_static /path/to/.rccontrol/enterprise-1/static | |
|
13 | ## ProxyPass /_static/rhodecode ! | |
|
14 | ## Alias /_static/rhodecode /path/to/.rccontrol/enterprise-1/static | |
|
15 | 15 | |
|
16 | 16 | <Proxy *> |
|
17 | 17 | Order allow,deny |
|
18 | 18 | Allow from all |
|
19 | 19 | </Proxy> |
|
20 | 20 | |
|
21 | 21 | ## Important ! |
|
22 | 22 | ## Directive to properly generate url (clone url) for pylons |
|
23 | 23 | ProxyPreserveHost On |
|
24 | 24 | |
|
25 | 25 | ## RhodeCode instance running |
|
26 | 26 | ProxyPass / http://127.0.0.1:10002/ |
|
27 | 27 | ProxyPassReverse / http://127.0.0.1:10002/ |
|
28 | 28 | |
|
29 | 29 | ## to enable https use line below |
|
30 | 30 | #SetEnvIf X-Url-Scheme https HTTPS=1 |
|
31 | 31 | |
|
32 | 32 | </VirtualHost> |
|
33 | 33 |
@@ -1,92 +1,92 b'' | |||
|
1 | 1 | Nginx Configuration Example |
|
2 | 2 | --------------------------- |
|
3 | 3 | |
|
4 | 4 | Use the following example to configure Nginx as a your web server. |
|
5 | 5 | |
|
6 | 6 | .. code-block:: nginx |
|
7 | 7 | |
|
8 | 8 | upstream rc { |
|
9 | 9 | |
|
10 | 10 | server 127.0.0.1:10002; |
|
11 | 11 | |
|
12 | 12 | # add more instances for load balancing |
|
13 | 13 | # server 127.0.0.1:10003; |
|
14 | 14 | # server 127.0.0.1:10004; |
|
15 | 15 | } |
|
16 | 16 | |
|
17 | 17 | ## gist alias |
|
18 | 18 | |
|
19 | 19 | server { |
|
20 | 20 | listen 443; |
|
21 | 21 | server_name gist.myserver.com; |
|
22 | 22 | access_log /var/log/nginx/gist.access.log; |
|
23 | 23 | error_log /var/log/nginx/gist.error.log; |
|
24 | 24 | |
|
25 | 25 | ssl on; |
|
26 | 26 | ssl_certificate gist.rhodecode.myserver.com.crt; |
|
27 | 27 | ssl_certificate_key gist.rhodecode.myserver.com.key; |
|
28 | 28 | |
|
29 | 29 | ssl_session_timeout 5m; |
|
30 | 30 | |
|
31 | 31 | ssl_protocols SSLv3 TLSv1; |
|
32 | 32 | ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5; |
|
33 | 33 | ssl_prefer_server_ciphers on; |
|
34 | 34 | add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; |
|
35 | 35 | |
|
36 | 36 | # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits |
|
37 | 37 | ssl_dhparam /etc/nginx/ssl/dhparam.pem; |
|
38 | 38 | |
|
39 | 39 | rewrite ^/(.+)$ https://rhodecode.myserver.com/_admin/gists/$1; |
|
40 | 40 | rewrite (.*) https://rhodecode.myserver.com/_admin/gists; |
|
41 | 41 | } |
|
42 | 42 | |
|
43 | 43 | server { |
|
44 | 44 | listen 443; |
|
45 | 45 | server_name rhodecode.myserver.com; |
|
46 | 46 | access_log /var/log/nginx/rhodecode.access.log; |
|
47 | 47 | error_log /var/log/nginx/rhodecode.error.log; |
|
48 | 48 | |
|
49 | 49 | ssl on; |
|
50 | 50 | ssl_certificate rhodecode.myserver.com.crt; |
|
51 | 51 | ssl_certificate_key rhodecode.myserver.com.key; |
|
52 | 52 | |
|
53 | 53 | ssl_session_timeout 5m; |
|
54 | 54 | |
|
55 | 55 | ssl_protocols SSLv3 TLSv1; |
|
56 | 56 | ssl_ciphers DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA:DES-CBC3-SHA:AES128-SHA:RC4-SHA:RC4-MD5; |
|
57 | 57 | ssl_prefer_server_ciphers on; |
|
58 | 58 | |
|
59 | 59 | include /etc/nginx/proxy.conf; |
|
60 | 60 | |
|
61 | 61 | ## uncomment to serve static files by nginx |
|
62 | # location /_static { | |
|
62 | # location /_static/rhodecode { | |
|
63 | 63 | # alias /path/to/.rccontrol/enterprise-1/static; |
|
64 | 64 | # } |
|
65 | 65 | |
|
66 | 66 | ## channel stream live components |
|
67 | 67 | location /_channelstream { |
|
68 | 68 | rewrite /_channelstream/(.*) /$1 break; |
|
69 | 69 | proxy_connect_timeout 10; |
|
70 | 70 | proxy_send_timeout 10m; |
|
71 | 71 | proxy_read_timeout 10m; |
|
72 | 72 | tcp_nodelay off; |
|
73 | 73 | proxy_pass http://127.0.0.1:9800; |
|
74 | 74 | proxy_set_header Host $host; |
|
75 | 75 | proxy_set_header X-Real-IP $remote_addr; |
|
76 | 76 | proxy_set_header X-Url-Scheme $scheme; |
|
77 | 77 | proxy_set_header X-Forwarded-Proto $scheme; |
|
78 | 78 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
|
79 | 79 | gzip off; |
|
80 | 80 | proxy_http_version 1.1; |
|
81 | 81 | proxy_set_header Upgrade $http_upgrade; |
|
82 | 82 | proxy_set_header Connection "upgrade"; |
|
83 | 83 | } |
|
84 | 84 | |
|
85 | 85 | location / { |
|
86 | 86 | try_files $uri @rhode; |
|
87 | 87 | } |
|
88 | 88 | |
|
89 | 89 | location @rhode { |
|
90 | 90 | proxy_pass http://rc; |
|
91 | 91 | } |
|
92 | 92 | } |
@@ -1,395 +1,395 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | |
|
3 | 3 | # Copyright (C) 2010-2016 RhodeCode GmbH |
|
4 | 4 | # |
|
5 | 5 | # This program is free software: you can redistribute it and/or modify |
|
6 | 6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
7 | 7 | # (only), as published by the Free Software Foundation. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU Affero General Public License |
|
15 | 15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | 16 | # |
|
17 | 17 | # This program is dual-licensed. If you wish to learn more about the |
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | 21 | """ |
|
22 | 22 | Pylons middleware initialization |
|
23 | 23 | """ |
|
24 | 24 | import logging |
|
25 | 25 | |
|
26 | 26 | from paste.registry import RegistryManager |
|
27 | 27 | from paste.gzipper import make_gzip_middleware |
|
28 | 28 | from pylons.wsgiapp import PylonsApp |
|
29 | 29 | from pyramid.authorization import ACLAuthorizationPolicy |
|
30 | 30 | from pyramid.config import Configurator |
|
31 | 31 | from pyramid.static import static_view |
|
32 | 32 | from pyramid.settings import asbool, aslist |
|
33 | 33 | from pyramid.wsgi import wsgiapp |
|
34 | 34 | from pyramid.httpexceptions import HTTPError, HTTPInternalServerError |
|
35 | 35 | from pylons.controllers.util import abort, redirect |
|
36 | 36 | import pyramid.httpexceptions as httpexceptions |
|
37 | 37 | from pyramid.renderers import render_to_response, render |
|
38 | 38 | from routes.middleware import RoutesMiddleware |
|
39 | 39 | import routes.util |
|
40 | 40 | |
|
41 | 41 | import rhodecode |
|
42 | 42 | import rhodecode.integrations # do not remove this as it registers celery tasks |
|
43 | 43 | from rhodecode.config import patches |
|
44 | 44 | from rhodecode.config.routing import STATIC_FILE_PREFIX |
|
45 | 45 | from rhodecode.config.environment import ( |
|
46 | 46 | load_environment, load_pyramid_environment) |
|
47 | 47 | from rhodecode.lib.middleware import csrf |
|
48 | 48 | from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled |
|
49 | 49 | from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper |
|
50 | 50 | from rhodecode.lib.middleware.https_fixup import HttpsFixup |
|
51 | 51 | from rhodecode.lib.middleware.vcs import VCSMiddleware |
|
52 | 52 | from rhodecode.lib.plugins.utils import register_rhodecode_plugin |
|
53 | 53 | |
|
54 | 54 | |
|
55 | 55 | log = logging.getLogger(__name__) |
|
56 | 56 | |
|
57 | 57 | |
|
58 | 58 | # this is used to avoid avoid the route lookup overhead in routesmiddleware |
|
59 | 59 | # for certain routes which won't go to pylons to - eg. static files, debugger |
|
60 | 60 | # it is only needed for the pylons migration and can be removed once complete |
|
61 | 61 | class SkippableRoutesMiddleware(RoutesMiddleware): |
|
62 | 62 | """ Routes middleware that allows you to skip prefixes """ |
|
63 | 63 | |
|
64 | 64 | def __init__(self, *args, **kw): |
|
65 | 65 | self.skip_prefixes = kw.pop('skip_prefixes', []) |
|
66 | 66 | super(SkippableRoutesMiddleware, self).__init__(*args, **kw) |
|
67 | 67 | |
|
68 | 68 | def __call__(self, environ, start_response): |
|
69 | 69 | for prefix in self.skip_prefixes: |
|
70 | 70 | if environ['PATH_INFO'].startswith(prefix): |
|
71 | 71 | return self.app(environ, start_response) |
|
72 | 72 | |
|
73 | 73 | return super(SkippableRoutesMiddleware, self).__call__( |
|
74 | 74 | environ, start_response) |
|
75 | 75 | |
|
76 | 76 | |
|
77 | 77 | def make_app(global_conf, full_stack=True, static_files=True, **app_conf): |
|
78 | 78 | """Create a Pylons WSGI application and return it |
|
79 | 79 | |
|
80 | 80 | ``global_conf`` |
|
81 | 81 | The inherited configuration for this application. Normally from |
|
82 | 82 | the [DEFAULT] section of the Paste ini file. |
|
83 | 83 | |
|
84 | 84 | ``full_stack`` |
|
85 | 85 | Whether or not this application provides a full WSGI stack (by |
|
86 | 86 | default, meaning it handles its own exceptions and errors). |
|
87 | 87 | Disable full_stack when this application is "managed" by |
|
88 | 88 | another WSGI middleware. |
|
89 | 89 | |
|
90 | 90 | ``app_conf`` |
|
91 | 91 | The application's local configuration. Normally specified in |
|
92 | 92 | the [app:<name>] section of the Paste ini file (where <name> |
|
93 | 93 | defaults to main). |
|
94 | 94 | |
|
95 | 95 | """ |
|
96 | 96 | # Apply compatibility patches |
|
97 | 97 | patches.kombu_1_5_1_python_2_7_11() |
|
98 | 98 | patches.inspect_getargspec() |
|
99 | 99 | |
|
100 | 100 | # Configure the Pylons environment |
|
101 | 101 | config = load_environment(global_conf, app_conf) |
|
102 | 102 | |
|
103 | 103 | # The Pylons WSGI app |
|
104 | 104 | app = PylonsApp(config=config) |
|
105 | 105 | if rhodecode.is_test: |
|
106 | 106 | app = csrf.CSRFDetector(app) |
|
107 | 107 | |
|
108 | 108 | expected_origin = config.get('expected_origin') |
|
109 | 109 | if expected_origin: |
|
110 | 110 | # The API can be accessed from other Origins. |
|
111 | 111 | app = csrf.OriginChecker(app, expected_origin, |
|
112 | 112 | skip_urls=[routes.util.url_for('api')]) |
|
113 | 113 | |
|
114 | 114 | |
|
115 | 115 | if asbool(full_stack): |
|
116 | 116 | |
|
117 | 117 | # Appenlight monitoring and error handler |
|
118 | 118 | app, appenlight_client = wrap_in_appenlight_if_enabled(app, config) |
|
119 | 119 | |
|
120 | 120 | # we want our low level middleware to get to the request ASAP. We don't |
|
121 | 121 | # need any pylons stack middleware in them |
|
122 | 122 | app = VCSMiddleware(app, config, appenlight_client) |
|
123 | 123 | |
|
124 | 124 | # Establish the Registry for this application |
|
125 | 125 | app = RegistryManager(app) |
|
126 | 126 | |
|
127 | 127 | app.config = config |
|
128 | 128 | |
|
129 | 129 | return app |
|
130 | 130 | |
|
131 | 131 | |
|
132 | 132 | def make_pyramid_app(global_config, **settings): |
|
133 | 133 | """ |
|
134 | 134 | Constructs the WSGI application based on Pyramid and wraps the Pylons based |
|
135 | 135 | application. |
|
136 | 136 | |
|
137 | 137 | Specials: |
|
138 | 138 | |
|
139 | 139 | * We migrate from Pylons to Pyramid. While doing this, we keep both |
|
140 | 140 | frameworks functional. This involves moving some WSGI middlewares around |
|
141 | 141 | and providing access to some data internals, so that the old code is |
|
142 | 142 | still functional. |
|
143 | 143 | |
|
144 | 144 | * The application can also be integrated like a plugin via the call to |
|
145 | 145 | `includeme`. This is accompanied with the other utility functions which |
|
146 | 146 | are called. Changing this should be done with great care to not break |
|
147 | 147 | cases when these fragments are assembled from another place. |
|
148 | 148 | |
|
149 | 149 | """ |
|
150 | 150 | # The edition string should be available in pylons too, so we add it here |
|
151 | 151 | # before copying the settings. |
|
152 | 152 | settings.setdefault('rhodecode.edition', 'Community Edition') |
|
153 | 153 | |
|
154 | 154 | # As long as our Pylons application does expect "unprepared" settings, make |
|
155 | 155 | # sure that we keep an unmodified copy. This avoids unintentional change of |
|
156 | 156 | # behavior in the old application. |
|
157 | 157 | settings_pylons = settings.copy() |
|
158 | 158 | |
|
159 | 159 | sanitize_settings_and_apply_defaults(settings) |
|
160 | 160 | config = Configurator(settings=settings) |
|
161 | 161 | add_pylons_compat_data(config.registry, global_config, settings_pylons) |
|
162 | 162 | |
|
163 | 163 | load_pyramid_environment(global_config, settings) |
|
164 | 164 | |
|
165 | 165 | includeme_first(config) |
|
166 | 166 | includeme(config) |
|
167 | 167 | pyramid_app = config.make_wsgi_app() |
|
168 | 168 | pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config) |
|
169 | 169 | return pyramid_app |
|
170 | 170 | |
|
171 | 171 | |
|
172 | 172 | def add_pylons_compat_data(registry, global_config, settings): |
|
173 | 173 | """ |
|
174 | 174 | Attach data to the registry to support the Pylons integration. |
|
175 | 175 | """ |
|
176 | 176 | registry._pylons_compat_global_config = global_config |
|
177 | 177 | registry._pylons_compat_settings = settings |
|
178 | 178 | |
|
179 | 179 | |
|
180 | 180 | def webob_to_pyramid_http_response(webob_response): |
|
181 | 181 | ResponseClass = httpexceptions.status_map[webob_response.status_int] |
|
182 | 182 | pyramid_response = ResponseClass(webob_response.status) |
|
183 | 183 | pyramid_response.status = webob_response.status |
|
184 | 184 | pyramid_response.headers.update(webob_response.headers) |
|
185 | 185 | if pyramid_response.headers['content-type'] == 'text/html': |
|
186 | 186 | pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8' |
|
187 | 187 | return pyramid_response |
|
188 | 188 | |
|
189 | 189 | |
|
190 | 190 | def error_handler(exception, request): |
|
191 | 191 | # TODO: dan: replace the old pylons error controller with this |
|
192 | 192 | from rhodecode.model.settings import SettingsModel |
|
193 | 193 | from rhodecode.lib.utils2 import AttributeDict |
|
194 | 194 | |
|
195 | 195 | try: |
|
196 | 196 | rc_config = SettingsModel().get_all_settings() |
|
197 | 197 | except Exception: |
|
198 | 198 | log.exception('failed to fetch settings') |
|
199 | 199 | rc_config = {} |
|
200 | 200 | |
|
201 | 201 | base_response = HTTPInternalServerError() |
|
202 | 202 | # prefer original exception for the response since it may have headers set |
|
203 | 203 | if isinstance(exception, HTTPError): |
|
204 | 204 | base_response = exception |
|
205 | 205 | |
|
206 | 206 | c = AttributeDict() |
|
207 | 207 | c.error_message = base_response.status |
|
208 | 208 | c.error_explanation = base_response.explanation or str(base_response) |
|
209 | 209 | c.visual = AttributeDict() |
|
210 | 210 | |
|
211 | 211 | c.visual.rhodecode_support_url = ( |
|
212 | 212 | request.registry.settings.get('rhodecode_support_url') or |
|
213 | 213 | request.route_url('rhodecode_support') |
|
214 | 214 | ) |
|
215 | 215 | c.redirect_time = 0 |
|
216 | 216 | c.rhodecode_name = rc_config.get('rhodecode_title', '') |
|
217 | 217 | if not c.rhodecode_name: |
|
218 | 218 | c.rhodecode_name = 'Rhodecode' |
|
219 | 219 | |
|
220 | 220 | response = render_to_response( |
|
221 | 221 | '/errors/error_document.html', {'c': c}, request=request, |
|
222 | 222 | response=base_response) |
|
223 | 223 | |
|
224 | 224 | return response |
|
225 | 225 | |
|
226 | 226 | |
|
227 | 227 | def includeme(config): |
|
228 | 228 | settings = config.registry.settings |
|
229 | 229 | |
|
230 | 230 | # plugin information |
|
231 | 231 | config.registry.rhodecode_plugins = {} |
|
232 | 232 | |
|
233 | 233 | config.add_directive( |
|
234 | 234 | 'register_rhodecode_plugin', register_rhodecode_plugin) |
|
235 | 235 | |
|
236 | 236 | if asbool(settings.get('appenlight', 'false')): |
|
237 | 237 | config.include('appenlight_client.ext.pyramid_tween') |
|
238 | 238 | |
|
239 | 239 | # Includes which are required. The application would fail without them. |
|
240 | 240 | config.include('pyramid_mako') |
|
241 | 241 | config.include('pyramid_beaker') |
|
242 | 242 | config.include('rhodecode.admin') |
|
243 | 243 | config.include('rhodecode.authentication') |
|
244 | 244 | config.include('rhodecode.integrations') |
|
245 | 245 | config.include('rhodecode.login') |
|
246 | 246 | config.include('rhodecode.tweens') |
|
247 | 247 | config.include('rhodecode.api') |
|
248 | 248 | config.add_route( |
|
249 | 249 | 'rhodecode_support', 'https://rhodecode.com/help/', static=True) |
|
250 | 250 | |
|
251 | 251 | # Set the authorization policy. |
|
252 | 252 | authz_policy = ACLAuthorizationPolicy() |
|
253 | 253 | config.set_authorization_policy(authz_policy) |
|
254 | 254 | |
|
255 | 255 | # Set the default renderer for HTML templates to mako. |
|
256 | 256 | config.add_mako_renderer('.html') |
|
257 | 257 | |
|
258 | 258 | # include RhodeCode plugins |
|
259 | 259 | includes = aslist(settings.get('rhodecode.includes', [])) |
|
260 | 260 | for inc in includes: |
|
261 | 261 | config.include(inc) |
|
262 | 262 | |
|
263 | 263 | pylons_app = make_app( |
|
264 | 264 | config.registry._pylons_compat_global_config, |
|
265 | 265 | **config.registry._pylons_compat_settings) |
|
266 | 266 | config.registry._pylons_compat_config = pylons_app.config |
|
267 | 267 | |
|
268 | 268 | pylons_app_as_view = wsgiapp(pylons_app) |
|
269 | 269 | |
|
270 | 270 | # Protect from VCS Server error related pages when server is not available |
|
271 | 271 | vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true')) |
|
272 | 272 | if not vcs_server_enabled: |
|
273 | 273 | pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view) |
|
274 | 274 | |
|
275 | 275 | |
|
276 | 276 | def pylons_app_with_error_handler(context, request): |
|
277 | 277 | """ |
|
278 | 278 | Handle exceptions from rc pylons app: |
|
279 | 279 | |
|
280 | 280 | - old webob type exceptions get converted to pyramid exceptions |
|
281 | 281 | - pyramid exceptions are passed to the error handler view |
|
282 | 282 | """ |
|
283 | 283 | try: |
|
284 | 284 | response = pylons_app_as_view(context, request) |
|
285 | 285 | if 400 <= response.status_int <= 599: # webob type error responses |
|
286 | 286 | return error_handler( |
|
287 | 287 | webob_to_pyramid_http_response(response), request) |
|
288 | 288 | except HTTPError as e: # pyramid type exceptions |
|
289 | 289 | return error_handler(e, request) |
|
290 | 290 | except Exception: |
|
291 | 291 | if settings.get('debugtoolbar.enabled', False): |
|
292 | 292 | raise |
|
293 | 293 | return error_handler(HTTPInternalServerError(), request) |
|
294 | 294 | return response |
|
295 | 295 | |
|
296 | 296 | # This is the glue which allows us to migrate in chunks. By registering the |
|
297 | 297 | # pylons based application as the "Not Found" view in Pyramid, we will |
|
298 | 298 | # fallback to the old application each time the new one does not yet know |
|
299 | 299 | # how to handle a request. |
|
300 | 300 | config.add_notfound_view(pylons_app_with_error_handler) |
|
301 | 301 | |
|
302 | 302 | if not settings.get('debugtoolbar.enabled', False): |
|
303 | 303 | # if no toolbar, then any exception gets caught and rendered |
|
304 | 304 | config.add_view(error_handler, context=Exception) |
|
305 | 305 | |
|
306 | 306 | config.add_view(error_handler, context=HTTPError) |
|
307 | 307 | |
|
308 | 308 | |
|
309 | 309 | def includeme_first(config): |
|
310 | 310 | # redirect automatic browser favicon.ico requests to correct place |
|
311 | 311 | def favicon_redirect(context, request): |
|
312 | 312 | return redirect( |
|
313 | 313 | request.static_url('rhodecode:public/images/favicon.ico')) |
|
314 | 314 | |
|
315 | 315 | config.add_view(favicon_redirect, route_name='favicon') |
|
316 | 316 | config.add_route('favicon', '/favicon.ico') |
|
317 | 317 | |
|
318 | 318 | config.add_static_view( |
|
319 | 319 | '_static/deform', 'deform:static') |
|
320 | 320 | config.add_static_view( |
|
321 | '_static', path='rhodecode:public', cache_max_age=3600 * 24) | |
|
321 | '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24) | |
|
322 | 322 | |
|
323 | 323 | def wrap_app_in_wsgi_middlewares(pyramid_app, config): |
|
324 | 324 | """ |
|
325 | 325 | Apply outer WSGI middlewares around the application. |
|
326 | 326 | |
|
327 | 327 | Part of this has been moved up from the Pylons layer, so that the |
|
328 | 328 | data is also available if old Pylons code is hit through an already ported |
|
329 | 329 | view. |
|
330 | 330 | """ |
|
331 | 331 | settings = config.registry.settings |
|
332 | 332 | |
|
333 | 333 | # enable https redirects based on HTTP_X_URL_SCHEME set by proxy |
|
334 | 334 | pyramid_app = HttpsFixup(pyramid_app, settings) |
|
335 | 335 | |
|
336 | 336 | # Add RoutesMiddleware to support the pylons compatibility tween during |
|
337 | 337 | # migration to pyramid. |
|
338 | 338 | pyramid_app = SkippableRoutesMiddleware( |
|
339 | 339 | pyramid_app, config.registry._pylons_compat_config['routes.map'], |
|
340 | 340 | skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar')) |
|
341 | 341 | |
|
342 | 342 | if asbool(settings.get('appenlight', 'false')): |
|
343 | 343 | pyramid_app, _ = wrap_in_appenlight_if_enabled( |
|
344 | 344 | pyramid_app, config.registry._pylons_compat_config) |
|
345 | 345 | |
|
346 | 346 | if asbool(settings.get('gzip_responses', 'true')): |
|
347 | 347 | pyramid_app = make_gzip_middleware( |
|
348 | 348 | pyramid_app, settings, compress_level=1) |
|
349 | 349 | |
|
350 | 350 | return pyramid_app |
|
351 | 351 | |
|
352 | 352 | |
|
353 | 353 | def sanitize_settings_and_apply_defaults(settings): |
|
354 | 354 | """ |
|
355 | 355 | Applies settings defaults and does all type conversion. |
|
356 | 356 | |
|
357 | 357 | We would move all settings parsing and preparation into this place, so that |
|
358 | 358 | we have only one place left which deals with this part. The remaining parts |
|
359 | 359 | of the application would start to rely fully on well prepared settings. |
|
360 | 360 | |
|
361 | 361 | This piece would later be split up per topic to avoid a big fat monster |
|
362 | 362 | function. |
|
363 | 363 | """ |
|
364 | 364 | |
|
365 | 365 | # Pyramid's mako renderer has to search in the templates folder so that the |
|
366 | 366 | # old templates still work. Ported and new templates are expected to use |
|
367 | 367 | # real asset specifications for the includes. |
|
368 | 368 | mako_directories = settings.setdefault('mako.directories', [ |
|
369 | 369 | # Base templates of the original Pylons application |
|
370 | 370 | 'rhodecode:templates', |
|
371 | 371 | ]) |
|
372 | 372 | log.debug( |
|
373 | 373 | "Using the following Mako template directories: %s", |
|
374 | 374 | mako_directories) |
|
375 | 375 | |
|
376 | 376 | # Default includes, possible to change as a user |
|
377 | 377 | pyramid_includes = settings.setdefault('pyramid.includes', [ |
|
378 | 378 | 'rhodecode.lib.middleware.request_wrapper', |
|
379 | 379 | ]) |
|
380 | 380 | log.debug( |
|
381 | 381 | "Using the following pyramid.includes: %s", |
|
382 | 382 | pyramid_includes) |
|
383 | 383 | |
|
384 | 384 | # TODO: johbo: Re-think this, usually the call to config.include |
|
385 | 385 | # should allow to pass in a prefix. |
|
386 | 386 | settings.setdefault('rhodecode.api.url', '/_admin/api') |
|
387 | 387 | |
|
388 | 388 | _bool_setting(settings, 'vcs.server.enable', 'true') |
|
389 | 389 | _bool_setting(settings, 'is_test', 'false') |
|
390 | 390 | |
|
391 | 391 | return settings |
|
392 | 392 | |
|
393 | 393 | |
|
394 | 394 | def _bool_setting(settings, name, default): |
|
395 | 395 | settings[name] = asbool(settings.get(name, default)) |
@@ -1,235 +1,235 b'' | |||
|
1 | 1 | // # Copyright (C) 2010-2016 RhodeCode GmbH |
|
2 | 2 | // # |
|
3 | 3 | // # This program is free software: you can redistribute it and/or modify |
|
4 | 4 | // # it under the terms of the GNU Affero General Public License, version 3 |
|
5 | 5 | // # (only), as published by the Free Software Foundation. |
|
6 | 6 | // # |
|
7 | 7 | // # This program is distributed in the hope that it will be useful, |
|
8 | 8 | // # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
9 | 9 | // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
10 | 10 | // # GNU General Public License for more details. |
|
11 | 11 | // # |
|
12 | 12 | // # You should have received a copy of the GNU Affero General Public License |
|
13 | 13 | // # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
14 | 14 | // # |
|
15 | 15 | // # This program is dual-licensed. If you wish to learn more about the |
|
16 | 16 | // # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | 17 | // # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | 18 | |
|
19 | 19 | /** |
|
20 | 20 | * Object holding the registered pyroutes. |
|
21 | 21 | * Routes will be registered with the generated script |
|
22 | 22 | * rhodecode/public/js/rhodecode/base/pyroutes.js |
|
23 | 23 | */ |
|
24 | 24 | var PROUTES_MAP = {}; |
|
25 | 25 | |
|
26 | 26 | /** |
|
27 | 27 | * PyRoutesJS |
|
28 | 28 | * |
|
29 | 29 | * Usage pyroutes.url('mark_error_fixed',{"error_id":error_id}) // /mark_error_fixed/<error_id> |
|
30 | 30 | */ |
|
31 | 31 | var pyroutes = (function() { |
|
32 | 32 | // access global map defined in special file pyroutes |
|
33 | 33 | var matchlist = PROUTES_MAP; |
|
34 | 34 | var sprintf = (function() { |
|
35 | 35 | function get_type(variable) { |
|
36 | 36 | return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); |
|
37 | 37 | } |
|
38 | 38 | function str_repeat(input, multiplier) { |
|
39 | 39 | for (var output = []; multiplier > 0; output[--multiplier] = input) { |
|
40 | 40 | /* do nothing */ |
|
41 | 41 | } |
|
42 | 42 | return output.join(''); |
|
43 | 43 | } |
|
44 | 44 | var str_format = function() { |
|
45 | 45 | if (!str_format.cache.hasOwnProperty(arguments[0])) { |
|
46 | 46 | str_format.cache[arguments[0]] = str_format.parse(arguments[0]); |
|
47 | 47 | } |
|
48 | 48 | return str_format.format.call(null, str_format.cache[arguments[0]], arguments); |
|
49 | 49 | }; |
|
50 | 50 | |
|
51 | 51 | str_format.format = function(parse_tree, argv) { |
|
52 | 52 | var cursor = 1, |
|
53 | 53 | tree_length = parse_tree.length, |
|
54 | 54 | node_type = '', |
|
55 | 55 | arg, |
|
56 | 56 | output = [], |
|
57 | 57 | i, k, |
|
58 | 58 | match, |
|
59 | 59 | pad, |
|
60 | 60 | pad_character, |
|
61 | 61 | pad_length; |
|
62 | 62 | for (i = 0; i < tree_length; i++) { |
|
63 | 63 | node_type = get_type(parse_tree[i]); |
|
64 | 64 | if (node_type === 'string') { |
|
65 | 65 | output.push(parse_tree[i]); |
|
66 | 66 | } |
|
67 | 67 | else if (node_type === 'array') { |
|
68 | 68 | match = parse_tree[i]; // convenience purposes only |
|
69 | 69 | if (match[2]) { // keyword argument |
|
70 | 70 | arg = argv[cursor]; |
|
71 | 71 | for (k = 0; k < match[2].length; k++) { |
|
72 | 72 | if (!arg.hasOwnProperty(match[2][k])) { |
|
73 | 73 | throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); |
|
74 | 74 | } |
|
75 | 75 | arg = arg[match[2][k]]; |
|
76 | 76 | } |
|
77 | 77 | } |
|
78 | 78 | else if (match[1]) { // positional argument (explicit) |
|
79 | 79 | arg = argv[match[1]]; |
|
80 | 80 | } |
|
81 | 81 | else { // positional argument (implicit) |
|
82 | 82 | arg = argv[cursor++]; |
|
83 | 83 | } |
|
84 | 84 | |
|
85 | 85 | if (/[^s]/.test(match[8]) && (get_type(arg) !== 'number')) { |
|
86 | 86 | throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); |
|
87 | 87 | } |
|
88 | 88 | switch (match[8]) { |
|
89 | 89 | case 'b': arg = arg.toString(2); break; |
|
90 | 90 | case 'c': arg = String.fromCharCode(arg); break; |
|
91 | 91 | case 'd': arg = parseInt(arg, 10); break; |
|
92 | 92 | case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; |
|
93 | 93 | case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; |
|
94 | 94 | case 'o': arg = arg.toString(8); break; |
|
95 | 95 | case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); |
|
96 | 96 | break; |
|
97 | 97 | case 'u': arg = Math.abs(arg); break; |
|
98 | 98 | case 'x': arg = arg.toString(16); break; |
|
99 | 99 | case 'X': arg = arg.toString(16).toUpperCase(); break; |
|
100 | 100 | } |
|
101 | 101 | arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); |
|
102 | 102 | pad_character = |
|
103 | 103 | match[4] ? match[4] === '0' ? '0' : match[4].charAt(1) : ' '; |
|
104 | 104 | pad_length = match[6] - String(arg).length; |
|
105 | 105 | pad = match[6] ? str_repeat(pad_character, pad_length) : ''; |
|
106 | 106 | output.push(match[5] ? arg + pad : pad + arg); |
|
107 | 107 | } |
|
108 | 108 | } |
|
109 | 109 | return output.join(''); |
|
110 | 110 | }; |
|
111 | 111 | |
|
112 | 112 | str_format.cache = {}; |
|
113 | 113 | |
|
114 | 114 | str_format.parse = function(fmt) { |
|
115 | 115 | var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; |
|
116 | 116 | while (_fmt) { |
|
117 | 117 | if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { |
|
118 | 118 | parse_tree.push(match[0]); |
|
119 | 119 | } |
|
120 | 120 | else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { |
|
121 | 121 | parse_tree.push('%'); |
|
122 | 122 | } |
|
123 | 123 | else if ( |
|
124 | 124 | (match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { |
|
125 | 125 | if (match[2]) { |
|
126 | 126 | arg_names |= 1; |
|
127 | 127 | var field_list = [], replacement_field = match[2], field_match = []; |
|
128 | 128 | if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { |
|
129 | 129 | field_list.push(field_match[1]); |
|
130 | 130 | while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { |
|
131 | 131 | if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { |
|
132 | 132 | field_list.push(field_match[1]); |
|
133 | 133 | } |
|
134 | 134 | else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { |
|
135 | 135 | field_list.push(field_match[1]); |
|
136 | 136 | } |
|
137 | 137 | else { |
|
138 | 138 | throw('[sprintf] huh?'); |
|
139 | 139 | } |
|
140 | 140 | } |
|
141 | 141 | } |
|
142 | 142 | else { |
|
143 | 143 | throw('[sprintf] huh?'); |
|
144 | 144 | } |
|
145 | 145 | match[2] = field_list; |
|
146 | 146 | } |
|
147 | 147 | else { |
|
148 | 148 | arg_names |= 2; |
|
149 | 149 | } |
|
150 | 150 | if (arg_names === 3) { |
|
151 | 151 | throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); |
|
152 | 152 | } |
|
153 | 153 | parse_tree.push(match); |
|
154 | 154 | } |
|
155 | 155 | else { |
|
156 | 156 | throw('[sprintf] huh?'); |
|
157 | 157 | } |
|
158 | 158 | _fmt = _fmt.substring(match[0].length); |
|
159 | 159 | } |
|
160 | 160 | return parse_tree; |
|
161 | 161 | }; |
|
162 | 162 | return str_format; |
|
163 | 163 | })(); |
|
164 | 164 | |
|
165 | 165 | var vsprintf = function(fmt, argv) { |
|
166 | 166 | argv.unshift(fmt); |
|
167 | 167 | return sprintf.apply(null, argv); |
|
168 | 168 | }; |
|
169 | 169 | return { |
|
170 | 170 | 'asset': function(path, ver) { |
|
171 | var asset_url = ASSET_URL || '/_static/'; | |
|
171 | var asset_url = ASSET_URL || '/_static/rhodecode/'; | |
|
172 | 172 | var ret = asset_url + path; |
|
173 | 173 | if (ver !== undefined) { |
|
174 | 174 | ret += '?ver=' + ver; |
|
175 | 175 | } |
|
176 | 176 | return ret; |
|
177 | 177 | }, |
|
178 | 178 | 'url': function(route_name, params) { |
|
179 | 179 | var result = route_name; |
|
180 | 180 | if (typeof(params) !== 'object'){ |
|
181 | 181 | params = {}; |
|
182 | 182 | } |
|
183 | 183 | if (matchlist.hasOwnProperty(route_name)) { |
|
184 | 184 | var route = matchlist[route_name]; |
|
185 | 185 | // param substitution |
|
186 | 186 | for(var i=0; i < route[1].length; i++) { |
|
187 | 187 | var param_name = route[1][i]; |
|
188 | 188 | if (!params.hasOwnProperty(param_name)) |
|
189 | 189 | throw new Error( |
|
190 | 190 | 'parameter '+ |
|
191 | 191 | param_name + |
|
192 | 192 | ' is missing in route"' + |
|
193 | 193 | route_name + '" generation'); |
|
194 | 194 | } |
|
195 | 195 | result = sprintf(route[0], params); |
|
196 | 196 | |
|
197 | 197 | var ret = []; |
|
198 | 198 | // extra params => GET |
|
199 | 199 | for (var param in params){ |
|
200 | 200 | if (route[1].indexOf(param) === -1){ |
|
201 | 201 | ret.push(encodeURIComponent(param) + "=" + |
|
202 | 202 | encodeURIComponent(params[param])); |
|
203 | 203 | } |
|
204 | 204 | } |
|
205 | 205 | var _parts = ret.join("&"); |
|
206 | 206 | if(_parts){ |
|
207 | 207 | result = result +'?'+ _parts; |
|
208 | 208 | } |
|
209 | 209 | if(APPLICATION_URL) { |
|
210 | 210 | result = APPLICATION_URL + result; |
|
211 | 211 | } |
|
212 | 212 | } |
|
213 | 213 | |
|
214 | 214 | return result; |
|
215 | 215 | }, |
|
216 | 216 | 'register': function(route_name, route_tmpl, req_params) { |
|
217 | 217 | if (typeof(req_params) !== 'object') { |
|
218 | 218 | req_params = []; |
|
219 | 219 | } |
|
220 | 220 | // fix escape |
|
221 | 221 | route_tmpl = unescape(route_tmpl); |
|
222 | 222 | keys = []; |
|
223 | 223 | for(var i=0; i < req_params.length; i++) { |
|
224 | 224 | keys.push(req_params[i]); |
|
225 | 225 | } |
|
226 | 226 | matchlist[route_name] = [ |
|
227 | 227 | route_tmpl, |
|
228 | 228 | keys |
|
229 | 229 | ]; |
|
230 | 230 | }, |
|
231 | 231 | '_routes': function(){ |
|
232 | 232 | return matchlist; |
|
233 | 233 | } |
|
234 | 234 | }; |
|
235 | 235 | })(); |
@@ -1,545 +1,545 b'' | |||
|
1 | 1 | ## -*- coding: utf-8 -*- |
|
2 | 2 | <%inherit file="/debug_style/index.html"/> |
|
3 | 3 | |
|
4 | 4 | <%def name="breadcrumbs_links()"> |
|
5 | 5 | ${h.link_to(_('Style'), h.url('debug_style_home'))} |
|
6 | 6 | » |
|
7 | 7 | ${c.active} |
|
8 | 8 | </%def> |
|
9 | 9 | |
|
10 | 10 | |
|
11 | 11 | <%def name="real_main()"> |
|
12 | 12 | <div class="box"> |
|
13 | 13 | <div class="title"> |
|
14 | 14 | ${self.breadcrumbs()} |
|
15 | 15 | </div> |
|
16 | 16 | |
|
17 | 17 | <div class='sidebar-col-wrapper'> |
|
18 | 18 | ##main |
|
19 | 19 | ${self.sidebar()} |
|
20 | 20 | |
|
21 | 21 | <div class="main-content"> |
|
22 | 22 | |
|
23 | 23 | <div style="opacity:.5"> |
|
24 | 24 | |
|
25 | 25 | <h2>Simple tables</h2> |
|
26 | 26 | |
|
27 | 27 | <p>These styles will be adjusted later to provide a baseline style |
|
28 | 28 | for all tables without classes added, whether part of the |
|
29 | 29 | application or not. Currently, some of the |
|
30 | 30 | application-specific styles are applied to this table.</p> |
|
31 | 31 | <p>This is a baseline style for all tables, whether part of the |
|
32 | 32 | application or not. It has no class applied for styling. Use |
|
33 | 33 | the "rctable" class as outlined before for tables which are |
|
34 | 34 | part of the RhodeCode application.</p> |
|
35 | 35 | <table> |
|
36 | 36 | <tbody> |
|
37 | 37 | <tr> |
|
38 | 38 | <th>Header A</th> |
|
39 | 39 | <th>Header B</th> |
|
40 | 40 | <th>Header C</th> |
|
41 | 41 | <th>Header D</th> |
|
42 | 42 | </tr> |
|
43 | 43 | <tr> |
|
44 | 44 | <td>Content of col A</td> |
|
45 | 45 | <td>Content of col B</td> |
|
46 | 46 | <td>Content of col C</td> |
|
47 | 47 | <td>Content of col D</td> |
|
48 | 48 | </tr> |
|
49 | 49 | <tr> |
|
50 | 50 | <td>Content of col A</td> |
|
51 | 51 | <td>Content of col B</td> |
|
52 | 52 | <td>Content of col C</td> |
|
53 | 53 | <td>Content of col D</td> |
|
54 | 54 | </tr> |
|
55 | 55 | <tr> |
|
56 | 56 | <td>Content of col A</td> |
|
57 | 57 | <td>Content of col B</td> |
|
58 | 58 | <td>Content of col C</td> |
|
59 | 59 | <td>Content of col D</td> |
|
60 | 60 | </tr> |
|
61 | 61 | <tr> |
|
62 | 62 | <td>Content of col A</td> |
|
63 | 63 | <td>Content of col B</td> |
|
64 | 64 | <td>Content of col C</td> |
|
65 | 65 | <td>Content of col D</td> |
|
66 | 66 | </tr> |
|
67 | 67 | </tbody> |
|
68 | 68 | </table> |
|
69 | 69 | </div> |
|
70 | 70 | |
|
71 | 71 | |
|
72 | 72 | |
|
73 | 73 | |
|
74 | 74 | <h2>RC application table with examples</h2> |
|
75 | 75 | |
|
76 | 76 | <p>This is a standard table which applies the rhodecode-specific styling to be used |
|
77 | 77 | throughout the application; it has <code><table class="rctable"></code>. |
|
78 | 78 | <br/> |
|
79 | 79 | By default, table data is not truncated, and wraps inside of the <code><td> |
|
80 | 80 | ;</code>. To prevent wrapping and contain data on one line, use the <code>< |
|
81 | 81 | class="truncate-wrap"></code> on the <code><td></code>, and <code>span |
|
82 | 82 | class="truncate"</code> around the specific data to be truncated. |
|
83 | 83 | </p> |
|
84 | 84 | <p> |
|
85 | 85 | Ellipsis is added via CSS. Please always add a row of headers using <code><th |
|
86 | 86 | ></code> to the top of a table. |
|
87 | 87 | </p> |
|
88 | 88 | |
|
89 | 89 | ## TODO: johbo: in case we have more tables with examples, we should |
|
90 | 90 | ## create a generic class here. |
|
91 | 91 | <table class="rctable issuetracker"> |
|
92 | 92 | <thead> |
|
93 | 93 | <tr> |
|
94 | 94 | <th>Header A</th> |
|
95 | 95 | <th>Header B</th> |
|
96 | 96 | <th>Header C</th> |
|
97 | 97 | <th>Header D</th> |
|
98 | 98 | </tr> |
|
99 | 99 | </thead> |
|
100 | 100 | <tbody> |
|
101 | 101 | <tr> |
|
102 | 102 | <td class="issue-tracker-example"> |
|
103 | 103 | Example of col A |
|
104 | 104 | </td> |
|
105 | 105 | <td class="issue-tracker-example"> |
|
106 | 106 | Example of col B |
|
107 | 107 | </td> |
|
108 | 108 | <td class="issue-tracker-example"> |
|
109 | 109 | Example of col C |
|
110 | 110 | </td> |
|
111 | 111 | <td class="issue-tracker-example"> |
|
112 | 112 | Example of col D |
|
113 | 113 | </td> |
|
114 | 114 | </tr> |
|
115 | 115 | <tr> |
|
116 | 116 | <td>Content of col A</td> |
|
117 | 117 | <td>Content of col B</td> |
|
118 | 118 | <td>Content of col C which is very long and will not be |
|
119 | 119 | truncated because sometimes people just want to write |
|
120 | 120 | really, really long commit messages which explain what |
|
121 | 121 | they did in excruciating detail and you really, really |
|
122 | 122 | want to read them.</td> |
|
123 | 123 | <td>Content of col D</td> |
|
124 | 124 | </tr> |
|
125 | 125 | <tr> |
|
126 | 126 | <td>Content of col A</td> |
|
127 | 127 | <td>Content of col B</td> |
|
128 | 128 | <td>Content of col C</td> |
|
129 | 129 | <td class="truncate-wrap"><span class="truncate">Truncated |
|
130 | 130 | content of column D truncate truncate truncatetruncate |
|
131 | 131 | truncate truncate</span></td> |
|
132 | 132 | </tr> |
|
133 | 133 | </tbody> |
|
134 | 134 | </table> |
|
135 | 135 | |
|
136 | 136 | <h2>RC application table data classes</h2> |
|
137 | 137 | |
|
138 | 138 | <p>The following tables contain documentation of all existing table data classes. |
|
139 | 139 | Please update when new classes are made. |
|
140 | 140 | </p> |
|
141 | 141 | <table class="rctable examples"> |
|
142 | 142 | <thead> |
|
143 | 143 | <tr> |
|
144 | 144 | <th>Class</th> |
|
145 | 145 | <th>Description</th> |
|
146 | 146 | <th>Example</th> |
|
147 | 147 | </tr> |
|
148 | 148 | </thead> |
|
149 | 149 | <tbody> |
|
150 | 150 | <td>td-user</td> |
|
151 | 151 | <td>Any username/gravatar combination (see also Icons style).</td> |
|
152 | 152 | <td class="td-user author"> |
|
153 | 153 | <img class="gravatar" alt="gravatar" src="https://secure.gravatar.com/avatar/0c9a7e6674b6f0b35d98dbe073e3f0ab?d=identicon&s=32" height="16" width="16"> |
|
154 | 154 | <span title="Oliver Strobel <oliver@rhodecode.com>" class="user">ostrobel (Oliver Strobel)</span> |
|
155 | 155 | </td> |
|
156 | 156 | </tr> |
|
157 | 157 | <tr> |
|
158 | 158 | <td>td-hash</td> |
|
159 | 159 | <td>Any hash; a commit, revision, etc. Use <code><pre></code> and header 'Commit'</td> |
|
160 | 160 | <td class="td-commit"> |
|
161 | 161 | <pre><a href="/anothercpythonforkkkk/files/8d6b27837c6979983b037693fe975cdbb761b500/">r93699:8d6b27837c69</a></pre> |
|
162 | 162 | </td> |
|
163 | 163 | </tr> |
|
164 | 164 | <tr> |
|
165 | 165 | <td>td-rss</td> |
|
166 | 166 | <td>RSS feed link icon</td> |
|
167 | 167 | <td class="td-rss"> |
|
168 | 168 | <a title="Subscribe to rss feed" href="/feed/rss"><i class="icon-rss-sign"></i></a> |
|
169 | 169 | </td> |
|
170 | 170 | </tr> |
|
171 | 171 | <tr> |
|
172 | 172 | <td>td-componentname</td> |
|
173 | 173 | <td>Any group, file, gist, or directory name.</td> |
|
174 | 174 | <td class="td-componentname"> |
|
175 | 175 | <a href="/cpythonfork"> |
|
176 | 176 | <span title="Mercurial repository"><i class="icon-hg"></i></span> |
|
177 | 177 | <i class="icon-unlock-alt" title="Public repository"></i> |
|
178 | 178 | rhodecode-dev-restyle-fork |
|
179 | 179 | </a> |
|
180 | 180 | </td> |
|
181 | 181 | </tr> |
|
182 | 182 | <tr> |
|
183 | 183 | <td>td-tags</td> |
|
184 | 184 | <td>Any cell containing tags, including branches and bookmarks.</td> |
|
185 | 185 | <td class="td-tags"> |
|
186 | 186 | <span class="branchtag tag" title="Branch default"> |
|
187 | 187 | <a href="/rhodecode-dev-restyle- fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a> |
|
188 | 188 | </span> |
|
189 | 189 | </td> |
|
190 | 190 | </tr> |
|
191 | 191 | <tr> |
|
192 | 192 | <td>tags-truncate</td> |
|
193 | 193 | <td>Used to truncate a cell containing tags; avoid if possible.</td> |
|
194 | 194 | <td class="td-tags truncate-wrap"> |
|
195 | 195 | <div class="truncate tags-truncate"> |
|
196 | 196 | <div class="autoexpand"> |
|
197 | 197 | <span class="tagtag tag" title="Tag tip"> |
|
198 | 198 | <a href="/rhodecode-dev-restyle-fork/files/e519d5a0e71466d27257ddff921c4a13c540408e/"><i class="icon-tag"></i>tip</a> |
|
199 | 199 | </span> |
|
200 | 200 | <span class="branchtag tag" title="Branch default"> |
|
201 | 201 | <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a> |
|
202 | 202 | </span> |
|
203 | 203 | <span class="branchtag tag" title="Branch default"> |
|
204 | 204 | <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a> |
|
205 | 205 | </span> |
|
206 | 206 | </div> |
|
207 | 207 | </div> |
|
208 | 208 | </td> |
|
209 | 209 | </tr> |
|
210 | 210 | <tr> |
|
211 | 211 | <td>td-ip</td> |
|
212 | 212 | <td>Any ip address.</td> |
|
213 | 213 | <td class="td-ip"> |
|
214 | 214 | 172.16.115.168 |
|
215 | 215 | </td> |
|
216 | 216 | </tr> |
|
217 | 217 | <tr> |
|
218 | 218 | <td>td-type</td> |
|
219 | 219 | <td>A state or an auth type.</td> |
|
220 | 220 | <td class="td-type"> |
|
221 | 221 | rhodecode |
|
222 | 222 | </td> |
|
223 | 223 | </tr> |
|
224 | 224 | <tr> |
|
225 | 225 | <td>td-authtoken</td> |
|
226 | 226 | <td>For auth tokens. Use truncate classes for hover expand; see html.</td> |
|
227 | 227 | <td class="truncate-wrap td-authtoken"> |
|
228 | 228 | <div class="truncate autoexpand"> |
|
229 | 229 | <code>688df65b87d3ad16ae9f8fc6338a551d40f41c7a</code> |
|
230 | 230 | </div> |
|
231 | 231 | </td> |
|
232 | 232 | </tr> |
|
233 | 233 | <tr> |
|
234 | 234 | <td>td-action</td> |
|
235 | 235 | <td>Buttons which perform an action.</td> |
|
236 | 236 | <td class="td-action"> |
|
237 | 237 | <div class="grid_edit"> |
|
238 | 238 | <a href="/_admin/users/2/edit" title="edit"> |
|
239 | 239 | <i class="icon-pencil"></i>Edit</a> |
|
240 | 240 | </div> |
|
241 | 241 | <div class="grid_delete"> |
|
242 | 242 | <form action="/_admin/users/2" method="post"> |
|
243 | 243 | <i class="icon-remove-sign"></i> |
|
244 | 244 | <input class="btn btn-danger btn-link" id="remove_user_2" name="remove_" type="submit" value="delete"> |
|
245 | 245 | </form> |
|
246 | 246 | </div> |
|
247 | 247 | </td> |
|
248 | 248 | </tr> |
|
249 | 249 | <tr> |
|
250 | 250 | <td>td-radio</td> |
|
251 | 251 | <td>Radio buttons for a form. Centers element.</td> |
|
252 | 252 | <td class="td-radio"> |
|
253 | 253 | <input type="radio" checked="checked" value="" name="1" id="read"></td> |
|
254 | 254 | </tr> |
|
255 | 255 | <tr> |
|
256 | 256 | <td>td-checkbox</td> |
|
257 | 257 | <td>Checkbox for a form. Centers element.</td> |
|
258 | 258 | <td class="td-checkbox"> |
|
259 | 259 | <input type="checkbox" checked="checked" value="" name="1" id="read"></td> |
|
260 | 260 | </tr> |
|
261 | 261 | <tr> |
|
262 | 262 | <tr> |
|
263 | 263 | <td>td-buttons</td> |
|
264 | 264 | <td>Buttons.</td> |
|
265 | 265 | <td class="td-buttons"> |
|
266 | 266 | <span class="btn btn-mini btn-primary">feed access</span> |
|
267 | 267 | </td> |
|
268 | 268 | </tr> |
|
269 | 269 | <tr> |
|
270 | 270 | <td>td-compare</td> |
|
271 | 271 | <td>Radio buttons to compare commits.</td> |
|
272 | 272 | <td class=" td-compare"> |
|
273 | 273 | <input class="compare-radio-button" type="radio" name="compare_source" value="2.0"> |
|
274 | 274 | <input class="compare-radio-button" type="radio" name="compare_target" value="2.0"> |
|
275 | 275 | </td> |
|
276 | 276 | </tr> |
|
277 | 277 | <tr> |
|
278 | 278 | <td>td-comments</td> |
|
279 | 279 | <td>Comments indicator icon.</td> |
|
280 | 280 | <td> |
|
281 | 281 | <i class="icon-comment icon-comment-colored"></i> 0 |
|
282 | 282 | </td> |
|
283 | 283 | </tr> |
|
284 | 284 | <tr> |
|
285 | 285 | <td>td-status</td> |
|
286 | 286 | <td>Status indicator icon.</td> |
|
287 | 287 | <td class="td-description"> |
|
288 | 288 | <div class="flag_status under_review pull-left"></div> |
|
289 | 289 | </td> |
|
290 | 290 | </tr> |
|
291 | 291 | </tbody> |
|
292 | 292 | </table> |
|
293 | 293 | <table class="dataTable rctable examples"> |
|
294 | 294 | <tbody> |
|
295 | 295 | <tr> |
|
296 | 296 | <td>quick_repo_menu</td> |
|
297 | 297 | <td>Hidden menu generated by dataTable.</td> |
|
298 | 298 | <td class="quick_repo_menu"> |
|
299 | 299 | <i class="pointer icon-more"></i> |
|
300 | 300 | <div class="menu_items_container" style="display: none;"> |
|
301 | 301 | <ul class="menu_items"> |
|
302 | 302 | <li> |
|
303 | 303 | <a title="Summary" href="/anothercpythonforkkkk-fork"> |
|
304 | 304 | <span>Summary</span> |
|
305 | 305 | </a> |
|
306 | 306 | </li> |
|
307 | 307 | <li> |
|
308 | 308 | <a title="Changelog" href="/anothercpythonforkkkk-fork/changelog"> |
|
309 | 309 | <span>Changelog</span> |
|
310 | 310 | </a> |
|
311 | 311 | </li> |
|
312 | 312 | <li> |
|
313 | 313 | <a title="Files" href="/anothercpythonforkkkk-fork/files/tip/"> |
|
314 | 314 | <span>Files</span> |
|
315 | 315 | </a> |
|
316 | 316 | </li> |
|
317 | 317 | <li> |
|
318 | 318 | <a title="Fork" href="/anothercpythonforkkkk-fork/fork"> |
|
319 | 319 | <span>Fork</span> |
|
320 | 320 | </a> |
|
321 | 321 | </li> |
|
322 | 322 | </ul> |
|
323 | 323 | </div> |
|
324 | 324 | </td> |
|
325 | 325 | <td></td> |
|
326 | 326 | </tr> |
|
327 | 327 | </tbody> |
|
328 | 328 | </table> |
|
329 | 329 | <script>quick_repo_menu();</script> |
|
330 | 330 | <table class="rctable examples"> |
|
331 | 331 | <tbody> |
|
332 | 332 | <tr> |
|
333 | 333 | <td>td-description</td> |
|
334 | 334 | <td>Any description. They may be rather long, and using the expand_commit outlined below is recommended.</td> |
|
335 | 335 | <td class="td-description"> |
|
336 | 336 | Ultrices mattis! Enim pellentesque lacus, sit magna natoque risus turpis ut, auctor ultrices facilisis dapibus odio? Parturient! Porta egestas nascetur, quis, elementum dolor, in magna ac dis sit etiam turpis, scelerisque! Integer tristique aliquam. |
|
337 | 337 | </td> |
|
338 | 338 | </tr> |
|
339 | 339 | </tbody> |
|
340 | 340 | </table> |
|
341 | 341 | <table id="changesets" class="rctable examples end"> |
|
342 | 342 | <tbody> |
|
343 | 343 | <tr> |
|
344 | 344 | <td>expand_commit</td> |
|
345 | 345 | <td>Expands a long message; see html+js.</td> |
|
346 | 346 | <td class="expand_commit" data-commit-id="2ffc6faabc7a9c790b1b452943a3f0c047b8b436" title="Expand commit message"> |
|
347 | 347 | <div class="show_more_col"> |
|
348 | 348 | <i class="show_more"></i> |
|
349 | 349 | </div> |
|
350 | 350 | </td> |
|
351 | 351 | <td class="mid td-description"> |
|
352 | 352 | <div class="log-container truncate-wrap"> |
|
353 | 353 | <div id="c-2ffc6faabc7a9c790b1b452943a3f0c047b8b436" class="message truncate" data-message-raw="tests: Test echo method on the server object |
|
354 | 354 | |
|
355 | 355 | This only works for Pyro4 so far, have to extend it still for HTTP to work.">tests: Test echo method on the server object |
|
356 | 356 | |
|
357 | 357 | This only works for Pyro4 so far, have to extend it still for HTTP to work.</div> |
|
358 | 358 | </div> |
|
359 | 359 | </td> |
|
360 | 360 | </tr> |
|
361 | 361 | </tbody> |
|
362 | 362 | </table> |
|
363 | 363 | <script type="text/javascript"> |
|
364 | 364 | var cache = {} |
|
365 | 365 | $('.expand_commit').on('click',function(e){ |
|
366 | 366 | var target_expand = $(this); |
|
367 | 367 | var cid = target_expand.data('commitId'); |
|
368 | 368 | |
|
369 | 369 | if (target_expand.hasClass('open')){ |
|
370 | 370 | $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'}); |
|
371 | 371 | $('#t-'+cid).css({'height': '1.5em', 'max-height': '1.5em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'}); |
|
372 | 372 | target_expand.removeClass('open'); |
|
373 | 373 | } |
|
374 | 374 | else { |
|
375 | 375 | $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'}); |
|
376 | 376 | $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'}); |
|
377 | 377 | target_expand.addClass('open'); |
|
378 | 378 | } |
|
379 | 379 | }); |
|
380 | 380 | |
|
381 | 381 | </script> |
|
382 | 382 | <p>The following classes currently do not have unique styles applied.</p> |
|
383 | 383 | <table class="rctable examples end"> |
|
384 | 384 | <tbody> |
|
385 | 385 | <tr> |
|
386 | 386 | <td>td-regex</td> |
|
387 | 387 | <td>Regex patterns</td> |
|
388 | 388 | <td class="td-regex">(?:#)(?P<issue_id>\d+)</td> |
|
389 | 389 | </tr> |
|
390 | 390 | <tr> |
|
391 | 391 | <td>td-url</td> |
|
392 | 392 | <td>Any URL.</td> |
|
393 | 393 | <td class="td-url">https://rhodecode.com</td> |
|
394 | 394 | </tr> |
|
395 | 395 | <tr> |
|
396 | 396 | <td>td-journalaction</td> |
|
397 | 397 | <td>Action listed in a journal</td> |
|
398 | 398 | <td class="td-journalaction">started following repository supervisor-fork-4</td> |
|
399 | 399 | </tr> |
|
400 | 400 | <tr> |
|
401 | 401 | <td>td-iprange</td> |
|
402 | 402 | <td>Any ip address.</td> |
|
403 | 403 | <td class="td-ip">127.0.0.1-127.0.0.10</td> |
|
404 | 404 | </tr> |
|
405 | 405 | <tr> |
|
406 | 406 | <td>td-exp</td> |
|
407 | 407 | <td>Expiration time.</td> |
|
408 | 408 | <td class="td-exp">never</td> |
|
409 | 409 | </tr> |
|
410 | 410 | <tr> |
|
411 | 411 | <td>td-prefix</td> |
|
412 | 412 | <td>Prefixes outlined in settings.</td> |
|
413 | 413 | <td class="td-prefix">ubuntu-92539</td> |
|
414 | 414 | </tr> |
|
415 | 415 | <tr> |
|
416 | 416 | <td>td-cachekey</td> |
|
417 | 417 | <td>Cache key value.</td> |
|
418 | 418 | <td class="td-cachekey">ubuntu-92539supervisor</td> |
|
419 | 419 | </tr> |
|
420 | 420 | <tr> |
|
421 | 421 | <td>td-email</td> |
|
422 | 422 | <td>Any email address.</td> |
|
423 | 423 | <td class="td-email">example@rhodecode.com</td> |
|
424 | 424 | </tr> |
|
425 | 425 | <tr> |
|
426 | 426 | <td>td-active</td> |
|
427 | 427 | <td>Shows active state with icon-true/icon-false.</td> |
|
428 | 428 | <td class="td-active"><i class="icon-false"></i></td> |
|
429 | 429 | </tr> |
|
430 | 430 | <tr> |
|
431 | 431 | <td>td-size</td> |
|
432 | 432 | <td>File, repo, or directory size.</td> |
|
433 | 433 | <td class="td-size">89 MB</td> |
|
434 | 434 | </tr> |
|
435 | 435 | <tr> |
|
436 | 436 | <td>td-number</td> |
|
437 | 437 | <td>Any numerical data.</td> |
|
438 | 438 | <td class="td-number">42</td> |
|
439 | 439 | </tr> |
|
440 | 440 | <tr> |
|
441 | 441 | <td>td-message</td> |
|
442 | 442 | <td>Any commit message. Often treated with the truncate class used for descriptions as well.</td> |
|
443 | 443 | <td class="td-message">Updated the files</td> |
|
444 | 444 | </tr> |
|
445 | 445 | </tbody> |
|
446 | 446 | </table> |
|
447 | 447 | |
|
448 | 448 | |
|
449 | 449 | <h2>Permissions table</h2> |
|
450 | 450 | |
|
451 | 451 | <p> |
|
452 | 452 | This is a special-case table; it has |
|
453 | 453 | <code>table class="rctable permissions"</code> |
|
454 | 454 | where "rctable" applies the rhodecode styling as above, and |
|
455 | 455 | "permissions" adds an extra layer of customization specific to |
|
456 | 456 | permissions tables. Other special-case tables may exist or be |
|
457 | 457 | created if necessary. |
|
458 | 458 | </p> |
|
459 | 459 | |
|
460 | 460 | <table class="rctable permissions"> |
|
461 | 461 | <tr> |
|
462 | 462 | <th class="td-radio">none</th> |
|
463 | 463 | <th class="td-radio">read</th> |
|
464 | 464 | <th class="td-radio">write</th> |
|
465 | 465 | <th class="td-radio">admin</th> |
|
466 | 466 | <th>user/user group</th> |
|
467 | 467 | <th></th> |
|
468 | 468 | </tr> |
|
469 | 469 | <tr class="perm_admin_row"> |
|
470 | 470 | <td class="td-radio"><input type="radio" value="repository.none" |
|
471 | 471 | name="admin_perm_2" id="admin_perm_2_repositorynone" |
|
472 | 472 | disabled="disabled"></td> |
|
473 | 473 | <td class="td-radio"><input type="radio" value="repository.read" |
|
474 | 474 | name="admin_perm_2" id="admin_perm_2_repositoryread" |
|
475 | 475 | disabled="disabled"></td> |
|
476 | 476 | <td class="td-radio"><input type="radio" value="repository.write" |
|
477 | 477 | name="admin_perm_2" id="admin_perm_2_repositorywrite" |
|
478 | 478 | disabled="disabled"></td> |
|
479 | 479 | <td class="td-radio"><input type="radio" value="repository.admin" |
|
480 | 480 | name="admin_perm_2" id="admin_perm_2_repositoryadmin" |
|
481 | 481 | disabled="disabled" checked="checked"></td> |
|
482 | 482 | <td> |
|
483 | 483 | <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&s=32" height="16" width="16"> |
|
484 | 484 | <span class="user">dev (super admin) (owner)</span> |
|
485 | 485 | </td> |
|
486 | 486 | <td></td> |
|
487 | 487 | </tr> |
|
488 | 488 | <tr> |
|
489 | 489 | <td colspan="4"> |
|
490 | 490 | <span class="private_repo_msg"> |
|
491 | 491 | private repository |
|
492 | 492 | </span> |
|
493 | 493 | </td> |
|
494 | 494 | <td class="private_repo_msg"> |
|
495 | 495 | <i class="icon-user"></i> |
|
496 | 496 | default - only people explicitly added here will have access</td> |
|
497 | 497 | <td></td> |
|
498 | 498 | </tr> |
|
499 | 499 | <tr> |
|
500 | 500 | <td class="td-radio"><input type="radio" value="repository.none" |
|
501 | 501 | name="u_perm_1" id="u_perm_1_repositorynone"></td> |
|
502 | 502 | <td class="td-radio"><input type="radio" checked="checked" |
|
503 | 503 | value="repository.read" name="u_perm_1" |
|
504 | 504 | id="u_perm_1_repositoryread"></td> |
|
505 | 505 | <td class="td-radio"><input type="radio" value="repository.write" |
|
506 | 506 | name="u_perm_1" id="u_perm_1_repositorywrite"></td> |
|
507 | 507 | <td class="td-radio"><input type="radio" value="repository.admin" |
|
508 | 508 | name="u_perm_1" id="u_perm_1_repositoryadmin"></td> |
|
509 | 509 | <td> |
|
510 | <img class="gravatar" src="/_static/images/user30.png" height="16" width="16"> | |
|
510 | <img class="gravatar" src="/_static/rhodecode/images/user30.png" height="16" width="16"> | |
|
511 | 511 | <span class="user">default</span> |
|
512 | 512 | </td> |
|
513 | 513 | <td></td> |
|
514 | 514 | </tr> |
|
515 | 515 | <tr> |
|
516 | 516 | <td class="td-radio"><input type="radio" value="repository.none" |
|
517 | 517 | name="u_perm_2" id="u_perm_2_repositorynone"></td> |
|
518 | 518 | <td class="td-radio"><input type="radio" checked="checked" |
|
519 | 519 | value="repository.read" name="u_perm_2" |
|
520 | 520 | id="u_perm_2_repositoryread"></td> |
|
521 | 521 | <td class="td-radio"><input type="radio" value="repository.write" |
|
522 | 522 | name="u_perm_2" id="u_perm_2_repositorywrite"></td> |
|
523 | 523 | <td class="td-radio"><input type="radio" value="repository.admin" |
|
524 | 524 | name="u_perm_2" id="u_perm_2_repositoryadmin"></td> |
|
525 | 525 | <td> |
|
526 | 526 | <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&s=32" height="16" width="16"> |
|
527 | 527 | <a class="user" href="/_admin/users/2/edit">dev</a> |
|
528 | 528 | </td> |
|
529 | 529 | <td> |
|
530 | 530 | <span member_type="user" member="2" |
|
531 | 531 | class="btn action_button btn-link btn-danger">revoke</span> |
|
532 | 532 | </td> |
|
533 | 533 | </tr> |
|
534 | 534 | </tbody> |
|
535 | 535 | </table> |
|
536 | 536 | <div class="link" id="add_perm"> |
|
537 | 537 | Add new |
|
538 | 538 | </div> |
|
539 | 539 | |
|
540 | 540 | |
|
541 | 541 | |
|
542 | 542 | </div> |
|
543 | 543 | </div> |
|
544 | 544 | </div> |
|
545 | 545 | </%def> |
General Comments 0
You need to be logged in to leave comments.
Login now