This repository was archived by the owner on Jan 23, 2018. It is now read-only.
forked from dead-repos/op-api
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
154 lines (129 loc) · 4.4 KB
/
app.py
File metadata and controls
154 lines (129 loc) · 4.4 KB
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
147
148
149
150
151
152
153
154
from sanic import Sanic
from sanic import response as res
from sanic import exceptions as exc
import argon2
import random, string, json
app = Sanic('codeecho')
ph = argon2.PasswordHasher()
config = {}
with open("config.json") as data:
config = json.loads(data.read())
data.close()
@app.listener('before_server_start')
def init(sanic, loop):
"""Initialize database before server starts"""
global db
from motor.motor_asyncio import AsyncIOMotorClient
db = AsyncIOMotorClient(
host=config.get('mongo_host', 'localhost'),
port=config.get('mongo_port', 27017)
)[config.get('mongo_db_name', 'codeecho')]
@app.route('/api/auth', methods=['POST'])
async def auth_handler(request):
"""Handles authentication requests"""
req = request.json
if not req:
raise exc.InvalidUsage("Bad request")
# Ensure required data is included in the request
username = req.get('username')
password = req.get('password')
if not (username and password):
raise exc.InvalidUsage("Bad request")
# Ensure user exists in database
user = await db['users'].find_one({ "username": username })
if not user:
raise exc.Forbidden("Invalid credentials")
# Ensure password is correct
try:
ph.verify(user['password'], password)
except argon2.exceptions.VerifyMismatchError:
raise exc.Forbidden("Invalid credentials")
except argon2.exceptions.VerificationError:
raise exc.ServerError("Password verification failed")
return res.json({
"id": str(user['_id']),
"username": user['username'],
"email": user['email'],
"token": user['token']
})
@app.route('/api/user', methods=['POST'])
async def new_user_handler(request):
"""Handles requests for new users"""
req = request.json
if not req:
raise exc.InvalidUsage("Bad request")
# Ensure required data is included in the request
username = req.get('username')
email = req.get('email')
password = req.get('password')
if not (username and email and password):
raise exc.InvalidUsage("Bad request")
# Ensure user does not already exist in database
user = await db['users'].find_one({ "username": username })
if user is not None:
return res.json({ "message": "A user with this username already exists", "status": 409 })
user = await db['users'].find_one({ "email": email })
if user is not None:
return res.json({ "message": "A user with this email already exists", "status": 409 })
# Hash password
hashed_pass = ph.hash(password)
# Generate new token
token = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for i in range(25))
# Insert user into database
user = await db['users'].insert_one({
"username": username,
"email": email,
"password": hashed_pass,
"token": token
})
# Send response
return res.json({
"id": str(user.inserted_id),
"username": username,
"email": email,
"token": token
})
@app.route('/api/user/<user_id:int>', methods=['GET', 'POST'])
async def user_handler(req, user_id):
"""TODO Handles requests for existing users"""
if not user_id:
raise exc.InvalidUsage("Bad request")
#if req.method == 'GET':
raise exc.NotFound("Soon™")
@app.route('/api/repo', methods=['POST'])
async def new_repo_handler(req):
"""TODO New repo"""
raise exc.NotFound("Soon™")
# Existing repo
@app.route('/api/repo/<repo_id:int>', methods=['GET', 'POST', 'DELETE'])
async def repo_handler(req, repo_id):
"""Handles requests for existing repositories"""
if not repo_id:
raise exc.InvalidUsage("Bad request")
# Get repository
if req.method == 'GET':
# TODO auth check
repo = await db['repos'].find_one({ "_id": repo_id })
if not repo:
raise exc.NotFound("Resource not found")
# Temporary confirmation
return res.json({ "message": f"You've requested repository ID {repo_id}" })
# Update repository
elif req.method == 'POST':
repo = await db['repos'].find_one({ "_id": repo_id })
if not repo:
raise exc.Forbidden("Repository doesn't exist")
else:
# TODO Update repo
pass
# Delete repository
elif req.method == 'DELETE':
repo = await db['repos'].find_one({ "_id": repo_id })
if not repo:
raise exc.Forbidden("Repository doesn't exist")
else:
return res.json({ "message": "testing" })
@app.exception(exc.SanicException)
def errors(request, exception):
"""Handles errors"""
return res.json({ "error": exception.args[0], "status": exception.status_code })