add domain tests

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt 2023-12-06 18:56:27 +01:00
parent cdfbb48cb6
commit 35482f48d4
No known key found for this signature in database
GPG Key ID: 9C3FA22FABF1AA8D
6 changed files with 410 additions and 64 deletions

View File

@ -1,59 +1,19 @@
"""Test Tenant API"""
from json import loads
from django.core.management import call_command
from django.db import connection
from django.urls import reverse
from rest_framework.test import APILiveServerTestCase, APITestCase, APITransactionTestCase
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.tenants.tests.utils import TenantAPITestCase
TENANTS_API_KEY = generate_id()
HEADERS = {"Authorization": f"Bearer {TENANTS_API_KEY}"}
class TestAPI(APITransactionTestCase):
class TestAPI(TenantAPITestCase):
"""Test api view"""
def _fixture_teardown(self):
for db_name in self._databases_names(include_mirrors=False):
call_command(
"flush",
verbosity=0,
interactive=False,
database=db_name,
reset_sequences=False,
allow_cascade=True,
inhibit_post_migrate=False,
)
def setUp(self):
call_command("migrate_schemas", schema="template", tenant=True)
def assertSchemaExists(self, schema_name):
with connection.cursor() as cursor:
cursor.execute(
f"SELECT * FROM information_schema.schemata WHERE schema_name = '{schema_name}';"
)
self.assertEqual(cursor.rowcount, 1)
cursor.execute(
"SELECT * FROM information_schema.tables WHERE table_schema = 'template';"
)
expected_tables = cursor.rowcount
cursor.execute(
f"SELECT * FROM information_schema.tables WHERE table_schema = '{schema_name}';"
)
self.assertEqual(cursor.rowcount, expected_tables)
def assertSchemaDoesntExist(self, schema_name):
with connection.cursor() as cursor:
cursor.execute(
f"SELECT * FROM information_schema.schemata WHERE schema_name = '{schema_name}';"
)
self.assertEqual(cursor.rowcount, 0)
@CONFIG.patch("outposts.disable_embedded_outpost", True)
@CONFIG.patch("tenants.enabled", True)
@CONFIG.patch("tenants.api_key", TENANTS_API_KEY)

View File

@ -0,0 +1,51 @@
"""Test Domain API"""
from json import loads
from django.urls import reverse
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.tenants.models import Domain, Tenant
from authentik.tenants.tests.utils import TenantAPITestCase
TENANTS_API_KEY = generate_id()
HEADERS = {"Authorization": f"Bearer {TENANTS_API_KEY}"}
class TestDomainAPI(TenantAPITestCase):
def setUp(self):
super().setUp()
self.tenant = Tenant.objects.create(
name=generate_id(), schema_name="t_" + generate_id().lower()
)
def tearDown(self):
self.tenant.delete()
@CONFIG.patch("outposts.disable_embedded_outpost", True)
@CONFIG.patch("tenants.enabled", True)
@CONFIG.patch("tenants.api_key", TENANTS_API_KEY)
def test_domain(self):
"""Test domain creation"""
response = self.client.post(
reverse("authentik_api:domain-list"),
headers=HEADERS,
data={"tenant": self.tenant.pk, "domain": "test.domain"},
)
self.assertEqual(response.status_code, 201)
body = loads(response.content.decode())
self.assertEqual(self.tenant.domains.get(domain="test.domain").pk, body["id"])
self.assertEqual(self.tenant.domains.get(domain="test.domain").is_primary, True)
response = self.client.post(
reverse("authentik_api:domain-list"),
headers=HEADERS,
data={"tenant": self.tenant.pk, "domain": "newprimary.domain", "is_primary": True},
)
self.assertEqual(response.status_code, 201)
self.assertEqual(
Domain.objects.get(tenant=self.tenant, domain="newprimary.domain").is_primary, True
)
self.assertEqual(
Domain.objects.get(tenant=self.tenant, domain="test.domain").is_primary, False
)

View File

