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
|
from flask import request
from auth.login_token import token_login
from db import cursor
from util import all_def, all_notdef
import valid
ranks = ["none", "user", "moderator", "admin", "bot"]
def util_two_person(func):
'''
! only used internally !
func(token_id?: str, explicit_id?: str)
This decorator doesn't check for hierarchy constraints, but does
make sure that token_id or explicit_id are valid user_id's
'''
def wrapper():
token_id = None
explicit_id = None
token = request.cookies.get("token") or ""
if token: token_id = token_login(token)
data = request.get_json()
if data: explicit_id = data.get("id")
if explicit_id and not valid.user_id(explicit_id): explicit_id = None
return func(token_id, explicit_id)
wrapper.__name__ = func.__name__
return wrapper
def two_person(func):
'''
endpoint should have two parameters:
endpoint(user_1_id: str, user_2_id: str)
no authentication, just runs endpoint() if both token_id and
explicit_id are present from @util_two_person.
'''
@util_two_person
def wrapper(token_id, explicit_id):
if not all_def([token_id, explicit_id]):
return "", 400
return func(token_id, explicit_id)
wrapper.__name__ = func.__name__
return wrapper
def one_person(func):
'''
endpoint should have two parameters:
endpoint(user_id: str, viewer?: str)
uses json data id with token_login id as fallback
doesn't check for authentication
expects that func takes these arguments: (user_id, viewer?)
'''
@util_two_person
def wrapper(token_id, explicit_id):
if all_notdef([token_id, explicit_id]):
return "", 400
return func(explicit_id or token_id, token_id)
wrapper.__name__ = func.__name__
return wrapper
def auth_required(level):
'''
level = "none" | "user" | "moderator" | "admin" | "bot"
endpoint should have one parameter for the user_id of the request author:
endpoint(user_id: str) # `user_id` can only be `None` when `level == "none"`
@auth_required function decorator (use after @flask.Blueprint.route() decorator)
This decorator only runs endpoint() if token_id from
@util_two_person is not None and passes hierarchy constraints
'''
def decorator(func):
@util_two_person
def wrapper(token_id, explicit_id):
if not token_id:
if level == ranks[0]:
return func(None)
else:
return "", 400
user_rank_text = cursor.execute(
"select type from users where user_id = ?", [token_id]
).fetchone()[0]
required_rank = ranks.index(level)
user_rank = ranks.index(user_rank_text)
if required_rank > user_rank: return "", 403
return func(token_id)
wrapper.__name__ = func.__name__
return wrapper
return decorator
|