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""" """Test Tenant API"""
from json import loads from json import loads
from django.core.management import call_command
from django.db import connection
from django.urls import reverse from django.urls import reverse
from rest_framework.test import APILiveServerTestCase, APITestCase, APITransactionTestCase
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
from authentik.tenants.tests.utils import TenantAPITestCase
TENANTS_API_KEY = generate_id() TENANTS_API_KEY = generate_id()
HEADERS = {"Authorization": f"Bearer {TENANTS_API_KEY}"} HEADERS = {"Authorization": f"Bearer {TENANTS_API_KEY}"}
class TestAPI(APITransactionTestCase): class TestAPI(TenantAPITestCase):
"""Test api view""" """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("outposts.disable_embedded_outpost", True)
@CONFIG.patch("tenants.enabled", True) @CONFIG.patch("tenants.enabled", True)
@CONFIG.patch("tenants.api_key", TENANTS_API_KEY) @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""" """API URLs"""
from django.urls import path from django.urls import path
from authentik.tenants.api import SettingsView, TenantViewSet from authentik.tenants.api import DomainViewSet, SettingsView, TenantViewSet
api_urlpatterns = [ api_urlpatterns = [
path("admin/settings/", SettingsView.as_view(), name="tenant_settings"), path("admin/settings/", SettingsView.as_view(), name="tenant_settings"),
( (
"tenants", "tenants/tenants",
TenantViewSet, TenantViewSet,
), ),
(
"tenants/domains",
DomainViewSet,
),
] ]

View File

@ -27839,9 +27839,221 @@ paths:
schema: schema:
$ref: '#/components/schemas/GenericError' $ref: '#/components/schemas/GenericError'
description: '' description: ''
/tenants/: /tenants/domains/:
get: 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 description: Tenant Viewset
parameters: parameters:
- name: ordering - name: ordering
@ -27870,8 +28082,6 @@ paths:
type: string type: string
tags: tags:
- tenants - tenants
security:
- authentik: []
responses: responses:
'200': '200':
content: content:
@ -27892,7 +28102,7 @@ paths:
$ref: '#/components/schemas/GenericError' $ref: '#/components/schemas/GenericError'
description: '' description: ''
post: post:
operationId: tenants_create operationId: tenants_tenants_create
description: Tenant Viewset description: Tenant Viewset
tags: tags:
- tenants - tenants
@ -27902,8 +28112,6 @@ paths:
schema: schema:
$ref: '#/components/schemas/TenantRequest' $ref: '#/components/schemas/TenantRequest'
required: true required: true
security:
- authentik: []
responses: responses:
'201': '201':
content: content:
@ -27923,9 +28131,9 @@ paths:
schema: schema:
$ref: '#/components/schemas/GenericError' $ref: '#/components/schemas/GenericError'
description: '' description: ''
/tenants/{tenant_uuid}/: /tenants/tenants/{tenant_uuid}/:
get: get:
operationId: tenants_retrieve operationId: tenants_tenants_retrieve
description: Tenant Viewset description: Tenant Viewset
parameters: parameters:
- in: path - in: path
@ -27937,8 +28145,6 @@ paths:
required: true required: true
tags: tags:
- tenants - tenants
security:
- authentik: []
responses: responses:
'200': '200':
content: content:
@ -27959,7 +28165,7 @@ paths:
$ref: '#/components/schemas/GenericError' $ref: '#/components/schemas/GenericError'
description: '' description: ''
put: put:
operationId: tenants_update operationId: tenants_tenants_update
description: Tenant Viewset description: Tenant Viewset
parameters: parameters:
- in: path - in: path
@ -27977,8 +28183,6 @@ paths:
schema: schema:
$ref: '#/components/schemas/TenantRequest' $ref: '#/components/schemas/TenantRequest'
required: true required: true
security:
- authentik: []
responses: responses:
'200': '200':
content: content:
@ -27999,7 +28203,7 @@ paths:
$ref: '#/components/schemas/GenericError' $ref: '#/components/schemas/GenericError'
description: '' description: ''
patch: patch:
operationId: tenants_partial_update operationId: tenants_tenants_partial_update
description: Tenant Viewset description: Tenant Viewset
parameters: parameters:
- in: path - in: path
@ -28016,8 +28220,6 @@ paths:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/PatchedTenantRequest' $ref: '#/components/schemas/PatchedTenantRequest'
security:
- authentik: []
responses: responses:
'200': '200':
content: content:
@ -28038,7 +28240,7 @@ paths:
$ref: '#/components/schemas/GenericError' $ref: '#/components/schemas/GenericError'
description: '' description: ''
delete: delete:
operationId: tenants_destroy operationId: tenants_tenants_destroy
description: Tenant Viewset description: Tenant Viewset
parameters: parameters:
- in: path - in: path
@ -28050,8 +28252,6 @@ paths:
required: true required: true
tags: tags:
- tenants - tenants
security:
- authentik: []
responses: responses:
'204': '204':
description: No response body description: No response body
@ -34935,6 +35135,18 @@ components:
required: required:
- pagination - pagination
- results - results
PaginatedDomainList:
type: object
properties:
pagination:
$ref: '#/components/schemas/Pagination'
results:
type: array
items:
$ref: '#/components/schemas/Domain'
required:
- pagination
- results
PaginatedDummyPolicyList: PaginatedDummyPolicyList:
type: object type: object
properties: properties:
@ -36619,6 +36831,19 @@ components:
nullable: true nullable: true
description: Certificate/Key used for authentication. Can be left empty description: Certificate/Key used for authentication. Can be left empty
for no authentication. 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: PatchedDummyPolicyRequest:
type: object type: object
description: Dummy Policy Serializer description: Dummy Policy Serializer