add UI for import/export site (#23210)
This commit is contained in:
parent
df942ea1ed
commit
623c64a064
|
@ -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'))
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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 %}
|
|
@ -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'),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue