Skip to content

Commit

Permalink
Merge pull request #47 from CS222-UIUC/aden/userpagetouchup
Browse files Browse the repository at this point in the history
return json in userpage() and fix userpage test
  • Loading branch information
akrakman authored Nov 25, 2022
2 parents 599cc09 + 332a33c commit 1e12232
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 103 deletions.
3 changes: 2 additions & 1 deletion src/backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ def userpage():
return result, 400
return result, 201
user = page.get_user(username) # request.method == "GET"
return user, username, 201
data_dict = dataclasses.asdict(user)
return json.dumps(data_dict), username, 201


@app.route("/logout")
Expand Down
Binary file modified src/backend/database/database_test.db
Binary file not shown.
19 changes: 3 additions & 16 deletions src/backend/pages/login.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
""" Contains Login class """
from dataclasses import dataclass
import re
from decorators import use_database
from tests.auth import validate_email, validate_password, validate_phone


@dataclass(frozen=True)
Expand All @@ -26,14 +26,13 @@ def register(
if (not username) or (not email) or (not password) or (not phone):
return RegisterResult("Missing information, please try again", False)

regex_email = re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b")
if not regex_email.fullmatch(email):
if not validate_email(email):
return RegisterResult("Invalid email, please try again", False)

if not validate_phone(phone):
return RegisterResult("Invalid phone number, please try again", False)

if len(password) < 8:
if not validate_password(password):
return RegisterResult("Password is too short, please try again", False)

check = self.register.cursor.execute(
Expand All @@ -60,15 +59,3 @@ def login(self, user_id: str, password: str) -> bool:

def logout(self) -> None:
"""Logout"""


def validate_phone(phone: str) -> bool:
"""Used in Login class and in User class"""
regex_phone = re.compile(
r"^\s*(?:\+?(\d{1,3}))?[-. (]"
r"*(\d{3})[-. )]*(\d{3})[-. ]"
r"*(\d{4})(?: *x(\d+))?\s*$"
)
if not regex_phone.fullmatch(phone):
return False
return True
76 changes: 35 additions & 41 deletions src/backend/pages/userpage.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Contains the UserPage backend"""
from typing import List
from pages.login import validate_phone
from tests.auth import validate_phone, validate_email, validate_password
from dataholders.user import User
from dataholders.apt import Apt
from decorators import use_database
Expand All @@ -15,7 +15,7 @@ def __init__(self, username: str) -> None:
self.user = self.get_user(username)

@use_database
def get_user(self, username: str):
def get_user(self, username: str) -> User:
"""Return User object based on username"""
query_sql = username
user_query = self.get_user.cursor.execute(
Expand All @@ -33,74 +33,68 @@ def get_user(self, username: str):
def update_password(self, password: str) -> bool:
"""Updates password based on username"""
# can use Flask-Hashing if we want
if not validate_password(password):
return False
if self.user.password == password:
return True
query_sql = "%" + str(self.user.user_id) + "%"
self.update_password.cursor.execute(
"UPDATE Users \
SET password = ? \
WHERE user_id = ?",
(password, query_sql),
WHERE (username = ?)",
(password, self.username),
)
self.user.password = password
return True

@use_database
def update_email(self, email: str) -> bool:
"""Updates email based on username"""
if not validate_email(email):
return False
if self.user.email == email:
return True

query_sql = email
self.update_email.cursor.execute(
"UPDATE Users \
SET email = ? \
WHERE username = ?",
(query_sql, self.username),
(email, self.username),
)
new_email = self.update_email.cursor.execute(
"SELECT email \
FROM Users \
WHERE (username = ?)",
(self.username,),
).fetchone()[0]
self.user.email = email
return True

return new_email == email
@use_database
def update_phone(self, phone: str) -> bool:
"""Updates User's phone number if valid"""
if not validate_phone(phone):
return False
if self.user.phone == phone:
return True
self.update_phone.cursor.execute(
"UPDATE Users SET phone = ? WHERE (username = ?)",
(phone, self.username),
)
self.user.phone = phone
return True

@use_database
def get_liked(self, user_id: int) -> List[Apt]:
"""Gets liked apartments based on username"""
apts = []
query_sql = "%" + user_id + "%"
liked = self.get_liked.cursor.execute(
"SELECT a.apt_id, a.apt_name, a.apt_address, a.price_min, a.price_max \
From Reviews r INNER JOIN Apartments a \
FROM Reviews r INNER JOIN Apartments a \
ON r.apt_id = a.apt_id \
WHERE r.user_id = ? AND r.vote = ?",
(query_sql, 1),
)

WHERE r.user_id = ? AND r.vote = 1",
(user_id,),
).fetchall()
for apt in liked:
apt_id, apt_name, apt_address, price_min, price_max = apt
query_sql = "%" + apt_id + "%"
apt_id, apt_name, address, price_min, price_max = apt
rating = self.get_liked.cursor.execute(
"SELECT AVG(r.vote) \
From Reviews r \
FROM Reviews r \
WHERE r.apt_id = ?",
(query_sql),
)
apts.append(
Apt(apt_id, apt_name, rating, apt_address, price_min, price_max)
)
(apt_id,),
).fetchone()[0]
rating = round(rating, 3)
apts.append(Apt(apt_id, apt_name, address, rating, price_min, price_max))
return apts

