general: serve all static files from /static/ (#11582)
This commit is contained in:
parent
79ad86c349
commit
80b6308f80
7
INSTALL
7
INSTALL
|
@ -33,10 +33,13 @@ package installs a init.d script automatically.
|
|||
ServerAdmin webmaster@example.com
|
||||
ServerName www.example.com
|
||||
DocumentRoot /usr/share/wcs/web/
|
||||
Alias /qo/ /usr/share/wcs/qommon/
|
||||
|
||||
SCGIMount / 127.0.0.1:3001
|
||||
<LocationMatch "^/(css|images|js|qo)/.*">
|
||||
|
||||
# this part allows serving static files directly from Apache, but it
|
||||
# requires to run wcsctl.py collectstatic first.
|
||||
Alias /static/ /var/lib/wcs/collectstatic/
|
||||
<LocationMatch "^/static">
|
||||
SCGIHandler off
|
||||
</LocationMatch>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* adapted from alto dotclear theme */
|
||||
|
||||
@import url(/qo/css/qommon.css);
|
||||
@import url(/static/css/qommon.css);
|
||||
|
||||
html, body {
|
||||
background: #CCCCCC;
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
<head>
|
||||
<title>[page_title]</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, user-scalable=0">
|
||||
<script type="text/javascript" src="[root_url]qo/js/jquery.js"></script>
|
||||
<script type="text/javascript" src="[root_url]static/xstatic/jquery.js"></script>
|
||||
[script]
|
||||
<script type="text/javascript" src="[root_url]qo/js/wcs.mobile.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="[root_url]qo/css/mobile.css"/>
|
||||
<script type="text/javascript" src="[root_url]static/js/wcs.mobile.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="[root_url]static/css/mobile.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="[theme_url]/mobile.css"/>
|
||||
</head>
|
||||
<body[if-any onload] onload="[onload]"[end]>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
@import url(../qo/css/sofresh.css);
|
||||
@import url(sofresh.css);
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>w.c.s.</title>
|
||||
<link rel="stylesheet" type="text/css" href="/css/wcs.css"/>
|
||||
<style type="text/css">
|
||||
p#wcs {
|
||||
margin-top: 30%;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p id="wcs">
|
||||
w.c.s
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -2,14 +2,20 @@
|
|||
ServerAdmin webmaster@locahost
|
||||
ServerName www.example.com
|
||||
DocumentRoot /usr/share/wcs/web/
|
||||
Alias /qo/ /usr/share/wcs/qommon/
|
||||
|
||||
SCGIMount / 127.0.0.1:3001
|
||||
<LocationMatch "^/(css|images|js|qo)/.*">
|
||||
|
||||
Alias /static/ /var/lib/wcs/collectstatic/
|
||||
<LocationMatch "^/static">
|
||||
SCGIHandler off
|
||||
</LocationMatch>
|
||||
|
||||
Alias /themes/ /usr/share/wcs/themes/
|
||||
RewriteEngine On
|
||||
RewriteCond /usr/share/wcs/%{REQUEST_URI} !-f
|
||||
RewriteCond /usr/share/wcs/%{REQUEST_URI} !-d
|
||||
RewriteRule ^/themes/(.*)$ /var/lib/wcs/%{HTTP_HOST}/themes/$1
|
||||
|
||||
CustomLog /var/log/apache2/wcs-access.log combined
|
||||
ErrorLog /var/log/apache2/wcs-error.log
|
||||
|
||||
</VirtualHost>
|
||||
|
|
|
@ -21,5 +21,8 @@ def test_loading():
|
|||
def test_collectstatic(pub):
|
||||
CmdCollectStatic.collectstatic(pub)
|
||||
assert os.path.exists(os.path.join(pub.app_dir, 'collectstatic', 'css', 'wcs.css'))
|
||||
assert os.path.exists(os.path.join(pub.app_dir, 'collectstatic', 'css', 'qommon.css'))
|
||||
assert os.path.exists(os.path.join(pub.app_dir, 'collectstatic', 'css', 'gadjo.css'))
|
||||
assert os.path.exists(os.path.join(pub.app_dir, 'collectstatic', 'xstatic', 'jquery.js'))
|
||||
CmdCollectStatic.collectstatic(pub, clear=True, link=True)
|
||||
assert os.path.islink(os.path.join(pub.app_dir, 'collectstatic', 'css', 'wcs.css'))
|
||||
|
|
|
@ -150,14 +150,14 @@ def test_advertized_site_user_access():
|
|||
assert 'authentication required' in output # locales ?
|
||||
|
||||
def test_static_directories():
|
||||
assert get_app(pub).get('/css/wcs.css')
|
||||
assert get_app(pub).get('/images/feed-icon-10x10.png')
|
||||
assert get_app(pub).get('/qo/css/qommon.css')
|
||||
assert get_app(pub).get('/static/css/wcs.css')
|
||||
assert get_app(pub).get('/static/images/feed-icon-10x10.png')
|
||||
assert get_app(pub).get('/static/css/qommon.css')
|
||||
if os.path.exists('/usr/share/javascript/leaflet/'):
|
||||
assert get_app(pub).get('/leaflet/leaflet.js')
|
||||
assert get_app(pub).get('/static/leaflet/leaflet.js')
|
||||
assert get_app(pub).get('/static/css/gadjo.css')
|
||||
assert get_app(pub).get('/static/xstatic/jquery.js')
|
||||
assert get_app(pub).get('/static/xstatic/jquery-ui.js')
|
||||
|
||||
assert 'Directory listing denied' in get_app(pub).get('/css/').body
|
||||
assert 'Directory listing denied' in get_app(pub).get('/static/css/').body
|
||||
assert get_app(pub).get('/static/xxx', status=404)
|
||||
|
|
|
@ -41,7 +41,8 @@ class CmdCollectStatic(Command):
|
|||
|
||||
@classmethod
|
||||
def collectstatic(cls, pub, clear=False, link=False):
|
||||
root_directory_class = pub.root_directory_class
|
||||
from wcs.root import StaticsDirectory
|
||||
root_directory_class = StaticsDirectory
|
||||
static_dir = os.path.join(pub.app_dir, 'collectstatic')
|
||||
if clear and os.path.exists(static_dir):
|
||||
shutil.rmtree(static_dir)
|
||||
|
|
|
@ -60,18 +60,18 @@ class HTTPResponse(quixote.http_response.HTTPResponse):
|
|||
if not self.javascript_scripts:
|
||||
self.javascript_scripts = []
|
||||
mappings = {
|
||||
'jquery.js': '../../static/xstatic/jquery.js',
|
||||
'jquery-ui.js': '../../static/xstatic/jquery-ui.js',
|
||||
'jquery.js': '../xstatic/jquery.js',
|
||||
'jquery-ui.js': '../xstatic/jquery-ui.js',
|
||||
}
|
||||
for script_name in script_names:
|
||||
mapped_script_name = mappings.get(script_name) or script_name
|
||||
if not mapped_script_name in self.javascript_scripts:
|
||||
if script_name == 'qommon.map.js':
|
||||
self.add_javascript(['jquery.js'])
|
||||
self.add_javascript(['../../leaflet/leaflet.js'])
|
||||
self.add_css_include('../../leaflet/leaflet.css')
|
||||
self.add_javascript(['../leaflet/leaflet.js'])
|
||||
self.add_css_include('../leaflet/leaflet.css')
|
||||
if script_name == 'jquery-ui.js':
|
||||
self.add_css_include('../../static/xstatic/themes/smoothness/jquery-ui.min.css')
|
||||
self.add_css_include('../xstatic/themes/smoothness/jquery-ui.min.css')
|
||||
self.javascript_scripts.append(str(mapped_script_name))
|
||||
if script_name == 'afterjob.js':
|
||||
self.add_javascript_code('var QOMMON_ROOT_URL = "%s";\n' % \
|
||||
|
@ -92,12 +92,7 @@ class HTTPResponse(quixote.http_response.HTTPResponse):
|
|||
if self.javascript_scripts:
|
||||
root_url = get_publisher().get_root_url() + get_publisher().qommon_static_dir
|
||||
s += '\n'.join(['<script type="text/javascript" src="%sjs/%s"></script>' % (
|
||||
root_url, str(x)) for x in self.javascript_scripts
|
||||
if not x[0] == '/'])
|
||||
s += '\n'
|
||||
s += '\n'.join(['<script type="text/javascript" src="%sjs/%s"></script>' % (
|
||||
get_publisher().get_root_url(), x[1:]) for x in self.javascript_scripts
|
||||
if x[0] == '/'])
|
||||
root_url, str(x)) for x in self.javascript_scripts])
|
||||
s += '\n'
|
||||
if self.javascript_code_parts:
|
||||
s += '<script type="text/javascript">'
|
||||
|
|
|
@ -81,7 +81,7 @@ class QommonPublisher(Publisher):
|
|||
unpickler_class = None
|
||||
|
||||
after_login_url = ''
|
||||
qommon_static_dir = 'qo/'
|
||||
qommon_static_dir = 'static/'
|
||||
qommon_admin_css = 'css/dc2/admin.css'
|
||||
default_theme = 'default'
|
||||
|
||||
|
|
|
@ -363,7 +363,7 @@ def decorate(body, response):
|
|||
app_label = get_publisher().get_site_option('app_label') or 'w.c.s.'
|
||||
else:
|
||||
if current_theme == 'default':
|
||||
css = root_url + 'css/%s.css' % get_publisher().APP_NAME
|
||||
css = root_url + 'static/css/%s.css' % get_publisher().APP_NAME
|
||||
else:
|
||||
css = root_url + 'themes/%s/%s.css' % (current_theme, get_publisher().APP_NAME)
|
||||
|
||||
|
|
97
wcs/root.py
97
wcs/root.py
|
@ -196,28 +196,64 @@ class RegisterDirectory(Directory):
|
|||
return errors.TraversalError()
|
||||
|
||||
|
||||
class StaticsDirectory(Directory):
|
||||
static_directories = {
|
||||
# maps /leaflet/ to the directory provided by the libjs-openlayers package
|
||||
'leaflet': ['/usr/share/javascript/leaflet'],
|
||||
'': ['web', 'qommon', 'django:gadjo'],
|
||||
'xstatic': ['xstatic:jquery', 'xstatic:jquery_ui', 'xstatic:font_awesome'],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def resolve_static_directories(cls, prefix):
|
||||
directories = cls.static_directories[prefix]
|
||||
for directory in directories:
|
||||
if directory[0] == '/':
|
||||
yield directory
|
||||
elif not ':' in directory:
|
||||
yield os.path.join(get_publisher().data_dir, directory)
|
||||
else:
|
||||
directory_type, value = directory.split(':')
|
||||
try:
|
||||
if directory_type == 'xstatic':
|
||||
module = import_module('xstatic.pkg.%s' % value)
|
||||
yield module.BASE_DIR
|
||||
elif directory_type == 'django':
|
||||
module = import_module(value)
|
||||
yield os.path.join(os.path.dirname(module.__file__), 'static')
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
def _q_traverse(self, path):
|
||||
if path[0] in self.static_directories.keys():
|
||||
prefix, rest = path[0], path[1:]
|
||||
else:
|
||||
prefix, rest = '', path
|
||||
|
||||
if not rest:
|
||||
raise errors.AccessForbiddenError()
|
||||
|
||||
for directory in self.resolve_static_directories(prefix):
|
||||
try:
|
||||
return StaticDirectory(directory, follow_symlinks=True)._q_traverse(rest)
|
||||
except errors.TraversalError:
|
||||
continue
|
||||
raise errors.TraversalError()
|
||||
|
||||
|
||||
class RootDirectory(Directory):
|
||||
_q_exports = ['admin', 'backoffice', 'forms', 'login', 'logout', 'saml',
|
||||
'ident', 'register', 'afterjobs', 'themes', 'myspace', 'user', 'roles',
|
||||
'pages', ('tmp-upload', 'tmp_upload'), 'api', '__version__',
|
||||
'tryauth', 'auth', 'preview', ('reload-top', 'reload_top'),
|
||||
'fargo', ('i18n.js', 'i18n_js')]
|
||||
'fargo', ('i18n.js', 'i18n_js'), 'static']
|
||||
|
||||
api = ApiDirectory()
|
||||
themes = template.ThemesDirectory()
|
||||
myspace = MyspaceDirectory()
|
||||
pages = qommon.pages.PagesDirectory()
|
||||
fargo = file_validation.FargoDirectory()
|
||||
|
||||
static_directories = {
|
||||
'css': ['web/css'],
|
||||
'images': ['web/images'],
|
||||
'qo': ['qommon'],
|
||||
# maps /leaflet/ to the directory provided by the libjs-openlayers package
|
||||
'leaflet': ['/usr/share/javascript/leaflet'],
|
||||
'static': ['django:gadjo'],
|
||||
'static_xstatic': ['xstatic:jquery', 'xstatic:jquery_ui', 'xstatic:font_awesome'],
|
||||
}
|
||||
static = StaticsDirectory()
|
||||
|
||||
def tryauth(self):
|
||||
return forms.root.tryauth(get_publisher().get_root_url())
|
||||
|
@ -303,9 +339,6 @@ class RootDirectory(Directory):
|
|||
if not self.backoffice:
|
||||
self.backoffice = get_publisher().backoffice_directory_class()
|
||||
|
||||
if path and path[0] in self.static_directories:
|
||||
return self.serve_statics(path)
|
||||
|
||||
try:
|
||||
return Directory._q_traverse(self, path)
|
||||
except errors.TraversalError:
|
||||
|
@ -313,42 +346,6 @@ class RootDirectory(Directory):
|
|||
|
||||
return forms.root.RootDirectory()._q_traverse(path)
|
||||
|
||||
@classmethod
|
||||
def resolve_static_directories(cls, prefix):
|
||||
directories = cls.static_directories[prefix]
|
||||
for directory in directories:
|
||||
if directory[0] == '/':
|
||||
yield directory
|
||||
elif not ':' in directory:
|
||||
yield os.path.join(get_publisher().data_dir, directory)
|
||||
else:
|
||||
directory_type, value = directory.split(':')
|
||||
try:
|
||||
if directory_type == 'xstatic':
|
||||
module = import_module('xstatic.pkg.%s' % value)
|
||||
yield module.BASE_DIR
|
||||
elif directory_type == 'django':
|
||||
module = import_module(value)
|
||||
yield os.path.join(os.path.dirname(module.__file__), 'static')
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
def serve_statics(self, path):
|
||||
if path[:2] == ['static', 'xstatic']:
|
||||
# hack path so it's easier to lookup files from xstatic modules
|
||||
# (the gadjo xstatic storage adds a "xstatic" prefix that is not on
|
||||
# the filesystem, while StaticDirectory expects the filesystem
|
||||
# layout to match exactly; so we merge the first two elements in a
|
||||
# single one, so we get the real path in path[1:])
|
||||
path = ['static_xstatic'] + path[2:]
|
||||
|
||||
for directory in self.resolve_static_directories(path[0]):
|
||||
try:
|
||||
return StaticDirectory(directory, follow_symlinks=True)._q_traverse(path[1:])
|
||||
except errors.TraversalError:
|
||||
continue
|
||||
raise errors.TraversalError()
|
||||
|
||||
def _q_lookup(self, component):
|
||||
# is this a category ?
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue