You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1053 lines
42 KiB
Python

# Copyright (C) 2022 CVAT.ai Corporation
#
# SPDX-License-Identifier: MIT
from copy import deepcopy
from http import HTTPStatus
from itertools import product
import pytest
from deepdiff import DeepDiff
from shared.utils.config import delete_method, get_method, patch_method, post_method
@pytest.mark.usefixtures('changedb')
class TestPostWebhooks:
proj_webhook = {
'description': 'webhook description',
'content_type': 'application/json',
'enable_ssl': False,
'events': [
'create:task',
'delete:task'
],
'is_active': True,
'project_id': 1,
'secret': 'secret',
'target_url': 'http://example.com',
'type': 'project',
}
org_webhook = {
'description': 'webhook description',
'content_type': 'application/json',
'enable_ssl': False,
'events': [
'create:task',
'delete:task'
],
'is_active': True,
'secret': 'secret',
'target_url': 'http://example.com',
'type': 'organization',
}
def test_sandbox_admin_can_create_webhook_for_project(self, projects, users):
admin = next((u for u in users if 'admin' in u['groups']))
project = [p for p in projects if p['owner']['id'] != admin['id'] and p['organization'] is None][0]
webhook = deepcopy(self.proj_webhook)
webhook['project_id'] = project['id']
response = post_method(admin['username'], 'webhooks', webhook)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
def test_admin_can_create_webhook_for_org(self, users, organizations, is_org_member):
admins = [u for u in users if 'admin' in u['groups']]
username, org_id = next((
(user['username'], org['id'])
for user in admins
for org in organizations
if not is_org_member(user['id'], org['id'])
))
webhook = deepcopy(self.org_webhook)
response = post_method(username, 'webhooks', webhook, org_id=org_id)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
def test_admin_can_create_webhook_for_project_in_org(self, users, projects_by_org,
organizations, is_org_member):
admins = [u for u in users if 'admin' in u['groups']]
not_org_members = [(u, o) for u, o in product(admins, organizations)
if not is_org_member(u['id'], o['id'])]
username, org_id = next((
(u['username'], o['id'])
for u, o in not_org_members
for p in projects_by_org.get(o['id'], [])
if p['owner']['id'] != u['id']
))
webhook = deepcopy(self.org_webhook)
response = post_method(username, 'webhooks', webhook, org_id=org_id)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_sandbox_project_owner_can_create_webhook_for_project(self, privilege, projects, users):
users = [user for user in users if privilege in user['groups']]
username, project_id = next((
(user['username'], project['id'])
for user in users
for project in projects
if project['owner']['id'] == user['id'] and project['organization'] is None
))
webhook = deepcopy(self.proj_webhook)
webhook['project_id'] = project_id
response = post_method(username, 'webhooks', webhook)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
@pytest.mark.parametrize('privilege', ['worker', 'user', 'business'])
def test_sandbox_project_assignee_cannot_create_webhook_for_project(self, privilege, projects, users):
users = [u for u in users if privilege in u['groups']]
projects = [p for p in projects if p['assignee'] is not None]
username, project_id = next((
(user['username'], project['id'])
for user in users
for project in projects
if project['assignee']['id'] == user['id'] and project['organization'] is None
))
webhook = deepcopy(self.proj_webhook)
webhook['project_id'] = project_id
response = post_method(username, 'webhooks', webhook)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['maintainer', 'owner'])
def test_member_can_create_webhook_for_org(self, role, find_users, organizations):
username, org_id = next((
(u['username'], o['id'])
for o in organizations
for u in find_users(org=o['id'], role=role, exclude_privilege='admin')
))
webhook = deepcopy(self.org_webhook)
response = post_method(username, 'webhooks', webhook, org_id=org_id)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
@pytest.mark.parametrize('role', ['maintainer', 'owner'])
def test_member_can_create_webhook_for_project(self, role, find_users, organizations,
projects_by_org, is_project_staff):
username, oid, pid = next((
(u['username'], o['id'], p['id'])
for o in organizations
for u in find_users(org=o['id'], role=role, exclude_privilege='admin')
for p in projects_by_org.get(o['id'], [])
if not is_project_staff(u['id'], p['id'])
))
webhook = deepcopy(self.proj_webhook)
webhook['project_id'] = pid
response = post_method(username, 'webhooks', webhook, org_id=oid)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
@pytest.mark.parametrize('role', ['supervisor', 'worker'])
def test_member_cannot_create_webhook_for_org(self, role, find_users, organizations):
username, org_id = next((
(u['username'], o['id'])
for o in organizations
for u in find_users(org=o['id'], role=role, exclude_privilege='admin')
))
webhook = deepcopy(self.org_webhook)
response = post_method(username, 'webhooks', webhook, org_id=org_id)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['supervisor', 'worker'])
def test_member_cannot_create_webhook_for_project(self, role, find_users, organizations,
projects_by_org, is_project_staff):
username, oid, pid = next((
(u['username'], o['id'], p['id'])
for o in organizations
for u in find_users(org=o['id'], role=role, exclude_privilege='admin')
for p in projects_by_org.get(o['id'], [])
if not is_project_staff(u['id'], p['id'])
))
webhook = deepcopy(self.proj_webhook)
webhook['project_id'] = pid
response = post_method(username, 'webhooks', webhook, org_id=oid)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['supervisor'])
def test_member_project_owner_can_create_webhook_for_project(self, role, find_users, organizations,
projects_by_org, is_project_staff):
username, oid, pid = next((
(u['username'], o['id'], p['id'])
for o in organizations
for u in find_users(org=o['id'], role=role, exclude_privilege='admin')
for p in projects_by_org.get(o['id'], [])
if p['owner']['id'] == u['id']
))
webhook = deepcopy(self.proj_webhook)
webhook['project_id'] = pid
response = post_method(username, 'webhooks', webhook, org_id=oid)
assert response.status_code == HTTPStatus.CREATED
assert 'secret' not in response.json()
def test_non_member_cannot_create_webhook_for_org(self, find_users, organizations,
is_org_member):
username, org_id = next((
(u['username'], o['id'])
for o in organizations
for u in find_users(exclude_privilege='admin')
if not is_org_member(u['id'], o['id'])
))
webhook = deepcopy(self.org_webhook)
response = post_method(username, 'webhooks', webhook, org_id=org_id)
assert response.status_code == HTTPStatus.FORBIDDEN
def test_can_create_without_unnecessary_fields(self):
post_data = deepcopy(self.proj_webhook)
post_data.pop('enable_ssl')
post_data.pop('content_type')
post_data.pop('description')
post_data.pop('is_active')
post_data.pop('secret')
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.CREATED
def test_cannot_create_without_target_url(self):
post_data = deepcopy(self.proj_webhook)
post_data.pop('target_url')
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
def test_cannot_create_without_events_list(self):
post_data = deepcopy(self.proj_webhook)
post_data.pop('events')
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
def test_cannot_create_without_type(self):
post_data = deepcopy(self.proj_webhook)
post_data.pop('type')
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
def test_cannot_create_without_project_id(self):
post_data = deepcopy(self.proj_webhook)
post_data.pop('project_id')
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
def test_cannot_create_organization_webhook_when_project_id_is_not_null(self, organizations):
post_data = deepcopy(self.proj_webhook)
post_data['type'] = 'organization'
org_id = organizations.raw[0]['id']
response = post_method('admin2', 'webhooks', post_data, org_id=org_id)
assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
def test_cannot_create_non_unique_webhook(self):
pytest.skip('Not implemeted yet')
response = post_method('admin2', 'webhooks', self.proj_webhook)
response = post_method('admin2', 'webhooks', self.proj_webhook)
assert response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR
def test_cannot_create_for_non_existent_organization(self, organizations):
post_data = deepcopy(self.proj_webhook)
post_data['type'] = 'organization'
org_id = max(a['id'] for a in organizations.raw) + 1
response = post_method('admin2', 'webhooks', post_data, org_id=org_id)
assert response.status_code == HTTPStatus.BAD_REQUEST
def test_cannot_create_for_non_existent_project(self, projects):
post_data = deepcopy(self.proj_webhook)
post_data['project_id'] = max(a['id'] for a in projects.raw) + 1
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
def test_cannot_create_with_non_supported_type(self):
post_data = deepcopy(self.proj_webhook)
post_data['type'] = 'some_type'
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
def test_cannot_create_with_non_supported_content_type(self):
post_data = deepcopy(self.proj_webhook)
post_data['content_type'] = ['application/x-www-form-urlencoded']
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
@pytest.mark.parametrize('event', ['some:event', 'create:project', 'update:organization', 'create:invitation'])
def test_cannot_create_project_webhook_with_non_supported_event_type(self, event):
post_data = deepcopy(self.proj_webhook)
post_data['events'] = [event]
response = post_method('admin2', 'webhooks', post_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
@pytest.mark.parametrize('event', ['some:event', 'create:organization'])
def test_cannot_create_organization_webhook_with_non_supported_event_type(self, event, organizations):
post_data = deepcopy(self.proj_webhook)
post_data['type'] = 'organization'
post_data['events'] = [event]
org_id = next(iter(organizations))['id']
response = post_method('admin2', 'webhooks', post_data, org_id=org_id)
assert response.status_code == HTTPStatus.BAD_REQUEST
@pytest.mark.usefixtures('dontchangedb')
class TestGetWebhooks:
def test_admin_can_get_webhook(self, webhooks, users, projects):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, wid = next((
(user['username'], webhook['id'])
for user in users
for webhook in proj_webhooks
if 'admin' in user['groups']
and webhook['owner']['id'] != user['id']
and projects[webhook['project']]['owner']['id'] != user['id']
))
response = get_method(username, f"webhooks/{wid}")
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhooks[wid], response.json(), ignore_order=True) == {}
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_project_owner_can_get_webhook(self, privilege, webhooks, projects, users):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, wid = next((
(user['username'], webhook['id'])
for user in users
for webhook in proj_webhooks
if privilege not in user['groups']
and projects[webhook['project']]['owner']['id'] == user['id']
))
response = get_method(username, f"webhooks/{wid}")
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhooks[wid], response.json(), ignore_order=True) == {}
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_webhook_owner_can_get_webhook(self, privilege, webhooks, projects, users):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, wid = next((
(user['username'], webhook['id'])
for user in users
for webhook in proj_webhooks
if privilege in user['groups']
and webhook['owner']['id'] == user['id']
))
response = get_method(username, f"webhooks/{wid}")
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhooks[wid], response.json(), ignore_order=True) == {}
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_not_project_staff_cannot_get_webhook(self, privilege, webhooks,
projects, users):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, wid = next((
(user['username'], webhook['id'])
for user in users
for webhook in proj_webhooks
if privilege in user['groups']
and projects[webhook['project']]['owner']['id'] != user['id']
and webhook['owner']['id'] != user['id']
))
response = get_method(username, f"webhooks/{wid}")
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['owner', 'maintainer'])
def test_org_staff_can_see_org_webhook(self, role, webhooks, find_users):
webhook = next((w for w in webhooks if w['type'] == 'organization'))
username = next((
u['username'] for u in find_users(role=role, org=webhook['organization'])
))
response = get_method(username, f"webhooks/{webhook['id']}",
org_id=webhook['organization'])
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True) == {}
@pytest.mark.parametrize('role', ['owner', 'maintainer'])
def test_org_staff_can_see_project_webhook_in_org(self, role, webhooks, find_users,
projects):
proj_webhooks = [w for w in webhooks if w['organization'] is not None and
w['type'] == 'project']
username, webhook = next((
(user['username'], webhook)
for webhook in proj_webhooks
for user in find_users(role=role, org=webhook['organization'])
if projects[webhook['project']]['owner']['id'] != user['id']
and webhook['owner']['id'] != user['id']
))
response = get_method(username, f"webhooks/{webhook['id']}",
org_id=webhook['organization'])
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True) == {}
@pytest.mark.parametrize('role', ['worker', 'supervisor'])
def test_member_cannot_get_org_webhook(self, role, webhooks, find_users):
webhook = next((w for w in webhooks if w['type'] == 'organization'))
username = next((
u['username'] for u in find_users(role=role, org=webhook['organization'])
))
response = get_method(username, f"webhooks/{webhook['id']}",
org_id=webhook['organization'])
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['worker', 'supervisor'])
def test_member_cannot_get_project_webhook_in_org(self, role, webhooks, find_users,
projects):
proj_webhooks = [w for w in webhooks if w['organization'] is not None and
w['type'] == 'project']
username, webhook = next((
(user['username'], webhook)
for webhook in proj_webhooks
for user in find_users(role=role, org=webhook['organization'])
if projects[webhook['project']]['owner']['id'] != user['id']
and webhook['owner']['id'] != user['id']
))
response = get_method(username, f"webhooks/{webhook['id']}",
org_id=webhook['organization'])
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['supervisor'])
def test_member_can_get_project_webhook_in_org(self, role, webhooks, find_users,
projects):
proj_webhooks = [w for w in webhooks if w['organization'] is not None and
w['type'] == 'project']
username, webhook = next((
(user['username'], webhook)
for webhook in proj_webhooks
for user in find_users(role=role, org=webhook['organization'])
if projects[webhook['project']]['owner']['id'] == user['id']
or webhook['owner']['id'] == user['id']
))
response = get_method(username, f"webhooks/{webhook['id']}",
org_id=webhook['organization'])
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True) == {}
@pytest.mark.usefixtures('dontchangedb')
class TestGetListWebhooks:
def test_can_get_webhooks_list(self, webhooks):
response = get_method('admin2', 'webhooks')
assert response.status_code == HTTPStatus.OK
assert all(['secret' not in webhook for webhook in response.json()['results']])
assert DeepDiff(webhooks.raw, response.json()['results'], ignore_order=True) == {}
def test_admin_can_get_webhooks_for_project(self, webhooks):
pid = next((webhook['project'] for webhook in webhooks
if webhook['type'] == 'project' and webhook['organization'] is None))
expected_response = [webhook for webhook in webhooks
if webhook['type'] == 'project' and webhook['project'] == pid]
filter_val = '{"and":[{"==":[{"var":"project_id"},%s]}]}' % pid
response = get_method('admin2', "webhooks", filter=filter_val)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'], ignore_order=True) == {}
def test_admin_can_get_webhooks_for_organization(self, webhooks):
org_id = next((webhook['organization'] for webhook in webhooks
if webhook['organization'] is not None))
expected_response = [webhook for webhook in webhooks
if webhook['organization'] == org_id]
response = get_method('admin2', "webhooks", org_id=org_id)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'], ignore_order=True) == {}
def test_admin_can_get_webhooks_for_project_in_org(self, webhooks):
pid, oid = next((
(webhook['project'], webhook['organization'])
for webhook in webhooks
if webhook['type'] == 'project'
and webhook['organization'] is not None
))
expected_response = [webhook for webhook in webhooks
if webhook['project'] == pid and webhook['organization'] == oid]
filter_val = '{"and":[{"==":[{"var":"project_id"},%s]}]}' % pid
response = get_method('admin2', "webhooks", org_id=oid, filter=filter_val)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'], ignore_order=True) == {}
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_user_cannot_get_webhook_list_for_project(self, privilege, find_users,
webhooks, projects):
username, pid = next((
(user['username'], webhook['project'])
for user in find_users(privilege=privilege)
for webhook in webhooks
if webhook['type'] == 'project'
and webhook['organization'] is None
and webhook['owner']['id'] != user['id']
and projects[webhook['project']]['owner']['id'] != user['id']
))
filter_val = '{"and":[{"==":[{"var":"project_id"},%s]}]}' % pid
response = get_method(username, "webhooks", filter=filter_val)
assert response.status_code == HTTPStatus.OK
assert DeepDiff([], response.json()['results'], ignore_order=True) == {}
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_user_can_get_webhook_list_for_project(self, privilege, find_users,
webhooks, projects):
username, pid = next((
(user['username'], webhook['project'])
for user in find_users(privilege=privilege)
for webhook in webhooks
if webhook['type'] == 'project'
and webhook['organization'] is None
and projects[webhook['project']]['owner']['id'] == user['id']
))
expected_response = [w for w in webhooks
if w['type'] == 'project' and w['project'] == pid]
filter_val = '{"and":[{"==":[{"var":"project_id"},%s]}]}' % pid
response = get_method(username, "webhooks", filter=filter_val)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'],
ignore_order=True) == {}
def test_non_member_cannot_see_webhook_list_for_org(self, webhooks, users,
is_org_member):
username, org_id = next((
(user['username'], webhook['organization'])
for webhook in webhooks
for user in users
if webhook['organization'] is not None
and not is_org_member(user['id'], webhook['organization'])
and 'admin' not in user['groups']
))
response = get_method(username, 'webhooks', org_id=org_id)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role', ['maintainer', 'owner'])
def test_org_staff_can_see_all_org_webhooks(self, role, webhooks, organizations,
find_users):
username, org_id = next((
(user['username'], org['id'])
for webhook in webhooks
for org in organizations
for user in find_users(role=role, org=org['id'])
if webhook['organization'] == org['id']
))
expected_response = [webhook for webhook in webhooks
if webhook['organization'] == org_id]
response = get_method(username, 'webhooks', org_id=org_id)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'],
ignore_order=True) == {}
@pytest.mark.parametrize('role', ['worker', 'supervisor'])
def test_member_cannot_see_all_org_webhook(self, role, webhooks, organizations,
find_users, projects):
username, org_id = next((
(user['username'], org['id'])
for webhook in webhooks
for org in organizations
for user in find_users(role=role, org=org['id'])
if webhook['organization'] == org['id']
))
expected_response = [
webhook for webhook in webhooks
if webhook['organization'] == org_id
and (webhook['owner']['username'] == username
or (webhook['project']
and projects[webhook['project']]['owner']['username'] == username))
]
response = get_method(username, 'webhooks', org_id=org_id)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'],
ignore_order=True) == {}
@pytest.mark.parametrize('role', ['supervisor'])
def test_member_can_see_list_of_project_webhooks_in_org(self, role, webhooks,
organizations, find_users, projects):
username, org_id = next((
(user['username'], org['id'])
for webhook in webhooks
for org in organizations
for user in find_users(role=role, org=org['id'])
if webhook['organization'] == org['id']
and webhook['type'] == 'project'
and projects[webhook['project']]['owner']['id'] == user['id']
))
expected_response = [
webhook for webhook in webhooks
if webhook['organization'] == org_id
and webhook['type'] == 'project'
and projects[webhook['project']]['owner']['username'] == username
]
response = get_method(username, 'webhooks', org_id=org_id)
assert response.status_code == HTTPStatus.OK
assert DeepDiff(expected_response, response.json()['results'],
ignore_order=True) == {}
@pytest.mark.usefixtures('changedb')
class TestPatchWebhooks:
WID = 2
def test_sandbox_admin_can_update_any_webhook(self, webhooks, find_users):
username, webhook = next((
(user['username'], deepcopy(webhook))
for user in find_users(privilege='admin')
for webhook in webhooks
if webhook['owner']['id'] != user['id'] and webhook['organization'] is None
))
patch_data = {
'target_url': 'http://newexample.com',
'secret': 'newsecret',
'events': ['create:task'],
'is_active': not webhook['is_active'],
'enable_ssl': not webhook['enable_ssl'],
}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}", patch_data)
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True,
exclude_paths=["root['updated_date']", "root['secret']"]) == {}
def test_cannot_update_with_nonexistent_contenttype(self):
patch_data = {
'content_type': 'application/x-www-form-urlencoded',
}
response = patch_method('admin2', f'webhooks/{self.WID}', patch_data)
assert response.status_code == HTTPStatus.BAD_REQUEST
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_sandbox_user_can_update_webhook(self, privilege, find_users, webhooks):
username, webhook = next((
(user['username'], deepcopy(webhook))
for user in find_users(privilege=privilege)
for webhook in webhooks
if webhook['owner']['id'] == user['id']
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}", patch_data)
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True,
exclude_paths=["root['updated_date']", "root['secret']"]) == {}
@pytest.mark.parametrize('privilege', ['worker', 'user', 'business'])
def test_sandbox_user_cannot_update_webhook(self, privilege, find_users, webhooks):
username, webhook = next((
(user['username'], deepcopy(webhook))
for user in find_users(privilege=privilege)
for webhook in webhooks
if webhook['owner']['id'] != user['id']
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}", patch_data)
assert response.status_code == HTTPStatus.FORBIDDEN
def test_admin_can_update_org_webhook(self, find_users, organizations, webhooks, is_org_member):
org_webhooks = [w for w in webhooks if w['type'] == 'organization']
admin, oid, webhook = next((
(u['username'], o['id'], deepcopy(w))
for u in find_users(privilege='admin')
for o in organizations
for w in org_webhooks
if w['organization'] == o['id'] and not is_org_member(u['id'], o['id'])
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(admin, f"webhooks/{webhook['id']}", patch_data, org_id=oid)
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True,
exclude_paths=["root['updated_date']", "root['secret']"]) == {}
@pytest.mark.parametrize('role', ['maintainer', 'owner'])
def test_member_can_update_org_webhook(self, role, find_users, organizations, webhooks):
org_webhooks = [w for w in webhooks if w['type'] == 'organization']
username, oid, webhook = next((
(u['username'], o['id'], deepcopy(w))
for o in organizations
for u in find_users(role=role, org=o['id'])
for w in org_webhooks
if w['organization'] == o['id']
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}", patch_data, org_id=oid)
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True,
exclude_paths=["root['updated_date']", "root['secret']"]) == {}
@pytest.mark.parametrize('role', ['worker', 'supervisor'])
def test_member_cannot_update_org_webhook(self, role, find_users, organizations, webhooks):
org_webhooks = [w for w in webhooks if w['type'] == 'organization']
username, oid, webhook = next((
(u['username'], o['id'], deepcopy(w))
for o in organizations
for u in find_users(role=role, org=o['id'])
for w in org_webhooks
if w['organization'] == o['id']
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}", patch_data, org_id=oid)
assert response.status_code == HTTPStatus.FORBIDDEN
@pytest.mark.parametrize('role, allow', [
('maintainer', True), ('owner', True),
('supervisor', False), ('worker', False)
])
def test_member_can_update_any_project_webhook_in_org(self, role, allow, find_users,
organizations, projects_by_org, webhooks, is_project_staff):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, org_id, webhook = next((
(u['username'], o['id'], deepcopy(w))
for o in organizations
for u in find_users(role=role, org=o['id'])
for w in proj_webhooks
for p in projects_by_org.get(o['id'], [])
if w['project'] == p['id']
and w['organization'] == o['id']
and not is_project_staff(u['id'], p['id'])
and w['owner']['id'] != u['id']
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}",
patch_data, org_id=org_id)
if not allow:
assert response.status_code == HTTPStatus.FORBIDDEN
else:
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True,
exclude_paths=["root['updated_date']", "root['secret']"]) == {}
@pytest.mark.parametrize('role', ['supervisor'])
def test_member_can_update_project_webhook_in_org(self, role, find_users,
organizations, projects_by_org, webhooks):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, org_id, webhook = next((
(u['username'], o['id'], deepcopy(w))
for o in organizations
for u in find_users(role=role, org=o['id'])
for w in proj_webhooks
for p in projects_by_org.get(o['id'], [])
if w['project'] == p['id']
and w['organization'] == o['id']
and u['id'] == p['owner']['id']
))
patch_data = {'target_url': 'http://newexample.com'}
webhook.update(patch_data)
response = patch_method(username, f"webhooks/{webhook['id']}",
patch_data, org_id=org_id)
assert response.status_code == HTTPStatus.OK
assert 'secret' not in response.json()
assert DeepDiff(webhook, response.json(), ignore_order=True,
exclude_paths=["root['updated_date']", "root['secret']"]) == {}
@pytest.mark.usefixtures('changedb')
class TestDeleteWebhooks:
@pytest.mark.parametrize('privilege, allow', [
('user', False), ('business', False), ('admin', True)
])
def test_user_can_delete_project_webhook(self, privilege, allow, find_users,
webhooks, projects):
users = find_users(privilege=privilege)
username, webhook_id = next((
(user['username'], webhook['id'])
for webhook in webhooks for user in users
if webhook['type'] == 'project'
and webhook['organization'] is None
and webhook['owner']['id'] != user['id']
and projects[webhook['project']]['owner']['id'] != user['id']
))
if not allow:
response = delete_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.FORBIDDEN
else:
response = delete_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NOT_FOUND
def test_admin_can_delete_project_webhook_in_org(self, find_users, webhooks,
projects, is_org_member):
admins = find_users(privilege='admin')
username, webhook_id = next((
(user['username'], webhook['id'])
for user in admins
for webhook in webhooks
if webhook['type'] == 'project'
and webhook['organization'] is not None
and webhook['owner']['id'] != user['id']
and projects[webhook['project']]['owner']['id'] != user['id']
and not is_org_member(user['id'], webhook['organization'])
))
response = delete_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NOT_FOUND
def test_admin_can_delete_org_webhook(self, find_users, webhooks, is_org_member):
admins = find_users(privilege='admin')
username, webhook_id = next((
(user['username'], webhook['id'])
for user in admins
for webhook in webhooks
if webhook['type'] == 'organization'
and webhook['organization'] is not None
and webhook['owner']['id'] != user['id']
and not is_org_member(user['id'], webhook['organization'])
))
response = delete_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NOT_FOUND
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_project_owner_can_delete_project_webhook(self, privilege, find_users,
webhooks, projects):
users = find_users(privilege=privilege)
username, webhook_id = next((
(user['username'], webhook['id'])
for user in users
for webhook in webhooks
if webhook['type'] == 'project'
and webhook['organization'] is None
and projects[webhook['project']]['owner']['id'] == user['id']
))
response = delete_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NOT_FOUND
@pytest.mark.parametrize('privilege', ['user', 'business'])
def test_webhook_owner_can_delete_project_webhook(self, privilege, find_users,
webhooks, projects):
users = find_users(privilege=privilege)
username, webhook_id = next((
(user['username'], webhook['id'])
for user in users
for webhook in webhooks
if webhook['type'] == 'project'
and webhook['organization'] is None
and webhook['owner']['id'] == user['id']
))
response = delete_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}')
assert response.status_code == HTTPStatus.NOT_FOUND
@pytest.mark.parametrize('role, allow', [
('owner', True), ('maintainer', True),
('worker', False), ('supervisor', False)
])
def test_member_can_delete_org_webhook(self, role, allow, find_users, organizations,
webhooks):
org_webhooks = [w for w in webhooks if w['type'] == 'organization']
print(org_webhooks)
username, org_id, webhook_id = next((
(user['username'], org['id'], webhook['id'])
for org in organizations
for webhook in org_webhooks
for user in find_users(role=role, org=org['id'])
if webhook['organization'] == org['id']
))
if not allow:
response = delete_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.FORBIDDEN
else:
response = delete_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.NOT_FOUND
@pytest.mark.parametrize('role, allow', [
('owner', True), ('maintainer', True),
('worker', False), ('supervisor', False)
])
def test_member_can_delete_project_webhook_in_org(self, role, allow, find_users,
organizations, projects, webhooks):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, org_id, webhook_id = next((
(user['username'], webhook['organization'], webhook['id'])
for org in organizations
for user in find_users(role=role, org=org['id'])
for webhook in proj_webhooks
if webhook['organization']
and webhook['organization'] == org['id']
and projects[webhook['project']]['owner']['id'] != user['id']
and webhook['owner']['id'] != user['id']
))
if not allow:
response = delete_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.FORBIDDEN
else:
response = delete_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.NOT_FOUND
@pytest.mark.parametrize('role', ['supervisor'])
def test_member_webhook_staff_can_delete_project_webhook_in_org(self, role,
find_users, organizations, projects, webhooks):
proj_webhooks = [w for w in webhooks if w['type'] == 'project']
username, org_id, webhook_id = next((
(user['username'], webhook['organization'], webhook['id'])
for org in organizations
for user in find_users(role=role, org=org['id'])
for webhook in proj_webhooks
if webhook['organization']
and webhook['organization'] == org['id']
and (projects[webhook['project']]['owner']['id'] == user['id']
or webhook['owner']['id'] == user['id'])
))
response = delete_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.NO_CONTENT
response = get_method(username, f'webhooks/{webhook_id}', org_id=org_id)
assert response.status_code == HTTPStatus.NOT_FOUND