This repository has been archived by the owner on Sep 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
180 lines (146 loc) · 5.55 KB
/
main.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import time, os
from db import User, FindBy, Recipe
from functools import wraps
from quart import Quart, render_template as render, g, request, session, redirect, url_for
from reccomend import recommend_recipes
app = Quart(__name__)
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 0
app.secret_key = os.urandom(32)
def login_required(func):
@wraps(func)
async def wrapper(*args, **kwargs):
if not "user" in g:
return redirect(url_for("login") + "?next=" + request.path)
return await func(*args, **kwargs)
return wrapper
@app.before_request
async def before_request():
print(dict(session))
if "uname" in session:
user = User.find_by(FindBy.NAME, session["uname"])
if user and not user.verify_pw(session["passw"]):
g.user = None
print("(!) User password changed, logging out...")
session.clear()
if user:
g.user = user
if "exp" in session and session["exp"] < time.time():
print("(!) User session expired, logging out...")
session.clear()
g.user = None
@app.route("/")
async def index():
return await render("index.html")
@app.get("/auth/login")
async def login():
if "user" in g:
return redirect(url_for("me"))
return await render("auth/login.html")
@app.get("/auth/logout")
@login_required
async def logout():
session.clear()
return redirect(url_for("login"))
@app.post("/auth/login")
async def login_POST():
data = await request.json
user = User.find_by(FindBy.EMAIL, data["email"])
if user is None:
return {"status": "USER_NOT_FOUND", "msg": "User not found"}, 404
if not user.verify_pw(data["password"]):
return {"status": "WRONG_PASSWORD", "msg": "Password incorrect"}, 401
session.update({
"uname": user.uname,
"passw": data["password"],
"exp": (time.time() + 60 * 60 * 24 * 7) if data.get("remember") else (time.time() + 60 * 60)
})
return {"status": "OK"}, 200
@app.get("/auth/signup")
async def signup():
return await render("auth/signup.html")
@app.post("/auth/signup")
async def signup_POST():
data = await request.json
uname, email, password = data.get(
"uname"), data.get("email"), data.get("password")
if not uname or not email or not password:
return {"status": "MISSING_DATA", "msg": "Missing data"}, 400
if len(uname) < 3 or len(uname) > 32:
return {"status": "INVALID_USERNAME", "msg": "Username must be between 3 and 32 characters"}, 400
if User.find_by(FindBy.EMAIL, email):
return {"status": "EMAIL_EXISTS", "msg": "Email already exists"}, 409
if User.find_by(FindBy.NAME, uname):
return {"status": "USERNAME_EXISTS", "msg": "Username already exists"}, 409
if len(password) < 8 or len(password) > 32:
return {"status": "INVALID_PASSWORD", "msg": "Password must be between 8 and 32 characters"}, 400
user = User.create_new(
uname=uname,
email=email,
passw=password
)
session.update({
"uname": user.uname,
"passw": password,
"exp": (time.time() + 60 * 60 * 24 * 7) if data.get("remember") else (time.time() + 60 * 60)
})
return {"status": "OK"}, 200
@app.get("/@user")
@login_required
async def me():
return await render("user/index.html")
@app.get("/@user/recipes/create")
@login_required
async def create():
new_recipe = Recipe.create_new(g.user._id, "New Recipe", "New Recipe Description", ingredients=[
], steps=["Step 1", "Step 2", "Step 3"])
return redirect(url_for("recipe", recipe_id=new_recipe._id))
@app.get("/@user/recipes/browse")
@login_required
async def browse():
if request.args.get("term"):
return await render("user/browse.html", recipes=Recipe.search(request.args.get("term")))
return await render("user/browse.html")
@app.get("/@user/recipes/<recipe_id>")
@app.get("/@user/recipes/<recipe_id>/view")
@login_required
async def view_recipe(recipe_id: str):
return await render("user/recipe.html", recipe=Recipe.find(recipe_id))
@app.get("/@user/recipes/<recipe_id>/recommendations")
@login_required
async def recommend_recipe(recipe_id: str):
recipe: Recipe = Recipe.find(recipe_id)
return await render("user/recommend.html", recipe=recipe, recipes=recommend_recipes(
recipe, Recipe.find_all(), 50
))
@app.get("/@user/recipes/<recipe_id>/edit")
@login_required
async def edit_recipe(recipe_id: str):
return await render("user/edit.html", recipe=Recipe.find(recipe_id))
@app.post("/@user/recipes/<recipe_id>/edit/general")
@login_required
async def recipe_POST(recipe_id: str):
data = await request.json
recipe = Recipe.find(recipe_id)
if recipe is None:
return {"status": "NOT_FOUND", "msg": "Recipe not found"}, 404
elif recipe.owner != g.user._id:
return {"status": "FORBIDDEN", "msg": "You can't edit this recipe"}, 403
recipe.name = data["name"]
recipe.desc = data["desc"]
recipe.update()
return {"status": "OK"}, 200
@app.post("/@user/recipes/<recipe_id>/edit/data")
@login_required
async def recipe_edit_POST(recipe_id: str):
data = await request.json
recipe = Recipe.find(recipe_id)
if recipe is None:
return {"status": "NOT_FOUND", "msg": "Recipe not found"}, 404
elif recipe.owner != g.user._id:
return {"status": "FORBIDDEN", "msg": "You can't edit this recipe"}, 403
recipe.ingredients = data["ingredients"]
recipe.steps = data["steps"]
recipe.update()
return {"status": "OK"}, 200
if __name__ == "__main__":
app.run(host="localhost", port=8000, debug=True)