~kline/torgateway

ref: 9e9275834728a965eae36cee4579dbdc108dc018 torgateway/web.py -rw-r--r-- 2.9 KiB
9e927583Gareth Pulham Add registration via XML-RPC 1 year, 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from flask import Flask, render_template, request, g, jsonify
import sqlite3
import hashcash

import freenode

hash_difficulty = 4
hash_expiry = 7 # Days

def get_db():
    db = getattr(g, "database", None)
    if db is None:
        db = g.database = sqlite3.connect("database.db", detect_types=sqlite3.PARSE_DECLTYPES)
        db.row_factory = sqlite3.Row
        db.cursor().execute("PRAGMA foreign_keys = ON;")
        db.commit()
    return db

app = Flask(__name__)

@app.route("/")
def index():
    return render_template("index.html")

@app.route("/register", methods=["POST"])
def register():
    try:
        token = request.form["token"]
        username = request.form["username"]
        password = request.form["password"]
        fingerprint = request.form["fingerprint"]
    except KeyError as e:
        return jsonify({"status": "failure", "reason": "incomplete registration details", "token_reusable": True})
    
    database = get_db()

    # Verify Token
    #   Failure?
    #       Return failed page.
    # Insert Token
    #   Failure?
    #       Return failed page.
    # Register user
    #   Success?
    #       Commit token
    #       Return success page
    #   Failure?
    #       Rollback Token
    #       Return failure page (with token for re-use)
    
    try:
        token_valid = hashcash.hashcash_check(token, "freenode.net", hash_difficulty, hash_expiry * 24 * 60 * 60)
    except AssertionError as e:
        return jsonify({"status": "failure", "reason": str(e), "token_reusable": False})
    if not token_valid:
        return jsonify({"status": "failure", "reason": "invalid token", "token_reusable": False})

    cursor = database.cursor()
    
    try:
        cursor.execute("insert into tokens (token, entry_time) values (?, datetime('now'));", (token,))
    except sqlite3.IntegrityError:
        database.rollback()
        return jsonify({"status": "failure", "reason": "token has already been used", "token_reusable": False})
    except Exception as e:
        database.rollback()
        return jsonify({"status": "failure", "reason": str(e)})

    try:
        freenode.register_user(username, password, certfp=fingerprint)
        database.commit()
    except NotImplementedError as e: # registration_error
        database.rollback()
        # Raise error page with appropriate info (username in use, invalid chars, etc)
        return jsonify({"status": "failure", "reason": str(e), "token_reusable": True})
    except Exception as e:
        database.rollback()
        # Raise error page with generic info (also token still valid)
        return jsonify({"status": "failure", "reason": str(e), "token_reusable": True})

    return jsonify({"status": "success", "username": username, "token_reusable": False})

def cleanup():  # Should run every day
    database = get_db()
    cursor = database.cursor()
    cursor.execute("delete from tokens where entry_time < datetime('now', ?);", ("-"+hash_expiry+" days",))
    database.commit()