implemented post management dashboard and started work on projects

This commit is contained in:
2024-06-02 00:58:11 +02:00
parent 8c56a9421e
commit a0a938021d
29 changed files with 969 additions and 595 deletions

View File

@@ -0,0 +1,75 @@
'use server'
import { getCookieAuth } from "@/app/lib/actions";
import AdminPanel from "@/components/server/admin/adminPanel";
import ServerAdminPanel from "@/components/server/admin/ServerAdminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import Sidebar from "@/components/server/admin/views/sidebar";
import { cookies } from "next/headers";
import PostView from "@/components/server/admin/views/PostView";
import { ReactNode } from "react";
type Props = {
params: {
slug: string[]
};
}
export type SidebarEntry = {
label:string;
view:string;
}
function Home(){
return <div>home</div>
}
function PostManager(){
return <div>posts</div>
}
async function getViewMap():Promise<Map<string, JSX.Element>>{
return new Map([
['home', <Home></Home>],
['man-post', <PostView></PostView>]
]);
}
async function getSidebarEntries():Promise<Array<SidebarEntry>>{
return [
{ label: 'Home', view: 'home'},
{ label: 'Post Management', view: 'man-post'},
{ label: 'Project Management', view: 'man-proj'},
{ label: 'Tag Management', view: 'man-tags'},
{ label: 'User Management', view: 'man-user'},
]
}
async function getCurrentView(view:string):Promise<JSX.Element>{
const viewMap = await getViewMap();
const viewJSX = viewMap.get(view);
return viewJSX ? viewJSX : <Home></Home>;
}
export default async function Page(props:Props){
const sidebarEntries:Array<SidebarEntry> = await getSidebarEntries();
const slug:string|string[] = props.params.slug ? props.params.slug : 'home';
return (
<main className="h-screen w-screen flex flex-col p-0 bg-gray-300 box-border m-0">
<AuthHandler params={null}>
<Sidebar sidebarEntries={sidebarEntries} slug={slug.toString()}></Sidebar>
<AdminPanel slug={slug.toString()} auth={await getCookieAuth()}>
{await getCurrentView(slug.toString())}
</AdminPanel>
</AuthHandler>
{/* <section>{JSON.stringify(cookies().getAll())}</section> */}
</main>
);
}

View File

@@ -1,4 +1,4 @@
import '../globals.css'
// import '../globals.css'
import { Inter } from 'next/font/google'
import StyledJsxRegistry from '../registry';
import Providers from '@/providers/providers';

View File

