kalendasz/app.py

81 lines
2.2 KiB
Python

import argparse
import base64
import json
import secrets
from urllib.parse import urlencode
import yaml
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from flask import Flask, redirect, render_template, request, session, url_for
parser = argparse.ArgumentParser()
parser.add_argument("config", help="Path to configuration file")
args = parser.parse_args()
with open(args.config) as f:
config = yaml.safe_load(f)
app = Flask(__name__)
app.secret_key = config["secret_key"]
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
@app.route("/")
def index():
return render_template("index.html", application_name=config["application_name"])
@app.route("/authorize")
def authorize():
public_key = private_key.public_key().public_bytes(
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo,
).decode()
nonce = secrets.token_hex(16)
client_id = secrets.token_hex(48)
session["nonce"] = nonce
session["client_id"] = client_id
params = {
"auth_redirect": config["redirect_url"],
"application_name": config["application_name"],
"scopes": "read",
"client_id": client_id,
"nonce": nonce,
"public_key": public_key,
}
return redirect(f"{config['forum_url']}/user-api-key/new?{urlencode(params)}")
@app.route("/callback")
def callback():
payload_b64 = request.args.get("payload")
if not payload_b64:
return "Missing payload", 400
try:
payload = base64.b64decode(payload_b64)
data = private_key.decrypt(payload, padding.PKCS1v15())
response = json.loads(data)
except Exception:
return "Failed to decrypt or decode payload", 400
if response.get("nonce") != session.get("nonce"):
return "Invalid nonce", 400
key = response["key"]
calendar_url = f"{config['forum_url']}/discourse-post-event/events.ics?order=desc&api_key={key}"
return render_template(
"result.html",
application_name=config["application_name"],
calendar_url=calendar_url,
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)