-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.py
146 lines (135 loc) · 4 KB
/
api.py
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
from flask import abort, request, redirect, Response
from werkzeug import wrappers
import uuid
from utils import db_execute, salt_hash, jsonify, default_response, check_auth
def vote(country, magnitude):
name = request.name
magnitude = int(magnitude)
assert 0 < magnitude <= 12 and magnitude != 11
db_execute("""
INSERT OR REPLACE INTO votes(user_id, contender_id, magnitude)
VALUES (
(SELECT id FROM users WHERE name = :name),
(SELECT id FROM contenders WHERE country = :country),
:magnitude
)
""", name=name, country=country.lower(), magnitude=magnitude)
def ladder_global():
return db_execute("""
WITH t AS (
SELECT contender_id, SUM(magnitude) AS score FROM votes
GROUP BY contender_id
)
SELECT country, IFNULL(t.score, 0) AS score
FROM contenders LEFT JOIN t ON id = contender_id
ORDER BY score DESC, country
""")
def ladder_user(name=None):
name = name or request.authorization.username
return db_execute("""
WITH t AS (
SELECT contender_id, SUM(magnitude) AS score
FROM votes
WHERE user_id = (SELECT id FROM users WHERE name = :name)
GROUP BY contender_id
)
SELECT country, IFNULL(t.score, 0) AS score
FROM contenders LEFT JOIN t ON id = contender_id
ORDER BY t.score DESC, country
""", name=name)
def users():
return db_execute("""
SELECT name FROM users
ORDER BY name
""")
def login(name, password):
resp = redirect('/')
try:
salt, hash = db_execute('''
SELECT salt, hash
FROM users
WHERE name = :name
''', name=name)[0]
if hash == salt_hash(salt, password):
token = salt_hash(uuid.uuid4().hex, name)
db_execute('''
UPDATE users
SET session = :token
WHERE name = :name
''', token=token, name=name)
resp.set_cookie('token', token)
return resp
except IndexError as e:
pass
resp.set_cookie('token', '', expires=0)
return resp
def register(name, password):
if '' in (name, password):
return redirect('/')
salt = uuid.uuid4().hex
hash = salt_hash(salt, password)
db_execute("""
INSERT INTO users (name, salt, hash)
VALUES (:name, :salt, :hash)
""", name=name, salt=salt, hash=hash)
return login(name, password)
def logout():
token = request.cookies.get('token')
if token is not None:
db_execute('''
UPDATE users
SET session = NULL
WHERE session = :token
''', token=token)
resp = redirect('/')
resp.set_cookie('token', '', expires=0)
return resp
actions_private = {
'logout': {
'func': logout,
'methods': ['GET'],
},
'vote': {
'func': vote,
'methods': ['POST'],
},
'users': {
'func': users,
'methods': ['GET'],
},
'ladder-user': {
'func': ladder_user,
'methods': ['GET'],
},
}
actions_public = {
'ladder-global': {
'func': ladder_global,
'methods': ['GET'],
},
'register': {
'func': register,
'methods': ['POST'],
},
'login': {
'func': login,
'methods': ['POST'],
},
}
def make_handler(public=True):
actions = actions_public if public else actions_private
def do_stuff(action):
kwargs = dict(request.args.items()) or dict(request.form.items())
try:
if action in actions:
assert request.method in actions[action]['methods']
data = actions[action]['func'](**kwargs) or default_response
if isinstance(data, wrappers.Response):
return data
return jsonify(data)
else:
abort(404)
except Exception as e:
print(e)
abort(403)
return do_stuff