kopia lustrzana https://github.com/jointakahe/takahe
Add Settings UI for adding apps with access token (alternative to OAuth method)
rodzic
ba4414dbce
commit
028065389a
|
@ -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",
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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,
|
||||
|
|
|
@ -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
|
Ładowanie…
Reference in New Issue