Many Changes

This commit is contained in:
2024-05-14 12:49:50 +02:00
parent a01b6bdbc2
commit f6eef1ded3
53 changed files with 636 additions and 579 deletions

View File

@@ -1,12 +1,12 @@
'use client'
import { authenticate } from '@/app/lib/actions'
import { serverAttemptAuthenticateUser } 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)
const [loginResult, dispatch] = useFormState(serverAttemptAuthenticateUser, undefined)
console.log(dispatch);
console.log(state);

View File

@@ -1,5 +1,5 @@
import AdminPanel from "@/components/admin/adminPanel";
import AuthHandler from "@/components/admin/authHandler";
import AdminPanel from "@/components/client/admin/adminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import { cookies } from "next/headers";

View File

@@ -14,17 +14,10 @@ export async function GET(request:Request, { params }: {params:{slug: string}}){
// @ts-ignore
cookies().set('name', 'lee');
return Response.json({
"a": "lorem",
"b": params
"params": params
});
}
// export default async function handler(req:NextApiRequest, res:NextApiResponse) {
// await MPost.sync();
// switch (req.method) {

View File

@@ -1,13 +1,10 @@
'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"
import { Auth, User } from "@/model/Models";
async function tryAuth(request:Request){
@@ -31,15 +28,24 @@ async function tryAuth(request:Request){
user_id: user.id,
})
console.log('ok');
const foundAuth = await Auth.findOne({
include: 'user',
include: {
model: User,
as: 'user'
},
where: {
user_id: user.id
}
})
console.log('ok2');
if(!foundAuth)
return new Response("error",{status:500});
const usr = foundAuth.user;
const authUser = await authentication.getUser();

View File

