working sessions
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import axios, { HttpStatusCode } from "axios";
|
||||
import { NextResponse } from "next/server";
|
||||
import { findKey, sessions, users } from "../data";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json();
|
||||
|
||||
if (!body.username || !body.password)
|
||||
return NextResponse.json(
|
||||
{ message: "Credentials are empty" },
|
||||
{ status: HttpStatusCode.BadRequest }
|
||||
);
|
||||
|
||||
const uuid = findKey(
|
||||
users,
|
||||
(u) => u.username == body.username && u.password == body.password
|
||||
);
|
||||
|
||||
if (!uuid) {
|
||||
return NextResponse.json(
|
||||
{ message: "Invalid username or password" },
|
||||
{ status: HttpStatusCode.BadRequest }
|
||||
);
|
||||
}
|
||||
|
||||
const sessionId = "SESH-" + crypto.randomUUID();
|
||||
|
||||
sessions[sessionId] = uuid;
|
||||
|
||||
return NextResponse.json({ message: "ok", sessionId });
|
||||
}
|
||||
|
||||
export async function GET(request: Request) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
|
||||
const id = searchParams.get("id") || "";
|
||||
|
||||
if (!sessions[id])
|
||||
return NextResponse.json(
|
||||
{ message: "Invalid session" },
|
||||
{ status: HttpStatusCode.Unauthorized }
|
||||
);
|
||||
|
||||
return NextResponse.json({ message: "ok" });
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
export function findKey<T extends object>(
|
||||
obj: T,
|
||||
predicate: (value: T[keyof T], key: keyof T) => boolean
|
||||
): keyof T | undefined {
|
||||
return Object.entries(obj).find(([key, value]) =>
|
||||
predicate(value as T[keyof T], key as keyof T)
|
||||
)?.[0] as keyof T | undefined;
|
||||
}
|
||||
|
||||
export type User = {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
export const users = {
|
||||
admin: {
|
||||
username: "admin",
|
||||
password: "admin",
|
||||
},
|
||||
};
|
||||
|
||||
export const sessions: { [key: string]: string } = {};
|
||||
@@ -0,0 +1,5 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json({ message: "ok", version: "0.0.1" });
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import getSession from "@/hooks/getSession";
|
||||
|
||||
export default async function Dashboard() {
|
||||
const session = await getSession();
|
||||
|
||||
}
|
||||
+58
-5
@@ -1,18 +1,71 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export default function Login() {
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const router = useRouter();
|
||||
|
||||
const login = () => {
|
||||
setError("");
|
||||
axios({
|
||||
method: "post",
|
||||
url: "/api/auth",
|
||||
data: {
|
||||
username,
|
||||
password,
|
||||
},
|
||||
})
|
||||
.then((r) => {
|
||||
Cookies.set("session_id", r.data.sessionId);
|
||||
router.replace("/dashboard");
|
||||
})
|
||||
.catch((e) => {
|
||||
setError(e.response.data.message);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<Card className="h-max w-[25rem] px-8 pb-10">
|
||||
<Card className="h-max w-[25rem] px-8 pb-8 gap-3">
|
||||
<h1 className="text-4xl font-bold text-center mt-5">Login</h1>
|
||||
<Label>Username</Label>
|
||||
<Input placeholder="Enter your username" />
|
||||
<Label>Password</Label>
|
||||
<Input placeholder="Enter your password" type="password" />
|
||||
<Button>Login</Button>
|
||||
<Input
|
||||
placeholder="Enter your username"
|
||||
onInput={(e) => {
|
||||
setUsername((e.target as any).value);
|
||||
}}
|
||||
/>
|
||||
<Label className="mt-1">Password</Label>
|
||||
<Input
|
||||
placeholder="Enter your password"
|
||||
type="password"
|
||||
onInput={(e) => {
|
||||
setPassword((e.target as any).value);
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key == "Enter" && username != "" && password != "") {
|
||||
login();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{error ? <Label className="text-destructive">{error}</Label> : ""}
|
||||
<Button
|
||||
className="w-max mx-auto mt-3"
|
||||
onClick={login}
|
||||
disabled={username == "" || password == ""}
|
||||
>
|
||||
Login
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
+7
-3
@@ -1,6 +1,10 @@
|
||||
import getSession from "@/hooks/getSession";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function Home() {
|
||||
redirect("/login");
|
||||
return <div>Hello, World!</div>;
|
||||
export default async function Home() {
|
||||
const session = await getSession();
|
||||
if (session) {
|
||||
redirect("/dashboard");
|
||||
}
|
||||
return <div>Redirecting..</div>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { cookies } from "next/headers";
|
||||
import axios from "axios";
|
||||
import Session from "@/lib/session";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default async function getSession(): Promise<Session | null> {
|
||||
const cookieStore = await cookies();
|
||||
const sessionId = cookieStore.get("session_id")?.value;
|
||||
|
||||
if (!sessionId) {
|
||||
redirect("/login");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
await axios.get("http://localhost:3000/api/auth", {
|
||||
params: { id: sessionId },
|
||||
});
|
||||
|
||||
return new Session(sessionId);
|
||||
} catch (err) {
|
||||
redirect("/login");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import axios from "axios";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import Session from "@/lib/session";
|
||||
|
||||
export default function useSession() {
|
||||
const router = useRouter();
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const id = Cookies.get("session_id");
|
||||
|
||||
if (id)
|
||||
axios({
|
||||
method: "get",
|
||||
url: "/api/auth",
|
||||
params: { id },
|
||||
})
|
||||
.then((r) => {
|
||||
setSession(new Session(id));
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
router.replace("/login");
|
||||
});
|
||||
});
|
||||
|
||||
return session;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default class Session {
|
||||
id: string;
|
||||
|
||||
constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user