@ -0,0 +1,50 @@
"""Test Settings API"""
from json import loads
from django.urls import reverse
from django_tenants.utils import get_public_schema_name
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.tenants.models import Domain, Tenant
from authentik.tenants.tests.utils import TenantAPITestCase
TENANTS_API_KEY = generate_id()
HEADERS = {"Authorization": f"Bearer {TENANTS_API_KEY}"}
# class TestSettingsAPI(TenantAPITestCase):
# def setUp(self):
# super().setUp()
# self.tenant_1 = Tenant.objects.get(schema_name=get_public_schema_name())
# self.tenant_2 = Tenant.objects.create(
# name=generate_id(), schema_name="t_" + generate_id().lower()
# )
#
# @CONFIG.patch("outposts.disable_embedded_outpost", True)
# @CONFIG.patch("tenants.enabled", True)
# @CONFIG.patch("tenants.api_key", TENANTS_API_KEY)
# def test_domain(self):
# """Test domain creation"""
# response = self.client.post(
# reverse("authentik_api:domain-list"),
# headers=HEADERS,
# data={"tenant": self.tenant.pk, "domain": "test.domain"},
# )
# self.assertEqual(response.status_code, 201)
# body = loads(response.content.decode())
# self.assertEqual(self.tenant.domains.get(domain="test.domain").pk, body["id"])
# self.assertEqual(self.tenant.domains.get(domain="test.domain").is_primary, True)
#
# response = self.client.post(
# reverse("authentik_api:domain-list"),
# headers=HEADERS,
# data={"tenant": self.tenant.pk, "domain": "newprimary.domain", "is_primary": True},
# )
# self.assertEqual(response.status_code, 201)
# self.assertEqual(
# Domain.objects.get(tenant=self.tenant, domain="newprimary.domain").is_primary, True
# )
# self.assertEqual(
# Domain.objects.get(tenant=self.tenant, domain="test.domain").is_primary, False
# )

View File

@ -0,0 +1,56 @@
from django.core.management import call_command
from django.db import connection, connections
from rest_framework.test import APITransactionTestCase
class TenantAPITestCase(APITransactionTestCase):
# Overriden to force TRUNCATE CASCADE
def _fixture_teardown(self):
for db_name in self._databases_names(include_mirrors=False):
call_command(
"flush",
verbosity=0,
interactive=False,
database=db_name,
reset_sequences=False,
allow_cascade=True,
inhibit_post_migrate=False,
)
with connections[db_name].cursor() as cursor:
cursor.execute(
"SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname !~ 'pg_*' AND nspname != 'information_schema' AND nspname != 'public' AND nspname != 'template'"
)
schemas = cursor.fetchall()
for row in schemas:
schema = row[0]
cursor.execute(f"DROP SCHEMA {schema}")
def setUp(self):
call_command("migrate_schemas", schema="template", tenant=True)
def assertSchemaExists(self, schema_name):
with connection.cursor() as cursor:
cursor.execute(
f"SELECT * FROM information_schema.schemata WHERE schema_name = %(schema_name)s",
{"schema_name": schema_name},
)
self.assertEqual(cursor.rowcount, 1)
cursor.execute(
"SELECT * FROM information_schema.tables WHERE table_schema = 'template'"
)
expected_tables = cursor.rowcount
cursor.execute(
f"SELECT * FROM information_schema.tables WHERE table_schema = %(schema_name)s",
{"schema_name": schema_name},
)
self.assertEqual(cursor.rowcount, expected_tables)
def assertSchemaDoesntExist(self, schema_name):
with connection.cursor() as cursor:
cursor.execute(
f"SELECT * FROM information_schema.schemata WHERE schema_name = %(schema_name)s",
{"schema_name": schema_name},
)
self.assertEqual(cursor.rowcount, 0)

View File

@ -1,12 +1,16 @@
"""API URLs"""
from django.urls import path
from authentik.tenants.api import SettingsView, TenantViewSet
from authentik.tenants.api import DomainViewSet, SettingsView, TenantViewSet
api_urlpatterns = [
path("admin/settings/", SettingsView.as_view(), name="tenant_settings"),
(
"tenants",
"tenants/tenants",
TenantViewSet,
),
(
"tenants/domains",
DomainViewSet,
),
]

View File

