diff --git a/packages/backend/src/app.ts b/packages/backend/src/app.ts index 0eaf3fc..1105d47 100644 --- a/packages/backend/src/app.ts +++ b/packages/backend/src/app.ts @@ -158,6 +158,45 @@ const app = new Elysia() .execute(); }) + .post("/change-password", async ({ db, body: { username, currentPassword, newPassword }, set }) => { + + const user = await db + .selectFrom("User") + .selectAll() + .where("username", "=", username) + .executeTakeFirst(); + + if (user === undefined) { + return error("Unauthorized", "Invalid username or password"); + } + + const valid = await Bun.password.verify(currentPassword, user.password); + if (!valid) { + return error("Unauthorized", "Invalid username or password"); + } + + const password = await Bun.password.hash(newPassword); + + const res = await db + .updateTable("User") + .set({ password }) + .where("username", "=", username) + .returningAll() + .execute(); + + if (res.length === 0) { + return error("Unauthorized", "Invalid username or password"); + } + + set.status = "No Content"; + }, { + body: t.Object({ + username: t.String({ minLength: 1 }), + currentPassword: t.String({ minLength: 1 }), + newPassword: t.String({ minLength: 1 }), + }), + }) + // --- MARK: USER MANAGEMENT ------------------------------------------- .get("/user/:userId", async ({ db, params: { userId }, user }) => { diff --git a/packages/frontend/src/cache.ts b/packages/frontend/src/cache.ts index a83531d..729ba6d 100644 --- a/packages/frontend/src/cache.ts +++ b/packages/frontend/src/cache.ts @@ -105,12 +105,12 @@ export const pieceLookup = (pieceId: PieceId) => pipe( export const userCache = Effect.runSync(Cache.make({ capacity: Infinity, - timeToLive: Duration.infinity, + timeToLive: Duration.days(1), lookup: userLookup, })); export const pieceCache = Effect.runSync(Cache.make({ capacity: Infinity, - timeToLive: Infinity, + timeToLive: Duration.days(1), lookup: pieceLookup, })); diff --git a/packages/frontend/src/routes/Settings.tsx b/packages/frontend/src/routes/Settings.tsx index f3d4a0b..dfe9b1f 100644 --- a/packages/frontend/src/routes/Settings.tsx +++ b/packages/frontend/src/routes/Settings.tsx @@ -1,7 +1,100 @@ +import { client } from "@/client"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { useStore } from "@/hooks/useStore"; +import { Label } from "@radix-ui/react-label"; +import { Loader2 } from "lucide-react"; +import { FormEventHandler, useId, useState } from "react"; + export function Settings() { return ( -
-
Tutaj by były ustawienia, gdyby były.
+
+
); } + +function PasswordChangeCard() { + + const [currentPassword, setCurrentPassword] = useState(""); + const [newPassword1, setNewPassword1] = useState(""); + const [newPassword2, setNewPassword2] = useState(""); + + const currentPasswordId = useId(); + const newPassword1Id = useId(); + const newPassword2Id = useId(); + + const [isLoading, setIsLoading] = useState(false); + + const user = useStore(store => store.user); + + const onSubmit: FormEventHandler = async (e) => { + e.preventDefault(); + + try { + setIsLoading(true); + + const { error } = await client["change-password"].post({ + username: user!.username, + currentPassword, + newPassword: newPassword1, + }); + + if (error !== null) { + console.error(error.value); + return; + } + } finally { + setIsLoading(false); + } + }; + + return ( +
+ + + Zmiana hasła + + + + setCurrentPassword(e.target.value)} + /> + + setNewPassword1(e.target.value)} + /> + + setNewPassword2(e.target.value)} + /> + + + + + +
+ ); +}