REST API tests: patch job/annotations, patch job (#4351)

main
Kirill Sizov 4 years ago committed by GitHub
parent 0f0d5bd018
commit 01eaf362aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -295,10 +295,39 @@
"version": 3
},
"3": {
"shapes": [],
"shapes": [
{
"attributes": [],
"frame": 0,
"group": 0,
"id": 28,
"label_id": 6,
"occluded": false,
"points": [
155.5,
634.4814453125,
222.17951945080313,
575.8846681922205,
214.09713958810244,
384.9384439359292,
160.55137299771377,
255.6203661327254,
96.90263157894879,
137.41556064073302,
284.8179633867294,
65.68443935926916,
354.52848970251944,
264.713043478263
],
"rotation": 0.0,
"source": "manual",
"type": "polyline",
"z_order": 0
}
],
"tags": [],
"tracks": [],
"version": 0
"version": 6
},
"4": {
"shapes": [
@ -1434,16 +1463,72 @@
"version": 3
},
"7": {
"shapes": [],
"shapes": [
{
"attributes": [],
"frame": 0,
"group": 0,
"id": 29,
"label_id": 9,
"occluded": false,
"points": [
364.0361328125,
528.87890625,
609.5286041189956,
586.544622425632,
835.2494279176244,
360.0000000000018,
543.6247139588122,
175.4691075514893,
326.9656750572103,
192.76887871853796,
244.58581235698148,
319.63386727689067
],
"rotation": 0.0,
"source": "manual",
"type": "polygon",
"z_order": 0
}
],
"tags": [],
"tracks": [],
"version": 0
"version": 3
},
"8": {
"shapes": [],
"tags": [],
"tracks": [],
"version": 0
},
"9": {
"shapes": [
{
"attributes": [],
"frame": 0,
"group": 0,
"id": 27,
"label_id": 11,
"occluded": false,
"points": [
448.3779296875,
356.4892578125,
438.2558352402775,
761.3861556064112,
744.1780320366161,
319.37356979405195,
446.1288329519466,
163.03832951945333
],
"rotation": 0.0,
"source": "manual",
"type": "polygon",
"z_order": 0
}
],
"tags": [],
"tracks": [],
"version": 3
}
}
}

