feat: add Daedalus API token management to profile settings
- Display the user's DRF auth token on the profile settings page - Add copy-to-clipboard button for easy token retrieval - Add token regeneration endpoint with confirmation prompt - Auto-create token on first visit via get_or_create - Instruct users to set DAEDALUS_MNEMOSYNE_API_KEY in Daedalus env
This commit is contained in:
@@ -140,5 +140,32 @@
|
||||
<button type="submit" class="btn btn-primary">Save Settings</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Daedalus API Token — separate form, outside the settings form -->
|
||||
<div class="card bg-base-200 mb-6">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title text-lg">Daedalus API Token</h2>
|
||||
<p class="text-sm opacity-70 mb-4">
|
||||
Used by Daedalus to authenticate with Mnemosyne. Set
|
||||
<code class="font-mono text-xs">DAEDALUS_MNEMOSYNE_API_KEY</code>
|
||||
in your Daedalus environment to this value.
|
||||
</p>
|
||||
<div class="flex items-center gap-3">
|
||||
<code class="font-mono bg-base-300 px-3 py-2 rounded flex-1 break-all select-all text-sm">{{ api_token.key }}</code>
|
||||
<button type="button"
|
||||
class="btn btn-ghost btn-sm"
|
||||
onclick="navigator.clipboard.writeText('{{ api_token.key }}').then(() => { this.textContent = 'Copied!'; setTimeout(() => this.textContent = 'Copy', 2000); }).catch(() => {})">
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<form method="post" action="{% url 'themis:api-token-regenerate' %}"
|
||||
onsubmit="return confirm('Regenerate token? Daedalus will stop working until you update DAEDALUS_MNEMOSYNE_API_KEY.')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-warning btn-sm">Regenerate</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -13,6 +13,7 @@ urlpatterns = [
|
||||
path("live/", views.live, name="live"),
|
||||
# Profile settings
|
||||
path("profile/settings/", views.profile_settings, name="profile-settings"),
|
||||
path("profile/api-token/regenerate/", views.api_token_regenerate, name="api-token-regenerate"),
|
||||
# API key management
|
||||
path("profile/keys/", views.key_list, name="key-list"),
|
||||
path("profile/keys/add/", views.key_create, name="key-create"),
|
||||
|
||||
@@ -12,6 +12,8 @@ from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils import timezone
|
||||
from django.views.decorators.http import require_GET, require_http_methods, require_POST
|
||||
|
||||
from rest_framework.authtoken.models import Token
|
||||
|
||||
from themis.encryption import encrypt_value
|
||||
from themis.forms import APIKeyCreateForm, APIKeyEditForm, ProfileSettingsForm
|
||||
from themis.models import UserAPIKey, UserNotification
|
||||
@@ -63,6 +65,7 @@ def live(request):
|
||||
def profile_settings(request):
|
||||
"""Display and update user profile preferences."""
|
||||
profile = request.user.profile
|
||||
api_token, _ = Token.objects.get_or_create(user=request.user)
|
||||
|
||||
if request.method == "POST":
|
||||
form = ProfileSettingsForm(request.POST, instance=profile)
|
||||
@@ -73,7 +76,17 @@ def profile_settings(request):
|
||||
else:
|
||||
form = ProfileSettingsForm(instance=profile)
|
||||
|
||||
return render(request, "themis/profile/settings.html", {"form": form})
|
||||
return render(request, "themis/profile/settings.html", {"form": form, "api_token": api_token})
|
||||
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def api_token_regenerate(request):
|
||||
"""Delete and recreate the user's DRF API token."""
|
||||
Token.objects.filter(user=request.user).delete()
|
||||
Token.objects.create(user=request.user)
|
||||
messages.success(request, "API token regenerated.")
|
||||
return redirect("themis:profile-settings")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user