1
0
mirror of https://github.com/peeringdb/peeringdb.git synced 2024-05-11 05:55:09 +00:00
Files
peeringdb-peeringdb/tests/test_keys.py
Matt Griswold 8cc0f13ec1 Support 202102 (#950)
* install django-grainy

* nsp to grainy first iteration

* nsp to grainy second iteration

* grainy and django-grainy pinned to latest releases

* Fix typo

* Update djangorestframework, peeringdb, django-ratelimit

* Rewrite login view ratelimit decorator

* Relock pipfile

* add list() to make copy of dictionaries before iterating

* relock pipfile with python3.9
change docker to use python3.9

* add ordering to admin search queryset for deskproticket and email

* add org api key and begin to write tests

* additional key tests

* add drf-api-keys to pipfile

* Wire orgapikey to modelviewsetpermissions

* Update api key helper functions

* add put test

* Add Org API key tab to frontend

* Add user api key model

* Update user key handling and tests

* Update APIPermissionsApplicator to make it work w requests

* Add org api key perm panel

* add org key permissions

* Add user api key views

* Add templates for handling user api key (adding, not revoking)

* relock pipfile

* assorted fixes and tweaks

* Add general user group permissions and org user group perms

* refactor org api key perms

* Add tests for api keys

* Add docstrings to permissions helpers

* Add api key examples

* squash migrations

* remove custom api key header config

* Change api key test setup

* Update permissions for grainy change

* Bump up pipfile and pipfile.lock

* Add API Key to Verification Queue Item

* Delete travis

* Add workaround to Dockerfile

* update pipfile and sort out migrations

* Add comment to Dockerfile

* Re-add API Key migrations

* Add locale to .gitignore

* remove suggest functionality from ix

* Update test to recognize that IX api no longer has suggest function

* Add test to outlaw POSTing an IX w its org equal to the suggest entity org

* Add meta information geowarning

* Add alert to demonstrate UI

* Add error to fac update

* Add template warning for geovalidation

* Add geowarning meta js

* cover absent meta_response test case

* Update styles for geowarning

* refactor geotag warning implementation

* null lat and long on unsuccessful geo locate

* modify geovalidation frontend update

* Add deskproticket model email field

* Add missing span

* add email to org keys

* Add email to org key tests

* update serializer with rdap validation wrapper

* update admin for api keys

* Enable writing an email as part of org key creation

* Add email validation to org api key form

* fix css style on perm row

* Add suggested info to api response

* display suggested address on frontend

* add needs geocode to serializer

* save lat long on forward geonormalization

* add address suggestion submit button

* Add suggested address popin to ADD facility form

* Fix css

* add lat and long rounding to geocodenabled model clean method

* add migration and regression test for lat long decimal db constraint

* Add another regression test for model decimal places

* Get deskpro functions passing isort and flake

* Update ticket_queue_deletion_prevented

* update ticket_queue_deletion_prevented for use with org api key

* add template for org key dpt from asnauto skipvq

* Update deskproticket for rdap error

* add facility aka

* add aka to serializer and views

* black and isort test api keys

* fix typo in org key deskpro template

* skip or rewrite unapplicable org key tests, and add as_set tests

* adjust api key test comments

* Add vqi_notify to signals

* Add reversion comments for api keys and helper function

* update how org keys are added to verification queue items

* rename verification queue item fk from api_key to org_key

* fix group id error

* update key tests with correct http header info

* check both user and key, not just user

* templates fiex

* adapt deskpro integration to work with email only

* make org api keys editable for desc and email

* pipfile relock

* edit test setupdata settings for groups

* Change comment to signify we don't need to remove code

* address untranslated accept button

* Add docstrings to the serializer functions

* Add loading shim

* Add migration for all longname and aka

* Add aka and long name to views and serializers

* delete migration w decimals

* standardize serializer lat and long fields

* Add clean rounding for lat and long

* fix serializer error

* api key admin improvements

* fix linebreak in user api key form

* remove debug prints

* Add rounding util

* Add rounding to lat and long fields

* remove 'clean' from geocode method (logic now in admin form)

* remove erroneous tests

* revert serializer changes

* Fix migrations

* Add long name and aka to admin models

* Update API key docs

* Add documentation for api keys

* fix typo

* fix org api key revoke broken by editable api keys

* doc tweaks

* doc tweaks

* doc tweaks

* black format

* fix migration hierarchy

* docs

* docs

* api key permissions screenshot

* formatting

* formatting

* padding fixed

* remove one image

* fix get_user_from_request type checking
take out POST only valdiator for entity suggest

* didnt mean to commit the django-peeringdb mount

* fix suggest on PUT net
fix tests

* black formatting

* update org key permission template

* install rust for cryptography

* pipfile relock (django-peeringdb to 2.6)

Co-authored-by: Stefan Pratter <stefan@20c.com>
Co-authored-by: Elliot Frank <elliot@20c.com>
2021-03-09 13:30:30 -06:00

342 lines
11 KiB
Python

import pytest
from django.conf import settings
from django.test import RequestFactory
from django.urls import reverse
from django_grainy.models import UserPermission
from grainy.const import PERM_CRUD, PERM_READ
from rest_framework.test import APIClient
from peeringdb_server.models import (
Group,
Network,
Organization,
OrganizationAPIKey,
OrganizationAPIPermission,
User,
UserAPIKey,
)
from peeringdb_server.permissions import (
check_permissions,
get_key_from_request,
get_permission_holder_from_request,
)
from .util import reset_group_ids
@pytest.fixture
def admin_user():
admin_user = User.objects.create_user(
"admin", "admin@localhost", first_name="admin", last_name="admin"
)
admin_user.is_superuser = True
admin_user.is_staff = True
admin_user.save()
admin_user.set_password("admin")
admin_user.save()
return admin_user
@pytest.fixture
def admin_client(admin_user):
c = APIClient()
c.login(username="admin", password="admin")
return c
@pytest.fixture
def groups():
Group.objects.create(name="guest")
Group.objects.create(name="user")
reset_group_ids()
@pytest.fixture
def user():
user = User.objects.create_user(
"user", "user@localhost", first_name="user", last_name="user"
)
user.save()
user.set_password("user")
user.save()
return user
@pytest.fixture
def org():
org = Organization.objects.create(name="test org")
return org
@pytest.fixture
def network(org):
net = Network.objects.create(name="test network", org=org, asn=123, status="ok")
return net
@pytest.mark.django_db
def test_create_org_api_key(org):
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
assert api_key.revoked is False
assert api_key.name == "test key"
assert api_key.is_valid(key) is True
# Test foreign key
assert org.api_keys.first() == api_key
@pytest.mark.django_db
def test_create_user_api_key(user):
api_key, key = UserAPIKey.objects.create_key(name="test key", user=user)
assert api_key.revoked is False
assert api_key.name == "test key"
assert api_key.is_valid(key) is True
assert api_key.readonly is False
# Test foreign key
assert user.api_keys.first() == api_key
@pytest.mark.django_db
def test_revoke_org_api_key(org):
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
api_key.revoked = True
api_key.save()
org.refresh_from_db()
assert org.api_keys.get_usable_keys().count() == 0
assert org.api_keys.count() == 1
@pytest.mark.django_db
def test_revoke_user_api_key(user):
api_key, key = UserAPIKey.objects.create_key(name="test key", user=user)
api_key.revoked = True
api_key.save()
user.refresh_from_db()
assert user.api_keys.get_usable_keys().count() == 0
assert user.api_keys.count() == 1
@pytest.mark.django_db
def test_validate_org_api_key(org):
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
assert api_key.is_valid(key)
assert api_key.is_valid("abcd") is False
@pytest.mark.django_db
def test_validate_user_api_key(user):
api_key, key = UserAPIKey.objects.create_key(name="test key", user=user)
assert api_key.is_valid(key)
assert api_key.is_valid("abcd") is False
@pytest.mark.django_db
def test_set_perms(org):
namespace = "peeringdb.organization.1.network"
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
OrganizationAPIPermission.objects.create(
org_api_key=api_key, namespace=namespace, permission=PERM_CRUD
)
assert api_key.grainy_permissions.count() == 1
@pytest.mark.django_db
def test_check_perms(org, groups):
namespace = "peeringdb.organization.1.network"
api_key, key = OrganizationAPIKey.objects.create_key(name="test key", org=org)
OrganizationAPIPermission.objects.create(
org_api_key=api_key, namespace=namespace, permission=PERM_READ
)
assert check_permissions(api_key, namespace, "r")
assert check_permissions(api_key, namespace, "u") is False
def test_get_key_from_request():
key = "abcd"
factory = RequestFactory()
request = factory.get("/api/net/1")
# Add api key header
request.META.update({"HTTP_AUTHORIZATION": "Api-Key " + key})
assert get_key_from_request(request) == key
@pytest.mark.django_db
def test_check_permissions_on_unauth_request(org):
namespace = "peeringdb.organization.1.network"
api_key, key = OrganizationAPIKey.objects.create_key(name="test key", org=org)
OrganizationAPIPermission.objects.create(
org_api_key=api_key, namespace=namespace, permission=PERM_READ
)
factory = RequestFactory()
request = factory.get("/api/net/1")
# Check permissions without any credentials
assert hasattr(request, "user") is False
assert request.META.get("HTTP_AUTHORIZATION") is None
perm_obj = get_permission_holder_from_request(request)
print(perm_obj)
assert check_permissions(perm_obj, namespace, "r") is False
@pytest.mark.django_db
def test_check_permissions_on_org_key_request_readonly(org, groups):
namespace = "peeringdb.organization.1.network"
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
OrganizationAPIPermission.objects.create(
org_api_key=api_key, namespace=namespace, permission=PERM_READ
)
factory = RequestFactory()
request = factory.get("/api/net/1")
# Add api key header
request.META.update({"HTTP_AUTHORIZATION": "Api-Key " + key})
# Assert we're making a request with a OrgAPIKey
assert hasattr(request, "user") is False
assert request.META["HTTP_AUTHORIZATION"] == "Api-Key " + key
# Test permissions
perm_obj = get_permission_holder_from_request(request)
assert check_permissions(perm_obj, namespace, "c") is False
assert check_permissions(perm_obj, namespace, "r")
assert check_permissions(perm_obj, namespace, "u") is False
assert check_permissions(perm_obj, namespace, "d") is False
@pytest.mark.django_db
def test_check_permissions_on_org_key_request_crud(org, groups):
namespace = "peeringdb.organization.1.network"
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
OrganizationAPIPermission.objects.create(
org_api_key=api_key, namespace=namespace, permission=PERM_CRUD
)
factory = RequestFactory()
request = factory.get("/api/net/1")
# Add api key header
request.META.update({"HTTP_AUTHORIZATION": "Api-Key " + key})
# Assert we're making a request with a OrgAPIKey
assert hasattr(request, "user") is False
assert request.META["HTTP_AUTHORIZATION"] == "Api-Key " + key
# Test permissions
perm_obj = get_permission_holder_from_request(request)
assert check_permissions(perm_obj, namespace, "c")
assert check_permissions(perm_obj, namespace, "r")
assert check_permissions(perm_obj, namespace, "u")
assert check_permissions(perm_obj, namespace, "d")
@pytest.mark.django_db
def test_check_permissions_on_user_key_request_crud(user):
namespace = "peeringdb.organization.1.network"
api_key, key = UserAPIKey.objects.create_key(name="test key", user=user)
UserPermission.objects.create(namespace=namespace, permission=PERM_CRUD, user=user)
factory = RequestFactory()
request = factory.get("/api/net/1")
# Add api key header
request.META.update({"HTTP_AUTHORIZATION": "Api-Key " + key})
# Assert we're making a request with a OrgAPIKey
assert hasattr(request, "user") is False
assert request.META["HTTP_AUTHORIZATION"] == "Api-Key " + key
# Test permissions
perm_obj = get_permission_holder_from_request(request)
assert check_permissions(perm_obj, namespace, "c")
assert check_permissions(perm_obj, namespace, "r")
assert check_permissions(perm_obj, namespace, "u")
assert check_permissions(perm_obj, namespace, "d")
@pytest.mark.django_db
def test_check_permissions_on_user_key_request_readonly(user):
namespace = "peeringdb.organization.1.network"
api_key, key = UserAPIKey.objects.create_key(
name="test key", user=user, readonly=True
)
assert api_key.readonly
# Define permissions as CRUD
UserPermission.objects.create(namespace=namespace, permission=PERM_CRUD, user=user)
factory = RequestFactory()
request = factory.get("/api/net/1")
# Add api key header
request.META.update({"HTTP_AUTHORIZATION": "Api-Key " + key})
# Assert we're making a request with a OrgAPIKey
assert hasattr(request, "user") is False
assert request.META["HTTP_AUTHORIZATION"] == "Api-Key " + key
# Test permissions are readonly
perm_obj = get_permission_holder_from_request(request)
assert perm_obj == api_key
assert check_permissions(perm_obj, namespace, "c") is False
assert check_permissions(perm_obj, namespace, "r")
assert check_permissions(perm_obj, namespace, "u") is False
assert check_permissions(perm_obj, namespace, "d") is False
@pytest.mark.django_db
def test_get_network_w_org_key(org, network, user, groups):
namespace = f"peeringdb.organization.{org.id}.network"
api_key, key = OrganizationAPIKey.objects.create_key(
name="test key", org=org, email="test@localhost"
)
OrganizationAPIPermission.objects.create(
org_api_key=api_key, namespace=namespace, permission=PERM_READ
)
assert Network.objects.count() == 1
url = reverse("net-detail", args=(network.id,))
client = APIClient()
response = client.get(url, HTTP_AUTHORIZATION="Api-Key " + key)
assert response.status_code == 200
net_from_api = response.json()["data"][0]
assert net_from_api["name"] == network.name
assert net_from_api["asn"] == network.asn
assert net_from_api["org_id"] == network.org.id
@pytest.mark.django_db
def test_get_network_w_user_key(network, user, org):
namespace = f"peeringdb.organization.{org.id}.network"
userperm = UserPermission.objects.create(
namespace=namespace, permission=PERM_CRUD, user=user
)
api_key, key = UserAPIKey.objects.create_key(name="test key", user=user)
assert userperm == user.grainy_permissions.first()
assert Network.objects.count() == 1
url = reverse("net-detail", args=(network.id,))
client = APIClient()
client.credentials(HTTP_AUTHORIZATION="Api-Key " + key)
response = client.get(url)
assert response.status_code == 200
net_from_api = response.json()["data"][0]
assert net_from_api["name"] == network.name
assert net_from_api["asn"] == network.asn
assert net_from_api["org_id"] == network.org.id