This repository has been archived by the owner on Jun 28, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.py
261 lines (191 loc) · 7.04 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
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
from datetime import datetime
from typing import Optional
from flask import Flask, request, redirect
from src.user import User
from src.meetup import Meetup
from src.usercollection import UserCollection
from src.meetupcollection import MeetupCollection
from src.utility.api import require_user_auth, require_form_entries
from src.utility.general import is_email
from src.utility.storage import Storage
app = Flask(__name__)
storage = Storage("data/data.json")
def mutate_uc(
uc: UserCollection): storage["user-collection"] = uc.to_dict(False)
def mutate_mc(
mc: MeetupCollection): storage["meetup-collection"] = mc.to_dict(False, True)
uc = UserCollection.load(storage, on_mutation=mutate_uc)
mc = MeetupCollection.load(storage, uc, on_mutation=mutate_mc)
@app.get("/")
def default() -> str:
return "ok"
@app.post("/account/register")
@require_form_entries("name", "password", "email-address")
def register(name: str, password: str, email_address: str) -> str | tuple:
"""
register a new user
:param name: the name of the registering user
:param password: the password of the registering user
:param email_address: the email address of the registering user,
which should has to be unique to the ones of other registered user:
"""
if not is_email(email_address):
return "Invalid email address", 400
if not (uc.by_email_address(email_address) is None):
return "Email already in use", 400
user = User(name, password, email_address)
user.generate_token()
uc.append(user)
return {"id": user.id, "token": user.token}
@app.post("/account/login")
@require_form_entries("email-address", "password")
def login(email_address: str, password: str) -> str | tuple:
"""
log in an already existing user
:param email_address: the user's email address
:param password: the (unhashed/plain) password of the user
"""
user = uc.by_email_address(email_address)
if not (user is None) and user.verify(password):
user.generate_token()
return {"id": user.id, "token": user.token}
else:
return "Wrong Credentials", 401
@app.delete("/account")
@require_user_auth(uc)
def delete_account(user: User) -> str | tuple:
"""
delete a user's account
:param user: the user to delete
"""
uc.remove(user)
return "ok"
@app.get("/user/me")
@require_user_auth(uc)
def get_me(me: User) -> dict:
"""
get information about the logged in user
:param me: the logged in user
"""
return me.to_dict()
@app.get("/user/<user_id>")
@require_user_auth(uc)
def get_user(_, user_id: str) -> dict:
"""
get information about a certain user
:param user_id: the id of the user to get information about
"""
user = uc.by_id(user_id)
if user is None:
return "User not found", 404
return user.to_dict()
@app.post("/meetup")
@require_form_entries("datetime", "location")
@require_user_auth(uc)
def create_meetup(user: User, timestamp: str, location: str) -> str | tuple:
"""
create a new meetup
:param user: the user which wants create the meetup
:param timestamp: the date/time when the meetup should take place, in the unix time format
:param location: the location where the meetup should take place, in a google maps compatible format
"""
meetup = Meetup(user, datetime.fromtimestamp(int(timestamp)), location)
if meetup.datetime < datetime.now():
return "Meetup can not be set in past", 400
else:
mc.append(meetup)
return meetup.id.hex
@app.get("/meetup")
@require_user_auth(uc)
def get_users_meetups(user: User) -> list[str]:
"""
get the meetups in which the user is a member
:param user: the user which is supposed to appear as a member in the meetups
"""
return {"meetups": list(map(lambda x: str(x.id), mc.with_member(user)))}
@app.get("/meetup/<meetup_id>")
@require_user_auth(uc)
def get_meetup(user: User, meetup_id: str) -> str:
"""
get information about a certain meetup, if the user is a member of it
:param user: the user that wants to get the information
:param meetup_id: the id of the meetup
"""
meetup = mc.by_id(meetup_id)
if meetup is None:
return f'The meetup id "{meetup_id}" does not exist', 404
if meetup.is_member(user):
return meetup.to_dict()
else:
return "You are not a member of this meetup", 401
@app.get("/meetup/<meetup_id>/join")
def join_meetup_in_app(meetup_id: str) -> str:
return redirect(f"puncty://join/{meetup_id}", code=302)
@app.put("/meetup/<meetup_id>/join")
@require_user_auth(uc)
def join_meetup(user: User, meetup_id: str) -> str:
"""
join a certain meetup
:param user: the user that wants to join the meetup
:param meetup_id: the id of the meetup to join
"""
meetup = mc.by_id(meetup_id)
if meetup is None:
return f"The meetup id {meetup_id} does not exist", 404
meetup.join(user)
# TODO: implement inside Meetup
mutate_mc(mc)
return meetup.to_dict()
@app.put("/meetup/<meetup_id>/leave")
@require_user_auth(uc)
def leave_meetup(user: User, meetup_id: str) -> str:
"""
leave a certain meetup
:param user: the user that wants to leave
:param meetup_id: the id of the meetup to leave
"""
meetup = mc.by_id(meetup_id)
if meetup is None:
return f"The meetup id {meetup_id} does not exist", 404
meetup.leave(user)
# TODO: implement inside Meetup
mutate_mc(mc)
return "ok"
@app.patch("/meetup/<meetup_id>")
@require_user_auth(uc)
def edit_meetup(user: User, meetup_id: str) -> tuple | dict:
"""
edit the properties of a certain meetup
:param user: the user to edit the meetup, which has to be it's admin
:param meetup_id: the id of the meetup to edit
"""
meetup = mc.by_id(meetup_id)
if meetup is None:
return f"The meetup id {meetup_id} does not exist", 404
if user != meetup.admin:
return "You are not the admin of the meeting", 401
meetup.datetime = request.form["datetime"] if "datetime" in request.form else meetup.datetime
meetup.location = request.form["location"] if "location" in request.form else meetup.location
new_admin_id = request.form["admin"] if "admin" in request.form else None
if new_admin_id and (new_admin := uc.by_id(new_admin_id)) and meetup.is_member(new_admin):
meetup.admin = new_admin
# TODO: implement inside Meetup
mutate_mc(mc)
return meetup.to_dict()
@app.delete("/meetup/<meetup_id>")
@require_user_auth(uc)
def delete_meetup(user: User, meetup_id: str) -> Optional[tuple]:
"""
delete a certain meetup if the user is the admin of it
:param user: the user, which has to be the admin of the meetup
:param meetup_id: the id of the meetup to delete
"""
meetup = mc.by_id(meetup_id)
if meetup is None:
return f"The meetup id {meetup_id} does not exist", 404
if user != meetup.admin:
return "You are not the admin of the meeting", 401
mc.remove(meetup)
return "ok"
if __name__ == "__main__":
app.run("localhost", "8002")