Skip to content

Commit

Permalink
admin: store version history (#11520)
Browse files Browse the repository at this point in the history
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
  • Loading branch information
rissson and BeryJu authored Oct 17, 2024
1 parent 0976e05 commit 3262e70
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 1 deletion.
33 changes: 33 additions & 0 deletions authentik/admin/api/version_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from rest_framework.permissions import IsAdminUser
from rest_framework.viewsets import ReadOnlyModelViewSet

from authentik.admin.models import VersionHistory
from authentik.core.api.utils import ModelSerializer


class VersionHistorySerializer(ModelSerializer):
"""VersionHistory Serializer"""

class Meta:
model = VersionHistory
fields = [
"id",
"timestamp",
"version",
"build",
]


class VersionHistoryViewSet(ReadOnlyModelViewSet):
"""VersionHistory Viewset"""

queryset = VersionHistory.objects.all()
serializer_class = VersionHistorySerializer
permission_classes = [IsAdminUser]
filterset_fields = [
"version",
"build",
]
search_fields = ["version", "build"]
ordering = ["-timestamp"]
pagination_class = None
22 changes: 22 additions & 0 deletions authentik/admin/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""authentik admin models"""

from django.db import models
from django.utils.translation import gettext_lazy as _


class VersionHistory(models.Model):
id = models.BigAutoField(primary_key=True)
timestamp = models.DateTimeField()
version = models.TextField()
build = models.TextField()

class Meta:
managed = False
db_table = "authentik_version_history"
ordering = ("-timestamp",)
verbose_name = _("Version history")
verbose_name_plural = _("Version history")
default_permissions = []

def __str__(self):
return f"{self.version}.{self.build} ({self.timestamp})"
2 changes: 2 additions & 0 deletions authentik/admin/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from authentik.admin.api.metrics import AdministrationMetricsViewSet
from authentik.admin.api.system import SystemView
from authentik.admin.api.version import VersionView
from authentik.admin.api.version_history import VersionHistoryViewSet
from authentik.admin.api.workers import WorkerView

api_urlpatterns = [
Expand All @@ -17,6 +18,7 @@
name="admin_metrics",
),
path("admin/version/", VersionView.as_view(), name="admin_version"),
("admin/version/history", VersionHistoryViewSet, "version_history"),
path("admin/workers/", WorkerView.as_view(), name="admin_workers"),
path("admin/system/", SystemView.as_view(), name="admin_system"),
]
4 changes: 3 additions & 1 deletion lifecycle/migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ def run_migrations():
curr = conn.cursor()
try:
wait_for_lock(curr)
for migration_path in Path(__file__).parent.absolute().glob("system_migrations/*.py"):
for migration_path in sorted(
Path(__file__).parent.absolute().glob("system_migrations/*.py")
):
spec = spec_from_file_location("lifecycle.system_migrations", migration_path)
if not spec:
continue
Expand Down
24 changes: 24 additions & 0 deletions lifecycle/system_migrations/version_history_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# flake8: noqa
from lifecycle.migrate import BaseMigration


class Migration(BaseMigration):
def needs_migration(self) -> bool:
self.cur.execute(
"SELECT * FROM information_schema.tables WHERE table_name = 'authentik_version_history';"
)
return not bool(self.cur.rowcount)

def run(self):
self.cur.execute(
"""
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS authentik_version_history (
id BIGSERIAL PRIMARY KEY,
"timestamp" timestamp with time zone NOT NULL,
version text NOT NULL,
build text NOT NULL
);
COMMIT;
"""
)
38 changes: 38 additions & 0 deletions lifecycle/system_migrations/version_history_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# flake8: noqa
from lifecycle.migrate import BaseMigration
from datetime import datetime

from authentik import __version__, get_build_hash


class Migration(BaseMigration):
def needs_migration(self) -> bool:
self.cur.execute(
"""
SELECT * FROM authentik_version_history
WHERE version = %s AND build = %s
ORDER BY "timestamp" DESC
LIMIT 1
""",
(__version__, get_build_hash()),
)
return not bool(self.cur.rowcount)

def run(self):
self.cur.execute(
"""
INSERT INTO authentik_version_history ("timestamp", version, build)
VALUES (%s, %s, %s)
""",
(datetime.now(), __version__, get_build_hash()),
)
self.cur.execute(
"""
DELETE FROM authentik_version_history WHERE id NOT IN (
SELECT id FROM authentik_version_history
ORDER BY "timestamp" DESC
LIMIT 1000
)
"""
)
self.con.commit()
103 changes: 103 additions & 0 deletions schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,90 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/admin/version/history/:
get:
operationId: admin_version_history_list
description: VersionHistory Viewset
parameters:
- in: query
name: build
schema:
type: string
- name: ordering
required: false
in: query
description: Which field to use when ordering the results.
schema:
type: string
- name: search
required: false
in: query
description: A search term.
schema:
type: string
- in: query
name: version
schema:
type: string
tags:
- admin
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/VersionHistory'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/admin/version/history/{id}/:
get:
operationId: admin_version_history_retrieve
description: VersionHistory Viewset
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Version history.
required: true
tags:
- admin
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/VersionHistory'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/admin/workers/:
get:
operationId: admin_workers_retrieve
Expand Down Expand Up @@ -53109,6 +53193,25 @@ components:
- version_current
- version_latest
- version_latest_valid
VersionHistory:
type: object
description: VersionHistory Serializer
properties:
id:
type: integer
readOnly: true
timestamp:
type: string
format: date-time
version:
type: string
build:
type: string
required:
- build
- id
- timestamp
- version
WebAuthnDevice:
type: object
description: Serializer for WebAuthn authenticator devices
Expand Down

0 comments on commit 3262e70

Please sign in to comment.