wip: rename to authentik (#361)

* root: initial rename

* web: rename custom element prefix

* root: rename external functions with pb_ prefix

* root: fix formatting

* root: replace domain with goauthentik.io

* proxy: update path

* root: rename remaining prefixes

* flows: rename file extension

* root: pbadmin -> akadmin

* docs: fix image filenames

* lifecycle: ignore migration files

* ci: copy default config from current source before loading last tagged

* *: new sentry dsn

* tests: fix missing python3.9-dev package

* root: add additional migrations for service accounts created by outposts

* core: mark system-created service accounts with attribute

* policies/expression: fix pb_ replacement not working

* web: fix last linting errors, add lit-analyse

* policies/expressions: fix lint errors

* web: fix sidebar display on screens where not all items fit

* proxy: attempt to fix proxy pipeline

* proxy: use go env GOPATH to get gopath

* lib: fix user_default naming inconsistency

* docs: add upgrade docs

* docs: update screenshots to use authentik

* admin: fix create button on empty-state of outpost

* web: fix modal submit not refreshing SiteShell and Table

* web: fix height of app-card and height of generic icon

* web: fix rendering of subtext

* admin: fix version check error not being caught

* web: fix worker count not being shown

* docs: update screenshots

* root: new icon

* web: fix lint error

* admin: fix linting error

* root: migrate coverage config to pyproject
This commit is contained in:
Jens L
2020-12-05 22:08:42 +01:00
committed by GitHub
parent 810a7ab50b
commit 1cfe1aff13
989 changed files with 6425 additions and 4412 deletions

View File

View File

@ -0,0 +1,11 @@
"""authentik Recovery app config"""
from django.apps import AppConfig
class AuthentikRecoveryConfig(AppConfig):
"""authentik Recovery app config"""
name = "authentik.recovery"
label = "authentik_recovery"
verbose_name = "authentik Recovery"
mountpoint = "recovery/"

View File

@ -0,0 +1,54 @@
"""authentik recovery createkey command"""
from datetime import timedelta
from getpass import getuser
from django.core.management.base import BaseCommand
from django.urls import reverse
from django.utils.timezone import now
from django.utils.translation import gettext as _
from structlog import get_logger
from authentik.core.models import Token, TokenIntents, User
LOGGER = get_logger()
class Command(BaseCommand):
"""Create Token used to recover access"""
help = _("Create a Key which can be used to restore access to authentik.")
def add_arguments(self, parser):
parser.add_argument(
"duration",
default=1,
action="store",
help="How long the token is valid for (in years).",
)
parser.add_argument(
"user", action="store", help="Which user the Token gives access to."
)
def get_url(self, token: Token) -> str:
"""Get full recovery link"""
return reverse("authentik_recovery:use-token", kwargs={"key": str(token.key)})
def handle(self, *args, **options):
"""Create Token used to recover access"""
duration = int(options.get("duration", 1))
_now = now()
expiry = _now + timedelta(days=duration * 365.2425)
user = User.objects.get(username=options.get("user"))
token = Token.objects.create(
expires=expiry,
user=user,
intent=TokenIntents.INTENT_RECOVERY,
description=f"Recovery Token generated by {getuser()} on {_now}",
)
self.stdout.write(
(
f"Store this link safely, as it will allow"
f" anyone to access authentik as {user}."
)
)
self.stdout.write(self.get_url(token))

View File

@ -0,0 +1,34 @@
"""recovery tests"""
from io import StringIO
from django.core.management import call_command
from django.shortcuts import reverse
from django.test import TestCase
from authentik.core.models import Token, TokenIntents, User
class TestRecovery(TestCase):
"""recovery tests"""
def setUp(self):
self.user = User.objects.create_user(username="recovery-test-user")
def test_create_key(self):
"""Test creation of a new key"""
out = StringIO()
self.assertEqual(len(Token.objects.all()), 0)
call_command("create_recovery_key", "1", self.user.username, stdout=out)
token = Token.objects.get(intent=TokenIntents.INTENT_RECOVERY, user=self.user)
self.assertIn(token.key, out.getvalue())
self.assertEqual(len(Token.objects.all()), 1)
def test_recovery_view(self):
"""Test recovery view"""
out = StringIO()
call_command("create_recovery_key", "1", self.user.username, stdout=out)
token = Token.objects.get(intent=TokenIntents.INTENT_RECOVERY, user=self.user)
self.client.get(
reverse("authentik_recovery:use-token", kwargs={"key": token.key})
)
self.assertEqual(int(self.client.session["_auth_user_id"]), token.user.pk)

View File

@ -0,0 +1,9 @@
"""recovery views"""
from django.urls import path
from authentik.recovery.views import UseTokenView
urlpatterns = [
path("use-token/<str:key>/", UseTokenView.as_view(), name="use-token"),
]

View File

@ -0,0 +1,24 @@
"""recovery views"""
from django.contrib import messages
from django.contrib.auth import login
from django.http import Http404, HttpRequest, HttpResponse
from django.shortcuts import redirect
from django.utils.translation import gettext as _
from django.views import View
from authentik.core.models import Token, TokenIntents
class UseTokenView(View):
"""Use token to login"""
def get(self, request: HttpRequest, key: str) -> HttpResponse:
"""Check if token exists, log user in and delete token."""
tokens = Token.filter_not_expired(key=key, intent=TokenIntents.INTENT_RECOVERY)
if not tokens.exists():
raise Http404
token = tokens.first()
login(request, token.user, backend="django.contrib.auth.backends.ModelBackend")
token.delete()
messages.warning(request, _("Used recovery-link to authenticate."))
return redirect("authentik_core:shell")