Add Settings UI for adding apps with access token (alternative to OAuth method)

pull/552/head
CSDUMMI 2023-03-31 21:00:51 +02:00
rodzic ba4414dbce
commit 028065389a
7 zmienionych plików z 150 dodań i 11 usunięć

Wyświetl plik

@ -1,3 +1,5 @@
import secrets
from django.db import models
@ -17,3 +19,23 @@ class Application(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
@classmethod
def add_app(
cls,
client_name: str,
website: str,
redirect_uris: str,
scopes: str | None = None,
):
client_id = "tk-" + secrets.token_urlsafe(16)
client_secret = secrets.token_urlsafe(40)
return cls.objects.create(
name=client_name,
website=website,
client_id=client_id,
client_secret=client_secret,
redirect_uris=redirect_uris,
scopes=scopes or "read",
)

Wyświetl plik

@ -1,5 +1,3 @@
import secrets
from hatchway import QueryOrBody, api_view
from .. import schemas
@ -14,14 +12,7 @@ def add_app(
scopes: QueryOrBody[None | str] = None,
website: QueryOrBody[None | str] = None,
) -> schemas.Application:
client_id = "tk-" + secrets.token_urlsafe(16)
client_secret = secrets.token_urlsafe(40)
application = Application.objects.create(
name=client_name,
website=website,
client_id=client_id,
client_secret=client_secret,
redirect_uris=redirect_uris,
scopes=scopes or "read",
application = Application.add_app(
client_name, website, redirect_uris, scopes=scopes
)
return schemas.Application.from_orm(application)

Wyświetl plik

@ -61,6 +61,8 @@ urlpatterns = [
settings.ProfilePage.as_view(),
name="settings_profile",
),
path("settings/apps/add", settings.AddAppsPage.as_view(), name="settings_apps_add"),
path("settings/apps/", settings.AppsPage.as_view(), name="settings_app"),
path(
"settings/interface/",
settings.InterfacePage.as_view(),

Wyświetl plik

@ -0,0 +1,18 @@
{% extends "settings/base.html" %}
{% block subtitle %}Add an App{% endblock %}
{% block content %}
<form action="/settings/apps/add" method="POST">
{% csrf_token %}
{% include "forms/_field.html" with field=form.name %}
{% include "forms/_field.html" with field=form.redirect_uri %}
{% include "forms/_field.html" with field=form.website %}
{% include "forms/_field.html" with field=form.scopes %}
<div class="buttons">
<button>Add Application</button>
</div>
</form>
{% endblock %}

Wyświetl plik

@ -0,0 +1,33 @@
{% extends "settings/base.html" %}
{% block subtitle %}Apps{% endblock %}
{% block content %}
<h2>Apps</h2>
<div>
{% for token in object_list %}
<p>
<h3>{{token.application.name}}</h3>
<table class="items">
<tr>
<td>Client ID</td>
<td>{{token.application.client_id}}</td>
</tr>
<tr>
<td>Client Secret</td>
<td>{{token.application.client_secret}}</td>
</tr>
<tr>
<td>Access Token</td>
<td>{{token.token}}</td>
</tr>
<tr>
<td>Scopes</td>
<td>{{token.scopes}}</td>
</tr>
</table>
</p>
{% endfor %}
</div>
<a href="/settings/apps/add">Add Application</a>
{% endblock %}

Wyświetl plik

@ -2,6 +2,7 @@ from django.utils.decorators import method_decorator
from django.views.generic import RedirectView
from users.decorators import identity_required
from users.views.settings.apps import AppsPage, AddAppsPage
from users.views.settings.import_export import ( # noqa
CsvFollowers,
CsvFollowing,

Wyświetl plik

@ -0,0 +1,72 @@
from django.utils.decorators import method_decorator
from django.views.generic.list import ListView
from api.models.token import Token
from users.decorators import identity_required
import secrets
from django import forms
from django.shortcuts import redirect
from django.views.generic import FormView
from api.models.application import Application
class AppsForm(forms.Form):
name = forms.CharField(help_text="Name to identify this App by for you.")
redirect_uri = forms.CharField(initial="urn:ietf:wg:oauth:2.0:oob",
help_text="Only change this if this app should authenticate other users")
website = forms.CharField(required=False,
help_text="Website of the App")
scopes = forms.MultipleChoiceField(choices=(("read", "read"),
("write", "write")),
help_text="What should this app be able to do with your account?")
@method_decorator(identity_required, name="dispatch")
class AddAppsPage(FormView):
"""Shows a page of the user's apps
And allows creating new apps and access tokens.
"""
template_name = "settings/add_apps.html"
form_class = AppsForm
success_url = "/settings/apps/add"
def form_valid(self, form):
super().form_valid(form)
print(type(form))
print(dir(form))
application = Application.add_app(
form.cleaned_data["name"],
form.cleaned_data.get("website", ""),
form.cleaned_data["redirect_uri"],
)
scopes = form.cleaned_data["scopes"]
Token.objects.create(
application=application,
user=self.request.user,
identity=self.request.identity,
token=secrets.token_urlsafe(43),
scopes=scopes,
)
return redirect("/settings/apps")
@method_decorator(identity_required, name="dispatch")
class AppsPage(ListView):
model = Token
template_name = "settings/apps.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
self.object_list = Token.objects.filter(
user=self.request.user, identity=self.request.identity
).prefetch_related("applications")
return context