Compare commits

..

No commits in common. "c9e7717130ea10fd709246eeddb04da550a1e485" and "0410cc8655dfb9b6d3d12dc03fc61be20dddb939" have entirely different histories.

40 changed files with 328 additions and 398 deletions

37
.vscode/settings.json vendored
View File

@ -2,24 +2,25 @@
"window.title": "${dirty}${activeEditorMedium}${separator}${rootName}${separator}${profileName}${separator}${appName}", "window.title": "${dirty}${activeEditorMedium}${separator}${rootName}${separator}${profileName}${separator}${appName}",
"workbench.editor.labelFormat": "medium", "workbench.editor.labelFormat": "medium",
"files.exclude": { "files.exclude": {
"**/.git": false, "**/.git": true,
"**/.svn": false, "**/.svn": true,
"**/.hg": false, "**/.hg": true,
"**/CVS": false, "**/CVS": true,
"**/.DS_Store": false, "**/.DS_Store": true,
"**/Thumbs.db": false, "**/Thumbs.db": true,
"**/.next": false, "**/.next": true,
"**/.sqlite_queries": false, "**/.sqlite_queries": true,
"**/node_modules": false, "**/node_modules": true,
"**/.env.example": false, "**/.env.example": true,
"**/.vscode": false, "**/.vscode": true,
"**/.env**": false, "**/.env**": true,
"**/.gitignore": false, "**/.gitignore": true,
"**/.eslintrc.json": false, "**/.eslintrc.json": true,
"**/next-env.d.ts": false, "**/next-env.d.ts": true,
"**/package-lock.json": false, "**/package-lock.json": true,
"**/package.json": false, "**/package.json": true,
"**/bucket": false "**/bucket": true,
}, },
"exportall.config.folderListener": [ "exportall.config.folderListener": [
"/src/util/api", "/src/util/api",

1
insomnia.json Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,30 +1,25 @@
// import '../globals.css' // import '../globals.css'
import { Inter } from "next/font/google"; import { Inter } from 'next/font/google'
import StyledJsxRegistry from "../registry"; import StyledJsxRegistry from '../registry';
import ContextProviders from "@/providers/contextproviders"; import Providers from '@/providers/providers';
import "bootstrap/dist/css/bootstrap.css"; import 'bootstrap/dist/css/bootstrap.css';
import { Toaster } from "react-hot-toast"; import { Toaster } from 'react-hot-toast';
const inter = Inter({ subsets: ["latin"], fallback: ["system-ui", "arial"] }); const inter = Inter({ subsets: ['latin'], fallback: ['system-ui', 'arial'] })
export const metadata = { export const metadata = {
title: "Create Next App", title: 'Create Next App',
description: "Generated by create next app", description: 'Generated by create next app',
}; }
export default function RootLayout({ export default function RootLayout({
children, children,
}: { }: {
children: React.ReactNode; children: React.ReactNode
}) { }) {
return ( return (
<html lang="en"> <html lang="en">
<body className={inter.className}> <body className={inter.className}><Toaster position="bottom-center" /><StyledJsxRegistry><Providers>{children}</Providers></StyledJsxRegistry></body>
<Toaster position="bottom-center" /> </html>
<StyledJsxRegistry> )
<ContextProviders>{children}</ContextProviders>
</StyledJsxRegistry>
</body>
</html>
);
} }

View File

@ -1,11 +0,0 @@
import { getApiDocs } from "@/lib/swagger";
import ReactSwagger from "@/components/client/SwaggerComponent";
export default async function IndexPage() {
const spec = await getApiDocs();
return (
<section className="container">
<ReactSwagger spec={spec} />
</section>
);
}

View File

@ -1,5 +1,6 @@
"use server"; "use server";
import { APIError, attemptAPIAction } from "@/util";
import { import {
sequelize, sequelize,
Bucket, Bucket,
@ -19,7 +20,6 @@ import {
} from "@/app/lib/actions/entityManagement/attachment/attachmentActions"; } from "@/app/lib/actions/entityManagement/attachment/attachmentActions";
import { Attributes } from "@sequelize/core"; import { Attributes } from "@sequelize/core";
import { RequestCookie } from "next/dist/compiled/@edge-runtime/cookies"; import { RequestCookie } from "next/dist/compiled/@edge-runtime/cookies";
import { APIError, attemptAPIAction } from "@/util/api";
export async function tryCreateAttachment(request: Request) { export async function tryCreateAttachment(request: Request) {
// Make sure the DB is ready // Make sure the DB is ready
@ -127,17 +127,6 @@ export async function tryCreateAttachment(request: Request) {
); );
} }
/**
* @swagger
* /api/attachment:
* get:
* description: Returns all attachments
* responses:
* 200:
* description: idk
*/
export async function tryFetchAttachments(request: Request) { export async function tryFetchAttachments(request: Request) {
await Post.sync(); await Post.sync();

View File

@ -1,8 +1,8 @@
"use server"; "use server";
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import { APIError, UserAuth, parseBasicAuth, getAssociatedUser } from "@/util";
import { Auth, User } from "@/models"; import { Auth, User } from "@/models";
import { APIError, getAssociatedUser, parseBasicAuth } from "@/util/api";
async function tryAuth(request: Request) { async function tryAuth(request: Request) {
// await User.sync(); // await User.sync();
@ -63,12 +63,11 @@ async function tryAuth(request: Request) {
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
return await tryAuth(request); return await tryAuth(request);
} catch(e){ } catch (e) {
if (e instanceof APIError){ if (e instanceof APIError) {
return new Response(e.info.responseText,{status:e.info.status}); return new Response(e.info.responseText, { status: e.info.status });
} } else {
else{ throw e;
throw e; }
} }
}
} }

View File

@ -1,189 +1,159 @@
"use server"; 'use server'
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import { APIError } from "@/util/api/error"; import { APIError} from "@/util/api/error"
import { import { UserAuth, parseBasicAuth, getAssociatedUser } from "@/util/api/user"
Attachment, import { Attachment, Auth, Bucket, DBState, Post, PostTag, Project, Tag, User, UserPerms,dbSync,sequelize} from "@/models";
Auth,
Bucket,
DBState,
Post,
PostTag,
Project,
Tag,
User,
UserPerms,
dbSync,
sequelize,
} from "@/models";
import Sequelize, { CreationAttributes, DataTypes } from "@sequelize/core"; import Sequelize, { CreationAttributes, DataTypes } from "@sequelize/core";
import { import { SqliteColumnsDescription, SqliteDialect, SqliteQueryInterface } from "@sequelize/sqlite3";
SqliteColumnsDescription,
SqliteDialect,
SqliteQueryInterface,
} from "@sequelize/sqlite3";
import { hashpassword } from "@/util/auth"; import { hashpassword } from "@/util/auth";
import { copyFile, readFileSync } from "fs"; import { copyFile, readFileSync } from "fs";
import path from "path"; import path from "path";
import { Attributes } from '@sequelize/core';
import { DeepPartial } from "@/util/DeepPartial";
import { UUID } from "crypto"; import { UUID } from "crypto";
import { runApiAction } from "@/util/api";
async function seedUsers(qif: SqliteQueryInterface<SqliteDialect>) { async function seedUsers(qif: SqliteQueryInterface<SqliteDialect>){
const fp = path.resolve("./db/seed/users.json"); const fp = path.resolve('./db/seed/users.json');
const json: { users: CreationAttributes<User>[] } = JSON.parse( const json: {users: CreationAttributes<User>[]} = JSON.parse(Buffer.from(readFileSync(fp).valueOf()).toString());
Buffer.from(readFileSync(fp).valueOf()).toString()
);
const users = json.users.map(async (user) => { const users = json.users.map(async user=>{
user.password = await hashpassword(user.password); user.password = await hashpassword(user.password);
return user; return user;
}); })
const dbUsers = await User.bulkCreate(await Promise.all(users), { const dbUsers = await User.bulkCreate(await Promise.all(users), {include: User.associations.perms})
include: User.associations.perms,
});
} }
async function seedPosts(qif: SqliteQueryInterface<SqliteDialect>) { async function seedPosts(qif: SqliteQueryInterface<SqliteDialect>){
const fp = path.resolve("./db/seed/posts.json"); const fp = path.resolve('./db/seed/posts.json');
const json: { users: CreationAttributes<User>[] } = JSON.parse( const json: {users: CreationAttributes<User>[]} = JSON.parse(Buffer.from(readFileSync(fp).valueOf()).toString());
Buffer.from(readFileSync(fp).valueOf()).toString() const projects =[
); {
const projects = [ "name": "Blog",
{ "readableIdentifier": "blog",
name: "Blog", "posts": [
readableIdentifier: "blog", {
posts: [ "title": "Test Post",
{ "content": "# Hello <ExampleComponent />\nthis is some **test** markdown and we make some edits\n![](/attachment/788dfc19-55ba-482c-8124-277702296dfb/FB_IMG_1716665756868.jpg)",
title: "Test Post", "description": "A new post to test the blog system",
content: "project_id": 1,
"# Hello <ExampleComponent />\nthis is some **test** markdown and we make some edits\n![](/attachment/788dfc19-55ba-482c-8124-277702296dfb/FB_IMG_1716665756868.jpg)", "user_id": 1,
description: "A new post to test the blog system", "buckets": [
project_id: 1, {
user_id: 1, "id": "788dfc19-55ba-482c-8124-277702296dfb",
buckets: [ "attachments": [
{ {
id: "788dfc19-55ba-482c-8124-277702296dfb", "filename": "FB_IMG_1716665756868.jpg"
attachments: [ }
{ ]
filename: "FB_IMG_1716665756868.jpg", }
}, ]
], }
}, ]
], }]
}, projects.map(project=>{
], Project.create({name: project.name, readableIdentifier: project.readableIdentifier});
}, project.posts.map(async post=>{
]; const pst = await Post.create({title:post.title, content:post.content, description:post.description, project_id: post.project_id, user_id: post.user_id});
projects.map((project) => { post.buckets.map(async bucket=>{
Project.create({ pst.createBucket({id:bucket.id as UUID});
name: project.name, bucket.attachments.map(attachment=>{
readableIdentifier: project.readableIdentifier, Attachment.create({bucket_id:bucket.id as UUID, filename: attachment.filename}).then((a)=>{
}); copyFile(
project.posts.map(async (post) => { path.resolve('.','db','seed','post',a.filename),
const pst = await Post.create({ path.resolve('.','bucket',bucket.id,a.filename),
title: post.title, ()=>{
content: post.content,
description: post.description,
project_id: post.project_id,
user_id: post.user_id,
});
post.buckets.map(async (bucket) => {
pst.createBucket({ id: bucket.id as UUID });
bucket.attachments.map((attachment) => {
Attachment.create({
bucket_id: bucket.id as UUID,
filename: attachment.filename,
}).then((a) => {
copyFile(
path.resolve(".", "db", "seed", "post", a.filename),
path.resolve(".", "bucket", bucket.id, a.filename),
() => {}
);
});
});
});
});
});
const project = await Project.findOne({ }
where: { )
readableIdentifier: "blog", })
}, })
}).then((e) => })
e })
? e })
: Project.create({
name: "General Blog",
readableIdentifier: "blog",
})
); const project = await Project.findOne({where: {
readableIdentifier: 'blog'
}}).then(e=> e ? e : Project.create({name:'General Blog',readableIdentifier:'blog'}));
} }
async function seedDatabase(qif: SqliteQueryInterface<SqliteDialect>) {
await seedUsers(qif);
await seedPosts(qif);
// await Post.create({
// title: 'Test Post',
// content: `
// # Hello <ExampleComponent /> async function seedDatabase(qif:SqliteQueryInterface<SqliteDialect>){
// this is some **test** markdown await seedUsers(qif);
// `, await seedPosts(qif)
// project_id: project.id,
// user_id: user.id // await Post.create({
// }) // title: 'Test Post',
// await Post.create({ // content: `
// title: 'Test Post 2', // # Hello <ExampleComponent />
// content: ` // this is some **test** markdown
// # Hello <ExampleComponent /> // `,
// this is amother post with some **test** markdown // project_id: project.id,
// `, // user_id: user.id
// project_id: project.id, // })
// user_id: user.id // await Post.create({
// }) // title: 'Test Post 2',
// content: `
// # Hello <ExampleComponent />
// this is amother post with some **test** markdown
// `,
// project_id: project.id,
// user_id: user.id
// })
} }
export async function GET(request: Request) { async function trySetup(request:Request){
runApiAction(async (request) => { await dbSync;
await dbSync;
const queryInterface = sequelize.queryInterface; const queryInterface = sequelize.queryInterface
const version = (await DBState.findAll()) const version = (await DBState.findAll()).sort((a,b)=> ((a.version > b.version) ? 1 : -1)).map(a=>a.version)[0];
.sort((a, b) => (a.version > b.version ? 1 : -1))
.map((a) => a.version)[0];
switch (version) {
case 1:
break;
default:
seedDatabase(queryInterface);
const postsRows: SqliteColumnsDescription = await queryInterface
.describeTable(Post.table.tableName)
.then((t) => t);
if (!postsRows["project_id"])
queryInterface.addColumn("Posts", "project_id", {
type: DataTypes.INTEGER,
acceptsNull: () => false,
defaultValue: 1,
});
break;
}
return new Response( switch(version){
JSON.stringify({ case 1:
test: await queryInterface break;
.describeTable("Posts") default:
.then((t) => t), seedDatabase(queryInterface);
}), const postsRows:SqliteColumnsDescription = await queryInterface.describeTable(Post.table.tableName).then(t=>t);
{ if (!postsRows['project_id']) queryInterface.addColumn('Posts','project_id',{type: DataTypes.INTEGER, acceptsNull:()=>false,defaultValue:1})
status: 200, break;
headers: { }
"Content-Type": "text/JSON",
}, return new Response(
} JSON.stringify(
); {
}, request); test: await queryInterface.describeTable('Posts').then(t=>t)
}),
{
status: 200,
headers:{
"Content-Type": "text/JSON"
}
}
);
}
export async function GET(request:Request){
try{
return await trySetup(request);
}
catch(e){
if (e instanceof APIError){
return new Response(e.info.responseText,{status:e.info.status});
}
else{
throw e;
}
}
} }

View File

@ -90,7 +90,7 @@ async function attemptGetUsers(request:Request){
); );
} }
export async function GET(request:Request): Promise<Response>{ export async function GET(request:Request){
try{ try{
return await attemptGetUsers(request); return await attemptGetUsers(request);
} }

View File

@ -12,7 +12,7 @@ import "@/app/index.css"
import { Post } from "@/models"; import { Post } from "@/models";
import { Attributes } from "@sequelize/core"; import { Attributes } from "@sequelize/core";
import { DeepPartial } from "@/util/deeppartial"; import { DeepPartial } from "@/util/DeepPartial";
async function getData(slug:string):Promise<Attributes<Post>> { async function getData(slug:string):Promise<Attributes<Post>> {

View File

@ -1,7 +1,7 @@
import './globals.css' import './globals.css'
import { Inter } from 'next/font/google' import { Inter } from 'next/font/google'
import StyledJsxRegistry from './registry'; import StyledJsxRegistry from './registry';
import ContextProviders from '@/providers/contextproviders'; import Providers from '@/providers/providers';
const inter = Inter({ subsets: ['latin'], fallback: ['system-ui', 'arial'] }) const inter = Inter({ subsets: ['latin'], fallback: ['system-ui', 'arial'] })
@ -17,7 +17,7 @@ export default function RootLayout({
}) { }) {
return ( return (
<html lang="en"> <html lang="en">
<body className={inter.className}><StyledJsxRegistry><ContextProviders>{children}</ContextProviders></StyledJsxRegistry></body> <body className={inter.className}><StyledJsxRegistry><Providers>{children}</Providers></StyledJsxRegistry></body>
</html> </html>
) )
} }

View File

@ -6,7 +6,7 @@ import { parseSetCookie } from "@/util/cookies";
import makeFetchCookie from "fetch-cookie"; import makeFetchCookie from "fetch-cookie";
import fetchCookie from "fetch-cookie"; import fetchCookie from "fetch-cookie";
import { User, Auth } from "@/models"; import { User, Auth } from "@/models";
import { AuthContextProviderProps } from "@/providers"; import { AuthProps } from "@/providers/providers";
type LoginReturn = { type LoginReturn = {
cookie?: unknown; cookie?: unknown;
@ -42,7 +42,7 @@ async function attemptAPILogin(
)}` )}`
).toString("base64")}` ).toString("base64")}`
); );
let res = await fetchWithCookie(await constructAPIUrl("auth"), { let res = await fetchWithCookie(constructAPIUrl("auth"), {
method: "POST", method: "POST",
credentials: "include", credentials: "include",
headers: headers, headers: headers,
@ -71,7 +71,6 @@ export async function serverAttemptAuthenticateUser(
return signInStatus; return signInStatus;
} catch (error: any) { } catch (error: any) {
if (error) { if (error) {
console.log(error);
switch (error.type) { switch (error.type) {
case "CredentialsSignin": case "CredentialsSignin":
return { errorMessage: "invalidCredentials" }; return { errorMessage: "invalidCredentials" };
@ -86,15 +85,12 @@ export async function serverAttemptAuthenticateUser(
export async function serverValidateSessionCookie( export async function serverValidateSessionCookie(
koek: string koek: string
): Promise<boolean> { ): Promise<boolean> {
const validateSession = await fetch( const validateSession = await fetch(constructAPIUrl("auth/validate"), {
await constructAPIUrl("auth/validate"), method: "POST",
{ headers: {
method: "POST", Cookie: `auth=${koek};`,
headers: { },
Cookie: `auth=${koek};`, });
},
}
);
if (validateSession.status == 200) return true; if (validateSession.status == 200) return true;
else return false; else return false;
} }
@ -111,7 +107,7 @@ export async function userIsAdmin(): Promise<boolean> {
if (!parsedAuth.id || !parsedAuth.token || !parsedAuth.user_id) if (!parsedAuth.id || !parsedAuth.token || !parsedAuth.user_id)
return false; return false;
const p: AuthContextProviderProps = { const p: AuthProps = {
auth: { auth: {
id: parsedAuth.id, id: parsedAuth.id,
token: parsedAuth.token, token: parsedAuth.token,
@ -125,7 +121,7 @@ export async function userIsAdmin(): Promise<boolean> {
return true; return true;
} }
export async function getCookieAuth(): Promise<AuthContextProviderProps> { export async function getCookieAuth(): Promise<AuthProps> {
const cookieAuthValue = await cookies().get("auth")?.value; const cookieAuthValue = await cookies().get("auth")?.value;
const cookieAuthSanitized = cookieAuthValue const cookieAuthSanitized = cookieAuthValue
? JSON.parse(JSON.stringify(cookieAuthValue)) ? JSON.parse(JSON.stringify(cookieAuthValue))
@ -142,7 +138,7 @@ export async function getCookieAuth(): Promise<AuthContextProviderProps> {
include: { model: User }, include: { model: User },
}); });
if (!foundAuth) return {}; if (!foundAuth) return {};
const authObject: AuthContextProviderProps = { const authObject: AuthProps = {
auth: { auth: {
id: kd.id, id: kd.id,
token: kd.token, token: kd.token,

View File

@ -7,7 +7,7 @@ import ReactDOM from "react";
import "/public/global.css" import "/public/global.css"
import "./index.css" import "./index.css"
import { Post } from "@/models"; import { Post } from "@/models";
import { constructAPIUrl } from "@/util/url"; import { constructAPIUrl } from "@/util";
import Link from "next/link"; import Link from "next/link";
import { Attributes } from "@sequelize/core"; import { Attributes } from "@sequelize/core";
@ -17,7 +17,7 @@ type DeepPartial<T> = T extends object ? {
export default async function Test() { export default async function Test() {
const response = await fetch(await constructAPIUrl('post')); const response = await fetch(constructAPIUrl('post'));
const articles:Array<Attributes<Post>> = await response.json(); const articles:Array<Attributes<Post>> = await response.json();

View File

@ -1,14 +0,0 @@
'use client';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
type Props = {
spec: Record<string, any>,
};
function ReactSwagger({ spec }: Props) {
return <SwaggerUI spec={spec} />;
}
export default ReactSwagger;

View File

@ -1,15 +0,0 @@
'use client'
import { AuthContext, AuthContextProviderProps } from "@/providers";
import { ReactNode } from "react"
type CAuthProviderProps = {
children?:ReactNode;
authProps:AuthContextProviderProps
}
export default function CAuthProvider(props:CAuthProviderProps){
return (
<AuthContext.Provider value={props.authProps}>{props.children}</AuthContext.Provider>
)
}

View File

@ -6,6 +6,9 @@ import { EntityEditorTextArea } from '../input/EntityEditorTextArea';
import { import {
ChangeEventHandler, ChangeEventHandler,
MouseEventHandler, MouseEventHandler,
MutableRefObject,
useLayoutEffect,
useRef,
useState, useState,
} from "react"; } from "react";
import { import {

View File

@ -19,7 +19,7 @@ import {
} from "@/app/lib/actions/entityManagement/post/postActions"; } from "@/app/lib/actions/entityManagement/post/postActions";
import { PostViewProps } from "@/views/admin/post"; import { PostViewProps } from "@/views/admin/post";
import { StateHook } from "@/util/"; import { aifa, StateHook } from "@/util/";
export type PostTableStateProps = { export type PostTableStateProps = {
posts: StateHook<GetPostsAttributes[]>; posts: StateHook<GetPostsAttributes[]>;
@ -110,10 +110,13 @@ export default function PostTable({
: `${post.content.substring(0, 255)}...`} : `${post.content.substring(0, 255)}...`}
</td> </td>
<td key="project"> <td key="project">
{projects.find((e) => { {aifa(
console.log(e.id); projects.find((e) => {
return e.id == post.project.id; console.log(e.id);
})?.readableIdentifier || "uncategorized"} return e.id == post.project.id;
})?.readableIdentifier,
"uncategorized"
)}
</td> </td>
<td key="createdAt">{post.createdAt?.toString()}</td> <td key="createdAt">{post.createdAt?.toString()}</td>
<td key="updatedAt">{post.updatedAt?.toString()}</td> <td key="updatedAt">{post.updatedAt?.toString()}</td>

View File

@ -0,0 +1,16 @@
'use client'
import { AuthContext, AuthProps } from "@/providers/providers";
import { ReactNode, createContext } from "react"
type Props = {
children?:ReactNode;
authProps:AuthProps
}
export default function ClientAuthHandler(props:Props){
return (
<AuthContext.Provider value={props.authProps}>{props.children}</AuthContext.Provider>
)
}

View File

@ -1,10 +1,19 @@
'use client' 'use client'
import { serverAttemptAuthenticateUser } from "@/app/lib/actions/actions"; import { serverAttemptAuthenticateUser } from "@/app/lib/actions/actions";
import { AuthContext } from "@/providers/providers";
import { constructAPIUrl } from "@/util/url";
import { createContext, useState } from "react";
import { useFormState, useFormStatus } from "react-dom"; import { useFormState, useFormStatus } from "react-dom";
export default function CLoginForm(){ // async function authenticate(){
// const url = await constructAPIUrl("auth");
// const auth = await fetch(url);
// }
export default function LoginForm(){
const [loginResult, dispatch] = useFormState(serverAttemptAuthenticateUser, undefined); const [loginResult, dispatch] = useFormState(serverAttemptAuthenticateUser, undefined);
return ( return (

View File

@ -5,6 +5,7 @@ import {
MutableRefObject, MutableRefObject,
useLayoutEffect, useLayoutEffect,
ChangeEventHandler, ChangeEventHandler,
useState,
} from "react"; } from "react";
import { StateHook } from "@/util"; import { StateHook } from "@/util";

View File

@ -1,46 +1,43 @@
"use server"; 'use server'
import { cookies } from "next/headers"; import { cookies } from "next/headers";
import CLoginForm from "@/components/client/admin/CLoginForm"; import LoginForm from "@/components/client/admin/loginForm";
import ClientAuthHandler from "@/components/client/admin/CAuthHandler"; import ClientAuthHandler from "@/components/client/admin/clientAuthHandler";
import { serverValidateSessionCookie } from "@/app/lib/actions/actions"; import { serverValidateSessionCookie } from "@/app/lib/actions/actions";
import { ReactNode } from "react"; import { ReactNode } from "react";
import { AuthContextProviderProps } from "@/providers"; import { AuthContext, AuthProps } from "@/providers/providers";
interface Props { interface Props {
children?: ReactNode; children?: ReactNode;
params?: any; params?: any;
requiredRole?: number; requiredRole?: number;
} // We interfacing lads } // We interfacing lads
export default async function AuthHandler(props: Props) {
const protoKoek = await cookies().get("auth")?.value;
const koek = decodeURIComponent(protoKoek ? protoKoek : "");
// console.log("koekje:" + koek)
let p: AuthContextProviderProps = {};
if (koek) {
const kd = JSON.parse(koek);
if (kd.id && kd.token && kd.user_id) {
p = {
auth: {
id: kd.id,
token: kd.token,
user_id: kd.user_id,
},
};
}
}
return ( export default async function AuthHandler(props: Props) {
<div className="flex flex-row w-[100%] h-[100%]"> const protoKoek = await cookies().get('auth')?.value;
{!(koek && (await serverValidateSessionCookie(koek))) ? ( const koek = decodeURIComponent(protoKoek ? protoKoek: "");
<CLoginForm>{}</CLoginForm> // console.log("koekje:" + koek)
) : ( let p:AuthProps = {
<ClientAuthHandler authProps={p}> };
{props.children} if(koek){
</ClientAuthHandler> const kd = JSON.parse(koek);
)} if(kd.id && kd.token && kd.user_id){
</div> p = {
); auth: {
id:kd.id,
token:kd.token,
user_id:kd.user_id
}
}
}
}
return (
<div className="flex flex-row w-[100%] h-[100%]">
{!(koek && await serverValidateSessionCookie(koek)) ? <LoginForm>{ }</LoginForm> : <ClientAuthHandler authProps={p}>{props.children}</ClientAuthHandler>}
</div>
);
} }

View File

@ -0,0 +1,10 @@
'use client'
import 'bootstrap/dist/css/bootstrap.css';
import { useEffect } from 'react';
export default function Bootstrap(Component, children, pageProps){
useEffect(() => {
typeof document !== undefined ? require('bootstrap/dist/js/bootstrap') : null
}, []);
return <><div {...pageProps} /></>;
}

View File

@ -7,7 +7,7 @@
margin-left:0px; margin-left:0px;
padding: 1px 5px 1px 5px; padding: 1px 5px 1px 5px;
border-radius: 20%; border-radius: 20%;
display: inline; *display: inline;
} }
.tagbar{ .tagbar{
margin: 0px 0px 0px 0px; margin: 0px 0px 0px 0px;

View File

@ -1,4 +1,3 @@
// @ts-ignore
import { createSwaggerSpec } from "next-swagger-doc"; import { createSwaggerSpec } from "next-swagger-doc";
export const getApiDocs = async () => { export const getApiDocs = async () => {

View File

@ -10,11 +10,10 @@ import {
HasOne, HasOne,
UpdatedAt, UpdatedAt,
CreatedAt, CreatedAt,
Table,
} from '@sequelize/core/decorators-legacy'; } from '@sequelize/core/decorators-legacy';
import { SqliteDialect } from '@sequelize/sqlite3'; import { SqliteDialect } from '@sequelize/sqlite3';
@Table({tableName: "DBStates"})
export class DBState extends Model<InferAttributes<DBState>, InferCreationAttributes<DBState>>{ export class DBState extends Model<InferAttributes<DBState>, InferCreationAttributes<DBState>>{
@Attribute(DataTypes.INTEGER) @Attribute(DataTypes.INTEGER)

View File

@ -20,7 +20,7 @@ export class Project extends Model<
> { > {
@Attribute(DataTypes.INTEGER) @Attribute(DataTypes.INTEGER)
@PrimaryKey @PrimaryKey
// @Unique @Unique
@AutoIncrement @AutoIncrement
declare id: CreationOptional<number>; declare id: CreationOptional<number>;
@Attribute(DataTypes.STRING) @Attribute(DataTypes.STRING)

View File

@ -25,7 +25,7 @@ export * from './UserPerms';
export const sequelize = new Sequelize({ export const sequelize = new Sequelize({
dialect: SqliteDialect, dialect: SqliteDialect,
storage: './db/db.sqlite', storage: 'db.sqlite',
models: [Auth, Attachment, Bucket, DBState, Post, PostBucket, PostTag, Project, Tag, User, UserPerms], models: [Auth, Attachment, Bucket, DBState, Post, PostBucket, PostTag, Project, Tag, User, UserPerms],
}); });

View File

@ -1,14 +0,0 @@
import { Auth, User } from "@/models";
import { Attributes } from "@sequelize/core";
import { Context, createContext } from "react";
export type AuthContextProviderProps = {
auth?: Attributes<Auth>
user?: Attributes<User>
}
let p: AuthContextProviderProps = {}
export const AuthContext: Context<AuthContextProviderProps> = createContext(p);

View File

@ -1,2 +0,0 @@
export * from './authprovider';
export * from './contextproviders';

View File

@ -3,14 +3,23 @@
import { Auth, User } from "@/models"; import { Auth, User } from "@/models";
import { ReactNode, createContext } from "react"; import { ReactNode, createContext } from "react";
import { Attributes, InferAttributes } from "@sequelize/core"; import { Attributes, InferAttributes } from "@sequelize/core";
import { AuthContext } from "./authprovider";
interface ProvidersProps {
children?: ReactNode; export type AuthProps = {
params?: any; auth?: Attributes<Auth>
user?: Attributes<User>
} }
export default function ContextProviders(props:ProvidersProps){ let p: AuthProps = {}
export const AuthContext = createContext(p);
interface Props {
children?: ReactNode;
params?: any;
}
export default function Providers(props:Props){
return ( return (
<AuthContext.Provider value={{}}>{props.children}</AuthContext.Provider> <AuthContext.Provider value={{}}>{props.children}</AuthContext.Provider>
) )

3
src/util/aifa.ts Normal file
View File

@ -0,0 +1,3 @@
import { ReactNode } from "react";
export const aifa = (a: ReactNode, b: ReactNode) => (a ? a : b);

View File

@ -1,9 +1,10 @@
'server only'; 'server only';
export async function getAPIEnv() { // import Auth from "./Auth";
export function getAPIEnv() {
return { return {
'schema': process.env.API_SCHEMA, 'schema': process.env.API_SCHEMA,
'host': process.env.API_HOST, 'host': process.env.API_HOST,
'port': process.env.API_PORT, 'port': process.env.API_PORT,
'basepath': process.env.API_BASEPATH, 'basepath': process.env.API_BASEPATH
}; };
} }

View File

@ -1,4 +1,3 @@
export * from './error'; export * from './error';
export * from './getAPIEnv'; export * from './getAPIEnv';
export * from './runapiaction';
export * from './user'; export * from './user';

View File

@ -1,19 +0,0 @@
import { NextApiResponse } from "next";
import { APIError } from "./error";
export type APIRequest = (request:Request)=>Promise<Response>;
export async function runApiAction(c:APIRequest,request:Request){
try{
return await c(request);
}
catch(e){
if (e instanceof APIError){
return new Response(e.info.responseText,{status:e.info.status});
console.log("responded");
}
else{
throw e;
}
}
}

View File

@ -1,5 +1,6 @@
export * from './DeepPartial';
export * from './aifa';
export * from './auth'; export * from './auth';
export * from './cookies'; export * from './cookies';
export * from './deeppartial';
export * from './state'; export * from './state';
export * from './strings'; export * from './strings';

View File

@ -1,2 +1 @@
export * from './loremipsum'; export * from './loremipsum';
export * from './truncateString';

View File

@ -2,11 +2,11 @@
import { getAPIEnv } from "../api/getAPIEnv"; import { getAPIEnv } from "../api/getAPIEnv";
export async function constructAPIUrl(endpoint:string){ export function constructAPIUrl(endpoint:string){
const { schema, host, port, basepath } = await getAPIEnv(); const { schema, host, port, basepath } = getAPIEnv();
return `${schema}://${host}:${port}/${basepath}/${endpoint}` return `${schema}://${host}:${port}/${basepath}/${endpoint}`
} }
export async function constructUrl(endpoint:string){ export function constructUrl(endpoint:string){
const { schema, host, port, basepath } = await getAPIEnv(); const { schema, host, port, basepath } = getAPIEnv();
return `${schema}://${host}:${port}/${endpoint}` return `${schema}://${host}:${port}/${endpoint}`
}1 }1

View File

@ -38,14 +38,16 @@ export function CPostView({
posts: parseStateHook(useState(posts)), posts: parseStateHook(useState(posts)),
editor: parseStateHook(useState(initEditorState)), editor: parseStateHook(useState(initEditorState)),
}; };
// render out the post table
return ( return (
<PostTable <>
headings={headings} <PostTable
posts={posts} headings={headings}
projects={projects} posts={posts}
actions={actions} projects={projects}
state={state} actions={actions}
></PostTable> state={state}
></PostTable>
</>
); );
} }

View File

@ -30,6 +30,14 @@ export async function PostView(props: Props) {
"UpdatedAt", "UpdatedAt",
]; ];
const actions: PostServerActions = {
deletePost: deletePost,
getPosts: getPostsWithBucketsAndProject,
getProjects: getProjects,
savePost: updatePost,
// uploadAttachment:tryCreateAttachment
};
const posts: GetPostsAttributes[] | undefined = handleActionResult( const posts: GetPostsAttributes[] | undefined = handleActionResult(
await getPostsWithBucketsAndProject() await getPostsWithBucketsAndProject()
); );
@ -44,12 +52,7 @@ export async function PostView(props: Props) {
posts={posts ? posts : []} posts={posts ? posts : []}
projects={projects} projects={projects}
headings={headings} headings={headings}
actions={{ actions={actions}
deletePost: deletePost,
getPosts: getPostsWithBucketsAndProject,
getProjects: getProjects,
savePost: updatePost
}}
/> />
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
cache: "no-store"; cache: "no-store";
import { ReactNode } from "react"; import { ReactNode, useEffect } from "react";
import EntityManagementTable from "../../../components/client/EntityManagementTable"; import EntityManagementTable from "../../../components/client/EntityManagementTable";
import PostTable from "@/components/client/admin/PostTable"; import PostTable from "@/components/client/admin/PostTable";
import { import {