0001-add-UI-for-import-export-site-23210.patch
src/authentic2/forms.py | ||
---|---|---|
191 | 191 |
if keys: |
192 | 192 |
self.exponential_backoff.success(*keys) |
193 | 193 |
return self.cleaned_data |
194 | ||
195 | ||
196 |
class SiteImportForm(forms.Form): |
|
197 |
site_json = forms.FileField(label=_('Site Export File')) |
src/authentic2/manager/templates/authentic2/manager/homepage.html | ||
---|---|---|
5 | 5 |
{% endblock %} |
6 | 6 | |
7 | 7 |
{% block appbar %} |
8 |
{% blocktrans %}Here you can manage objects related to organizational units, users, roles and applications.{% endblocktrans %} |
|
8 |
<h2>{% blocktrans %}Here you can manage objects related to organizational units, users, roles and applications.{% endblocktrans %}</h2> |
|
9 |
<a class="extra-actions-menu-opener"></a> |
|
10 |
<ul class="extra-actions-menu"> |
|
11 |
<li><a href="{% url 'a2-manager-site-export' %}">{% trans 'Export Site' %}</a></li> |
|
12 |
<li><a href="{% url 'a2-manager-site-import' %}">{% trans 'Import Site' %}</a></li> |
|
13 |
</ul> |
|
14 | ||
9 | 15 |
{% endblock %} |
10 | 16 | |
11 | 17 |
{% block content %} |
src/authentic2/manager/templates/authentic2/manager/site_import.html | ||
---|---|---|
1 |
{% extends "authentic2/manager/form.html" %} |
|
2 |
{% load i18n %} |
|
3 | ||
4 |
{% block appbar %} |
|
5 |
<h2>{% trans "Site Import" %}</h2> |
|
6 |
{% endblock %} |
|
7 | ||
8 |
{% block content %} |
|
9 | ||
10 |
<form method="post" enctype="multipart/form-data"> |
|
11 |
{% csrf_token %} |
|
12 |
{{ form.as_p }} |
|
13 |
<div class="buttons"> |
|
14 |
<button>{% trans "Import" %}</button> |
|
15 |
<a class="cancel" href="{% url 'a2-manager-homepage' %}">{% trans 'Cancel' %}</a> |
|
16 |
</div> |
|
17 |
</form> |
|
18 |
{% endblock %} |
src/authentic2/manager/urls.py | ||
---|---|---|
115 | 115 | |
116 | 116 |
# backoffice menu as json |
117 | 117 |
url(r'^menu.json$', views.menu_json), |
118 | ||
119 |
# general management |
|
120 |
url(r'^site-export/$', views.site_export, name='a2-manager-site-export'), |
|
121 |
url(r'^site-import/$', views.site_import, name='a2-manager-site-import'), |
|
118 | 122 |
) |
119 | 123 |
) |
120 | 124 |
src/authentic2/manager/views.py | ||
---|---|---|
5 | 5 |
from django.views.generic.base import ContextMixin |
6 | 6 |
from django.views.generic.edit import FormMixinBase |
7 | 7 |
from django.views.generic import (FormView, UpdateView, CreateView, DeleteView, TemplateView, |
8 |
DetailView) |
|
8 |
DetailView, View)
|
|
9 | 9 |
from django.views.generic.detail import SingleObjectMixin |
10 | 10 |
from django.http import HttpResponse, Http404 |
11 | 11 |
from django.utils.encoding import force_text |
... | ... | |
21 | 21 | |
22 | 22 |
from django_rbac.utils import get_ou_model |
23 | 23 | |
24 |
from authentic2.forms import modelform_factory |
|
24 |
from authentic2.data_transfer import export_site, import_site, DataImportError, ImportContext |
|
25 |
from authentic2.forms import modelform_factory, SiteImportForm |
|
25 | 26 |
from authentic2.utils import redirect |
26 | 27 |
from authentic2.decorators import json as json_view |
27 | 28 |
from authentic2 import hooks |
... | ... | |
607 | 608 |
return widget |
608 | 609 | |
609 | 610 |
select2 = Select2View.as_view() |
611 | ||
612 | ||
613 |
class SiteExport(View): |
|
614 | ||
615 |
def get(self, request, *args, **kwargs): |
|
616 |
return HttpResponse( |
|
617 |
json.dumps(export_site(), indent=4), content_type='application/json') |
|
618 | ||
619 | ||
620 |
site_export = SiteExport.as_view() |
|
621 | ||
622 | ||
623 |
class SiteImportView(FormView): |
|
624 |
form_class = SiteImportForm |
|
625 |
template_name = 'authentic2/manager/site_import.html' |
|
626 |
success_url = reverse_lazy('a2-manager-homepage') |
|
627 | ||
628 |
def form_valid(self, form): |
|
629 |
try: |
|
630 |
json_site = json.load(self.request.FILES['site_json']) |
|
631 |
except ValueError: |
|
632 |
form.add_error('site_json', _('File is not in the expected JSON format.')) |
|
633 |
return self.form_invalid(form) |
|
634 | ||
635 |
try: |
|
636 |
import_site(json_site, ImportContext()) |
|
637 |
except DataImportError as e: |
|
638 |
form.add_error('site_json', unicode(e)) |
|
639 |
return self.form_invalid(form) |
|
640 | ||
641 |
return super(SiteImportView, self).form_valid(form) |
|
642 | ||
643 | ||
644 |
site_import = SiteImportView.as_view() |
tests/test_manager.py | ||
---|---|---|
1 | 1 |
import pytest |
2 |
import json |
|
2 | 3 |
from urlparse import urlparse |
3 | 4 | |
4 | 5 |
from django.core.urlresolvers import reverse |
5 | 6 |
from django.core import mail |
6 | 7 | |
8 |
from webtest import Upload |
|
9 | ||
7 | 10 |
from authentic2.a2_rbac.utils import get_default_ou |
8 | 11 | |
9 | 12 |
from django_rbac.utils import get_ou_model, get_role_model |
... | ... | |
552 | 555 |
assert set(names) == {u'Auto Admin Role'} |
553 | 556 | |
554 | 557 |
test_user_listing_auto_admin_role(user_with_auto_admin_role) |
558 | ||
559 | ||
560 |
def test_manager_site_export(app, superuser_or_admin): |
|
561 |
response = login(app, superuser_or_admin, '/manage/site-export/') |
|
562 |
assert 'roles' in response.json |
|
563 |
assert 'ous' in response.json |
|
564 | ||
565 | ||
566 |
def test_manager_site_import(app, db, superuser_or_admin): |
|
567 |
site_import = login(app, superuser_or_admin, '/manage/site-import/') |
|
568 |
form = site_import.form |
|
569 |
site_export = { |
|
570 |
'roles': [ |
|
571 |
{ |
|
572 |
"description": "", "service": None, "name": "basic", |
|
573 |
"attributes": [], |
|
574 |
"ou": { |
|
575 |
"slug": "default", |
|
576 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
577 |
"name": "Collectivit\u00e9 par d\u00e9faut" |
|
578 |
}, |
|
579 |
"external_id": "", |
|
580 |
"slug": "basic", |
|
581 |
"uuid": "6eb7bbf64bf547119120f925f0e560ac" |
|
582 |
}] |
|
583 |
} |
|
584 |
form['site_json'] = Upload( |
|
585 |
'site_export.json', json.dumps(site_export), 'application/octet-stream') |
|
586 |
res = form.submit() |
|
587 |
assert res.status_code == 302 |
|
588 |
assert get_role_model().objects.get(slug='basic') |
|
589 | ||
590 | ||
591 |
def test_manager_site_import_error(app, db, superuser_or_admin): |
|
592 |
site_import = login(app, superuser_or_admin, '/manage/site-import/') |
|
593 |
form = site_import.form |
|
594 |
site_export = { |
|
595 |
'roles': [ |
|
596 |
{ |
|
597 |
"description": "", "service": None, "name": "basic", |
|
598 |
"attributes": [], |
|
599 |
"ou": { |
|
600 |
"slug": "unkown-ou", |
|
601 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
602 |
"name": "unkown ou" |
|
603 |
}, |
|
604 |
"external_id": "", |
|
605 |
"slug": "basic", |
|
606 |
"uuid": "6eb7bbf64bf547119120f925f0e560ac" |
|
607 |
}] |
|
608 |
} |
|
609 |
form['site_json'] = Upload( |
|
610 |
'site_export.json', json.dumps(site_export), 'application/octet-stream') |
|
611 |
res = form.submit() |
|
612 |
assert res.status_code == 200 |
|
613 |
assert 'missing Organizational Unit' in res.text |
|
614 |
Role = get_role_model() |
|
615 |
with pytest.raises(Role.DoesNotExist): |
|
616 |
Role.objects.get(slug='basic') |
|
555 |
- |