diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index 247ccd6..f687318 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -22,6 +22,7 @@ import { Route as OcpLotsImport } from './routes/ocp/lots' import { Route as EomEomImport } from './routes/_eom/eom' import { Route as AuthProfileImport } from './routes/_auth/profile' import { Route as AdminSettingsImport } from './routes/_admin/settings' +import { Route as AdminServersImport } from './routes/_admin/servers' import { Route as AdminModulesImport } from './routes/_admin/modules' import { Route as logisticsMaterialHelperIndexImport } from './routes/(logistics)/materialHelper/index' import { Route as EomArticleAvImport } from './routes/_eom/article/$av' @@ -93,6 +94,12 @@ const AdminSettingsRoute = AdminSettingsImport.update({ getParentRoute: () => AdminRoute, } as any) +const AdminServersRoute = AdminServersImport.update({ + id: '/servers', + path: '/servers', + getParentRoute: () => AdminRoute, +} as any) + const AdminModulesRoute = AdminModulesImport.update({ id: '/modules', path: '/modules', @@ -179,6 +186,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AdminModulesImport parentRoute: typeof AdminImport } + '/_admin/servers': { + id: '/_admin/servers' + path: '/servers' + fullPath: '/servers' + preLoaderRoute: typeof AdminServersImport + parentRoute: typeof AdminImport + } '/_admin/settings': { id: '/_admin/settings' path: '/settings' @@ -249,11 +263,13 @@ declare module '@tanstack/react-router' { interface AdminRouteChildren { AdminModulesRoute: typeof AdminModulesRoute + AdminServersRoute: typeof AdminServersRoute AdminSettingsRoute: typeof AdminSettingsRoute } const AdminRouteChildren: AdminRouteChildren = { AdminModulesRoute: AdminModulesRoute, + AdminServersRoute: AdminServersRoute, AdminSettingsRoute: AdminSettingsRoute, } @@ -287,6 +303,7 @@ export interface FileRoutesByFullPath { '/about': typeof AboutRoute '/login': typeof LoginRoute '/modules': typeof AdminModulesRoute + '/servers': typeof AdminServersRoute '/settings': typeof AdminSettingsRoute '/profile': typeof AuthProfileRoute '/eom': typeof EomEomRoute @@ -304,6 +321,7 @@ export interface FileRoutesByTo { '/about': typeof AboutRoute '/login': typeof LoginRoute '/modules': typeof AdminModulesRoute + '/servers': typeof AdminServersRoute '/settings': typeof AdminSettingsRoute '/profile': typeof AuthProfileRoute '/eom': typeof EomEomRoute @@ -324,6 +342,7 @@ export interface FileRoutesById { '/about': typeof AboutRoute '/login': typeof LoginRoute '/_admin/modules': typeof AdminModulesRoute + '/_admin/servers': typeof AdminServersRoute '/_admin/settings': typeof AdminSettingsRoute '/_auth/profile': typeof AuthProfileRoute '/_eom/eom': typeof EomEomRoute @@ -343,6 +362,7 @@ export interface FileRouteTypes { | '/about' | '/login' | '/modules' + | '/servers' | '/settings' | '/profile' | '/eom' @@ -359,6 +379,7 @@ export interface FileRouteTypes { | '/about' | '/login' | '/modules' + | '/servers' | '/settings' | '/profile' | '/eom' @@ -377,6 +398,7 @@ export interface FileRouteTypes { | '/about' | '/login' | '/_admin/modules' + | '/_admin/servers' | '/_admin/settings' | '/_auth/profile' | '/_eom/eom' @@ -449,6 +471,7 @@ export const routeTree = rootRoute "filePath": "_admin.tsx", "children": [ "/_admin/modules", + "/_admin/servers", "/_admin/settings" ] }, @@ -475,6 +498,10 @@ export const routeTree = rootRoute "filePath": "_admin/modules.tsx", "parent": "/_admin" }, + "/_admin/servers": { + "filePath": "_admin/servers.tsx", + "parent": "/_admin" + }, "/_admin/settings": { "filePath": "_admin/settings.tsx", "parent": "/_admin" diff --git a/frontend/src/routes/_admin/servers.tsx b/frontend/src/routes/_admin/servers.tsx new file mode 100644 index 0000000..e7df747 --- /dev/null +++ b/frontend/src/routes/_admin/servers.tsx @@ -0,0 +1,14 @@ +import ServerPage from "@/components/admin/servers/ServerPage"; +import {createFileRoute} from "@tanstack/react-router"; + +export const Route = createFileRoute("/_admin/servers")({ + component: RouteComponent, +}); + +function RouteComponent() { + return ( +
+ +
+ ); +} diff --git a/frontend/src/utils/querys/servers.tsx b/frontend/src/utils/querys/servers.tsx new file mode 100644 index 0000000..675404d --- /dev/null +++ b/frontend/src/utils/querys/servers.tsx @@ -0,0 +1,19 @@ +import {queryOptions} from "@tanstack/react-query"; +import axios from "axios"; + +export function getServers(token: string) { + return queryOptions({ + queryKey: ["servers"], + queryFn: () => fetchSettings(token), + enabled: !!token, + staleTime: 1000, + refetchInterval: 500, + refetchOnWindowFocus: true, + }); +} + +const fetchSettings = async (token: string) => { + const {data} = await axios.get("/api/server/servers", {headers: {Authorization: `Bearer ${token}`}}); + + return data.data; +}; diff --git a/server/scripts/updateServers.ts b/server/scripts/updateServers.ts index 6eae1c1..987b05f 100644 --- a/server/scripts/updateServers.ts +++ b/server/scripts/updateServers.ts @@ -5,9 +5,43 @@ import {serverData} from "../../database/schema/serverData.js"; import {eq, sql} from "drizzle-orm"; import {createLog} from "../services/logger/logger.js"; -const updateServer = async (devApp: string, server: string) => { +type UpdateServerResponse = { + success: boolean; + message: string; +}; + +export const updateServer = async (devApp: string, server: string | null): Promise => { const app = await getAppInfo(devApp); - const serverInfo = await db.select().from(serverData).where(eq(serverData.sName, server.toLowerCase())); + const serverInfo = await db + .select() + .from(serverData) + .where(eq(serverData.plantToken, server?.toLowerCase() ?? "")); + + if (serverInfo.length === 0) { + createLog( + "error", + "lst", + "serverUpdater", + `Looks like you are missing the plant token or have entered an incorrect one please try again.` + ); + return { + success: false, + message: "Looks like you are missing the plant token or have entered an incorrect one please try again.", + }; + } + + if (serverInfo[0].isUpgrading) { + createLog( + "error", + "lst", + "serverUpdater", + `Looks like ${serverInfo[0].plantToken} is upgrading already you cant do this again.` + ); + return { + success: false, + message: `Looks like ${serverInfo[0].plantToken} is upgrading already you cant do this again.`, + }; + } const scriptPath = `${process.env.DEVFOLDER}\\server\\scripts\\update.ps1 `; const args = [ @@ -39,9 +73,13 @@ const updateServer = async (devApp: string, server: string) => { , ]; - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { const process = spawn("powershell", args); - + // change the server to upgradeing + await db + .update(serverData) + .set({isUpgrading: true}) + .where(eq(serverData.plantToken, server?.toLowerCase() ?? "")); //let stdout = ""; //let stderr = ""; @@ -69,7 +107,16 @@ const updateServer = async (devApp: string, server: string) => { //update the last build. try { - await db.update(serverData).set({lastUpdated: sql`NOW()`}); + await db + .update(serverData) + .set({lastUpdated: sql`NOW()`, isUpgrading: false}) + .where(eq(serverData.plantToken, server?.toLowerCase() ?? "")); + createLog( + "info", + "lst", + "serverUpdater", + `${server?.toLowerCase()}, has been updated and can now be used again.` + ); } catch (error) { createLog( "error", @@ -79,7 +126,10 @@ const updateServer = async (devApp: string, server: string) => { ); } - resolve({success: true, code}); + resolve({ + success: true, + message: `${server?.toLowerCase()}, has been updated and can now be used again.`, + }); } else { const errorMessage = `Process exited with code ${code}`; @@ -87,7 +137,10 @@ const updateServer = async (devApp: string, server: string) => { // //onClose(code); // } - reject(new Error(errorMessage)); + reject({ + success: false, + message: `${server?.toLowerCase()}, Has encounted an error while updating.`, + }); } }); @@ -107,7 +160,7 @@ export async function processAllServers(devApp: string) { let count = 1; for (const server of servers) { try { - const updateToServer = await updateServer(devApp, server.sName); + const updateToServer = await updateServer(devApp, server.plantToken); createLog("info", "lst", "serverUpdater", `${server.sName} was updated.`); count = count + 1; @@ -118,5 +171,3 @@ export async function processAllServers(devApp: string) { } } } - -updateServer("C:\\Users\\matthes01\\Documents\\lstv2", "test"); diff --git a/server/scripts/zipUpBuild.ts b/server/scripts/zipUpBuild.ts index 5cb8bad..e994ffb 100644 --- a/server/scripts/zipUpBuild.ts +++ b/server/scripts/zipUpBuild.ts @@ -9,6 +9,7 @@ import {getAppInfo} from "../globalUtils/appInfo.js"; const ignoreList = [ ".git", "builds", + "server", "node_modules", "apiDocsLSTV2", "testFiles", @@ -19,7 +20,7 @@ const ignoreList = [ "nssm.exe", "postgresql-17.2-3-windows-x64.exe", // front end ignore - "/frontend/node_modules", + "frontend/node_modules", "fonrtend/.env", "frontend/public", "frontend/src", @@ -33,6 +34,7 @@ const ignoreList = [ "frontend/tsconfig.app.json", "frontend/tsconfig.node.json", "frontend/vite.config.ts", + "frontend/components.json", ]; const shouldIgnore = (itemPath: any) => { @@ -40,7 +42,10 @@ const shouldIgnore = (itemPath: any) => { return ignoreList.some((ignorePattern) => { const normalizedIgnorePatther = ignorePattern.replace(/\\/g, "/"); - return normalizedItemPath.includes(normalizedIgnorePatther); + return ( + normalizedItemPath === normalizedIgnorePatther || + normalizedItemPath.startsWith(`${normalizedIgnorePatther}/`) + ); }); }; diff --git a/server/services/server/route/servers/getServers.ts b/server/services/server/route/servers/getServers.ts new file mode 100644 index 0000000..01532b0 --- /dev/null +++ b/server/services/server/route/servers/getServers.ts @@ -0,0 +1,64 @@ +import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; +import {db} from "../../../../../database/dbclient.js"; +import {authMiddleware} from "../../../auth/middleware/authMiddleware.js"; +import {serverData} from "../../../../../database/schema/serverData.js"; +import {eq} from "drizzle-orm"; + +// Define the request body schema +const requestSchema = z.object({ + ip: z.string().optional(), + endpoint: z.string().optional(), + action: z.string().optional(), + stats: z.string().optional(), +}); + +// Define the response schema +const responseSchema = z.object({ + message: z.string().optional(), + module_id: z.string().openapi({example: "6c922c6c-7de3-4ec4-acb0-f068abdc"}).optional(), + name: z.string().openapi({example: "Production"}).optional(), + active: z.boolean().openapi({example: true}).optional(), + roles: z.string().openapi({example: `["viewer","technician"]`}).optional(), +}); + +const app = new OpenAPIHono(); + +app.openapi( + createRoute({ + tags: ["server"], + summary: "Returns all serverData on the server", + method: "get", + path: "/servers", + middleware: authMiddleware, + responses: { + 200: { + content: { + "application/json": {schema: responseSchema}, + }, + description: "Response message", + }, + }, + }), + async (c) => { + //console.log("system modules"); + let servers: any = []; + try { + servers = await db.select().from(serverData).where(eq(serverData.active, true)); + } catch (error) { + console.log(error); + servers = []; + } + + // sort the servers by there name + servers = servers.sort((a: any, b: any) => a.sName.localeCompare(b.sName)); + + // Return response with the received data + + return c.json({ + message: `All active modules`, + data: servers, + }); + } +); + +export default app; diff --git a/server/services/server/route/updates/updateServer.ts b/server/services/server/route/updates/updateServer.ts new file mode 100644 index 0000000..c323c27 --- /dev/null +++ b/server/services/server/route/updates/updateServer.ts @@ -0,0 +1,93 @@ +import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; +import {authMiddleware} from "../../../auth/middleware/authMiddleware.js"; +import {updateServer} from "../../../../scripts/updateServers.js"; + +// Define the request body schema +const requestSchema = z.object({ + ip: z.string().optional(), + endpoint: z.string().optional(), + action: z.string().optional(), + stats: z.string().optional(), +}); + +// Define the response schema +const responseSchema = z.object({ + message: z.string().optional(), + module_id: z.string().openapi({example: "6c922c6c-7de3-4ec4-acb0-f068abdc"}).optional(), + name: z.string().openapi({example: "Production"}).optional(), + active: z.boolean().openapi({example: true}).optional(), + roles: z.string().openapi({example: `["viewer","technician"]`}).optional(), +}); + +const ParamsSchema = z.object({ + server: z + .string() + .min(3) + .openapi({ + param: { + name: "server", + in: "path", + }, + example: "usbow1", + }), +}); +const UpdateServer = z.object({ + devDir: z.string().openapi({example: "C:\\something\\Something"}), +}); + +const app = new OpenAPIHono(); + +app.openapi( + createRoute({ + tags: ["server"], + summary: "Updates server(s)", + method: "post", + path: "/update/:server", + middleware: authMiddleware, + request: { + params: ParamsSchema, + body: { + content: { + "application/json": {schema: UpdateServer}, + }, + }, + }, + responses: { + 200: { + content: { + "application/json": {schema: responseSchema}, + }, + description: "Response message", + }, + 400: { + content: { + "application/json": {schema: responseSchema}, + }, + description: "Response message", + }, + }, + }), + async (c) => { + const {server} = c.req.valid("param"); + const body = await c.req.json(); + + // fire off the update we wont make this way + try { + const update = await updateServer(body.devDir, server); + + return c.json({ + success: update?.success ?? false, + message: update?.message, + data: [], + }); + } catch (error) { + return c.json({ + success: false, + message: `${server} Encountered an ${error}`, + data: [], + }); + } + } +); + +export default app; diff --git a/server/services/server/utils/serverData.ts b/server/services/server/utils/serverData.ts index 1d740fe..20b2c36 100644 --- a/server/services/server/utils/serverData.ts +++ b/server/services/server/utils/serverData.ts @@ -14,44 +14,40 @@ export const serversCheckPoint = async () => { } else { filePath = "./dist/server/services/server/utils/serverData.json"; } - fs.readFile(filePath, "utf8", (err, data) => { - if (err) { - console.error("Error reading JSON file:", err); - return; - } - servers = JSON.parse(data); - }); + + try { + const data = fs.readFileSync(filePath, "utf8"); + const serverData = JSON.parse(data); + servers = serverData.servers; + } catch (err) { + console.error("Error reading JSON file:", err); + } // get the roles - try { - const settingsCheck = await db.select().from(serverData); - try { - for (let i = 0; i < servers.length; i++) { - const newRole = await db - .insert(serverData) - .values(servers[i]) - .onConflictDoUpdate({ - target: serverData.plantToken, - set: { - sName: servers[i].sName, - serverDNS: servers[i].serverDNS, - active: servers[i].active, - contactEmail: servers[i].contactEmail, - contactPhone: servers[i].contactPhone, - shippingHours: servers[i].shippingHours, - customerTiAcc: servers[i].customerTiAcc, - tiPostTime: servers[i].tiPostTime, - otherSettings: servers[i].otherSettings, - }, - }) // this will only update the ones that are new :D - .returning({name: serverData.sName}); - } - createLog("info", "lst", "server", "Servers were just added/updated due to server startup"); - } catch (error) { - createLog("error", "lst", "server", `There was an error adding/updating serverData to the db, ${error}`); + try { + for (let i = 0; i < servers.length; i++) { + const serverUpdate = await db + .insert(serverData) + .values(servers[i]) + .onConflictDoUpdate({ + target: serverData.plantToken, + set: { + sName: servers[i].sName, + serverDNS: servers[i].serverDNS, + active: servers[i].active, + contactEmail: servers[i].contactEmail, + contactPhone: servers[i].contactPhone, + shippingHours: servers[i].shippingHours, + customerTiAcc: servers[i].customerTiAcc, + tiPostTime: servers[i].tiPostTime, + otherSettings: servers[i].otherSettings, + }, + }) // this will only update the ones that are new :D + .returning({name: serverData.sName}); } + createLog("info", "lst", "server", "Servers were just added/updated due to server startup"); } catch (error) { - createLog("error", "lst", "server", `There was an error adding serverData to the db, ${error}`); + createLog("error", "lst", "server", `There was an error adding/updating serverData to the db, ${error}`); } };