statics and theme management (#7070)
Templates and statics upload to organization dir
This commit is contained in:
parent
1b6c172710
commit
f4843b93ea
|
@ -23,4 +23,6 @@ METADATAS_DIR = os.path.join(VAR_DIR, 'metadatas')
|
|||
|
||||
SECRET_KEY = file('/etc/%s/secret' % PROJECT_NAME).read()
|
||||
|
||||
ORGANIZATIONS_DIR = os.path.join(VAR_DIR, 'organizations')
|
||||
|
||||
execfile(os.path.join(ETC_DIR, 'settings.py'))
|
||||
|
|
|
@ -9,10 +9,11 @@ server {
|
|||
access_log /var/log/nginx/u-auth.example.org-access.log combined;
|
||||
error_log /var/log/nginx/u-auth.example.org-error.log;
|
||||
|
||||
location ~ ^/static/(.+)$ {
|
||||
location ~ ^(.*)/static/(.+)$ {
|
||||
root /;
|
||||
try_files /var/lib/u-auth/static/$1
|
||||
/var/lib/u-auth/collectstatic/$1
|
||||
try_files /var/lib/u-auth/organizations/$1/static/$2
|
||||
/var/lib/u-auth/static/$2
|
||||
/var/lib/u-auth/collectstatic/$2
|
||||
=404;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/etc/u-auth
|
||||
/usr/lib/u-auth
|
||||
/var/lib/u-auth/organizations
|
||||
/var/lib/u-auth/collectstatic
|
||||
/var/lib/u-auth/static
|
||||
/var/lib/u-auth/templates
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.template.loader import get_template, TemplateDoesNotExist
|
||||
|
||||
def theme_base(request):
|
||||
if request.session.get('organization'):
|
||||
try:
|
||||
base = get_template('base.html', [os.path.join(settings.ORGANIZATIONS_DIR,
|
||||
request.session['organization'], 'templates')])
|
||||
except TemplateDoesNotExist:
|
||||
base = get_template('uauth/base.html')
|
||||
|
||||
return {'theme_base': base}
|
|
@ -31,3 +31,10 @@ class LocalAccountCreateForm(LocalAccountForm):
|
|||
|
||||
class UsersImportForm(forms.Form):
|
||||
users_file = forms.FileField(_('Users file'))
|
||||
|
||||
|
||||
class TemplateForm(forms.Form):
|
||||
template_file = forms.FileField(_('Template file'))
|
||||
|
||||
class StaticForm(forms.Form):
|
||||
static_file = forms.FileField(_('Static file'))
|
||||
|
|
|
@ -4,5 +4,6 @@
|
|||
{% block content %}
|
||||
<ul class="apps">
|
||||
<li class="users"><a href="{% url 'manage-users' organization.slug %}">{% trans 'Users' %}</a></li>
|
||||
<li class="theme"><a href="{% url 'manage-theme' organization.slug %}">{% trans 'Theme' %}</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
{% extends "organization/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page-title %}
|
||||
{% trans 'Theme management' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Theme" %}</h2>
|
||||
<a href="{% url "static-upload" organization.slug %}" rel="popup">{% trans "Upload static" %}</a>
|
||||
<a href="{% url "template-upload" organization.slug %}" rel="popup">{% trans "Upload template" %}</a>
|
||||
|
||||
<h3>{% trans "Templates" %}</h3>
|
||||
<form action='{% url "template-delete" organization.slug %}'>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><td>{% trans "Filename" %}</td><td></td></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for template in templates %}
|
||||
<tr><td>{{ template }}</td><td> <button name="template" value="{{ template }}" class="icon-delete">{% trans "Remove" %}</button></td></tr>
|
||||
{% empty %}
|
||||
<tr><td colspan=2>{% trans "No templates uploaded yet" %}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<h3>{% trans "Statics" %}</h3>
|
||||
<form action='{% url "static-delete" organization.slug %}'>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><td>{% trans "Filename" %}</td><td></td></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for static in statics %}
|
||||
<tr><td>{{ static }}</td><td><button name="static" value="{{ static }}" class="icon-delete">{% trans "Remove" %}</button></td></tr>
|
||||
{% empty %}
|
||||
<tr><td>{% trans "No statics uploaded yet" %}</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{% extends "organization/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block more-user-links %}
|
||||
{{ block.super }}
|
||||
<a href="{% url "manage-theme" organization.slug %}">{% trans 'Theme' %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Theme" %}</h2>
|
||||
<a href="{% url "static-upload" organization.slug %}" rel="popup">{% trans "Upload static" %}</a>
|
||||
<a href="{% url "template-upload" organization.slug %}" rel="popup">{% trans "Upload template" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<p><button name="upload">{% trans "Upload" %}</button>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -9,4 +9,9 @@ urlpatterns = patterns('',
|
|||
url(r'^users/import$', import_users, name='import-users'),
|
||||
url(r'^users/(?P<pk>[\w]+)/$', view_user, name='view-user'),
|
||||
url(r'^users/(?P<pk>[\w]+)/edit$', edit_user, name='edit-user'),
|
||||
url(r'^theme/?$', theme, name='manage-theme'),
|
||||
url(r'^theme/template/upload$', template_upload, name='template-upload'),
|
||||
url(r'^theme/template/delete$', template_delete, name='template-delete'),
|
||||
url(r'^theme/static/upload$', static_upload, name='static-upload'),
|
||||
url(r'^theme/static/delete$', static_delete, name='static-delete'),
|
||||
)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import os
|
||||
import csv
|
||||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.shortcuts import render, redirect
|
||||
|
@ -15,7 +17,7 @@ from django_tables2 import RequestConfig
|
|||
|
||||
from .utils import create_user, create_or_update_users
|
||||
from .models import LocalAccount, Organization
|
||||
from .forms import LocalAccountCreateForm, LocalAccountForm, UsersImportForm
|
||||
from .forms import *
|
||||
from .tables import AccountTable
|
||||
|
||||
|
||||
|
@ -153,3 +155,111 @@ class ImportUsersView(OrganizationMixin, TemplateView):
|
|||
return self.render_to_response(context)
|
||||
|
||||
import_users = ImportUsersView.as_view()
|
||||
|
||||
|
||||
class ThemeView(OrganizationMixin, TemplateView):
|
||||
template_name = 'organization/theme.html'
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('manage-theme', kwargs={'organization_slug': self.kwargs['organization_slug']})
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(ThemeView, self).get_context_data(**kwargs)
|
||||
organization = ctx['organization']
|
||||
templates_dir = os.path.join(settings.ORGANIZATIONS_DIR,
|
||||
organization.slug, 'templates')
|
||||
statics_dir = os.path.join(settings.ORGANIZATIONS_DIR,
|
||||
organization.slug, 'static')
|
||||
ctx['templates'] = []
|
||||
ctx['statics'] = []
|
||||
if os.path.exists(templates_dir):
|
||||
ctx['templates'] = os.listdir(templates_dir)
|
||||
if os.path.exists(statics_dir):
|
||||
ctx['statics'] = os.listdir(statics_dir)
|
||||
ctx['templates_dir'] = templates_dir
|
||||
ctx['statics_dir'] = statics_dir
|
||||
return ctx
|
||||
|
||||
theme = ThemeView.as_view()
|
||||
|
||||
class UploadMixin(object):
|
||||
template_name = "organization/upload.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(UploadMixin, self).get_context_data(**kwargs)
|
||||
ctx['form'] = self.form_class()
|
||||
return ctx
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.form_class(request.POST, request.FILES)
|
||||
context = self.get_context_data(**kwargs)
|
||||
context['form'] = form
|
||||
organization = context['organization']
|
||||
destination_dir = os.path.join(settings.ORGANIZATIONS_DIR,
|
||||
organization.slug, self.upload_dir)
|
||||
if form.is_valid():
|
||||
data = form.cleaned_data[self.filename_param]
|
||||
if not os.path.exists(destination_dir):
|
||||
os.makedirs(destination_dir)
|
||||
try:
|
||||
with open(os.path.join(destination_dir, data.name), 'w') as template:
|
||||
template.write(data.read())
|
||||
messages.info(request, _('File "%s" successfully uploaded') % data.name)
|
||||
except OSError:
|
||||
messages.error(request, _('An error occured while uploading file "%s"') % data.name)
|
||||
return redirect(self.get_success_url())
|
||||
else:
|
||||
return self.render_to_response(context)
|
||||
|
||||
|
||||
class TemplateUpload(UploadMixin, ThemeView):
|
||||
form_class = TemplateForm
|
||||
filename_param = 'template_file'
|
||||
upload_dir = 'templates'
|
||||
|
||||
template_upload = TemplateUpload.as_view()
|
||||
|
||||
|
||||
class TemplateDelete(ThemeView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
ctx = self.get_context_data(**kwargs)
|
||||
template = request.GET.get('template')
|
||||
if os.path.exists(os.path.join(ctx['templates_dir'], template)):
|
||||
try:
|
||||
os.remove(os.path.join(ctx['templates_dir'], template))
|
||||
messages.info(request, _('Template %s successfully removed') % template)
|
||||
except IOError:
|
||||
messages.error(request, _('An error occured while removing file %s') % template)
|
||||
else:
|
||||
messages.error(request, _('Unknown template %s') % template)
|
||||
return redirect(self.get_success_url())
|
||||
|
||||
|
||||
template_delete = TemplateDelete.as_view()
|
||||
|
||||
|
||||
class StaticUpload(UploadMixin, ThemeView):
|
||||
form_class = StaticForm
|
||||
filename_param = 'static_file'
|
||||
upload_dir = 'static'
|
||||
|
||||
static_upload = StaticUpload.as_view()
|
||||
|
||||
|
||||
class StaticDelete(ThemeView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
ctx = self.get_context_data(**kwargs)
|
||||
static = request.GET.get('static')
|
||||
if os.path.exists(os.path.join(ctx['statics_dir'], static)):
|
||||
try:
|
||||
os.remove(os.path.join(ctx['statics_dir'], static))
|
||||
messages.info(request, _('Static file %s successfully removed') % static)
|
||||
except IOError:
|
||||
messages.error(request, _('An error occured while removing file %s') % static)
|
||||
else:
|
||||
messages.error(request, _('Unknown static %s') % static)
|
||||
return redirect(self.get_success_url())
|
||||
|
||||
static_delete = StaticDelete.as_view()
|
||||
|
|
|
@ -54,7 +54,9 @@ MIDDLEWARE_CLASSES = (
|
|||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
)
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + ('django.core.context_processors.request',)
|
||||
TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + \
|
||||
('django.core.context_processors.request',
|
||||
'uauth.context_processors.theme_base',)
|
||||
|
||||
ROOT_URLCONF = 'uauth.urls'
|
||||
|
||||
|
@ -97,6 +99,8 @@ LDAP_CONF = {
|
|||
'dn': 'ou=radius,dc=entrouvert,dc=org',
|
||||
}
|
||||
|
||||
ORGANIZATIONS_DIR = os.path.join(BASE_DIR, 'organizations')
|
||||
|
||||
AUTHENTICATION_BACKENDS = global_settings.AUTHENTICATION_BACKENDS + (
|
||||
'mellon.backends.SAMLBackend',
|
||||
'uauth.backends.LocalAccountPasswordBackend',
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
|
@ -74,4 +74,5 @@ div.example {
|
|||
}
|
||||
|
||||
/* icons */
|
||||
li.users a {background-image: url(icons/icon-personnes.png);}
|
||||
li.users a {background-image: url(icons/icon-personnes.png);}
|
||||
li.theme a {background-image: url(icons/icon-ressources.png);}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "uauth/base.html" %}
|
||||
{% extends theme_base %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block more-user-links %}
|
||||
|
|
|
@ -77,6 +77,7 @@ class OrganizationPageView(LoginMixin, FormView):
|
|||
context = super(OrganizationPageView, self).get_context_data(**kwargs)
|
||||
idps = get_idp_list()
|
||||
organization = Organization.objects.get(slug=self.kwargs['organization_slug'])
|
||||
self.request.session['organization'] = organization.slug
|
||||
self.request.session[organization.slug] = self.request.GET.urlencode()
|
||||
relay = signing.dumps({'organization': organization.slug})
|
||||
context.update({'idps': idps,
|
||||
|
|
Reference in New Issue