feat: rework auth model with UserToken and Daedalus/Pallas integration
- Rename MCPToken to UserToken across models, views, and tests - Update URL names from mcp-token-* to token-* - Add Daedalus/Pallas integration design doc (v2) - Switch docker-compose to build local mnemosyne:local image via shared build config instead of pulling from git.helu.ca
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"""Self-service dashboard for MCP bearer tokens.
|
||||
"""Self-service dashboard for per-user API tokens.
|
||||
|
||||
Mirrors the Themis API-keys flow visually but stores hashed tokens. Plaintext
|
||||
is shown to the user exactly once (on the create-success page) and never
|
||||
persisted.
|
||||
Mirrors the Themis API-keys flow visually but stores hashed tokens.
|
||||
Plaintext is shown to the user exactly once (on the create-success
|
||||
page) and never persisted.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -13,24 +13,24 @@ from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.views.decorators.http import require_GET, require_http_methods, require_POST
|
||||
|
||||
from .forms import MCPTokenCreateForm, MCPTokenEditForm
|
||||
from .models import MCPToken
|
||||
from .forms import UserTokenCreateForm, UserTokenEditForm
|
||||
from .models import UserToken
|
||||
|
||||
|
||||
@login_required
|
||||
@require_GET
|
||||
def mcp_token_list(request: HttpRequest) -> HttpResponse:
|
||||
tokens = MCPToken.objects.filter(user=request.user).order_by("-created_at")
|
||||
def token_list(request: HttpRequest) -> HttpResponse:
|
||||
tokens = UserToken.objects.filter(user=request.user).order_by("-created_at")
|
||||
return render(request, "mcp_server/tokens/list.html", {"tokens": tokens})
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def mcp_token_create(request: HttpRequest) -> HttpResponse:
|
||||
def token_create(request: HttpRequest) -> HttpResponse:
|
||||
if request.method == "POST":
|
||||
form = MCPTokenCreateForm(request.POST, user=request.user)
|
||||
form = UserTokenCreateForm(request.POST, user=request.user)
|
||||
if form.is_valid():
|
||||
token, plaintext = MCPToken.objects.create_token(
|
||||
token, plaintext = UserToken.objects.create_token(
|
||||
user=request.user,
|
||||
name=form.cleaned_data["name"],
|
||||
allowed_tools=form.cleaned_data.get("allowed_tools") or [],
|
||||
@@ -43,25 +43,25 @@ def mcp_token_create(request: HttpRequest) -> HttpResponse:
|
||||
{"token": token, "plaintext": plaintext},
|
||||
)
|
||||
else:
|
||||
form = MCPTokenCreateForm(user=request.user)
|
||||
form = UserTokenCreateForm(user=request.user)
|
||||
|
||||
return render(request, "mcp_server/tokens/create.html", {"form": form})
|
||||
|
||||
|
||||
@login_required
|
||||
@require_GET
|
||||
def mcp_token_detail(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(MCPToken, pk=pk, user=request.user)
|
||||
def token_detail(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(UserToken, pk=pk, user=request.user)
|
||||
return render(request, "mcp_server/tokens/detail.html", {"token": token})
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def mcp_token_edit(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(MCPToken, pk=pk, user=request.user)
|
||||
def token_edit(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(UserToken, pk=pk, user=request.user)
|
||||
|
||||
if request.method == "POST":
|
||||
form = MCPTokenEditForm(request.POST, instance=token, user=request.user)
|
||||
form = UserTokenEditForm(request.POST, instance=token, user=request.user)
|
||||
if form.is_valid():
|
||||
instance = form.save(commit=False)
|
||||
instance.allowed_tools = form.cleaned_data.get("allowed_tools") or []
|
||||
@@ -69,10 +69,10 @@ def mcp_token_edit(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
form.cleaned_data.get("allowed_libraries") or []
|
||||
)
|
||||
instance.save()
|
||||
messages.success(request, "MCP token updated.")
|
||||
return redirect("mcp_server:mcp-token-detail", pk=token.pk)
|
||||
messages.success(request, "Token updated.")
|
||||
return redirect("mcp_server:token-detail", pk=token.pk)
|
||||
else:
|
||||
form = MCPTokenEditForm(instance=token, user=request.user)
|
||||
form = UserTokenEditForm(instance=token, user=request.user)
|
||||
|
||||
return render(
|
||||
request, "mcp_server/tokens/edit.html", {"form": form, "token": token}
|
||||
@@ -81,19 +81,19 @@ def mcp_token_edit(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def mcp_token_revoke(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(MCPToken, pk=pk, user=request.user)
|
||||
def token_revoke(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(UserToken, pk=pk, user=request.user)
|
||||
token.is_active = False
|
||||
token.save(update_fields=["is_active", "updated_at"])
|
||||
messages.success(request, f"Revoked “{token.name}”. The token can no longer be used.")
|
||||
return redirect("mcp_server:mcp-token-detail", pk=token.pk)
|
||||
return redirect("mcp_server:token-detail", pk=token.pk)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def mcp_token_delete(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(MCPToken, pk=pk, user=request.user)
|
||||
def token_delete(request: HttpRequest, pk: int) -> HttpResponse:
|
||||
token = get_object_or_404(UserToken, pk=pk, user=request.user)
|
||||
name = token.name
|
||||
token.delete()
|
||||
messages.success(request, f"Deleted “{name}”.")
|
||||
return redirect("mcp_server:mcp-token-list")
|
||||
return redirect("mcp_server:token-list")
|
||||
|
||||
Reference in New Issue
Block a user