Compare commits
	
		
			2 Commits
		
	
	
		
			0410cc8655
			...
			c9e7717130
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c9e7717130 | ||
|  | 169ba29253 | 
							
								
								
									
										37
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @ -2,25 +2,24 @@ | ||||
|     "window.title": "${dirty}${activeEditorMedium}${separator}${rootName}${separator}${profileName}${separator}${appName}", | ||||
|     "workbench.editor.labelFormat": "medium", | ||||
|     "files.exclude": { | ||||
|         "**/.git": true, | ||||
|         "**/.svn": true, | ||||
|         "**/.hg": true, | ||||
|         "**/CVS": true, | ||||
|         "**/.DS_Store": true, | ||||
|         "**/Thumbs.db": true, | ||||
|         "**/.next": true, | ||||
|         "**/.sqlite_queries": true, | ||||
|         "**/node_modules": true, | ||||
|         "**/.env.example": true, | ||||
|         "**/.vscode": true, | ||||
|         "**/.env**": true, | ||||
|         "**/.gitignore": true, | ||||
|         "**/.eslintrc.json": true, | ||||
|         "**/next-env.d.ts": true, | ||||
|         "**/package-lock.json": true, | ||||
|         "**/package.json": true, | ||||
|         "**/bucket": true, | ||||
| 
 | ||||
|         "**/.git": false, | ||||
|         "**/.svn": false, | ||||
|         "**/.hg": false, | ||||
|         "**/CVS": false, | ||||
|         "**/.DS_Store": false, | ||||
|         "**/Thumbs.db": false, | ||||
|         "**/.next": false, | ||||
|         "**/.sqlite_queries": false, | ||||
|         "**/node_modules": false, | ||||
|         "**/.env.example": false, | ||||
|         "**/.vscode": false, | ||||
|         "**/.env**": false, | ||||
|         "**/.gitignore": false, | ||||
|         "**/.eslintrc.json": false, | ||||
|         "**/next-env.d.ts": false, | ||||
|         "**/package-lock.json": false, | ||||
|         "**/package.json": false, | ||||
|         "**/bucket": false | ||||
|     }, | ||||
|     "exportall.config.folderListener": [ | ||||
|         "/src/util/api", | ||||
|  | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -1,25 +1,30 @@ | ||||
| // import '../globals.css'
 | ||||
| import { Inter } from 'next/font/google' | ||||
| import StyledJsxRegistry from '../registry'; | ||||
| import Providers from '@/providers/providers'; | ||||
| import 'bootstrap/dist/css/bootstrap.css'; | ||||
| import { Toaster } from 'react-hot-toast'; | ||||
| import { Inter } from "next/font/google"; | ||||
| import StyledJsxRegistry from "../registry"; | ||||
| import ContextProviders from "@/providers/contextproviders"; | ||||
| import "bootstrap/dist/css/bootstrap.css"; | ||||
| 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 = { | ||||
|   title: 'Create Next App', | ||||
|   description: 'Generated by create next app', | ||||
| } | ||||
| 	title: "Create Next App", | ||||
| 	description: "Generated by create next app", | ||||
| }; | ||||
| 
 | ||||
| export default function RootLayout({ | ||||
|   children, | ||||
| 	children, | ||||
| }: { | ||||
|   children: React.ReactNode | ||||
| 	children: React.ReactNode; | ||||
| }) { | ||||
|   return ( | ||||
|     <html lang="en"> | ||||
|       <body className={inter.className}><Toaster position="bottom-center" /><StyledJsxRegistry><Providers>{children}</Providers></StyledJsxRegistry></body> | ||||
|     </html> | ||||
|   ) | ||||
| 	return ( | ||||
| 		<html lang="en"> | ||||
| 			<body className={inter.className}> | ||||
| 				<Toaster position="bottom-center" /> | ||||
| 				<StyledJsxRegistry> | ||||
| 					<ContextProviders>{children}</ContextProviders> | ||||
| 				</StyledJsxRegistry> | ||||
| 			</body> | ||||
| 		</html> | ||||
| 	); | ||||
| } | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/app/api-doc/page.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/app/api-doc/page.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| 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,6 +1,5 @@ | ||||
| "use server"; | ||||
| 
 | ||||
