diff --git a/tests/rest_api/assets/cvat_data.tar.bz2 b/tests/rest_api/assets/cvat_data.tar.bz2 index 624ee1ab9cf8..14893f1cbd28 100644 Binary files a/tests/rest_api/assets/cvat_data.tar.bz2 and b/tests/rest_api/assets/cvat_data.tar.bz2 differ diff --git a/tests/rest_api/assets/cvat_db/cvat_db.sql b/tests/rest_api/assets/cvat_db/cvat_db.sql index 06c9e60a5f03..7ad93d195718 100644 --- a/tests/rest_api/assets/cvat_db/cvat_db.sql +++ b/tests/rest_api/assets/cvat_db/cvat_db.sql @@ -2,8 +2,8 @@ -- PostgreSQL database dump -- --- Dumped from database version 10.20 --- Dumped by pg_dump version 10.20 +-- Dumped from database version 10.19 +-- Dumped by pg_dump version 10.19 SET statement_timeout = 0; SET lock_timeout = 0; @@ -2651,7 +2651,9 @@ COPY public.auth_user (id, password, last_login, is_superuser, username, first_n 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 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 +19 pbkdf2_sha256$260000$sKpnXRfALvvS3bBUj8e2SD$wcq2zoyeXxa+gnn6007p6DGtNd+ND6H4pGOq9ekb9t0= \N f user5 User Fifth user5@cvat.org f t 2022-02-24 20:45:07+00 +20 pbkdf2_sha256$260000$V3cCtaea9FrYFYQRGJfBGO$nZVdhgyq1iEcv3Ed4QDnMt18ULQViJn0snZDm9ZL2SA= \N f user6 User Sixth user6@cvat.org f t 2022-02-24 20:45:19+00 +1 pbkdf2_sha256$260000$DevmxlmLwciP1P6sZs2Qag$U9DFtjTWx96Sk95qY6UXVcvpdQEP2LcoFBftk5D2RKY= 2022-02-24 21:25:06.462854+00 t admin1 Admin First admin1@cvat.org t t 2021-12-14 18:04:57+00 \. @@ -2674,6 +2676,8 @@ COPY public.auth_user_groups (id, user_id, group_id) FROM stdin; 21 12 2 23 13 2 31 18 1 +49 19 3 +50 20 3 \. @@ -2750,6 +2754,10 @@ COPY public.django_admin_log (id, action_time, object_id, object_repr, action_fl 39 2021-12-14 18:41:27.383994+00 18 admin2 2 [{"changed": {"fields": ["Staff status", "Superuser status"]}}] 4 1 40 2021-12-14 18:41:37.492062+00 18 admin2 2 [{"changed": {"fields": ["password"]}}] 4 1 41 2021-12-14 18:41:50.468234+00 1 admin1 2 [{"changed": {"fields": ["password"]}}] 4 1 +42 2022-02-24 20:45:07.810075+00 19 user5 1 [{"added": {}}] 4 1 +43 2022-02-24 20:45:13.620976+00 19 user5 2 [{"changed": {"fields": ["First name", "Last name", "Email address"]}}] 4 1 +44 2022-02-24 20:45:19.301266+00 20 user6 1 [{"added": {}}] 4 1 +45 2022-02-24 20:45:25.772476+00 20 user6 2 [{"changed": {"fields": ["First name", "Last name", "Email address"]}}] 4 1 \. @@ -2921,6 +2929,8 @@ wf6d6vzf4u74l08o0qgbqehei21hibea .eJxVjDEOwjAMRe-SGUUkpHZgZO8ZIttxSAG1UtNOiLtDpQ 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 +gcz795933839j3g0t3rjgmikzkzlwse3 .eJxVjEEOwiAQRe_C2hCmUCgu3XsGMjCDVA1NSrsy3l1JutDtf-_9lwi4byXsjdcwkzgLEKffLWJ6cO2A7lhvi0xL3dY5yq7IgzZ5XYifl8P9OyjYSq-9niK4b6A1cfYZnCUEBGuzZxW1UsnYFBV7A9PAIxlMzmmj8pDdyOL9AfdKOC0:1nNKyv:kkKNWtjON5Uk-FR_FbwNa3oJ8t5PEd-rZ1y8BsRyays 2022-03-10 20:44:57.190131+00 +lqzut02cip3i7xxinmal28z3mo302vey .eJxVjEEOwiAQRe_C2hCmUCgu3XsGMjCDVA1NSrsy3l1JutDtf-_9lwi4byXsjdcwkzgLEKffLWJ6cO2A7lhvi0xL3dY5yq7IgzZ5XYifl8P9OyjYSq-9niK4b6A1cfYZnCUEBGuzZxW1UsnYFBV7A9PAIxlMzmmj8pDdyOL9AfdKOC0:1nNLbm:bXtVicsOrZtQ_p4Qr9bOTAmHWYJMHD8_GCUbncB6nzQ 2022-03-10 21:25:06.476016+00 \. @@ -3935,6 +3945,8 @@ COPY public.engine_profile (id, rating, user_id) FROM stdin; 16 0 16 17 0 17 18 0 18 +19 0 19 +20 0 20 \. @@ -3943,8 +3955,8 @@ COPY public.engine_profile (id, rating, user_id) FROM stdin; -- COPY public.engine_project (id, name, bug_tracker, created_date, updated_date, status, assignee_id, owner_id, organization_id) FROM stdin; -1 project1 2021-12-14 19:46:37.969497+00 2021-12-14 19:48:33.103265+00 annotation \N 10 \N -2 project2 2021-12-14 19:52:37.278149+00 2021-12-14 19:55:57.483506+00 annotation 3 10 2 +2 project2 2021-12-14 19:52:37.278149+00 2022-02-24 21:32:36.197153+00 annotation 3 10 2 +1 project1 2021-12-14 19:46:37.969497+00 2022-02-24 21:33:48.037024+00 annotation 20 10 \N \. @@ -3997,11 +4009,11 @@ COPY public.engine_serverfile (id, file, data_id) FROM stdin; COPY public.engine_task (id, name, mode, created_date, updated_date, status, bug_tracker, owner_id, overlap, assignee_id, segment_size, project_id, data_id, dimension, subset, organization_id) FROM stdin; 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 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 +3 task1_in_project1 annotation 2021-12-14 19:48:33.089778+00 2022-02-24 21:25:10.697341+00 annotation 10 0 19 50 1 3 2d Train \N +4 task1_in_project2 annotation 2021-12-14 19:55:57.475273+00 2022-02-24 21:32:36.190676+00 annotation 10 0 19 58 2 4 2d train 2 \. @@ -4044,6 +4056,7 @@ mFpVV2Yh39uUdU8IpigSxvuPegqi8sjxFi6P9Jdy6fBE8Ky9Juzi1KjeGDQsizSS 2021-12-14 19:5 h43G28di7vfs4Jv5VrKZ26xvGAfm6Yc2FFv14z9EKhiuIEDQ22pEnzmSCab8MnK1 2021-12-14 19:55:13.745912+00 9 10 5FjIXya6fTGvlRpauFvi2QN1wDOqo1V9REB5rJinDR8FZO9gr0qmtWpghsCte8Y1 2022-01-19 13:54:42.005381+00 10 10 BrwoDmMNQQ1v9WXOukp9DwQVuqB3RDPjpUECCEq6QcAuG0Pi8k1IYtQ9uz9jg0Bv 2022-01-19 13:54:42.015131+00 11 10 +Fi3WRUhFxTWpMiVpdwNR2CGyhgcIXSCUYgPCugPq72QUOgHz9NSMOGiKS3PfJ7Ql 2022-02-24 21:29:21.978055+00 12 1 \. @@ -4063,6 +4076,7 @@ COPY public.organizations_membership (id, is_active, joined_date, role, organiza 9 t 2021-12-14 19:55:13.745912+00 supervisor 2 3 10 t 2022-01-19 13:54:42.005381+00 supervisor 2 4 11 t 2022-01-19 13:54:42.015131+00 maintainer 2 5 +12 t 2022-02-24 21:29:21.978055+00 worker 2 19 \. @@ -4147,14 +4161,14 @@ 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', 47, true); +SELECT pg_catalog.setval('public.auth_user_groups_id_seq', 51, true); -- -- Name: auth_user_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root -- -SELECT pg_catalog.setval('public.auth_user_id_seq', 18, true); +SELECT pg_catalog.setval('public.auth_user_id_seq', 20, true); -- @@ -4168,7 +4182,7 @@ SELECT pg_catalog.setval('public.auth_user_user_permissions_id_seq', 1, false); -- Name: django_admin_log_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root -- -SELECT pg_catalog.setval('public.django_admin_log_id_seq', 41, true); +SELECT pg_catalog.setval('public.django_admin_log_id_seq', 45, true); -- @@ -4315,7 +4329,7 @@ SELECT pg_catalog.setval('public.engine_manifest_id_seq', 1, false); -- Name: engine_profile_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root -- -SELECT pg_catalog.setval('public.engine_profile_id_seq', 18, true); +SELECT pg_catalog.setval('public.engine_profile_id_seq', 20, true); -- @@ -4385,7 +4399,7 @@ SELECT pg_catalog.setval('public.engine_video_id_seq', 1, true); -- Name: organizations_membership_id_seq; Type: SEQUENCE SET; Schema: public; Owner: root -- -SELECT pg_catalog.setval('public.organizations_membership_id_seq', 11, true); +SELECT pg_catalog.setval('public.organizations_membership_id_seq', 12, true); -- diff --git a/tests/rest_api/assets/invitations.json b/tests/rest_api/assets/invitations.json index e9c3a007493f..17d3be87848b 100644 --- a/tests/rest_api/assets/invitations.json +++ b/tests/rest_api/assets/invitations.json @@ -1,8 +1,28 @@ { - "count": 9, + "count": 10, "next": null, "previous": null, "results": [ + { + "created_date": "2022-02-24T21:29:21.978055Z", + "key": "Fi3WRUhFxTWpMiVpdwNR2CGyhgcIXSCUYgPCugPq72QUOgHz9NSMOGiKS3PfJ7Ql", + "organization": 2, + "owner": { + "first_name": "Admin", + "id": 1, + "last_name": "First", + "url": "http://localhost:8080/api/users/1", + "username": "admin1" + }, + "role": "worker", + "user": { + "first_name": "User", + "id": 19, + "last_name": "Fifth", + "url": "http://localhost:8080/api/users/19", + "username": "user5" + } + }, { "created_date": "2022-01-19T13:54:42.015131Z", "key": "BrwoDmMNQQ1v9WXOukp9DwQVuqB3RDPjpUECCEq6QcAuG0Pi8k1IYtQ9uz9jg0Bv", diff --git a/tests/rest_api/assets/memberships.json b/tests/rest_api/assets/memberships.json index e07940dd3166..415af2670ff5 100644 --- a/tests/rest_api/assets/memberships.json +++ b/tests/rest_api/assets/memberships.json @@ -1,8 +1,23 @@ { - "count": 11, + "count": 12, "next": null, "previous": null, "results": [ + { + "id": 12, + "invitation": "Fi3WRUhFxTWpMiVpdwNR2CGyhgcIXSCUYgPCugPq72QUOgHz9NSMOGiKS3PfJ7Ql", + "is_active": true, + "joined_date": "2022-02-24T21:29:21.978055Z", + "organization": 2, + "role": "worker", + "user": { + "first_name": "User", + "id": 19, + "last_name": "Fifth", + "url": "http://localhost:8080/api/users/19", + "username": "user5" + } + }, { "id": 11, "invitation": "BrwoDmMNQQ1v9WXOukp9DwQVuqB3RDPjpUECCEq6QcAuG0Pi8k1IYtQ9uz9jg0Bv", diff --git a/tests/rest_api/assets/projects.json b/tests/rest_api/assets/projects.json index a57d12e57381..921aaa8a229a 100644 --- a/tests/rest_api/assets/projects.json +++ b/tests/rest_api/assets/projects.json @@ -45,11 +45,17 @@ "tasks": [ 4 ], - "updated_date": "2021-12-14T19:55:57.483506Z", + "updated_date": "2022-02-24T21:32:36.197153Z", "url": "http://localhost:8080/api/projects/2" }, { - "assignee": null, + "assignee": { + "first_name": "User", + "id": 20, + "last_name": "Sixth", + "url": "http://localhost:8080/api/users/20", + "username": "user6" + }, "bug_tracker": "", "created_date": "2021-12-14T19:46:37.969497Z", "dimension": "2d", @@ -97,7 +103,7 @@ "tasks": [ 3 ], - "updated_date": "2021-12-14T19:48:33.103265Z", + "updated_date": "2022-02-24T21:33:48.037024Z", "url": "http://localhost:8080/api/projects/1" } ] diff --git a/tests/rest_api/assets/tasks.json b/tests/rest_api/assets/tasks.json index e68fb4257dd3..4d67926d7c69 100644 --- a/tests/rest_api/assets/tasks.json +++ b/tests/rest_api/assets/tasks.json @@ -184,7 +184,13 @@ "url": "http://localhost:8080/api/tasks/5" }, { - "assignee": null, + "assignee": { + "first_name": "User", + "id": 19, + "last_name": "Fifth", + "url": "http://localhost:8080/api/users/19", + "username": "user5" + }, "bug_tracker": "", "created_date": "2021-12-14T19:55:57.475273Z", "data": 4, @@ -246,11 +252,17 @@ "size": 58, "status": "annotation", "subset": "train", - "updated_date": "2021-12-22T07:17:34.836384Z", + "updated_date": "2022-02-24T21:32:36.190676Z", "url": "http://localhost:8080/api/tasks/4" }, { - "assignee": null, + "assignee": { + "first_name": "User", + "id": 19, + "last_name": "Fifth", + "url": "http://localhost:8080/api/users/19", + "username": "user5" + }, "bug_tracker": "", "created_date": "2021-12-14T19:48:33.089778Z", "data": 3, @@ -347,7 +359,7 @@ "size": 148, "status": "annotation", "subset": "Train", - "updated_date": "2022-02-21T10:37:27.697705Z", + "updated_date": "2022-02-24T21:25:10.697341Z", "url": "http://localhost:8080/api/tasks/3" }, { diff --git a/tests/rest_api/assets/users.json b/tests/rest_api/assets/users.json index 3e7a0b38be79..c8775a00df0e 100644 --- a/tests/rest_api/assets/users.json +++ b/tests/rest_api/assets/users.json @@ -1,5 +1,5 @@ { - "count": 18, + "count": 20, "next": null, "previous": null, "results": [ @@ -14,7 +14,7 @@ "is_active": true, "is_staff": true, "is_superuser": true, - "last_login": "2022-02-21T10:37:08.947950Z", + "last_login": "2022-02-24T21:25:06.462854Z", "last_name": "First", "url": "http://localhost:8080/api/users/1", "username": "admin1" @@ -282,6 +282,38 @@ "last_name": "Second", "url": "http://localhost:8080/api/users/18", "username": "admin2" + }, + { + "date_joined": "2022-02-24T20:45:07Z", + "email": "user5@cvat.org", + "first_name": "User", + "groups": [ + "user" + ], + "id": 19, + "is_active": true, + "is_staff": false, + "is_superuser": false, + "last_login": null, + "last_name": "Fifth", + "url": "http://localhost:8080/api/users/19", + "username": "user5" + }, + { + "date_joined": "2022-02-24T20:45:19Z", + "email": "user6@cvat.org", + "first_name": "User", + "groups": [ + "user" + ], + "id": 20, + "is_active": true, + "is_staff": false, + "is_superuser": false, + "last_login": null, + "last_name": "Sixth", + "url": "http://localhost:8080/api/users/20", + "username": "user6" } ] } \ No newline at end of file diff --git a/tests/rest_api/conftest.py b/tests/rest_api/conftest.py index 5d3e587ab7b9..30b08e7033a4 100644 --- a/tests/rest_api/conftest.py +++ b/tests/rest_api/conftest.py @@ -185,7 +185,6 @@ def find(**kwargs): return data return find - @pytest.fixture(scope='module') def test_db(users, users_by_name, memberships): data = [] diff --git a/tests/rest_api/test_tasks.py b/tests/rest_api/test_tasks.py index 7e5bf552573d..c6157d297d4d 100644 --- a/tests/rest_api/test_tasks.py +++ b/tests/rest_api/test_tasks.py @@ -3,8 +3,145 @@ # SPDX-License-Identifier: MIT from http import HTTPStatus +from deepdiff import DeepDiff import pytest -from .utils.config import get_method + +from .utils.config import get_method, post_method + +class TestGetTasks: + def _test_task_list_200(self, user, project_id, data, exclude_paths = '', **kwargs): + response = get_method(user, f'projects/{project_id}/tasks', **kwargs) + response_data = response.json() + assert response.status_code == HTTPStatus.OK + assert DeepDiff(data, response_data['results'], ignore_order=True, exclude_paths=exclude_paths) == {} + + def _test_task_list_403(self, user, project_id, **kwargs): + response = get_method(user, f'projects/{project_id}/tasks', **kwargs) + assert response.status_code == HTTPStatus.FORBIDDEN + + def _test_users_to_see_task_list(self, project_id, tasks, users, is_staff, is_allow, is_project_staff, **kwargs): + if is_staff: + users = [user for user in users if is_project_staff(user['id'], project_id) ] + else: + users = [user for user in users if not is_project_staff(user['id'], project_id)] + assert len(users) + + for user in users: + if is_allow: + self._test_task_list_200(user['username'], project_id, tasks, **kwargs) + else: + self._test_task_list_403(user['username'], project_id, **kwargs) + + def _test_assigned_users_to_see_task_data(self, tasks, users, is_task_staff, **kwargs): + for task in tasks: + staff_users = [user for user in users if is_task_staff(user['id'], task['id'])] + assert len(staff_users) + for user in staff_users: + response = get_method(user['username'], f'tasks', **kwargs) + response_data = response.json() + assert response.status_code == HTTPStatus.OK + assert any(_task['id'] == task['id'] for _task in response_data['results']) + + # [sandbox] admin can see task data in project even he has no ownerships in this project + # [sandbox] business cannot see task data in project if he has no ownerships in this project + # [sandbox] user that has one of these ownerships: [Project:owner, Project:assignee] can see task data + @pytest.mark.parametrize('project_id', [1]) + @pytest.mark.parametrize('groups, is_staff, is_allow', [ + ('admin', False, True), + ('business', False, False), + ]) + def test_project_tasks_visibility(self, project_id, groups, users, tasks, is_staff, is_allow, find_users, is_project_staff): + users = find_users(privilege=groups) + tasks = list(filter(lambda x: x['project_id'] == project_id, tasks)) + assert len(tasks) + + self._test_users_to_see_task_list(project_id, tasks, users, is_staff, is_allow, is_project_staff) + + # [sandbox] user that has one of these ownerships: [Owner, Assignee] can see task data + @pytest.mark.parametrize('project_id, groups', [(1, 'user')]) + def test_task_assigneed_to_see_task(self, project_id, groups, users, tasks, find_users, is_task_staff): + users = find_users(privilege=groups) + tasks = list(filter(lambda x: x['project_id'] == project_id and x['assignee'], tasks)) + assert len(tasks) + + self._test_assigned_users_to_see_task_data(tasks, users, is_task_staff) + + # [organization] maintainer can see task data even if he has no ownerships in corresponding Project, Task + # [organization] supervisor cannot see task data if he has no ownerships in corresponding Project, Task + # [organization] worker (as role) that has one of these ownerships: [Project:owner, Project:assignee], can see task data + @pytest.mark.parametrize('org, project_id', [({'id': 2, 'slug': 'org2'}, 2)]) + @pytest.mark.parametrize('role, is_staff, is_allow', [ + ('maintainer', False, True), + ('supervisor', False, False), + ]) + def test_org_project_tasks_visibility(self, org, project_id, role, is_staff, is_allow, tasks, is_task_staff, is_project_staff, find_users): + users = find_users(org=org['id'], role=role) + tasks = list(filter(lambda x: x['project_id'] == project_id, tasks)) + assert len(tasks) + + self._test_users_to_see_task_list(project_id, tasks, users, is_staff, is_allow, is_project_staff, org=org['slug']) + + # [organization] worker (as role) that has one of these ownerships: [Owner, Assignee], can see task data + @pytest.mark.parametrize('org, project_id, role', [ + ({'id': 2, 'slug': 'org2'}, 2, 'worker') + ]) + def test_org_task_assigneed_to_see_task(self, org, project_id, role, users, tasks, find_users, is_task_staff): + users = find_users(org=org['id'], role=role) + tasks = list(filter(lambda x: x['project_id'] == project_id and x['assignee'], tasks)) + assert len(tasks) + + self._test_assigned_users_to_see_task_data(tasks, users, is_task_staff, org=org['slug']) + + +class TestPostTasks: + def _test_create_task_201(self, user, spec, **kwargs): + response = post_method(user, '/tasks', spec, **kwargs) + assert response.status_code == HTTPStatus.CREATED + + def _test_create_task_403(self, user, spec, **kwargs): + response = post_method(user, '/tasks', spec, **kwargs) + assert response.status_code == HTTPStatus.FORBIDDEN + + def _test_users_to_create_task_in_project(self, project_id, users, is_staff, is_allow, is_project_staff, **kwargs): + if is_staff: + users = [user for user in users if is_project_staff(user['id'], project_id) ] + else: + users = [user for user in users if not is_project_staff(user['id'], project_id)] + assert len(users) + + for user in users: + username = user['username'] + spec = { + 'name': f'test {username} to create a task within a project', + 'project_id': project_id, + } + + if is_allow: + self._test_create_task_201(username, spec, **kwargs) + else: + self._test_create_task_403(username, spec, **kwargs) + + # [sandbox] admin can create task in project even he has no ownerships in this project + # [sandbox] business cannot create task in project if he has no ownerships in this project + # [sandbox] user that has one of these ownerships: [Project:owner, Project:assignee] and has less than 10 task can create task in project + @pytest.mark.parametrize('project_id', [1]) + @pytest.mark.parametrize('groups, is_staff, is_allow', [ + ('admin', False, True), + ('business', False, False), + ('user', True, True), + ]) + def test_users_to_create_task_in_project(self, project_id, groups, is_staff, is_allow, is_project_staff, find_users): + users = find_users(privilege=groups) + self._test_users_to_create_task_in_project(project_id, users, is_staff, is_allow, is_project_staff) + + # [organization] worker cannot create task in project even he has no ownerships in this project + @pytest.mark.parametrize('org, project_id', [({'id': 2, 'slug': 'org2'}, 2)]) + @pytest.mark.parametrize('role, is_staff, is_allow', [ + ('worker', False, False), + ]) + def test_worker_cannot_create_task_in_project_without_ownership(self, org, project_id, role, is_staff, is_allow, is_project_staff, find_users): + users = find_users(org=org['id'], role=role) + self._test_users_to_create_task_in_project(project_id, users, is_staff, is_allow, is_project_staff, org=org['slug']) class TestGetData: _USERNAME = 'user1' @@ -17,4 +154,4 @@ class TestGetData: def test_frame_content_type(self, content_type, task_id): response = get_method(self._USERNAME, f'tasks/{task_id}/data', type='frame', quality='original', number=0) assert response.status_code == HTTPStatus.OK - assert response.headers['Content-Type'] == content_type + assert response.headers['Content-Type'] == content_type \ No newline at end of file