-
Super Secret Admin Panel!
-
this is where we use the context test:
-
-
+
+ {/*
Super Secret Admin Panel!
*/}
+ {/*
this is where we use the context test:
*/}
+ {/*
*/}
+ {/*
*/}
+ {/* {props.children} */}
+ {/* */}
+ {/* */}
+
+
{view}
+
)
}
diff --git a/src/components/client/admin/entryEditor.tsx b/src/components/client/admin/entryEditor.tsx
new file mode 100644
index 0000000..6a9e9b6
--- /dev/null
+++ b/src/components/client/admin/entryEditor.tsx
@@ -0,0 +1,9 @@
+
+
+export default function EntryEditor(){
+ return (
+
+ Entries
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/client/admin/views/ClientPostView.tsx b/src/components/client/admin/views/ClientPostView.tsx
new file mode 100644
index 0000000..4e82fd5
--- /dev/null
+++ b/src/components/client/admin/views/ClientPostView.tsx
@@ -0,0 +1,16 @@
+'use client'
+
+import ServerComponentTest from "@/components/server/ServerComponentTest";
+import { ReactNode } from "react";
+
+type Props = {
+ children?:ReactNode
+}
+
+export default function ClientPostView(props:Props){
+ return (
+
+ test
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/client/admin/views/sidebar.css b/src/components/client/admin/views/sidebar.css
new file mode 100644
index 0000000..8c630a5
--- /dev/null
+++ b/src/components/client/admin/views/sidebar.css
@@ -0,0 +1,90 @@
+body {
+ min-height: 100vh;
+ min-height: -webkit-fill-available;
+ }
+
+ html {
+ height: -webkit-fill-available;
+ }
+
+ main {
+ display: flex;
+ flex-wrap: nowrap;
+ height: 100vh;
+ height: -webkit-fill-available;
+ max-height: 100vh;
+ overflow-x: auto;
+ overflow-y: hidden;
+ }
+
+ .b-example-divider {
+ flex-shrink: 0;
+ width: 1.5rem;
+ height: 100vh;
+ background-color: rgba(0, 0, 0, .1);
+ border: solid rgba(0, 0, 0, .15);
+ border-width: 1px 0;
+ box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
+ }
+
+ .bi {
+ vertical-align: -.125em;
+ pointer-events: none;
+ fill: currentColor;
+ }
+
+ .dropdown-toggle { outline: 0; }
+
+ .nav-flush .nav-link {
+ border-radius: 0;
+ }
+
+ .btn-toggle {
+ display: inline-flex;
+ align-items: center;
+ padding: .25rem .5rem;
+ font-weight: 600;
+ color: rgba(0, 0, 0, .65);
+ background-color: transparent;
+ border: 0;
+ }
+ .btn-toggle:hover,
+ .btn-toggle:focus {
+ color: rgba(0, 0, 0, .85);
+ background-color: #d2f4ea;
+ }
+
+ .btn-toggle::before {
+ width: 1.25em;
+ line-height: 0;
+ content: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='rgba%280,0,0,.5%29' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/%3e%3c/svg%3e");
+ transition: transform .35s ease;
+ transform-origin: .5em 50%;
+ }
+
+ .btn-toggle[aria-expanded="true"] {
+ color: rgba(0, 0, 0, .85);
+ }
+ .btn-toggle[aria-expanded="true"]::before {
+ transform: rotate(90deg);
+ }
+
+ .btn-toggle-nav a {
+ display: inline-flex;
+ padding: .1875rem .5rem;
+ margin-top: .125rem;
+ margin-left: 1.25rem;
+ text-decoration: none;
+ }
+ .btn-toggle-nav a:hover,
+ .btn-toggle-nav a:focus {
+ background-color: #d2f4ea;
+ }
+
+ .scrollarea {
+ overflow-y: auto;
+ }
+
+ .fw-semibold { font-weight: 600; }
+ .lh-tight { line-height: 1.25; }
+
\ No newline at end of file
diff --git a/src/components/client/admin/views/sidebar.tsx b/src/components/client/admin/views/sidebar.tsx
new file mode 100644
index 0000000..03d86d3
--- /dev/null
+++ b/src/components/client/admin/views/sidebar.tsx
@@ -0,0 +1,30 @@
+import './sidebar.css'
+import { Button, NavLink } from 'react-bootstrap';
+import { SidebarEntry } from '../adminPanel';
+import React, { ReactNode, useState } from 'react';
+
+
+
+
+type Props = {
+ children?:ReactNode;
+ sidebarEntries:Array
;
+ switchView:any;
+}
+
+
+
+export default function Sidebar(props:Props){
+
+ return (
+
+
+ {props.sidebarEntries.map((sidebarEntry)=>{
+ return - {props.switchView(sidebarEntry.view)}}>
+ {sidebarEntry.label}
+
+ })}
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/server/ServerComponentTest.tsx b/src/components/server/ServerComponentTest.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/server/admin/authHandler.tsx b/src/components/server/admin/authHandler.tsx
index 87c1027..940ab83 100644
--- a/src/components/server/admin/authHandler.tsx
+++ b/src/components/server/admin/authHandler.tsx
@@ -40,8 +40,8 @@ export default async function AuthHandler(props: Props) {
}
return (
-
- {!(koek && await serverValidateSessionCookie(koek)) ?
{ } :
{props.children}signed in! :D
}
+
+ {!(koek && await serverValidateSessionCookie(koek)) ? { } : {props.children}}
);
}
diff --git a/src/components/server/admin/authWrapper.tsx b/src/components/server/admin/authWrapper.tsx
new file mode 100644
index 0000000..f8ed201
--- /dev/null
+++ b/src/components/server/admin/authWrapper.tsx
@@ -0,0 +1,47 @@
+'use server'
+import { cookies } from "next/headers";
+
+import LoginForm from "@/components/client/admin/loginForm";
+import AdminPanel from "@/components/client/admin/adminPanel";
+import ClientAuthHandler from "@/components/client/admin/clientAuthHandler";
+
+import { serverValidateSessionCookie } from "@/app/lib/actions";
+import { constructAPIUrl } from "@/util/Utils";
+import { ReactNode } from "react";
+import { AuthContext, AuthProps } from "@/providers/providers";
+
+
+interface Props {
+ 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 = {
+ test:"not pog"
+ };
+ if(koek){
+ const kd = JSON.parse(koek);
+ if(kd.id && kd.token && kd.user_id){
+ p = {
+ test:"success!",
+ auth: {
+ id:kd.id,
+ token:kd.token,
+ user_id:kd.user_id
+ }
+ }
+ }
+ }
+
+ return (
+
+ {!(koek && await serverValidateSessionCookie(koek)) ? { } : }
+
+ );
+}
diff --git a/src/components/server/admin/views/PostView.tsx b/src/components/server/admin/views/PostView.tsx
new file mode 100644
index 0000000..4d3a246
--- /dev/null
+++ b/src/components/server/admin/views/PostView.tsx
@@ -0,0 +1,21 @@
+'use server'
+
+import { ReactNode } from "react"
+import AuthHandler from "../authHandler"
+import { Post } from "@/model/Post"
+import { constructAPIUrl } from "@/util/Utils"
+
+type Props = {
+ children?:ReactNode
+}
+
+export default async function PostView(props:Props){
+ // const posts = await Post.findAll();
+
+
+ return (
+
+ test
+
+ );
+}
\ No newline at end of file
diff --git a/src/model/Project.ts b/src/model/Project.ts
index 178e384..cfe60b2 100644
--- a/src/model/Project.ts
+++ b/src/model/Project.ts
@@ -1,11 +1,9 @@
import { Association, BelongsToGetAssociationMixin, CreationOptional, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize } from "@sequelize/core";import { User } from "./User";
import { SqliteDialect } from '@sequelize/sqlite3';
+import { Attribute, AutoIncrement, PrimaryKey, Unique } from "@sequelize/core/decorators-legacy";
+import { Post } from "./Post";
-const sequelize = new Sequelize({
- dialect: SqliteDialect,
- storage: 'db.sqlite'
-});
export type ProjectAttributes = {
id: number;
title: string;
@@ -20,37 +18,21 @@ export type ProjectCreationAttributes = {
user_id:number;
}
export class Project extends Model
{
+ @Attribute(DataTypes.INTEGER) @PrimaryKey @Unique @AutoIncrement
declare id: number;
- declare user:NonAttribute;
- declare user_id:ForeignKey;
- declare getUser: BelongsToGetAssociationMixin;
+ @Attribute(DataTypes.STRING) @Unique
+ declare readableIdentifier: string;
+ @Attribute(DataTypes.STRING)
+ declare name: string;
+
declare static associations: {
- user: Association;
+ posts: Association;
+
};
+
}
-Project.init(
- {
- id: {
- allowNull: false,
- autoIncrement: true,
- type: DataTypes.INTEGER,
- primaryKey: true,
- unique: true,
- },
- content: {
- type: DataTypes.STRING
- },
- title: {
- type: DataTypes.STRING
- },
- date: {
- type: DataTypes.DATE
- },
-
- },
- {
- tableName: 'Projects',
- sequelize // passing the `sequelize` instance is required
- }
-);
\ No newline at end of file
+const sequelize = new Sequelize({
+ dialect: SqliteDialect,
+ models: [Project]
+})
diff --git a/src/model/Tag.ts b/src/model/Tag.ts
index ea99f8f..8ec5ab0 100644
--- a/src/model/Tag.ts
+++ b/src/model/Tag.ts
@@ -10,12 +10,10 @@ export class Tag extends Model, InferCreationAttributes;
-
- declare user_id:ForeignKey;
- declare getPost: BelongsToManyGetAssociationsMixin;
+ declare getPosts: BelongsToManyGetAssociationsMixin;
+
declare static associations: {
posts: Association;
};
diff --git a/src/model/User.ts b/src/model/User.ts
index 0b222ce..723dec5 100644
--- a/src/model/User.ts
+++ b/src/model/User.ts
@@ -55,9 +55,10 @@ export class User extends Model, InferCreationAttributes
+
declare static associations: {
- perms: Association;
- posts: Association
+ perms: Association;
+ posts: Association
authtokens: Association;
};
diff --git a/src/providers/providers.tsx b/src/providers/providers.tsx
index ec63481..57dfb17 100644
--- a/src/providers/providers.tsx
+++ b/src/providers/providers.tsx
@@ -15,8 +15,19 @@ let p: AuthProps = {
test: "lorem",
}
+export type AdminViewProps = {
+ view: string;
+}
+
+let avp: AdminViewProps = {
+ view: "home",
+}
+
+export const AdminViewContext = createContext(avp);
export const AuthContext = createContext(p);
+
+
interface Props {
children?: ReactNode;
params?: any;
@@ -24,6 +35,6 @@ interface Props {
export default function Providers(props:Props){
return (
- {props.children}
+ {props.children}
)
}
\ No newline at end of file
diff --git a/src/util/api/error.ts b/src/util/api/error.ts
new file mode 100644
index 0000000..716b6b2
--- /dev/null
+++ b/src/util/api/error.ts
@@ -0,0 +1,28 @@
+type APIErrorMessage = {
+ status: number,
+ responseText: string
+}
+class APIError extends Error{
+ declare info:APIErrorMessage
+ constructor(message:APIErrorMessage) {
+ super(JSON.stringify(message))
+ this.info = message;
+ this.name = "AuthError"; // (different names for different built-in error classes)
+ }
+}
+
+const attemptAPIAction = async (action:Function,request:Request) => {
+ try {
+ return await action(request);
+ }
+ catch (e) {
+ if (e instanceof APIError) {
+ return new Response(e.info.responseText, { status: e.info.status });
+ }
+ else {
+ throw e;
+ }
+ }
+}
+
+export { APIError, attemptAPIAction }
\ No newline at end of file
diff --git a/src/api/user.ts b/src/util/api/user.ts
similarity index 95%
rename from src/api/user.ts
rename to src/util/api/user.ts
index f9a0c37..a56f4de 100644
--- a/src/api/user.ts
+++ b/src/util/api/user.ts
@@ -2,7 +2,7 @@
// import { MAuth } from "@/model/sequelize/Auth";
import { validatePassword } from "@/util/Auth";
-import { APIError } from "@/api/error";
+import { APIError } from "@/util/api/error";
import { User } from "@/model/User";
export function parseBasicAuth(authb64:string):UserAuth