From bc06a2760b08a9902e5d78130b60f81207104cbf Mon Sep 17 00:00:00 2001 From: H1ghBre4k3r Date: Sun, 3 Nov 2024 21:47:58 +0100 Subject: [PATCH] feat(auth): add possibility to register new users --- src/App.css | 4 --- src/contexts/auth.tsx | 46 +++++++++++++++++------------ src/index.css | 9 ++++++ src/routes/index.tsx | 15 +++++++--- src/routes/login.css | 6 ---- src/routes/login.tsx | 34 ++++++++++++--------- src/routes/register.tsx | 65 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 133 insertions(+), 46 deletions(-) delete mode 100644 src/routes/login.css create mode 100644 src/routes/register.tsx diff --git a/src/App.css b/src/App.css index a9cfc8c..858e1cd 100644 --- a/src/App.css +++ b/src/App.css @@ -4,7 +4,3 @@ /* justify-content: center; */ /* align-items: center; */ /* } */ - -main { - padding-top: 80px; -} diff --git a/src/contexts/auth.tsx b/src/contexts/auth.tsx index 7645a94..7bbf111 100644 --- a/src/contexts/auth.tsx +++ b/src/contexts/auth.tsx @@ -6,14 +6,15 @@ import { useState, } from "react"; import { useAppwrite } from "../hooks/useAppwrite"; -import { Account, Models } from "appwrite"; +import { Account, AppwriteException, ID, Models } from "appwrite"; export type AuthContextValue = { session?: Models.Session; user?: Models.User; loggedIn: boolean; - login(username: string, password: string): Promise; + login(email: string, password: string): Promise; logout(): Promise; + register(email: string, password: string, name: string): Promise; }; export const AuthContext = createContext({} as AuthContextValue); @@ -42,23 +43,21 @@ export function AuthContextProvider({ children }: PropsWithChildren) { .catch(() => {}); }, [account]); - async function login(username: string, password: string): Promise { - try { - const session = await account.createEmailPasswordSession( - username, - password, - ); + async function login(email: string, password: string): Promise { + const session = await account.createEmailPasswordSession(email, password); - account - .get() - .then((user) => { - setSession(session); - setUser(user); - }) - .catch(() => account.deleteSession("current")); - } catch (e) { - console.error(e); - } + account + .get() + .then((user) => { + if (!user.emailVerification) { + throw new AppwriteException( + "Please verify your email before logging in!", + ); + } + setSession(session); + setUser(user); + }) + .catch(() => account.deleteSession("current")); } async function logout(): Promise { @@ -71,10 +70,19 @@ export function AuthContextProvider({ children }: PropsWithChildren) { } } + async function register( + email: string, + password: string, + name: string, + ): Promise { + await account.create(ID.unique(), email, password, name); + } + const value = { login, - session, logout, + register, + session, user, loggedIn: !!(session && user), }; diff --git a/src/index.css b/src/index.css index e69de29..0d2e8c4 100644 --- a/src/index.css +++ b/src/index.css @@ -0,0 +1,9 @@ +main { + padding-top: 60px; +} + +form { + display: flex; + flex-direction: column; + gap: 20px; +} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 2241f5d..efb96c7 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -8,6 +8,7 @@ import { useAuth } from "../hooks/useAuth"; import { Login } from "./login"; import ErrorPage from "./error"; import { Main } from "./main"; +import { Register } from "./register"; export function Router() { const { loggedIn } = useAuth(); @@ -19,10 +20,16 @@ export function Router() { ]; if (!loggedIn) { - children.push({ - path: "/login", - element: , - }); + children.push( + { + path: "/login", + element: , + }, + { + path: "/register", + element: , + }, + ); } const routes: RouteObject[] = [ diff --git a/src/routes/login.css b/src/routes/login.css deleted file mode 100644 index d0036b4..0000000 --- a/src/routes/login.css +++ /dev/null @@ -1,6 +0,0 @@ -.login-form { - display: flex; - flex-direction: column; - gap: 20px; - width: 100%; -} diff --git a/src/routes/login.tsx b/src/routes/login.tsx index def5ab1..531a6d1 100644 --- a/src/routes/login.tsx +++ b/src/routes/login.tsx @@ -1,9 +1,8 @@ -import { useState } from "react"; +import { FormEvent, useState } from "react"; import { useAuth } from "../hooks/useAuth"; -import { Button, FormControl, TextField } from "@mui/material"; +import { Alert, Button, Container, TextField } from "@mui/material"; import { useNavigate } from "react-router-dom"; - -import "./login.css"; +import { AppwriteException } from "appwrite"; export function Login() { const navigate = useNavigate(); @@ -12,26 +11,35 @@ export function Login() { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); - function onSubmit() { + const [err, setErr] = useState(); + + function onSubmit(e: FormEvent) { + e.preventDefault(); auth .login(username, password) .then(() => { navigate("/"); }) - .catch(console.error); + .catch((e: AppwriteException | unknown) => { + if (e instanceof AppwriteException) { + setErr(e.message); + } + console.log(e); + }); } return ( - <> +

Login

- +
+ {err && {err}} setUsername(e.target.value)} variant="standard" - label="Username" + label="EMail" /> setPassword(e.target.value)} variant="standard" /> - - - + + +
); } diff --git a/src/routes/register.tsx b/src/routes/register.tsx new file mode 100644 index 0000000..ed1fcf5 --- /dev/null +++ b/src/routes/register.tsx @@ -0,0 +1,65 @@ +import { useNavigate } from "react-router-dom"; +import { useAuth } from "../hooks/useAuth"; +import { FormEvent, useState } from "react"; +import { Alert, Button, Container, TextField } from "@mui/material"; +import { AppwriteException } from "appwrite"; + +export function Register() { + const navigate = useNavigate(); + const auth = useAuth(); + + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [name, setName] = useState(""); + + const [err, setErr] = useState(); + + function onSubmit(e: FormEvent) { + e.preventDefault(); + auth + .register(email, password, name) + .then(() => { + navigate("/"); + }) + .catch((e: AppwriteException | unknown) => { + if (e instanceof AppwriteException) { + setErr(e.message); + } + console.log(e); + }); + } + + return ( + +

Register

+
+ {err && {err}} + setName(e.target.value)} + variant="standard" + label="Username" + /> + setEmail(e.target.value)} + variant="standard" + label="EMail" + /> + setPassword(e.target.value)} + variant="standard" + /> + + +
+ ); +}