@ -27839,9 +27839,221 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/tenants/:
/tenants/domains/:
get:
operationId: tenants_list
operationId: tenants_domains_list
description: Domain ViewSet
parameters:
- name: ordering
required: false
in: query
description: Which field to use when ordering the results.
schema:
type: string
- name: page
required: false
in: query
description: A page number within the paginated result set.
schema:
type: integer
- name: page_size
required: false
in: query
description: Number of results to return per page.
schema:
type: integer
- name: search
required: false
in: query
description: A search term.
schema:
type: string
tags:
- tenants
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedDomainList'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
post:
operationId: tenants_domains_create
description: Domain ViewSet
tags:
- tenants
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/DomainRequest'
required: true
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/tenants/domains/{id}/:
get:
operationId: tenants_domains_retrieve
description: Domain ViewSet
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Domain.
required: true
tags:
- tenants
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
put:
operationId: tenants_domains_update
description: Domain ViewSet
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Domain.
required: true
tags:
- tenants
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/DomainRequest'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
patch:
operationId: tenants_domains_partial_update
description: Domain ViewSet
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Domain.
required: true
tags:
- tenants
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PatchedDomainRequest'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Domain'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
delete:
operationId: tenants_domains_destroy
description: Domain ViewSet
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Domain.
required: true
tags:
- tenants
responses:
'204':
description: No response body
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/tenants/tenants/:
get:
operationId: tenants_tenants_list
description: Tenant Viewset
parameters:
- name: ordering
@ -27870,8 +28082,6 @@ paths:
type: string
tags:
- tenants
security:
- authentik: []
responses:
'200':
content:
@ -27892,7 +28102,7 @@ paths:
$ref: '#/components/schemas/GenericError'
description: ''
post:
operationId: tenants_create
operationId: tenants_tenants_create
description: Tenant Viewset
tags:
- tenants
@ -27902,8 +28112,6 @@ paths:
schema:
$ref: '#/components/schemas/TenantRequest'
required: true
security:
- authentik: []
responses:
'201':
content:
@ -27923,9 +28131,9 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/tenants/{tenant_uuid}/:
/tenants/tenants/{tenant_uuid}/:
get:
operationId: tenants_retrieve
operationId: tenants_tenants_retrieve
description: Tenant Viewset
parameters:
- in: path
@ -27937,8 +28145,6 @@ paths:
required: true
tags:
- tenants
security:
- authentik: []
responses:
'200':
content:
@ -27959,7 +28165,7 @@ paths:
$ref: '#/components/schemas/GenericError'
description: ''
put:
operationId: tenants_update
operationId: tenants_tenants_update
description: Tenant Viewset
parameters:
- in: path
@ -27977,8 +28183,6 @@ paths:
schema:
$ref: '#/components/schemas/TenantRequest'
required: true
security:
- authentik: []
responses:
'200':
content:
@ -27999,7 +28203,7 @@ paths:
$ref: '#/components/schemas/GenericError'
description: ''
patch:
operationId: tenants_partial_update
operationId: tenants_tenants_partial_update
description: Tenant Viewset
parameters:
- in: path
@ -28016,8 +28220,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/PatchedTenantRequest'
security:
- authentik: []
responses:
'200':
content:
@ -28038,7 +28240,7 @@ paths:
$ref: '#/components/schemas/GenericError'
description: ''
delete:
operationId: tenants_destroy
operationId: tenants_tenants_destroy
description: Tenant Viewset
parameters:
- in: path
@ -28050,8 +28252,6 @@ paths:
required: true
tags:
- tenants
security:
- authentik: []
responses:
'204':
description: No response body
@ -34935,6 +35135,18 @@ components:
required:
- pagination
- results
PaginatedDomainList:
type: object
properties:
pagination:
$ref: '#/components/schemas/Pagination'
results:
type: array
items:
$ref: '#/components/schemas/Domain'
required:
- pagination
- results
PaginatedDummyPolicyList:
type: object
properties:
@ -36619,6 +36831,19 @@ components:
nullable: true
description: Certificate/Key used for authentication. Can be left empty
for no authentication.
PatchedDomainRequest:
type: object
description: Domain Serializer
properties:
domain:
type: string
minLength: 1
maxLength: 253
is_primary:
type: boolean
tenant:
type: string
format: uuid
PatchedDummyPolicyRequest:
type: object
description: Dummy Policy Serializer