From 8cc727e30942b3138b5486d86ad81679e535a2c1 Mon Sep 17 00:00:00 2001 From: swve Date: Thu, 22 Sep 2022 22:17:27 +0200 Subject: [PATCH] feat: init login & register from frontend --- app.py | 18 ++++++++---- front/pages/login.tsx | 2 ++ front/pages/signup.tsx | 2 ++ front/services/auth.ts | 61 ++++++++++++++++++++++++++++++++++++++++ front/services/config.ts | 3 ++ src/routers/auth.py | 2 +- src/services/auth.py | 4 +-- src/services/users.py | 12 ++++---- 8 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 front/services/auth.ts create mode 100644 front/services/config.ts diff --git a/app.py b/app.py index b1cc30d3..63093868 100644 --- a/app.py +++ b/app.py @@ -1,9 +1,7 @@ -from typing import Union from fastapi import FastAPI -from src import main -from fastapi.staticfiles import StaticFiles from src.main import global_router -import pymongo +from fastapi.middleware.cors import CORSMiddleware + # Init app = FastAPI( @@ -12,9 +10,19 @@ app = FastAPI( version="0.1.0", root_path="/" ) +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_methods=["*"], + allow_credentials=True, + allow_headers=["*"], +) app.include_router(global_router) + + @app.get("/") async def root(): - return {"Message": "Welcome to LearnHouse ✨"} \ No newline at end of file + return {"Message": "Welcome to LearnHouse ✨"} + diff --git a/front/pages/login.tsx b/front/pages/login.tsx index f888e029..8f36941c 100644 --- a/front/pages/login.tsx +++ b/front/pages/login.tsx @@ -1,6 +1,7 @@ import React from "react"; import Layout from "../components/ui/layout"; import { Title } from "../components/ui/styles/title"; +import { loginAndGetToken } from "../services/auth"; const Login = () => { const [email, setEmail] = React.useState(""); @@ -10,6 +11,7 @@ const Login = () => { e.preventDefault(); console.log({ email, password }); alert(JSON.stringify({ email, password })); + loginAndGetToken(email, password); }; const handleEmailChange = (e: any) => { diff --git a/front/pages/signup.tsx b/front/pages/signup.tsx index 41359817..5d45a404 100644 --- a/front/pages/signup.tsx +++ b/front/pages/signup.tsx @@ -1,6 +1,7 @@ import React from "react"; import Layout from "../components/ui/layout"; import { Title } from "../components/ui/styles/title"; +import { signup } from "../services/auth"; const SignUp = () => { const [email, setEmail] = React.useState(""); @@ -11,6 +12,7 @@ const SignUp = () => { e.preventDefault(); console.log({ email, password, username }); alert(JSON.stringify({ email, password, username })); + signup({ email, password, username }); }; const handleEmailChange = (e: any) => { diff --git a/front/services/auth.ts b/front/services/auth.ts new file mode 100644 index 00000000..244ec5f9 --- /dev/null +++ b/front/services/auth.ts @@ -0,0 +1,61 @@ +import { getAPIUrl } from "./config"; + +interface LoginAndGetTokenResponse { + access_token: "string"; + token_type: "string"; +} + +// TODO : everything in this file need to be refactored / mvp phase + +export async function loginAndGetToken(username: string, password: string): Promise { + // Request Config + const HeadersConfig = new Headers({ "Content-Type": "application/x-www-form-urlencoded", Origin: "http://localhost:3000" }); + const urlencoded = new URLSearchParams({ username: username, password: password }); + + const requestOptions: any = { + method: "POST", + headers: HeadersConfig, + body: urlencoded, + redirect: "follow", + }; + + return fetch(`${getAPIUrl()}auth/token`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); +} + +export async function getUserInfo(token: string): Promise { + const HeadersConfig = new Headers({ Authorization: `Bearer ${token}`, Origin: "http://localhost:3000" }); + const requestOptions: any = { + method: "GET", + headers: HeadersConfig, + redirect: "follow", + }; + + return fetch(`${getAPIUrl()}auth/users/me`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); +} + +// signup + +interface NewAccountBody { + username: string; + email: string; + password: string; +} + +export async function signup(body: NewAccountBody): Promise { + const HeadersConfig = new Headers({ "Content-Type": "application/json" }); + + const requestOptions: any = { + method: "POST", + headers: HeadersConfig, + body: JSON.stringify(body), + redirect: "follow", + }; + + return fetch(`${getAPIUrl()}users/`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); +} diff --git a/front/services/config.ts b/front/services/config.ts new file mode 100644 index 00000000..bdc1713f --- /dev/null +++ b/front/services/config.ts @@ -0,0 +1,3 @@ +const LEARNHOUSE_API_URL = "http://localhost:1338/api/"; + +export const getAPIUrl = () => LEARNHOUSE_API_URL; diff --git a/src/routers/auth.py b/src/routers/auth.py index 49aef977..da46b4b5 100644 --- a/src/routers/auth.py +++ b/src/routers/auth.py @@ -17,7 +17,7 @@ async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends( if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, - detail="Incorrect username or password", + detail="Incorrect Email or password", headers={"WWW-Authenticate": "Bearer"}, ) access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) diff --git a/src/services/auth.py b/src/services/auth.py index d3dcc4ee..1fbe29ba 100644 --- a/src/services/auth.py +++ b/src/services/auth.py @@ -23,8 +23,8 @@ class TokenData(BaseModel): #### Classes #################################################### -async def authenticate_user(username: str, password: str): - user = await security_get_user(username) +async def authenticate_user(email: str, password: str): + user = await security_get_user(email) if not user: return False if not await security_verify_password(password, user.password): diff --git a/src/services/users.py b/src/services/users.py index e6d0895d..47104981 100644 --- a/src/services/users.py +++ b/src/services/users.py @@ -12,10 +12,10 @@ class User(BaseModel): username: str email: str full_name: str | None = None - disabled: bool | None = None + disabled: bool | None = False avatar_url: str | None = None - verified: bool - user_type: str + verified: bool | None = False + user_type: str | None = None bio: str | None = None @@ -69,15 +69,15 @@ async def get_user_by_userid(user_id: str): return user -async def security_get_user(username: str): +async def security_get_user(email: str): check_database() users = learnhouseDB["users"] - user = users.find_one({"username": username}) + user = users.find_one({"email": email}) if not user: raise HTTPException( - status_code=status.HTTP_409_CONFLICT, detail="User does not exist") + status_code=status.HTTP_409_CONFLICT, detail="User with Email does not exist") return UserInDB(**user)