recovery(new): add recovery app to create recovery links
This commit is contained in:
parent
3d8242be06
commit
b9991465ee
|
@ -0,0 +1,11 @@
|
||||||
|
"""passbook Recovery app config"""
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class PassbookRecoveryConfig(AppConfig):
|
||||||
|
"""passbook Recovery app config"""
|
||||||
|
|
||||||
|
name = 'passbook.recovery'
|
||||||
|
label = 'passbook_recovery'
|
||||||
|
verbose_name = 'passbook Recovery'
|
||||||
|
mountpoint = 'recovery/'
|
|
@ -0,0 +1,46 @@
|
||||||
|
"""passbook 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 passbook.core.models import Nonce, User
|
||||||
|
from passbook.lib.config import CONFIG
|
||||||
|
|
||||||
|
LOGGER = get_logger()
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
"""Create Nonce used to recover access"""
|
||||||
|
|
||||||
|
help = _('Create a Key which can be used to restore access to passbook.')
|
||||||
|
|
||||||
|
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, nonce: Nonce) -> str:
|
||||||
|
"""Get full recovery link"""
|
||||||
|
path = reverse('passbook_recovery:use-nonce', kwargs={'uuid': str(nonce.uuid)})
|
||||||
|
return f"https://{CONFIG.y('domain')}{path}"
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
"""Create Nonce used to recover access"""
|
||||||
|
duration = int(options.get('duration', 1))
|
||||||
|
delta = timedelta(days=duration * 365.2425)
|
||||||
|
_now = now()
|
||||||
|
expiry = _now + delta
|
||||||
|
user = User.objects.get(username=options.get('user'))
|
||||||
|
nonce = Nonce.objects.create(
|
||||||
|
expires=expiry,
|
||||||
|
user=user,
|
||||||
|
description=f'Recovery Nonce generated by {getuser()} on {_now}')
|
||||||
|
self.stdout.write((f"Store this link safely, as it will allow"
|
||||||
|
f" anyone to access passbook as {user}."))
|
||||||
|
self.stdout.write(self.get_url(nonce))
|
|
@ -0,0 +1,9 @@
|
||||||
|
"""recovery views"""
|
||||||
|
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from passbook.recovery.views import UseNonceView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('use-nonce/<uuid:uuid>/', UseNonceView.as_view(), name='use-nonce'),
|
||||||
|
]
|
|
@ -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 get_object_or_404, redirect
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
from django.views import View
|
||||||
|
|
||||||
|
from passbook.core.models import Nonce
|
||||||
|
|
||||||
|
|
||||||
|
class UseNonceView(View):
|
||||||
|
"""Use nonce to login"""
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, uuid: str) -> HttpResponse:
|
||||||
|
"""Check if nonce exists, log user in and delete nonce."""
|
||||||
|
nonce: Nonce = get_object_or_404(Nonce, pk=uuid)
|
||||||
|
if nonce.is_expired:
|
||||||
|
nonce.delete()
|
||||||
|
raise Http404
|
||||||
|
login(request, nonce.user, backend='django.contrib.auth.backends.ModelBackend')
|
||||||
|
nonce.delete()
|
||||||
|
messages.warning(request, _("Used recovery-link to authenticate."))
|
||||||
|
return redirect('passbook_core:overview')
|
|
@ -72,6 +72,7 @@ INSTALLED_APPS = [
|
||||||
'passbook.api.apps.PassbookAPIConfig',
|
'passbook.api.apps.PassbookAPIConfig',
|
||||||
'passbook.lib.apps.PassbookLibConfig',
|
'passbook.lib.apps.PassbookLibConfig',
|
||||||
'passbook.audit.apps.PassbookAuditConfig',
|
'passbook.audit.apps.PassbookAuditConfig',
|
||||||
|
'passbook.recovery.apps.PassbookRecoveryConfig',
|
||||||
|
|
||||||
'passbook.sources.ldap.apps.PassbookSourceLDAPConfig',
|
'passbook.sources.ldap.apps.PassbookSourceLDAPConfig',
|
||||||
'passbook.sources.oauth.apps.PassbookSourceOAuthConfig',
|
'passbook.sources.oauth.apps.PassbookSourceOAuthConfig',
|
||||||
|
|
Reference in New Issue