From 8491c5263988d39196abcda67abb0bb1584a3566 Mon Sep 17 00:00:00 2001 From: Archben Date: Mon, 9 Mar 2026 14:35:16 +0000 Subject: [PATCH] Updates --- src/components/general/admin/hero.tsx | 25 +++++++++++++++++++ .../pages/admin/(sections)/summary.tsx | 11 ++++++++ src/components/pages/admin/index.tsx | 19 ++++++++++++++ .../pages/admin/default-admin-props.ts | 7 +++++- src/layouts/login/index.tsx | 4 +-- src/pages/_app.tsx | 14 +++++++++-- src/pages/admin/index.tsx | 2 +- src/styles/globals.css | 9 +++++++ src/types/index.ts | 12 ++++++++- src/utils/grab-cookie-names.ts | 23 +++++++++++++++++ src/utils/grab-dir-names.ts | 2 ++ src/utils/login-user.ts | 8 +++--- src/utils/user-auth.ts | 11 ++++---- 13 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 src/components/general/admin/hero.tsx create mode 100644 src/components/pages/admin/(sections)/summary.tsx create mode 100644 src/components/pages/admin/index.tsx create mode 100644 src/utils/grab-cookie-names.ts diff --git a/src/components/general/admin/hero.tsx b/src/components/general/admin/hero.tsx new file mode 100644 index 0000000..835100d --- /dev/null +++ b/src/components/general/admin/hero.tsx @@ -0,0 +1,25 @@ +import H1 from "@/twui/components/layout/H1"; +import Row from "@/twui/components/layout/Row"; +import Span from "@/twui/components/layout/Span"; +import Stack from "@/twui/components/layout/Stack"; +import { ReactNode } from "react"; + +type Props = { + title: string | ReactNode; + description?: string | ReactNode; + ctas?: ReactNode; +}; + +export default function AdminHero({ title, ctas, description }: Props) { + return ( + + +

{title}

+ {description ? ( + {description} + ) : null} +
+ {ctas} +
+ ); +} diff --git a/src/components/pages/admin/(sections)/summary.tsx b/src/components/pages/admin/(sections)/summary.tsx new file mode 100644 index 0000000..a093fb7 --- /dev/null +++ b/src/components/pages/admin/(sections)/summary.tsx @@ -0,0 +1,11 @@ +import { AppContext } from "@/src/pages/_app"; +import Row from "@/twui/components/layout/Row"; +import { useContext } from "react"; + +export default function AdminSummary() { + const { pageProps } = useContext(AppContext); + + console.log("pageProps", pageProps); + + return ; +} diff --git a/src/components/pages/admin/index.tsx b/src/components/pages/admin/index.tsx new file mode 100644 index 0000000..0efdb34 --- /dev/null +++ b/src/components/pages/admin/index.tsx @@ -0,0 +1,19 @@ +import Stack from "@/twui/components/layout/Stack"; +import AdminSummary from "./(sections)/summary"; +import AdminHero from "../../general/admin/hero"; + +export default function Main() { + return ( + + + Deployment ad9asd + + } + /> + + + ); +} diff --git a/src/functions/pages/admin/default-admin-props.ts b/src/functions/pages/admin/default-admin-props.ts index a0a5614..43bf582 100644 --- a/src/functions/pages/admin/default-admin-props.ts +++ b/src/functions/pages/admin/default-admin-props.ts @@ -1,5 +1,6 @@ import { EJSON } from "@/src/exports/client-exports"; import { PagePropsType, URLQueryType, User } from "@/src/types"; +import grabTurboCiConfig from "@/src/utils/grab-turboci-config"; import parsePageUrl from "@/src/utils/parse-page-url"; import userAuth from "@/src/utils/user-auth"; import _ from "lodash"; @@ -24,9 +25,12 @@ export default async function defaultAdminProps({ props, propsFn, }: Params): Promise> { - const { req, query, res } = ctx; + const { req, res } = ctx; + const query: URLQueryType = ctx.query; const { singleRes: user } = await userAuth({ req }); + const config = grabTurboCiConfig(); + if (!user?.id) { return { redirect: { @@ -64,6 +68,7 @@ export default async function defaultAdminProps({ query, user, pageUrl: finalAdminUrl, + config, }; let finalProps = _.merge(props, propsFnProps, defaultPageProps); diff --git a/src/layouts/login/index.tsx b/src/layouts/login/index.tsx index 13b9d03..848c488 100644 --- a/src/layouts/login/index.tsx +++ b/src/layouts/login/index.tsx @@ -15,8 +15,8 @@ export default function Layout({ children }: Props) { return (
- - + + diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 4515678..db8882f 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,6 +1,16 @@ import "@/src/styles/globals.css"; import type { AppProps } from "next/app"; +import { createContext } from "react"; +import { PagePropsType, TurboCIAdminAppContextType } from "../types"; -export default function App({ Component, pageProps }: AppProps) { - return ; +export const AppContext = createContext( + {} as TurboCIAdminAppContextType, +); + +export default function App({ Component, pageProps }: AppProps) { + return ( + + + + ); } diff --git a/src/pages/admin/index.tsx b/src/pages/admin/index.tsx index 1a2eda8..78b34aa 100644 --- a/src/pages/admin/index.tsx +++ b/src/pages/admin/index.tsx @@ -1,4 +1,4 @@ -import Main from "@/src/components/pages/home"; +import Main from "@/src/components/pages/admin"; import defaultAdminProps from "@/src/functions/pages/admin/default-admin-props"; import Layout from "@/src/layouts/admin"; import { GetServerSideProps } from "next"; diff --git a/src/styles/globals.css b/src/styles/globals.css index ee1d3a1..9a8b1a7 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -85,3 +85,12 @@ .turboci-admin-aside-link.active * { @apply font-semibold; } + +.admin-h1 { + @apply text-3xl; +} + +code { + @apply bg-slate-100 dark:bg-white/10 px-3 py-1 rounded-default; + @apply my-1; +} diff --git a/src/types/index.ts b/src/types/index.ts index 1478acb..3b58fa2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -169,9 +169,15 @@ export type ServiceScriptObject = { work_dir?: string; }; -export type PagePropsType = {}; export type URLQueryType = {}; +export type PagePropsType = { + config?: TCIGlobalConfig | null; + query?: URLQueryType | null; + user: User; + pageUrl?: string | null; +}; + export type APIReqObject = { username?: string; email?: string; @@ -201,3 +207,7 @@ export type TurboCISignupFormObject = { password?: string; confirmed_password?: string; }; + +export type TurboCIAdminAppContextType = { + pageProps: PagePropsType; +}; diff --git a/src/utils/grab-cookie-names.ts b/src/utils/grab-cookie-names.ts new file mode 100644 index 0000000..6531e78 --- /dev/null +++ b/src/utils/grab-cookie-names.ts @@ -0,0 +1,23 @@ +import { existsSync, readFileSync } from "fs"; +import grabDirNames from "./grab-dir-names"; + +export default function grabCookieNames() { + const { TURBOCI_DEPLOYMENT_ID_FILE } = grabDirNames(); + + if (!existsSync(TURBOCI_DEPLOYMENT_ID_FILE)) { + throw new Error(`\`${TURBOCI_DEPLOYMENT_ID_FILE}\` does not exist.`); + } + + const deployment_id = readFileSync(TURBOCI_DEPLOYMENT_ID_FILE, "utf-8"); + + const deplyment_uid_short = deployment_id.split("-").shift(); + + if (!deplyment_uid_short) { + throw new Error(`Invalid deployment_id`); + } + + const auth_key_cookie_name = `turboci-admin-${deplyment_uid_short}-auth-key`; + const csrf_cookie_name = `turboci-admin-${deplyment_uid_short}-csrf`; + + return { auth_key_cookie_name, csrf_cookie_name }; +} diff --git a/src/utils/grab-dir-names.ts b/src/utils/grab-dir-names.ts index 94b2cc4..83e68bd 100644 --- a/src/utils/grab-dir-names.ts +++ b/src/utils/grab-dir-names.ts @@ -8,6 +8,7 @@ export default function grabDirNames() { TURBOCI_CONFIG_DIR, "turboci.json", ); + const TURBOCI_DEPLOYMENT_ID_FILE = path.join(TURBOCI_DIR, "deployment_id"); const TURBOCI_SSH_DIR = path.join(TURBOCI_DIR, ".ssh"); const TURBOCI_SSH_KEY_FILE = path.join(TURBOCI_SSH_DIR, "turboci"); @@ -19,5 +20,6 @@ export default function grabDirNames() { TURBOCI_DIR, TURBOCI_SSH_DIR, TURBOCI_SSH_KEY_FILE, + TURBOCI_DEPLOYMENT_ID_FILE, }; } diff --git a/src/utils/login-user.ts b/src/utils/login-user.ts index 482de46..d778ba0 100644 --- a/src/utils/login-user.ts +++ b/src/utils/login-user.ts @@ -3,13 +3,13 @@ import { ServerResponse } from "http"; import NSQLite from "@moduletrace/nsqlite"; import { NSQLITE_TEST_DB_USERS, NSQLiteTables } from "../db/types"; import { User } from "../types"; -import { AppData } from "../data/app-data"; import { setCookie } from "./cookies-actions"; import { EJSON } from "../exports/client-exports"; import encrypt from "@moduletrace/datasquirel/dist/package-shared/functions/dsql/encrypt"; import { APIResponseObject } from "@moduletrace/datasquirel/dist/package-shared/types"; import hashPassword from "@moduletrace/datasquirel/dist/package-shared/functions/dsql/hashPassword"; import dayjs from "dayjs"; +import grabCookieNames from "./grab-cookie-names"; type Params = { res: NextApiResponse | ServerResponse; @@ -111,9 +111,11 @@ export default async function loginUser({ const expiration_date = dayjs(Date.now()).add(7, "days"); expiration_date.add(7, "days"); + const { auth_key_cookie_name, csrf_cookie_name } = grabCookieNames(); + setCookie(res, [ { - name: AppData["AuthCookieName"], + name: auth_key_cookie_name, value: encrypted_payload || "", options: { secure: process.env.DOMAIN !== "localhost", @@ -123,7 +125,7 @@ export default async function loginUser({ }, }, { - name: AppData["AuthCSRFCookieName"], + name: csrf_cookie_name, value: csrf_k, options: { path: "/", diff --git a/src/utils/user-auth.ts b/src/utils/user-auth.ts index 84d3c24..050e257 100644 --- a/src/utils/user-auth.ts +++ b/src/utils/user-auth.ts @@ -1,11 +1,11 @@ import { NextApiRequest } from "next"; import { User } from "../types"; import { IncomingMessage } from "http"; -import { AppData } from "../data/app-data"; import { getCookie } from "./cookies-actions"; import { APIResponseObject } from "@moduletrace/datasquirel/dist/package-shared/types"; import decrypt from "@moduletrace/datasquirel/dist/package-shared/functions/dsql/decrypt"; import { EJSON } from "../exports/client-exports"; +import grabCookieNames from "./grab-cookie-names"; type Params = { req: @@ -17,12 +17,13 @@ export default async function userAuth({ req, }: Params): Promise> { try { - const key = getCookie(req, AppData["AuthCookieName"]); + const { auth_key_cookie_name, csrf_cookie_name } = grabCookieNames(); + const key = getCookie(req, auth_key_cookie_name); if (!key) { return { success: false, - msg: `No ${AppData["AuthCookieName"]} found in request object.`, + msg: `No ${auth_key_cookie_name} found in request object.`, }; } @@ -36,12 +37,12 @@ export default async function userAuth({ }; } - const csrf = getCookie(req, AppData["AuthCSRFCookieName"]); + const csrf = getCookie(req, csrf_cookie_name); if (!csrf) { return { success: false, - msg: `No ${AppData["AuthCSRFCookieName"]} found in request object.`, + msg: `No ${csrf_cookie_name} found in request object.`, }; }