add UI for import/export site (#23210)

This commit is contained in:
Emmanuel Cazenave 2018-05-03 11:40:25 +02:00
parent df942ea1ed
commit 623c64a064
6 changed files with 162 additions and 3 deletions

View File

@ -191,3 +191,7 @@ class AuthenticationForm(auth_forms.AuthenticationForm):
if keys:
self.exponential_backoff.success(*keys)
return self.cleaned_data
class SiteImportForm(forms.Form):
site_json = forms.FileField(label=_('Site Export File'))

View File

@ -5,7 +5,14 @@
{% endblock %}
{% block appbar %}
{% blocktrans %}Here you can manage objects related to organizational units, users, roles and applications.{% endblocktrans %}
<h2>{% blocktrans %}Here you can manage objects related to organizational units, users, roles and applications.{% endblocktrans %}</h2>
{% if user.is_superuser %}
<a class="extra-actions-menu-opener"></a>
<ul class="extra-actions-menu">
<li><a href="{% url 'a2-manager-site-export' %}">{% trans 'Export Site' %}</a></li>
<li><a href="{% url 'a2-manager-site-import' %}">{% trans 'Import Site' %}</a></li>
</ul>
{% endif %}
{% endblock %}
{% block content %}

View File

@ -0,0 +1,18 @@
{% extends "authentic2/manager/form.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans "Site Import" %}</h2>
{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button>{% trans "Import" %}</button>
<a class="cancel" href="{% url 'a2-manager-homepage' %}">{% trans 'Cancel' %}</a>
</div>
</form>
{% endblock %}

View File

@ -115,6 +115,10 @@ urlpatterns = required(
# backoffice menu as json
url(r'^menu.json$', views.menu_json),
# general management
url(r'^site-export/$', views.site_export, name='a2-manager-site-export'),
url(r'^site-import/$', views.site_import, name='a2-manager-site-import'),
)
)

View File

@ -5,7 +5,7 @@ from django.core.exceptions import PermissionDenied
from django.views.generic.base import ContextMixin
from django.views.generic.edit import FormMixinBase
from django.views.generic import (FormView, UpdateView, CreateView, DeleteView, TemplateView,
DetailView)
DetailView, View)
from django.views.generic.detail import SingleObjectMixin
from django.http import HttpResponse, Http404
from django.utils.encoding import force_text
@ -21,7 +21,8 @@ from django_select2.views import AutoResponseView
from django_rbac.utils import get_ou_model
from authentic2.forms import modelform_factory
from authentic2.data_transfer import export_site, import_site, DataImportError, ImportContext
from authentic2.forms import modelform_factory, SiteImportForm
from authentic2.utils import redirect, batch_queryset
from authentic2.decorators import json as json_view
from authentic2 import hooks
@ -608,3 +609,44 @@ class Select2View(AutoResponseView):
return widget
select2 = Select2View.as_view()
class SiteExport(View):
def get(self, request, *args, **kwargs):
if not request.user.is_superuser:
raise PermissionDenied
return HttpResponse(
json.dumps(export_site(), indent=4), content_type='application/json')
site_export = SiteExport.as_view()
class SiteImportView(FormView):
form_class = SiteImportForm
template_name = 'authentic2/manager/site_import.html'
success_url = reverse_lazy('a2-manager-homepage')
def form_valid(self, form):
try:
json_site = json.load(self.request.FILES['site_json'])
except ValueError:
form.add_error('site_json', _('File is not in the expected JSON format.'))
return self.form_invalid(form)
try:
import_site(json_site, ImportContext())
except DataImportError as e:
form.add_error('site_json', unicode(e))
return self.form_invalid(form)
return super(SiteImportView, self).form_valid(form)
def dispatch(self, request, *args, **kwargs):
if not request.user.is_superuser:
raise PermissionDenied
return super(SiteImportView, self).dispatch(request, *args, **kwargs)
site_import = SiteImportView.as_view()

View File

@ -1,9 +1,12 @@
import pytest
import json
from urlparse import urlparse
from django.core.urlresolvers import reverse
from django.core import mail
from webtest import Upload
from authentic2.a2_rbac.utils import get_default_ou
from django_rbac.utils import get_ou_model, get_role_model
@ -552,3 +555,84 @@ def test_manager_many_ou_auto_admin_role(app, ou1, admin, user_with_auto_admin_r
assert set(names) == {u'Auto Admin Role'}
test_user_listing_auto_admin_role(user_with_auto_admin_role)
def test_manager_site_export(app, superuser):
response = login(app, superuser, '/manage/site-export/')
assert 'roles' in response.json
assert 'ous' in response.json
def test_manager_site_export_forbidden(app, simple_user):
login(app, simple_user)
app.get('/manage/site-export/', status=403)
def test_manager_site_import(app, db, superuser):
site_import = login(app, superuser, '/manage/site-import/')
form = site_import.form
site_export = {
'roles': [
{
"description": "", "service": None, "name": "basic",
"attributes": [],
"ou": {
"slug": "default",
"uuid": "ba60d9e6c2874636883bdd604b23eab2",
"name": "Collectivit\u00e9 par d\u00e9faut"
},
"external_id": "",
"slug": "basic",
"uuid": "6eb7bbf64bf547119120f925f0e560ac"
}]
}
form['site_json'] = Upload(
'site_export.json', json.dumps(site_export), 'application/octet-stream')
res = form.submit()
assert res.status_code == 302
assert get_role_model().objects.get(slug='basic')
def test_manager_site_import_error(app, db, superuser):
site_import = login(app, superuser, '/manage/site-import/')
form = site_import.form
site_export = {
'roles': [
{
"description": "", "service": None, "name": "basic",
"attributes": [],
"ou": {
"slug": "unkown-ou",
"uuid": "ba60d9e6c2874636883bdd604b23eab2",
"name": "unkown ou"
},
"external_id": "",
"slug": "basic",
"uuid": "6eb7bbf64bf547119120f925f0e560ac"
}]
}
form['site_json'] = Upload(
'site_export.json', json.dumps(site_export), 'application/octet-stream')
res = form.submit()
assert res.status_code == 200
assert 'missing Organizational Unit' in res.text
Role = get_role_model()
with pytest.raises(Role.DoesNotExist):
Role.objects.get(slug='basic')
def test_manager_site_import_forbidden(app, simple_user):
login(app, simple_user)
app.get('/manage/site-import/', status=403)
def test_manager_homepatge_import_export(superuser, app):
manager_home_page = login(app, superuser, reverse('a2-manager-homepage'))
assert 'site-import' in manager_home_page.text
assert 'site-export' in manager_home_page.text
def test_manager_homepatge_import_export_hidden(admin, app):
manager_home_page = login(app, admin, reverse('a2-manager-homepage'))
assert 'site-import' not in manager_home_page.text
assert 'site-export' not in manager_home_page.text