From a6a228ded9c3c9605010dec34107c697a240d2c0 Mon Sep 17 00:00:00 2001 From: andrei-mihnea-cerbu Date: Sat, 13 Jan 2024 03:18:17 +0200 Subject: [PATCH] login si signin done --- .../api/v1/endpoints/auth/__init__.py | 17 +++ messenger_app/api/v1/endpoints/auth/login.py | 14 ++- messenger_app/api/v1/endpoints/auth/signup.py | 13 +++ .../api/v1/endpoints/user/__init__.py | 0 messenger_app/api/v1/endpoints/user/user.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 884 -> 884 bytes .../users/__pycache__/create.cpython-310.pyc | Bin 775 -> 769 bytes .../api/v1/endpoints/users/create.py | 5 +- .../app/__pycache__/main.cpython-310.pyc | Bin 436 -> 519 bytes messenger_app/app/main.py | 2 + messenger_app/app/models/__init__.py | 1 + .../__pycache__/__init__.cpython-310.pyc | Bin 234 -> 269 bytes .../models/__pycache__/user.cpython-310.pyc | Bin 453 -> 434 bytes messenger_app/app/models/user.py | 1 - messenger_gui/app/http/request_builder.py | 32 +++--- messenger_gui/app/http/request_handler.py | 17 ++- messenger_gui/app/main.py | 23 ++-- .../app/models/http_models/__init__.py | 2 + messenger_gui/app/models/http_models/login.py | 4 + .../app/models/http_models/signup.py | 8 ++ .../app/models/view_models/__init__.py | 2 + messenger_gui/app/models/view_models/login.py | 29 +++++ .../app/models/view_models/signup.py | 2 +- messenger_gui/app/views/initial.py | 6 +- messenger_gui/app/views/login.py | 100 +++++++++++++++--- messenger_gui/app/views/signup.py | 63 +++++++++-- 26 files changed, 278 insertions(+), 63 deletions(-) delete mode 100644 messenger_app/api/v1/endpoints/user/__init__.py delete mode 100644 messenger_app/api/v1/endpoints/user/user.py create mode 100644 messenger_gui/app/models/http_models/login.py create mode 100644 messenger_gui/app/models/http_models/signup.py diff --git a/messenger_app/api/v1/endpoints/auth/__init__.py b/messenger_app/api/v1/endpoints/auth/__init__.py index e69de29..d6f48e0 100644 --- a/messenger_app/api/v1/endpoints/auth/__init__.py +++ b/messenger_app/api/v1/endpoints/auth/__init__.py @@ -0,0 +1,17 @@ +from fastapi import APIRouter +from .login import login +from app.models import Login +from app.models import User +from .signup import signup + +router = APIRouter() + + +@router.post("/login") +async def login_router(login_info: Login): + return await login(login_info) + + +@router.post("/sign_up") +async def signup_router(user: User): + return await signup(user) diff --git a/messenger_app/api/v1/endpoints/auth/login.py b/messenger_app/api/v1/endpoints/auth/login.py index c249d51..21f1d42 100644 --- a/messenger_app/api/v1/endpoints/auth/login.py +++ b/messenger_app/api/v1/endpoints/auth/login.py @@ -1 +1,13 @@ -from app.models.login import Login \ No newline at end of file +from fastapi import HTTPException +from app.models.login import Login +from database.queries.user import get_user_by_email + + +async def login(login_info: Login): + result = get_user_by_email(login_info.email) + if not result: + raise HTTPException(status_code=404, detail='User not in system.') + + password, email = result[2], result[3] + if login_info.email != email or login_info.password != password: + raise HTTPException(status_code=401, detail="Invalid credentials.") diff --git a/messenger_app/api/v1/endpoints/auth/signup.py b/messenger_app/api/v1/endpoints/auth/signup.py index e69de29..67b529c 100644 --- a/messenger_app/api/v1/endpoints/auth/signup.py +++ b/messenger_app/api/v1/endpoints/auth/signup.py @@ -0,0 +1,13 @@ +from fastapi import HTTPException +from app.models.user import User +from database.queries.user import get_user_by_email, create_user_db + + +async def signup(user: User): + result = get_user_by_email(user.email) + if result: + raise HTTPException(status_code=409, detail='User already exists.') + + print(user.username, user.email, user.password) + + create_user_db(username=user.username, password=user.password, email=user.email) diff --git a/messenger_app/api/v1/endpoints/user/__init__.py b/messenger_app/api/v1/endpoints/user/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/messenger_app/api/v1/endpoints/user/user.py b/messenger_app/api/v1/endpoints/user/user.py deleted file mode 100644 index e69de29..0000000 diff --git a/messenger_app/api/v1/endpoints/users/__pycache__/__init__.cpython-310.pyc b/messenger_app/api/v1/endpoints/users/__pycache__/__init__.cpython-310.pyc index 90bb0c427ab3747f37707a702df395620b52e4d6..4c27a3cf055bc3349d0613254ff31c1d4b412b25 100644 GIT binary patch delta 19 Zcmeyu_JxfrpO=@50SHz;*vOT|3;;Ko1w#M; delta 19 Zcmeyu_JxfrpO=@50SInQ-N=>23;;Js1t|ak diff --git a/messenger_app/api/v1/endpoints/users/__pycache__/create.cpython-310.pyc b/messenger_app/api/v1/endpoints/users/__pycache__/create.cpython-310.pyc index b11645b537c6a982c8fdc36aee5d482fe6c3c813..d5b05a4859091a4cafae924d11d300c33c2028f4 100644 GIT binary patch delta 172 zcmZo?Yh>fi=jG*M00O~_3sV#P@nSDJ*lCYnf9x zYM3(_gBdhA{W51VGB8w$gche3DJ13;r6#6SDx_9q7MB$3P4;6nv3LoTW_Za2BA9_h z5gU-uWG`X?vAID6Na_}AK~ZL2Nf9SV0OW`w*2!lXR|*I*i7;_7vN5qS0^wf{w#jWw FjR2i6C)@x4 delta 185 zcmZo$13sbu%@*ZGJn0QWOG6$o&VGUCXha^J^=Ny(=<`k|P=1j(5 z22F0i%$bY~3{}FR#i>OKi8)27i7Ax|sTG;UCB>7Y8BM&4fU*oP!2}bC#SA1gS#B|9 zrWA1knMEMWinu`p8%Tz&hy^YHQeVUhA|NU!A7@-CAi~7O$i~FR2!?++*e5qIH39$| CawhQr diff --git a/messenger_app/api/v1/endpoints/users/create.py b/messenger_app/api/v1/endpoints/users/create.py index 2de5e38..f2cedc7 100644 --- a/messenger_app/api/v1/endpoints/users/create.py +++ b/messenger_app/api/v1/endpoints/users/create.py @@ -6,12 +6,13 @@ from database.queries.user import get_user_by_email, create_user_db async def create_user(user: User): result = get_user_by_email(user.email) if result: - raise HTTPException(status_code=409, detail='User already exists') + raise HTTPException(status_code=409, detail='User already exists.') + + print(user.username, user.email, user.password) create_user_db(username=user.username, password=user.password, email=user.email) created_user = get_user_by_email(user.email) created_user_dict = { - "id": created_user[0], "username": created_user[1], "password": created_user[2], "email": created_user[3], diff --git a/messenger_app/app/__pycache__/main.cpython-310.pyc b/messenger_app/app/__pycache__/main.cpython-310.pyc index d2a10b07a64237a2e6682518d57ce64e6c82303f..5d74ec0bbb11e825c1d6af1065942e48a01d2555 100644 GIT binary patch delta 193 zcmdnO+|I(A&&$ij00d$W7pAV6$SccOFi~6GFNGn6DTh6mIf{dkA(gS2A&N7VGm9&g zC51ViF@+_CwU-$v4iaHYVFQY=BZ+XNZ~#R(AtEVU!3>(*6Px@5Zm~F)mSj}1>L&sz zKcLvF#-Tcd@Nr8 delta 117 zcmZo?*}}}5&&$ij00jQi7N(j`inH+p4J_iHyp+*TfCtFrVc=opVPsYFz_%6FaiJ;CLA*W delta 84 zcmeBWdd0|_&&$ij00hBP7p9s_p&-P{amQP{cNIRU`)skj29wzz6_GSQ7C7 diff --git a/messenger_app/app/models/__pycache__/user.cpython-310.pyc b/messenger_app/app/models/__pycache__/user.cpython-310.pyc index fe4dace754fc53507ee5b9aef87014a461eda9e4..8e7ecf715c92de48e5aceda4eab11eba8b65e136 100644 GIT binary patch delta 146 zcmX@gyos4NpO=@50SLm*EKJRw$eVAZ2IQnNL@}l?L@|Xjq%xw#$BKU#CEe@O9{FKt1R69l>ub2f$ J@Gyul0|2N{Dx?4a diff --git a/messenger_app/app/models/user.py b/messenger_app/app/models/user.py index 50ad3b2..8693145 100644 --- a/messenger_app/app/models/user.py +++ b/messenger_app/app/models/user.py @@ -2,7 +2,6 @@ from pydantic import BaseModel class User(BaseModel): - id: int username: str password: str email: str diff --git a/messenger_gui/app/http/request_builder.py b/messenger_gui/app/http/request_builder.py index ad68895..d43c589 100644 --- a/messenger_gui/app/http/request_builder.py +++ b/messenger_gui/app/http/request_builder.py @@ -3,26 +3,32 @@ from .request_handler import _HttpRequestHandler class RequestBuilder: def __init__(self): - self.url = "" - self.headers = {} - self.body = None - self.method = "GET" + self.__url = "" + self.__headers = {} + self.__body = None + self.__params = None + self.__method = "GET" - def set_url(self, url): - self.url = url + def set_url(self, url=str): + self.__url = url return self - def set_headers(self, headers): - self.headers = headers + def set_headers(self, headers=dict): + self.__headers = headers return self - def set_body(self, body): - self.body = body + def set_body(self, body=dict): + self.__body = body return self - def set_method(self, method): - self.method = method + def set_params(self, params=dict): + self.__params = params + return self + + def set_method(self, method=str): + self.__method = method return self def build(self): - return _HttpRequestHandler(self.url) + return _HttpRequestHandler(url=self.__url, method=self.__method, body=self.__body, + params=self.__params, headers=self.__headers) diff --git a/messenger_gui/app/http/request_handler.py b/messenger_gui/app/http/request_handler.py index d1a4876..8458204 100644 --- a/messenger_gui/app/http/request_handler.py +++ b/messenger_gui/app/http/request_handler.py @@ -1,11 +1,18 @@ +import json import requests class _HttpRequestHandler: - def __init__(self, base_url): - self.base_url = base_url + def __init__(self, url, method="GET", params=None, headers=None, body=None): + self.url = url + self.method = method + self.headers = headers + print(body) + self.body = json.dumps(body) + self.params = params - def make_request(self, method, endpoint, params=None, data=None, headers=None): - url = f"{self.base_url}/{endpoint}" - response = requests.request(method, url, params=params, data=data, headers=headers) + def make_request(self): + print(self.body) + response = requests.request(method=self.method, url=self.url, + params=self.params, data=self.body, headers=self.headers) return response diff --git a/messenger_gui/app/main.py b/messenger_gui/app/main.py index 6032e22..41f4c29 100644 --- a/messenger_gui/app/main.py +++ b/messenger_gui/app/main.py @@ -12,21 +12,26 @@ class MainApplication(tk.Tk): screen_height = self.winfo_screenheight() self.geometry(f"{screen_height // 2}x{screen_height // 2}") - - # Create instances of the views - self.login_view = LoginView(self) - self.initial_view = InitialView(self) - self.signup_view = SignupView(self) - self.main_view = tk.Label(self, text="Main View") - self.current_view = None - self.change_view(self.initial_view) + + self.change_to_initial_view() + + def change_to_initial_view(self): + self.change_view(InitialView(self)) + + def change_to_sing_in_view(self): + self.change_view(SignupView(self)) + + def change_to_login_view(self): + self.change_view(LoginView(self)) def change_view(self, view: tk.Frame): if self.current_view: - self.current_view.pack_forget() + self.current_view.destroy() self.current_view = view self.current_view.pack(expand=True, fill=tk.BOTH) self.current_view.place(relx=0.5, rely=0.5, anchor=tk.CENTER) + + diff --git a/messenger_gui/app/models/http_models/__init__.py b/messenger_gui/app/models/http_models/__init__.py index e69de29..5dd9f36 100644 --- a/messenger_gui/app/models/http_models/__init__.py +++ b/messenger_gui/app/models/http_models/__init__.py @@ -0,0 +1,2 @@ +from .login import LoginRequestModel +from .signup import SignupRequestModel diff --git a/messenger_gui/app/models/http_models/login.py b/messenger_gui/app/models/http_models/login.py new file mode 100644 index 0000000..2866a66 --- /dev/null +++ b/messenger_gui/app/models/http_models/login.py @@ -0,0 +1,4 @@ +class LoginRequestModel: + def __init__(self, email, password): + self.email = email + self.password = password diff --git a/messenger_gui/app/models/http_models/signup.py b/messenger_gui/app/models/http_models/signup.py new file mode 100644 index 0000000..7466b5c --- /dev/null +++ b/messenger_gui/app/models/http_models/signup.py @@ -0,0 +1,8 @@ +import json + + +class SignupRequestModel: + def __init__(self, username, email, password): + self.username = username + self.email = email + self.password = password diff --git a/messenger_gui/app/models/view_models/__init__.py b/messenger_gui/app/models/view_models/__init__.py index e69de29..d698275 100644 --- a/messenger_gui/app/models/view_models/__init__.py +++ b/messenger_gui/app/models/view_models/__init__.py @@ -0,0 +1,2 @@ +from .login import LoginModel +from .signup import SignupModel diff --git a/messenger_gui/app/models/view_models/login.py b/messenger_gui/app/models/view_models/login.py index e69de29..a16efec 100644 --- a/messenger_gui/app/models/view_models/login.py +++ b/messenger_gui/app/models/view_models/login.py @@ -0,0 +1,29 @@ +import re + + +class LoginModel: + def __init__(self, password: str, email: str): + self.password = password + self.email = email + + def validate(self): + errors = [] + + # Check if username, password, and email are provided + if not self.email: + errors.append("Email is required.") + + email_pattern = re.compile(r"[^@]+@[^@]+\.[^@]+") + if not email_pattern.match(self.email): + errors.append("Invalid email format.") + + if not self.password: + errors.append("Password is required.") + if len(self.password) < 8: + errors.append("Password must be at least 8 characters.") + + if errors: + return False, errors + + # If all validations pass, return True + return True, [] diff --git a/messenger_gui/app/models/view_models/signup.py b/messenger_gui/app/models/view_models/signup.py index 7ef7530..85b1609 100644 --- a/messenger_gui/app/models/view_models/signup.py +++ b/messenger_gui/app/models/view_models/signup.py @@ -2,7 +2,7 @@ import re class SignupModel: - def __init__(self, username:str, password:str, email:str): + def __init__(self, username: str, password: str, email: str): self.username = username self.password = password self.email = email diff --git a/messenger_gui/app/views/initial.py b/messenger_gui/app/views/initial.py index 19c63b8..3326d2d 100644 --- a/messenger_gui/app/views/initial.py +++ b/messenger_gui/app/views/initial.py @@ -16,9 +16,7 @@ class InitialView(tk.Frame): signin_button.pack(side=tk.RIGHT, padx=5) def on_login(self): - self.master.change_view(self.master.login_view) + self.master.change_to_login_view() def on_signin(self): - self.master.change_view(self.master.signup_view) - pass - + self.master.change_to_sing_in_view() \ No newline at end of file diff --git a/messenger_gui/app/views/login.py b/messenger_gui/app/views/login.py index 634871f..561e534 100644 --- a/messenger_gui/app/views/login.py +++ b/messenger_gui/app/views/login.py @@ -1,36 +1,102 @@ +import hashlib +import json import tkinter as tk +from app.models.view_models import LoginModel +from app.http import request_builder +from app.models.http_models import LoginRequestModel +def hash_password(password): + sha256_hash = hashlib.sha256() + sha256_hash.update(password.encode('utf-8')) + hashed_output = sha256_hash.hexdigest() + return hashed_output + class LoginView(tk.Frame): def __init__(self, master=None): super().__init__(master) + self.form_frame = None + self.define_http_params() self.create_widgets() + def define_http_params(self): + self.url = "http://localhost:8000/auth/login" + self.headers = {"Content-Type": "application/json"} + self.method = "POST" + self.params = None + def create_widgets(self): - # Username Label and Entry - username_label = tk.Label(self, text="Username:") - username_label.pack(pady=5) - self.username_entry = tk.Entry(self) - self.username_entry.pack(pady=5) + # Create a frame to hold the entry fields and labels + self.form_frame = tk.Frame(self) + + # Error label + self.error_var = tk.StringVar() # Variable to store error message + self.error_label = tk.Label(self.form_frame, textvariable=self.error_var, fg="red") + self.error_label.grid(row=0, column=0, pady=5, columnspan=2) # Span columns for full width + + # Left frame for labels + label_frame = tk.Frame(self.form_frame) + label_frame.grid(row=1, column=0, pady=5, padx=5, sticky="w") + + # Right frame for entry widgets + entry_frame = tk.Frame(self.form_frame) + entry_frame.grid(row=1, column=1, pady=5, padx=5, sticky="e") + + # Email Label and Entry + self.email_label = tk.Label(label_frame, text="Email:") + self.email_label.grid(row=1, column=0, pady=5, sticky="w") + + self.email_entry = tk.Entry(entry_frame) + self.email_entry.grid(row=1, column=0, pady=5, sticky="e") # Password Label and Entry - password_label = tk.Label(self, text="Password:") - password_label.pack(pady=5) - self.password_entry = tk.Entry(self, show="*") # Use show="*" to hide password characters - self.password_entry.pack(pady=5) + self.password_label = tk.Label(label_frame, text="Password:") + self.password_label.grid(row=2, column=0, pady=5, sticky="w") + + self.password_entry = tk.Entry(entry_frame, show="*") + self.password_entry.grid(row=2, column=0, pady=5, sticky="e") # Login Button - login_button = tk.Button(self, text="Submit", command=self.on_login) - login_button.pack(pady=10) + self.signup_button = tk.Button(self.form_frame, text="Login", command=self.on_login) + self.signup_button.grid(row=2, column=0, pady=10) # No columnspan for the signup button + + # Return to Main Menu Button + self.return_button = tk.Button(self.form_frame, text="Return to Main Menu", command=self.return_to_initial_view) + self.return_button.grid(row=2, column=1, pady=10, padx=5) # Place next to the signup button + + self.form_frame.pack() + + def return_to_initial_view(self): + self.master.change_to_initial_view() def on_login(self): - # Retrieve username and password values - username = self.username_entry.get() + # Retrieve values from entry fields + email = self.email_entry.get() password = self.password_entry.get() - # Example: Check credentials (you'll need to implement your own logic) - if username == "example" and password == "password": - self.master.show_main_view() + model = LoginModel(email=email, password=password) + validation, errors = model.validate() + + if not validation: + self.error_var.set(errors[0]) + self.error_label.grid(row=0, column=0, pady=5) + + request_builder.set_url(self.url) + request_builder.set_headers(self.headers) + request_builder.set_params(self.params) + request_builder.set_body( + LoginRequestModel( + email=email, + password=hash_password(password) + ).__dict__) + request_builder.set_method(self.method) + + result = request_builder.build().make_request() + if result.status_code == 200: + self.master.change_to_initial_view() else: - print("Invalid credentials") \ No newline at end of file + json_data = json.loads(result.text) + detail_value = json_data.get('detail') + self.error_var.set(detail_value) + self.error_label.grid(row=0, column=0, pady=5) \ No newline at end of file diff --git a/messenger_gui/app/views/signup.py b/messenger_gui/app/views/signup.py index 7a73b37..50518a5 100644 --- a/messenger_gui/app/views/signup.py +++ b/messenger_gui/app/views/signup.py @@ -1,27 +1,46 @@ +import hashlib +import json import tkinter as tk -from app.models.view_models.signup import SignupModel +from app.models.view_models import SignupModel +from app.http import request_builder +from app.models.http_models import SignupRequestModel + + +def hash_password(password): + sha256_hash = hashlib.sha256() + sha256_hash.update(password.encode('utf-8')) + hashed_output = sha256_hash.hexdigest() + return hashed_output class SignupView(tk.Frame): def __init__(self, master=None): super().__init__(master) + self.form_frame = None + self.define_http_params() self.create_widgets() + def define_http_params(self): + self.url = "http://localhost:8000/auth/sign_up" + self.headers = {"Content-Type": "application/json"} + self.method = "POST" + self.params = None + def create_widgets(self): # Create a frame to hold the entry fields and labels - form_frame = tk.Frame(self) + self.form_frame = tk.Frame(self) # Error label self.error_var = tk.StringVar() # Variable to store error message - self.error_label = tk.Label(form_frame, textvariable=self.error_var, fg="red") + self.error_label = tk.Label(self.form_frame, textvariable=self.error_var, fg="red") self.error_label.grid(row=0, column=0, pady=5, columnspan=2) # Span columns for full width # Left frame for labels - label_frame = tk.Frame(form_frame) + label_frame = tk.Frame(self.form_frame) label_frame.grid(row=1, column=0, pady=5, padx=5, sticky="w") # Right frame for entry widgets - entry_frame = tk.Frame(form_frame) + entry_frame = tk.Frame(self.form_frame) entry_frame.grid(row=1, column=1, pady=5, padx=5, sticky="e") # Username Label and Entry @@ -46,10 +65,17 @@ class SignupView(tk.Frame): self.password_entry.grid(row=2, column=0, pady=5, sticky="e") # Signup Button - self.signup_button = tk.Button(form_frame, text="Signup", command=self.on_signup) - self.signup_button.grid(row=2, column=0, columnspan=2, pady=10) # Span columns for full width + self.signup_button = tk.Button(self.form_frame, text="Sign up", command=self.on_signup) + self.signup_button.grid(row=2, column=0, pady=10) # No columnspan for the signup button - form_frame.pack() + # Return to Main Menu Button + self.return_button = tk.Button(self.form_frame, text="Return to Main Menu", command=self.return_to_initial_view) + self.return_button.grid(row=2, column=1, pady=10, padx=5) # Place next to the signup button + + self.form_frame.pack() + + def return_to_initial_view(self): + self.master.change_to_initial_view() def on_signup(self): # Retrieve values from entry fields @@ -64,5 +90,22 @@ class SignupView(tk.Frame): self.error_var.set(errors[0]) self.error_label.grid(row=0, column=0, pady=5) - # Print or handle the values as needed - print(f"Username: {username}, Email: {email}, Password: {password}") + request_builder.set_url(self.url) + request_builder.set_headers(self.headers) + request_builder.set_params(self.params) + request_builder.set_body( + SignupRequestModel( + username=username, + email=email, + password=hash_password(password) + ).__dict__) + request_builder.set_method(self.method) + + result = request_builder.build().make_request() + if result.status_code == 200: + self.master.change_to_initial_view() + else: + json_data = json.loads(result.text) + detail_value = json_data.get('detail') + self.error_var.set(detail_value) + self.error_label.grid(row=0, column=0, pady=5)