Switch authentication over to OAuth.

Going to add fallback for running locally.
This commit is contained in:
Jason McBrayer 2018-05-14 15:35:10 -04:00
parent df085c5956
commit f40cc58852
4 changed files with 98 additions and 16 deletions

2
.gitignore vendored
View File

@ -107,3 +107,5 @@ db.sqlite3
include/ include/
lib64 lib64
pip-selfcheck.json pip-selfcheck.json
/Pipfile.lock
/dev_https

View File

@ -13,6 +13,10 @@ class LoginForm(forms.Form):
max_length=256) max_length=256)
password = forms.CharField(widget=forms.PasswordInput()) password = forms.CharField(widget=forms.PasswordInput())
class OAuthLoginForm(forms.Form):
instance = forms.CharField(label="Instance",
max_length=256)
class SettingsForm(forms.Form): class SettingsForm(forms.Form):
fullbrutalism = forms.BooleanField(label="Use FULLBRUTALISM mode?", fullbrutalism = forms.BooleanField(label="Use FULLBRUTALISM mode?",
required=False, required=False,

View File

@ -22,6 +22,7 @@ urlpatterns = [
path('home', views.home, name='home'), path('home', views.home, name='home'),
path('login', views.login, name="login"), path('login', views.login, name="login"),
path('logout', views.logout, name='logout'), path('logout', views.logout, name='logout'),
path('oauth_callback', views.oauth_callback, name="oauth_callback"),
path('error', views.error, name='error'), path('error', views.error, name='error'),
path('note', views.note, name='note'), path('note', views.note, name='note'),
path('local', views.local, name='local'), path('local', views.local, name='local'),

View File

@ -1,20 +1,34 @@
from django.http import HttpResponse, Http404 from django.http import HttpResponse, Http404
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.views.decorators.cache import never_cache from django.views.decorators.cache import never_cache
from brutaldon.forms import LoginForm, SettingsForm, PostForm from django.urls import reverse
from django.core.files.uploadhandler import TemporaryFileUploadHandler
from brutaldon.forms import LoginForm, OAuthLoginForm, SettingsForm, PostForm
from brutaldon.models import Client, Account from brutaldon.models import Client, Account
from mastodon import Mastodon from mastodon import Mastodon
from urllib import parse from urllib import parse
from django.core.files.uploadhandler import TemporaryFileUploadHandler
class NotLoggedInException(Exception): class NotLoggedInException(Exception):
pass pass
def get_mastodon(request): def get_mastodon(request):
if not (request.session.has_key('instance') and if not (request.session.has_key('instance') and
request.session.has_key('username')): (request.session.has_key('username') or
request.session.has_key('access_token'))):
raise NotLoggedInException() raise NotLoggedInException()
if request.session.has_key('access_token'):
try:
client = Client.objects.get(api_base_id=request.session['instance'])
except (Client.DoesNotExist, Client.MultipleObjectsReturned):
raise NotLoggedInException()
mastodon = Mastodon(
client_id = client.client_id,
client_secret = client.client_secret,
api_base_url = client.api_base_id,
access_token = request.session['access_token'],
ratelimit_method='pace')
else:
try: try:
client = Client.objects.get(api_base_id=request.session['instance']) client = Client.objects.get(api_base_id=request.session['instance'])
user = Account.objects.get(username=request.session['username']) user = Account.objects.get(username=request.session['username'])
@ -69,6 +83,68 @@ def tag(request, tag):
@never_cache @never_cache
def login(request): def login(request):
# User posts instance name in form.
# POST page redirects user to instance, where they log in.
# Instance redirects user to oauth_after_login view.
# oauth_after_login view saves credential in session, then redirects to home.
if request.method == "GET":
form = OAuthLoginForm()
return render(request, 'setup/login-oauth.html', {'form': form})
elif request.method == "POST":
form = OAuthLoginForm(request.POST)
redirect_uris = request.build_absolute_uri(reverse('oauth_callback'))
if form.is_valid():
api_base_url = form.cleaned_data['instance']
tmp_base = parse.urlparse(api_base_url.lower())
if tmp_base.netloc == '':
api_base_url = parse.urlunparse(('https', tmp_base.path,
'','','',''))
else:
api_base_url = api_base_url.lower()
request.session['instance'] = api_base_url
try:
client = Client.objects.get(api_base_id=api_base_url)
except (Client.DoesNotExist, Client.MultipleObjectsReturned):
(client_id, client_secret) = Mastodon.create_app('brutaldon',
api_base_url=api_base_url,
redirect_uris=redirect_uris)
client = Client(
api_base_id = api_base_url,
client_id=client_id,
client_secret = client_secret)
client.save()
request.session['client_id'] = client.client_id
request.session['client_secret'] = client.client_secret
mastodon = Mastodon(
client_id = client.client_id,
client_secret = client.client_secret,
api_base_url = api_base_url)
return redirect(mastodon.auth_request_url(redirect_uris=redirect_uris))
else:
return render(request, 'setup/login.html', {'form': form})
else:
return redirect(login)
@never_cache
def oauth_callback(request):
code = request.GET.get('code', '')
mastodon = Mastodon(client_id=request.session['client_id'],
client_secret=request.session['client_secret'],
api_base_url=request.session['instance'])
redirect_uri = request.build_absolute_uri(reverse('oauth_callback'))
access_token = mastodon.log_in(code=code,
redirect_uri=redirect_uri,
scopes=['read', 'write', 'follow'])
request.session['access_token'] = access_token
return redirect(home)
@never_cache
def old_login(request):
if request.method == "GET": if request.method == "GET":
form = LoginForm() form = LoginForm()
return render(request, 'setup/login.html', {'form': form}) return render(request, 'setup/login.html', {'form': form})
@ -76,7 +152,6 @@ def login(request):
form = LoginForm(request.POST) form = LoginForm(request.POST)
if form.is_valid(): if form.is_valid():
api_base_url = form.cleaned_data['instance'] api_base_url = form.cleaned_data['instance']
# Fixme, make sure this is url
tmp_base = parse.urlparse(api_base_url.lower()) tmp_base = parse.urlparse(api_base_url.lower())
if tmp_base.netloc == '': if tmp_base.netloc == '':
api_base_url = parse.urlunparse(('https', tmp_base.path, api_base_url = parse.urlunparse(('https', tmp_base.path,