From 441b636154ce02a727d98ecbaa5c60b47b81ccf4 Mon Sep 17 00:00:00 2001 From: Winston Hsiao Date: Fri, 9 Aug 2024 23:02:58 -0400 Subject: [PATCH] EmailSignUp token creation done, refined routes --- frontend/src/App.tsx | 2 +- .../src/components/auth/SignupWithEmail.tsx | 4 +-- frontend/src/gen/api.ts | 16 +++++----- frontend/src/pages/ListingDetails.tsx | 2 +- frontend/src/pages/Register.tsx | 23 +++++++------- store/app/crud/email_signup.py | 22 ++++++------- store/app/model.py | 3 +- store/app/routers/email_signup.py | 31 +++++++++++-------- 8 files changed, 54 insertions(+), 49 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 72f18110..819e4def 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -40,7 +40,7 @@ const App = () => { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/frontend/src/components/auth/SignupWithEmail.tsx b/frontend/src/components/auth/SignupWithEmail.tsx index 3b2f0156..8a5c652b 100644 --- a/frontend/src/components/auth/SignupWithEmail.tsx +++ b/frontend/src/components/auth/SignupWithEmail.tsx @@ -26,7 +26,6 @@ const SignupWithEmail = () => { }); const onSubmit = async ({ email }: EmailSignupType) => { - console.log(`email: ${email}`); const { data, error } = await auth.client.POST("/email-signup/create/", { body: { email, @@ -38,7 +37,8 @@ const SignupWithEmail = () => { } else { const responseData = data as EmailSignUpResponse; const successMessage = - responseData?.message || "Sign-up email sent! Check your inbox."; + responseData?.message || + "Sign up email sent! Follow the link sent to you to continue registration."; addAlert(successMessage, "success"); } }; diff --git a/frontend/src/gen/api.ts b/frontend/src/gen/api.ts index 10d0bc5d..e4523dd1 100644 --- a/frontend/src/gen/api.ts +++ b/frontend/src/gen/api.ts @@ -379,7 +379,7 @@ export interface paths { patch?: never; trace?: never; }; - "/email-signup/get/{token}": { + "/email-signup/get/{id}": { parameters: { query?: never; header?: never; @@ -387,7 +387,7 @@ export interface paths { cookie?: never; }; /** Get Signup Token */ - get: operations["get_signup_token_email_signup_get__token__get"]; + get: operations["get_signup_token_email_signup_get__id__get"]; put?: never; post?: never; delete?: never; @@ -396,7 +396,7 @@ export interface paths { patch?: never; trace?: never; }; - "/email-signup/delete/{token}": { + "/email-signup/delete/{id}": { parameters: { query?: never; header?: never; @@ -407,7 +407,7 @@ export interface paths { put?: never; post?: never; /** Delete Signup Token */ - delete: operations["delete_signup_token_email_signup_delete__token__delete"]; + delete: operations["delete_signup_token_email_signup_delete__id__delete"]; options?: never; head?: never; patch?: never; @@ -1272,12 +1272,12 @@ export interface operations { }; }; }; - get_signup_token_email_signup_get__token__get: { + get_signup_token_email_signup_get__id__get: { parameters: { query?: never; header?: never; path: { - token: string; + id: string; }; cookie?: never; }; @@ -1303,12 +1303,12 @@ export interface operations { }; }; }; - delete_signup_token_email_signup_delete__token__delete: { + delete_signup_token_email_signup_delete__id__delete: { parameters: { query?: never; header?: never; path: { - token: string; + id: string; }; cookie?: never; }; diff --git a/frontend/src/pages/ListingDetails.tsx b/frontend/src/pages/ListingDetails.tsx index cbf127cd..869bce4c 100644 --- a/frontend/src/pages/ListingDetails.tsx +++ b/frontend/src/pages/ListingDetails.tsx @@ -21,7 +21,7 @@ const RenderListing = (props: RenderListingProps) => { const { listing } = props; return ( -
+
{ const { addErrorAlert } = useAlertQueue(); - const { token } = useParams(); - const [emailToken, setEmailToken] = useState( + const { id } = useParams(); + const [signUpToken, setSignUpToken] = useState( null, ); const auth = useAuthentication(); useEffect(() => { - const fetchListing = async () => { - if (token === undefined) { + const fetchSignUpToken = async () => { + console.log(`id in useEffect: ${id}`); + if (id === undefined) { return; } try { const { data, error } = await auth.client.GET( - "/email-signup/get/{token}", + "/email-signup/get/{id}", { params: { - path: { token }, + path: { id }, }, }, ); if (error) { addErrorAlert(error); } else { - setEmailToken(data); + setSignUpToken(data); } } catch (err) { addErrorAlert(err); } }; - fetchListing(); - }, [token]); + fetchSignUpToken(); + }, [id]); - if (!emailToken) { + if (!signUpToken) { return (

Invalid Sign Up Link

diff --git a/store/app/crud/email_signup.py b/store/app/crud/email_signup.py index 91e73eeb..27b28bb5 100644 --- a/store/app/crud/email_signup.py +++ b/store/app/crud/email_signup.py @@ -6,20 +6,20 @@ class EmailSignUpCrud(BaseCrud): async def create_email_signup_token(self, email: str) -> EmailSignUpToken: - token = EmailSignUpToken.create(email=email) - await self._add_item(token) - return token + signup_token = EmailSignUpToken.create(email=email) + await self._add_item(signup_token) + return signup_token - async def get_email_signup_token(self, token: str) -> EmailSignUpToken | None: - return await self._get_item(token, EmailSignUpToken, throw_if_missing=False) + async def get_email_signup_token(self, id: str) -> EmailSignUpToken | None: - async def delete_email_signup_token(self, token: str) -> None: - await self._delete_item(token) + return await self._get_item(id, EmailSignUpToken, throw_if_missing=False) + + async def delete_email_signup_token(self, id: str) -> None: + await self._delete_item(id) async def test_adhoc() -> None: async with EmailSignUpCrud() as crud: - token = await crud.create_email_signup_token(email="test@example.com") - retrieved_token = await crud.get_email_signup_token(token.token) - print(f"Retrieved Token: {retrieved_token}") - await crud.delete_email_signup_token(token.token) + signup_token = await crud.create_email_signup_token(email="test@example.com") + await crud.get_email_signup_token(signup_token.id) + await crud.delete_email_signup_token(signup_token.id) diff --git a/store/app/model.py b/store/app/model.py index e0634eff..6b15f7b8 100644 --- a/store/app/model.py +++ b/store/app/model.py @@ -80,11 +80,10 @@ class EmailSignUpToken(RobolistBaseModel): """ email: EmailStr - token: str @classmethod def create(cls, email: str) -> Self: - return cls(email=email, token=new_uuid()) + return cls(id=new_uuid(), email=email) class OAuthKey(RobolistBaseModel): diff --git a/store/app/routers/email_signup.py b/store/app/routers/email_signup.py index 82aea647..71ded152 100644 --- a/store/app/routers/email_signup.py +++ b/store/app/routers/email_signup.py @@ -3,7 +3,8 @@ from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel, EmailStr -from store.app.crud.users import UserCrud +from store.app.crud.email_signup import EmailSignUpCrud +from store.app.utils.email import send_register_email email_signup_router = APIRouter() @@ -29,27 +30,31 @@ class DeleteTokenResponse(BaseModel): # POST: Create Signup Token @email_signup_router.post("/create/", response_model=EmailSignUpResponse) -async def create_signup_token(data: EmailSignUpRequest, crud: UserCrud = Depends()) -> EmailSignUpResponse: - try: - await crud.create_email_signup_token(data.email) - return {"message": "Sign-up token created successfully."} - except Exception as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) +async def create_signup_token(data: EmailSignUpRequest) -> EmailSignUpResponse: + async with EmailSignUpCrud() as crud: + try: + signup_token = await crud.create_email_signup_token(data.email) + await send_register_email(email=data.email, token=signup_token.id) + + return {"message": "Sign up email sent! Follow the link sent to you to continue registration."} + except Exception as e: + print(f"Error creating signup token: {e}") + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) # GET: Retrieve Signup Token -@email_signup_router.get("/get/{token}", response_model=GetTokenResponse) -async def get_signup_token(token: str, crud: UserCrud = Depends()) -> GetTokenResponse: - signup_token = await crud.get_email_signup_token(token) +@email_signup_router.get("/get/{id}", response_model=GetTokenResponse) +async def get_signup_token(id: str, crud: EmailSignUpCrud = Depends()) -> GetTokenResponse: + signup_token = await crud.get_email_signup_token(id) if not signup_token: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Token not found.") return signup_token # DELETE: Delete Signup Token -@email_signup_router.delete("/delete/{token}", response_model=DeleteTokenResponse) -async def delete_signup_token(token: str, crud: UserCrud = Depends()) -> DeleteTokenResponse: - deleted = await crud.delete_email_signup_token(token) +@email_signup_router.delete("/delete/{id}", response_model=DeleteTokenResponse) +async def delete_signup_token(id: str, crud: EmailSignUpCrud = Depends()) -> DeleteTokenResponse: + deleted = await crud.delete_email_signup_token(id) if not deleted: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Token not found.") return {"message": "Token deleted successfully."}