Skip to content

Commit 24ef302

Browse files
committed
Added tags table + creation
1 parent 7c91fe0 commit 24ef302

File tree

6 files changed

+116
-31
lines changed

6 files changed

+116
-31
lines changed

PyMatcha.postman_collection.json

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,7 @@
11801180
"",
11811181
"tests[\"Is email correct\"] = response.email == user_email",
11821182
"tests[\"Is username correct\"] = response.username == user_username",
1183+
"tests[\"Are tags present\"] = response.tags.length == 7",
11831184
"",
11841185
"pm.collectionVariables.set(\"user_id\", response.id)"
11851186
],
@@ -1318,7 +1319,7 @@
13181319
"header": [],
13191320
"body": {
13201321
"mode": "raw",
1321-
"raw": "{\n\t\"orientation\": \"heterosexual\",\n\t\"bio\": \"Nunc faucibus velit metus, nec iaculis sem fringilla ut. Nullam vel vulputate diam. Vivamus vehicula, enim at hendrerit tincidunt, leo sapien maximus nisi, nec suscipit arcu nisi a turpis. Suspendisse rutrum quis quam et sollicitudin. Proin commodo justo non dui tempor, at maximus velit vulputate. Integer vitae porta nulla, ut congue est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin purus ex, venenatis vel aliquet a, interdum sit amet quam. Donec ac volutpat dui. In ornare augue in nisi efficitur varius. Donec hendrerit nunc a pulvinar posuere. Donec malesuada eros quam, eget pharetra nunc elementum in.\"\n}",
1322+
"raw": "{\n\t\"orientation\": \"heterosexual\",\n\t\"bio\": \"Nunc faucibus velit metus, nec iaculis sem fringilla ut. Nullam vel vulputate diam. Vivamus vehicula, enim at hendrerit tincidunt, leo sapien maximus nisi, nec suscipit arcu nisi a turpis. Suspendisse rutrum quis quam et sollicitudin. Proin commodo justo non dui tempor, at maximus velit vulputate. Integer vitae porta nulla, ut congue est. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin purus ex, venenatis vel aliquet a, interdum sit amet quam. Donec ac volutpat dui. In ornare augue in nisi efficitur varius. Donec hendrerit nunc a pulvinar posuere. Donec malesuada eros quam, eget pharetra nunc elementum in.\",\n\t\"tags\": [\n\t\t\"bot\",\n\t\t\"robot\",\n\t\t\"postman\",\n\t\t\"sex\",\n\t\t\"friends\",\n\t\t\"drink\",\n\t\t\"smoke\"\n\t\t]\n}",
13221323
"options": {
13231324
"raw": {
13241325
"language": "json"
@@ -1494,67 +1495,67 @@
14941495
],
14951496
"variable": [
14961497
{
1497-
"id": "f4dd475b-c423-4497-a1d7-826619651283",
1498+
"id": "b1180951-59af-4533-b1ef-89cba4c3a87b",
14981499
"key": "host",
14991500
"value": "http://127.0.0.1:5000",
15001501
"type": "string"
15011502
},
15021503
{
1503-
"id": "8d82efce-58a4-4ae6-be77-3f9a94c64aa4",
1504+
"id": "1515f3bd-a9b1-4a08-9c0f-21aa1933edc0",
15041505
"key": "user_id",
15051506
"value": "",
15061507
"type": "string"
15071508
},
15081509
{
1509-
"id": "54e97677-add0-44ce-b4de-08e78149669d",
1510+
"id": "0894f3b3-3d31-4bd0-a1b8-ab95c8078037",
15101511
"key": "user_email",
15111512
"value": "foo@example.org",
15121513
"type": "string"
15131514
},
15141515
{
1515-
"id": "f13b4302-ae17-4f05-bd3d-0092d7d0e988",
1516+
"id": "5211c78f-5d86-4bba-bf5e-e5654918b50d",
15161517
"key": "user_username",
15171518
"value": "bar",
15181519
"type": "string"
15191520
},
15201521
{
1521-
"id": "b71e8f9f-9932-4c65-b1b8-88bbe02146c2",
1522+
"id": "de2fec5e-d349-4fa4-bf7f-fae061264a71",
15221523
"key": "user_password",
15231524
"value": "admin",
15241525
"type": "string"
15251526
},
15261527
{
1527-
"id": "d567e6be-d3ae-418d-bc4a-a2b8ec7971a3",
1528+
"id": "c3ce41b9-6851-477f-b745-66b427934bc8",
15281529
"key": "user_firstname",
15291530
"value": "Foo",
15301531
"type": "string"
15311532
},
15321533
{
1533-
"id": "9f99c685-7bf2-4774-b694-c3fcebb92b84",
1534+
"id": "a25c1222-84ea-4d47-b8d3-f22a54d1d49f",
15341535
"key": "user_lastname",
15351536
"value": "Bar",
15361537
"type": "string"
15371538
},
15381539
{
1539-
"id": "34adee57-0702-4c96-9efb-58a80542d55d",
1540+
"id": "0568293c-5883-41e1-a684-f6dbaaf73623",
15401541
"key": "debug_token",
15411542
"value": "xX69jules69Xx",
15421543
"type": "string"
15431544
},
15441545
{
1545-
"id": "dcd1f01b-44a4-4750-a05c-af21292576b6",
1546+
"id": "aa8e48a3-11c0-48d9-bdab-4887c1d5b121",
15461547
"key": "user_access_token",
15471548
"value": "",
15481549
"type": "string"
15491550
},
15501551
{
1551-
"id": "633549e9-b8aa-42ed-8178-6a91d38961b8",
1552+
"id": "08788a8b-e5db-4841-9021-3f95c4fc0607",
15521553
"key": "user_refresh_token",
15531554
"value": "",
15541555
"type": "string"
15551556
},
15561557
{
1557-
"id": "b712d83c-9221-4571-9945-6fc52fcd167f",
1558+
"id": "26e146a6-35e0-4436-a1d5-bacc245090b3",
15581559
"key": "expired_token",
15591560
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1OTAyNDIyNjQsIm5iZiI6MTU5MDI0MjI2NCwianRpIjoiNTM0ZGI5NzQtOWE4Ni00MGViLWE1NDEtMDg3N2ZmNzQ3NDVhIiwiZXhwIjoxNTkwMjQyMzI0LCJpZGVudGl0eSI6eyJpZCI6NTEyLCJlbWFpbCI6ImZvb0BleGFtcGxlLm9yZyIsInVzZXJuYW1lIjoiYmFyIiwiaXNfb25saW5lIjp0cnVlLCJkYXRlX2xhc3RzZWVuIjoiU2F0LCAyMyBNYXkgMjAyMCAxMzo1Nzo0NCBHTVQifSwiZnJlc2giOnRydWUsInR5cGUiOiJhY2Nlc3MifQ.NTp2P0WNkXDwzuzrcNIQdeAfizQ57HQgkzBLSvY1yHU",
15601561
"type": "string"

backend/PyMatcha/models/tag.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
PyMatcha - A Python Dating Website
3+
Copyright (C) 2018-2019 jlasne/gmorer
4+
<jlasne@student.42.fr> - <gmorer@student.42.fr>
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU General Public License for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
"""
19+
from __future__ import annotations
20+
21+
import logging
22+
from typing import Dict
23+
24+
from PyMatcha.utils import create_tags_table
25+
from PyMatcha.utils.orm import Field
26+
from PyMatcha.utils.orm import Model
27+
28+
29+
class Tag(Model):
30+
table_name = "tags"
31+
32+
id = Field(int, modifiable=False)
33+
user_id = Field(int)
34+
name = Field(str)
35+
36+
def before_init(self, data):
37+
pass
38+
39+
@staticmethod
40+
def create(user_id: int, name="") -> Tag:
41+
new_tag = Tag(user_id=user_id, name=name)
42+
new_tag.save()
43+
logging.debug("Creating new tag")
44+
return new_tag
45+
46+
def get_all_info(self) -> Dict:
47+
return {"id": self.id, "user_id": self.user_id, "name": self.name}
48+
49+
@classmethod
50+
def create_table(cls):
51+
create_tags_table(cls.db)

backend/PyMatcha/models/user.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import datetime
2222
import hashlib
23-
import json
2423
import logging
2524
from typing import Any
2625
from typing import Dict
@@ -31,6 +30,7 @@
3130
import PyMatcha.models.user_image as user_image
3231
from PyMatcha.errors import ConflictError
3332
from PyMatcha.errors import NotFoundError
33+
from PyMatcha.models.tag import Tag
3434
from PyMatcha.utils import create_user_table
3535
from PyMatcha.utils import hash_password
3636
from PyMatcha.utils.orm import Field
@@ -53,7 +53,6 @@ class User(Model):
5353
orientation = Field(str)
5454
birthdate = Field(datetime.date)
5555
geohash = Field(str)
56-
tags = Field(dict)
5756
heat_score = Field(int)
5857
is_online = Field(bool)
5958
date_joined = Field(datetime.datetime, fmt="%Y-%m-%d %H:%M:%S")
@@ -86,7 +85,6 @@ def create(
8685
orientation: str,
8786
birthdate: datetime.date,
8887
geohash: str,
89-
tags,
9088
heat_score: int = 0,
9189
is_online: bool = False,
9290
date_joined: datetime.datetime = datetime.datetime.utcnow(),
@@ -135,8 +133,6 @@ def create(
135133
logging.error("Geohash error: {}".format(e))
136134
raise e
137135

138-
# TODO: Check if all tags are set in tags
139-
140136
# Encrypt password
141137
password = hash_password(password)
142138

@@ -151,7 +147,6 @@ def create(
151147
orientation=orientation,
152148
birthdate=birthdate,
153149
geohash=geohash,
154-
tags=str(json.dumps(tags)),
155150
heat_score=heat_score,
156151
is_online=is_online,
157152
date_joined=date_joined,
@@ -199,7 +194,6 @@ def register(email: str, username: str, password: str, first_name: str, last_nam
199194
orientation="bisexual",
200195
birthdate=None,
201196
geohash=None,
202-
tags="",
203197
heat_score=0,
204198
is_online=False,
205199
date_joined=datetime.datetime.utcnow(),
@@ -220,21 +214,19 @@ def get_all_info(self) -> Dict:
220214
"last_name": self.last_name,
221215
"email": self.email,
222216
"username": self.username,
223-
"password": self.password,
224217
"bio": self.bio,
225218
"gender": self.gender,
226219
"orientation": self.orientation,
227220
"birthdate": self.birthdate,
228221
"geohash": self.geohash,
229-
"tags": json.loads(self.tags) if self.tags else "", # TODO: Optimize this
222+
"tags": [t.name for t in self.get_tags()],
230223
"heat_score": self.heat_score,
231224
"is_online": self.is_online,
232225
"date_joined": self.date_joined,
233226
"date_lastseen": self.date_lastseen,
234227
"is_profile_completed": self.is_profile_completed,
235228
"is_confirmed": self.is_confirmed,
236229
"confirmed_on": self.confirmed_on,
237-
"previous_reset_token": self.previous_reset_token,
238230
}
239231

240232
@classmethod
@@ -250,7 +242,7 @@ def get_images(self) -> List[UserImage]:
250242
user_images.timestamp as timestamp, user_images.is_primary as is_primary
251243
FROM users
252244
INNER JOIN user_images on users.id = user_images.user_id
253-
WHERE users.id = CAST({} AS INT)
245+
WHERE users.id = CAST({} AS UNSIGNED)
254246
""".format(
255247
self.id
256248
)
@@ -270,6 +262,25 @@ def get_base_info(self):
270262
"date_lastseen": self.date_lastseen,
271263
}
272264

265+
def get_tags(self):
266+
logging.debug("Getting all tags for user {}".format(self.id))
267+
with self.db.cursor() as c:
268+
c.execute(
269+
"""
270+
SELECT tags.id as id, tags.user_id as user_id, tags.name as name
271+
FROM users
272+
INNER JOIN tags on users.id = tags.user_id
273+
WHERE users.id = CAST({} AS UNSIGNED)
274+
""".format(
275+
self.id
276+
)
277+
)
278+
tags = c.fetchall()
279+
tags_list = []
280+
for t in tags:
281+
tags_list.append(Tag(t))
282+
return tags_list
283+
273284

274285
def get_user(uid: Any[int, str]) -> Optional[User]:
275286
not_found = 0

backend/PyMatcha/routes/api/profile.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from flask import Blueprint
2222
from flask import request
2323
from PyMatcha.errors import BadRequestError
24+
from PyMatcha.models.tag import Tag
2425
from PyMatcha.success import Success
2526
from PyMatcha.utils.decorators import validate_params
2627

@@ -29,11 +30,7 @@
2930

3031
profile_bp = Blueprint("profile", __name__)
3132

32-
REQUIRED_PARAMS_COMPLETE_PROFILE = {
33-
"orientation": str,
34-
"bio": str,
35-
# "tags": str
36-
}
33+
REQUIRED_PARAMS_COMPLETE_PROFILE = {"orientation": str, "bio": str, "tags": list}
3734

3835

3936
@profile_bp.route("/profile/complete", methods=["POST"])
@@ -48,10 +45,14 @@ def complete_profile():
4845
data = request.get_json()
4946
orientation = data["orientation"]
5047
bio = data["bio"]
48+
tags = data["tags"]
5149

5250
if orientation not in ["heterosexual", "homosexual", "bisexual", "other"]:
5351
raise BadRequestError("Genre must be heterosexual, homosexual, bisexual or other", "Try again")
5452

53+
for tag in tags:
54+
Tag.create(name=tag, user_id=current_user.id)
55+
5556
current_user.orientation = orientation
5657
current_user.bio = bio
5758
current_user.is_profile_completed = True

backend/PyMatcha/utils/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
from PyMatcha.utils.password import hash_password
2-
from PyMatcha.utils.tables import create_tables, _create_user_images_table, _create_user_table
2+
from PyMatcha.utils.tables import _create_tags_table
3+
from PyMatcha.utils.tables import _create_user_images_table
4+
from PyMatcha.utils.tables import _create_user_table
5+
from PyMatcha.utils.tables import create_tables
36

47
create_user_images_table = _create_user_images_table
58
create_user_table = _create_user_table
9+
create_tags_table = _create_tags_table
610

7-
__all__ = ["hash_password", "create_tables", "create_user_table", "create_user_images_table"]
11+
__all__ = ["hash_password", "create_tables", "create_user_table", "create_user_images_table", "create_tags_table"]

backend/PyMatcha/utils/tables.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def _create_user_table(db):
3838
orientation ENUM('heterosexual', 'homosexual', 'bisexual', 'other'),
3939
birthdate DATE DEFAULT NULL,
4040
geohash VARCHAR(256) DEFAULT NULL,
41-
tags LONGTEXT, # TODO: JSON ?
4241
heat_score INT DEFAULT (0),
4342
date_joined DATETIME DEFAULT NOW(),
4443
date_lastseen DATETIME DEFAULT NOW(),
@@ -72,6 +71,24 @@ def _create_user_images_table(db):
7271
c.execute("""SET sql_notes = 1;""")
7372

7473

74+
def _create_tags_table(db):
75+
with db.cursor() as c:
76+
logging.info("Creating table tags.")
77+
c.execute("""SET sql_notes = 0;""")
78+
c.execute(
79+
"""
80+
CREATE TABLE IF NOT EXISTS tags
81+
(
82+
id INT auto_increment PRIMARY KEY,
83+
user_id INT NOT NULL,
84+
name VARCHAR(256)
85+
)
86+
"""
87+
)
88+
c.execute("""SET sql_notes = 1;""")
89+
90+
7591
def create_tables(db):
7692
_create_user_table(db)
7793
_create_user_images_table(db)
94+
_create_tags_table(db)

0 commit comments

Comments
 (0)