From 88c9b168fd24f3306df2bc20b4a5ef426fd30f4d Mon Sep 17 00:00:00 2001 From: JustIceO7 Date: Fri, 14 Feb 2025 00:14:16 +0000 Subject: [PATCH] UPDATE: Updated VideoPage UI UPDATE: Added response to successful password reset redirect to homepage --- .../category_banners/category_banners.json | 5 - frontend/public/images/icons/user.png | Bin 0 -> 571 bytes .../src/components/Auth/PasswordResetForm.tsx | 8 +- frontend/src/pages/ResetPasswordPage.tsx | 8 +- frontend/src/pages/VideoPage.tsx | 131 +++++++++++------- web_server/blueprints/oauth.py | 7 +- web_server/blueprints/user.py | 8 +- web_server/utils/auth.py | 4 +- web_server/utils/email.py | 5 +- 9 files changed, 98 insertions(+), 78 deletions(-) delete mode 100644 frontend/public/images/category_banners/category_banners.json create mode 100644 frontend/public/images/icons/user.png diff --git a/frontend/public/images/category_banners/category_banners.json b/frontend/public/images/category_banners/category_banners.json deleted file mode 100644 index cc72d6a..0000000 --- a/frontend/public/images/category_banners/category_banners.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "1": "https://example.com/category/101", - "2": "https://example.com/category/102", - "3": "https://example.com/category/103" - } \ No newline at end of file diff --git a/frontend/public/images/icons/user.png b/frontend/public/images/icons/user.png new file mode 100644 index 0000000000000000000000000000000000000000..2d4af2326e5def0acf1ff0d95593bfe7b43d66f2 GIT binary patch literal 571 zcmV-B0>u4^P)n4`v3p{8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10mw;2 zK~zYIwUaSxlTj3gpZBH(aj>CQ1!Ga%s*414)1j+#2bT~Wtf^=dL_`z`P70Q$iY9e% z7J`Fo z;sbjNTb`&?s{gmZrcX~IT?dluN_E5~&6X>^e&>bfr!FH^+Q0#l7-gHzUG*_KZeaN{ zX^5V0Gz4HMI-=S67ww9k<|rQkkB5w0p;OTZI2r)|t*~R85ex?lP{+GI!BV(@kKGHT zXTf;sY4?JtH3KvP@C}@9b}i7{y#>rNK+^+nVq`UQ=Y7|LSWSg$ffAP*v9>BSSI1?>0RRJ$ z8o3W-HVIzKAjTC^+xHlp6j=O<3b||#;D1C}3b_n`tXOo^mluFk?*ssRAh~Ow = ({ onSubmit, token }) => { confirmNewPassword: "", }); - const confirmPasswordReset = () => { - alert(`${resetData.newPassword} - ${token}`); - - }; const handlePasswordChange = (e: React.ChangeEvent) => { const { name, value } = e.target; @@ -77,9 +73,9 @@ const PasswordResetForm: React.FC = ({ onSubmit, token }) => { if (!response.ok) { const data = await response.json(); - throw new Error(data.message || "An error has occurred while resetting"); + throw new Error(data.error || "An error has occurred while resetting"); } else { - confirmPasswordReset(); + onSubmit(true) } } catch (error: any) { console.error("Password reset error:", error.message); diff --git a/frontend/src/pages/ResetPasswordPage.tsx b/frontend/src/pages/ResetPasswordPage.tsx index a7fdff6..f7e83cc 100644 --- a/frontend/src/pages/ResetPasswordPage.tsx +++ b/frontend/src/pages/ResetPasswordPage.tsx @@ -6,9 +6,13 @@ const ResetPasswordPage: React.FC = () => { const { token } = useParams<{ token: string }>(); const navigate = useNavigate(); - const handlePasswordReset = () => { - + const handlePasswordReset = (success: boolean) => { + if (success) { + alert("Password reset successful!"); + navigate("/"); + } }; + if (!token) { return

Invalid or missing token.