@ -2,8 +2,8 @@
-- PostgreSQL database dump
--
-- Dumped from database version 10.19
-- Dumped by pg_dump version 10.19
-- Dumped from database version 10.20
-- Dumped by pg_dump version 10.20
SET statement_timeout = 0;
SET lock_timeout = 0;
@ -2640,7 +2640,6 @@ COPY public.auth_user (id, password, last_login, is_superuser, username, first_n
7 pbkdf2_sha256$260000$EtdCZTYNPHPX50kM67A7kA$JxuHkmB25RkeMszSV9Pd58E9AFdSu3Rx2UYSAKu/q4k= \N f worker2 Worker Second worker2@cvat.org f t 2021-12-14 18:30:43+00
8 pbkdf2_sha256$260000$PNnmu5EKgxZCY9HQgNLfta$JjsE9zrFYJ3ISUHANjjwnxuiGNRGIyVamqnqrkqR9fQ= \N f worker3 Worker Third worker3@cvat.org f t 2021-12-14 18:31:25+00
9 pbkdf2_sha256$260000$ipL3D6HSba1Cn7pzb5Q7bh$OFx/xO6Q3Q5sBGq3W3MBsmqFhVjkPmVVfaQdnJ8FAtg= \N f worker4 Worker Fourth worker4@cvat.org f t 2021-12-14 18:32:01+00
11 pbkdf2_sha256$260000$Zw76ANIvIsDngZGsTv2G8O$piTVoqHrpTskW8rI1FBT9rzM2dcpjhrcOfI3pDgtjbo= \N f business2 Business Second business2@cvat.org f t 2021-12-14 18:34:01+00
12 pbkdf2_sha256$260000$KcNRm6RwodBaGfWhh7ngqB$SsKUBx7vF1Ee0WBDwExd/JI39w1Ee0cBoox7lqNbhCk= \N f business3 Business Third business3@cvat.org f t 2021-12-14 18:34:34+00
13 pbkdf2_sha256$260000$BbdWU6TKtVfIAW00Dk4Qyb$mkqf3VrZULPrzfH5NFEeEYCnzBPLaBBsVgdeTCve4lA= \N f business4 Business Fourth business4@cvat.org f t 2021-12-14 18:35:15+00
14 pbkdf2_sha256$260000$47xWwGNsT3dvBc1qZDcLvC$fLC2y72acILlhGFiVp3nA/bnCxY/mRb7xOqOh7Es95k= \N f dummy1 Dummy First dummy1@cvat.org f t 2021-12-14 18:36:00+00
@ -2650,8 +2649,9 @@ COPY public.auth_user (id, password, last_login, is_superuser, username, first_n
18 pbkdf2_sha256$260000$uOqP32bk2zHuvO0sdGBGmu$hMbzA1yBWcY5rIU670sZ3SHXRLUa7bCkbrMnrEDGSRM= \N t admin2 Admin Second admin2@cvat.org t t 2021-12-14 18:38:46+00
6 pbkdf2_sha256$260000$15iUjDNh5gPg5683u1HhOG$fF8hW6AR90o9SCsO/MomzdQFkgQsMUW3YQUlwwiC1vA= 2021-12-14 19:11:21.04874+00 f worker1 Worker First worker1@cvat.org f t 2021-12-14 18:30:00+00
10 pbkdf2_sha256$260000$X4F89IRqnBtojZuHidrwQG$j1+EpXfyvMesHdod4N+dNUfF4WKS2NWFfeGDec/43as= 2022-01-19 13:52:59.477881+00 f business1 Business First business1@cvat.org f t 2021-12-14 18:33:06+00
1 pbkdf2_sha256$260000$DevmxlmLwciP1P6sZs2Qag$U9DFtjTWx96Sk95qY6UXVcvpdQEP2LcoFBftk5D2RKY= 2022-02-11 14:54:28.083729+00 t admin1 Admin First admin1@cvat.org t t 2021-12-14 18:04:57+00
2 pbkdf2_sha256$260000$Pf2xYWXBedoAJ504jyDD8e$8sJ244Ai0xhZrUTelapPNHlEg7CV0cCUaxbcxZtfaug= 2022-02-16 06:24:53.910205+00 f user1 User First user1@cvat.org f t 2021-12-14 18:21:09+00
11 pbkdf2_sha256$260000$Zw76ANIvIsDngZGsTv2G8O$piTVoqHrpTskW8rI1FBT9rzM2dcpjhrcOfI3pDgtjbo= 2022-02-21 10:29:16.518442+00 f business2 Business Second business2@cvat.org f t 2021-12-14 18:34:01+00
1 pbkdf2_sha256$260000$DevmxlmLwciP1P6sZs2Qag$U9DFtjTWx96Sk95qY6UXVcvpdQEP2LcoFBftk5D2RKY= 2022-02-21 10:37:08.94795+00 t admin1 Admin First admin1@cvat.org t t 2021-12-14 18:04:57+00
\.
@ -2691,8 +2691,8 @@ COPY public.auth_user_user_permissions (id, user_id, permission_id) FROM stdin;
COPY public.authtoken_token (key, created, user_id) FROM stdin;
a959159194c4b5238d95ef4e07919110fab346b0 2021-12-14 19:44:48.519942+00 10
f952dc4730c58346882176f775ccaaf2a1c72416 2021-12-22 08:11:58.498742+00 1
e28ce88d18614314476dec601b5c29b9093045f1 2022-02-16 06:24:53.902374+00 2
48372a6aac494a9932803913ec9088216778b57c 2022-02-21 10:37:08.935479+00 1
\.
@ -2919,6 +2919,8 @@ po0rbd1yhywmc0i2jfam69r419a66aj8 .eJxVjMsOwiAQRf-FtSE8pB1cuvcbCMMMUjWQlHZl_HdD0o
v28l0efbrv9x06z97ilwcf7lwtuf4ctc .eJxVjDsOwjAQRO_iGlm22fhDSc8ZrLV3gwPIluKkQtydREoBzRTz3sxbRFyXEtfOc5xIXIRW4vRbJsxPrjuhB9Z7k7nVZZ6S3BV50C5vjfh1Pdy_g4K9bGuLXqMDQqdDTtYN6AHIIoGGMIJlQwxB-VFn3gLPzjil3ABkAIBZfL7_vTer:1nABOV:0UAK9VV6D18QF1-189XQ2T9LrQUSdioGNoHdRUzzt7o 2022-02-02 13:52:59.489923+00
wf6d6vzf4u74l08o0qgbqehei21hibea .eJxVjDEOwjAMRe-SGUUkpHZgZO8ZIttxSAG1UtNOiLtDpQ6w_vfef5lE61LT2nROQzYX48zhd2OSh44byHcab5OVaVzmge2m2J02209Zn9fd_Tuo1Oq3DrGwD040Ro_-nJmJgkgsqAAIioCi0KGKMhU4Mgip6wjRF6JyMu8PBAI5Mw:1nIXJc:oovNJRods5cbviWOWush4H3jDdP8XklEignva_EnQ8Q 2022-02-25 14:54:28.092369+00
9rh2r15lb3xra3kdqjtll5n4zw7ebw95 .eJxVjDsOwjAQBe_iGln-xJ9Q0ucM1q69xgFkS3FSIe5OIqWA9s3Me7MA21rC1mkJc2JXptjld0OIT6oHSA-o98Zjq-syIz8UftLOp5bodTvdv4MCvey1tOiNIpGNATlq55IZvaABd4Ao1RCzARLWJ5dRA2kJGqxU1kfjPRL7fAHVPjfN:1nKDkD:rZM4YHHS9MckfKB5KrsvNBVMegYSRdlMqL3uDJRE0Cg 2022-03-02 06:24:53.914069+00
khn67dfajnzkr0tlusuyyub011gt0aqb .eJxVjMEOwiAQRP-FsyEsobL16N1vIAvLStVAUtqT8d9tkx70OPPezFsFWpcS1p7nMLG6KFCn3y5Seua6A35QvTedWl3mKepd0Qft-tY4v66H-3dQqJdt7UU4MedxGKwFh0RoCBFi4niOTsSAHQFA_JaYmI2nTBEdGRRrSX2-CY443A:1nM5q9:nf3N_nhzYu-XfEC1O2ICYP2Zt9XXPPVziSLrP5uHSVw 2022-03-07 10:22:45.432248+00
5x9v6r58e4l9if78anupog0ittsq2w3j .eJxVjMEOwiAQRP-FsyEsobL16N1vIAvLStVAUtqT8d9tkx70OPPezFsFWpcS1p7nMLG6KFCn3y5Seua6A35QvTedWl3mKepd0Qft-tY4v66H-3dQqJdt7UU4MedxGKwFh0RoCBFi4niOTsSAHQFA_JaYmI2nTBEdGRRrSX2-CY443A:1nM644:zfo0j_Zkrm04UxrDj8g_nnsXrpWtRzL4oRx3hAdqyqI 2022-03-07 10:37:08.963511+00
\.
@ -3306,6 +3308,17 @@ COPY public.engine_clientfile (id, file, data_id) FROM stdin;
359 /home/django/data/data/4/raw/134.png 4
360 /home/django/data/data/5/raw/test_video_1.mp4 5
361 /home/django/data/data/6/raw/test_pointcloud_pcd.zip 6
362 /home/django/data/data/7/raw/10.png 7
363 /home/django/data/data/7/raw/3.png 7
364 /home/django/data/data/7/raw/9.png 7
365 /home/django/data/data/7/raw/6.png 7
366 /home/django/data/data/7/raw/0.png 7
367 /home/django/data/data/7/raw/8.png 7
368 /home/django/data/data/7/raw/2.png 7
369 /home/django/data/data/7/raw/7.png 7
370 /home/django/data/data/7/raw/5.png 7
371 /home/django/data/data/7/raw/1.png 7
372 /home/django/data/data/7/raw/4.png 7
\.
@ -3342,6 +3355,7 @@ COPY public.engine_data (id, chunk_size, size, image_quality, start_frame, stop_
4 72 58 70 0 57 imageset imageset cache local \N lexicographical
5 72 25 70 0 24 imageset video cache local \N lexicographical
6 72 1 70 0 0 imageset imageset cache local \N lexicographical
7 72 11 70 0 10 imageset imageset cache local \N lexicographical
\.
@ -3710,6 +3724,17 @@ COPY public.engine_image (id, path, frame, height, width, data_id) FROM stdin;
358 98.png 56 370 615 4
359 99.png 57 545 343 4
360 test_pointcloud_pcd/pointcloud/000001.pcd 0 1 100 6
361 0.png 0 983 827 7
362 1.png 1 547 467 7
363 10.png 2 202 598 7
364 2.png 3 276 449 7
365 3.png 4 999 170 7
366 4.png 5 471 473 7
367 5.png 6 745 607 7
368 6.png 7 578 853 7
369 7.png 8 270 823 7
370 8.png 9 179 545 7
371 9.png 10 932 827 7
\.
@ -3730,14 +3755,15 @@ COPY public.engine_issue (id, frame, "position", created_date, updated_date, job
--
COPY public.engine_job (id, segment_id, assignee_id, status, stage, state) FROM stdin;
3 3 \N annotation annotation new
5 5 \N validation acceptance new
2 2 6 annotation annotation new
1 1 \N annotation annotation new
6 6 7 annotation annotation new
4 4 \N validation validation new
7 7 \N annotation annotation new
8 8 \N annotation annotation new
1 1 1 annotation annotation new
9 9 \N annotation annotation in progress
3 3 \N annotation annotation in progress
7 7 9 annotation annotation in progress
\.
@ -3761,6 +3787,18 @@ COPY public.engine_jobcommit (id, version, "timestamp", message, owner_id, job_i
13 4 2021-12-22 07:22:30.331021+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 4
14 5 2021-12-22 07:22:30.362857+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 4
15 6 2021-12-22 07:22:30.388715+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 4
16 1 2022-02-21 10:32:04.068136+00 Changes: tags - 0; shapes - 1; tracks - 0 \N 9
17 2 2022-02-21 10:32:04.169838+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 9
18 3 2022-02-21 10:32:04.256121+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 9
19 1 2022-02-21 10:37:22.961448+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 3
20 2 2022-02-21 10:37:23.075321+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 3
21 3 2022-02-21 10:37:23.187161+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 3
22 4 2022-02-21 10:37:27.7082+00 Changes: tags - 0; shapes - 1; tracks - 0 \N 3
23 5 2022-02-21 10:37:27.834371+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 3
24 6 2022-02-21 10:37:27.95231+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 3
25 1 2022-02-21 10:40:21.267763+00 Changes: tags - 0; shapes - 1; tracks - 0 \N 7
26 2 2022-02-21 10:40:21.354689+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 7
27 3 2022-02-21 10:40:21.435822+00 Changes: tags - 0; shapes - 0; tracks - 0 \N 7
\.
@ -3779,6 +3817,8 @@ COPY public.engine_label (id, name, task_id, color, project_id) FROM stdin;
8 dog \N #406040 2
9 car 5 #2080c0 \N
10 car 6 #2080c0 \N
11 cat 7 #6080c0 \N
12 dog 7 #406040 \N
\.
@ -3829,6 +3869,9 @@ COPY public.engine_labeledshape (id, frame, "group", type, occluded, z_order, po
24 52 0 rectangle f 0 85.9462890625,138.1123046875,166.75294494628906,391.78382873535156 4 5 manual 0
25 52 0 rectangle f 0 45.03125,638.294921875,224.0333251953125,770.2450256347656 4 5 manual 0
26 53 0 rectangle f 0 34.384765625,283.845703125,108.30784606933594,382.30724334716797 4 5 manual 0
27 0 0 polygon f 0 448.3779296875,356.4892578125,438.2558352402775,761.3861556064112,744.1780320366161,319.37356979405195,446.1288329519466,163.03832951945333 9 11 manual 0
28 0 0 polyline f 0 155.5,634.4814453125,222.17951945080313,575.8846681922205,214.09713958810244,384.9384439359292,160.55137299771377,255.6203661327254,96.90263157894879,137.41556064073302,284.8179633867294,65.68443935926916,354.52848970251944,264.713043478263 3 6 manual 0
29 0 0 polygon f 0 364.0361328125,528.87890625,609.5286041189956,586.544622425632,835.2494279176244,360.0000000000018,543.6247139588122,175.4691075514893,326.9656750572103,192.76887871853796,244.58581235698148,319.63386727689067 7 9 manual 0
\.
@ -3935,6 +3978,7 @@ COPY public.engine_segment (id, start_frame, stop_frame, task_id) FROM stdin;
6 0 57 4
7 0 24 5
8 0 0 6
9 0 10 7
\.
@ -3954,9 +3998,10 @@ COPY public.engine_task (id, name, mode, created_date, updated_date, status, bug
2 task2 annotation 2021-12-14 18:50:29.458488+00 2021-12-22 07:14:15.234748+00 annotation 2 0 \N 23 \N 2 2d 1
1 task1 annotation 2021-12-14 18:43:47.601289+00 2021-12-22 07:15:22.942484+00 annotation 2 0 \N 130 \N 1 2d \N
4 task1_in_project2 annotation 2021-12-14 19:55:57.475273+00 2021-12-22 07:17:34.836384+00 annotation 10 0 \N 58 2 4 2d train 2
3 task1_in_project1 annotation 2021-12-14 19:48:33.089778+00 2021-12-22 07:19:33.85476+00 annotation 10 0 \N 50 1 3 2d Train \N
5 task2 interpolation 2022-02-16 06:25:48.168612+00 2022-02-16 06:25:48.889352+00 annotation 2 5 \N 25 \N 5 2d \N
6 task3 annotation 2022-02-16 06:26:54.631217+00 2022-02-16 06:26:54.836403+00 annotation 2 0 \N 1 \N 6 3d \N
3 task1_in_project1 annotation 2021-12-14 19:48:33.089778+00 2022-02-21 10:37:27.697705+00 annotation 10 0 \N 50 1 3 2d Train \N
5 task2 interpolation 2022-02-16 06:25:48.168612+00 2022-02-21 10:40:21.257604+00 annotation 2 5 \N 25 \N 5 2d \N
7 task_2_org2 annotation 2022-02-21 10:31:52.429478+00 2022-02-21 10:41:38.540427+00 annotation 11 0 7 11 \N 7 2d 2
\.
@ -4102,7 +4147,7 @@ SELECT pg_catalog.setval('public.auth_permission_id_seq', 88, true);
-- Name: auth_user_groups_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.auth_user_groups_id_seq', 44, true);
SELECT pg_catalog.setval('public.auth_user_groups_id_seq', 47, true);
--
@ -4158,7 +4203,7 @@ SELECT pg_catalog.setval('public.engine_attributespec_id_seq', 1, true);
-- Name: engine_clientfile_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_clientfile_id_seq', 361, true);
SELECT pg_catalog.setval('public.engine_clientfile_id_seq', 372, true);
--
@ -4179,14 +4224,14 @@ SELECT pg_catalog.setval('public.engine_comment_id_seq', 6, true);
-- Name: engine_data_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_data_id_seq', 6, true);
SELECT pg_catalog.setval('public.engine_data_id_seq', 7, true);
--
-- Name: engine_image_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_image_id_seq', 360, true);
SELECT pg_catalog.setval('public.engine_image_id_seq', 371, true);
--
@ -4200,21 +4245,21 @@ SELECT pg_catalog.setval('public.engine_issue_id_seq', 4, true);
-- Name: engine_job_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_job_id_seq', 8, true);
SELECT pg_catalog.setval('public.engine_job_id_seq', 9, true);
--
-- Name: engine_jobcommit_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_jobcommit_id_seq', 15, true);
SELECT pg_catalog.setval('public.engine_jobcommit_id_seq', 27, true);
--
-- Name: engine_label_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_label_id_seq', 10, true);
SELECT pg_catalog.setval('public.engine_label_id_seq', 12, true);
--
@ -4235,7 +4280,7 @@ SELECT pg_catalog.setval('public.engine_labeledimageattributeval_id_seq', 1, fal
-- Name: engine_labeledshape_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_labeledshape_id_seq', 26, true);
SELECT pg_catalog.setval('public.engine_labeledshape_id_seq', 29, true);
--
@ -4298,7 +4343,7 @@ SELECT pg_catalog.setval('public.engine_remotefile_id_seq', 1, false);
-- Name: engine_segment_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_segment_id_seq', 8, true);
SELECT pg_catalog.setval('public.engine_segment_id_seq', 9, true);
--
@ -4312,7 +4357,7 @@ SELECT pg_catalog.setval('public.engine_serverfile_id_seq', 1, false);
-- Name: engine_task_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root
--
SELECT pg_catalog.setval('public.engine_task_id_seq', 6, true);
SELECT pg_catalog.setval('public.engine_task_id_seq', 7, true);
--

@ -1,10 +1,16 @@
{
"count": 8,
"count": 9,
"next": null,
"previous": null,
"results": [
{
"assignee": null,
"assignee": {
"first_name": "Admin",
"id": 1,
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
},
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
@ -109,7 +115,7 @@
"project_id": 1,
"stage": "annotation",
"start_frame": 0,
"state": "new",
"state": "in progress",
"status": "annotation",
"stop_frame": 49,
"task_id": 3,
@ -241,7 +247,13 @@
"url": "http://localhost:8080/api/jobs/6"
},
{
"assignee": null,
"assignee": {
"first_name": "Worker",
"id": 9,
"last_name": "Fourth",
"url": "http://localhost:8080/api/users/9",
"username": "worker4"
},
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
@ -259,7 +271,7 @@
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "new",
"state": "in progress",
"status": "annotation",
"stop_frame": 24,
"task_id": 5,
@ -289,6 +301,37 @@
"stop_frame": 0,
"task_id": 6,
"url": "http://localhost:8080/api/jobs/8"
},
{
"assignee": null,
"bug_tracker": null,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"dimension": "2d",
"id": 9,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 11,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 12,
"name": "dog"
}
],
"mode": "annotation",
"project_id": null,
"stage": "annotation",
"start_frame": 0,
"state": "in progress",
"status": "annotation",
"stop_frame": 10,
"task_id": 7,
"url": "http://localhost:8080/api/jobs/9"
}
]
}

@ -1,8 +1,74 @@
{
"count": 6,
"count": 7,
"next": null,
"previous": null,
"results": [
{
"assignee": {
"first_name": "Worker",
"id": 7,
"last_name": "Second",
"url": "http://localhost:8080/api/users/7",
"username": "worker2"
},
"bug_tracker": "",
"created_date": "2022-02-21T10:31:52.429478Z",
"data": 7,
"data_chunk_size": 72,
"data_compressed_chunk_type": "imageset",
"data_original_chunk_type": "imageset",
"dimension": "2d",
"id": 7,
"image_quality": 70,
"labels": [
{
"attributes": [],
"color": "#6080c0",
"id": 11,
"name": "cat"
},
{
"attributes": [],
"color": "#406040",
"id": 12,
"name": "dog"
}
],
"mode": "annotation",
"name": "task_2_org2",
"organization": 2,
"overlap": 0,
"owner": {
"first_name": "Business",
"id": 11,
"last_name": "Second",
"url": "http://localhost:8080/api/users/11",
"username": "business2"
},
"project_id": null,
"segment_size": 11,
"segments": [
{
"jobs": [
{
"assignee": null,
"id": 9,
"stage": "annotation",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/9"
}
],
"start_frame": 0,
"stop_frame": 10
}
],
"size": 11,
"status": "annotation",
"subset": "",
"updated_date": "2022-02-21T10:41:38.540427Z",
"url": "http://localhost:8080/api/tasks/7"
},
{
"assignee": null,
"bug_tracker": "",
@ -93,10 +159,16 @@
{
"jobs": [
{
"assignee": null,
"assignee": {
"first_name": "Worker",
"id": 9,
"last_name": "Fourth",
"url": "http://localhost:8080/api/users/9",
"username": "worker4"
},
"id": 7,
"stage": "annotation",
"state": "new",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/7"
}
@ -108,7 +180,7 @@
"size": 25,
"status": "annotation",
"subset": "",
"updated_date": "2022-02-16T06:25:48.889352Z",
"updated_date": "2022-02-21T10:40:21.257604Z",
"url": "http://localhost:8080/api/tasks/5"
},
{
@ -235,7 +307,7 @@
"assignee": null,
"id": 3,
"stage": "annotation",
"state": "new",
"state": "in progress",
"status": "annotation",
"url": "http://localhost:8080/api/jobs/3"
}
@ -275,7 +347,7 @@
"size": 148,
"status": "annotation",
"subset": "Train",
"updated_date": "2021-12-22T07:19:33.854760Z",
"updated_date": "2022-02-21T10:37:27.697705Z",
"url": "http://localhost:8080/api/tasks/3"
},
{
@ -386,7 +458,13 @@
{
"jobs": [
{
"assignee": null,
"assignee": {
"first_name": "Admin",
"id": 1,
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
},
"id": 1,
"stage": "annotation",
"state": "new",

@ -14,7 +14,7 @@
"is_active": true,
"is_staff": true,
"is_superuser": true,
"last_login": "2022-02-11T14:54:28.083729Z",
"last_login": "2022-02-21T10:37:08.947950Z",
"last_name": "First",
"url": "http://localhost:8080/api/users/1",
"username": "admin1"
@ -174,7 +174,7 @@
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": null,
"last_login": "2022-02-21T10:29:16.518442Z",
"last_name": "Second",
"url": "http://localhost:8080/api/users/11",
"username": "business2"

@ -31,7 +31,7 @@ def drop_test_db():
def create_test_db():
docker_cp(source=osp.join(ASSETS_DIR, 'cvat_db'), target='cvat_db:/')
cvat_db_container('createdb test_db')
cvat_db_container('psql -U root -d test_db -f /cvat_db/cvat_db.sql')
cvat_db_container('psql -U root -q -d test_db -f /cvat_db/cvat_db.sql')
@pytest.fixture(scope='session', autouse=True)
def init_test_db():
@ -118,6 +118,53 @@ def annotations():
def users_by_name(users):
return {user['username']: user for user in users}
@pytest.fixture(scope='module')
def jobs_by_org(tasks, jobs):
data = {}
for job in jobs:
data.setdefault(tasks[job['task_id']]['organization'], []).append(job)
data[''] = data.pop(None, [])
return data
@pytest.fixture(scope='module')
def assignee_id():
def get_id(data):
if data.get('assignee') is not None:
return data['assignee']['id']
return get_id
def ownership(func):
def wrap(user_id, resource_id):
if resource_id is None:
return False
return func(user_id, resource_id)
return wrap
@pytest.fixture(scope='module')
def is_project_staff(projects, assignee_id):
@ownership
def check(user_id, pid):
return user_id == projects[pid]['owner']['id'] or \
user_id == assignee_id(projects[pid])
return check
@pytest.fixture(scope='module')
def is_task_staff(tasks, is_project_staff, assignee_id):
@ownership
def check(user_id, tid):
return user_id == tasks[tid]['owner']['id'] or \
user_id == assignee_id(tasks[tid]) or \
is_project_staff(user_id, tasks[tid]['project_id'])
return check
@pytest.fixture(scope='module')
def is_job_staff(jobs, is_task_staff, assignee_id):
@ownership
def check(user_id, jid):
return user_id == assignee_id(jobs[jid]) or \
is_task_staff(user_id, jobs[jid]['task_id'])
return check
@pytest.fixture(scope='module')
def find_users(test_db):
def find(**kwargs):
@ -158,3 +205,34 @@ def test_db(users, users_by_name, memberships):
membership_id=membership['id'])
return data
@pytest.fixture(scope='module')
def org_staff(memberships):
def find(org_id):
if org_id in ['', None]:
return set()
else:
return set(m['user']['id'] for m in memberships
if m['role'] in ['maintainer', 'owner'] and m['user'] != None
and m['organization'] == org_id)
return find
@pytest.fixture(scope='module')
def is_org_member(memberships):
def check(user_id, org_id):
if org_id in ['', None]:
return True
else:
return user_id in set(m['user']['id'] for m in memberships
if m['user'] != None and m['organization'] == org_id)
return check
@pytest.fixture(scope='module')
def find_job_staff_user(is_job_staff):
def find(jobs, users, is_staff):
for job in jobs:
for user in users:
if is_staff == is_job_staff(user['id'], job['id']):
return user['username'], job['id']
return None, None
return find

@ -1,170 +0,0 @@
# Copyright (C) 2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
from http import HTTPStatus
from deepdiff import DeepDiff
import pytest
from .utils.config import get_method
def get_job_staff(job, tasks, projects):
job_staff = []
job_staff.append(job['assignee'])
tid = job['task_id']
job_staff.append(tasks[tid]['owner'])
job_staff.append(tasks[tid]['assignee'])
pid = job['project_id']
if pid:
job_staff.append(projects[pid]['owner'])
job_staff.append(projects[pid]['assignee'])
job_staff = set(u['id'] for u in job_staff if u is not None)
return job_staff
def get_org_staff(org_id, memberships):
if org_id in ['', None]:
return set()
else:
return set(m['user']['id'] for m in memberships
if m['role'] in ['maintainer', 'owner'] and m['user'] != None
and m['organization'] == org_id)
def filter_jobs(jobs, tasks, org):
if org is None:
kwargs = {}
jobs = jobs.raw
elif org == '':
kwargs = {'org': ''}
jobs = [job for job in jobs
if tasks[job['task_id']]['organization'] is None]
else:
kwargs = {'org_id': org}
jobs = [job for job in jobs
if tasks[job['task_id']]['organization'] == org]
return jobs, kwargs
def is_org_member(memberships, user, org_id):
if org_id in ['', None]:
return True
else:
return user['id'] in set(m['user']['id'] for m in memberships
if m['user'] != None and m['organization'] == org_id)
class TestGetJobs:
def _test_get_job_200(self, user, jid, data, **kwargs):
response = get_method(user, f'jobs/{jid}', **kwargs)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()) == {}
def _test_get_job_403(self, user, jid, **kwargs):
response = get_method(user, f'jobs/{jid}', **kwargs)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('org', [None, '', 1, 2])
def test_admin_get_job(self, jobs, tasks, org):
jobs, kwargs = filter_jobs(jobs, tasks, org)
# keep only the reasonable amount of jobs
for job in jobs[:8]:
self._test_get_job_200('admin2', job['id'], job, **kwargs)
@pytest.mark.parametrize('org_id', ['', None, 1, 2])
@pytest.mark.parametrize('groups', [['business'], ['user'], ['worker'], []])
def test_non_admin_get_job(self, org_id, groups, users, jobs, tasks, projects,
memberships):
# keep the reasonable amount of users and jobs
users = [u for u in users if u['groups'] == groups][:4]
jobs, kwargs = filter_jobs(jobs, tasks, org_id)
org_staff = get_org_staff(org_id, memberships)
for job in jobs[:8]:
job_staff = get_job_staff(job, tasks, projects)
# check if the specific user in job_staff to see the job
for user in users:
if user['id'] in job_staff | org_staff:
self._test_get_job_200(user['username'], job['id'], job, **kwargs)
else:
self._test_get_job_403(user['username'], job['id'], **kwargs)
class TestListJobs:
def _test_list_jobs_200(self, user, data, **kwargs):
response = get_method(user, 'jobs', **kwargs, page_size=all)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()['results']) == {}
def _test_list_jobs_403(self, user, **kwargs):
response = get_method(user, 'jobs', **kwargs)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('org', [None, '', 1, 2])
def test_admin_list_jobs(self, jobs, tasks, org):
jobs, kwargs = filter_jobs(jobs, tasks, org)
self._test_list_jobs_200('admin1', jobs, **kwargs)
@pytest.mark.parametrize('org_id', ['', None, 1, 2])
@pytest.mark.parametrize('groups', [['business'], ['user'], ['worker'], []])
def test_non_admin_list_jobs(self, org_id, groups, users, jobs, tasks,
projects, memberships):
# keep the reasonable amount of users and jobs
users = [u for u in users if u['groups'] == groups][:2]
jobs, kwargs = filter_jobs(jobs, tasks, org_id)
org_staff = get_org_staff(org_id, memberships)
for user in users:
user_jobs = []
for job in jobs:
job_staff = get_job_staff(job, tasks, projects)
if user['id'] in job_staff | org_staff:
user_jobs.append(job)
if is_org_member(memberships, user, org_id):
self._test_list_jobs_200(user['username'], user_jobs, **kwargs)
else:
self._test_list_jobs_403(user['username'], **kwargs)
class TestGetAnnotations:
def _test_get_job_annotations_200(self, user, jid, data, **kwargs):
response = get_method(user, f'jobs/{jid}/annotations', **kwargs)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()) == {}
def _test_get_job_annotations_403(self, user, jid, **kwargs):
response = get_method(user, f'jobs/{jid}/annotations', **kwargs)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('org', [None, '', 1, 2])
def test_admin_get_job_annotations(self, jobs, tasks, annotations, org):
jobs, kwargs = filter_jobs(jobs, tasks, org)
# keep only the reasonable amount of jobs
for job in jobs[:8]:
jid = str(job['id'])
self._test_get_job_annotations_200('admin2', jid,
annotations['job'][jid], **kwargs)
@pytest.mark.parametrize('org_id', ['', None])
@pytest.mark.parametrize('groups', [['business'], ['user'], ['worker'], []])
def test_non_admin_get_job_annotations(self, org_id, groups, users, jobs, tasks,
projects, annotations, memberships):
users = [u for u in users if u['groups'] == groups][:4]
jobs, kwargs = filter_jobs(jobs, tasks, org_id)
org_staff = get_org_staff(org_id, memberships)
# keep only the reasonable amount of jobs
for job in jobs[:8]:
job_staff = get_job_staff(job, tasks, projects)
jid = str(job['id'])
for user in users:
if user['id'] in job_staff | org_staff:
self._test_get_job_annotations_200(user['username'],
jid, annotations['job'][jid], **kwargs)
else:
self._test_get_job_annotations_403(user['username'],
jid, **kwargs)

@ -0,0 +1,306 @@
# Copyright (C) 2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
from http import HTTPStatus
from deepdiff import DeepDiff
import pytest
from .utils.config import get_method, patch_method
def get_job_staff(job, tasks, projects):
job_staff = []
job_staff.append(job['assignee'])
tid = job['task_id']
job_staff.append(tasks[tid]['owner'])
job_staff.append(tasks[tid]['assignee'])
pid = job['project_id']
if pid:
job_staff.append(projects[pid]['owner'])
job_staff.append(projects[pid]['assignee'])
job_staff = set(u['id'] for u in job_staff if u is not None)
return job_staff
def filter_jobs(jobs, tasks, org):
if org is None:
kwargs = {}
jobs = jobs.raw
elif org == '':
kwargs = {'org': ''}
jobs = [job for job in jobs
if tasks[job['task_id']]['organization'] is None]
else:
kwargs = {'org_id': org}
jobs = [job for job in jobs
if tasks[job['task_id']]['organization'] == org]
return jobs, kwargs
class TestGetJobs:
def _test_get_job_200(self, user, jid, data, **kwargs):
response = get_method(user, f'jobs/{jid}', **kwargs)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()) == {}
def _test_get_job_403(self, user, jid, **kwargs):
response = get_method(user, f'jobs/{jid}', **kwargs)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('org', [None, '', 1, 2])
def test_admin_get_job(self, jobs, tasks, org):
jobs, kwargs = filter_jobs(jobs, tasks, org)
# keep only the reasonable amount of jobs
for job in jobs[:8]:
self._test_get_job_200('admin2', job['id'], job, **kwargs)
@pytest.mark.parametrize('org_id', ['', None, 1, 2])
@pytest.mark.parametrize('groups', [['business'], ['user'], ['worker'], []])
def test_non_admin_get_job(self, org_id, groups, users, jobs, tasks, projects,
org_staff):
# keep the reasonable amount of users and jobs
users = [u for u in users if u['groups'] == groups][:4]
jobs, kwargs = filter_jobs(jobs, tasks, org_id)
org_staff = org_staff(org_id)
for job in jobs[:8]:
job_staff = get_job_staff(job, tasks, projects)
# check if the specific user in job_staff to see the job
for user in users:
if user['id'] in job_staff | org_staff:
self._test_get_job_200(user['username'], job['id'], job, **kwargs)
else:
self._test_get_job_403(user['username'], job['id'], **kwargs)
class TestListJobs:
def _test_list_jobs_200(self, user, data, **kwargs):
response = get_method(user, 'jobs', **kwargs, page_size=all)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()['results']) == {}
def _test_list_jobs_403(self, user, **kwargs):
response = get_method(user, 'jobs', **kwargs)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('org', [None, '', 1, 2])
def test_admin_list_jobs(self, jobs, tasks, org):
jobs, kwargs = filter_jobs(jobs, tasks, org)
self._test_list_jobs_200('admin1', jobs, **kwargs)
@pytest.mark.parametrize('org_id', ['', None, 1, 2])
@pytest.mark.parametrize('groups', [['business'], ['user'], ['worker'], []])
def test_non_admin_list_jobs(self, org_id, groups, users, jobs, tasks,
projects, org_staff, is_org_member):
users = [u for u in users if u['groups'] == groups][:2]
jobs, kwargs = filter_jobs(jobs, tasks, org_id)
org_staff = org_staff(org_id)
for user in users:
user_jobs = []
for job in jobs:
job_staff = get_job_staff(job, tasks, projects)
if user['id'] in job_staff | org_staff:
user_jobs.append(job)
if is_org_member(user['id'], org_id):
self._test_list_jobs_200(user['username'], user_jobs, **kwargs)
else:
self._test_list_jobs_403(user['username'], **kwargs)
class TestGetAnnotations:
def _test_get_job_annotations_200(self, user, jid, data, **kwargs):
response = get_method(user, f'jobs/{jid}/annotations', **kwargs)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()) == {}
def _test_get_job_annotations_403(self, user, jid, **kwargs):
response = get_method(user, f'jobs/{jid}/annotations', **kwargs)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('org', [''])
@pytest.mark.parametrize('groups, job_staff, is_allow', [
(['admin'], True, True), (['admin'], False, True),
(['business'], True, True), (['business'], False, False),
(['worker'], True, True), (['worker'], False, False),
(['user'], True, True), (['user'], False, False)
])
def test_user_get_job_annotations(self, org, groups, job_staff,
is_allow, users, jobs, tasks, annotations, find_job_staff_user):
users = [u for u in users if u['groups'] == groups]
jobs, kwargs = filter_jobs(jobs, tasks, org)
username, job_id = find_job_staff_user(jobs, users, job_staff)
if is_allow:
self._test_get_job_annotations_200(username,
job_id, annotations['job'][str(job_id)], **kwargs)
else:
self._test_get_job_annotations_403(username, job_id, **kwargs)
@pytest.mark.parametrize('org', [2])
@pytest.mark.parametrize('role, job_staff, is_allow', [
('owner', True, True), ('owner', False, True),
('maintainer', True, True), ('maintainer', False, True),
('supervisor', True, True), ('supervisor', False, False),
('worker', True, True), ('worker', False, False),
])
def test_member_get_job_annotations(self, org, role, job_staff, is_allow,
jobs, tasks, find_job_staff_user, annotations, find_users):
users = find_users(org=org, role=role)
jobs, kwargs = filter_jobs(jobs, tasks, org)
username, jid = find_job_staff_user(jobs, users, job_staff)
if is_allow:
self._test_get_job_annotations_200(username,
jid, annotations['job'][str(jid)], **kwargs)
else:
self._test_get_job_annotations_403(username, jid, **kwargs)
@pytest.mark.parametrize('org', [1])
@pytest.mark.parametrize('privilege, is_allow', [
('admin', True), ('business', False), ('worker', False), ('user', False)
])
def test_non_member_get_job_annotations(self, org, privilege, is_allow,
jobs, tasks, find_job_staff_user, annotations, find_users):
users = find_users(privilege=privilege, exclude_org=org)
jobs, kwargs = filter_jobs(jobs, tasks, org)
username, job_id = find_job_staff_user(jobs, users, False)
kwargs = {'org_id': org}
if is_allow:
self._test_get_job_annotations_200(username,
job_id, annotations['job'][str(job_id)], **kwargs)
else:
self._test_get_job_annotations_403(username, job_id, **kwargs)
class TestPatchJobAnnotations:
_ORG = 2
def _test_check_respone(self, is_allow, response, data=None):
if is_allow:
assert response.status_code == HTTPStatus.OK
assert DeepDiff(data, response.json()) == {}
else:
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.fixture(scope='class')
def request_data(self, annotations):
def get_data(jid):
data = annotations['job'][str(jid)].copy()
data['shapes'][0].update({'points': [2.0, 3.0, 4.0, 5.0, 6.0, 7.0]})
data['version'] += 1
return data
return get_data
@pytest.mark.parametrize('org', [2])
@pytest.mark.parametrize('role, job_staff, is_allow', [
('maintainer', False, True), ('owner', False, True),
('supervisor', False, False), ('worker', False, False),
('maintainer', True, True), ('owner', True, True),
('supervisor', True, True), ('worker', True, True)
])
def test_member_update_job_annotations(self, org, role, job_staff, is_allow,
find_job_staff_user, find_users, request_data, jobs_by_org):
users = find_users(role=role, org=org)
jobs = jobs_by_org[org]
username, jid = find_job_staff_user(jobs, users, job_staff)
data = request_data(jid)
response = patch_method(username, f'jobs/{jid}/annotations',
data, org_id=org, action='update')
self._test_check_respone(is_allow, response, data)
@pytest.mark.parametrize('org', [2])
@pytest.mark.parametrize('privilege, is_allow', [
('admin', True), ('business', False), ('worker', False), ('user', False)
])
def test_non_member_update_job_annotations(self, org, privilege, is_allow,
find_job_staff_user, find_users, request_data, jobs_by_org):
users = find_users(privilege=privilege, exclude_org=org)
jobs = jobs_by_org[org]
username, jid = find_job_staff_user(jobs, users, False)
data = request_data(jid)
response = patch_method(username, f'jobs/{jid}/annotations', data,
org_id=org, action='update')
self._test_check_respone(is_allow, response, data)
@pytest.mark.parametrize('org', [''])
@pytest.mark.parametrize('privilege, job_staff, is_allow', [
('admin', True, True), ('admin', False, True),
('business', True, True), ('business', False, False),
('worker', True, True), ('worker', False, False),
('user', True, True), ('user', False, False)
])
def test_user_update_job_annotations(self, org, privilege, job_staff, is_allow,
find_job_staff_user, find_users, request_data, jobs_by_org):
users = find_users(privilege=privilege)
jobs = jobs_by_org[org]
username, jid = find_job_staff_user(jobs, users, job_staff)
data = request_data(jid)
response = patch_method(username, f'jobs/{jid}/annotations', data,
org_id=org, action='update')
self._test_check_respone(is_allow, response, data)
class TestPatchJob:
_ORG = 2
@pytest.fixture(scope='class')
def find_task_staff_user(self, is_task_staff):
def find(jobs, users, is_staff):
for job in jobs:
for user in users:
if is_staff == is_task_staff(user['id'], job['task_id']):
return user, job['id']
return None, None
return find
@pytest.fixture(scope='class')
def expected_data(self, jobs, users):
keys = ['url', 'id', 'username', 'first_name', 'last_name']
def find(job_id, assignee_id):
data = jobs[job_id].copy()
data['assignee'] = dict(filter(lambda a: a[0] in keys,
users[assignee_id].items()))
return data
return find
@pytest.fixture(scope='class')
def new_assignee(self, jobs, tasks, assignee_id, org_staff):
def find_new_assignee(jid, user_id):
members = org_staff(tasks[jobs[jid]['task_id']]['organization'])
members -= {assignee_id(jobs[jid]), user_id}
return members.pop()
return find_new_assignee
@pytest.mark.parametrize('org', [2])
@pytest.mark.parametrize('role, task_staff, is_allow', [
('maintainer', False, True), ('owner', False, True),
('supervisor', False, False), ('worker', False, False),
('maintainer', True, True), ('owner', True, True),
('supervisor', True, True), ('worker', True, True)
])
def test_member_update_job_assignee(self, org, role, task_staff, is_allow,
find_task_staff_user, find_users, jobs_by_org, new_assignee, expected_data):
users, jobs = find_users(role=role, org=org), jobs_by_org[org]
user, jid = find_task_staff_user(jobs, users, task_staff)
assignee = new_assignee(jid, user['id'])
response = patch_method(user['username'], f'jobs/{jid}',
{'assignee': assignee}, org_id=self._ORG)
if is_allow:
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_data(jid, assignee), response.json()) == {}
else:
assert response.status_code == HTTPStatus.FORBIDDEN
Loading…
Cancel
Save