Projet

Général

Profil

0001-api-include-roles-in-bundle-export-68036.patch

Frédéric Péters, 09 août 2022 09:38

Télécharger (13,1 ko)

Voir les différences:

Subject: [PATCH] api: include roles in bundle export (#68036)

 tests/api/test_export_import.py | 29 +++++++++++++++++++++++------
 wcs/api_export_import.py        | 19 ++++++++++++++++---
 wcs/roles.py                    |  4 ++++
 wcs/wf/dispatch.py              | 12 +++++++++++-
 wcs/wf/form.py                  |  1 +
 wcs/wf/roles.py                 |  5 ++++-
 wcs/wf/sendmail.py              |  1 +
 wcs/workflows.py                | 30 +++++++++++++++++++++++++++++-
 8 files changed, 89 insertions(+), 12 deletions(-)
tests/api/test_export_import.py
91 91

  
92 92

  
93 93
def test_export_import_dependencies(pub):
94
    role = pub.role_class(name='Test role')
95
    role.store()
96

  
94 97
    formdef = FormDef()
95 98
    formdef.name = 'Test'
96 99
    formdef.store()
......
111 114
    workflow.variables_formdef.fields = [StringField(label='Test', id='1')]
112 115

  
113 116
    status = workflow.add_status('New')
114
    status.add_action('form')
117
    action = status.add_action('form')
118
    action.by = [role.id]
115 119

  
116 120
    data_source = NamedDataSource(name='foobar')
117 121
    data_source.store()
......
121 125
    display_form.formdef.fields.append(StringField(label='Test', data_source={'type': 'foobar'}))
122 126

  
123 127
    send_mail = status.add_action('sendmail')
128
    send_mail.to = [role.id]
124 129

  
125 130
    workflow.store()
126 131

  
......
132 137

  
133 138
    resp = get_app(pub).get(sign_uri('/api/export-import/forms/'))
134 139
    resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
135
    assert resp.json['data']
136 140
    assert {(x['id'], x['type']) for x in resp.json['data']} == {('test', 'workflows'), ('test', 'blocks')}
141
    for dependency in resp.json['data']:
142
        get_app(pub).get(sign_uri(dependency['urls']['export']))
137 143

  
138 144
    resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
139 145
    resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
140
    assert resp.json['data']
141 146
    assert {(x['id'], x['type']) for x in resp.json['data']} == {
142 147
        ('foobar', 'data-sources'),
143 148
        ('test', 'blocks'),
149
        ('test-role', 'roles'),
144 150
    }
151
    for dependency in resp.json['data']:
152
        resp = get_app(pub).get(sign_uri(dependency['urls']['export']))
153
        if 'test-role' in dependency['urls']['export']:
154
            assert resp.json == {'name': 'Test role', 'slug': 'test-role', 'uuid': None}
155
            assert resp.content_type == 'application/json'
156
        else:
157
            assert resp.content_type == 'text/xml'
145 158

  
146 159
    mail_template = MailTemplate(name='test mail template')
147 160
    mail_template.store()
......
149 162
    workflow.store()
150 163
    resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
151 164
    resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
152
    assert resp.json['data']
153 165
    assert {(x['id'], x['type']) for x in resp.json['data']} == {
154 166
        ('foobar', 'data-sources'),
155 167
        ('test', 'blocks'),
156 168
        ('test-mail-template', 'mail-templates'),
169
        ('test-role', 'roles'),
157 170
    }
171
    for dependency in resp.json['data']:
172
        get_app(pub).get(sign_uri(dependency['urls']['export']))
158 173
    resp = get_app(pub).get(sign_uri(resp.json['data'][-1]['urls']['dependencies']))
159 174
    assert resp.json['data'] == []
160 175

  
......
165 180
    resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
166 181
    resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
167 182
    resp = get_app(pub).get(sign_uri(resp.json['data'][-1]['urls']['dependencies']))
168
    assert resp.json['data']
169 183
    assert {(x['id'], x['type']) for x in resp.json['data']} == {('cat', 'mail-templates-categories')}
184
    for dependency in resp.json['data']:
185
        get_app(pub).get(sign_uri(dependency['urls']['export']))
170 186

  
171 187
    resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
172 188
    resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
......
179 195
    data_source.store()
180 196
    resp = get_app(pub).get(sign_uri('/api/export-import/workflows/'))
181 197
    resp = get_app(pub).get(sign_uri(resp.json['data'][0]['urls']['dependencies']))
182
    resp = get_app(pub).get(sign_uri(resp.json['data'][1]['urls']['dependencies']))
198
    data_sources_entry = [x for x in resp.json['data'] if x['type'] == 'data-sources'][0]
199
    resp = get_app(pub).get(sign_uri(data_sources_entry['urls']['dependencies']))
183 200
    assert {(x['id'], x['type']) for x in resp.json['data']} == {('cat', 'data-sources-categories')}
184 201

  
185 202

  
wcs/api_export_import.py
36 36
from wcs.data_sources import NamedDataSource, StubNamedDataSource
37 37
from wcs.formdef import FormDef
38 38
from wcs.mail_templates import MailTemplate
39
from wcs.sql import Role
39 40
from wcs.workflows import Workflow
40 41
from wcs.wscalls import NamedWsCall
41 42

  
......
52 53
    'data-sources-categories': DataSourceCategory,
53 54
    'forms-categories': Category,
54 55
    'forms': FormDef,
56
    'roles': Role,
55 57
    'mail-templates-categories': MailTemplateCategory,
56 58
    'mail-templates': MailTemplate,
57 59
    'workflows-categories': WorkflowCategory,
......
117 119
            'singular': _('Category (data Sources)'),
118 120
            'minor': True,
119 121
        },
