From 0b44956a03803e3ae3a7d464334244e82d721381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Sat, 1 Apr 2017 17:28:23 +0200 Subject: [PATCH 1/2] general: remove support for advanced fargo features (#15720) --- tests/test_backoffice_pages.py | 240 ------------------------------ tests/test_fields.py | 3 +- tests/test_form_pages.py | 98 ------------ tests/test_formdata.py | 120 --------------- tests/test_formdef.py | 43 +++--- tests/test_formdef_import.py | 15 -- wcs/backoffice/management.py | 2 +- wcs/fields.py | 46 ++---- wcs/forms/common.py | 57 +------ wcs/portfolio.py | 88 ----------- wcs/qommon/form.py | 114 ++------------ wcs/qommon/static/css/qommon.css | 10 -- wcs/qommon/static/js/qommon.fileupload.js | 45 +----- 13 files changed, 45 insertions(+), 836 deletions(-) diff --git a/tests/test_backoffice_pages.py b/tests/test_backoffice_pages.py index adf30d42..35510475 100644 --- a/tests/test_backoffice_pages.py +++ b/tests/test_backoffice_pages.py @@ -10,12 +10,10 @@ import hashlib import pytest from webtest import Upload -import mock from quixote import cleanup, get_publisher from wcs.qommon import errors, sessions from qommon.ident.password_accounts import PasswordAccount -from qommon.misc import json_loads from wcs.qommon.http_request import HTTPRequest from wcs.roles import Role from wcs.workflows import (Workflow, CommentableWorkflowStatusItem, @@ -2500,244 +2498,6 @@ def test_menu_json(pub): assert resp.body == 'foo(%s);' % menu_json_str assert resp.headers['content-type'] == 'application/javascript' -def test_backoffice_file_field_fargo_no_metadata(pub, fargo_url): - document_type = { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'mimetypes': ['application/pdf'], - 'label': 'Justificatif de domicile', - } - user = create_user(pub, is_admin=True) - user.name_identifiers = ['12345'] - user.store() - FormDef.wipe() - formdef = FormDef() - formdef.name = 'form title' - formdef.fields = [fields.FileField( - id='0', label='1st field', type='file', - document_type=document_type)] - formdef.store() - formdef.data_class().wipe() - upload = Upload('test.pdf', '%PDF-1.4', 'application/pdf') - digest = hashlib.sha256('%PDF-1.4').hexdigest() - app = login(get_app(pub)) - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - resp = app.get('/form-title/') - assert fargo_get.call_count == 0 - resp.forms[0]['f0$file'] = upload - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - resp = resp.forms[0].submit('submit') - assert fargo_get.call_count == 0 - assert 'Check values then click submit.' in resp.body - resp = resp.forms[0].submit('submit').follow() - assert formdef.data_class().count() == 1 - formdata = formdef.data_class().select()[0] - form_id = formdata.id - assert not hasattr(formdata.data['0'], 'metadata') - assert not '0_structured' in formdata.data - resp = app.get('/backoffice/management/form-title/%s/' % form_id) - assert not 'Validate' in resp.body - with mock.patch('wcs.portfolio.fargo_post_json') as fargo_post_json: - resp = app.get('/backoffice/management/form-title/%s/validate?field_id=0' % form_id) - assert fargo_post_json.call_count == 0 - resp = resp.follow() - assert not 'Valid ' in resp.body - assert not 'Validate' in resp.body - - -def test_backoffice_file_field_validation(pub, fargo_url): - document_type = { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'mimetypes': ['application/pdf'], - 'label': 'Justificatif de domicile', - 'metadata': [ - {'label': 'Nom', 'varname': 'nom', 'type': 'string'}, - {'label': 'Prénom(s)', 'varname': 'prenoms', 'type': 'string'}, - {'label': 'Numéro', 'varname': 'numero', 'type': 'string'}, - {'label': 'Rue', 'varname': 'rue', 'type': 'string'}, - {'label': 'Code postal', 'varname': 'code-postal', 'type': 'string'}, - {'label': 'Ville', 'varname': 'ville', 'type': 'string'}, - ], - } - metadata = { - 'nom': 'Doe', - 'prenoms': 'John', - 'numero': '169', - 'rue': 'rue du château', - 'code-postal': '75014', - 'ville': 'PARIS', - } - user = create_user(pub, is_admin=True) - user.name_identifiers = ['12345'] - user.store() - FormDef.wipe() - formdef = FormDef() - formdef.name = 'form title' - formdef.fields = [fields.FileField( - id='0', label='1st field', type='file', - document_type=document_type)] - formdef.store() - formdef.data_class().wipe() - upload = Upload('test.pdf', '%PDF-1.4', 'application/pdf') - digest = hashlib.sha256('%PDF-1.4').hexdigest() - app = login(get_app(pub)) - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - fargo_get.return_value = {'result': 1, 'data': {'results': []}} - resp = app.get('/form-title/') - fargo_get.assert_called_once_with( - 'api/validation/justificatif-de-domicile/?user_nameid=12345') - resp.forms[0]['f0$file'] = upload - for i, meta_field in enumerate(document_type['metadata']): - resp.forms[0]['f0$f%s' % i] = metadata[meta_field['varname']] - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - fargo_get.return_value = {'result': 1, 'data': {'results': []}} - resp = resp.forms[0].submit('submit') - fargo_get.assert_called_once_with( - 'api/validation/justificatif-de-domicile/?user_nameid=12345') - for key in metadata: - assert 'value="%s"' % metadata[key] in resp.body - assert 'Check values then click submit.' in resp.body - resp = resp.forms[0].submit('submit').follow() - for metadata_field in document_type['metadata']: - - fragment = '%s : %s' % (metadata_field['label'], metadata[metadata_field['varname']]) - assert fragment in resp.body - assert formdef.data_class().count() == 1 - formdata = formdef.data_class().select()[0] - form_id = formdata.id - assert formdata.data['0'].metadata == metadata - assert formdata.data['0_structured'] == metadata - resp = app.get('/backoffice/management/form-title/%s/' % form_id) - assert 'Validate' in resp.body - for metadata_field in document_type['metadata']: - - fragment = '%s : %s' % (metadata_field['label'], metadata[metadata_field['varname']]) - assert fragment in resp.body - with mock.patch('wcs.portfolio.fargo_post_json') as fargo_post_json: - payload = { - 'user_nameid': '12345', - 'origin': 'example.net', - 'creator': 'admin', - 'content_hash': digest, - } - payload.update(metadata) - result = { - 'result': 1, - 'data': payload.copy() - } - result['data'].update({ - 'url': 'zob', - 'created': '1970-01-01T10:10:10Z', - 'start': '1970-01-01', - 'end': '1978-01-01', - 'display': 'John Doe, 169 rue du château, 75014 PARIS' - }) - fargo_post_json.return_value = 201, result - resp = app.get('/backoffice/management/form-title/%s/validate?field_id=0' % form_id) - assert fargo_post_json.call_count == 1 - assert fargo_post_json.call_args[0][0] == '/api/validation/justificatif-de-domicile/' - assert fargo_post_json.call_args[0][1] == payload - resp = resp.follow() - - assert 'Valid from 1970-01-01 to 1978-01-01' in resp.body - - -def test_backoffice_file_validation_no_upload(pub, fargo_url, fargo_secret): - document_type = { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'mimetypes': ['application/pdf'], - 'label': 'Justificatif de domicile', - 'metadata': [ - {'label': 'Nom', 'varname': 'nom', 'type': 'string'}, - {'label': 'Prénom(s)', 'varname': 'prenoms', 'type': 'string'}, - {'label': 'Numéro', 'varname': 'numero', 'type': 'string'}, - {'label': 'Rue', 'varname': 'rue', 'type': 'string'}, - {'label': 'Code postal', 'varname': 'code-postal', 'type': 'string'}, - {'label': 'Ville', 'varname': 'ville', 'type': 'string'}, - ], - } - metadata = { - 'nom': 'Doe', - 'prenoms': 'John', - 'numero': '169', - 'rue': 'rue du château', - 'code-postal': '75014', - 'ville': 'PARIS', - } - validation = { - 'url': 'zob', - 'creator': 'admin', - 'created': '1970-01-01T10:10:10Z', - 'start': '1970-01-01', - 'end': '1978-01-01', - 'display': 'John Doe, 169 rue du château, 75014 PARIS' - } - validation.update(metadata) - - user = create_user(pub, is_admin=True) - user.name_identifiers = ['12345'] - user.store() - FormDef.wipe() - formdef = FormDef() - formdef.name = 'form title' - formdef.fields = [fields.FileField( - id='0', label='1st field', type='file', - document_type=document_type)] - formdef.store() - formdef.data_class().wipe() - app = login(get_app(pub)) - return_value = {'result': 1, 'data': {'results': [validation]}} - with mock.patch('wcs.portfolio.http_get_page') as http_get_page: - http_get_page.return_value = None, 200, json.dumps(return_value), None - resp = app.get('/form-title/') - assert http_get_page.call_count == 1 - assert http_get_page.call_args[0][0].startswith( - 'http://fargo.example.net/api/validation/justificatif-de-domicile/?user_nameid=12345') - assert validation['display'] in resp.body - resp.forms[0]['f0$validation_url'] = 'zob' - for i, meta_field in enumerate(document_type['metadata']): - resp.forms[0]['f0$f%s' % i] = metadata[meta_field['varname']] - with mock.patch('wcs.portfolio.http_get_page') as http_get_page: - return_value2 = { - 'result': 1, - 'data': validation, - } - - def side_effect(url): - if url.startswith('http://fargo.example.net/zob'): - return None, 200, json.dumps(return_value2), None - else: - return None, 200, json.dumps(return_value), None - http_get_page.side_effect = side_effect - resp = resp.forms[0].submit('submit') - assert http_get_page.call_count == 3 - assert 'api/validation/justificatif-de-domicile/?user_nameid=12345' in http_get_page.call_args_list[0][0][0] - assert http_get_page.call_args_list[1][0][0].startswith('http://fargo.example.net/zob') - assert http_get_page.call_args_list[2][0][0].startswith('http://fargo.example.net/zob') - for key in metadata: - assert 'value="%s"' % metadata[key] in resp.body - assert 'Check values then click submit.' in resp.body - resp = resp.forms[0].submit('submit').follow() - assert formdef.data_class().count() == 1 - formdata = formdef.data_class().select()[0] - form_id = formdata.id - assert formdata.data['0'].metadata == validation - assert formdata.data['0_structured'] == validation - for metadata_field in document_type['metadata']: - - fragment = '%s : %s' % (metadata_field['label'], metadata[metadata_field['varname']]) - assert fragment in resp.body - resp = app.get('/backoffice/management/form-title/%s/' % form_id) - assert not 'Validate' in resp.body - for metadata_field in document_type['metadata']: - - fragment = '%s : %s' % (metadata_field['label'], metadata[metadata_field['varname']]) - assert fragment in resp.body - assert 'Valid from 1970-01-01 to 1978-01-01' in resp.body - - def test_360_user_view(pub): if not pub.is_using_postgresql(): pytest.skip('this requires SQL') diff --git a/tests/test_fields.py b/tests/test_fields.py index ddd7cb6c..6a53ed2c 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -6,7 +6,8 @@ import shutil import pytest from quixote import cleanup -from quixote.http_request import HTTPRequest, Upload +from quixote.http_request import Upload +from qommon.http_request import HTTPRequest from wcs.qommon import sessions from wcs import fields from wcs.qommon.form import Form diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py index ae20f604..289615e8 100644 --- a/tests/test_form_pages.py +++ b/tests/test_form_pages.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json import pytest import hashlib @@ -3074,103 +3073,6 @@ def test_form_autosave_with_parameterized_datasource(pub): assert formdef.data_class().select()[0].data['3'] == '1' assert formdef.data_class().select()[0].data['3_display'] == 'barbar' -def test_file_field_validation(pub, fargo_url): - document_type = { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'label': 'Justificatif de domicile', - 'metadata': [ - {'label': 'Nom', 'varname': 'nom', 'type': 'string'}, - {'label': 'Prénom(s)', 'varname': 'prenoms', 'type': 'string'}, - {'label': 'Numéro', 'varname': 'numero', 'type': 'string'}, - {'label': 'Rue', 'varname': 'rue', 'type': 'string'}, - {'label': 'Code postal', 'varname': 'code-postal', 'type': 'string'}, - {'label': 'Ville', 'varname': 'ville', 'type': 'string'}, - ], - } - metadata = { - 'nom': 'Doe', - 'prenoms': 'John', - 'numero': '169', - 'rue': 'rue du château', - 'code-postal': '75014', - 'ville': 'PARIS', - } - user = create_user(pub) - user.name_identifiers = ['12345'] - user.store() - FormDef.wipe() - formdef = FormDef() - formdef.name = 'form title' - formdef.fields = [fields.FileField( - id='0', label='1st field', type='file', - document_type=document_type) - ] - formdef.store() - formdef.data_class().wipe() - upload = Upload('test.pdf', '%PDF-1.4', 'application/pdf') - app = login(get_app(pub), username='foo', password='foo') - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - fargo_get.return_value = {'result': 1, 'data': {'results': []}} - resp = app.get('/form-title/') - fargo_get.assert_called_once_with( - 'api/validation/justificatif-de-domicile/?user_nameid=12345') - resp.forms[0]['f0$file'] = upload - for i, meta_field in enumerate(document_type['metadata']): - resp.forms[0]['f0$f%s' % i] = metadata[meta_field['varname']] - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - fargo_get.return_value = {'result': 1, 'data': {'results': []}} - resp = resp.forms[0].submit('submit') - fargo_get.assert_called_once_with( - 'api/validation/justificatif-de-domicile/?user_nameid=12345') - assert 'Check values then click submit.' in resp.body - resp = resp.forms[0].submit('submit') - assert resp.status_int == 302 - resp = resp.follow() - assert 'The form has been recorded' in resp.body - assert formdef.data_class().count() == 1 - formdata = formdef.data_class().select()[0] - assert formdata.data['0'].metadata == metadata - assert formdata.data['0_structured'] == metadata - - -def test_file_field_fargo_no_metadata(pub, fargo_url): - document_type = { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'label': 'Justificatif de domicile', - } - user = create_user(pub) - user.name_identifiers = ['12345'] - user.store() - FormDef.wipe() - formdef = FormDef() - formdef.name = 'form title' - formdef.fields = [fields.FileField( - id='0', label='1st field', type='file', - document_type=document_type) - ] - formdef.store() - formdef.data_class().wipe() - upload = Upload('test.pdf', '%PDF-1.4', 'application/pdf') - app = login(get_app(pub), username='foo', password='foo') - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - resp = app.get('/form-title/') - assert fargo_get.call_count == 0 - resp.forms[0]['f0$file'] = upload - with mock.patch('wcs.portfolio.fargo_get') as fargo_get: - resp = resp.forms[0].submit('submit') - assert fargo_get.call_count == 0 - assert 'Check values then click submit.' in resp.body - resp = resp.forms[0].submit('submit') - assert resp.status_int == 302 - resp = resp.follow() - assert 'The form has been recorded' in resp.body - assert formdef.data_class().count() == 1 - formdata = formdef.data_class().select()[0] - assert not hasattr(formdata.data['0'], 'metadata') - assert not '0_structured' in formdata.data - def test_form_string_field_autocomplete(pub): formdef = create_formdef() formdef.fields = [fields.StringField(id='0', label='string', type='string', required=False)] diff --git a/tests/test_formdata.py b/tests/test_formdata.py index 05c38902..8613833e 100644 --- a/tests/test_formdata.py +++ b/tests/test_formdata.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pytest import sys import shutil @@ -15,8 +14,6 @@ from wcs.workflows import Workflow, WorkflowCriticalityLevel, WorkflowBackoffice from wcs.wf.anonymise import AnonymiseWorkflowStatusItem from wcs.wf.wscall import JournalWsCallErrorPart from wcs.wf.register_comment import JournalEvolutionPart -from wcs.qommon.form import NoUpload -import mock from utilities import create_temporary_pub, clean_temporary_pub @@ -159,123 +156,6 @@ def test_file_field(pub): assert substvars.get('form_var_foo_url').endswith('/foobar/1/download?f=0') assert isinstance(substvars.get('form_var_foo_raw'), Upload) - formdata.data = {'0': None} - substvars = formdata.get_substitution_variables() - assert substvars['form_var_foo'] is None - assert substvars['form_var_foo_raw'] is None - assert substvars['form_var_foo_url'] is None - - formdata.data = {} - substvars = formdata.get_substitution_variables() - assert substvars['form_var_foo'] is None - assert substvars['form_var_foo_raw'] is None - assert substvars['form_var_foo_url'] is None - -def test_file_field_fargo_no_metadata(pub): - document_types = { - 'justificatif-de-domicile': { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'label': 'Justificatif de domicile', - } - } - formdef.data_class().wipe() - formdef.fields = [fields.FileField(id='0', label='file', varname='foo', - document_type=document_types['justificatif-de-domicile'])] - formdef.store() - formdata = formdef.data_class()() - upload = Upload('test.txt', 'text/plain', 'ascii') - upload.receive(['first line', 'second line']) - formdata.data = {'0': upload} - formdata.id = 1 - substvars = formdata.get_substitution_variables() - assert substvars.get('form_var_foo') == 'test.txt' - assert substvars.get('form_var_foo_url').endswith('/foobar/1/download?f=0') - assert isinstance(substvars.get('form_var_foo_raw'), Upload) - - -def test_file_field_with_metadata(pub): - document_types = { - 'justificatif-de-domicile': { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'label': 'Justificatif de domicile', - 'metadata': [ - {'label': 'Nom', 'varname': 'nom', 'type': 'string'}, - {'label': 'Prénom(s)', 'varname': 'prenoms', 'type': 'string'}, - {'label': 'Numéro', 'varname': 'numero', 'type': 'string'}, - {'label': 'Rue', 'varname': 'rue', 'type': 'string'}, - {'label': 'Code postal', 'varname': 'code-postal', 'type': 'string'}, - {'label': 'Ville', 'varname': 'ville', 'type': 'string'}, - ], - } - } - formdef.data_class().wipe() - formdef.fields = [fields.FileField(id='0', label='file', varname='foo', - document_type=document_types['justificatif-de-domicile'])] - formdef.store() - formdata = formdef.data_class()() - upload = Upload('test.txt', 'text/plain', 'ascii') - upload.receive(['first line', 'second line']) - upload.metadata = { - 'nom': 'Doe', - 'prenoms': 'John', - 'numero': '169', - 'rue': 'rue du château', - 'code-postal': '75014', - 'ville': 'PARIS', - } - formdata.data = {'0': upload, '0_structured': upload.metadata} - formdata.id = 1 - substvars = formdata.get_substitution_variables() - assert substvars.get('form_var_foo') == 'test.txt' - assert substvars.get('form_var_foo_url').endswith('/foobar/1/download?f=0') - assert isinstance(substvars.get('form_var_foo_raw'), Upload) - for key in upload.metadata: - assert substvars.get('form_var_foo_%s' % key) == upload.metadata[key] - - -def test_file_field_no_file_with_metadata(pub): - document_types = { - 'justificatif-de-domicile': { - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'label': 'Justificatif de domicile', - 'metadata': [ - {'label': 'Nom', 'varname': 'nom', 'type': 'string'}, - {'label': 'Prénom(s)', 'varname': 'prenoms', 'type': 'string'}, - {'label': 'Numéro', 'varname': 'numero', 'type': 'string'}, - {'label': 'Rue', 'varname': 'rue', 'type': 'string'}, - {'label': 'Code postal', 'varname': 'code-postal', 'type': 'string'}, - {'label': 'Ville', 'varname': 'ville', 'type': 'string'}, - ], - } - } - formdef.data_class().wipe() - formdef.fields = [fields.FileField(id='0', label='file', varname='foo', - document_type=document_types['justificatif-de-domicile'])] - formdef.store() - formdata = formdef.data_class()() - metadata = { - 'nom': 'Doe', - 'prenoms': 'John', - 'numero': '169', - 'rue': 'rue du château', - 'code-postal': '75014', - 'ville': 'PARIS', - } - with mock.patch('wcs.portfolio.get_validation', return_value=metadata): - upload = NoUpload('http://whatever.com/') - formdata.data = {'0': upload, '0_structured': upload.metadata} - formdata.id = 1 - substvars = formdata.get_substitution_variables() - assert isinstance(substvars.get('form_var_foo'), NoUpload) - assert substvars['form_var_foo_url'] is None - assert isinstance(substvars.get('form_var_foo_raw'), NoUpload) - for key in upload.metadata: - assert substvars.get('form_var_foo_%s' % key) == upload.metadata[key] - - def test_get_submitter(pub): formdef.data_class().wipe() formdef.fields = [fields.StringField(id='0', label='email', varname='foo', diff --git a/tests/test_formdef.py b/tests/test_formdef.py index 5b398bda..8c017e6a 100644 --- a/tests/test_formdef.py +++ b/tests/test_formdef.py @@ -6,8 +6,6 @@ import time import pytest -from mock import patch - from quixote import cleanup from wcs import formdef from wcs.formdef import FormDef @@ -170,27 +168,20 @@ def test_file_field_migration(): 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], 'label': 'Documents'}} - with patch('wcs.portfolio.get_document_types') as get_document_types: - get_document_types.return_value = { - 'justificatif-de-domicile': { - 'id': 'justificatif-de-domicile', - 'label': 'Justificatif de domicile', - 'fargo': True, - }, - } - FormDef.wipe() - formdef = FormDef() - formdef.name = 'foo' - formdef.fields = [ - FileField(type='file', id='1', label='images & docs'), - FileField(type='file', id='2', label='images')] - formdef.fields[0].__dict__['file_type'] = ['image/*', 'application/pdf,application/vnd.oasis.opendocument.text,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.spreadsheet,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] - formdef.fields[1].__dict__['file_type'] = ['image/*'] - formdef.store() - formdef = FormDef.get(1) - assert 'file_type' not in formdef.fields[0].__dict__ - assert formdef.fields[0].document_type - assert formdef.fields[0].document_type['id'] == '_legacy' - assert formdef.fields[0].document_type['mimetypes'] == ['image/*', 'application/pdf,application/vnd.oasis.opendocument.text,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.spreadsheet,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] - assert formdef.fields[1].document_type['label'] == 'Image files' - assert formdef.fields[0].document_type['label'] == 'Image files, Documents' + + FormDef.wipe() + formdef = FormDef() + formdef.name = 'foo' + formdef.fields = [ + FileField(type='file', id='1', label='images & docs'), + FileField(type='file', id='2', label='images')] + formdef.fields[0].__dict__['file_type'] = ['image/*', 'application/pdf,application/vnd.oasis.opendocument.text,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.spreadsheet,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] + formdef.fields[1].__dict__['file_type'] = ['image/*'] + formdef.store() + formdef = FormDef.get(1) + assert 'file_type' not in formdef.fields[0].__dict__ + assert formdef.fields[0].document_type + assert formdef.fields[0].document_type['id'] == '_legacy' + assert formdef.fields[0].document_type['mimetypes'] == ['image/*', 'application/pdf,application/vnd.oasis.opendocument.text,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.spreadsheet,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] + assert formdef.fields[1].document_type['label'] == 'Image files' + assert formdef.fields[0].document_type['label'] == 'Image files, Documents' diff --git a/tests/test_formdef_import.py b/tests/test_formdef_import.py index 0e5cb0d0..f93a7c1d 100644 --- a/tests/test_formdef_import.py +++ b/tests/test_formdef_import.py @@ -243,21 +243,6 @@ def test_file_field(): assert_xml_import_export_works(formdef) assert_json_import_export_works(formdef, include_id=True) assert_json_import_export_works(formdef) - formdef = FormDef() - formdef.name = 'foo' - formdef.fields = [fields.FileField(type='file', id='1', document_type={ - 'id': 'justificatif-de-domicile', - 'fargo': True, - 'mimetypes': ['application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'image/*'], - 'metadata': [ - {'varname': 'nom', 'label': 'Nom', 'type': 'string'}, - {'varname': 'rue', 'label': 'Rue', 'type': 'string'}, - ] - })] - assert_xml_import_export_works(formdef, include_id=True) - assert_xml_import_export_works(formdef) - assert_json_import_export_works(formdef, include_id=True) - assert_json_import_export_works(formdef) def test_invalid_field_type(): formdef = FormDef() diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py index 28d97954..e64360ab 100644 --- a/wcs/backoffice/management.py +++ b/wcs/backoffice/management.py @@ -1838,7 +1838,7 @@ class FormPage(Directory): class FormBackOfficeStatusPage(FormStatusPage): - _q_exports_orig = ['', 'download', 'json', 'action', 'inspect', 'validate'] + _q_exports_orig = ['', 'download', 'json', 'action', 'inspect'] form_page_class = FormFillPage def html_top(self, title = None): diff --git a/wcs/fields.py b/wcs/fields.py index 6fa68ab8..9dd17a8c 100644 --- a/wcs/fields.py +++ b/wcs/fields.py @@ -15,7 +15,6 @@ # along with this program; if not, see . import datetime -import json import time import random import re @@ -754,17 +753,13 @@ class FileField(WidgetField): self.document_type = self.document_type or {} @property - def metadata(self): - return self.document_type.get('metadata', []) - - @property def file_type(self): - return self.document_type.get('mimetypes', []) + return (self.document_type or {}).get('mimetypes', []) def fill_admin_form(self, form): WidgetField.fill_admin_form(self, form) document_types = self.get_document_types() - cur_dt = self.document_type + cur_dt = self.document_type or {} # SingleSelectWidget compare the value and not the keys, so if we want # the current value not to be hidden, we must reset it with the corresponding # value from settings based on the 'id' @@ -780,25 +775,19 @@ class FileField(WidgetField): form.add(FileSizeWidget, 'max_file_size', title=_('Max file size'), value=self.max_file_size, advanced=not(self.max_file_size)) - form.add(CheckboxWidget, 'allow_portfolio_picking', - title=_('Allow user to pick a file from a portfolio'), - value=self.allow_portfolio_picking, - advanced=(self.allow_portfolio_picking is True)) + if portfolio.has_portfolio(): + form.add(CheckboxWidget, 'allow_portfolio_picking', + title=_('Allow user to pick a file from a portfolio'), + value=self.allow_portfolio_picking, + advanced=(self.allow_portfolio_picking is True)) def get_admin_attributes(self): return WidgetField.get_admin_attributes(self) + [ 'document_type', 'max_file_size', 'allow_portfolio_picking'] def get_view_value(self, value): - r = TemplateIO(html=True) - if not getattr(value, 'no_file', False): - r += htmltext('%s') % ( + return htmltext('%s') % ( value.base_filename, self.id, value) - for meta_field in self.metadata: - if 'varname' in meta_field: - metadata_value = getattr(value, 'metadata', {}).get(meta_field['varname'], '') - r += htmltext('

%s : %s

') % (meta_field['label'], metadata_value) - return r.getvalue() def get_csv_value(self, value, hint=None, **kwargs): if not value: @@ -833,7 +822,6 @@ class FileField(WidgetField): value = get_request().get_field(self.field_key) if value and hasattr(value, 'token'): get_request().form[self.field_key + '$token'] = value.token - kwargs['document_type'] = self.document_type def get_document_types(self): document_types = { @@ -852,12 +840,10 @@ class FileField(WidgetField): } # Local document types document_types.update(get_cfg('filetypes', {})) - # Remote documents types - document_types.update(portfolio.get_document_types()) for key, document_type in document_types.iteritems(): document_type['id'] = key # add current file type if it does not exist anymore in the settings - cur_dt = self.document_type + cur_dt = self.document_type or {} if cur_dt and cur_dt['id'] not in document_types: document_types[cur_dt['id']] = cur_dt return document_types @@ -900,13 +886,9 @@ class FileField(WidgetField): if self.document_type and self.document_type.get('mimetypes'): old_value = self.document_type['mimetypes'] self.document_type['mimetypes'] = '|'.join(self.document_type['mimetypes']) - if self.document_type and self.document_type.get('metadata'): - self.document_type['metadata'] = json.dumps(self.document_type['metadata']) result = super(FileField, self).export_to_xml(charset, include_id=include_id) if self.document_type and self.document_type.get('mimetypes'): self.document_type['mimetypes'] = old_value - if self.document_type and self.document_type.get('metadata'): - self.document_type['metadata'] = json.loads(self.document_type['metadata']) return result def init_with_xml(self, element, charset, include_id=False): @@ -916,16 +898,6 @@ class FileField(WidgetField): self.document_type['mimetypes'] = self.document_type['mimetypes'].split('|') if self.document_type and self.document_type.get('fargo'): self.document_type['fargo'] = self.document_type['fargo'] == 'True' - if self.document_type and self.document_type.get('metadata'): - self.document_type['metadata'] = json.loads(self.document_type['metadata']) - - def store_structured_value(self, data, field_id): - value = data.get(field_id) - return getattr(value, 'metadata', {}) - - def __setstate__(self, state): - self.__dict__ = state - self.document_type = self.document_type or {} register_field_class(FileField) diff --git a/wcs/forms/common.py b/wcs/forms/common.py index cf509dd2..2941e94e 100644 --- a/wcs/forms/common.py +++ b/wcs/forms/common.py @@ -99,27 +99,6 @@ class FormStatusPage(Directory): def html_top(self, title = None): template.html_top(title = title, default_org = _('Forms')) - def validate(self): - if not portfolio.has_portfolio(): - return redirect('.') - field_id = get_request().form.get('field_id') - if not field_id: - return redirect('.') - for field in self.formdef.fields: - if field.id == field_id: - break - else: - return redirect('.') - if field.key != 'file': - return redirect('.') - if not field.document_type.get('fargo', False): - return redirect('.') - if not field.document_type.get('metadata', []): - return redirect('.') - value = self.filled.data.get(field_id) - portfolio.validate(self.filled, field, value) - return redirect('.') - def __init__(self, formdef, filled, register_workflow_subdirs=True): get_publisher().substitutions.feed(filled) self.formdef = formdef @@ -683,44 +662,10 @@ class FormStatusPage(Directory): def display_file_field(self, form_url, field, value): r = TemplateIO(html=True) - validated = None - is_fargo_dt = field.document_type.get('fargo', False) - has_metadata = bool(field.document_type.get('metadata', [])) - if portfolio.has_portfolio() and is_fargo_dt and has_metadata: - validated = portfolio.is_valid(self.filled, field, value) - if validated is False: - extra_class = ' invalid' - else: - extra_class = ' valid' - r += htmltext('
' % extra_class) - else: - r += htmltext('
') + r += htmltext('
') s = field.get_view_value(value) s = s.replace(str('[download]'), str('%sdownload' % form_url)) r += s - if validated is not None and get_request().is_in_backoffice(): - r += htmltext('
') - if validated: - creator = value.metadata['creator'] - created = misc.localstrftime( - time.localtime( - misc.parse_isotime(value.metadata['created']))) - r += htmltext('

%s

') % _( - 'validated by %(creator)s on %(created)s') % { - 'creator': creator, 'created': created} - r += htmltext('

%s

') % (_('Valid from %(start)s to %(end)s') % { - 'start': strftime( - misc.date_format(), - misc.get_as_datetime(value.metadata['start'])), - 'end': strftime( - misc.date_format(), - misc.get_as_datetime(value.metadata['end'])), - }) - elif self.filled.user: - r += htmltext('
' - '
') % ( - field.id, _('Validate')) - r += htmltext('
') r += htmltext('
') return str(r) diff --git a/wcs/portfolio.py b/wcs/portfolio.py index 9bfe3a60..ac92290d 100644 --- a/wcs/portfolio.py +++ b/wcs/portfolio.py @@ -80,94 +80,6 @@ def sha256_of_upload(upload): return hashlib.sha256(upload.get_content()).hexdigest() -def get_document_types(): - if not has_portfolio(): - return {} - try: - response = fargo_get('/document-types/') - except ConnectionError: - get_logger().warning('unable to retrieve document types from fargo') - return {} - if response.get('err') == 0: - result = {} - for schema in response['data']: - d = { - 'id': schema['name'], - 'label': schema['label'], - 'fargo': True, - } - if 'mimetypes' in schema: - d['mimetypes'] = schema['mimetypes'] - result[d['id']] = d - d['metadata'] = schema.get('metadata', []) - return result - return {} - - -def get_validation(url): - try: - result = fargo_get(url) - except ConnectionError: - get_logger().warning('unable to retrieve validation from fargo') - return None - return result['data'] if result else None - - -def get_validations(document_type): - request = get_request() - document_type_id = document_type['id'] - qs = {} - if not request.user: - return [] - if request.user.name_identifiers: - qs['user_nameid'] = request.user.name_identifiers[0] - elif request.user.email: - qs['user_email'] = request.user.email - else: - return [] - path = 'api/validation/%s/' % urllib.quote(document_type_id) - try: - validations = fargo_get(path + '?%s' % urllib.urlencode(qs)) - except ConnectionError: - get_logger().warning('unable to retrieve validations from fargo') - return [] - if validations and validations.get('data', {}).get('results', []): - return validations['data']['results'] - return [] - - -def is_valid(filled, field, upload): - '''Check validation of the uploaded file with Fargo''' - return 'url' in getattr(upload, 'metadata', {}) - - -def validate(filled, field, upload): - '''Compute link to Fargo to validate the given document''' - document_type_id = field.document_type['id'] - url = '/api/validation/%s/' % urllib.quote(document_type_id) - payload = {} - if filled.user: - if filled.user.name_identifiers: - payload['user_nameid'] = filled.user.name_identifiers[0] - else: - payload['user_email'] = filled.user.email - payload['origin'] = get_request().get_server() - payload['creator'] = get_request().user.display_name - payload['content_hash'] = sha256_of_upload(upload) - for meta_field in field.metadata: - if 'varname' in meta_field: - payload[meta_field['varname']] = upload.metadata.get(meta_field['varname'], '') - try: - status, response = fargo_post_json(url, payload) - except ConnectionError: - get_logger().warning('unable to validate document on fargo for %s', filled.get_display_id()) - return - if status == 201: - upload.metadata = response['data'] - filled.data['%s_structured' % field.id] = upload.metadata - filled.store() - - def push_document(user, filename, stream): if not user: return diff --git a/wcs/qommon/form.py b/wcs/qommon/form.py index f2566d8e..bcc4886d 100644 --- a/wcs/qommon/form.py +++ b/wcs/qommon/form.py @@ -65,7 +65,6 @@ from qommon import _, ngettext import misc from strftime import strftime from publisher import get_cfg -from wcs import portfolio from . import ezt QuixoteForm = Form @@ -601,14 +600,6 @@ class UploadWidget(CompositeWidget): self.value = None -class NoUpload(object): - no_file = True - metadata = None - - def __init__(self, validation_url): - self.metadata = portfolio.get_validation(validation_url) - - class FileWithPreviewWidget(CompositeWidget): """Widget that proposes a File Upload widget but that stores the file ondisk so it has a "readonly" mode where the filename is shown.""" @@ -617,14 +608,11 @@ class FileWithPreviewWidget(CompositeWidget): max_file_size = None file_type = None - max_file_size_bytes = None # will be filled automatically + max_file_size_bytes = None # will be filled automatically def __init__(self, name, value=None, **kwargs): - from wcs import fields - CompositeWidget.__init__(self, name, value, **kwargs) self.value = value - self.document_type = kwargs.pop('document_type', None) or {} self.readonly = kwargs.get('readonly') self.max_file_size = kwargs.pop('max_file_size', None) self.allow_portfolio_picking = kwargs.pop('allow_portfolio_picking', True) @@ -635,9 +623,7 @@ class FileWithPreviewWidget(CompositeWidget): hint = '' if self.allow_portfolio_picking: root_url = get_publisher().get_root_url() - if (portfolio.has_portfolio() - and get_request().user - and not self.readonly): + if get_request().user: get_response().add_javascript(['fargo.js']) params = (root_url, _('Pick a file from the portfolio'), @@ -657,38 +643,6 @@ class FileWithPreviewWidget(CompositeWidget): # this could be used for client size validation of file size attrs['data-max-file-size'] = str(self.max_file_size_bytes) self.add(FileWidget, 'file', hint=hint, render_br=False, attrs=attrs) - if self.document_type.get('metadata'): - if self.readonly: - self.add(HiddenWidget, 'validation_url') - else: - validations = portfolio.get_validations(self.document_type) - if validations: - options = [('', _('Known documents'), '')] - options += [(v['url'], v['display'], v['url']) for v in validations] - for validation in validations: - for i, meta_field in enumerate(self.metadata): - # translate varname to f$f - if meta_field['varname'] in validation: - value = validation.pop(meta_field['varname']) - validation['f%s' % i] = value - self.add(SingleSelectWidget, 'validation_url', options=options, - attrs={'data-validations': json.dumps(validations)}) - for i, meta_field in enumerate(self.metadata): - field = fields.get_field_class_by_type(meta_field.get('type', 'string'))() - field.id = i - field.init_with_json(meta_field, include_id=False) - if meta_field.get('varname'): - subvalue = getattr(value, 'metadata', {}).get(meta_field['varname']) - else: - subvalue = None - # required only if composite field is required - field.required = field.required and self.required - field.extra_css_class = 'subwidget' - if self.readonly: - # preview - field.add_to_view_form(self, subvalue) - else: - field.add_to_form(self, subvalue) if value: self.set_value(value) @@ -704,23 +658,24 @@ class FileWithPreviewWidget(CompositeWidget): self.get_widget('token').set_value(self.value.token) def render_content(self): - get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'jquery.iframe-transport.js', - 'jquery.fileupload.js', 'qommon.fileupload.js']) + get_response().add_javascript(['jquery.js', 'jquery-ui.js', + 'jquery.iframe-transport.js', 'jquery.fileupload.js', + 'qommon.fileupload.js']) temp = get_session().get_tempfile(self.get('token')) or {} r = TemplateIO(html=True) - if self.get_widget('file'): - r += self.get_widget('file').render() + for widget in self.get_widgets(): + r += widget.render() r += htmltext('') - r += htmltext('
%s' - % temp.get('base_filename', '')) + r += htmltext('
%s' % temp.get('base_filename', '')) if not self.readonly: - r += htmltext(' %s' - % (_('Remove this file'), _('remove'))) + r += htmltext(' %s' % ( + _('Remove this file'), + _('remove'))) elif temp: filetype = mimetypes.guess_type(temp.get('orig_filename', '')) include_image = False @@ -736,25 +691,12 @@ class FileWithPreviewWidget(CompositeWidget): r += htmltext('' % self.get('token')) r += htmltext('
') - - for widget in self.get_widgets(): - if widget is self.get_widget('file'): - continue - r += widget.render() - return r.getvalue() - @property - def metadata(self): - return self.document_type.get('metadata', []) - def _parse(self, request): self.value = None if self.get('token'): token = self.get('token') - elif self.get('validation_url'): - self.value = NoUpload(self.get('validation_url')) - return elif self.get('file'): token = get_session().add_tempfile(self.get('file')) request.form[self.get_widget('token').get_name()] = token @@ -763,43 +705,13 @@ class FileWithPreviewWidget(CompositeWidget): session = get_session() if token and session.tempfiles and session.tempfiles.has_key(token): + temp = session.tempfiles[token] self.value = session.get_tempfile_content(token) if self.value is None: - # there's no file, check all metadata field are empty too - # if not file and required metadata field become required - if (self.get_widget('file') - and not self.required - and any([self.get('f%s' % i) for i, meta_field in enumerate(self.metadata)])): - self.get_widget('file').required = True - self.get_widget('file').set_error(self.REQUIRED_ERROR) - for i, meta_field in enumerate(self.metadata): - name = 'f%s' % i - required = meta_field.get('required', True) - if required: - widget = self.get_widget(name) - widget.required = True - if not self.get(name): - widget.set_error(self.REQUIRED_ERROR) + # there's no file, the other checks are irrelevant. return - # There is some file, check all required metadata files have been filled - for i, meta_field in enumerate(self.metadata): - name = 'f%s' % i - required = meta_field.get('required', True) - if required: - widget = self.get_widget(name) - widget.required = True - if not self.get(name): - widget.set_error(self.REQUIRED_ERROR) - - if self.metadata: - self.value.metadata = {} - for i, meta_field in enumerate(self.metadata): - name = 'f%s' % i - if 'varname' in meta_field: - self.value.metadata[meta_field['varname']] = self.get(name) - # Don't trust the browser supplied MIME type, update the Upload object # with a MIME type created with magic (or based on the extension if the # module is missing). diff --git a/wcs/qommon/static/css/qommon.css b/wcs/qommon/static/css/qommon.css index 41f83eaf..7472e584 100644 --- a/wcs/qommon/static/css/qommon.css +++ b/wcs/qommon/static/css/qommon.css @@ -87,16 +87,6 @@ div.SingleSelectWidgetWithOther .content .widget { display: inline-block; } -/* nested widgets */ -.widget .subwidget { - padding-left: 2em; -} -div.FileWithPreviewWidget .validation { - display: inline-block; - font-size: xx-small; - margin-right: 2em; -} - p.use-file-from-fargo span { border-bottom: 1px dotted #999; cursor: pointer; diff --git a/wcs/qommon/static/js/qommon.fileupload.js b/wcs/qommon/static/js/qommon.fileupload.js index 78b81af9..eaad66c5 100644 --- a/wcs/qommon/static/js/qommon.fileupload.js +++ b/wcs/qommon/static/js/qommon.fileupload.js @@ -7,18 +7,6 @@ $(function() { } else { $(base_widget).find('.fileinfo').hide(); } - function disable() { - base_widget.find('.subwidget input').prop('disabled', true); - $('form').on('submit', function () { - $('input').prop('disabled', false); - }); - } - function enable() { - if (base_widget.find('.subwidget input:disabled').length) { - base_widget.find('.subwidget input').val(''); - base_widget.find('.subwidget input').prop('disabled', false); - } - } $(this).find('input[type=file]').fileupload({ dataType: 'json', add: function (e, data) { @@ -32,9 +20,7 @@ $(function() { $(base_widget).find('.fileprogress').hide(); $(base_widget).find('.filename').text(data.result[0].name); $(base_widget).find('.fileinfo').show(); - $(base_widget).find('input[name$="$token"]').val(data.result[0].token); - $(base_widget).find('select[name$="$validation_url"]').val(''); - enable(); + $(base_widget).find('input[type=hidden]').val(data.result[0].token); $(base_widget).parents('form').find('input[name=submit]').prop('disabled', false); $(this).hide(); $(base_widget).find('.use-file-from-fargo').hide(); @@ -45,7 +31,7 @@ $(function() { } }); $(this).find('a.remove').click(function() { - $(base_widget).find('input[name$="$token"]').val(''); + $(base_widget).find('input[type=hidden]').val(''); $(base_widget).find('.fileinfo').hide(); $(base_widget).find('input[type=file]').show(); $(base_widget).find('.use-file-from-fargo').show(); @@ -55,32 +41,5 @@ $(function() { $(base_widget).find('input[type=file]').click(); return false; }); - if ($(this).find('select[name$="$validation_url"] option:selected').val()) { - disable(); - } - $(this).find('select[name$="$validation_url"]').on('change', function() { - var url = $(this).find(':selected').val(); - if (url) { - var validations = $(this).data('validations'); - - for (var i = 0; i < validations.length; i++) { - if (validations[i].url == url) { - base_widget.find('a.remove').trigger('click'); - for (var item in validations[i]) { - if (! item) { - continue; - } - var $input = base_widget.find('input[name$="$' + item + '"]'); - if ($input.length) { - $input.val(validations[i][item]); - } - } - disable(); - } - } - } else { - enable(); - } - }); }); }); -- 2.11.0