Projet

Général

Profil

0001-datasources-refuse-to-delete-or-change-slug-of-datas.patch

Nicolas Roche, 12 octobre 2019 00:39

Télécharger (5,71 ko)

Voir les différences:

Subject: [PATCH 1/2] datasources: refuse to delete or change slug of
 datasources in use (#15163)

 tests/test_admin_pages.py | 43 +++++++++++++++++++++++++++++++++++++++
 wcs/admin/data_sources.py | 24 +++++++++++++---------
 wcs/formdef.py            |  9 ++++++++
 3 files changed, 66 insertions(+), 10 deletions(-)
tests/test_admin_pages.py
4855 4855
    resp = resp.follow()
4856 4856
    assert NamedDataSource.count() == 0
4857 4857

  
4858
def test_data_sources_in_use_delete(pub):
4859
    create_superuser(pub)
4860
    NamedDataSource.wipe()
4861
    category = NamedDataSource(name='foobar')
4862
    category.store()
4863

  
4864
    FormDef.wipe()
4865
    formdef = FormDef()
4866
    formdef.name = 'form title'
4867
    formdef.fields = [
4868
        fields.ItemField(id='0', label='string', type='item',
4869
                data_source={'type': 'foobar'}),
4870
    ]
4871
    formdef.store()
4872

  
4873
    app = login(get_app(pub))
4874
    resp = app.get('/backoffice/settings/data-sources/1/')
4875
    resp = app.get('/backoffice/settings/data-sources/1/delete', status=404)
4876

  
4858 4877
def test_data_sources_edit_slug(pub):
4859 4878
    create_superuser(pub)
4860 4879
    NamedDataSource.wipe()
......
4889 4908
    resp = resp.forms[0].submit('submit')
4890 4909
    assert resp.location == 'http://example.net/backoffice/settings/data-sources/1/'
4891 4910

  
4911
def test_data_sources_in_use_edit_slug(pub):
4912
    create_superuser(pub)
4913
    NamedDataSource.wipe()
4914
    data_source = NamedDataSource(name='foobar')
4915
    data_source.data_source = {'type': 'formula', 'value': '[]'}
4916
    data_source.store()
4917

  
4918
    FormDef.wipe()
4919
    formdef = FormDef()
4920
    app = login(get_app(pub))
4921
    resp = app.get('/backoffice/settings/data-sources/1/')
4922
    resp = resp.click(href='edit')
4923

  
4924
    formdef.name = 'form title'
4925
    formdef.fields = [
4926
        fields.ItemField(id='0', label='string', type='item',
4927
                data_source={'type': 'foobar'}),
4928
    ]
4929
    formdef.store()
4930

  
4931
    assert NamedDataSource.get(1).slug == 'foobar'
4932
    resp.forms[0]['slug'] = 'barfoo'
4933
    resp = resp.forms[0].submit('submit', status=404)
4934

  
4892 4935
def test_wscalls_new(pub):
4893 4936
    create_superuser(pub)
4894 4937
    NamedWsCall.wipe()
wcs/admin/data_sources.py
20 20

  
21 21
from ..qommon import _
22 22
from ..qommon import template
23
from ..qommon import errors
23 24
from ..qommon.form import *
24 25
from ..qommon.misc import json_response
25 26
from ..qommon.backoffice.menu import html_top
26 27
from wcs.data_sources import (NamedDataSource, DataSourceSelectionWidget,
27 28
        get_structured_items)
28
from wcs.formdef import FormDef
29
from wcs.formdef import FormDef, get_formdefs_of_all_kinds
29 30

  
30 31
class NamedDataSourceUI(object):
31 32
    def __init__(self, datasource):
......
33 34
        if self.datasource is None:
34 35
            self.datasource = NamedDataSource()
35 36

  
37
    def is_datasource_in_use(self):
38
        for formdef in get_formdefs_of_all_kinds():
39
            if formdef.is_using_datasource(self.datasource):
40
                return True
41
        return False
42

  
36 43
    def get_form(self):
37 44
        form = Form(enctype='multipart/form-data',
38 45
                advanced_label=_('Additional options'))
......
95 102
            slug = form.get_widget('slug').parse()
96 103
        else:
97 104
            slug = None
105
        if self.datasource.slug != slug and self.is_datasource_in_use():
106
            raise errors.TraversalError()
98 107

  
99 108
        for nds in NamedDataSource.select():
100 109
            if nds.id == self.datasource.id:
......
135 144
    def usage_in_formdefs(self):
136 145
        formdefs = []
137 146
        for formdef in FormDef.select(ignore_errors=True, ignore_migration=True, order_by='name'):
138
            for field in (formdef.fields or []):
139
                data_source = getattr(field, 'data_source', None)
140
                if not data_source:
141
                    continue
142
                if data_source.get('type') == self.datasource.slug:
143
                    formdefs.append(formdef)
144
                    break
145
            else:
146
                continue
147
            if formdef.is_using_datasource(self.datasource):
148
                formdefs.append(formdef)
147 149
        return formdefs
148 150

  
149 151
    def preview_block(self):
......
198 200
        return r.getvalue()
199 201

  
200 202
    def delete(self):
203
        if self.datasource_ui.is_datasource_in_use():
204
            raise errors.TraversalError()
201 205
        form = Form(enctype='multipart/form-data')
202 206
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
203 207
                        'You are about to irrevocably delete this data source.')))
wcs/formdef.py
1414 1414
            if changed:
1415 1415
                formdef.store()
1416 1416

  
1417
    def is_using_datasource(self, datasource):
1418
        for field in (self.fields or []):
1419
            data_source = getattr(field, 'data_source', None)
1420
            if not data_source:
1421
                continue
1422
            if data_source.get('type') == datasource.slug:
1423
                return True
1424
        return False
1425

  
1417 1426
    class _EmptyClass(object):  # helper for instance creation without calling __init__
1418 1427
        pass
1419 1428

  
1420
-