122
        {
123
            'id': 'roles',
124
            'text': _('Roles'),
125
            'singular': _('Role'),
126
            'minor': True,
127
        },
120 128
    ]
121 129
    for obj in response:
122 130
        obj['urls'] = {
......
166 174
    obj = get_object(objects, slug)
167 175
    if obj is None:
168 176
        raise Http404()
169
    etree = obj.export_to_xml(include_id=True)
170
    indent_xml(etree)
171
    return HttpResponse(ET.tostring(etree), content_type='text/xml')
177
    if hasattr(obj, 'export_for_application'):
178
        content, content_type = obj.export_for_application()
179
    else:
180
        etree = obj.export_to_xml(include_id=True)
181
        indent_xml(etree)
182
        content = ET.tostring(etree)
183
        content_type = 'text/xml'
184
    return HttpResponse(content, content_type=content_type)
172 185

  
173 186

  
174 187
@signature_required
wcs/roles.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import json
17 18
import urllib.parse
18 19
import xml.etree.ElementTree as ET
19 20

  
......
114 115
            ET.SubElement(root, boolean_attribute).text = value
115 116
        return root
116 117

  
118
    def export_for_application(self):
119
        return (json.dumps({'name': self.name, 'slug': self.slug, 'uuid': self.uuid}), 'application/json')
120

  
117 121
    @classmethod
118 122
    def import_from_xml(cls, fd, charset=None, include_id=False):
119 123
        try:
wcs/wf/dispatch.py
21 21
from quixote.html import htmltext
22 22

  
23 23
from wcs.roles import get_user_roles
24
from wcs.workflows import WorkflowStatusItem, XmlSerialisable, get_role_name_and_slug, register_item_class
24
from wcs.workflows import (
25
    WorkflowStatusItem,
26
    XmlSerialisable,
27
    get_role_dependencies,
28
    get_role_name_and_slug,
29
    register_item_class,
30
)
25 31

  
26 32
from ..qommon import _
27 33
from ..qommon.form import (
......
136 142
        if rules:
137 143
            self.rules = rules
138 144

  
145
    def get_dependencies(self):
146
        yield from get_role_dependencies([self.role_id])
147
        yield from get_role_dependencies([x.get('role_id') for x in self.rules])
148

  
139 149
    def get_line_details(self):
140 150
        if self.role_key:
141 151
            function_label = self.parent.parent.roles.get(self.role_key, '?')
wcs/wf/form.py
193 193
        return changed
194 194

  
195 195
    def get_dependencies(self):
196
        yield from super().get_dependencies()
196 197
        if self.formdef and self.formdef.fields:
197 198
            for field in self.formdef.fields:
198 199
                yield from field.get_dependencies()
wcs/wf/roles.py
20 20

  
21 21
from wcs.api_utils import MissingSecret, get_secret_and_orig, sign_url
22 22
from wcs.roles import get_user_roles
23
from wcs.workflows import WorkflowStatusItem, register_item_class
23
from wcs.workflows import WorkflowStatusItem, get_role_dependencies, register_item_class
24 24

  
25 25
from ..qommon import _
26 26
from ..qommon.form import SingleSelectWidgetWithOther
......
57 57
            return role.name
58 58
        return _('unknown - %s') % self.role_id
59 59

  
60
    def get_dependencies(self):
61
        yield from get_role_dependencies([self.role_id])
62

  
60 63

  
61 64
class AddRoleWorkflowStatusItem(RoleMixin, WorkflowStatusItem):
62 65
    description = _('Role Addition')
wcs/wf/sendmail.py
70 70
    comment = None
71 71

  
72 72
    def get_dependencies(self):
73
        yield from super().get_dependencies()
73 74
        yield MailTemplate.get_by_slug(self.mail_template)
74 75

  
75 76
    def _get_role_id_from_xml(self, elem, charset, include_id=False, snapshot=False):
wcs/workflows.py
142 142
    pass
143 143

  
144 144

  
145
def get_role_dependencies(roles):
146
    for role_id in roles or []:
147
        if not role_id:
148
            continue
149
        role_id = str(role_id)
150
        if role_id.startswith('_') or role_id == 'logged-users':
151
            continue
152
        yield get_publisher().role_class.get(role_id, ignore_errors=True)
153

  
154

  
145 155
class AttachmentSubstitutionProxy:
146 156
    def __init__(self, formdata, attachment_evolution_part):
147 157
        self.formdata = formdata
......
638 648
        if self.possible_status:
639 649
            for status in self.possible_status:
640 650
                yield from status.get_dependencies()
651
        if self.global_actions:
652
            for action in self.global_actions:
653
                yield from action.get_dependencies()
641 654

  
642 655
    @classmethod
643 656
    def get(cls, id, ignore_errors=False, ignore_migration=False):
......
1329 1342
    def roles_init_with_xml(self, elem, charset, include_id=False, snapshot=False):
1330 1343
        self._roles_init_with_xml('roles', elem, charset, include_id=include_id, snapshot=snapshot)
1331 1344

  
1345
    def get_dependencies(self):
1346
        yield from get_role_dependencies(self.roles)
1347

  
1332 1348

  
1333 1349
class WorkflowGlobalActionTimeoutTriggerMarker(EvolutionPart):
1334 1350
    def __init__(self, timeout_id):
......
1637 1653
                        )
1638 1654
                        break
1639 1655

  
1656
    def get_dependencies(self):
1657
        return []
1658

  
1640 1659

  
1641 1660
class WorkflowGlobalActionWebserviceTrigger(WorkflowGlobalActionManualTrigger):
1642 1661
    key = 'webservice'
......
1673 1692

  
1674 1693
        return [('hooks', WorkflowGlobalActionWebserviceHooksDirectory(formdata))]
1675 1694

  
1695
    def get_dependencies(self):
1696
        return []
1697

  
1676 1698

  
1677 1699
class SerieOfActionsMixin:
1678 1700
    items = None
......
1782 1804
            trigger_o.parent = self
1783 1805
            trigger_o.init_with_xml(trigger, charset, include_id=include_id, snapshot=snapshot)
1784 1806

  
1807
    def get_dependencies(self):
1808
        yield from super().get_dependencies()
1809
        for trigger in self.triggers or []:
1810
            yield from trigger.get_dependencies()
1811

  
1785 1812

  
1786 1813
class WorkflowCriticalityLevel:
1787 1814
    id = None
......
2194 2221
        return self.parent.parent.get_add_role_label()
2195 2222

  
2196 2223
    def get_dependencies(self):
2197
        return []
2224
        yield from get_role_dependencies(getattr(self, 'by', None))
2225
        yield from get_role_dependencies(getattr(self, 'to', None))
2198 2226

  
2199 2227
    @noop_mark
2200 2228
    def perform(self, formdata):
2201
-