1
|
|
|
""" |
2
|
|
|
Main file for the API |
3
|
|
|
""" |
4
|
|
|
import datetime |
5
|
|
|
import json |
6
|
|
|
import secrets |
7
|
|
|
import os |
8
|
|
|
from typing import List |
9
|
|
|
import functools |
10
|
|
|
|
11
|
|
|
from fastapi import FastAPI, HTTPException |
12
|
|
|
from pydantic import BaseModel |
13
|
|
|
from pymongo import MongoClient |
14
|
|
|
from fastapi.responses import JSONResponse |
15
|
|
|
|
16
|
|
|
# Take the url for connection to MongoDB |
17
|
|
|
urlMongo = os.getenv('MONGO_URL') |
18
|
|
|
|
19
|
|
|
# Init the client of Mongo |
20
|
|
|
client = MongoClient(urlMongo) |
21
|
|
|
|
22
|
|
|
db = client.virgilUsers |
23
|
|
|
users_collection = db.users |
24
|
|
|
users_collection.create_index("userId", unique=True) |
25
|
|
|
calendar_collection = db.calendarEvent |
26
|
|
|
|
27
|
|
|
app = FastAPI() |
28
|
|
|
|
29
|
|
|
# Take the base of setting |
30
|
|
|
@functools.lru_cache(maxsize=None) |
31
|
|
|
def get_cached_setting(): |
32
|
|
|
""" |
33
|
|
|
Get all settings from database and cache it in memory |
34
|
|
|
|
35
|
|
|
Returns: |
36
|
|
|
json: The default settings |
37
|
|
|
""" |
38
|
|
|
with open('setting.json', 'r',encoding='utf-8') as file: |
39
|
|
|
return json.load(file) |
40
|
|
|
|
41
|
|
|
# Modifica la chiamata nel codice originale |
42
|
|
|
setting = get_cached_setting() |
43
|
|
|
|
44
|
|
|
# User Model |
45
|
|
|
class User(BaseModel): |
46
|
|
|
""" |
47
|
|
|
User model used in this API |
48
|
|
|
|
49
|
|
|
Args: |
50
|
|
|
BaseModel (Class): The base model |
51
|
|
|
""" |
52
|
|
|
userId: str |
53
|
|
|
setting: dict |
54
|
|
|
|
55
|
|
|
# Event Model |
56
|
|
|
class Event(BaseModel): |
57
|
|
|
""" |
58
|
|
|
Event model used in this API |
59
|
|
|
|
60
|
|
|
Args: |
61
|
|
|
BaseModel (Class): The base model |
62
|
|
|
""" |
63
|
|
|
date: str |
64
|
|
|
events: dict |
65
|
|
|
|
66
|
|
|
|
67
|
|
|
# ---------- USER FUNCTION ---------- |
68
|
|
|
|
69
|
|
|
@app.get('/api/setting/{id_user}/', response_model=User) |
70
|
|
|
def get_user_settings(id_user: str): |
71
|
|
|
""" |
72
|
|
|
A function to bring the user's setting through the generated key to Virgilio. |
73
|
|
|
|
74
|
|
|
Raises: |
75
|
|
|
HTTPException: Error |
76
|
|
|
Returns: |
77
|
|
|
JsonResponse: the result of request |
78
|
|
|
""" |
79
|
|
|
result = users_collection.find_one({"userId": str(id_user)}, {"_id": 0, "userId": 0}) |
80
|
|
|
if result is None: |
81
|
|
|
raise HTTPException(status_code=404, detail="User not found") |
82
|
|
|
user_dict = dict(result) |
83
|
|
|
return JSONResponse(content=user_dict, status_code=200) |
84
|
|
|
|
85
|
|
|
def check_email_pass(list_of_events): |
86
|
|
|
""" |
87
|
|
|
A function that checks whether a list contains an email and password or not |
88
|
|
|
|
89
|
|
|
Args: |
90
|
|
|
list (list): An list of data |
91
|
|
|
|
92
|
|
|
Returns: |
93
|
|
|
bool: False or None |
94
|
|
|
""" |
95
|
|
|
for i in list_of_events: |
96
|
|
|
if i == "": |
97
|
|
|
return False |
98
|
|
|
|
99
|
|
|
@app.post('/api/setting/modify/{id_user}/', response_model=User) |
100
|
|
|
def new_setting(id_user: str, new_setting: dict): |
101
|
|
|
""" |
102
|
|
|
This function updates all the setting of Virgil specifying the key of the user and |
103
|
|
|
sends a payload in json and skips the empty values. |
104
|
|
|
|
105
|
|
|
Returns: |
106
|
|
|
dict: Json format file |
107
|
|
|
""" |
108
|
|
|
updates = {f"setting.{key}": value for key, value in new_setting.items() if value != ""} |
109
|
|
|
query = {"userId": str(id_user)} |
110
|
|
|
value = {"$set": updates} |
111
|
|
|
users_collection.update_many(query, value) |
112
|
|
|
return get_user_settings(id_user) |
113
|
|
|
|
114
|
|
|
|
115
|
|
|
# ---- CALENDAR ---- |
116
|
|
|
@app.put('/api/createUser', response_model=User, status_code=201) |
117
|
|
|
def create_user(): |
118
|
|
|
""" |
119
|
|
|
This function creates a new user which is entered into the database by the |
120
|
|
|
simple random key generated randomly and the setting base |
121
|
|
|
|
122
|
|
|
Returns: |
123
|
|
|
dict: The dict with the user id and the settings |
124
|
|
|
""" |
125
|
|
|
|
126
|
|
|
key = secrets.token_hex(16) |
127
|
|
|
users_collection.insert_one({ |
128
|
|
|
"userId": key, |
129
|
|
|
"setting": setting |
130
|
|
|
}) |
131
|
|
|
|
132
|
|
|
return {"userId": key, "setting": setting} |
133
|
|
|
|
134
|
|
|
# ---------- CALENDAR FUNCTION ---------- |
135
|
|
|
|
136
|
|
|
@app.get('/api/calendar/{id_user}/', response_model=dict) |
137
|
|
|
def get_events(id_user: str): |
138
|
|
|
""" |
139
|
|
|
Get all the events from a user by the id |
140
|
|
|
|
141
|
|
|
Args: |
142
|
|
|
id (str): The id of user |
143
|
|
|
|
144
|
|
|
Raises: |
145
|
|
|
HTTPException: _description_ |
146
|
|
|
|
147
|
|
|
Returns: |
148
|
|
|
list: List of events from the user |
149
|
|
|
""" |
150
|
|
|
result = calendar_collection.find_one({"userId": str(id_user)},{"_id":0,"userId":0}) |
151
|
|
|
if result is None: |
152
|
|
|
raise HTTPException(status_code=404, detail="User not found") |
153
|
|
|
return result |
154
|
|
|
|
155
|
|
|
@app.put('/api/calendar/createUser/{id_user}/', status_code=201) |
156
|
|
|
def create_user_calendar(id_user: str): |
157
|
|
|
""" |
158
|
|
|
Create the profile in the db for manage the events of a user |
159
|
|
|
|
160
|
|
|
Args: |
161
|
|
|
id (str): id of user |
162
|
|
|
|
163
|
|
|
Returns: |
164
|
|
|
id_user: the id of user |
165
|
|
|
""" |
166
|
|
|
calendar_collection.insert_one({"userId": id_user}) # Prepare the user for give event |
167
|
|
|
return id_user |
168
|
|
|
|
169
|
|
|
@app.put('/api/calendar/createEvent/{id_user}/{date}/', status_code=201) |
170
|
|
|
def create_event(id_user: str, date: str, events: List[str]): |
171
|
|
|
# Cambiato events: Event a events: List[str] |
172
|
|
|
""" |
173
|
|
|
Create an event to save it into the database |
174
|
|
|
|
175
|
|
|
Args: |
176
|
|
|
id (str): The id of user |
177
|
|
|
date (str): the date of events |
178
|
|
|
events (List[str]): the description of events |
179
|
|
|
|
180
|
|
|
Returns: |
181
|
|
|
dict: The final result of modify |
182
|
|
|
""" |
183
|
|
|
|
184
|
|
|
result = calendar_collection.find_one({"userId": id_user}, {date: 1}) |
185
|
|
|
query = {"userId": id_user} |
186
|
|
|
if result is None or date not in result: |
187
|
|
|
# Utilizziamo direttamente il payload JSON per l'aggiornamento |
188
|
|
|
value = {"$set": {date: events}} |
189
|
|
|
result = calendar_collection.update_one(query, value) |
190
|
|
|
else: |
191
|
|
|
# Utilizziamo direttamente il payload JSON per l'aggiornamento |
192
|
|
|
value = {"$addToSet": {date: {"$each": events}}} |
193
|
|
|
result = calendar_collection.update_many(query, value) # Aggiungi evento |
194
|
|
|
return value |
195
|
|
|
|
196
|
|
|
|
197
|
|
|
def get_formatted_date(): |
198
|
|
|
""" |
199
|
|
|
Get today's format date |
200
|
|
|
|
201
|
|
|
Returns: |
202
|
|
|
str: The date formatted |
203
|
|
|
""" |
204
|
|
|
today = datetime.datetime.today() |
205
|
|
|
yesterday = today.date() + datetime.timedelta(days=-1) |
206
|
|
|
yesterday = yesterday.strftime("%d-%m-%Y") |
207
|
|
|
yesterday = yesterday.split("-") |
208
|
|
|
yesterday[1] = int(yesterday[1]) |
209
|
|
|
yesterday[1] = str(yesterday[1]) |
210
|
|
|
yesterday[0] = int(yesterday[0]) |
211
|
|
|
yesterday[0] = str(yesterday[0]) |
212
|
|
|
yesterday = "-".join(yesterday) |
213
|
|
|
|
214
|
|
|
return yesterday |
215
|
|
|
|
216
|
|
|
@app.put('/api/calendar/deleteEvent/{id_user}/', status_code=201) |
217
|
|
|
def delete_event(id_user: str): |
218
|
|
|
""" |
219
|
|
|
Delete all old events from the day and update the collection |
220
|
|
|
|
221
|
|
|
Args: |
222
|
|
|
id (str): id of user |
223
|
|
|
|
224
|
|
|
Returns: |
225
|
|
|
dict:Element deleted |
226
|
|
|
""" |
227
|
|
|
yesterday = get_formatted_date() |
228
|
|
|
result = calendar_collection.find_one({"userId": id_user}) |
229
|
|
|
query = {"userId": id_user} |
230
|
|
|
if result is None or yesterday not in result: |
231
|
|
|
return {"Delete": "No events yesterday"}, 202 |
232
|
|
|
value = {"$unset": {yesterday: 1}} |
233
|
|
|
result = calendar_collection.update_one(query, value) # Add event |
234
|
|
|
return value |
235
|
|
|
|