Compare commits
No commits in common. "c9e7717130ea10fd709246eeddb04da550a1e485" and "0410cc8655dfb9b6d3d12dc03fc61be20dddb939" have entirely different histories.
c9e7717130
...
0410cc8655
37
.vscode/settings.json
vendored
37
.vscode/settings.json
vendored
@ -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
1
insomnia.json
Normal file
File diff suppressed because one or more lines are too long
@ -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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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",
|
||||||
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",
|
"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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>> {
|
||||||
|
|||||||
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
|
||||||
@ -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>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -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 {
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
16
src/components/client/admin/clientAuthHandler.tsx
Normal file
16
src/components/client/admin/clientAuthHandler.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -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 (
|
||||||
@ -5,6 +5,7 @@ import {
|
|||||||
MutableRefObject,
|
MutableRefObject,
|
||||||
useLayoutEffect,
|
useLayoutEffect,
|
||||||
ChangeEventHandler,
|
ChangeEventHandler,
|
||||||
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { StateHook } from "@/util";
|
import { StateHook } from "@/util";
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/components/shared/bootstrap.tsx
Normal file
10
src/components/shared/bootstrap.tsx
Normal 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} /></>;
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
|||||||
@ -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 () => {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
|
||||||
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from './authprovider';
|
|
||||||
export * from './contextproviders';
|
|
||||||
@ -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
3
src/util/aifa.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
export const aifa = (a: ReactNode, b: ReactNode) => (a ? a : b);
|
||||||
@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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';
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
export * from './loremipsum';
|
export * from './loremipsum';
|
||||||
export * from './truncateString';
|
|
||||||
@ -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
|
||||||
@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user