@use_database
def update_phone(self, phone: str) -> bool:
"""Updates User's phone number if valid"""
if not validate_phone(phone):
return False
self.update_phone.cursor.execute(
"UPDATE Users SET phone = ? WHERE (username = ?)",
(phone, self.username),
)
self.update_phone.connection.commit()
return True
23 changes: 23 additions & 0 deletions src/backend/tests/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Tests password, email, and phone"""
import re


def validate_password(password: str) -> bool:
"""Used in Login and User class"""
return len(password) >= 8


def validate_email(email: str) -> bool:
"""Used in Login and User class"""
regex_email = re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b")
return regex_email.fullmatch(email)


def validate_phone(phone: str) -> bool:
"""Used in Login and User class"""
regex_phone = re.compile(
r"^\s*(?:\+?(\d{1,3}))?[-. (]"
r"*(\d{3})[-. )]*(\d{3})[-. ]"
r"*(\d{4})(?: *x(\d+))?\s*$"
)
return regex_phone.fullmatch(phone)
8 changes: 4 additions & 4 deletions src/backend/tests/mainpage_staging.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ def insert_apartments(self, cursor: sqlite3.Cursor, connection: sqlite3.Connecti
def insert_users(self, cursor: sqlite3.Cursor, connection: sqlite3.Connection):
"""Initialize users for use by test methods"""
args = [
("Minh Phan", "", "", ""),
("Minh", "", "", ""),
("Big_finger", "", "", ""),
("Fig_binger", "", "", ""),
("Minh Phan", "phan_password1", "phan@gmail.com", "111-111-1111"),
("Minh", "minh_password1", "minh@gmail.com", "222-222-2222"),
("Big_finger", "big_password1", "big@gmail.com", "333-333-3333"),
("Fig_binger", "fig_password1", "fig@gmail.com", "444-444-4444"),
]
cursor.executemany(
"INSERT INTO Users (username, password, email, phone) \
Expand Down
23 changes: 13 additions & 10 deletions src/backend/tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,20 +289,24 @@ def test_userpage_not_logged_in(client):


@use_test
def test_userpage_get_request():
def test_userpage_get_request(client):
"""Tests session object works, user is logged in, and user is correct"""
reg_info = {
"username": "Mike",
"email": "junk@gmail.com",
"password": "1234",
"password": "123456991",
"phone": "0003335555",
}
with app.test_request_context("/register", method="POST", json=reg_info):
with app.test_request_context("/user/", method="GET"):
session["username"] = "Mike"
res = userpage()
print(res)
### Will test json.dumps(user), username, 201 ###
client.post("/register", json=reg_info)
with app.test_request_context("/user/", method="GET"):
session["username"] = "Mike"
res = userpage()
assert res[1] == "Mike" and res[2] == 201
connection = sqlite3.connect("database/database_test.db")
cursor = connection.cursor()
cursor.execute("DELETE FROM Users WHERE username = ?", ("Mike",))
connection.commit()
connection.close()


@use_test
Expand All @@ -314,7 +318,7 @@ def test_userpage_post_request(client):
"password": "1234123432123",
"phone": "0003335555",
}

client.post("/register", json=reg_info)
with app.test_request_context(
"/user/", method="POST", json={"is_phone": "True", "phone": "0111115555"}
):
Expand All @@ -327,7 +331,6 @@ def test_userpage_post_request(client):
json={"is_password": "True", "password": "1234sadfds1324"},
):
session["username"] = "Mike"
client.post("/register", json=reg_info)
res = userpage()
assert res[1] == 201
with app.test_request_context(
Expand Down
Loading

3 comments on commit 1e12232

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCover
app.py1320100%
config.py10100%
decorators.py270100%
dataholders
   apt.py90100%
   mainpage_get.py150100%
   review.py70100%
   user.py80100%
pages
   login.py290100%
   mainpage.py1000100%
   userpage.py540100%
TOTAL3820100%

Tests Skipped Failures Errors Time
48 0 💤 0 ❌ 0 🔥 0.941s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCover
app.py1320100%
config.py10100%
decorators.py270100%
dataholders
   apt.py90100%
   mainpage_get.py150100%
   review.py70100%
   user.py80100%
pages
   login.py290100%
   mainpage.py1000100%
   userpage.py540100%
TOTAL3820100%

Tests Skipped Failures Errors Time
48 0 💤 0 ❌ 0 🔥 0.972s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCover
app.py1320100%
config.py10100%
decorators.py270100%
dataholders
   apt.py90100%
   mainpage_get.py150100%
   review.py70100%
   user.py80100%
pages
   login.py290100%
   mainpage.py1000100%
   userpage.py540100%
TOTAL3820100%

Tests Skipped Failures Errors Time
48 0 💤 0 ❌ 0 🔥 1.071s ⏱️

Please sign in to comment.