@@ -1,12 +1,45 @@
import AdminPanel from "@/components/client/admin/adminPanel";
'use server'
import { getCookieAuth } from "@/app/lib/actions";
import AdminPanel from "@/components/server/admin/adminPanel";
import ServerAdminPanel from "@/components/server/admin/ServerAdminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import Sidebar from "@/components/server/admin/views/sidebar";
import { cookies } from "next/headers";
type Props = {
params: {
slug: string[]
};
}
export default async function Page(){
export type SidebarEntry = {
label:string;
view:string;
}
async function getSidebarEntries():Promise<Array<SidebarEntry>>{
return [
{ label: 'Home', view: 'home'},
{ label: 'Post Management', view: 'man-post'},
{ label: 'Project Management', view: 'man-proj'},
{ label: 'Tag Management', view: 'man-tags'},
{ label: 'User Management', view: 'man-user'},
]
}
export default async function Page(props:Props){
const sidebarEntries:Array<SidebarEntry> = await getSidebarEntries();
const slug:string|string[] = props.params.slug ? props.params.slug : 'home';
return (
<main className="h-screen w-screen flex flex-col p-0 bg-background-500 box-border m-0">
<AuthHandler params={null}><AdminPanel></AdminPanel></AuthHandler>
<AuthHandler params={null}>
<Sidebar sidebarEntries={sidebarEntries} slug={""}></Sidebar>
<ServerAdminPanel slug={slug.toString()} auth={await getCookieAuth()}></ServerAdminPanel>
</AuthHandler>
{/* <section>{JSON.stringify(cookies().getAll())}</section> */}
</main>
);

View File

@@ -0,0 +1,14 @@
import AdminPanel from "@/components/client/admin/adminPanel";
import AuthHandler from "@/components/server/admin/authHandler";
import { cookies } from "next/headers";
import { Router } from "next/router";
export default async function Page(){
return (
<main className="h-screen w-screen flex flex-col p-0 bg-background-500 box-border m-0">
<AuthHandler params={null}><AdminPanel></AdminPanel></AuthHandler>
{/* <section>{JSON.stringify(cookies().getAll())}</section> */}
</main>
);
}

View File

@@ -0,0 +1,92 @@
'use server'
import { APIError, attemptAPIAction } from "@/util/api/error";
import { Auth, Post, PostTag, Tag, User } from "@/model/Models";
import { cookies } from "next/headers";
async function tryCreateAttachment(request: Request) {
// Make sure the DB is ready
await PostTag.sync();
await Tag.sync();
await Post.sync();
// Prepare data
const requestBody = await request.json();
const authCkie = await cookies().get("auth");
// Sanity check auth cookie
if ( !authCkie || !authCkie.value) throw new APIError({ status: 500, responseText: "missing auth cookie" });
// Get JSON from the Cookie
const cookieJSON = authCkie.value;
const authObject = JSON.parse(cookieJSON);
// Fetch User Auth from the database
const auth = await Auth.findOne({
include: [
{
model: User.withScope(['withPerms']),
attributes: {
exclude: ['username', 'password', 'updatedAt', 'createdAt']
}
}
],
where: { token: authObject.token }
});
// Sanity check the auth and associated user
if (!auth || !auth.user) throw new APIError({ status: 401, responseText: "Authentication Error" });
// Handle incomplete data or other problems
if (!requestBody) throw new APIError({ status: 500, responseText: "Empty request body" });
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 (!auth.user.id) throw new APIError({ status: 500, responseText: "Missing user id" });
if (!auth.user.perms || !auth.user.perms.isAdmin) throw new APIError({ status: 401, responseText: `Unauthorized ${JSON.stringify(auth.user)}` });
// Create a new Post in the database
const post = await Post.create(
{
content: requestBody.content,
user_id: auth.user.id,
title: requestBody.title,
},{
include: {
association: Post.associations.user
}
}).then(post=>post.reload())
// Return the response
return new Response(JSON.stringify(post), { status: 200 });
}
export async function tryFetchAttachments(request: Request) {
await Post.sync();
const foundPosts = await Post.findAll({
include: [
{
association: Post.associations.user,
attributes: { exclude: ['password', 'createdAt', 'updatedAt'] }
},{
association: Post.associations.postTags
}]
});
return new Response(JSON.stringify(foundPosts), { status: 200 });
}
export async function GET(request: Request) {
return await attemptAPIAction(tryFetchAttachments,request);
}
export async function POST(request: Request) {
return await attemptAPIAction(tryCreateAttachment,request);
}

View File

@@ -1,6 +1,6 @@
'use server'
import { APIError } from "@/app/lib/api/error";
import { APIError } from "@/util/api/error";
import { Post } from "@/model/Models";

View File

@@ -66,7 +66,7 @@ async function tryCreatePost(request: Request) {
async function tryFetchPosts(request: Request) {
export async function tryFetchPosts(request: Request) {
await Post.sync();

View File

@@ -5,8 +5,10 @@ import { cookies } from "next/headers"
import { parseSetCookie } from "@/util/parseSetCookie";
import makeFetchCookie from 'fetch-cookie';
import fetchCookie from "fetch-cookie";
import { Attributes } from "@sequelize/core";
import { Attribute, Attributes } from "@sequelize/core";
import { User } from "@/model/User";
import { AuthProps } from "@/providers/providers";
import { Auth } from "@/model/Auth";
type LoginReturn = {
cookie?:unknown,
@@ -80,6 +82,48 @@ export async function serverValidateSessionCookie(koek:string):Promise<boolean>
export async function userIsAdmin(user:Partial<Attributes<User>>):Promise<boolean>
{
const cookieAuthValue = await cookies().get('auth')?.value;
const cookieAuthSanitized = decodeURIComponent(cookieAuthValue ? cookieAuthValue: "");
if(!cookieAuthSanitized) return false;
const parsedAuth = JSON.parse(cookieAuthSanitized);
if(!parsedAuth.id || !parsedAuth.token || !parsedAuth.user_id) return false
const p:AuthProps = {
auth: {
id:parsedAuth.id,
token:parsedAuth.token,
user_id:parsedAuth.user_id
}
};
const foundAuth = await Auth.findOne({where: { id: p.auth?.id}});
if(!foundAuth || foundAuth.token != p.auth?.token ) return false;
return true;
}
export async function getCookieAuth():Promise<AuthProps>
{
const cookieAuthValue = await cookies().get('auth')?.value;
const cookieAuthSanitized = decodeURIComponent(cookieAuthValue ? cookieAuthValue: "");
if(!cookieAuthSanitized) return {}
const kd = JSON.parse(cookieAuthSanitized);
if(!kd.id || !kd.token || !kd.user_id) return {};
const foundAuth = await Auth.findOne({where: { id: kd.id},include:{model:User}});
if(!foundAuth) return {};
const authObject:AuthProps = {
auth: {
id:kd.id,
token:kd.token,
user_id:kd.user_id
},
user: await foundAuth.user
}
return authObject;
}
return false;
}

View File

@@ -0,0 +1,15 @@
'use server';
import { Post } from "@/model/Post";
import { Attributes } from "@sequelize/core";
export async function deletePost(postID: number): Promise<boolean> {
const destroy = await Post.destroy({ where: { id: postID } });
return true;
}
export async function getPosts(): Promise<string> {
const posts = await Post.findAll();
return JSON.stringify(posts);
}