@@ -1,9 +1,10 @@
'use server'
import { Model } from "sequelize";
import { Model } from "@sequelize/core";
import { cookies } from "next/headers";
import { Auth, Post, User } from "@/model/sequelize/NewModels";
import { Auth } from "@/model/Models";
import { APIError} from "@/api/error"
@@ -23,9 +24,13 @@ async function tryAuth(request:Request){
console.log(koek);
const auth = JSON.parse(koek.value);
const authentication = await Auth.findOne( { include: 'user', where: {token:auth.token} })
const authentication = await Auth.findOne( { include: {
association: Auth.associations.user
}, where: { token:auth.token } })
if(!authentication)
return new Response("unauthorized: invalid token",{status:403});

View File

@@ -1,7 +1,7 @@
'use server'
import { APIError } from "@/api/error";
import { Post } from "@/model/sequelize/NewModels";
import { Post } from "@/model/Models";
export async function tryFetchPost(request:Request, { params }: {params:{slug: string}}){

View File

@@ -1,15 +1,16 @@
'use server'
import { APIError } from "@/api/error";
import { Auth, Post, User } from "@/model/Models";
import { Auth, Post, PostTag, Tag, User } from "@/model/Models";
import { cookies } from "next/headers";
import { where } from "sequelize";
async function tryCreatePost(request: Request) {
// Make sure the DB is ready
await PostTag.sync();
await Tag.sync();
await Post.sync();
// Prepare data
@@ -24,7 +25,7 @@ async function tryCreatePost(request: Request) {
const authObject = JSON.parse(cookieJSON);
// Fetch User Auth from the database
const auth = await Auth.findOne({ include: 'user', where: { token: authObject.token } });
const auth:any = await Auth.findOne({ include: 'user', where: { token: authObject.token } });
// Sanity check the auth and associated user
if (!auth || !auth.user) throw new APIError({ status: 401, responseText: "Authentication Error" });
@@ -35,6 +36,7 @@ async function tryCreatePost(request: Request) {
if (!requestBody.title) throw new APIError({ status: 500, responseText: "Missing post title" });
if (!requestBody.content) throw new APIError({ status: 500, responseText: "Missing post content" });
if (!user.id) throw new APIError({ status: 500, responseText: "Missing user id" });
if (!user.perms || !user.perms.isAdmin) throw new APIError({ status: 401, responseText: "Unauthorized" });
// Create a new Post in the database
const post = await Post.create(
@@ -42,8 +44,11 @@ async function tryCreatePost(request: Request) {
content: requestBody.content,
user_id: user.id,
title: requestBody.title,
date: Date.now()
},{include: "user"})
},{
include: {
association: Post.associations.user
}
}).then(post=>post.reload())
// // Find the post (Unneeded but nice to check)
// const foundPost = await Post.findOne({
// include: "user",
@@ -52,7 +57,7 @@ async function tryCreatePost(request: Request) {
// }
// })
return new Response(JSON.stringify(Post), { status: 200 });
return new Response(JSON.stringify(post), { status: 200 });
}
@@ -76,9 +81,12 @@ async function tryFetchPosts(request: Request) {
await Post.sync();
const foundPosts = await Post.findAll({
include: [{
association: 'user',
include: [
{
association: Post.associations.user,
attributes: { exclude: ['password', 'createdAt', 'updatedAt'] }
},{
association: Post.associations.postTags
}]
});

View File

@@ -1,41 +1,48 @@
'use server'
import { User, Auth, Post, UserPerms } from "@/model/sequelize/NewModels"
/* =================================================================================================
*
* Copyright 2024 Andreas Schaafsma
* Purpose: Handle API requests that fetch or permute User data
*
* ================================================================================================= */
import { APIError } from "@/api/error";
import { UserAuth } from "@/api/user";
import { UserPerms, User, Auth } from "@/model/Models"; // Do not alter "unused" imports, they are required to perform the nescessairy includes on the User model
import { hashPassword } from "@/util/Auth";
async function tryRegister(request:Request){
// Attempt to register a new User
async function attemptRegister(request:Request){
// Sync User model
User.sync();
// Get request body
const requestBody:Partial<UserAuth> = await request.json();
// Handle edgecases
if(!requestBody) throw new APIError({status:500,responseText: "Request Body is Empty"})
if(!requestBody.username) throw new APIError({status:500,responseText: "No username specified"})
if(!requestBody.password) throw new APIError({status:500,responseText: "No password specified"})
// Try to get user from database
const dbUser = await User.findOne({where:{username:requestBody.username}});
// If it exists we throw an error
if(dbUser) throw new APIError({status:500,responseText: "Username unavailable, try another"});
const hash = await hashPassword(requestBody.password);
// Hash the password and create a new user in the database
const user = await User.create({
username: requestBody.username,
password: hash,
password: await hashPassword(requestBody.password),
perms:{
isAdmin: false
}
},
{
include: [{
association: 'perms'
association: User.associations.perms
}]
})
}).then(user=>user.reload());
// Return the HTTP response
return new Response(
JSON.stringify(
{
@@ -52,7 +59,7 @@ async function tryRegister(request:Request){
export async function POST(request:Request){
try{
return await tryRegister(request);
return await attemptRegister(request);
}
catch(e){
if (e instanceof APIError){
@@ -65,23 +72,9 @@ export async function POST(request:Request){
}
}
async function tryGetUsers(request:Request){
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,
}
);
async function attemptGetUsers(request:Request){
// Get users with scopes applied
const users = await User.withScope(['defaultScope','withPerms','withAuthtokens']).findAll();
return new Response(
JSON.stringify(
{
@@ -98,7 +91,7 @@ async function tryGetUsers(request:Request){
export async function GET(request:Request){
try{
return await tryGetUsers(request);
return await attemptGetUsers(request);
}
catch(e){
if (e instanceof APIError){

View File

@@ -1,21 +1,21 @@
import Header from "@/components/header";
import PageContainer from "@/components/page-container";
import Navbar from "@/components/navbar";
import Sidebar from "@/components/sidebar";
import Article from "@/components/news/article";
import ArticlePreview from "@/components/news/article-preview"
import Header from "@/components/shared/header";
import PageContainer from "@/components/shared/page-container";
import Navbar from "@/components/shared/navbar";
import Sidebar from "@/components/shared/sidebar";
import Article from "@/components/shared/news/article";
import ArticlePreview from "@/components/shared/news/article-preview"
import ReactDOM from "react";
import "/public/global.css"
import "@/app/index.css"
import { Post, User } from "@/model/sequelize/NewModels";
import { Attributes } from "sequelize";
import { Post } from "@/model/Post";
import { Attributes } from "@sequelize/core";
import { DeepPartial } from "@/util/DeepPartial";
type DeepPartial<T> = T extends object ? {
[P in keyof T]?: DeepPartial<T[P]>;
} : T;
async function getData(slug:string):Promise<DeepPartial<Post>> {
async function getData(slug:string):Promise<Attributes<Post>> {
// Get all posts from the API
const res = await fetch(`http://localhost:3000/api/post/${slug}`);
// The return value is *not* serialized
@@ -31,7 +31,7 @@ async function getData(slug:string):Promise<DeepPartial<Post>> {
export default async function Page({ params }: {params: {slug:string}}) {
const { slug } = params;
const post:DeepPartial<Attributes<Post>> = await getData(slug);
const post:Attributes<Post> = await getData(slug);
console.log(post);

View File

@@ -5,27 +5,30 @@ import { constructAPIUrl } from "@/util/Utils"
import { cookies } from "next/headers"
import { parseSetCookie } from "@/util/parseSetCookie";
import makeFetchCookie from 'fetch-cookie';
import fetchCookie from "fetch-cookie";
type LoginReturn = {
cookie?:unknown,
errorMessage?:string;
}
async function signIn(method:string,b:FormData):Promise<LoginReturn|null>
async function attemptAPILogin(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"), {
const { CookieJar, Cookie } = fetchCookie.toughCookie;
const cj = new CookieJar()
const fetchKoek = makeFetchCookie(fetch, cj);
// Set Basic Auth
headers.set('Authorization', `Basic ${Buffer.from(`${b.get('input_username')}:${b.get('input_password')}`).toString('base64')}`);
let res = await fetchKoek(constructAPIUrl("auth"), {
method:'POST',
credentials: 'include',
headers:headers,
});
console.log(cj.store.idx['localhost']['/']);
// 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)));
@@ -40,11 +43,11 @@ async function signIn(method:string,b:FormData):Promise<LoginReturn|null>
// console.log(koek);
}
export async function authenticate(_currentState: unknown, formData: FormData):Promise<LoginReturn|null>
export async function serverAttemptAuthenticateUser(_currentState: unknown, formData: FormData):Promise<LoginReturn|null>
{
console.log("action triggered")
try {
const signInStatus = await signIn('credentials', formData)
const signInStatus = await attemptAPILogin('credentials', formData)
return signInStatus;
} catch (error:any) {
if (error) {
@@ -62,10 +65,9 @@ export async function authenticate(_currentState: unknown, formData: FormData):P
throw error
}
}
export async function koekValid(koek:string):Promise<boolean>
{
export async function serverValidateSessionCookie(koek:string):Promise<boolean>
{
const validateSession = await fetch(constructAPIUrl("auth/validate"),{
method:"POST",
headers:{

View File

@@ -1,14 +1,15 @@
import Header from "@/components/header";
import PageContainer from "@/components/page-container";
import Navbar from "@/components/navbar";
import Sidebar from "@/components/sidebar";
import ArticlePreview from "@/components/news/article-preview"
import Header from "@/components/shared/header";
import PageContainer from "@/components/shared/page-container";
import Navbar from "@/components/shared/navbar";
import Sidebar from "@/components/shared/sidebar";
import ArticlePreview from "@/components/shared/news/article-preview"
import ReactDOM from "react";
import "/public/global.css"
import "./index.css"
import { Post, PostAttributes } from "@/model/sequelize/NewModels";
import { Post } from "@/model/Post";
import { constructAPIUrl } from "@/util/Utils";
import Link from "next/link";
import { Attributes } from "@sequelize/core";
type DeepPartial<T> = T extends object ? {
[P in keyof T]?: DeepPartial<T[P]>;
@@ -18,7 +19,7 @@ export default async function Test() {
const response = await fetch(constructAPIUrl('post'));
const articles:Array<DeepPartial<PostAttributes>> = await response.json();
const articles:Array<Attributes<Post>> = await response.json();
return <div className={`root`}>
<Header/>
@@ -32,9 +33,8 @@ export default async function Test() {
</Sidebar> */}
<main>
{articles.map((article, i) => {
console.log("Entered");
// Return the element. Also pass key
return (<ArticlePreview id={article?.id?.toString()} content={article?.content} title={article?.title}></ArticlePreview>)
return (<ArticlePreview key={article?.id} id={article?.id?.toString()} content={article?.content} title={article?.title}></ArticlePreview>)
})}
</main>
</PageContainer>

View File

@@ -1,17 +1,30 @@
import Header from "@/components/header";
import PageContainer from "@/components/page-container";
import Navbar from "@/components/navbar";
import Sidebar from "@/components/sidebar";
import ArticlePreview from "@/components/news/article-preview"
import ReactDOM from "react";
// import components
import Header from "@/components/shared/header";
import PageContainer from "@/components/shared/page-container";
import Navbar from "@/components/shared/navbar";
import Sidebar from "@/components/shared/sidebar";
import ArticlePreview from "@/components/shared/news/article-preview"
// import styles
import "public/global.css"
import "@/app/index.css"
// import other shit
import ReactDOM, { ReactNode } from "react";
type Props = {
children?: ReactNode
}
export default function Page() {
return <div className={`root`}>
<Header/>
<Navbar/>
export default function Page(props: Props) {
return (
<div className={`root`}>
<Header />
<Navbar />
<PageContainer>
<Sidebar>
<h1>
@@ -20,10 +33,10 @@ export default function Page() {
<ul><li>filter 1</li><li>filter 2</li><li>filter 3</li></ul>
</Sidebar>
<main>
<ArticlePreview/>
<ArticlePreview/>
<ArticlePreview/>
<ArticlePreview />
<ArticlePreview />
<ArticlePreview />
</main>
</PageContainer>
</div>;
</div>);
}

View File

@@ -1,7 +1,7 @@
import Header from "@/components/header";
import PageContainer from "@/components/page-container";
import PageContainer from "@/components/shared/page-container";
import Navbar from "@/components/navbar";
import Sidebar from "@/components/sidebar";
import Sidebar from "@/components/shared/sidebar";
import ArticlePreview from "@/components/news/article-preview"
import ReactDOM from "react";
import "public/global.css"