| import { APIError, attemptAPIAction } from "@/util"; | ||||
| import { | ||||
| 	sequelize, | ||||
| 	Bucket, | ||||
| @ -20,6 +19,7 @@ import { | ||||
| } from "@/app/lib/actions/entityManagement/attachment/attachmentActions"; | ||||
| import { Attributes } from "@sequelize/core"; | ||||
| import { RequestCookie } from "next/dist/compiled/@edge-runtime/cookies"; | ||||
| import { APIError, attemptAPIAction } from "@/util/api"; | ||||
| 
 | ||||
| export async function tryCreateAttachment(request: Request) { | ||||
| 	// Make sure the DB is ready
 | ||||
| @ -127,6 +127,17 @@ export async function tryCreateAttachment(request: Request) { | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * @swagger | ||||
|  * /api/attachment: | ||||
|  *   get: | ||||
|  *     description: Returns all attachments | ||||
|  *     responses: | ||||
|  *       200: | ||||
|  *         description: idk | ||||
|  */ | ||||
| export async function tryFetchAttachments(request: Request) { | ||||
| 	await Post.sync(); | ||||
| 
 | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| "use server"; | ||||
| 
 | ||||
| import { cookies } from "next/headers"; | ||||
| import { APIError, UserAuth, parseBasicAuth, getAssociatedUser } from "@/util"; | ||||
| import { Auth, User } from "@/models"; | ||||
| import { APIError, getAssociatedUser, parseBasicAuth } from "@/util/api"; | ||||
| 
 | ||||
| async function tryAuth(request: Request) { | ||||
| 	// await User.sync();
 | ||||
| @ -63,11 +63,12 @@ async function tryAuth(request: Request) { | ||||
| export async function POST(request: Request) { | ||||
| 	try { | ||||
| 		return await tryAuth(request); | ||||
| 	} catch (e) { | ||||
| 		if (e instanceof APIError) { | ||||
| 			return new Response(e.info.responseText, { status: e.info.status }); | ||||
| 		} else { | ||||
| 			throw e; | ||||
| 		} | ||||
| 	} | ||||
| 	} catch(e){ | ||||
|         if (e instanceof APIError){ | ||||
|             return new Response(e.info.responseText,{status:e.info.status}); | ||||
|         } | ||||
|         else{ | ||||
|             throw e; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,159 +1,189 @@ | ||||
| 'use server' | ||||
| "use server"; | ||||
| 
 | ||||
| import { cookies } from "next/headers"; | ||||
| 
 | ||||
| import { APIError} from "@/util/api/error" | ||||
| import { UserAuth, parseBasicAuth, getAssociatedUser } from "@/util/api/user" | ||||
| import { Attachment, Auth, Bucket, DBState, Post, PostTag, Project, Tag, User, UserPerms,dbSync,sequelize} from "@/models"; | ||||
| import { APIError } from "@/util/api/error"; | ||||
| import { | ||||
| 	Attachment, | ||||
| 	Auth, | ||||
| 	Bucket, | ||||
| 	DBState, | ||||
| 	Post, | ||||
| 	PostTag, | ||||
| 	Project, | ||||
| 	Tag, | ||||
| 	User, | ||||
| 	UserPerms, | ||||
| 	dbSync, | ||||
| 	sequelize, | ||||
| } from "@/models"; | ||||
| import Sequelize, { CreationAttributes, DataTypes } from "@sequelize/core"; | ||||
| import { SqliteColumnsDescription, SqliteDialect, SqliteQueryInterface } from "@sequelize/sqlite3"; | ||||
| import { | ||||
| 	SqliteColumnsDescription, | ||||
| 	SqliteDialect, | ||||
| 	SqliteQueryInterface, | ||||
| } from "@sequelize/sqlite3"; | ||||
| import { hashpassword } from "@/util/auth"; | ||||
| import { copyFile, readFileSync } from "fs"; | ||||
| import path from "path"; | ||||
| import { Attributes } from '@sequelize/core'; | ||||
| import { DeepPartial } from "@/util/DeepPartial"; | ||||
| import { UUID } from "crypto"; | ||||
| import { runApiAction } from "@/util/api"; | ||||
| 
 | ||||
| async function seedUsers(qif: SqliteQueryInterface<SqliteDialect>){ | ||||
|     const fp = path.resolve('./db/seed/users.json'); | ||||
|     const json: {users: CreationAttributes<User>[]} = JSON.parse(Buffer.from(readFileSync(fp).valueOf()).toString()); | ||||
| async function seedUsers(qif: SqliteQueryInterface<SqliteDialect>) { | ||||
| 	const fp = path.resolve("./db/seed/users.json"); | ||||
| 	const json: { users: CreationAttributes<User>[] } = JSON.parse( | ||||
| 		Buffer.from(readFileSync(fp).valueOf()).toString() | ||||
| 	); | ||||
| 
 | ||||
|     const users = json.users.map(async user=>{ | ||||
|         user.password = await hashpassword(user.password); | ||||
|         return user; | ||||
|     }) | ||||
|      | ||||
|     const dbUsers = await User.bulkCreate(await Promise.all(users), {include: User.associations.perms}) | ||||
| 	const users = json.users.map(async (user) => { | ||||
| 		user.password = await hashpassword(user.password); | ||||
| 		return user; | ||||
| 	}); | ||||
| 
 | ||||
| 	const dbUsers = await User.bulkCreate(await Promise.all(users), { | ||||
| 		include: User.associations.perms, | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| async function seedPosts(qif: SqliteQueryInterface<SqliteDialect>){ | ||||
|     const fp = path.resolve('./db/seed/posts.json'); | ||||
|     const json: {users: CreationAttributes<User>[]} = JSON.parse(Buffer.from(readFileSync(fp).valueOf()).toString()); | ||||
|     const projects =[ | ||||
|     { | ||||
|         "name": "Blog", | ||||
|         "readableIdentifier": "blog", | ||||
|         "posts": [ | ||||
|             { | ||||
|                 "title": "Test Post", | ||||
|                 "content": "# Hello <ExampleComponent />\nthis is some **test** markdown and we make some edits\n", | ||||
|                 "description": "A new post to test the blog system", | ||||
|                 "project_id": 1, | ||||
|                 "user_id": 1, | ||||
|                 "buckets": [ | ||||
|                     { | ||||
|                         "id": "788dfc19-55ba-482c-8124-277702296dfb", | ||||
|                         "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}); | ||||
|             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), | ||||
|                             ()=>{ | ||||
| async function seedPosts(qif: SqliteQueryInterface<SqliteDialect>) { | ||||
| 	const fp = path.resolve("./db/seed/posts.json"); | ||||
| 	const json: { users: CreationAttributes<User>[] } = JSON.parse( | ||||
| 		Buffer.from(readFileSync(fp).valueOf()).toString() | ||||
| 	); | ||||
| 	const projects = [ | ||||
| 		{ | ||||
| 			name: "Blog", | ||||
| 			readableIdentifier: "blog", | ||||
| 			posts: [ | ||||
| 				{ | ||||
| 					title: "Test Post", | ||||
| 					content: | ||||
| 						"# Hello <ExampleComponent />\nthis is some **test** markdown and we make some edits\n", | ||||
| 					description: "A new post to test the blog system", | ||||
| 					project_id: 1, | ||||
| 					user_id: 1, | ||||
| 					buckets: [ | ||||
| 						{ | ||||
| 							id: "788dfc19-55ba-482c-8124-277702296dfb", | ||||
| 							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, | ||||
| 			}); | ||||
| 			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); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| async function seedDatabase(qif:SqliteQueryInterface<SqliteDialect>){ | ||||
|     await seedUsers(qif); | ||||
|     await seedPosts(qif) | ||||
|      | ||||
|     // await Post.create({
 | ||||
|     //     title: 'Test Post',
 | ||||
|     //     content: `
 | ||||
|     //     # Hello <ExampleComponent />
 | ||||
|     //     this is some **test** markdown
 | ||||
|     //     `,
 | ||||
|     //     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
 | ||||
|     // })
 | ||||
| 	// await Post.create({
 | ||||
| 	//     title: 'Test Post',
 | ||||
| 	//     content: `
 | ||||
| 	//     # Hello <ExampleComponent />
 | ||||
| 	//     this is some **test** markdown
 | ||||
| 	//     `,
 | ||||
| 	//     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
 | ||||
| 	// })
 | ||||
| } | ||||
| 
 | ||||
| async function trySetup(request:Request){ | ||||
|     await dbSync; | ||||
| export async function GET(request: Request) { | ||||
| 	runApiAction(async (request) => { | ||||
| 		await dbSync; | ||||
| 
 | ||||
|     const queryInterface = sequelize.queryInterface | ||||
|      | ||||
| 		const queryInterface = sequelize.queryInterface; | ||||
| 
 | ||||
|     const version = (await DBState.findAll()).sort((a,b)=> ((a.version > b.version) ? 1 : -1)).map(a=>a.version)[0]; | ||||
| 		const version = (await DBState.findAll()) | ||||
| 			.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; | ||||
| 		} | ||||
| 
 | ||||
|     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( | ||||
|         JSON.stringify( | ||||
|         { | ||||
|             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; | ||||
|         } | ||||
|     } | ||||
| 		return new Response( | ||||
| 			JSON.stringify({ | ||||
| 				test: await queryInterface | ||||
| 					.describeTable("Posts") | ||||
| 					.then((t) => t), | ||||
| 			}), | ||||
| 			{ | ||||
| 				status: 200, | ||||
| 				headers: { | ||||
| 					"Content-Type": "text/JSON", | ||||
| 				}, | ||||
| 			} | ||||
| 		); | ||||
| 	}, request); | ||||
| } | ||||
|  | ||||
| @ -90,7 +90,7 @@ async function attemptGetUsers(request:Request){ | ||||
|     );  | ||||
| } | ||||
| 
 | ||||
| export async function GET(request:Request){ | ||||
| export async function GET(request:Request): Promise<Response>{ | ||||
|     try{ | ||||
|         return await attemptGetUsers(request);       | ||||
|     } | ||||
|  | ||||
| @ -12,7 +12,7 @@ import "@/app/index.css" | ||||
| 
 | ||||
| import { Post } from "@/models"; | ||||
| import { Attributes } from "@sequelize/core"; | ||||
| import { DeepPartial } from "@/util/DeepPartial"; | ||||
| import { DeepPartial } from "@/util/deeppartial"; | ||||
| 
 | ||||
| 
 | ||||
| async function getData(slug:string):Promise<Attributes<Post>> { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import './globals.css' | ||||
| import { Inter } from 'next/font/google' | ||||
| import StyledJsxRegistry from './registry'; | ||||
| import Providers from '@/providers/providers'; | ||||
| import ContextProviders from '@/providers/contextproviders'; | ||||
| 
 | ||||
| const inter = Inter({ subsets: ['latin'], fallback: ['system-ui', 'arial'] }) | ||||
| 
 | ||||
| @ -17,7 +17,7 @@ export default function RootLayout({ | ||||
| }) { | ||||
|   return ( | ||||
|     <html lang="en"> | ||||
|       <body className={inter.className}><StyledJsxRegistry><Providers>{children}</Providers></StyledJsxRegistry></body> | ||||
|       <body className={inter.className}><StyledJsxRegistry><ContextProviders>{children}</ContextProviders></StyledJsxRegistry></body> | ||||
|     </html> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| @ -6,7 +6,7 @@ import { parseSetCookie } from "@/util/cookies"; | ||||
| import makeFetchCookie from "fetch-cookie"; | ||||
| import fetchCookie from "fetch-cookie"; | ||||
| import { User, Auth } from "@/models"; | ||||
| import { AuthProps } from "@/providers/providers"; | ||||
| import { AuthContextProviderProps } from "@/providers"; | ||||
| 
 | ||||
| type LoginReturn = { | ||||
| 	cookie?: unknown; | ||||
| @ -42,7 +42,7 @@ async function attemptAPILogin( | ||||
| 			)}` | ||||
| 		).toString("base64")}` | ||||
| 	); | ||||
| 	let res = await fetchWithCookie(constructAPIUrl("auth"), { | ||||
| 	let res = await fetchWithCookie(await constructAPIUrl("auth"), { | ||||
| 		method: "POST", | ||||
| 		credentials: "include", | ||||
| 		headers: headers, | ||||
| @ -71,6 +71,7 @@ export async function serverAttemptAuthenticateUser( | ||||
| 		return signInStatus; | ||||
| 	} catch (error: any) { | ||||
| 		if (error) { | ||||
| 			console.log(error); | ||||
| 			switch (error.type) { | ||||
| 				case "CredentialsSignin": | ||||
| 					return { errorMessage: "invalidCredentials" }; | ||||
| @ -85,12 +86,15 @@ export async function serverAttemptAuthenticateUser( | ||||
| export async function serverValidateSessionCookie( | ||||
| 	koek: string | ||||
| ): Promise<boolean> { | ||||
| 	const validateSession = await fetch(constructAPIUrl("auth/validate"), { | ||||
| 		method: "POST", | ||||
| 		headers: { | ||||
| 			Cookie: `auth=${koek};`, | ||||
| 		}, | ||||
| 	}); | ||||
| 	const validateSession = await fetch( | ||||
| 		await constructAPIUrl("auth/validate"), | ||||
| 		{ | ||||
| 			method: "POST", | ||||
| 			headers: { | ||||
| 				Cookie: `auth=${koek};`, | ||||
| 			}, | ||||
| 		} | ||||
| 	); | ||||
| 	if (validateSession.status == 200) return true; | ||||
| 	else return false; | ||||
| } | ||||
| @ -107,7 +111,7 @@ export async function userIsAdmin(): Promise<boolean> { | ||||
| 	if (!parsedAuth.id || !parsedAuth.token || !parsedAuth.user_id) | ||||
| 		return false; | ||||
| 
 | ||||
| 	const p: AuthProps = { | ||||
| 	const p: AuthContextProviderProps = { | ||||
| 		auth: { | ||||
| 			id: parsedAuth.id, | ||||
| 			token: parsedAuth.token, | ||||
| @ -121,7 +125,7 @@ export async function userIsAdmin(): Promise<boolean> { | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| export async function getCookieAuth(): Promise<AuthProps> { | ||||
| export async function getCookieAuth(): Promise<AuthContextProviderProps> { | ||||
| 	const cookieAuthValue = await cookies().get("auth")?.value; | ||||
| 	const cookieAuthSanitized = cookieAuthValue | ||||
| 		? JSON.parse(JSON.stringify(cookieAuthValue)) | ||||
| @ -138,7 +142,7 @@ export async function getCookieAuth(): Promise<AuthProps> { | ||||
| 		include: { model: User }, | ||||
| 	}); | ||||
| 	if (!foundAuth) return {}; | ||||
| 	const authObject: AuthProps = { | ||||
| 	const authObject: AuthContextProviderProps = { | ||||
| 		auth: { | ||||
| 			id: kd.id, | ||||
| 			token: kd.token, | ||||
|  | ||||
| @ -7,7 +7,7 @@ import ReactDOM from "react"; | ||||
| import "/public/global.css" | ||||
| import "./index.css" | ||||
| import { Post } from "@/models"; | ||||
| import { constructAPIUrl } from "@/util"; | ||||
| import { constructAPIUrl } from "@/util/url"; | ||||
| import Link from "next/link"; | ||||
| import { Attributes } from "@sequelize/core"; | ||||
| 
 | ||||
| @ -17,7 +17,7 @@ type DeepPartial<T> = T extends object ? { | ||||
| 
 | ||||
| export default async function Test() { | ||||
|      | ||||
|     const response = await fetch(constructAPIUrl('post')); | ||||
|     const response = await fetch(await constructAPIUrl('post')); | ||||
| 
 | ||||
|     const articles:Array<Attributes<Post>> = await response.json(); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										14
									
								
								src/components/client/SwaggerComponent.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/components/client/SwaggerComponent.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| '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; | ||||
							
								
								
									
										15
									
								
								src/components/client/admin/CAuthHandler.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/components/client/admin/CAuthHandler.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| '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> | ||||
|     ) | ||||
| } | ||||
| @ -1,19 +1,10 @@ | ||||
| 'use client' | ||||
| 
 | ||||
| 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"; | ||||
| 
 | ||||
| 
 | ||||
| // async function authenticate(){
 | ||||
| //     const url = await constructAPIUrl("auth");
 | ||||
| //     const auth = await fetch(url);
 | ||||
| // }
 | ||||
| 
 | ||||
| 
 | ||||
| export default function LoginForm(){ | ||||
| export default function CLoginForm(){ | ||||
|     const [loginResult, dispatch] = useFormState(serverAttemptAuthenticateUser, undefined); | ||||
| 
 | ||||
|     return ( | ||||
| @ -6,9 +6,6 @@ import { EntityEditorTextArea } from '../input/EntityEditorTextArea'; | ||||
| import { | ||||
| 	ChangeEventHandler, | ||||
| 	MouseEventHandler, | ||||
| 	MutableRefObject, | ||||
| 	useLayoutEffect, | ||||
| 	useRef, | ||||
| 	useState, | ||||
| } from "react"; | ||||
| import { | ||||
|  | ||||
| @ -19,7 +19,7 @@ import { | ||||
| } from "@/app/lib/actions/entityManagement/post/postActions"; | ||||
| 
 | ||||
| import { PostViewProps } from "@/views/admin/post"; | ||||
| import { aifa, StateHook } from "@/util/"; | ||||
| import { StateHook } from "@/util/"; | ||||
| 
 | ||||
| export type PostTableStateProps = { | ||||
| 	posts: StateHook<GetPostsAttributes[]>; | ||||
| @ -110,13 +110,10 @@ export default function PostTable({ | ||||
| 								: `${post.content.substring(0, 255)}...`} | ||||
| 						</td> | ||||
| 						<td key="project"> | ||||
| 							{aifa( | ||||
| 								projects.find((e) => { | ||||
| 									console.log(e.id); | ||||
| 									return e.id == post.project.id; | ||||
| 								})?.readableIdentifier, | ||||
| 								"uncategorized" | ||||
| 							)} | ||||
| 							{projects.find((e) => { | ||||
| 								console.log(e.id); | ||||
| 								return e.id == post.project.id; | ||||
| 							})?.readableIdentifier || "uncategorized"} | ||||
| 						</td> | ||||
| 						<td key="createdAt">{post.createdAt?.toString()}</td> | ||||
| 						<td key="updatedAt">{post.updatedAt?.toString()}</td> | ||||
|  | ||||
| @ -1,16 +0,0 @@ | ||||
| '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> | ||||
|     ) | ||||
| } | ||||
| @ -5,7 +5,6 @@ import { | ||||
| 	MutableRefObject, | ||||
| 	useLayoutEffect, | ||||
| 	ChangeEventHandler, | ||||
| 	useState, | ||||
| } from "react"; | ||||
| import { StateHook } from "@/util"; | ||||
| 
 | ||||
|  | ||||
| @ -1,43 +1,46 @@ | ||||
| 'use server' | ||||
| "use server"; | ||||
| import { cookies } from "next/headers"; | ||||
| 
 | ||||
| import LoginForm            from "@/components/client/admin/loginForm"; | ||||
| import ClientAuthHandler    from "@/components/client/admin/clientAuthHandler"; | ||||
| import CLoginForm from "@/components/client/admin/CLoginForm"; | ||||
| import ClientAuthHandler from "@/components/client/admin/CAuthHandler"; | ||||
| 
 | ||||
| import { serverValidateSessionCookie } from "@/app/lib/actions/actions"; | ||||
| import { ReactNode } from "react"; | ||||
| import { AuthContext, AuthProps } from "@/providers/providers"; | ||||
| 
 | ||||
| import { AuthContextProviderProps } from "@/providers"; | ||||
| 
 | ||||
| interface Props { | ||||
|     children?: ReactNode; | ||||
|     params?: any; | ||||
|     requiredRole?: number; | ||||
| 	children?: ReactNode; | ||||
| 	params?: any; | ||||
| 	requiredRole?: number; | ||||
| } // 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:AuthProps = { | ||||
|     }; | ||||
|     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 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 	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 ( | ||||
|         <div className="flex flex-row w-[100%] h-[100%]"> | ||||
|             {!(koek && await serverValidateSessionCookie(koek)) ? <LoginForm>{ }</LoginForm> : <ClientAuthHandler authProps={p}>{props.children}</ClientAuthHandler>} | ||||
|         </div> | ||||
|     ); | ||||
| 	return ( | ||||
| 		<div className="flex flex-row w-[100%] h-[100%]"> | ||||
| 			{!(koek && (await serverValidateSessionCookie(koek))) ? ( | ||||
| 				<CLoginForm>{}</CLoginForm> | ||||
| 			) : ( | ||||
| 				<ClientAuthHandler authProps={p}> | ||||
| 					{props.children} | ||||
| 				</ClientAuthHandler> | ||||
| 			)} | ||||
| 		</div> | ||||
| 	); | ||||
| } | ||||
|  | ||||
| @ -1,10 +0,0 @@ | ||||
| '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; | ||||
|     padding: 1px 5px 1px 5px; | ||||
|     border-radius: 20%; | ||||
|     *display: inline;  | ||||
|     display: inline;  | ||||
| } | ||||
| .tagbar{ | ||||
|     margin: 0px 0px 0px 0px; | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| // @ts-ignore
 | ||||
| import { createSwaggerSpec } from "next-swagger-doc"; | ||||
| 
 | ||||
| export const getApiDocs = async () => { | ||||
|  | ||||
| @ -10,10 +10,11 @@ import { | ||||
|     HasOne, | ||||
|     UpdatedAt, | ||||
|     CreatedAt, | ||||
|     Table, | ||||
| } from '@sequelize/core/decorators-legacy'; | ||||
| 
 | ||||
| import { SqliteDialect } from '@sequelize/sqlite3'; | ||||
| 
 | ||||
| @Table({tableName: "DBStates"}) | ||||
| export class DBState extends Model<InferAttributes<DBState>, InferCreationAttributes<DBState>>{ | ||||
|      | ||||
|     @Attribute(DataTypes.INTEGER) | ||||
|  | ||||
| @ -20,7 +20,7 @@ export class Project extends Model< | ||||
| > { | ||||
| 	@Attribute(DataTypes.INTEGER) | ||||
| 	@PrimaryKey | ||||
| 	@Unique | ||||
| 	// @Unique
 | ||||
| 	@AutoIncrement | ||||
| 	declare id: CreationOptional<number>; | ||||
| 	@Attribute(DataTypes.STRING) | ||||
|  | ||||
| @ -25,7 +25,7 @@ export * from './UserPerms'; | ||||
| 
 | ||||
| export const sequelize = new Sequelize({ | ||||
|     dialect: SqliteDialect, | ||||
|     storage: 'db.sqlite', | ||||
|     storage: './db/db.sqlite', | ||||
|     models: [Auth, Attachment, Bucket, DBState, Post, PostBucket, PostTag, Project, Tag, User, UserPerms], | ||||
| }); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										14
									
								
								src/providers/authprovider.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/providers/authprovider.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| 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); | ||||
| 
 | ||||
| @ -3,23 +3,14 @@ | ||||
| import { Auth, User } from "@/models"; | ||||
| import { ReactNode, createContext } from "react"; | ||||
| import { Attributes, InferAttributes } from "@sequelize/core"; | ||||
| import { AuthContext } from "./authprovider"; | ||||
| 
 | ||||
| 
 | ||||
| export type AuthProps = { | ||||
|     auth?: Attributes<Auth> | ||||
|     user?: Attributes<User> | ||||
| } | ||||
| 
 | ||||
| let p: AuthProps = {} | ||||
| 
 | ||||
| export const AuthContext = createContext(p); | ||||
| 
 | ||||
| interface Props { | ||||
| interface ProvidersProps { | ||||
|     children?: ReactNode; | ||||
|     params?: any; | ||||
| }  | ||||
| } | ||||
| 
 | ||||
| export default function Providers(props:Props){ | ||||
| export default function ContextProviders(props:ProvidersProps){ | ||||
|     return ( | ||||
|         <AuthContext.Provider value={{}}>{props.children}</AuthContext.Provider> | ||||
|     ) | ||||
							
								
								
									
										2
									
								
								src/providers/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/providers/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| export * from './authprovider'; | ||||
| export * from './contextproviders'; | ||||
| @ -1,3 +0,0 @@ | ||||
| import { ReactNode } from "react"; | ||||
| 
 | ||||
| export const aifa = (a: ReactNode, b: ReactNode) => (a ? a : b); | ||||
| @ -1,10 +1,9 @@ | ||||
| 'server only'; | ||||
| // import Auth from "./Auth";
 | ||||
| export function getAPIEnv() { | ||||
| export async function getAPIEnv() { | ||||
|     return { | ||||
|         'schema': process.env.API_SCHEMA, | ||||
|         'host': process.env.API_HOST, | ||||
|         'port': process.env.API_PORT, | ||||
|         'basepath': process.env.API_BASEPATH | ||||
|         'basepath': process.env.API_BASEPATH, | ||||
|     }; | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| export * from './error'; | ||||
| export * from './getAPIEnv'; | ||||
| export * from './runapiaction'; | ||||
| export * from './user'; | ||||
|  | ||||
							
								
								
									
										19
									
								
								src/util/api/runapiaction.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/util/api/runapiaction.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| 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,6 +1,5 @@ | ||||
| export * from './DeepPartial'; | ||||
| export * from './aifa'; | ||||
| export * from './auth'; | ||||
| export * from './cookies'; | ||||
| export * from './deeppartial'; | ||||
| export * from './state'; | ||||
| export * from './strings'; | ||||
|  | ||||
| @ -1 +1,2 @@ | ||||
| export * from './loremipsum'; | ||||
| export * from './truncateString'; | ||||
| @ -2,11 +2,11 @@ | ||||
| 
 | ||||
| import { getAPIEnv } from "../api/getAPIEnv"; | ||||
| 
 | ||||
| export function constructAPIUrl(endpoint:string){ | ||||
|     const { schema, host, port, basepath } = getAPIEnv(); | ||||
| export async function constructAPIUrl(endpoint:string){ | ||||
|     const { schema, host, port, basepath } = await getAPIEnv(); | ||||
|     return `${schema}://${host}:${port}/${basepath}/${endpoint}` | ||||
| } | ||||
| export function constructUrl(endpoint:string){ | ||||
|     const { schema, host, port, basepath } = getAPIEnv(); | ||||
| export async function constructUrl(endpoint:string){ | ||||
|     const { schema, host, port, basepath } = await getAPIEnv(); | ||||
|     return `${schema}://${host}:${port}/${endpoint}` | ||||
| }1 | ||||
| @ -38,16 +38,14 @@ export function CPostView({ | ||||
|         posts: parseStateHook(useState(posts)), | ||||
|         editor: parseStateHook(useState(initEditorState)), | ||||
| 	}; | ||||
| 
 | ||||
| 	// render out the post table
 | ||||
| 	return ( | ||||
| 		<> | ||||
| 			<PostTable | ||||
| 				headings={headings} | ||||
| 				posts={posts} | ||||
| 				projects={projects} | ||||
| 				actions={actions} | ||||
| 				state={state} | ||||
| 			></PostTable> | ||||
| 		</> | ||||
| 		<PostTable | ||||
| 			headings={headings} | ||||
| 			posts={posts} | ||||
| 			projects={projects} | ||||
| 			actions={actions} | ||||
| 			state={state} | ||||
| 		></PostTable> | ||||
| 	); | ||||
| } | ||||
|  | ||||
| @ -30,14 +30,6 @@ export async function PostView(props: Props) { | ||||
| 		"UpdatedAt", | ||||
| 	]; | ||||
| 
 | ||||
| 	const actions: PostServerActions = { | ||||
| 		deletePost: deletePost, | ||||
| 		getPosts: getPostsWithBucketsAndProject, | ||||
| 		getProjects: getProjects, | ||||
| 		savePost: updatePost, | ||||
| 		// uploadAttachment:tryCreateAttachment
 | ||||
| 	}; | ||||
| 
 | ||||
| 	const posts: GetPostsAttributes[] | undefined = handleActionResult( | ||||
| 		await getPostsWithBucketsAndProject() | ||||
| 	); | ||||
| @ -52,7 +44,12 @@ export async function PostView(props: Props) { | ||||
| 					posts={posts ? posts : []} | ||||
| 					projects={projects} | ||||
| 					headings={headings} | ||||
| 					actions={actions} | ||||
| 					actions={{ | ||||
| 						deletePost: deletePost, | ||||
| 						getPosts: getPostsWithBucketsAndProject, | ||||
| 						getProjects: getProjects, | ||||
| 						savePost: updatePost | ||||
| 					}} | ||||
| 				/> | ||||
| 			</div> | ||||
| 		</div> | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| cache: "no-store"; | ||||
| 
 | ||||
| import { ReactNode, useEffect } from "react"; | ||||
| import { ReactNode } from "react"; | ||||
| import EntityManagementTable from "../../../components/client/EntityManagementTable"; | ||||
| import PostTable from "@/components/client/admin/PostTable"; | ||||
| import { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user