mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-01-24 22:39:02 -06:00
one-time code
This commit is contained in:
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import secrets
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -196,3 +198,16 @@ MIGRATION_TRANSFORMED_PATH = __get_path(
|
|||||||
"PAPERLESS_MIGRATION_TRANSFORMED_PATH",
|
"PAPERLESS_MIGRATION_TRANSFORMED_PATH",
|
||||||
EXPORT_DIR / "manifest.v3.json",
|
EXPORT_DIR / "manifest.v3.json",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# One-time access code required for migration logins; stable across autoreload
|
||||||
|
_code = os.getenv("PAPERLESS_MIGRATION_ACCESS_CODE")
|
||||||
|
if not _code:
|
||||||
|
_code = secrets.token_urlsafe(12)
|
||||||
|
os.environ["PAPERLESS_MIGRATION_ACCESS_CODE"] = _code
|
||||||
|
MIGRATION_ACCESS_CODE = _code
|
||||||
|
if os.environ.get("PAPERLESS_MIGRATION_CODE_LOGGED") != "1":
|
||||||
|
logging.getLogger(__name__).warning(
|
||||||
|
"Migration one-time access code: %s",
|
||||||
|
MIGRATION_ACCESS_CODE,
|
||||||
|
)
|
||||||
|
os.environ["PAPERLESS_MIGRATION_CODE_LOGGED"] = "1"
|
||||||
|
|||||||
@@ -48,10 +48,14 @@
|
|||||||
<input type="text" name="login" id="inputUsername" placeholder="{{ i18n_username }}" class="form-control" autocorrect="off" autocapitalize="none" required autofocus>
|
<input type="text" name="login" id="inputUsername" placeholder="{{ i18n_username }}" class="form-control" autocorrect="off" autocapitalize="none" required autofocus>
|
||||||
<label for="inputUsername">{{ i18n_username }}</label>
|
<label for="inputUsername">{{ i18n_username }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating form-stacked-bottom">
|
<div class="form-floating form-stacked-middle">
|
||||||
<input type="password" name="password" id="inputPassword" placeholder="{{ i18n_password }}" class="form-control" required>
|
<input type="password" name="password" id="inputPassword" placeholder="{{ i18n_password }}" class="form-control" required>
|
||||||
<label for="inputPassword">{{ i18n_password }}</label>
|
<label for="inputPassword">{{ i18n_password }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-floating form-stacked-bottom">
|
||||||
|
<input type="text" name="code" id="inputCode" placeholder="One-time code" class="form-control" required>
|
||||||
|
<label for="inputCode">One-time code</label>
|
||||||
|
</div>
|
||||||
<div class="d-grid mt-3">
|
<div class="d-grid mt-3">
|
||||||
<button class="btn btn-lg btn-primary" type="submit">{% translate "Sign in" %}</button>
|
<button class="btn btn-lg btn-primary" type="submit">{% translate "Sign in" %}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth import authenticate
|
||||||
|
from django.contrib.auth import login
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpResponseForbidden
|
from django.http import HttpResponseForbidden
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
@@ -13,6 +15,8 @@ from paperless_migration import settings
|
|||||||
@login_required
|
@login_required
|
||||||
@require_http_methods(["GET", "POST"])
|
@require_http_methods(["GET", "POST"])
|
||||||
def migration_home(request):
|
def migration_home(request):
|
||||||
|
if not request.session.get("migration_code_ok"):
|
||||||
|
return HttpResponseForbidden("Access code required")
|
||||||
if not request.user.is_superuser:
|
if not request.user.is_superuser:
|
||||||
return HttpResponseForbidden("Superuser access required")
|
return HttpResponseForbidden("Superuser access required")
|
||||||
|
|
||||||
@@ -44,3 +48,30 @@ def migration_home(request):
|
|||||||
"transformed_exists": transformed_path.exists(),
|
"transformed_exists": transformed_path.exists(),
|
||||||
}
|
}
|
||||||
return render(request, "paperless_migration/migration_home.html", context)
|
return render(request, "paperless_migration/migration_home.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@require_http_methods(["GET", "POST"])
|
||||||
|
def migration_login(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
username = request.POST.get("login", "")
|
||||||
|
password = request.POST.get("password", "")
|
||||||
|
code = request.POST.get("code", "")
|
||||||
|
|
||||||
|
if not code or code != settings.MIGRATION_ACCESS_CODE:
|
||||||
|
messages.error(request, "One-time code is required.")
|
||||||
|
return redirect("account_login")
|
||||||
|
|
||||||
|
user = authenticate(request, username=username, password=password)
|
||||||
|
if user is None:
|
||||||
|
messages.error(request, "Invalid username or password.")
|
||||||
|
return redirect("account_login")
|
||||||
|
|
||||||
|
if not user.is_superuser:
|
||||||
|
messages.error(request, "Superuser access required.")
|
||||||
|
return redirect("account_login")
|
||||||
|
|
||||||
|
login(request, user)
|
||||||
|
request.session["migration_code_ok"] = True
|
||||||
|
return redirect(settings.LOGIN_REDIRECT_URL)
|
||||||
|
|
||||||
|
return render(request, "account/login.html")
|
||||||
|
|||||||
Reference in New Issue
Block a user