This brings a health check with authentification Reviewed-on: #51 Co-authored-by: Juergen Edelbluth <jed@noreply.git.codebau.dev> Co-committed-by: Juergen Edelbluth <jed@noreply.git.codebau.dev>
This commit is contained in:
parent
769241c170
commit
77898d59bc
|
@ -3,5 +3,5 @@
|
|||
<component name="Black">
|
||||
<option name="sdkName" value="Poetry (platform)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (platform)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (platform) (2)" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -14,7 +14,7 @@
|
|||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Poetry (platform)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Poetry (platform) (2)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
*** Settings ***
|
||||
Documentation Check the registration and login procedures
|
||||
Resource ../Keywords/django.resource
|
||||
Library Browser
|
||||
Library String
|
||||
|
||||
Suite Setup Solawi-Suite Inner Setup
|
||||
Suite Teardown Solawi-Suite Inner Teardown
|
||||
|
||||
*** Test Cases ***
|
||||
Invalid Credentials
|
||||
Open Page /
|
||||
${response} = Http /health/
|
||||
Should Be Equal As Integers ${response.status} 403
|
||||
|
||||
Valid Credentials
|
||||
${token_result} = Run Manage.Py Command create_health_api_access_token
|
||||
${token_data} = Decode Bytes To String ${token_result.stdout} utf-8
|
||||
@{splits} = Split String ${token_data} :
|
||||
Length Should Be ${splits} 4
|
||||
${header} = Strip String ${splits[1]}
|
||||
${token_id} = Strip String ${splits[2]}
|
||||
${token_code} = Strip String ${splits[3]}
|
||||
${auth_token} = Set Variable ${token_id}:${token_code}
|
||||
Open Page /
|
||||
${response} = Http /health/ headers={"${header}": "${auth_token}"}
|
||||
Should Be Equal As Integers ${response.status} 200
|
|
@ -0,0 +1,4 @@
|
|||
GET {{host}}/health/
|
||||
Accept: application/json
|
||||
X-Solawi-Suite-Access-Token: 7zzbekqqt7z3k6d2meyz0gnju1impapy:t78Wjywk9hqTXJYo928MYmRh_DWFdQIjVKEh$d6MCwa$dD29J.Tn3K-SVGpYWrBdZ3VKcXfv0u30QL-.oQJFL2EHWwULR-h6cBbrBaIoW.iNG4yUhn0koEmfNkmlFCFD
|
||||
###
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"dev": {
|
||||
"host": "http://localhost:8000"
|
||||
},
|
||||
"prod": {
|
||||
"host": "https://solawi.me"
|
||||
}
|
||||
}
|
|
@ -999,6 +999,24 @@ pubcontrol = ">=3.0,<4"
|
|||
six = ">=1.10,<2"
|
||||
Werkzeug = ">=1.0,<4"
|
||||
|
||||
[[package]]
|
||||
name = "django-health-check"
|
||||
version = "3.18.1"
|
||||
description = "Run checks on services like databases, queue servers, celery processes, etc."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "django-health-check-3.18.1.tar.gz", hash = "sha256:44552d55ae8950c9548d3b90f9d9fd5570b57446a19b2a8e674c82f993cb7a2c"},
|
||||
{file = "django_health_check-3.18.1-py2.py3-none-any.whl", hash = "sha256:2c89a326cd79830e2fc6808823a9e7e874ab23f7aef3ff2c4d1194c998e1dca1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
django = ">=2.2"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx"]
|
||||
test = ["celery", "pytest", "pytest-cov", "pytest-django", "redis"]
|
||||
|
||||
[[package]]
|
||||
name = "django-ipware"
|
||||
version = "6.0.5"
|
||||
|
@ -1770,13 +1788,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "locust"
|
||||
version = "2.24.1"
|
||||
version = "2.25.0"
|
||||
description = "Developer friendly load testing framework"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "locust-2.24.1-py3-none-any.whl", hash = "sha256:7f6ed4dc289aad66c304582e6d25e4de5d7c3b175b580332442ab2be35b9d916"},
|
||||
{file = "locust-2.24.1.tar.gz", hash = "sha256:094161d44d94839bf1120fd7898b7abb9c143833743ba7c096beb470a236b9a7"},
|
||||
{file = "locust-2.25.0-py3-none-any.whl", hash = "sha256:35ee14d0a2b91d0d644150d0b628ce4569b0e1fec1c33c55040fa26cc693d085"},
|
||||
{file = "locust-2.25.0.tar.gz", hash = "sha256:45bc88b3097f0346a46514f99ebf8d8a86f07325366da0b9dc2c3f207499dbc6"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -3089,7 +3107,6 @@ files = [
|
|||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
|
@ -3587,13 +3604,13 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"]
|
|||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "69.5.0"
|
||||
version = "69.5.1"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "setuptools-69.5.0-py3-none-any.whl", hash = "sha256:3b2dbd8f63dcc6b7c327d0243c2d7dc8c96cc507c016f09221f3787e6e528719"},
|
||||
{file = "setuptools-69.5.0.tar.gz", hash = "sha256:8d881f842bfc0e29e93bc98a2e650e8845609adff4d2989ba6c748e67b09d5be"},
|
||||
{file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"},
|
||||
{file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
|
@ -4193,4 +4210,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "6878a3edf9d5eada0e4a5f875ebe0c497bfcd4aa0fc89d40d848488e2487c9a7"
|
||||
content-hash = "7b498b2c2cb0053b8f4710c6b187476c68ec44fe6ed0ed42e213dd471b57905a"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[tool.poetry]
|
||||
name = "platform"
|
||||
version = "0.5.2-dev"
|
||||
version = "0.5.3-dev"
|
||||
description = "Plattform für die Apps der Solawi."
|
||||
authors = ["Juergen Edelbluth <solawi@jued.de>"]
|
||||
license = "Apache License 2.0"
|
||||
|
@ -39,6 +39,7 @@ markdown = "^3.6"
|
|||
django-csp = "^3.8"
|
||||
django-cors-headers = "^4.3.1"
|
||||
webauthn = "^2.1.0"
|
||||
django-health-check = "^3.18.1"
|
||||
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Ahg',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('name', models.CharField(max_length=255, verbose_name='Name')),
|
||||
|
@ -33,7 +33,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='HarvestYear',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('year', models.CharField(max_length=255, verbose_name='Jahr')),
|
||||
|
@ -50,7 +50,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Date',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
@ -69,7 +69,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Member',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
@ -90,7 +90,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Team',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
@ -108,7 +108,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='PlanMemberLink',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('date_fk', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ahg.date', verbose_name='Datum')),
|
||||
|
@ -124,7 +124,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='PlanTeamLink',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('date_fk', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ahg.date', verbose_name='Datum')),
|
||||
|
@ -140,7 +140,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='TeamMember',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('note', models.TextField(blank=True, default=None, max_length=100000, null=True, verbose_name='Notiz')),
|
||||
('member_fk', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ahg.member', verbose_name='Mitglied')),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, OwnerMixin
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, OwnerMixin
|
||||
|
||||
|
||||
class Ahg(NanoIdPkMixin, OwnerMixin, CreatedMixin, LastModifiedMixin, models.Model):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.urls import path, register_converter
|
||||
|
||||
from solawi_apps.ahg.views.ahgs import AhgListView, AhgCreateView, AhgEditView, AhgDetailView, AhgDeleteView
|
||||
from solawi_apps.db.dbid import NanoIdConverter
|
||||
from solawi_apps.db_lib.dbid import NanoIdConverter
|
||||
|
||||
|
||||
register_converter(NanoIdConverter, "nanoid")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import datetime
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='MemberAnnouncement',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
@ -34,7 +34,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='PublicAnnouncement',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.contrib import messages
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db.models import NanoIdPkMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, CreatedMixin, \
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, CreatedMixin, \
|
||||
LastModifiedMixin
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import datetime
|
||||
import django.db.models.deletion
|
||||
import solawi_apps.app_permission.integration
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='AccessPermission',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import datetime
|
||||
import solawi_apps.app_permission.integration
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='DefaultPermission',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -3,7 +3,7 @@ from django.db import models
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.app_permission.integration import get_all_installed_app_labels
|
||||
from solawi_apps.db.models import NanoIdPkMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, CreatedMixin, \
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, CreatedMixin, \
|
||||
LastModifiedMixin
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import datetime
|
||||
import django.db.models.deletion
|
||||
import solawi_apps.bidding.pin
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Event',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
@ -39,7 +39,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='FiscalPlan',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('required_amount', models.DecimalField(decimal_places=2, max_digits=16, verbose_name='Benötigter Betrag')),
|
||||
('currency', models.CharField(default='EUR', max_length=5, verbose_name='Währung')),
|
||||
|
@ -67,7 +67,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Round',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('name', models.CharField(max_length=200, verbose_name='Runden-Name')),
|
||||
|
@ -84,7 +84,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Share',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('divider', models.PositiveIntegerField(default=1, verbose_name='Teiler')),
|
||||
|
@ -104,7 +104,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='PreBid',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('from_round', models.PositiveIntegerField(default=1, verbose_name='Gültig ab Runde')),
|
||||
|
@ -123,7 +123,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Bid',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('value', models.DecimalField(decimal_places=2, max_digits=16, verbose_name='Wert')),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import datetime
|
||||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='TeamMember',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.db import models
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.bidding.pin import make_event_pin, make_share_pin
|
||||
from solawi_apps.db.models import NanoIdPkMixin, CreatedMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, \
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, CreatedMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, \
|
||||
ArchivedMixin, OwnerMixin, LastModifiedMixin
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ from solawi_apps.bidding.views.team import TeamBiddingEventsView, TeamBiddingEve
|
|||
TeamEndRoundView, TeamRoundResultView, TeamRoundResultPdfView, TeamRoundResultsPdfPageView, TeamPreBidView, \
|
||||
TeamAddBidView, TeamEditPreBidView, TeamDeletePreBidView, TeamAddPreBidView
|
||||
from solawi_apps.bidding.views.user import AccessByPinView, AccessByLinkView, EventView, LeaveEventView
|
||||
from solawi_apps.db.dbid import NanoIdConverter
|
||||
from solawi_apps.db_lib.dbid import NanoIdConverter
|
||||
|
||||
|
||||
register_converter(NanoIdConverter, "nanoid")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Version',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
('version_identifier', models.CharField(max_length=255, unique=True, verbose_name='Versionsbezeichnung')),
|
||||
|
@ -30,7 +30,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Item',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
('enhancement_type', models.CharField(choices=[('bugfix', 'Fehlerbehebung'), ('feature', 'Neue Funktionalität'), ('enhancement', 'Verbesserung')], max_length=128, verbose_name='Typ')),
|
||||
|
@ -49,7 +49,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Ticket',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
('ticket', models.CharField(max_length=128, verbose_name='Ticket')),
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"versions":[{"version_identifier":"0.5.3-dev","release_date":"2024-04-14T00:00:00+02:00","note":"Zur besseren Überwachung der Anwendung braucht es Schnittstellen für das Monitoring, die über ein \"Ping\" hinausgehen.","version_name":"Monitoring","items":[{"is_breaking_change":false,"requires_db_update":false,"title":"Health Check API","note":"Eine API ermöglicht das Monitoring in einem externen System. Für den Zugang ist ein Token erforderlich. Dieses kann mit\ndem Management-Kommando `create_health_api_access_token` erzeugt werden.","item_type":"feature","tickets":[{"ticket_id":"50","ticket_url":"https://git.codebau.dev/solawi-suite/platform/issues/50"}]}]}]}
|
|
@ -0,0 +1,54 @@
|
|||
from os.path import dirname, join
|
||||
from json import loads
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from solawi_apps.changelog.object_model import ChangelogDataMigration
|
||||
|
||||
|
||||
DATA_FILE = join(dirname(__file__), '0020_changelog_append.json')
|
||||
|
||||
|
||||
def append_changelog(apps, schema_editor):
|
||||
Version = apps.get_model("changelog", "Version")
|
||||
Item = apps.get_model("changelog", "Item")
|
||||
Ticket = apps.get_model("changelog", "Ticket")
|
||||
with open(DATA_FILE, "rt", encoding="utf-8") as fd:
|
||||
json_data = fd.read()
|
||||
todo = ChangelogDataMigration(**loads(json_data))
|
||||
for v in todo.versions:
|
||||
version = Version.objects.create(
|
||||
version_identifier=v.version_identifier,
|
||||
release_datetime=v.release_date,
|
||||
note_md=v.note,
|
||||
version_name=v.version_name,
|
||||
enabled=True,
|
||||
)
|
||||
for i in v.items:
|
||||
item = Item.objects.create(
|
||||
version_fk=version,
|
||||
enhancement_type=i.item_type,
|
||||
requires_db_update=i.requires_db_update,
|
||||
is_breaking_change=i.is_breaking_change,
|
||||
title=i.title,
|
||||
note_md=i.note,
|
||||
enabled=True,
|
||||
)
|
||||
for t in i.tickets:
|
||||
Ticket.objects.create(
|
||||
item_fk=item,
|
||||
ticket=t.ticket_id,
|
||||
ticket_url=t.ticket_url,
|
||||
enabled=True,
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('changelog', '0019_changelog_append'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(append_changelog),
|
||||
]
|
|
@ -2,7 +2,7 @@ from django.db import models
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.changelog.enhancement import ENHANCEMENT_TYPE
|
||||
from solawi_apps.db.models import NanoIdPkMixin, CreatedMixin, EnabledMixin
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, CreatedMixin, EnabledMixin
|
||||
|
||||
|
||||
class Version(NanoIdPkMixin, CreatedMixin, EnabledMixin, models.Model):
|
||||
|
|
|
@ -4,5 +4,5 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
class DbConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'solawi_apps.db'
|
||||
name = 'solawi_apps.db_lib'
|
||||
verbose_name = _('[solawi-suite] Datenbank-Tools')
|
|
@ -7,8 +7,8 @@ from django.db.models import ForeignKey
|
|||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db.dbid import generate_id, ID_LENGTH, validate_nanoid
|
||||
from solawi_apps.db.dt import MIN_DATE, MAX_DATE
|
||||
from solawi_apps.db_lib.dbid import generate_id, ID_LENGTH, validate_nanoid
|
||||
from solawi_apps.db_lib.dt import MIN_DATE, MAX_DATE
|
||||
from solawi_apps.encrypted_settings.crypt import encrypt_item, decrypt_item
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class HealthConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'solawi_apps.health'
|
||||
verbose_name = _('[solawi-suite] Health Check')
|
|
@ -0,0 +1,25 @@
|
|||
from django.contrib.auth.hashers import make_password
|
||||
from django.core.management import BaseCommand
|
||||
|
||||
from solawi_apps.health.models import AccessToken
|
||||
from solawi_apps.health.verification import get_verification_code
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
help = 'Creates health API access token'
|
||||
|
||||
@staticmethod
|
||||
def get_new_token() -> str:
|
||||
new_token = get_verification_code()
|
||||
hashed = make_password(new_token)
|
||||
token_object = AccessToken.objects.create(
|
||||
verification_code=hashed,
|
||||
enabled=True,
|
||||
)
|
||||
return f"X-Solawi-Suite-Access-Token: {token_object.id}:{new_token}"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS('Erfolg: ') + Command.get_new_token()
|
||||
)
|
|
@ -0,0 +1,60 @@
|
|||
from typing import Optional
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.hashers import verify_password
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse
|
||||
from django.utils.timezone import now
|
||||
|
||||
from solawi_apps.db_lib.dbid import NANO_ID_RE
|
||||
from solawi_apps.health.models import AccessToken
|
||||
|
||||
|
||||
class HealthCheckApiAuthMiddleware:
|
||||
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
self.__disable_access_allow_origin_request_key = "__request__disable_access_allow_origin"
|
||||
self.access_token_header = settings.HEALTH_CHECK_ACCESS_TOKEN_HEADER
|
||||
self.access_denied_response = JsonResponse({
|
||||
"status": "access denied",
|
||||
}, status=403)
|
||||
|
||||
def __call__(self, request: HttpRequest) -> HttpResponse:
|
||||
response = self.get_response(request)
|
||||
if getattr(request, self.__disable_access_allow_origin_request_key, False):
|
||||
response["Access-Control-Allow-Origin"] = "*"
|
||||
return response
|
||||
|
||||
@staticmethod
|
||||
def verify_token(token: str) -> bool:
|
||||
t_split = token.split(":", 1)
|
||||
if len(t_split) != 2:
|
||||
return False
|
||||
token_id, token_passwd = t_split
|
||||
if NANO_ID_RE.match(token_id) is None:
|
||||
return False
|
||||
t_now = now()
|
||||
try:
|
||||
token_obj = AccessToken.objects.filter(
|
||||
enabled=True,
|
||||
active_from__lte=t_now,
|
||||
active_to__gte=t_now,
|
||||
).get(id=token_id)
|
||||
except (AccessToken.DoesNotExist, AccessToken.MultipleObjectsReturned):
|
||||
return False
|
||||
verified, _ = verify_password(token_passwd, token_obj.verification_code)
|
||||
return verified
|
||||
|
||||
def handle_health_api_auth(self, request: HttpRequest) -> Optional[HttpResponse]:
|
||||
if (token := request.headers.get(self.access_token_header, None)) is None:
|
||||
return self.access_denied_response
|
||||
if not HealthCheckApiAuthMiddleware.verify_token(token):
|
||||
return self.access_denied_response
|
||||
return None
|
||||
|
||||
def process_view(self, request: HttpRequest, *args, **kwargs) -> Optional[HttpResponse]:
|
||||
if (request.resolver_match is not None
|
||||
and request.resolver_match.namespaces is not None and 'health' in request.resolver_match.namespaces):
|
||||
setattr(request, self.__disable_access_allow_origin_request_key, True)
|
||||
return self.handle_health_api_auth(request)
|
||||
return None
|
|
@ -0,0 +1,30 @@
|
|||
import datetime
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AccessToken',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
('active_from', models.DateTimeField(default=datetime.datetime(2000, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name='Aktiv ab')),
|
||||
('active_to', models.DateTimeField(default=datetime.datetime(2999, 12, 31, 23, 59, 59, 999999, tzinfo=datetime.timezone.utc), verbose_name='Aktiv bis')),
|
||||
('verification_code', models.CharField(editable=False, max_length=255, verbose_name='Verifizierungscode')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Zugangstoken',
|
||||
'verbose_name_plural': 'Zugangstokens',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,21 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db_lib.models import (NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, ActiveFromMixin,
|
||||
ActiveToMixin)
|
||||
|
||||
|
||||
class AccessToken(
|
||||
NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, ActiveFromMixin, ActiveToMixin, models.Model
|
||||
):
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Zugangstoken')
|
||||
verbose_name_plural = _('Zugangstokens')
|
||||
|
||||
verification_code = models.CharField(
|
||||
verbose_name=_("Verifizierungscode"), editable=False, null=False, blank=False, max_length=255
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return _("Verifizierungscode %s") % self.id
|
|
@ -0,0 +1,73 @@
|
|||
from json import loads
|
||||
|
||||
from django.db import connection
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from solawi_apps.health.management.commands.create_health_api_access_token import Command
|
||||
|
||||
|
||||
class HealthCheckApiTestCase(TestCase):
|
||||
|
||||
failed_response = {
|
||||
"status": "access denied",
|
||||
}
|
||||
|
||||
good_response = {
|
||||
"Cache backend: default": "working",
|
||||
"DatabaseBackend": "working",
|
||||
"DefaultFileStorageHealthCheck": "working",
|
||||
"MigrationsHealthCheck": "working"
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
token = Command.get_new_token()
|
||||
cls.header_name, cls.header_value = [t.strip() for t in token.split(':', 1)]
|
||||
cls.endpoint = reverse("health:health_check:health_check_home")
|
||||
|
||||
def test_without_header(self):
|
||||
response = self.client.get(self.endpoint)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertDictEqual(self.failed_response, loads(response.content))
|
||||
|
||||
def test_with_bad_headers(self):
|
||||
values = (
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
'0' * 128,
|
||||
':1:2:3:4:5:6:7:8:9:10',
|
||||
'',
|
||||
)
|
||||
for value in values:
|
||||
with self.subTest(value=value):
|
||||
response = self.client.get(self.endpoint, headers={
|
||||
self.header_name: value,
|
||||
})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertDictEqual(self.failed_response, loads(response.content))
|
||||
|
||||
def test_good_header(self):
|
||||
if '?mode=memory' in str(connection.settings_dict.get('NAME')):
|
||||
self.skipTest("in-memory db not supported")
|
||||
response = self.client.get(self.endpoint, headers={
|
||||
self.header_name: self.header_value,
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertDictEqual(self.good_response, loads(response.content))
|
||||
|
||||
def test_bad_mutations(self):
|
||||
values = (
|
||||
self.header_value[1:],
|
||||
self.header_value[:-1],
|
||||
self.header_value + "-a",
|
||||
"a-" + self.header_value,
|
||||
self.header_value.replace(":", "-"),
|
||||
)
|
||||
for value in values:
|
||||
with self.subTest(value=value):
|
||||
response = self.client.get(self.endpoint, headers={
|
||||
self.header_name: value,
|
||||
})
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertDictEqual(self.failed_response, loads(response.content))
|
|
@ -0,0 +1,7 @@
|
|||
from django.urls import path, include
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path(r'', include('health_check.urls')),
|
||||
]
|
||||
app_name = 'solawi_apps.health'
|
|
@ -0,0 +1,7 @@
|
|||
import string
|
||||
|
||||
from nanoid import generate
|
||||
|
||||
|
||||
def get_verification_code(length: int = 128, chars: str = string.ascii_letters + string.digits + ".-$_!/") -> str:
|
||||
return generate(size=length, alphabet=chars)
|
|
@ -1,6 +1,6 @@
|
|||
import datetime
|
||||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -17,7 +17,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Passkey',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.conf import settings
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, ActiveToMixin, \
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, ActiveToMixin, \
|
||||
ActiveFromMixin
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.urls import path, register_converter
|
||||
|
||||
from solawi_apps.db.dbid import NanoIdConverter
|
||||
from solawi_apps.db_lib.dbid import NanoIdConverter
|
||||
from solawi_apps.passkeys.views.auth import PasskeyLoginView, PasskeyAuthOptionsView, PasskeyAuthView
|
||||
from solawi_apps.passkeys.views.user import ListPasskeysView, AddPasskeyView, DeletePasskeyView, ManagePasskeyView, \
|
||||
InitCreatePasskeyView, VerifyCreatePasskeyView
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
from django.contrib import admin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.health.models import AccessToken
|
||||
|
||||
|
||||
class AccessTokenAdmin(admin.ModelAdmin):
|
||||
|
||||
ordering = ("id", "created")
|
||||
|
||||
list_display = ("id", "get_currently_active", "enabled", "active_from", "active_to")
|
||||
readonly_fields = ("id", "verification_code", "created", "last_modified", "get_currently_active")
|
||||
|
||||
fieldsets = (
|
||||
(_("Zugangstoken"), {
|
||||
"fields": ("id", "verification_code"),
|
||||
}),
|
||||
(_("Gültigkeit"), {
|
||||
"fields": ("enabled", "active_from", "active_to"),
|
||||
}),
|
||||
(_("Status"), {
|
||||
"fields": ("get_currently_active",),
|
||||
}),
|
||||
(_("Meta"), {
|
||||
"fields": ("created", "last_modified"),
|
||||
}),
|
||||
)
|
||||
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
|
||||
@admin.display(description=_("Ist aktuell aktiv"), boolean=True)
|
||||
def get_currently_active(self, obj: AccessToken) -> bool:
|
||||
return obj.is_active()
|
|
@ -9,6 +9,7 @@ class PasskeyAdmin(admin.ModelAdmin):
|
|||
ordering = ("owner_fk__email", "name", "created")
|
||||
|
||||
list_display = ("name", "get_owner", "get_currently_active", "created")
|
||||
list_filter = ("owner_fk__email",)
|
||||
|
||||
search_fields = ("owner_fk__email", "name")
|
||||
|
||||
|
|
|
@ -8,9 +8,11 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from solawi_apps.announce.models import PublicAnnouncement, MemberAnnouncement
|
||||
from solawi_apps.app_permission.models import AccessPermission, DefaultPermission
|
||||
from solawi_apps.health.models import AccessToken
|
||||
from solawi_apps.passkeys.models import Passkey
|
||||
from solawi_apps.s_admin.admin.announce import AnnouncementAdmin
|
||||
from solawi_apps.s_admin.admin.app_permission import AccessPermissionAdmin, DefaultPermissionAdmin
|
||||
from solawi_apps.s_admin.admin.health import AccessTokenAdmin
|
||||
from solawi_apps.s_admin.admin.passkeys import PasskeyAdmin
|
||||
from solawi_apps.s_admin.admin.register import AllowedEmailDomainAdmin, RegistrationAdmin, DomainBasedAppAccessAdmin
|
||||
from solawi_apps.s_admin.admin.session import SessionAdmin
|
||||
|
@ -56,3 +58,5 @@ admin_site.register(PublicAnnouncement, AnnouncementAdmin)
|
|||
admin_site.register(MemberAnnouncement, AnnouncementAdmin)
|
||||
|
||||
admin_site.register(Passkey, PasskeyAdmin)
|
||||
|
||||
admin_site.register(AccessToken, AccessTokenAdmin)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -13,7 +13,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='TxtFile',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin
|
||||
|
||||
|
||||
class TxtFile(NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EnabledMixin, models.Model):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import datetime
|
||||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db.models
|
||||
import solawi_apps.db_lib.dbid
|
||||
import solawi_apps.db_lib.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='AllowedEmailDomain',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
@ -34,7 +34,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='OtpAttempt',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('success', models.BooleanField(default=False, editable=False, verbose_name='Erfolgreicher Versuch')),
|
||||
('user_fk', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
|
@ -48,15 +48,15 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='Registration',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
('active_from', models.DateTimeField(default=datetime.datetime(2000, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name='Aktiv ab')),
|
||||
('active_to', models.DateTimeField(default=datetime.datetime(2999, 12, 31, 23, 59, 59, 999999, tzinfo=datetime.timezone.utc), verbose_name='Aktiv bis')),
|
||||
('as_superuser', models.BooleanField(default=False, editable=False, verbose_name='Registrierung als Superuser')),
|
||||
('registration_id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, unique=True, verbose_name='Registrierungs-ID')),
|
||||
('registration_check', solawi_apps.db.models.EncryptedTextField(default=solawi_apps.db.dbid.generate_id, editable=False, verbose_name='Registrierungs-Check')),
|
||||
('registration_id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, unique=True, verbose_name='Registrierungs-ID')),
|
||||
('registration_check', solawi_apps.db_lib.models.EncryptedTextField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, verbose_name='Registrierungs-Check')),
|
||||
('registration_finished', models.BooleanField(default=False, verbose_name='Registrierung abgeschlossen')),
|
||||
('user_fk', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
|
@ -69,10 +69,10 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='TotpSetup',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('totp_provisioning', solawi_apps.db.models.EncryptedTextField(editable=False, max_length=1024, verbose_name='TOTP Provisionierung')),
|
||||
('totp_provisioning', solawi_apps.db_lib.models.EncryptedTextField(editable=False, max_length=1024, verbose_name='TOTP Provisionierung')),
|
||||
('user_fk', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
options={
|
||||
|
@ -84,7 +84,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='BurnedOtp',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('otp', models.CharField(editable=False, max_length=6, verbose_name='Einmalpasswort')),
|
||||
('totp_setup_fk', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='user.totpsetup', verbose_name='TOTP Setup')),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='LoginAttempt',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('success', models.BooleanField(default=False, editable=False, verbose_name='Erfolgreicher Versuch')),
|
||||
('user_fk', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='AuthenticationAttempt',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('ip', models.GenericIPAddressField(verbose_name='IP Adresse')),
|
||||
],
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='UserSession',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('session_fk', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, to='sessions.session', verbose_name='Sitzung')),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='ForgotPassword',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('ip', models.GenericIPAddressField(verbose_name='IP Adresse')),
|
||||
('user_fk', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import django.db.models.deletion
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='EmergencyCode',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('code_hash', models.CharField(editable=False, max_length=255, verbose_name='Code Hash')),
|
||||
('owner_fk', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Besitzer')),
|
||||
|
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='EmergencyCodeAttempt',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('success', models.BooleanField(default=False, editable=False, verbose_name='Erfolgreicher Versuch')),
|
||||
('ip', models.GenericIPAddressField(default=None, null=True, verbose_name='IP Adresse')),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import datetime
|
||||
import django.db.models.deletion
|
||||
import solawi_apps.app_permission.integration
|
||||
import solawi_apps.db.dbid
|
||||
import solawi_apps.db_lib.dbid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
|
|||
migrations.CreateModel(
|
||||
name='DomainBasedAppAccess',
|
||||
fields=[
|
||||
('id', models.CharField(default=solawi_apps.db.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('id', models.CharField(default=solawi_apps.db_lib.dbid.generate_id, editable=False, max_length=32, primary_key=True, serialize=False, validators=[solawi_apps.db_lib.dbid.validate_nanoid], verbose_name='ID')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='Erstellt')),
|
||||
('last_modified', models.DateTimeField(auto_now=True, verbose_name='Zuletzt geändert')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='Aktiviert')),
|
||||
|
|
|
@ -4,8 +4,8 @@ from django.db.models import OneToOneField
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.app_permission.integration import get_all_installed_app_labels
|
||||
from solawi_apps.db.dbid import generate_id, ID_LENGTH
|
||||
from solawi_apps.db.models import CreatedMixin, LastModifiedMixin, ActiveFromMixin, ActiveToMixin, EnabledMixin, \
|
||||
from solawi_apps.db_lib.dbid import generate_id, ID_LENGTH
|
||||
from solawi_apps.db_lib.models import CreatedMixin, LastModifiedMixin, ActiveFromMixin, ActiveToMixin, EnabledMixin, \
|
||||
EncryptedTextField, NanoIdPkMixin
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.db import models
|
|||
from django.db.models import OneToOneField, ForeignKey, CharField, BooleanField, GenericIPAddressField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from solawi_apps.db.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EncryptedTextField
|
||||
from solawi_apps.db_lib.models import NanoIdPkMixin, CreatedMixin, LastModifiedMixin, EncryptedTextField
|
||||
|
||||
|
||||
class TotpSetup(NanoIdPkMixin, CreatedMixin, LastModifiedMixin, models.Model):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.urls import path, register_converter
|
||||
|
||||
from solawi_apps.db.dbid import NanoIdConverter
|
||||
from solawi_apps.db_lib.dbid import NanoIdConverter
|
||||
from solawi_apps.user.views.auth import LoginView, LogoutView, OtpView, LogoutAllSessionsView, EmergencyCodeView
|
||||
from solawi_apps.user.views.manage import AccountManageView, ChangePasswordView, ChangeOtpView, ChangeOtpQrCodeView, \
|
||||
ForgotPasswordView, ResetPasswordView, EmergencyCodeRegenView
|
||||
|
|
|
@ -76,7 +76,7 @@ INSTALLED_APPS = [
|
|||
'solawi_apps.ui',
|
||||
'solawi_apps.encrypted_settings',
|
||||
'solawi_apps.url',
|
||||
'solawi_apps.db',
|
||||
'solawi_apps.db_lib',
|
||||
'solawi_apps.user',
|
||||
'solawi_apps.handbook',
|
||||
'solawi_apps.bidding',
|
||||
|
@ -99,11 +99,18 @@ INSTALLED_APPS = [
|
|||
'solawi_apps.txt',
|
||||
'solawi_apps.passkeys',
|
||||
'solawi_apps.announce',
|
||||
'solawi_apps.health',
|
||||
'health_check', # required
|
||||
'health_check.db', # stock Django health checkers
|
||||
'health_check.cache',
|
||||
'health_check.storage',
|
||||
'health_check.contrib.migrations',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'solawi_apps.ui.middleware.request_id.RequestIdMiddleware',
|
||||
'solawi_apps.health.middleware.HealthCheckApiAuthMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'csp.middleware.CSPMiddleware',
|
||||
'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||
|
@ -345,6 +352,7 @@ CORS_ALLOW_ALL_ORIGINS = False
|
|||
CORS_ALLOW_HEADERS = (
|
||||
*default_headers,
|
||||
"x-solawi-suite-csrf-token",
|
||||
"x-solawi-suite-access-token",
|
||||
)
|
||||
CORS_ALLOW_CREDENTIALS = False
|
||||
ACCESS_CONTROL_ALLOW_ORIGIN = None
|
||||
|
@ -366,3 +374,9 @@ PASSKEYS_EXPECTED_ORIGINS = [
|
|||
]
|
||||
if TEST_ORIGIN is not None:
|
||||
PASSKEYS_EXPECTED_ORIGINS.append(TEST_ORIGIN)
|
||||
|
||||
HEALTH_CHECK = {
|
||||
'DISK_USAGE_MAX': 80, # percent
|
||||
}
|
||||
|
||||
HEALTH_CHECK_ACCESS_TOKEN_HEADER = "x-solawi-suite-access-token"
|
||||
|
|
|
@ -37,6 +37,7 @@ urlpatterns = [
|
|||
path('ahg/', include("solawi_apps.ahg.urls", namespace="ahg")),
|
||||
path('access/', include("solawi_apps.app_permission.urls", namespace="access")),
|
||||
path('changelog/', include("solawi_apps.changelog.urls", namespace="changelog")),
|
||||
path('health/', include("solawi_apps.health.urls", namespace="health")),
|
||||
path(
|
||||
'favicon.png',
|
||||
RedirectView.as_view(
|
||||
|
|
Loading…
Reference in New Issue