From 767481ec7a5634fb92678a8bdd76973e4fb945fa Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Sat, 28 Nov 2020 15:54:21 +0100
Subject: [PATCH 2/3] settings: add export/import for api_access objects
 (#48751)

---
 tests/admin_pages/test_all.py | 10 ++++++++++
 wcs/admin/settings.py         |  8 ++++++--
 wcs/publisher.py              |  2 +-
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/tests/admin_pages/test_all.py b/tests/admin_pages/test_all.py
index aaa8f12d..2e2e0145 100644
--- a/tests/admin_pages/test_all.py
+++ b/tests/admin_pages/test_all.py
@@ -18,16 +18,17 @@ from django.utils.six.moves.urllib import parse as urlparse
 
 from quixote.http_request import Upload as QuixoteUpload
 
 from wcs.qommon.form import UploadedFile
 from wcs.qommon.ident.password_accounts import PasswordAccount
 from wcs.qommon.http_request import HTTPRequest
 from wcs.qommon.template import get_current_theme
 from wcs.admin.settings import UserFieldsFormDef
+from wcs.api_access import ApiAccess
 from wcs.categories import Category, CardDefCategory
 from wcs.data_sources import NamedDataSource
 from wcs.wscalls import NamedWsCall
 from wcs.roles import Role
 from wcs.workflows import (
     Workflow, CommentableWorkflowStatusItem,
     ChoiceWorkflowStatusItem, JumpOnSubmitWorkflowStatusItem)
 from wcs.wf.export_to_model import ExportToModel
@@ -639,16 +640,17 @@ def test_settings_export_import(pub, studio):
         FormDef.wipe()
         CardDef.wipe()
         Workflow.wipe()
         Role.wipe()
         Category.wipe()
         CardDefCategory.wipe()
         NamedDataSource.wipe()
         NamedWsCall.wipe()
+        ApiAccess.wipe()
 
     wipe()
     create_superuser(pub)
     app = login(get_app(pub))
     resp = app.get('/backoffice/settings/export')
     resp = resp.form.submit('cancel')
     resp = app.get('/backoffice/settings/export')
     resp = resp.form.submit('submit')
@@ -687,16 +689,22 @@ def test_settings_export_import(pub, studio):
     upload.fp = BytesIO()
     upload.fp.write(file_content)
     upload.fp.seek(0)
     export_to.model_file = UploadedFile('models', 'export_to_model-1.upload', upload)
     st1.items.append(export_to)
     export_to.parent = st1
     wf.store()
 
+    api_access = ApiAccess()
+    api_access.name = 'Jhon'
+    api_access.api_identifier = 'jhon'
+    api_access.api_key = '1234'
+    api_access.store()
+
     resp = app.get('/backoffice/settings/export')
     resp = resp.form.submit('submit')
     assert resp.location.startswith('http://example.net/backoffice/settings/export?job=')
     job_id = urlparse.parse_qs(urlparse.urlparse(resp.location).query)['job'][0]
     resp = resp.follow()
     resp = resp.click('Download Export')
     zip_content = BytesIO(resp.body)
     zipf = zipfile.ZipFile(zip_content, 'a')
@@ -708,16 +716,17 @@ def test_settings_export_import(pub, studio):
     assert 'workflows/1' not in filelist
     assert 'workflows_xml/1' in filelist
     assert 'models/export_to_model-1.upload' not in filelist
     assert 'roles/1' in filelist
     assert 'categories/1' in filelist
     assert 'carddef_categories/1' in filelist
     assert 'datasources/1' in filelist
     assert 'wscalls/corge' in filelist
+    assert 'apiaccess/1' in filelist
     for filename in filelist:
         assert '.indexes' not in filename
 
     wipe()
     assert FormDef.count() == 0
 
     resp = app.get('/backoffice/settings/import')
     resp = resp.form.submit('cancel')
@@ -732,16 +741,17 @@ def test_settings_export_import(pub, studio):
     resp = resp.form.submit('submit')
     assert 'Imported successfully' in resp.text
     assert '1 forms' in resp.text
     assert '1 cards' in resp.text
     assert FormDef.count() == 1
     assert FormDef.select()[0].url_name == 'foo'
     assert CardDef.count() == 1
     assert CardDef.select()[0].url_name == 'bar'
+    assert ApiAccess.count() == 1
 
     # check roles are found by name
     wipe()
     role = Role(name='qux')
     role.store()
 
     workflow = Workflow(name='Workflow One')
     st1 = workflow.add_status(name='st1')
diff --git a/wcs/admin/settings.py b/wcs/admin/settings.py
index f520813a..0f2a6480 100644
--- a/wcs/admin/settings.py
+++ b/wcs/admin/settings.py
@@ -874,16 +874,17 @@ class SettingsDirectory(QommonSettingsDirectory):
         if not get_cfg('sp', {}).get('idp-manage-roles'):
             form.add(CheckboxWidget, 'roles', title = _('Roles'), value = True)
         form.add(CheckboxWidget, 'categories', title = _('Categories'), value = True)
         form.add(CheckboxWidget, 'carddef_categories', title = _('Card Model Categories'), value = True)
         form.add(CheckboxWidget, 'settings', title = _('Settings'), value = False)
         form.add(CheckboxWidget, 'datasources', title=_('Data sources'), value=True)
         form.add(CheckboxWidget, 'mail-templates', title=_('Mail templates'), value=True)
         form.add(CheckboxWidget, 'wscalls', title=_('Webservice calls'), value=True)
+        form.add(CheckboxWidget, 'apiaccess', title=_('API access'), value=True)
         form.add_submit('submit', _('Submit'))
         form.add_submit('cancel', _('Cancel'))
         if form.get_submit() == 'cancel':
             return redirect('.')
 
         if not form.is_submitted():
             get_response().breadcrumb.append(('export', _('Export')))
             html_top('settings', title = _('Export'))
@@ -897,17 +898,18 @@ class SettingsDirectory(QommonSettingsDirectory):
                 self.app_dir = get_publisher().app_dir
                 self.dirs = dirs
                 self.settings = settings
 
             def export(self, job):
                 c = BytesIO()
                 z = zipfile.ZipFile(c, 'w')
                 for d in self.dirs:
-                    if d not in ('roles', 'categories', 'carddef_categories', 'datasources', 'wscalls', 'mail-templates'):
+                    if d not in ('roles', 'categories', 'carddef_categories', 'datasources',
+                                 'wscalls', 'mail-templates', 'apiaccess'):
                         continue
                     path = os.path.join(self.app_dir, d)
                     if not os.path.exists(path):
                         continue
                     for f in os.listdir(path):
                         if f == '.indexes':
                             continue
                         z.write(os.path.join(path, f), os.path.join(d, f))
@@ -946,17 +948,17 @@ class SettingsDirectory(QommonSettingsDirectory):
                             z.write(os.path.join(self.app_dir, 'config', f), os.path.join('config', f))
                 z.close()
 
                 job.file_content = c.getvalue()
                 job.store()
 
         dirs = []
         for w in ('formdefs', 'carddefs', 'workflows', 'roles', 'categories', 'carddef_categories',
-                  'datasources', 'wscalls', 'mail-templates', 'blockdefs'):
+                  'datasources', 'wscalls', 'mail-templates', 'blockdefs', 'apiaccess'):
             if form.get_widget(w) and form.get_widget(w).parse():
                 dirs.append(w)
         if not dirs and not form.get_widget('settings').parse():
             return redirect('.')
 
         exporter = Exporter(dirs, settings=form.get_widget('settings').parse())
 
         job = get_response().add_after_job(
@@ -1048,16 +1050,18 @@ class SettingsDirectory(QommonSettingsDirectory):
                 if results['settings']:
                     r += htmltext('<li>%s</li>') % _('Settings')
                 if results['datasources']:
                     r += htmltext('<li>%d %s</li>') % (results['datasources'], _('data sources'))
                 if results['mail-templates']:
                     r += htmltext('<li>%d %s</li>') % (results['mail-templates'], _('mail templates'))
                 if results['wscalls']:
                     r += htmltext('<li>%d %s</li>') % (results['wscalls'], _('webservice calls'))
+                if results['apiaccess']:
+                    r += htmltext('<li>%d %s</li>') % (results['apiaccess'], _('API access'))
                 r += htmltext('</ul>')
             else:
                 r += htmltext('<p>%s %s</p>') % (_('Error:'), reason)
             r += htmltext('<a href=".">%s</a>') % _('Back')
             return r.getvalue()
 
     def import_submit(self, form):
         return get_publisher().import_zip(form.get_widget('file').parse().fp)
diff --git a/wcs/publisher.py b/wcs/publisher.py
index 325f0a69..e5e6c806 100644
--- a/wcs/publisher.py
+++ b/wcs/publisher.py
@@ -163,17 +163,17 @@ class WcsPublisher(StubWcsPublisher):
 
         self.session_manager_class = sessions.StorageSessionManager
         self.set_session_manager(self.session_manager_class(session_class=self.session_class))
 
     def import_zip(self, fd):
         z = zipfile.ZipFile(fd)
         results = {'formdefs': 0, 'carddefs': 0, 'workflows': 0, 'categories': 0, 'roles': 0,
                 'settings': 0, 'datasources': 0, 'wscalls': 0, 'mail-templates': 0,
-                'blockdefs': 0}
+                'blockdefs': 0, 'apiaccess': 0}
 
         def _decode_list(data):
             rv = []
             for item in data:
                 if isinstance(item, six.string_types):
                     item = force_str(item)
                 elif isinstance(item, list):
                     item = _decode_list(item)
-- 
2.29.2

