Compare commits
12 changed files with 27 additions and 162 deletions
|
|
@ -2,16 +2,12 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { login, signup } from "@/lib/server_functions/userAuth";
|
import { login, signup } from "@/lib/server_functions/userAuth";
|
||||||
import Form from "@/components/ui/Form";
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
const [createAccount, setCreateAccount] = useState(false);
|
const [createAccount, setCreateAccount] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full justify-center py-10">
|
<div>
|
||||||
<Form
|
<form action={createAccount ? login : signup}>
|
||||||
action={createAccount ? login : signup}
|
|
||||||
submitText={createAccount ? "Login" : "Signup"}
|
|
||||||
>
|
|
||||||
<input type="text" name="username" placeholder="Username" required />
|
<input type="text" name="username" placeholder="Username" required />
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
|
|
@ -19,12 +15,11 @@ export default function Login() {
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<button onClick={() => setCreateAccount(!createAccount)}>
|
<button type="submit">{createAccount ? "Login" : "Signup"}</button>
|
||||||
{createAccount
|
</form>
|
||||||
? "Don't have an account?"
|
<button onClick={() => setCreateAccount(!createAccount)}>
|
||||||
: "Already have an account?"}
|
{createAccount ? "Don't have an account?" : "Already have an account?"}
|
||||||
</button>
|
</button>
|
||||||
</Form>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import ProtectedRoute from "@/components/wrappers/ProtectedRoute";
|
export default function AdminLayout({children}: {children: React.ReactNode}) {
|
||||||
|
|
||||||
export default async function AdminLayout({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
// TODO: Put user state management here
|
// TODO: Put user state management here
|
||||||
//redirect("wherever state says") <= stateRouteManager()
|
//redirect("wherever state says") <= stateRouteManager()
|
||||||
return <ProtectedRoute>{children}</ProtectedRoute>;
|
return (
|
||||||
}
|
<div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import UnderConstruction from "@/components/static_pages/UnderConstruction";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
export default function Admin() {
|
export default function Admin() {
|
||||||
return <UnderConstruction />;
|
// TODO: Replace with Layout State Manager
|
||||||
|
redirect("/Admin/Login");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,7 @@
|
||||||
const BACKEND_URL = process.env.BACKEND_URL;
|
const BACKEND_URL = process.env.BACKEND_URL;
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
const response = await fetch(`${BACKEND_URL}/users/auth`, {
|
const response = await fetch(`${BACKEND_URL}/users/auth`, request);
|
||||||
method: "POST",
|
|
||||||
headers: request.headers,
|
|
||||||
body: request.body,
|
|
||||||
duplex: "half",
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,7 @@ export async function GET() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
const response = await fetch(`${BACKEND_URL}/users`, {
|
const response = await fetch(`${BACKEND_URL}/users`, request);
|
||||||
method: "POST",
|
|
||||||
headers: request.headers,
|
|
||||||
body: request.body,
|
|
||||||
duplex: "half",
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,7 @@
|
||||||
const BACKEND_URL = process.env.BACKEND_URL;
|
const BACKEND_URL = process.env.BACKEND_URL;
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
export async function GET() {
|
||||||
const authorization = request.headers.get("authorization");
|
const response = await fetch(`${BACKEND_URL}/users/user`);
|
||||||
|
|
||||||
const response = await fetch(`${BACKEND_URL}/users/user`, {
|
|
||||||
headers: {
|
|
||||||
Authorization: authorization ?? "",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return new Response("Request failed in backend", {
|
return new Response("Request failed in backend", {
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import RoundedContainer from "./RoundedContainer";
|
|
||||||
|
|
||||||
export default function Form({
|
|
||||||
action,
|
|
||||||
children,
|
|
||||||
submitText,
|
|
||||||
}: {
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
action?: string | ((formData: FormData) => void | Promise<void>);
|
|
||||||
children: React.ReactNode;
|
|
||||||
submitText: string;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<form action={action}>
|
|
||||||
<RoundedContainer slim={false}>
|
|
||||||
{children}
|
|
||||||
<button type="submit">{submitText}</button>
|
|
||||||
</RoundedContainer>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
|
|
||||||
import { verifySession } from "@/lib/server_functions/dataAccessLayer";
|
|
||||||
|
|
||||||
export default async function ProtectedRoute({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
const session = await verifySession();
|
|
||||||
if (!session.isAuthed) {
|
|
||||||
redirect("/Authentication/Login");
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div>{children}</div>;
|
|
||||||
}
|
|
||||||
|
|
@ -14,18 +14,3 @@ export async function cmFetch<T>(
|
||||||
|
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cmFetchRaw(
|
|
||||||
bffUrl: string | URL,
|
|
||||||
options?: RequestInit,
|
|
||||||
ignoreStatuses?: number[],
|
|
||||||
): Promise<Response> {
|
|
||||||
const response = await fetch(`${FRONTEND_URL}/${bffUrl}`, options);
|
|
||||||
|
|
||||||
if (!response.ok && !ignoreStatuses?.includes(response.status)) {
|
|
||||||
throw new Error("Request failed");
|
|
||||||
}
|
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,24 @@
|
||||||
import { getSessionToken } from "@/lib/server_functions/userAuth";
|
import { cmFetch } from "../cmFetch";
|
||||||
|
|
||||||
import { cmFetch, cmFetchRaw } from "../cmFetch";
|
|
||||||
import { Token, User } from "../types";
|
import { Token, User } from "../types";
|
||||||
|
|
||||||
export async function getUsers() {
|
export async function getUsers() {
|
||||||
return cmFetch<User[]>(`/api/users`);
|
return cmFetch<User[]>(`/api/users`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCurrentUser() {
|
|
||||||
return cmFetchRaw(
|
|
||||||
`/api/users/user`,
|
|
||||||
{ headers: { Authorization: `Bearer ${await getSessionToken()}` } },
|
|
||||||
[401],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getUser(id: number) {
|
export async function getUser(id: number) {
|
||||||
return cmFetch<User>(`/api/users/${id}`);
|
return cmFetch<User>(`/api/users/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loginUser(user: FormData) {
|
export async function loginUser(user: FormData) {
|
||||||
const body = {
|
|
||||||
username: user.get("username"),
|
|
||||||
password: user.get("password"),
|
|
||||||
};
|
|
||||||
return cmFetch<Token>(`/api/users/login`, {
|
return cmFetch<Token>(`/api/users/login`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
body: user,
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createUser(user: FormData) {
|
export async function createUser(user: FormData) {
|
||||||
const body = {
|
|
||||||
username: user.get("username"),
|
|
||||||
password: user.get("password"),
|
|
||||||
authority: 0,
|
|
||||||
};
|
|
||||||
return cmFetch<Token>(`/api/users`, {
|
return cmFetch<Token>(`/api/users`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
body: user,
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import { cookies } from "next/headers";
|
|
||||||
import { cache } from "react";
|
|
||||||
|
|
||||||
import "server-only";
|
|
||||||
import { getCurrentUser } from "../api/helpers/users";
|
|
||||||
import { User } from "../api/types";
|
|
||||||
|
|
||||||
export const verifySession = cache(async () => {
|
|
||||||
const cookie = (await cookies()).get("access_token")?.value;
|
|
||||||
if (!cookie) {
|
|
||||||
return { isAuthed: false };
|
|
||||||
}
|
|
||||||
const response = await getCurrentUser();
|
|
||||||
if (response.status == 401) {
|
|
||||||
return { isAuthed: false };
|
|
||||||
}
|
|
||||||
const user = (await response.json()) as User;
|
|
||||||
return {
|
|
||||||
isAuthed: true,
|
|
||||||
surface_auth_level: user.authority,
|
|
||||||
username: user.username,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
@ -9,7 +9,7 @@ export async function login(formData: FormData) {
|
||||||
"use server";
|
"use server";
|
||||||
const token = await loginUser(formData);
|
const token = await loginUser(formData);
|
||||||
await createSession(token);
|
await createSession(token);
|
||||||
redirect("/Admin/Overview");
|
redirect("/admin/overview");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signup(formData: FormData) {
|
export async function signup(formData: FormData) {
|
||||||
|
|
@ -17,7 +17,7 @@ export async function signup(formData: FormData) {
|
||||||
"use server";
|
"use server";
|
||||||
const token = await createUser(formData);
|
const token = await createUser(formData);
|
||||||
await createSession(token);
|
await createSession(token);
|
||||||
redirect("/Admin/Overview");
|
redirect("/admin/overview");
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createSession(token: Token) {
|
export async function createSession(token: Token) {
|
||||||
|
|
@ -26,16 +26,8 @@ export async function createSession(token: Token) {
|
||||||
|
|
||||||
cookieStore.set("access_token", access_token, {
|
cookieStore.set("access_token", access_token, {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: process.env.NODE_ENV === "production",
|
secure: true,
|
||||||
sameSite: "lax",
|
sameSite: "lax",
|
||||||
path: "/",
|
path: "/",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSessionToken() {
|
|
||||||
const cookieStore = await cookies();
|
|
||||||
console.log(cookieStore.getAll());
|
|
||||||
const token = cookieStore.get("access_token")?.value;
|
|
||||||
|
|
||||||
return token ? token : null;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue