Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58471b1a4d | ||
|
|
11399bb860 |
@@ -8,6 +8,7 @@ from fastapi.templating import Jinja2Templates
|
|||||||
from starlette.middleware.sessions import SessionMiddleware
|
from starlette.middleware.sessions import SessionMiddleware
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
import authentik as ak
|
import authentik as ak
|
||||||
import cache
|
import cache
|
||||||
@@ -56,14 +57,29 @@ def is_admin(user) -> bool:
|
|||||||
|
|
||||||
def require_admin(request: Request):
|
def require_admin(request: Request):
|
||||||
user = current_user(request)
|
user = current_user(request)
|
||||||
|
if not user and request.method == "GET" and "text/html" in request.headers.get("accept", ""):
|
||||||
|
# Ikke logget ind: login og tilbage hertil (fx et link fra en ntfy),
|
||||||
|
# i stedet for en 403-blindgyde.
|
||||||
|
nxt = request.url.path + (f"?{request.url.query}" if request.url.query else "")
|
||||||
|
raise HTTPException(303, headers={"Location": "/auth/login?next=" + urllib.parse.quote(nxt, safe="")})
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(401, "Log ind først")
|
||||||
if not is_admin(user):
|
if not is_admin(user):
|
||||||
raise HTTPException(403, "Kun for administratorer")
|
raise HTTPException(403, "Kun for administratorer")
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
def _sikker_next(nxt: str | None) -> str:
|
||||||
|
# Kun stier på denne side; "//host" og "/\\host" ville sende videre ud af huset.
|
||||||
|
if nxt and nxt.startswith("/") and not nxt.startswith(("//", "/\\")):
|
||||||
|
return nxt
|
||||||
|
return "/"
|
||||||
|
|
||||||
|
|
||||||
# ---------------- auth ----------------
|
# ---------------- auth ----------------
|
||||||
@app.get("/auth/login")
|
@app.get("/auth/login")
|
||||||
async def login(request: Request):
|
async def login(request: Request, next: str = ""):
|
||||||
|
request.session["next"] = _sikker_next(next)
|
||||||
return await oauth.authentik.authorize_redirect(request, config.REDIRECT_URI)
|
return await oauth.authentik.authorize_redirect(request, config.REDIRECT_URI)
|
||||||
|
|
||||||
|
|
||||||
@@ -78,7 +94,7 @@ async def callback(request: Request):
|
|||||||
"name": info.get("name") or info.get("preferred_username"),
|
"name": info.get("name") or info.get("preferred_username"),
|
||||||
"username": info.get("preferred_username"), "email": info.get("email"),
|
"username": info.get("preferred_username"), "email": info.get("email"),
|
||||||
"groups": info.get("groups") or []}
|
"groups": info.get("groups") or []}
|
||||||
return RedirectResponse("/", status_code=302)
|
return RedirectResponse(_sikker_next(request.session.pop("next", "/")), status_code=302)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/auth/logout")
|
@app.get("/auth/logout")
|
||||||
@@ -370,7 +386,7 @@ async def admin_claude_login_status(request: Request):
|
|||||||
@app.post("/admin/claude-login/start")
|
@app.post("/admin/claude-login/start")
|
||||||
async def admin_claude_login_start(request: Request):
|
async def admin_claude_login_start(request: Request):
|
||||||
user = require_admin(request)
|
user = require_admin(request)
|
||||||
claudelogin.request((user or {}).get("preferred_username") or "?")
|
claudelogin.request((user or {}).get("username") or "?")
|
||||||
return JSONResponse(claudelogin.state())
|
return JSONResponse(claudelogin.state())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@
|
|||||||
};
|
};
|
||||||
var $ = function (id) { return document.getElementById(id); };
|
var $ = function (id) { return document.getElementById(id); };
|
||||||
var timer = null;
|
var timer = null;
|
||||||
|
// Efter et tryk på Start venter vi i op til et minut på en status, serveren har
|
||||||
|
// skrevet EFTER trykket; en ældre hvile-status betyder bare, at den ikke er nået dertil.
|
||||||
|
var klik = 0;
|
||||||
|
|
||||||
function dato(t) {
|
function dato(t) {
|
||||||
var d = new Date(t * 1000);
|
var d = new Date(t * 1000);
|
||||||
@@ -56,6 +59,8 @@
|
|||||||
|
|
||||||
function vis(st) {
|
function vis(st) {
|
||||||
var s = st.status || "ukendt";
|
var s = st.status || "ukendt";
|
||||||
|
var hvile = s === "ok" || s === "snart" || s === "udloebet" || s === "ukendt";
|
||||||
|
if (hvile && klik && Date.now() - klik < 60000 && (st.updated || 0) * 1000 < klik) s = "starter";
|
||||||
var linje = TEKST[s] || s;
|
var linje = TEKST[s] || s;
|
||||||
if (st.expires && (s === "ok" || s === "snart")) {
|
if (st.expires && (s === "ok" || s === "snart")) {
|
||||||
var dage = Math.floor((st.expires * 1000 - Date.now()) / 86400000);
|
var dage = Math.floor((st.expires * 1000 - Date.now()) / 86400000);
|
||||||
@@ -93,6 +98,7 @@
|
|||||||
|
|
||||||
$("cl-start-btn").addEventListener("click", function () {
|
$("cl-start-btn").addEventListener("click", function () {
|
||||||
$("cl-start-btn").disabled = true;
|
$("cl-start-btn").disabled = true;
|
||||||
|
klik = Date.now();
|
||||||
fetch("/admin/claude-login/start", { method: "POST", credentials: "same-origin" })
|
fetch("/admin/claude-login/start", { method: "POST", credentials: "same-origin" })
|
||||||
.then(function (r) { return r.json(); }).then(vis)
|
.then(function (r) { return r.json(); }).then(vis)
|
||||||
.finally(function () { $("cl-start-btn").disabled = false; });
|
.finally(function () { $("cl-start-btn").disabled = false; });
|
||||||
|
|||||||
Reference in New Issue
Block a user