commit working state
This commit is contained in:
40
src/app/admin/login/page.tsx
Normal file
40
src/app/admin/login/page.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
'use client'
|
||||
|
||||
import { authenticate } from '@/app/lib/actions'
|
||||
import { useFormState, useFormStatus } from "react-dom";
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
|
||||
export default function Page(state:any) {
|
||||
const [loginResult, dispatch] = useFormState(authenticate, undefined)
|
||||
console.log(dispatch);
|
||||
|
||||
console.log(state);
|
||||
// if(loginResult?.cookie && loginResult.cookie){
|
||||
// cookies().set('auth',loginResult.cookie['auth'])
|
||||
// }
|
||||
|
||||
return (
|
||||
<main className="h-screen w-screen flex flex-col p-10 bg-background-500 box-border m-0">
|
||||
<form action={dispatch}>
|
||||
<input type="text" name="username" placeholder="Username" required />
|
||||
<input type="password" name="password" placeholder="Password" required />
|
||||
<div>{loginResult?.errorMessage && <p>{loginResult?.errorMessage}</p>}</div>
|
||||
<LoginButton />
|
||||
</form>
|
||||
<div>
|
||||
<p>{""+loginResult?.cookie}</p>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
function LoginButton() {
|
||||
const { pending } = useFormStatus()
|
||||
|
||||
return (
|
||||
<button aria-disabled={pending} className="mr-auto bg-secondary-200 outline outline-2 border-5 p-3 mt-3 rounded-lg outline-secondary-500 shadow-primary" type="submit">
|
||||
Login
|
||||
</button>
|
||||
)
|
||||
}
|
||||
@@ -1,58 +1,13 @@
|
||||
'use client'
|
||||
import Container from 'react-bootstrap/Container';
|
||||
import Nav from 'react-bootstrap/Nav';
|
||||
import Navbar from 'react-bootstrap/Navbar';
|
||||
import NavDropdown from 'react-bootstrap/NavDropdown';
|
||||
import Button from 'react-bootstrap/Button';
|
||||
import Form from 'react-bootstrap/Form';
|
||||
import AdminPanel from "@/components/admin/adminPanel";
|
||||
import AuthHandler from "@/components/admin/authHandler";
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
|
||||
export default function Page(){
|
||||
return <div>
|
||||
<Navbar bg="light" expand="lg">
|
||||
<Container>
|
||||
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
<Nav className="me-auto">
|
||||
<Nav.Link href="#home">Home</Nav.Link>
|
||||
<Nav.Link href="#link">Link</Nav.Link>
|
||||
<NavDropdown title="Dropdown" id="basic-nav-dropdown">
|
||||
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
|
||||
<NavDropdown.Item href="#action/3.2">
|
||||
Another action
|
||||
</NavDropdown.Item>
|
||||
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
|
||||
<NavDropdown.Divider />
|
||||
<NavDropdown.Item href="#action/3.4">
|
||||
Separated link
|
||||
</NavDropdown.Item>
|
||||
</NavDropdown>
|
||||
</Nav>
|
||||
</Navbar.Collapse>
|
||||
</Container>
|
||||
</Navbar>
|
||||
<Container style={{width:"800px"}}>
|
||||
<Form>
|
||||
<Form.Group className="mb-3" controlId="formBasicEmail">
|
||||
<Form.Label>Email address</Form.Label>
|
||||
<Form.Control type="email" placeholder="Enter email" />
|
||||
<Form.Text className="text-muted">
|
||||
We'll never share your email with anyone else.
|
||||
</Form.Text>
|
||||
</Form.Group>
|
||||
|
||||
<Form.Group className="mb-3" controlId="formBasicPassword">
|
||||
<Form.Label>Password</Form.Label>
|
||||
<Form.Control type="password" placeholder="Password" />
|
||||
</Form.Group>
|
||||
<Form.Group className="mb-3" controlId="formBasicCheckbox">
|
||||
<Form.Check type="checkbox" label="Check me out" />
|
||||
</Form.Group>
|
||||
<Button variant="primary" type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</Container>
|
||||
</div>
|
||||
export default async function Page(){
|
||||
return (
|
||||
<main className="h-screen w-screen flex flex-col p-10 bg-background-500 box-border m-0">
|
||||
<AuthHandler params={null}><AdminPanel><p>this is only shown on the admin panel</p></AdminPanel></AuthHandler>
|
||||
<section>{JSON.stringify(cookies().getAll())}</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ export async function GET(request:Request, { params }: {params:{slug: string}}){
|
||||
// @ts-ignore
|
||||
cookies().set('name', 'lee');
|
||||
return Response.json({
|
||||
"a": "kanker",
|
||||
"a": "lorem",
|
||||
"b": params
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ async function tryAuth(request:Request){
|
||||
return new Response("error",{status:500});
|
||||
|
||||
|
||||
const kanker = await authentication.getUser();
|
||||
const authUser = await authentication.getUser();
|
||||
|
||||
// @ts-ignore
|
||||
cookies().set('auth', JSON.stringify(authentication));
|
||||
@@ -51,7 +51,7 @@ async function tryAuth(request:Request){
|
||||
{
|
||||
credentials: userAuth,
|
||||
auth: authentication,
|
||||
kanker: kanker,
|
||||
user: authUser,
|
||||
foundAuth: foundAuth
|
||||
}),
|
||||
{
|
||||
|
||||
64
src/app/api/auth/validate/route.ts
Normal file
64
src/app/api/auth/validate/route.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
'use server'
|
||||
|
||||
import { Model } from "sequelize";
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
import { Auth, Post, User } from "@/model/sequelize/NewModels";
|
||||
|
||||
|
||||
import { APIError} from "@/api/error"
|
||||
import { UserAuth, parseBasicAuth, getAssociatedUser } from "@/api/user"
|
||||
|
||||
|
||||
async function tryAuth(request:Request){
|
||||
|
||||
// await User.sync();
|
||||
await Auth.sync();
|
||||
|
||||
|
||||
const koek = cookies().get('auth');
|
||||
if(!koek){
|
||||
return new Response("unauthorized",{status:403});
|
||||
}
|
||||
console.log(koek);
|
||||
const auth = JSON.parse(koek.value);
|
||||
|
||||
const authentication = await Auth.findOne( { include: 'user', where: {token:auth.token} })
|
||||
|
||||
|
||||
if(!authentication)
|
||||
return new Response("unauthorized: invalid token",{status:403});
|
||||
|
||||
|
||||
const authUser = await authentication.getUser();
|
||||
|
||||
// @ts-ignore
|
||||
cookies().set('auth', JSON.stringify(authentication));
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(
|
||||
{
|
||||
auth: authentication,
|
||||
}),
|
||||
{
|
||||
status: 200,
|
||||
headers:{
|
||||
"Content-Type": "text/JSON"
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function POST(request:Request){
|
||||
try{
|
||||
return await tryAuth(request);
|
||||
}
|
||||
catch(e){
|
||||
if (e instanceof APIError){
|
||||
return new Response(e.info.responseText,{status:e.info.status});
|
||||
}
|
||||
else{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
'use server'
|
||||
|
||||
import { User, Auth, Post } from "@/model/sequelize/NewModels"
|
||||
import { User, Auth, Post, UserPerms } from "@/model/sequelize/NewModels"
|
||||
import { APIError } from "@/api/error";
|
||||
import { UserAuth } from "@/api/user";
|
||||
import { hashPassword } from "@/util/Auth";
|
||||
@@ -24,7 +24,16 @@ async function tryRegister(request:Request){
|
||||
const hash = await hashPassword(requestBody.password);
|
||||
const user = await User.create({
|
||||
username: requestBody.username,
|
||||
password: hash
|
||||
password: hash,
|
||||
perms:{
|
||||
isAdmin: false
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
include: [{
|
||||
association: 'perms'
|
||||
}]
|
||||
})
|
||||
|
||||
return new Response(
|
||||
@@ -58,7 +67,19 @@ export async function POST(request:Request){
|
||||
|
||||
async function tryGetUsers(request:Request){
|
||||
|
||||
const users = await User.findAll({include: "authtokens"});
|
||||
const defaultScope:any = User.scope('defaultScope');
|
||||
|
||||
const mergedInclude = defaultScope.include ? [defaultScope.include] : [];
|
||||
mergedInclude.push({ association: 'authtokens' });
|
||||
|
||||
// const mergedInclude = [...defaultScope.include, { association: 'authtokens' }];
|
||||
|
||||
const users = await User.findAll(
|
||||
{
|
||||
attributes: defaultScope.attributes,
|
||||
include: mergedInclude,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return new Response(
|
||||
|
||||
@@ -5,7 +5,7 @@ import Sidebar from "@/components/sidebar";
|
||||
import Article from "@/components/news/article";
|
||||
import ArticlePreview from "@/components/news/article-preview"
|
||||
import ReactDOM from "react";
|
||||
import "public/global.css"
|
||||
import "/public/global.css"
|
||||
import "@/app/index.css"
|
||||
import { Post, User } from "@/model/sequelize/NewModels";
|
||||
import { Attributes } from "sequelize";
|
||||
@@ -17,7 +17,7 @@ type DeepPartial<T> = T extends object ? {
|
||||
|
||||
async function getData(slug:string):Promise<DeepPartial<Post>> {
|
||||
// Get all posts from the API
|
||||
const res = await fetch(`http://localhost:3000/api2/post/${slug}`);
|
||||
const res = await fetch(`http://localhost:3000/api/post/${slug}`);
|
||||
// The return value is *not* serialized
|
||||
// You can return Date, Map, Set, etc.
|
||||
// Recommendation: handle errors
|
||||
@@ -39,12 +39,12 @@ export default async function Page({ params }: {params: {slug:string}}) {
|
||||
<Header />
|
||||
<Navbar />
|
||||
<PageContainer>
|
||||
<Sidebar>
|
||||
{/* <Sidebar>
|
||||
<h1>
|
||||
Filters
|
||||
</h1>
|
||||
<ul><li>filter 1</li><li>filter 2</li><li>filter 3</li></ul>
|
||||
</Sidebar>
|
||||
</Sidebar> */}
|
||||
<main>
|
||||
<Article id={post?.id?.toString()} title={post?.title?.toString()} content={post?.content?.toString()}/>
|
||||
</main>
|
||||
|
||||
@@ -25,3 +25,130 @@ body {
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--text-50: #f3eff5;
|
||||
--text-100: #e7dfec;
|
||||
--text-200: #cfbfd9;
|
||||
--text-300: #b89fc6;
|
||||
--text-400: #a080b3;
|
||||
--text-500: #88609f;
|
||||
--text-600: #6d4d80;
|
||||
--text-700: #523960;
|
||||
--text-800: #362640;
|
||||
--text-900: #1b1320;
|
||||
--text-950: #0e0a10;
|
||||
|
||||
--background-50: #f4eef6;
|
||||
--background-100: #e8ddee;
|
||||
--background-200: #d2bbdd;
|
||||
--background-300: #bb99cc;
|
||||
--background-400: #a477bb;
|
||||
--background-500: #8e55aa;
|
||||
--background-600: #714488;
|
||||
--background-700: #553366;
|
||||
--background-800: #392244;
|
||||
--background-900: #1c1122;
|
||||
--background-950: #0e0911;
|
||||
|
||||
--primary-50: #f3edf8;
|
||||
--primary-100: #e6daf1;
|
||||
--primary-200: #ceb5e3;
|
||||
--primary-300: #b590d5;
|
||||
--primary-400: #9c6bc7;
|
||||
--primary-500: #8346b9;
|
||||
--primary-600: #693894;
|
||||
--primary-700: #4f2a6f;
|
||||
--primary-800: #351c4a;
|
||||
--primary-900: #1a0e25;
|
||||
--primary-950: #0d0712;
|
||||
|
||||
--secondary-50: #f3ebf9;
|
||||
--secondary-100: #e7d7f4;
|
||||
--secondary-200: #cfb0e8;
|
||||
--secondary-300: #b788dd;
|
||||
--secondary-400: #9f61d1;
|
||||
--secondary-500: #8739c6;
|
||||
--secondary-600: #6c2e9e;
|
||||
--secondary-700: #512277;
|
||||
--secondary-800: #36174f;
|
||||
--secondary-900: #1b0b28;
|
||||
--secondary-950: #0d0614;
|
||||
|
||||
--accent-50: #f3eafb;
|
||||
--accent-100: #e7d5f6;
|
||||
--accent-200: #cfaaee;
|
||||
--accent-300: #b880e5;
|
||||
--accent-400: #a056dc;
|
||||
--accent-500: #882bd4;
|
||||
--accent-600: #6d23a9;
|
||||
--accent-700: #521a7f;
|
||||
--accent-800: #361155;
|
||||
--accent-900: #1b092a;
|
||||
--accent-950: #0e0415;
|
||||
|
||||
}
|
||||
.dark {
|
||||
--text-50: #0e0910;
|
||||
--text-100: #1b1320;
|
||||
--text-200: #362541;
|
||||
--text-300: #513861;
|
||||
--text-400: #6c4a82;
|
||||
--text-500: #885da2;
|
||||
--text-600: #9f7db5;
|
||||
--text-700: #b79ec7;
|
||||
--text-800: #cfbeda;
|
||||
--text-900: #e7dfec;
|
||||
--text-950: #f3eff6;
|
||||
|
||||
--background-50: #0d0911;
|
||||
--background-100: #1b1122;
|
||||
--background-200: #352244;
|
||||
--background-300: #503366;
|
||||
--background-400: #6a4488;
|
||||
--background-500: #8555aa;
|
||||
--background-600: #9d77bb;
|
||||
--background-700: #b699cc;
|
||||
--background-800: #cebbdd;
|
||||
--background-900: #e7ddee;
|
||||
--background-950: #f3eef6;
|
||||
|
||||
--primary-50: #0d0712;
|
||||
--primary-100: #1a0e25;
|
||||
--primary-200: #351c4a;
|
||||
--primary-300: #4f2a6f;
|
||||
--primary-400: #693894;
|
||||
--primary-500: #8346b9;
|
||||
--primary-600: #9c6bc7;
|
||||
--primary-700: #b590d5;
|
||||
--primary-800: #ceb5e3;
|
||||
--primary-900: #e6daf1;
|
||||
--primary-950: #f3edf8;
|
||||
|
||||
--secondary-50: #0d0614;
|
||||
--secondary-100: #1b0b28;
|
||||
--secondary-200: #36174f;
|
||||
--secondary-300: #512277;
|
||||
--secondary-400: #6c2e9e;
|
||||
--secondary-500: #8739c6;
|
||||
--secondary-600: #9f61d1;
|
||||
--secondary-700: #b788dd;
|
||||
--secondary-800: #cfb0e8;
|
||||
--secondary-900: #e7d7f4;
|
||||
--secondary-950: #f3ebf9;
|
||||
|
||||
--accent-50: #0e0415;
|
||||
--accent-100: #1b092a;
|
||||
--accent-200: #361155;
|
||||
--accent-300: #521a7f;
|
||||
--accent-400: #6d23a9;
|
||||
--accent-500: #882bd4;
|
||||
--accent-600: #a056dc;
|
||||
--accent-700: #b880e5;
|
||||
--accent-800: #cfaaee;
|
||||
--accent-900: #e7d5f6;
|
||||
--accent-950: #f3eafb;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import './globals.css'
|
||||
import { Inter } from 'next/font/google'
|
||||
import StyledJsxRegistry from './registry';
|
||||
import Providers from '@/providers/providers';
|
||||
|
||||
const inter = Inter({ subsets: ['latin'], fallback: ['system-ui', 'arial'] })
|
||||
|
||||
@@ -16,7 +17,7 @@ export default function RootLayout({
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}><StyledJsxRegistry>{children}</StyledJsxRegistry></body>
|
||||
<body className={inter.className}><StyledJsxRegistry><Providers>{children}</Providers></StyledJsxRegistry></body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
||||
79
src/app/lib/actions.ts
Normal file
79
src/app/lib/actions.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
'use server'
|
||||
|
||||
import { constructAPIUrl } from "@/util/Utils"
|
||||
// import { signIn } from '@/auth'
|
||||
import { cookies } from "next/headers"
|
||||
import { parseSetCookie } from "@/util/parseSetCookie";
|
||||
import makeFetchCookie from 'fetch-cookie';
|
||||
|
||||
type LoginReturn = {
|
||||
cookie?:unknown,
|
||||
errorMessage?:string;
|
||||
}
|
||||
|
||||
async function signIn(method:string,b:FormData):Promise<LoginReturn|null>
|
||||
{
|
||||
console.log("form data:");
|
||||
console.log(b);
|
||||
|
||||
if(!b || !b.get('input_username') || !b.get('input_password')) return null;
|
||||
let headers:Headers = new Headers();
|
||||
const fetchCookie = makeFetchCookie(fetch)
|
||||
headers.set('Authorization', 'Basic ' + Buffer.from(b.get('input_username') + ":" + b.get('input_password')).toString('base64'));
|
||||
let res = await fetchCookie(constructAPIUrl("auth"), {
|
||||
method:'POST',
|
||||
credentials: 'include',
|
||||
headers:headers,
|
||||
});
|
||||
|
||||
// if(res.headers.get('set-coo')) console.log(res.headers['set-cookie'])
|
||||
let koek = res.headers.getSetCookie();
|
||||
// console.log("api koek:" + koek.map((k)=>decodeURIComponent(k)));
|
||||
let cookieDict = parseSetCookie(koek);
|
||||
console.log("testing cookiedict")
|
||||
console.log(cookieDict);
|
||||
await cookies().set('auth', cookieDict.auth);
|
||||
return {
|
||||
cookie:cookieDict.auth,
|
||||
errorMessage:""
|
||||
};
|
||||
// console.log(koek);
|
||||
}
|
||||
|
||||
export async function authenticate(_currentState: unknown, formData: FormData):Promise<LoginReturn|null>
|
||||
{
|
||||
console.log("action triggered")
|
||||
try {
|
||||
const signInStatus = await signIn('credentials', formData)
|
||||
return signInStatus;
|
||||
} catch (error:any) {
|
||||
if (error) {
|
||||
switch (error.type) {
|
||||
case 'CredentialsSignin':
|
||||
return {
|
||||
errorMessage: 'invalidCredentials'
|
||||
}
|
||||
default:
|
||||
return {
|
||||
errorMessage: 'Something went wrong.'
|
||||
}
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
export async function koekValid(koek:string):Promise<boolean>
|
||||
{
|
||||
|
||||
|
||||
const validateSession = await fetch(constructAPIUrl("auth/validate"),{
|
||||
method:"POST",
|
||||
headers:{
|
||||
Cookie: `auth=${koek};`
|
||||
}
|
||||
});
|
||||
if(validateSession.status == 200)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
}
|
||||
@@ -4,10 +4,11 @@ import Navbar from "@/components/navbar";
|
||||
import Sidebar from "@/components/sidebar";
|
||||
import ArticlePreview from "@/components/news/article-preview"
|
||||
import ReactDOM from "react";
|
||||
import "public/global.css"
|
||||
import "/public/global.css"
|
||||
import "./index.css"
|
||||
import { Post, PostAttributes } from "@/model/sequelize/NewModels";
|
||||
import { constructAPIUrl } from "@/util/Utils";
|
||||
import Link from "next/link";
|
||||
|
||||
type DeepPartial<T> = T extends object ? {
|
||||
[P in keyof T]?: DeepPartial<T[P]>;
|
||||
@@ -23,12 +24,12 @@ export default async function Test() {
|
||||
<Header/>
|
||||
<Navbar/>
|
||||
<PageContainer>
|
||||
<Sidebar>
|
||||
{/* <Sidebar>
|
||||
<h1>
|
||||
Filters
|
||||
</h1>
|
||||
<ul><li>filter 1</li><li>filter 2</li><li>filter 3</li></ul>
|
||||
</Sidebar>
|
||||
</Sidebar> */}
|
||||
<main>
|
||||
{articles.map((article, i) => {
|
||||
console.log("Entered");
|
||||
|
||||
Reference in New Issue
Block a user