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 pathdb.py
142 lines (113 loc) · 3.66 KB
/
db.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
from os import getenv
from enum import Enum
from bcrypt import hashpw, gensalt, checkpw
from pymongo import MongoClient
from bson.objectid import ObjectId
from dataclasses import dataclass
from typing import List, Literal
from re import compile, IGNORECASE
from dotenv import load_dotenv
load_dotenv()
conn = MongoClient(getenv("MONGO_URI"))
db = conn.FoodTracker
users = db.users
recipes = db.recipes
def oid(data: str):
return data if isinstance(data, ObjectId) else ObjectId(data)
@dataclass
class Ingredient:
name: str
amount: str
unit: str
@classmethod
def from_dict(cls, data):
return cls(**data)
def to_dict(self):
return self.__dict__
@dataclass
class Recipe:
_id: ObjectId
owner: ObjectId
name: str
desc: str
ingredients: List[Ingredient]
steps: list
@classmethod
def from_dict(cls, data):
return cls(**data)
def to_dict(self, convert: bool = None):
if convert is True:
return {**self.__dict__, "_id": str(self._id), "owner": str(self.owner)}
return self.__dict__
@classmethod
def find(cls, _id: ObjectId):
recipe = recipes.find_one({"_id": oid(_id)})
if not recipe:
return None
return cls.from_dict(recipe)
@classmethod
def find_all(cls):
return [cls.from_dict(data) for data in recipes.find({})]
def update(self):
recipes.update_one({"_id": self._id}, {"$set": self.to_dict()})
@classmethod
def create_new(cls, owner: ObjectId, name: str, desc: str, ingredients: list, steps: list):
data = recipes.insert_one({"owner": owner, "name": name, "desc": desc, "ingredients": ingredients, "steps": steps})
return cls.find(data.inserted_id)
def get_url(self, type: Literal["edit", "view"]):
return f"/@user/recipes/{self._id}/edit"
@staticmethod
def search(term: str):
term = compile(term, IGNORECASE)
return [Recipe.from_dict(data) for data in recipes.find({"name": term})]
def delete(self):
recipes.delete_one({"_id": self._id})
class FindBy(Enum):
ID = 1
NAME = 2
EMAIL = 3
@dataclass
class User:
_id: ObjectId
uname: str
passw: str
email: str
def get_reciepies(self):
return [Recipe.from_dict(data) for data in recipes.find({"owner": self._id})]
@classmethod
def from_dict(cls, data):
return cls(**data)
def to_dict(self):
return self.__dict__
@classmethod
def find_by(cls, find_by: FindBy, value: str):
user = None
match find_by:
case FindBy.ID:
user = users.find_one({"_id": ObjectId(value)})
case FindBy.NAME:
user = users.find_one({"uname": value})
case FindBy.EMAIL:
user = users.find_one({"email": value.lower()})
if not user:
return None
return cls.from_dict(user)
@staticmethod
def _hash_pw(passw: str):
return hashpw(passw.encode("utf-8"), gensalt()).decode("utf-8")
def verify_pw(self, passw: str):
return checkpw(passw.encode("utf-8"), self.passw.encode("utf-8"))
@classmethod
def create_new(cls, uname: str, passw: str, email: str):
data = users.insert_one({"uname": uname.lower(), "passw": cls._hash_pw(passw), "email": email.lower()})
return cls(data.inserted_id, uname, passw, email)
if __name__ == "__main__":
# testing
found = []
reps = list(Recipe.find_all())
for recipe in reps:
if recipe.name in found:
print("DUPLICATE")
else:
found.append(recipe.name)
print(len(reps) - len(found))