; } diff --git a/frontend/src/pages/VideoPage.tsx b/frontend/src/pages/VideoPage.tsx index c42ef2e..96a4fff 100644 --- a/frontend/src/pages/VideoPage.tsx +++ b/frontend/src/pages/VideoPage.tsx @@ -100,9 +100,8 @@ const VideoPage: React.FC = ({ streamerId }) => {
@@ -114,7 +113,7 @@ const VideoPage: React.FC = ({ streamerId }) => { extraClasses="group cursor-pointer absolute top-[70px] right-[20px] text-[1rem] flex items-center flex-nowrap" > {isChatOpen ? "Hide Chat" : "Show Chat"} - + Press C @@ -123,68 +122,98 @@ const VideoPage: React.FC = ({ streamerId }) => { onViewerCountChange={(count: number) => setViewerCount(count)} /> + {/* Stream Data */}
-

- {streamData ? streamData.streamTitle : "Loading..."} -

-
- + {streamData ? streamData.streamerName : "Loading..."} + +
- {/* (Un)Follow Button */} - {!isFollowing ? ( - - ) : ( - - )} + {/* Stream Title */} +
+

+ {streamData ? streamData.streamTitle : "Loading..."} +

+ + {streamData ? streamData.categoryName : "Loading..."} +
-
- Viewers - {viewerCount} + + {/* Streamer Info */} +
+
+ {!isFollowing ? ( + + ) : ( + + )} +
-
- Started - + + {/* Stream Stats */} +
+
+ Viewers Icon + {viewerCount} +
+
+ +
+ Started + {streamData - ? new Date(streamData.startTime).toLocaleString() + ? `${Math.floor((Date.now() - new Date(streamData.startTime).getTime()) / 3600000)} hours ago` : "Loading..."}
-
- Category - {streamData ? streamData.categoryName : "Loading..."} + + {/* Subscribe Button */} +
+
+
- {isLoggedIn && ( - - )} + {/* {showCheckout && setShowCheckout(false)} />} */} + {/* {showReturn && } */} + {showAuthModal && setShowAuthModal(false)} />}
- {/* {showCheckout && setShowCheckout(false)} />} */} - {/* {showReturn && } */} - {showAuthModal && setShowAuthModal(false)} />}
); diff --git a/web_server/blueprints/oauth.py b/web_server/blueprints/oauth.py index c1554d1..e32ffc3 100644 --- a/web_server/blueprints/oauth.py +++ b/web_server/blueprints/oauth.py @@ -11,7 +11,8 @@ google = None from os import getenv load_dotenv() -url = getenv("VITE_API_URL") +url_api = getenv("VITE_API_URL") +url = getenv("HOMEPAGE_URL") def init_oauth(app): @@ -27,7 +28,7 @@ def init_oauth(app): api_base_url='https://www.googleapis.com/oauth2/v1/', userinfo_endpoint='https://openidconnect.googleapis.com/v1/userinfo', server_metadata_url='https://accounts.google.com/.well-known/openid-configuration', - redirect_uri=f"{url}/api/google_auth" + redirect_uri=f"{url_api}/google_auth" ) @oauth_bp.route('/login/google') @@ -40,7 +41,7 @@ def login_google(): session["origin"] = request.args.get("next") return google.authorize_redirect( - f'{url}/api/google_auth', + f'{url_api}/google_auth', nonce=session['nonce'] ) diff --git a/web_server/blueprints/user.py b/web_server/blueprints/user.py index 4622b1f..672e4f2 100644 --- a/web_server/blueprints/user.py +++ b/web_server/blueprints/user.py @@ -131,11 +131,7 @@ def user_reset_password(token, new_password): r.delete(token) email = verify_token(token[:-5], salt_value) - if email: - response = reset_password(new_password, email) - if response: - return 200 - else: - return jsonify({"error": "Failed to reset password"}), 500 + reset_password(new_password, email) + return jsonify({"message": "Password reset successful"}), 200 return jsonify({"error": "Invalid token"}), 400 \ No newline at end of file diff --git a/web_server/utils/auth.py b/web_server/utils/auth.py index 74ee468..67b8bfe 100644 --- a/web_server/utils/auth.py +++ b/web_server/utils/auth.py @@ -31,7 +31,7 @@ def verify_token(token: str, salt_value) -> Optional[str]: print("Token is invalid", flush=True) return None -def reset_password(new_password: str, email: str) -> bool: +def reset_password(new_password: str, email: str): """ Given email and new password reset the password for a given user """ @@ -41,5 +41,3 @@ def reset_password(new_password: str, email: str) -> bool: SET password = ? WHERE email = ? """, (generate_password_hash(new_password), email)) - - return True \ No newline at end of file diff --git a/web_server/utils/email.py b/web_server/utils/email.py index 180e898..471eca9 100644 --- a/web_server/utils/email.py +++ b/web_server/utils/email.py @@ -12,6 +12,9 @@ r = redis.from_url(redis_url, decode_responses=True) load_dotenv() +url = getenv("HOMEPAGE_URL") + + def send_email(email, func) -> None: """ Send a verification email to the user. @@ -53,7 +56,6 @@ def forgot_password_body(email) -> str: token = generate_token(email, salt) token += "R3sET" - url = getenv("VITE_API_URL") r.setex(token, 3600, salt) full_url = url + "/reset_password/" + token @@ -92,7 +94,6 @@ def confirm_account_creation_body(email) -> str: token = generate_token(email, salt) token += "CrEaTe" - url = getenv("VITE_API_URL") r.setex(token, 3600, salt) full_url = url + "/confirm_account_creation/" + token