Switch to standard auth
This commit is contained in:
parent
c17cc80b77
commit
c565373f49
100
todosrht/app.py
100
todosrht/app.py
|
@ -1,51 +1,20 @@
|
|||
from flask import render_template, request
|
||||
from flask_login import LoginManager, current_user
|
||||
from jinja2 import Markup
|
||||
import locale
|
||||
import urllib
|
||||
|
||||
from srht.config import cfg, cfgi, load_config
|
||||
from srht.flask import SrhtFlask
|
||||
from srht.config import cfg, load_config
|
||||
load_config("todo")
|
||||
|
||||
from srht.database import DbSession
|
||||
db = DbSession(cfg("sr.ht", "connection-string"))
|
||||
from todosrht.types import User, TicketAccess, TicketStatus, TicketResolution, TicketSeen
|
||||
|
||||
from todosrht.types import User
|
||||
from todosrht.types import TicketAccess, TicketStatus, TicketResolution
|
||||
from todosrht.types import TicketSeen
|
||||
db.init()
|
||||
|
||||
from srht.flask import SrhtFlask
|
||||
app = SrhtFlask("todo", __name__)
|
||||
app.url_map.strict_slashes = False
|
||||
app.secret_key = cfg("server", "secret-key")
|
||||
login_manager = LoginManager()
|
||||
login_manager.init_app(app)
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(username):
|
||||
return User.query.filter(User.username == username).first()
|
||||
|
||||
login_manager.anonymous_user = lambda: None
|
||||
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, 'en_US')
|
||||
except:
|
||||
pass
|
||||
|
||||
def oauth_url(return_to):
|
||||
return "{}/oauth/authorize?client_id={}&scopes=profile&state={}".format(
|
||||
meta_sr_ht, meta_client_id, urllib.parse.quote_plus(return_to))
|
||||
|
||||
from todosrht.blueprints.html import html
|
||||
from todosrht.blueprints.auth import auth
|
||||
from todosrht.blueprints.tracker import tracker
|
||||
from todosrht.blueprints.ticket import ticket
|
||||
|
||||
app.register_blueprint(html)
|
||||
app.register_blueprint(auth)
|
||||
app.register_blueprint(tracker)
|
||||
app.register_blueprint(ticket)
|
||||
|
||||
meta_sr_ht = cfg("network", "meta")
|
||||
meta_client_id = cfg("meta.sr.ht", "oauth-client-id")
|
||||
|
||||
def tracker_name(tracker, full=False):
|
||||
split = tracker.name.split("/")
|
||||
user = tracker.owner.canonical_name()
|
||||
|
@ -80,15 +49,46 @@ def render_status(ticket, access):
|
|||
else:
|
||||
return "<span>{}</span>".format(ticket.status.name)
|
||||
|
||||
@app.context_processor
|
||||
def inject():
|
||||
return {
|
||||
"oauth_url": oauth_url(request.full_path),
|
||||
"current_user": User.query.filter(User.id == current_user.id).first() \
|
||||
if current_user else None,
|
||||
"format_tracker_name": tracker_name,
|
||||
"render_status": render_status,
|
||||
"TicketAccess": TicketAccess,
|
||||
"TicketStatus": TicketStatus,
|
||||
"TicketResolution": TicketResolution
|
||||
}
|
||||
class TodoApp(SrhtFlask):
|
||||
def __init__(self):
|
||||
super().__init__("todo", __name__)
|
||||
|
||||
self.url_map.strict_slashes = False
|
||||
|
||||
self.register_blueprint(html)
|
||||
self.register_blueprint(tracker)
|
||||
self.register_blueprint(ticket)
|
||||
|
||||
meta_client_id = cfg("meta.sr.ht", "oauth-client-id")
|
||||
meta_client_secret = cfg("meta.sr.ht", "oauth-client-secret")
|
||||
self.configure_meta_auth(meta_client_id, meta_client_secret)
|
||||
|
||||
@self.context_processor
|
||||
def inject():
|
||||
return {
|
||||
"format_tracker_name": tracker_name,
|
||||
"render_status": render_status,
|
||||
"TicketAccess": TicketAccess,
|
||||
"TicketStatus": TicketStatus,
|
||||
"TicketResolution": TicketResolution
|
||||
}
|
||||
|
||||
@self.login_manager.user_loader
|
||||
def user_loader(username):
|
||||
# TODO: Switch to a session token
|
||||
return User.query.filter(User.username == username).one_or_none()
|
||||
|
||||
def lookup_or_register(self, exchange, profile, scopes):
|
||||
user = User.query.filter(User.username == profile["username"]).first()
|
||||
if not user:
|
||||
user = User()
|
||||
db.session.add(user)
|
||||
user.username = profile.get("username")
|
||||
user.email = profile.get("email")
|
||||
user.oauth_token = exchange["token"]
|
||||
user.oauth_token_expires = exchange["expires"]
|
||||
user.oauth_token_scopes = scopes
|
||||
db.session.commit()
|
||||
return user
|
||||
|
||||
app = TodoApp()
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
from flask import Blueprint, request, render_template, redirect
|
||||
from flask_login import login_user, logout_user
|
||||
from sqlalchemy import or_
|
||||
from srht.config import cfg
|
||||
from srht.flask import DATE_FORMAT
|
||||
from srht.oauth import OAuthScope
|
||||
from srht.database import db
|
||||
from todosrht.types import User
|
||||
from datetime import datetime
|
||||
import urllib.parse
|
||||
import requests
|
||||
|
||||
auth = Blueprint('auth', __name__)
|
||||
|
||||
meta_uri = cfg("network", "meta")
|
||||
client_id = cfg("meta.sr.ht", "oauth-client-id")
|
||||
client_secret = cfg("meta.sr.ht", "oauth-client-secret")
|
||||
|
||||
@auth.route("/oauth/callback")
|
||||
def oauth_callback():
|
||||
error = request.args.get("error")
|
||||
if error:
|
||||
details = request.args.get("details")
|
||||
return render_template("oauth-error.html", details=details)
|
||||
exchange = request.args.get("exchange")
|
||||
scopes = request.args.get("scopes")
|
||||
state = request.args.get("state")
|
||||
_scopes = [OAuthScope(s) for s in scopes.split(",")]
|
||||
if not OAuthScope("profile:read") in _scopes:
|
||||
return render_template("oauth-error.html",
|
||||
details="todo.sr.ht requires profile and key access at a mininum to function correctly. " +
|
||||
"To use todo.sr.ht, try again and do not untick these permissions.")
|
||||
if not exchange:
|
||||
return render_template("oauth-error.html",
|
||||
details="Expected an exchange token from meta.sr.ht. Something odd has happened, try again.")
|
||||
r = requests.post(meta_uri + "/oauth/exchange", json={
|
||||
"client_id": client_id,
|
||||
"client_secret": client_secret,
|
||||
"exchange": exchange,
|
||||
})
|
||||
if r.status_code != 200:
|
||||
return render_template("oauth-error.html",
|
||||
details="Error occured retrieving OAuth token. Try again.")
|
||||
json = r.json()
|
||||
token = json.get("token")
|
||||
expires = json.get("expires")
|
||||
if not token or not expires:
|
||||
return render_template("oauth-error.html",
|
||||
details="Error occured retrieving OAuth token. Try again.")
|
||||
expires = datetime.strptime(expires, DATE_FORMAT)
|
||||
|
||||
r = requests.get(meta_uri + "/api/user/profile", headers={
|
||||
"Authorization": "token " + token
|
||||
})
|
||||
if r.status_code != 200:
|
||||
return render_template("oauth-error.html",
|
||||
details="Error occured retrieving account info. Try again.")
|
||||
|
||||
json = r.json()
|
||||
user = User.query.filter(or_(User.oauth_token == token,
|
||||
User.username == json["username"])).first()
|
||||
if not user:
|
||||
user = User()
|
||||
db.session.add(user)
|
||||
user.username = json.get("username")
|
||||
user.email = json.get("email")
|
||||
user.oauth_token = token
|
||||
user.oauth_token_expires = expires
|
||||
user.oauth_token_scopes = scopes
|
||||
db.session.commit()
|
||||
|
||||
login_user(user, remember=True)
|
||||
if not state or not state.startswith("/"):
|
||||
return redirect("/")
|
||||
else:
|
||||
return redirect(urllib.parse.unquote(state))
|
||||
|
||||
@auth.route("/logout")
|
||||
def logout():
|
||||
logout_user()
|
||||
return redirect(request.headers.get("Referer") or "/")
|
|
@ -3,7 +3,6 @@ import string
|
|||
from flask import Blueprint, render_template, request, url_for, abort, redirect
|
||||
from flask import session
|
||||
from flask_login import current_user
|
||||
from todosrht.decorators import loginrequired
|
||||
from todosrht.access import get_tracker, get_ticket
|
||||
from todosrht.types import Tracker, User, Ticket, TicketStatus, TicketAccess
|
||||
from todosrht.types import TicketComment, TicketResolution, TicketSeen
|
||||
|
@ -12,6 +11,7 @@ from todosrht.types import Event, EventType, EventNotification
|
|||
from todosrht.email import notify
|
||||
from srht.config import cfg
|
||||
from srht.database import db
|
||||
from srht.flask import loginrequired
|
||||
from srht.validation import Validation
|
||||
from datetime import datetime
|
||||
|
||||
|
|
|
@ -5,14 +5,13 @@ from flask import Blueprint, render_template, request, url_for, abort, redirect
|
|||
from flask import session
|
||||
from flask_login import current_user
|
||||
from todosrht.access import get_tracker
|
||||
from todosrht.decorators import loginrequired
|
||||
from todosrht.email import notify
|
||||
from todosrht.types import Tracker, User, Ticket, TicketStatus, TicketAccess
|
||||
from todosrht.types import TicketComment, TicketResolution, TicketSubscription
|
||||
from todosrht.types import TicketSeen, Event, EventType, EventNotification
|
||||
from srht.config import cfg
|
||||
from srht.database import db
|
||||
from srht.flask import paginate_query
|
||||
from srht.flask import paginate_query, loginrequired
|
||||
from srht.validation import Validation
|
||||
from datetime import datetime
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
from flask import redirect, request, abort
|
||||
from flask_login import current_user
|
||||
from functools import wraps
|
||||
from todosrht.app import oauth_url
|
||||
|
||||
import urllib
|
||||
|
||||
def loginrequired(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwargs):
|
||||
if not current_user:
|
||||
return redirect(oauth_url(request.url))
|
||||
else:
|
||||
return f(*args, **kwargs)
|
||||
return wrapper
|
Loading…
Reference in New Issue