Projet

Général

Profil

0001-api-change-schema-of-formdefs-user-forms-and-user-dr.patch

Thomas Noël, 16 janvier 2018 11:38

Télécharger (24,9 ko)

Voir les différences:

Subject: [PATCH] api: change schema of formdefs, user/forms and user/drafts
 APIs (#13184)

All responses now have the form {"err": x, "data": y}.
 help/fr/api-user.page | 146 ++++++++++++++++++++++---------------------
 tests/test_api.py     | 169 ++++++++++++++++++++++++++++++--------------------
 wcs/api.py            |  13 ++--
 3 files changed, 186 insertions(+), 142 deletions(-)
help/fr/api-user.page
63 63
    </p>
64 64
<screen>
65 65
<output style="prompt">$ </output><input>curl https://www.example.net/api/user/forms</input>
66
<output>[
67
    {
68
        "category_id": "1",
69
        "category_name": "Divers",
70
        "datetime": "2014-03-28 15:36:52",
71
        "form_name": "Demande d'inscription",
72
        "form_slug": "demande-d-inscription",
73
        "form_number": "123",
74
        "form_number_raw": "123",
75
        "form_receipt_date": "28/03/2014",
76
        "form_receipt_time": "15:36",
77
        "form_status": "Nouveau",
78
        "form_status_is_endpoint": false,
79
        "form_uri": "demande-d-inscription/123/",
80
        "form_url": "http://www.example.net/demande-d-inscription/123/",
81
        "form_url_backoffice": "http://www.example.net/backoffice/demande-d-inscription/123/",
82
        "name": "Demande d'inscription",
83
        "status": "Nouveau",
84
        "title": "Demande d'inscription #123 (Nouveau)",
85
        "url": "http://www.example.net/demande-d-inscription/123/",
86
    },
87
    {
88
        "category_id": "2",
89
        "category_name": "Prise de rendez-vous",
90
        "datetime": "2014-03-17 10:39:52",
91
        "form_name": "Rendez-vous avec le service B",
92
        "form_slug": "rendez-vous-service-b",
93
        "form_number": "456",
94
        "form_number_raw": "456",
95
        "form_receipt_date": "17/03/2014",
96
        "form_receipt_time": "10:39",
97
        "form_status": "En cours",
98
        "form_status_is_endpoint": false,
99
        "form_uri": "rendez-vous-service-b/456/",
100
        "form_url": "http://www.example.net/rendez-vous-service-b/456/",
101
        "form_url_backoffice": "http://www.example.net/backoffice/rendez-vous-service-b/456/",
102
        "name": "Rendez-vous avec le service B"",
103
        "status": "Nouveau",
104
        "title": "Rendez-vous avec le service B #456 (En cours)",
105
        "url": "http://www.example.net/rendez-vous-service-b/456/",
106
    },
107
    {
108
        "category_id": "3",
109
        "category_name": "Modification de vos coordonn\u00e9es",
110
        "datetime": "2014-03-17 10:42:17",
111
        "form_name": "Changement d'adresse",
112
        "form_slug": "changement-d-adresse",
113
        "form_number": "424",
114
        "form_number_raw": "424",
115
        "form_receipt_date": "17/03/2014",
116
        "form_receipt_time": "10:42",
117
        "form_status": "Traitement de la demande termin\u00e9",
118
        "form_status_is_endpoint": true,
119
        "form_uri": "changement-d-adresse/424/",
120
        "form_url": "http://www.example.net/changement-d-adresse/424/",
121
        "form_url_backoffice": "http://www.example.net/backoffice/changement-d-adresse/424/",
122
        "name": "Changement d'adresse",
123
        "status": "Traitement de la demande termin\u00e9",
124
        "title": "Changement d'adresse #424 (Traitement de la demande termin\u00e9)",
125
        "url": "http://www.example.net/changement-d-adresse/424/",
126
    }
127
]</output></screen>
66
<output>{
67
    "err": 0,
68
    "data": [
69
        {
70
            "category_id": "1",
71
            "category_name": "Divers",
72
            "datetime": "2014-03-28 15:36:52",
73
            "form_name": "Demande d'inscription",
74
            "form_slug": "demande-d-inscription",
75
            "form_number": "123",
76
            "form_number_raw": "123",
77
            "form_receipt_date": "28/03/2014",
78
            "form_receipt_time": "15:36",
79
            "form_status": "Nouveau",
80
            "form_status_is_endpoint": false,
81
            "form_uri": "demande-d-inscription/123/",
82
            "form_url": "http://www.example.net/demande-d-inscription/123/",
83
            "form_url_backoffice": "http://www.example.net/backoffice/demande-d-inscription/123/",
84
            "name": "Demande d'inscription",
85
            "status": "Nouveau",
86
            "title": "Demande d'inscription #123 (Nouveau)",
87
            "url": "http://www.example.net/demande-d-inscription/123/",
88
        },
89
        {
90
            "category_id": "2",
91
            "category_name": "Prise de rendez-vous",
92
            "datetime": "2014-03-17 10:39:52",
93
            "form_name": "Rendez-vous avec le service B",
94
            "form_slug": "rendez-vous-service-b",
95
            "form_number": "456",
96
            "form_number_raw": "456",
97
            "form_receipt_date": "17/03/2014",
98
            "form_receipt_time": "10:39",
99
            "form_status": "En cours",
100
            "form_status_is_endpoint": false,
101
            "form_uri": "rendez-vous-service-b/456/",
102
            "form_url": "http://www.example.net/rendez-vous-service-b/456/",
103
            "form_url_backoffice": "http://www.example.net/backoffice/rendez-vous-service-b/456/",
104
            "name": "Rendez-vous avec le service B"",
105
            "status": "Nouveau",
106
            "title": "Rendez-vous avec le service B #456 (En cours)",
107
            "url": "http://www.example.net/rendez-vous-service-b/456/",
108
        },
109
        {
110
            "category_id": "3",
111
            "category_name": "Modification de vos coordonn\u00e9es",
112
            "datetime": "2014-03-17 10:42:17",
113
            "form_name": "Changement d'adresse",
114
            "form_slug": "changement-d-adresse",
115
            "form_number": "424",
116
            "form_number_raw": "424",
117
            "form_receipt_date": "17/03/2014",
118
            "form_receipt_time": "10:42",
119
            "form_status": "Traitement de la demande termin\u00e9",
120
            "form_status_is_endpoint": true,
121
            "form_uri": "changement-d-adresse/424/",
122
            "form_url": "http://www.example.net/changement-d-adresse/424/",
123
            "form_url_backoffice": "http://www.example.net/backoffice/changement-d-adresse/424/",
124
            "name": "Changement d'adresse",
125
            "status": "Traitement de la demande termin\u00e9",
126
            "title": "Changement d'adresse #424 (Traitement de la demande termin\u00e9)",
127
            "url": "http://www.example.net/changement-d-adresse/424/",
128
        }
129
    ]
130
}</output></screen>
128 131

  
129 132
<p>
130 133
Il est possible de recevoir un ensemble plus complet de données en passant un
......
143 146

  
144 147
<screen>
145 148
<output style="prompt">$ </output><input>curl https://www.example.net/api/user/drafts</input>
146
<output>[
147
    {
148
        "datetime": "2014-07-21 10:15:21",
149
        "name": "Demande de relecture",
150
        "title": "Demande de relecture, brouillon enregistré le 21/07/2014 10:15",
151
        "url": "http://www.example.net/demande-de-relecture/164"
152
    }
153
]</output></screen>
149
<output>{
150
    "err": 0,
151
    "data": [
152
        {
153
            "datetime": "2014-07-21 10:15:21",
154
            "name": "Demande de relecture",
155
            "title": "Demande de relecture, brouillon enregistré le 21/07/2014 10:15",
156
            "url": "http://www.example.net/demande-de-relecture/164"
157
        }
158
    ]
159
}</output></screen>
154 160

  
155 161
<note>
156 162
<p>Note de compatibilité : cette information est également disponible à
tests/test_api.py
174 174
    output = get_app(pub).get('/categories?%s&signature=%s' % (query, signature))
175 175
    assert output.json == {'data': []}
176 176
    output = get_app(pub).get('/json?%s&signature=%s' % (query, signature))
177
    assert output.json == []
177
    assert output.json == {'err': 0, 'data': []}
178 178

  
179 179
def test_get_user_from_api_query_string_error_unknown_nameid_valid_endpoint(pub):
180 180
    # check the categories and forms endpoints accept an unknown NameID
......
188 188
    output = get_app(pub).get('/categories?%s&signature=%s' % (query, signature))
189 189
    assert output.json == {'data': []}
190 190
    output = get_app(pub).get('/json?%s&signature=%s' % (query, signature))
191
    assert output.json == []
191
    assert output.json == {'err': 0, 'data': []}
192 192

  
193 193
def test_get_user_from_api_query_string_error_success_sha1(pub, local_user):
194 194
    timestamp = datetime.datetime.utcnow().isoformat()[:19] + 'Z'
......
316 316
    resp2 = get_app(pub).get('/', headers={'Accept': 'application/json'})
317 317
    resp3 = get_app(pub).get('/api/formdefs/')
318 318
    assert resp1.json == resp2.json == resp3.json
319
    assert resp1.json[0]['title'] == 'test'
320
    assert resp1.json[0]['url'] == 'http://example.net/test/'
321
    assert resp1.json[0]['count'] == 0
322
    assert resp1.json[0]['redirection'] == False
323
    assert resp1.json[0]['description'] == 'plop'
324
    assert resp1.json[0]['keywords'] == ['mobile', 'test']
325
    assert resp1.json[0]['functions'].keys() == ['_receiver']
326
    assert resp1.json[0]['functions']['_receiver']['label'] == 'Recipient'
327
    assert resp1.json[0]['functions']['_receiver']['role']['slug'] == role.slug
328
    assert resp1.json[0]['functions']['_receiver']['role']['name'] == role.name
319
    assert resp1.json['data'][0]['title'] == 'test'
320
    assert resp1.json['data'][0]['url'] == 'http://example.net/test/'
321
    assert resp1.json['data'][0]['count'] == 0
322
    assert resp1.json['data'][0]['redirection'] == False
323
    assert resp1.json['data'][0]['description'] == 'plop'
324
    assert resp1.json['data'][0]['keywords'] == ['mobile', 'test']
325
    assert resp1.json['data'][0]['functions'].keys() == ['_receiver']
326
    assert resp1.json['data'][0]['functions']['_receiver']['label'] == 'Recipient'
327
    assert resp1.json['data'][0]['functions']['_receiver']['role']['slug'] == role.slug
328
    assert resp1.json['data'][0]['functions']['_receiver']['role']['name'] == role.name
329 329

  
330 330
    # backoffice_submission formdef : none
331 331
    resp1 = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
332
    assert len(resp1.json) == 0
332
    assert resp1.json['err'] == 0
333
    assert len(resp1.json['data']) == 0
333 334

  
334 335
def test_limited_formdef_list(pub, local_user):
335 336
    Role.wipe()
......
346 347
    formdef.store()
347 348

  
348 349
    resp = get_app(pub).get('/api/formdefs/')
349
    assert len(resp.json) == 1
350
    assert resp.json['err'] == 0
351
    assert len(resp.json['data']) == 1
350 352
    # not present in backoffice-submission formdefs
351 353
    resp = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
352
    assert len(resp.json) == 0
354
    assert resp.json['err'] == 0
355
    assert len(resp.json['data']) == 0
353 356

  
354 357
    # check it's not advertised
355 358
    formdef.roles = [role.id]
......
358 361
    resp2 = get_app(pub).get(sign_uri('/api/formdefs/?NameID='))
359 362
    resp3 = get_app(pub).get(sign_uri('/api/formdefs/?NameID=XXX'))
360 363
    resp4 = get_app(pub).get(sign_uri('/api/formdefs/?NameID=%s' % local_user.name_identifiers[0]))
361
    assert len(resp.json) == 0
364
    assert resp.json['err'] == 0
365
    assert len(resp.json['data']) == 0
362 366
    assert resp.json == resp2.json == resp3.json == resp4.json
363 367
    # still not present in backoffice-submission formdefs
364 368
    resp = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
365
    assert len(resp.json) == 0
369
    assert resp.json['err'] == 0
370
    assert len(resp.json['data']) == 0
366 371

  
367 372
    # unless user has correct roles
368 373
    local_user.roles = [role.id]
369 374
    local_user.store()
370 375
    resp = get_app(pub).get(sign_uri('/api/formdefs/?NameID=%s' % local_user.name_identifiers[0]))
371
    assert len(resp.json) == 1
376
    assert resp.json['err'] == 0
377
    assert len(resp.json['data']) == 1
372 378

  
373 379
    local_user.roles = []
374 380
    local_user.store()
......
380 386
    resp2 = get_app(pub).get(sign_uri('/api/formdefs/?NameID='))
381 387
    resp3 = get_app(pub).get(sign_uri('/api/formdefs/?NameID=XXX'))
382 388
    resp4 = get_app(pub).get(sign_uri('/api/formdefs/?NameID=%s' % local_user.name_identifiers[0]))
383
    assert len(resp.json) == 1
384
    assert resp.json[0]['authentication_required']
389
    assert resp.json['err'] == 0
390
    assert len(resp.json['data']) == 1
391
    assert resp.json['data'][0]['authentication_required']
385 392
    assert resp.json == resp2.json == resp3.json == resp4.json
386 393

  
387 394
    formdef.required_authentication_contexts = ['fedict']
388 395
    formdef.store()
389 396
    resp = get_app(pub).get('/api/formdefs/')
390
    assert resp.json[0]['required_authentication_contexts'] == ['fedict']
397
    assert resp.json['data'][0]['required_authentication_contexts'] == ['fedict']
391 398

  
392 399
def test_formdef_list_redirection(pub):
393 400
    FormDef.wipe()
......
399 406
    formdef.store()
400 407

  
401 408
    resp1 = get_app(pub).get('/json')
402
    assert resp1.json[0]['title'] == 'test'
403
    assert resp1.json[0]['url'] == 'http://example.net/test/'
404
    assert resp1.json[0]['count'] == 0
405
    assert resp1.json[0]['redirection'] == True
409
    assert resp1.json['err'] == 0
410
    assert resp1.json['data'][0]['title'] == 'test'
411
    assert resp1.json['data'][0]['url'] == 'http://example.net/test/'
412
    assert resp1.json['data'][0]['count'] == 0
413
    assert resp1.json['data'][0]['redirection'] == True
406 414

  
407 415
def test_backoffice_submission_formdef_list(pub, local_user):
408 416
    Role.wipe()
......
419 427
    formdef.store()
420 428

  
421 429
    resp = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
422
    assert len(resp.json) == 0
430
    assert resp.json['err'] == 0
431
    assert len(resp.json['data']) == 0
423 432

  
424 433
    # check it's not advertised ...
425 434
    formdef.backoffice_submission_roles = [role.id]
426 435
    formdef.store()
427 436
    resp = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
428
    assert len(resp.json) == 0
437
    assert resp.json['err'] == 0
438
    assert len(resp.json['data']) == 0
429 439

  
430 440
    # even if it's advertised on frontoffice
431 441
    formdef.always_advertise = True
432 442
    formdef.store()
433 443
    resp = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
434
    assert len(resp.json) == 0
444
    assert resp.json['err'] == 0
445
    assert len(resp.json['data']) == 0
435 446

  
436 447
    # ... unless user has correct roles
437 448
    local_user.roles = [role.id]
438 449
    local_user.store()
439 450
    resp = get_app(pub).get(sign_uri('/api/formdefs/?backoffice-submission=on&NameID=%s' %
440 451
                                     local_user.name_identifiers[0]))
441
    assert len(resp.json) == 1
452
    assert resp.json['err'] == 0
453
    assert len(resp.json['data']) == 1
442 454

  
443 455
    # but not advertised if it's a redirection
444 456
    formdef.disabled = True
445 457
    formdef.disabled_redirection = 'http://example.net'
446 458
    formdef.store()
447 459
    resp = get_app(pub).get('/api/formdefs/?backoffice-submission=on')
448
    assert len(resp.json) == 0
460
    assert resp.json['err'] == 0
461
    assert len(resp.json['data']) == 0
449 462

  
450 463
def test_formdef_schema(pub):
451 464
    Workflow.wipe()
......
914 927
    resp = get_app(pub).get('/api/categories/category/formdefs/')
915 928
    resp2 = get_app(pub).get('/category/json')
916 929
    assert resp.json == resp2.json
917
    assert len(resp.json) == 2
918
    assert resp.json[0]['title'] == 'test'
919
    assert resp.json[0]['url'] == 'http://example.net/test/'
920
    assert resp.json[0]['count'] == 0
921
    assert resp.json[0]['redirection'] == False
922
    assert resp.json[0]['category'] == 'Category'
923
    assert resp.json[0]['category_slug'] == 'category'
930
    assert resp.json['err'] == 0
931
    assert len(resp.json['data']) == 2
932
    assert resp.json['data'][0]['title'] == 'test'
933
    assert resp.json['data'][0]['url'] == 'http://example.net/test/'
934
    assert resp.json['data'][0]['count'] == 0
935
    assert resp.json['data'][0]['redirection'] == False
936
    assert resp.json['data'][0]['category'] == 'Category'
937
    assert resp.json['data'][0]['category_slug'] == 'category'
924 938

  
925 939
    get_app(pub).get('/api/categories/XXX/formdefs/', status=404)
926 940

  
927 941
    resp = get_app(pub).get('/api/categories/category/formdefs/?backoffice-submission=on')
928
    assert len(resp.json) == 0
942
    assert resp.json['err'] == 0
943
    assert len(resp.json['data']) == 0
929 944

  
930 945
    Role.wipe()
931 946
    role = Role(name='test')
......
936 951
    formdef.backoffice_submission_roles = [role.id]
937 952
    formdef.store()
938 953
    resp = get_app(pub).get('/api/categories/category/formdefs/?backoffice-submission=on')
939
    assert len(resp.json) == 0
954
    assert resp.json['err'] == 0
955
    assert len(resp.json['data']) == 0
940 956
    resp = get_app(pub).get(sign_uri(
941 957
        '/api/categories/category/formdefs/?backoffice-submission=on&NameID=%s' %
942 958
        local_user.name_identifiers[0]))
943
    assert len(resp.json) == 0
959
    assert resp.json['err'] == 0
960
    assert len(resp.json['data']) == 0
944 961
    # ... unless user has correct roles
945 962
    local_user.roles = [role.id]
946 963
    local_user.store()
947 964
    resp = get_app(pub).get(sign_uri(
948 965
        '/api/categories/category/formdefs/?backoffice-submission=on&NameID=%s' %
949 966
        local_user.name_identifiers[0]))
950
    assert len(resp.json) == 1
967
    assert resp.json['err'] == 0
968
    assert len(resp.json['data']) == 1
951 969

  
952 970
def test_categories_full(pub):
953 971
    test_categories(pub)
......
1200 1218
    formdef.data_class().wipe()
1201 1219

  
1202 1220
    resp = get_app(pub).get(sign_uri('/api/user/forms', user=local_user))
1203
    assert len(resp.json) == 0
1221
    assert resp.json['err'] == 0
1222
    assert len(resp.json['data']) == 0
1204 1223

  
1205 1224
    formdata = formdef.data_class()()
1206 1225
    formdata.data = {'0': 'foo@localhost', '1': 'xxx'}
......
1212 1231
    resp = get_app(pub).get(sign_uri('/api/user/forms', user=local_user))
1213 1232
    resp2 = get_app(pub).get(sign_uri('/myspace/forms', user=local_user))
1214 1233
    resp3 = get_app(pub).get(sign_uri('/api/users/%s/forms' % local_user.id))
1215
    assert len(resp.json) == 1
1216
    assert resp.json[0]['form_name'] == 'test'
1217
    assert resp.json[0]['form_slug'] == 'test'
1218
    assert resp.json[0]['form_status'] == 'New'
1219
    assert datetime.datetime.strptime(resp.json[0]['form_receipt_datetime'],
1220
                                      '%Y-%m-%dT%H:%M:%S')
1221
    assert resp.json[0]['keywords'] == ['hello', 'world']
1234
    assert resp.json['err'] == 0
1235
    assert len(resp.json['data']) == 1
1236
    assert resp.json['data'][0]['form_name'] == 'test'
1237
    assert resp.json['data'][0]['form_slug'] == 'test'
1238
    assert resp.json['data'][0]['form_status'] == 'New'
1239
    assert resp.json['data'][0]['keywords'] == ['hello', 'world']
1222 1240
    assert resp.json == resp2.json == resp3.json
1223 1241

  
1224
    resp = get_app(pub).get(sign_uri('/api/user/forms?full=on', user=local_user))
1225
    assert resp.json[0]['fields']['foobar'] == 'foo@localhost'
1226
    assert resp.json[0]['keywords'] == ['hello', 'world']
1242
    resp = get_app(pub).get(sign_uri('/api/user/forms?&full=on', user=local_user))
1243
    assert resp.json['err'] == 0
1244
    assert resp.json['data'][0]['fields']['foobar'] == 'foo@localhost'
1245
    assert resp.json['data'][0]['keywords'] == ['hello', 'world']
1227 1246

  
1228 1247
    formdef.disabled = True
1229 1248
    formdef.store()
1230 1249
    resp = get_app(pub).get(sign_uri('/api/user/forms', user=local_user))
1231
    assert len(resp.json) == 1
1250
    assert resp.json['err'] == 0
1251
    assert len(resp.json['data']) == 1
1252

  
1253
    resp = get_app(pub).get(sign_uri('/api/user/forms?&NameID=xxx'))
1254
    assert resp.json == {'err': 1, 'err_desc': 'unknown NameID', 'data': []}
1255

  
1232 1256

  
1233 1257
    formdata = formdef.data_class()()
1234 1258
    formdata.user_id = local_user.id
......
1237 1261
    formdata.store()
1238 1262

  
1239 1263
    resp = get_app(pub).get(sign_uri('/api/user/forms', user=local_user))
1240
    assert len(resp.json) == 1
1264
    assert resp.json['err'] == 0
1265
    assert len(resp.json['data']) == 1
1241 1266

  
1242 1267
    resp = get_app(pub).get(sign_uri('/api/user/forms?include-drafts=true', user=local_user))
1243
    assert len(resp.json) == 1
1268
    assert resp.json['err'] == 0
1269
    assert len(resp.json['data']) == 1
1244 1270

  
1245 1271
    formdef.disabled = False
1246 1272
    formdef.store()
1247 1273

  
1248 1274
    resp = get_app(pub).get(sign_uri('/api/user/forms?include-drafts=true', user=local_user))
1249
    assert len(resp.json) == 2
1275
    assert resp.json['err'] == 0
1276
    assert len(resp.json['data']) == 2
1250 1277

  
1251
    draft_formdata = [x for x in resp.json if x['status'] == 'Draft'][0]
1278
    draft_formdata = [x for x in resp.json['data'] if x['status'] == 'Draft'][0]
1252 1279
    assert draft_formdata.get('url')[-1] != '/'
1253 1280

  
1254 1281
def test_user_drafts(pub, local_user):
......
1267 1294
    formdef.data_class().wipe()
1268 1295

  
1269 1296
    resp = get_app(pub).get(sign_uri('/api/user/drafts', user=local_user))
1270
    assert len(resp.json) == 0
1297
    assert resp.json['err'] == 0
1298
    assert len(resp.json['data']) == 0
1271 1299

  
1272 1300
    formdata = formdef.data_class()()
1273 1301
    upload = PicklableUpload('test.txt', 'text/plain', 'ascii')
......
1281 1309

  
1282 1310
    resp = get_app(pub).get(sign_uri('/api/user/drafts', user=local_user))
1283 1311
    resp2 = get_app(pub).get(sign_uri('/myspace/drafts', user=local_user))
1284
    assert len(resp.json) == 1
1312
    assert resp.json['err'] == 0
1313
    assert len(resp.json['data']) == 1
1285 1314
    assert resp.json == resp2.json
1286
    assert not 'fields' in resp.json[0]
1287
    assert resp.json[0]['keywords'] == ['hello', 'world']
1315
    assert not 'fields' in resp.json['data'][0]
1316
    assert resp.json['data'][0]['keywords'] == ['hello', 'world']
1288 1317

  
1289 1318
    resp = get_app(pub).get(sign_uri('/api/user/drafts?full=on', user=local_user))
1290
    assert 'fields' in resp.json[0]
1291
    assert resp.json[0]['fields']['foobar'] == 'foo@localhost'
1292
    assert 'file' not in resp.json[0]['fields'] # no file export in full lists
1293
    assert resp.json[0]['keywords'] == ['hello', 'world']
1319
    assert resp.json['err'] == 0
1320
    assert 'fields' in resp.json['data'][0]
1321
    assert resp.json['data'][0]['fields']['foobar'] == 'foo@localhost'
1322
    assert 'file' not in resp.json['data'][0]['fields']  # no file export in full lists
1323
    assert resp.json['data'][0]['keywords'] == ['hello', 'world']
1294 1324

  
1295 1325
    formdef.enable_tracking_codes = False
1296 1326
    formdef.store()
1297 1327
    resp = get_app(pub).get(sign_uri('/api/user/drafts', user=local_user))
1298
    assert len(resp.json) == 0
1328
    assert resp.json['err'] == 0
1329
    assert len(resp.json['data']) == 0
1299 1330

  
1300 1331
    formdef.enable_tracking_codes = True
1301 1332
    formdef.disabled = True
1302 1333
    formdef.store()
1303 1334
    resp = get_app(pub).get(sign_uri('/api/user/drafts', user=local_user))
1304
    assert len(resp.json) == 0
1335
    assert resp.json['err'] == 0
1336
    assert len(resp.json['data']) == 0
1337

  
1338
    resp = get_app(pub).get(sign_uri('/api/user/drafts?&NameID=xxx'))
1339
    assert resp.json == {'err': 1, 'err_desc': 'unknown NameID', 'data': []}
1305 1340

  
1306 1341
def test_api_list_formdata(pub, local_user):
1307 1342
    Role.wipe()
wcs/api.py
447 447
            del formdict['category_position']
448 448

  
449 449
        get_response().set_content_type('application/json')
450
        return json.dumps(list_forms)
450
        return json.dumps({'err': 0, 'data': list_forms})
451 451

  
452 452
    def _q_lookup(self, component):
453 453
        try:
......
553 553

  
554 554
    def forms(self, include_drafts=False, include_non_drafts=True):
555 555
        get_response().set_content_type('application/json')
556
        user = self.user or get_user_from_api_query_string() or get_request().user
556
        try:
557
            user = self.user or get_user_from_api_query_string() or get_request().user
558
        except UnknownNameIdAccessForbiddenError:
559
            return json.dumps({'err': 1, 'err_desc': 'unknown NameID', 'data': []})
557 560
        if not user:
558
            raise AccessForbiddenError('no user specified')
561
            return json.dumps({'err': 1, 'err_desc': 'no user specified', 'data': []})
559 562
        forms = []
560 563
        include_drafts = include_drafts or get_request().form.get('include-drafts') == 'true'
561 564
        for form in self.get_user_forms(user):
......
573 576
                continue
574 577
            forms.append(formdata_dict)
575 578

  
576
        return json.dumps(forms,
579
        return json.dumps({'err': 0, 'data': forms},
577 580
                cls=misc.JSONEncoder,
578 581
                encoding=get_publisher().site_charset)
579 582

  
......
691 694
        for role in Role.select():
692 695
            list_roles.append(role.get_json_export_dict())
693 696
        get_response().set_content_type('application/json')
694
        return json.dumps({'data': list_roles})
697
        return json.dumps({'err': 0, 'data': list_roles})
695 698

  
696 699
    def validate_expression(self):
697 700
        get_response().set_content_type('application/json')
698
-