From 12e15babb45bffbd7322197d850fa0507c86c05f Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Fri, 7 Mar 2025 13:40:29 -0600 Subject: [PATCH] fix(logging): updated entire server side to the new logging system --- database/schema/logs.ts | 26 ++++++++ server/globalUtils/createUrl.ts | 32 ++++++++++ server/index.ts | 35 ++++++++++- server/services/auth/controllers/login.ts | 7 ++- .../auth/controllers/users/updateProfile.ts | 12 ++-- server/services/auth/routes/login.ts | 3 +- server/services/auth/routes/session.ts | 3 +- .../auth/routes/user/profileUpdate.ts | 4 +- server/services/auth/utils/roleCheck.ts | 13 ++-- server/services/general/route/scalar.ts | 11 +++- server/services/general/utils/mailer.ts | 4 +- .../logistics/controller/consumeMaterial.ts | 54 +++++++++++++++++ server/services/logistics/logisticsService.ts | 13 ++++ .../logistics/route/consumeMaterial.ts | 59 +++++++++++++++++++ .../server/controller/module/addModule.ts | 6 +- .../server/controller/module/updateModule.ts | 8 +-- .../server/controller/settings/addSetting.ts | 10 ++-- .../server/controller/settings/getSettings.ts | 6 +- .../controller/settings/updateSetting.ts | 10 ++-- .../server/route/modules/addModule.ts | 5 -- .../server/route/modules/getModules.ts | 1 - .../server/route/modules/updateModules.ts | 4 -- .../server/route/settings/addSetting.ts | 3 +- .../server/route/settings/getSettings.ts | 3 +- .../server/route/settings/updateSetting.ts | 2 - server/services/server/utils/moduleCheck.ts | 13 ++-- server/services/server/utils/settingsCheck.ts | 8 +-- .../querys/materialHelpers/labelInfo.ts | 3 + .../services/sqlServer/route/closeProdSql.ts | 46 +++++++++++++++ .../sqlServer/route/restartProdSql.ts | 48 +++++++++++++++ .../services/sqlServer/route/startProdSql.ts | 46 +++++++++++++++ .../sqlServer/utils/prodServerConfig.ts | 43 ++++++++++++++ server/services/tcpServer/tcpServer.ts | 13 ++-- 33 files changed, 482 insertions(+), 72 deletions(-) create mode 100644 database/schema/logs.ts create mode 100644 server/globalUtils/createUrl.ts create mode 100644 server/services/logistics/controller/consumeMaterial.ts create mode 100644 server/services/logistics/logisticsService.ts create mode 100644 server/services/logistics/route/consumeMaterial.ts create mode 100644 server/services/sqlServer/querys/materialHelpers/labelInfo.ts create mode 100644 server/services/sqlServer/route/closeProdSql.ts create mode 100644 server/services/sqlServer/route/restartProdSql.ts create mode 100644 server/services/sqlServer/route/startProdSql.ts create mode 100644 server/services/sqlServer/utils/prodServerConfig.ts diff --git a/database/schema/logs.ts b/database/schema/logs.ts new file mode 100644 index 0000000..5711e81 --- /dev/null +++ b/database/schema/logs.ts @@ -0,0 +1,26 @@ +import {text, pgTable, numeric, index, timestamp, boolean, uuid, uniqueIndex} from "drizzle-orm/pg-core"; +import {createInsertSchema, createSelectSchema} from "drizzle-zod"; +import {z} from "zod"; + +export const logs = pgTable( + "logs", + { + log_id: uuid("log_id").defaultRandom().primaryKey(), + level: text("level"), + username: text("username").default("LST_Serivce"), + service: text("service").notNull().default("system"), + message: text("message").notNull(), + created_at: timestamp("add_Date").defaultNow(), + }, + (table) => [ + // uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`), + // uniqueIndex("role_name").on(table.name), + ] +); + +// Schema for inserting a user - can be used to validate API requests +// export const insertRolesSchema = createInsertSchema(roles, { +// name: z.string().min(3, {message: "Role name must be more than 3 letters"}), +// }); +// Schema for selecting a Expenses - can be used to validate API responses +export const selectRolesSchema = createSelectSchema(logs); diff --git a/server/globalUtils/createUrl.ts b/server/globalUtils/createUrl.ts new file mode 100644 index 0000000..50c88e7 --- /dev/null +++ b/server/globalUtils/createUrl.ts @@ -0,0 +1,32 @@ +import {eq} from "drizzle-orm"; +import {db} from "../../database/dbclient.js"; +import {settings} from "../../database/schema/settings.js"; + +// create the test server stuff +const testServers = [ + {token: "test1", port: 8940}, + {token: "test2", port: 8941}, + {token: "test3", port: 8942}, +]; + +export const prodEndpointCreation = async (endpoint: string) => { + let url = ""; + //get the plant token + const plantToken = await db.select().from(settings).where(eq(settings.name, "plantToken")); + + // check if we are a test server + const testServer = testServers.some((server) => server.token === plantToken[0].value); + const server = await db.select().from(settings).where(eq(settings.name, "dbServer")); + + if (testServer) { + //filter out what testserver we are + const test = testServers.filter((t) => t.token === plantToken[0].value); + // "https://usmcd1vms036.alpla.net:8942/application/public/v1.0/DemandManagement/ORDERS" + // "https://usmcd1vms036.alpla.net:8492/application/public/v1.0/DemandManagement/ORDERS" + url = `https://${server[0].value}.alpla.net:${test[0].port}/application${endpoint}`; + return url; + } else { + url = `https://${plantToken[0].value}prod.alpla.net/application${endpoint}`; + return url; + } +}; diff --git a/server/index.ts b/server/index.ts index e6df617..d5b6d77 100644 --- a/server/index.ts +++ b/server/index.ts @@ -4,7 +4,8 @@ import {OpenAPIHono} from "@hono/zod-openapi"; import {serveStatic} from "@hono/node-server/serve-static"; import {logger} from "hono/logger"; import {cors} from "hono/cors"; -import {log} from "./services/logger/logger.js"; +import {createLog} from "./services/logger/logger.js"; +import {closePool} from "./services/sqlServer/prodSqlServer.js"; // custom routes import scalar from "./services/general/route/scalar.js"; @@ -12,6 +13,8 @@ import system from "./services/server/systemServer.js"; import auth from "./services/auth/authService.js"; import tcpServer from "./services/tcpServer/tcpServer.js"; import ocme from "./services/ocme/ocmeService.js"; +import sqlService from "./services/sqlServer/sqlService.js"; +import logistics from "./services/logistics/logisticsService.js"; const allowedOrigins = ["http://localhost:3000", "http://localhost:4000", "http://localhost:5173"]; const app = new OpenAPIHono(); @@ -46,7 +49,7 @@ app.use("*", async (c, next) => { app.doc("/api/ref", { openapi: "3.0.0", info: { - version: "1.0.0", + version: "2.0.0", title: "LST API", }, }); @@ -57,6 +60,8 @@ const routes = [ // apiHits, system, tcpServer, + sqlService, + logistics, ] as const; const appRoutes = routes.forEach((route) => { @@ -77,13 +82,37 @@ app.route("/ocme/", ocme); app.use("/*", serveStatic({root: "./frontend/dist"})); app.use("*", serveStatic({path: "./frontend/dist/index.html"})); +// Handle app exit signals +process.on("SIGINT", async () => { + console.log("\nGracefully shutting down..."); + await closePool(); + process.exit(0); +}); + +process.on("SIGTERM", async () => { + console.log("Received termination signal, closing database..."); + await closePool(); + process.exit(0); +}); + +process.on("uncaughtException", async (err) => { + console.log("Uncaught Exception:", err); + await closePool(); + process.exit(1); +}); + +process.on("beforeExit", async () => { + console.log("Process is about to exit..."); + await closePool(); +}); + serve( { fetch: app.fetch, port: Number(process.env.VITE_SERVER_PORT), }, (info) => { - log.info({username: "LST-SYSTEM"}, `Server is running on http://localhost:${info.port}`); + createLog("info", "LST", "server", `Server is running on http://localhost:${info.port}`); } ); diff --git a/server/services/auth/controllers/login.ts b/server/services/auth/controllers/login.ts index 08ab5e0..6d25a20 100644 --- a/server/services/auth/controllers/login.ts +++ b/server/services/auth/controllers/login.ts @@ -4,7 +4,7 @@ import {users} from "../../../../database/schema/users.js"; import {eq, sql} from "drizzle-orm"; import {checkPassword} from "../utils/checkPassword.js"; import {roleCheck} from "./userRoles/getUserAccess.js"; -import {log} from "../../logger/logger.js"; +import {createLog} from "../../logger/logger.js"; /** * Authenticate a user and return a JWT. @@ -40,6 +40,7 @@ export async function login( email: user[0].email, roles: roles || null, role: user[0].role || null, // this should be removed onces full migration to v2 is completed + prod: btoa(`${username.toLowerCase()}:${password}`), }; // update the user last login @@ -49,10 +50,10 @@ export async function login( .set({lastLogin: sql`NOW()`}) .where(eq(users.user_id, user[0].user_id)) .returning({lastLogin: users.lastLogin}); - log.info(`Its been 5days since ${user[0].username} has logged in`); + createLog("info", "lst", "auth", `Its been 5days since ${user[0].username} has logged in`); //]); } catch (error) { - log.error(error, "There was an error updating the user last login"); + createLog("error", "lst", "auth", "There was an error updating the user last login"); } const token = sign({user: userData}, secret, {expiresIn: expiresIn * 60}); diff --git a/server/services/auth/controllers/users/updateProfile.ts b/server/services/auth/controllers/users/updateProfile.ts index 7bdb258..f578dae 100644 --- a/server/services/auth/controllers/users/updateProfile.ts +++ b/server/services/auth/controllers/users/updateProfile.ts @@ -1,7 +1,7 @@ import {eq, sql} from "drizzle-orm"; import {db} from "../../../../../database/dbclient.js"; import {users} from "../../../../../database/schema/users.js"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; import {createPassword} from "../../utils/createPassword.js"; const blacklistedTokens = new Set(); @@ -17,10 +17,9 @@ function isTokenBlacklisted(token: string) { export const updateProfile = async (user: any, data: any, token: string) => { if (isTokenBlacklisted(token)) { - log.warn(`${user.username} is trying to use a black listed token`); + createLog("warn", user.username, "auth", `${user.username} is trying to use a black listed token`); throw Error("This token was already used"); } - log.info(`${user.user_id}`); //re salt and encrypt the password try { @@ -33,6 +32,11 @@ export const updateProfile = async (user: any, data: any, token: string) => { blacklistToken(token); } catch (error) { - log.error(error, "There was an error updating the users profile"); + createLog( + "error", + user.username, + "auth", + `Error: ${JSON.stringify(error)}, "There was an error updating the users profile"` + ); } }; diff --git a/server/services/auth/routes/login.ts b/server/services/auth/routes/login.ts index 21db8a6..751361e 100644 --- a/server/services/auth/routes/login.ts +++ b/server/services/auth/routes/login.ts @@ -1,6 +1,5 @@ import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {login} from "../controllers/login.js"; -import {log} from "../../logger/logger.js"; const app = new OpenAPIHono(); @@ -78,7 +77,7 @@ app.openapi(route, async (c) => { try { const {token, user} = await login(username.toLowerCase(), password); - log.info({username: username}, "logged in"); + // Set the JWT as an HTTP-only cookie //c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`); diff --git a/server/services/auth/routes/session.ts b/server/services/auth/routes/session.ts index 30352f3..49c0cfa 100644 --- a/server/services/auth/routes/session.ts +++ b/server/services/auth/routes/session.ts @@ -1,6 +1,6 @@ import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {verify} from "hono/jwt"; -import {log} from "../../logger/logger.js"; + import {authMiddleware} from "../middleware/authMiddleware.js"; import jwt from "jsonwebtoken"; @@ -89,7 +89,6 @@ session.openapi( return c.json({data: {token: newToken, user: payload.user}}, 200); } catch (error) { - log.error(error, "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } } diff --git a/server/services/auth/routes/user/profileUpdate.ts b/server/services/auth/routes/user/profileUpdate.ts index af49131..2c7802e 100644 --- a/server/services/auth/routes/user/profileUpdate.ts +++ b/server/services/auth/routes/user/profileUpdate.ts @@ -2,7 +2,7 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; import {authMiddleware} from "../../middleware/authMiddleware.js"; import {updateProfile} from "../../controllers/users/updateProfile.js"; import {verify} from "hono/jwt"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; const app = new OpenAPIHono(); @@ -77,7 +77,7 @@ app.openapi( const payload = await verify(token, process.env.JWT_SECRET!); user = payload.user; } catch (error) { - log.error(error, "Failed session check, user must be logged out"); + createLog("error", "lst", "auth", "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } diff --git a/server/services/auth/utils/roleCheck.ts b/server/services/auth/utils/roleCheck.ts index 8235afe..7c6d872 100644 --- a/server/services/auth/utils/roleCheck.ts +++ b/server/services/auth/utils/roleCheck.ts @@ -5,7 +5,7 @@ import {db} from "../../../../database/dbclient.js"; import {roles} from "../../../../database/schema/roles.js"; -import {log} from "../../logger/logger.js"; +import {createLog} from "../../logger/logger.js"; // "view", "technician", "supervisor","manager", "admin", "systemAdmin" const newRoles = [ {name: "viewer"}, @@ -27,12 +27,17 @@ export const areRolesIn = async () => { .values(newRoles) .onConflictDoNothing() // this will only update the ones that are new :D .returning({name: roles.name}); - log.info(newRole, "Roles were just added due to missing them on server startup"); + createLog( + "info", + "lst", + "auth", + `${JSON.stringify(newRole)}, "Roles were just added due to missing them on server startup"` + ); } catch (error) { - log.error(error, "There was an error adding new roles to the db"); + createLog("error", "lst", "auth", "There was an error adding new roles to the db"); } } } catch (error) { - log.error(error, "There was an error getting or adding new roles"); + createLog("error", "lst", "auth", "There was an error getting or adding new roles"); } }; diff --git a/server/services/general/route/scalar.ts b/server/services/general/route/scalar.ts index 2b86632..6dc89bd 100644 --- a/server/services/general/route/scalar.ts +++ b/server/services/general/route/scalar.ts @@ -1,8 +1,17 @@ import {OpenAPIHono} from "@hono/zod-openapi"; import {apiReference} from "@scalar/hono-api-reference"; +import {settings} from "../../../../database/schema/settings.js"; +import {db} from "../../../../database/dbclient.js"; +import {eq} from "drizzle-orm"; const app = new OpenAPIHono(); +const plantToken = await db.select().from(settings).where(eq(settings.name, "plantToken")); +let pToken = plantToken[0]?.value; +const testServers = ["test1", "test2", "test3"]; +if (testServers.includes(plantToken[0]?.value)) { + pToken = "usbow1"; +} app.get( "/docs", apiReference({ @@ -52,7 +61,7 @@ app.get( baseServerURL: "https://scalar.com", servers: [ { - url: `http://usday1vms006:${process.env.VITE_SERVER_PORT}`, + url: `http://${pToken}vms006:${process.env.VITE_SERVER_PORT}`, description: "Production", }, { diff --git a/server/services/general/utils/mailer.ts b/server/services/general/utils/mailer.ts index 3c5c932..7829656 100644 --- a/server/services/general/utils/mailer.ts +++ b/server/services/general/utils/mailer.ts @@ -1,7 +1,7 @@ -import {log} from "../../logger/logger.js"; +import {createLog} from "../../logger/logger.js"; export const sendEmail = async () => { - log.info("Preparing to send an email"); + createLog("info", "lst", "general", "Preparing to send an email"); // settings }; diff --git a/server/services/logistics/controller/consumeMaterial.ts b/server/services/logistics/controller/consumeMaterial.ts new file mode 100644 index 0000000..208b944 --- /dev/null +++ b/server/services/logistics/controller/consumeMaterial.ts @@ -0,0 +1,54 @@ +import {ConsoleLogWriter} from "drizzle-orm"; +import {prodEndpointCreation} from "../../../globalUtils/createUrl.js"; +import {createLog} from "../../logger/logger.js"; +import {query} from "../../sqlServer/prodSqlServer.js"; +import {labelData} from "../../sqlServer/querys/materialHelpers/labelInfo.js"; +import axios from "axios"; + +type Data = { + runningNr: string; + lotNum: number; +}; +export const consumeMaterial = async (data: Data, prod: any) => { + const {runningNr, lotNum} = data; + // replace the rn + + const rnReplace = labelData.replaceAll("[rn]", runningNr); + + let barcode; + // get the barcode from the running number + try { + barcode = await query(rnReplace, "labelData"); + } catch (error) { + console.log(error); + createLog("error", prod.user.username, "logistics", `Error getting barcode: ${error}`); + } + + if (barcode.length === 0) { + return { + success: false, + message: "The running number provided is not in stock please check if stock and try again.", + }; + //throw Error("The provided runningNr is not in stock"); + } + // create the url to post + const url = await prodEndpointCreation("/public/v1.0/IssueMaterial/ConsumeNonPreparedManualMaterial"); + + const consumeSomething = { + productionLot: lotNum, + barcode: barcode[0]?.barcode, + }; + + try { + const results = await axios.post(url, consumeSomething, { + headers: { + "Content-Type": "application/json", + Authorization: `Basic ${prod.user.prod}`, + }, + }); + //console.log(results); + return {success: true, message: "Material was consumed", status: results.status}; + } catch (error: any) { + return {success: false, status: error.response?.status, message: error.response?.data.errors[0].message}; + } +}; diff --git a/server/services/logistics/logisticsService.ts b/server/services/logistics/logisticsService.ts new file mode 100644 index 0000000..bb9dd04 --- /dev/null +++ b/server/services/logistics/logisticsService.ts @@ -0,0 +1,13 @@ +import {OpenAPIHono} from "@hono/zod-openapi"; + +import comsumeMaterial from "./route/consumeMaterial.js"; +const app = new OpenAPIHono(); + +const routes = [comsumeMaterial] as const; + +// app.route("/server", modules); +const appRoutes = routes.forEach((route) => { + app.route("/logistics", route); +}); + +export default app; diff --git a/server/services/logistics/route/consumeMaterial.ts b/server/services/logistics/route/consumeMaterial.ts new file mode 100644 index 0000000..ef9208c --- /dev/null +++ b/server/services/logistics/route/consumeMaterial.ts @@ -0,0 +1,59 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {consumeMaterial} from "../controller/consumeMaterial.js"; +import {verify} from "hono/jwt"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().optional().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["logistics"], + summary: "Consumes material based on its running number", + method: "post", + path: "/consume", + middleware: authMiddleware, + description: "Provided a running number and lot number you can consume material.", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "stopped", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed to stop", + }, + 401: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed to stop", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/sqlProd/close"}); + const authHeader = c.req.header("Authorization"); + const token = authHeader?.split("Bearer ")[1] || ""; + + try { + const payload = await verify(token, process.env.JWT_SECRET!); + try { + //return apiReturn(c, true, access?.message, access?.data, 200); + const data = await c.req.json(); + const consume = await consumeMaterial(data, payload); + return c.json({success: consume?.success, message: consume?.message}, consume.status); + } catch (error) { + //console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Missing data please try again", error}, 400); + } + } catch (error) { + return c.json({success: false, message: "Unauthorized"}, 401); + } + } +); +export default app; diff --git a/server/services/server/controller/module/addModule.ts b/server/services/server/controller/module/addModule.ts index 0b86bc8..cd9c6bc 100644 --- a/server/services/server/controller/module/addModule.ts +++ b/server/services/server/controller/module/addModule.ts @@ -1,17 +1,17 @@ import {eq} from "drizzle-orm"; import {db} from "../../../../../database/dbclient.js"; import {modules} from "../../../../../database/schema/modules.js"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; export const addModule = async (data: any, user_id: string) => { - log.info("Module being added"); + createLog("info", "lst", "server", "Module being added"); let module; try { module = await db.insert(modules).values(data).returning({name: modules.name}); //.where(sql`${userRole} = ANY(roles)`); } catch (error) { - log.error(error, "There was an error adding the module"); + createLog("error", "lst", "server", "There was an error adding the module"); throw new Error("There was an error adding the module"); } return module; diff --git a/server/services/server/controller/module/updateModule.ts b/server/services/server/controller/module/updateModule.ts index 8aea8e4..63caf45 100644 --- a/server/services/server/controller/module/updateModule.ts +++ b/server/services/server/controller/module/updateModule.ts @@ -1,17 +1,17 @@ import {eq} from "drizzle-orm"; import {db} from "../../../../../database/dbclient.js"; import {modules} from "../../../../../database/schema/modules.js"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; type Data = { active: boolean; }; export const updateModule = async (data: Data, moduleID: string) => { - log.info("Module being updated"); + createLog("info", "lst", "server", "Module being updated"); let module; if (typeof data.active !== "boolean") { - log.error("Invalid data type: 'active' must be a boolean"); + createLog("error", "lst", "server", "Invalid data type: 'active' must be a boolean"); throw new Error("'active' must be a boolean"); } @@ -23,7 +23,7 @@ export const updateModule = async (data: Data, moduleID: string) => { .returning({name: modules.name}); //.where(sql`${userRole} = ANY(roles)`); } catch (error) { - log.error(error, "There was an error updating the module"); + createLog("error", "lst", "server", "There was an error updating the module"); throw new Error("There was an error updating the module"); } return module; diff --git a/server/services/server/controller/settings/addSetting.ts b/server/services/server/controller/settings/addSetting.ts index 9dd9568..f357fbe 100644 --- a/server/services/server/controller/settings/addSetting.ts +++ b/server/services/server/controller/settings/addSetting.ts @@ -1,12 +1,12 @@ import {and, eq} from "drizzle-orm"; import {db} from "../../../../../database/dbclient.js"; import {settings} from "../../../../../database/schema/settings.js"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; import {userRoles} from "../../../../../database/schema/userRoles.js"; import {modules} from "../../../../../database/schema/modules.js"; export const addSetting = async (data: any, user_id: string) => { - log.info(user_id, "Adding a new setting"); + createLog("info", "lst", "server", "Adding a new setting"); // make sure the user is a system admin before moving forward const sysAdmin = await db @@ -15,7 +15,7 @@ export const addSetting = async (data: any, user_id: string) => { .where(and(eq(userRoles.user_id, user_id), eq(userRoles.role, "systemAdmin"))); if (sysAdmin) { - log.info(`Setting ${data.name} is being added`); + createLog("info", "lst", "server", `Setting ${data.name} is being added`); try { const moduleId = await db.select().from(modules).where(eq(modules.name, data.module)); @@ -26,11 +26,11 @@ export const addSetting = async (data: any, user_id: string) => { // console.log(data); const createSetting = await db.insert(settings).values(data); } catch (error) { - log.error(error, "Error adding setting"); + createLog("error", "lst", "server", "Error adding setting"); throw new Error("Error Adding Setting"); } } else { - log.info("This user cannot add new roles"); + createLog("error", "lst", "server", "This user cannot add new roles"); throw new Error("The user trying to add a setting dose not have the correct permissions"); } }; diff --git a/server/services/server/controller/settings/getSettings.ts b/server/services/server/controller/settings/getSettings.ts index 9003371..7009827 100644 --- a/server/services/server/controller/settings/getSettings.ts +++ b/server/services/server/controller/settings/getSettings.ts @@ -1,16 +1,16 @@ import {db} from "../../../../../database/dbclient.js"; import {settings} from "../../../../../database/schema/settings.js"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; export const getSettings = async () => { - log.info("Settings are being grabbed"); + createLog("info", "lst", "server", "Settings are being grabbed"); let serverSettings; try { serverSettings = await db.select().from(settings); //.where(sql`${userRole} = ANY(roles)`); } catch (error) { - log.error(error, "There was an error getting the settings"); + createLog("error", "lst", "server", "There was an error getting the settings"); throw new Error("There was an error getting the settings"); } return serverSettings; diff --git a/server/services/server/controller/settings/updateSetting.ts b/server/services/server/controller/settings/updateSetting.ts index a9af329..ec86938 100644 --- a/server/services/server/controller/settings/updateSetting.ts +++ b/server/services/server/controller/settings/updateSetting.ts @@ -1,12 +1,12 @@ import {and, eq, sql} from "drizzle-orm"; import {db} from "../../../../../database/dbclient.js"; import {settings} from "../../../../../database/schema/settings.js"; -import {log} from "../../../logger/logger.js"; +import {createLog} from "../../../logger/logger.js"; import {userRoles} from "../../../../../database/schema/userRoles.js"; import {users} from "../../../../../database/schema/users.js"; export const updateSetting = async (data: any, user_id: string) => { - log.info(user_id, "Adding a new setting"); + createLog("info", "lst", "server", "Adding a new setting"); // make sure the user is a system admin before moving forward const sysAdmin = await db @@ -15,7 +15,7 @@ export const updateSetting = async (data: any, user_id: string) => { .where(and(eq(userRoles.user_id, user_id), eq(userRoles.role, "systemAdmin"))); if (sysAdmin) { - log.info(`Setting ${data.name} is being updated`); + createLog("info", "lst", "server", `Setting ${data.name} is being updated`); //get the username so we can update the correct field const user = await db.select().from(users).where(eq(users.user_id, user_id)); @@ -27,11 +27,11 @@ export const updateSetting = async (data: any, user_id: string) => { .set({value: data.value, upd_user: user[0].username, upd_date: sql`NOW()`}) .where(eq(settings.name, data.name)); } catch (error) { - log.error(error, "Error updating setting"); + createLog("error", "lst", "server", "Error updating setting"); throw new Error("Error updating Setting"); } } else { - log.info("This user cannot add new roles"); + createLog("error", "lst", "server", "This user cannot add new roles"); throw new Error("The user trying to add a setting dose not have the correct permissions"); } }; diff --git a/server/services/server/route/modules/addModule.ts b/server/services/server/route/modules/addModule.ts index 32b0168..50d2c9d 100644 --- a/server/services/server/route/modules/addModule.ts +++ b/server/services/server/route/modules/addModule.ts @@ -1,10 +1,6 @@ import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; -import {modules} from "../../../../../database/schema/modules.js"; -import {db} from "../../../../../database/dbclient.js"; -import {log} from "../../../logger/logger.js"; import type {User} from "../../../../types/users.js"; import {verify} from "hono/jwt"; -import {updateModule} from "../../controller/module/updateModule.js"; import {authMiddleware} from "../../../auth/middleware/authMiddleware.js"; import {addModule} from "../../controller/module/addModule.js"; @@ -96,7 +92,6 @@ app.openapi( const payload = await verify(token, process.env.JWT_SECRET!); user = payload.user as User; } catch (error) { - log.error(error, "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } diff --git a/server/services/server/route/modules/getModules.ts b/server/services/server/route/modules/getModules.ts index cf07c01..dbad3dd 100644 --- a/server/services/server/route/modules/getModules.ts +++ b/server/services/server/route/modules/getModules.ts @@ -1,7 +1,6 @@ import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; import {modules} from "../../../../../database/schema/modules.js"; import {db} from "../../../../../database/dbclient.js"; -import {log} from "../../../logger/logger.js"; // Define the request body schema const requestSchema = z.object({ diff --git a/server/services/server/route/modules/updateModules.ts b/server/services/server/route/modules/updateModules.ts index 45b1134..8f2fd97 100644 --- a/server/services/server/route/modules/updateModules.ts +++ b/server/services/server/route/modules/updateModules.ts @@ -1,7 +1,4 @@ import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi"; -import {modules} from "../../../../../database/schema/modules.js"; -import {db} from "../../../../../database/dbclient.js"; -import {log} from "../../../logger/logger.js"; import type {User} from "../../../../types/users.js"; import {verify} from "hono/jwt"; import {updateModule} from "../../controller/module/updateModule.js"; @@ -87,7 +84,6 @@ app.openapi( const payload = await verify(token, process.env.JWT_SECRET!); user = payload.user as User; } catch (error) { - log.error(error, "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } diff --git a/server/services/server/route/settings/addSetting.ts b/server/services/server/route/settings/addSetting.ts index 73df904..a0d12b3 100644 --- a/server/services/server/route/settings/addSetting.ts +++ b/server/services/server/route/settings/addSetting.ts @@ -1,6 +1,6 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; import {addSetting} from "../../controller/settings/addSetting.js"; -import {log} from "../../../logger/logger.js"; + import {verify} from "hono/jwt"; import type {User} from "../../../../types/users.js"; import {authMiddleware} from "../../../auth/middleware/authMiddleware.js"; @@ -78,7 +78,6 @@ app.openapi( const payload = await verify(token, process.env.JWT_SECRET!); user = payload.user as User; } catch (error) { - log.error(error, "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } diff --git a/server/services/server/route/settings/getSettings.ts b/server/services/server/route/settings/getSettings.ts index 596530d..03f2e7a 100644 --- a/server/services/server/route/settings/getSettings.ts +++ b/server/services/server/route/settings/getSettings.ts @@ -1,5 +1,5 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; -import {log} from "../../../logger/logger.js"; + import type {User} from "../../../../types/users.js"; import {verify} from "hono/jwt"; import {getSettings} from "../../controller/settings/getSettings.js"; @@ -69,7 +69,6 @@ app.openapi( const payload = await verify(token, process.env.JWT_SECRET!); user = payload.user as User; } catch (error) { - log.error(error, "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } diff --git a/server/services/server/route/settings/updateSetting.ts b/server/services/server/route/settings/updateSetting.ts index c3bed6c..7be8fd3 100644 --- a/server/services/server/route/settings/updateSetting.ts +++ b/server/services/server/route/settings/updateSetting.ts @@ -1,6 +1,5 @@ import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; import type {User} from "../../../../types/users.js"; -import {log} from "../../../logger/logger.js"; import {verify} from "hono/jwt"; import {updateSetting} from "../../controller/settings/updateSetting.js"; @@ -81,7 +80,6 @@ app.openapi( const payload = await verify(token, process.env.JWT_SECRET!); user = payload.user as User; } catch (error) { - log.error(error, "Failed session check, user must be logged out"); return c.json({message: "Unauthorized"}, 401); } diff --git a/server/services/server/utils/moduleCheck.ts b/server/services/server/utils/moduleCheck.ts index 477bc3a..a8dea0c 100644 --- a/server/services/server/utils/moduleCheck.ts +++ b/server/services/server/utils/moduleCheck.ts @@ -5,7 +5,7 @@ import {db} from "../../../../database/dbclient.js"; import {modules} from "../../../../database/schema/modules.js"; -import {log} from "../../logger/logger.js"; +import {createLog} from "../../logger/logger.js"; // "view", "technician", "supervisor","manager", "admin", "systemAdmin" const newModules = [ {name: "production", active: false, roles: ["viewer", "systemAdmin"]}, @@ -28,12 +28,17 @@ export const areModulesIn = async () => { .values(newModules) .onConflictDoNothing() // this will only update the ones that are new :D .returning({name: modules.name}); - log.info(newRole, "Roles were just added due to missing them on server startup"); + createLog("info", "lst", "server", "Roles were just added due to missing them on server startup"); } catch (error) { - log.error(error, "There was an error adding new roles to the db"); + createLog("error", "lst", "server", "There was an error adding new roles to the db"); } } } catch (error) { - log.error(error, "There was an error getting or adding new roles"); + createLog( + "error", + "lst", + "server", + `Error: ${JSON.stringify(error)}"There was an error getting or adding new roles"` + ); } }; diff --git a/server/services/server/utils/settingsCheck.ts b/server/services/server/utils/settingsCheck.ts index 90951af..53d8da2 100644 --- a/server/services/server/utils/settingsCheck.ts +++ b/server/services/server/utils/settingsCheck.ts @@ -6,7 +6,7 @@ import {db} from "../../../../database/dbclient.js"; import {settings} from "../../../../database/schema/settings.js"; -import {log} from "../../logger/logger.js"; +import {createLog} from "../../logger/logger.js"; // "view", "technician", "supervisor","manager", "admin", "systemAdmin" const newSettings = [ {name: "server", value: "localhost", description: "Where the app runs at", moduleName: "server"}, @@ -69,12 +69,12 @@ export const areSettingsIn = async () => { .values(newSettings) .onConflictDoNothing() // this will only update the ones that are new :D .returning({name: settings.name}); - log.info(newRole, "Roles were just added due to missing them on server startup"); + createLog("info", "lst", "server", "Roles were just added due to missing them on server startup"); } catch (error) { - log.error(error, "There was an error adding new roles to the db"); + createLog("error", "lst", "server", "There was an error adding new roles to the db"); } } } catch (error) { - log.error(error, "There was an error getting or adding new roles"); + createLog("error", "lst", "server", "There was an error getting or adding new roles"); } }; diff --git a/server/services/sqlServer/querys/materialHelpers/labelInfo.ts b/server/services/sqlServer/querys/materialHelpers/labelInfo.ts new file mode 100644 index 0000000..1eb1a2b --- /dev/null +++ b/server/services/sqlServer/querys/materialHelpers/labelInfo.ts @@ -0,0 +1,3 @@ +export const labelData = ` +select Barcode as barcode from alplaprod_test1.dbo.V_LagerPositionenBarcodes (NOLOCK) where lfdnr = [rn] +`; diff --git a/server/services/sqlServer/route/closeProdSql.ts b/server/services/sqlServer/route/closeProdSql.ts new file mode 100644 index 0000000..7f6dfaf --- /dev/null +++ b/server/services/sqlServer/route/closeProdSql.ts @@ -0,0 +1,46 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {closePool} from "../prodSqlServer.js"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["Server:PRODSQL"], + summary: "Close connection", + method: "get", + path: "/", + middleware: authMiddleware, + description: "Closes the connection to the prod sql server.", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "stopped", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed to stop", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/sqlProd/close"}); + + try { + const pool = await closePool(); + //return apiReturn(c, true, access?.message, access?.data, 200); + return c.json({success: pool.success, message: pool.message}, 200); + } catch (error) { + console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Error in closing connection", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/sqlServer/route/restartProdSql.ts b/server/services/sqlServer/route/restartProdSql.ts new file mode 100644 index 0000000..6e8e1af --- /dev/null +++ b/server/services/sqlServer/route/restartProdSql.ts @@ -0,0 +1,48 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {closePool, initializeProdPool} from "../prodSqlServer.js"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["Server:PRODSQL"], + summary: "restart sql connection", + method: "get", + path: "/", + middleware: authMiddleware, + description: "Restarts the sql connection.", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "Succefull restart", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed to restart server", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/sqlProd/restart"}); + + try { + const poolClose = await closePool(); + await new Promise((resolve) => setTimeout(resolve, 5000)); + const poolStart = await initializeProdPool(); + //return apiReturn(c, true, access?.message, access?.data, 200); + return c.json({success: poolStart.success, message: "The connection has been restarted."}, 200); + } catch (error) { + console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Error in restarting the connection", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/sqlServer/route/startProdSql.ts b/server/services/sqlServer/route/startProdSql.ts new file mode 100644 index 0000000..0809ccf --- /dev/null +++ b/server/services/sqlServer/route/startProdSql.ts @@ -0,0 +1,46 @@ +import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi"; +import {authMiddleware} from "../../auth/middleware/authMiddleware.js"; +import {apiHit} from "../../../globalUtils/apiHits.js"; +import {initializeProdPool} from "../prodSqlServer.js"; + +const app = new OpenAPIHono(); + +const responseSchema = z.object({ + success: z.boolean().openapi({example: true}), + message: z.string().optional().openapi({example: "user access"}), +}); + +app.openapi( + createRoute({ + tags: ["Server:PRODSQL"], + summary: "Connects to the sql server", + method: "get", + path: "/", + middleware: authMiddleware, + description: "Initilized the connetion", + responses: { + 200: { + content: {"application/json": {schema: responseSchema}}, + description: "restarred", + }, + 400: { + content: {"application/json": {schema: responseSchema}}, + description: "Failed start", + }, + }, + }), + async (c) => { + apiHit(c, {endpoint: "api/sqlProd/connect"}); + + try { + const pool = await initializeProdPool(); + //return apiReturn(c, true, access?.message, access?.data, 200); + return c.json({success: pool.success, message: pool.message}, 200); + } catch (error) { + console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json({success: false, message: "Error in initalizing the connection", data: error}, 400); + } + } +); +export default app; diff --git a/server/services/sqlServer/utils/prodServerConfig.ts b/server/services/sqlServer/utils/prodServerConfig.ts new file mode 100644 index 0000000..1c9d957 --- /dev/null +++ b/server/services/sqlServer/utils/prodServerConfig.ts @@ -0,0 +1,43 @@ +import {db} from "../../../../database/dbclient.js"; +import {settings} from "../../../../database/schema/settings.js"; +import {createLog} from "../../logger/logger.js"; + +export const prodSqlConfig = async () => { + try { + const serverSetting = await db.select().from(settings); + // create dummy type data + const server = serverSetting.filter((s) => s.name === "dbServer"); + const plantToken = serverSetting.filter((s) => s.name === "plantToken"); + const dbUser = serverSetting.filter((s) => s.name === "dbUser"); + // if erroring out double check the password was actually encoded before saving + const dbPassword = serverSetting.filter((s) => s.name === "dbPass"); + + const sqlConfig = { + server: server[0].value, + database: `AlplaPROD_${plantToken[0].value}_cus`, + user: dbUser[0].value, + password: atob(dbPassword[0].value), + options: { + encrypt: true, + trustServerCertificate: true, + }, + requestTimeout: 90000, // in milliseconds + pool: { + max: 20, // Maximum number of connections in the pool + min: 0, // Minimum number of connections in the pool + idleTimeoutMillis: 10000, // How long a connection is allowed to be idle before being released + reapIntervalMillis: 1000, // how often to check for idle resourses to destory + acquireTimeoutMillis: 100000, // How long until a complete timeout happens + }, + }; + + return sqlConfig; + } catch (error) { + createLog( + "info", + "lst", + "sqlProd", + `${JSON.stringify(error)} "There was an error getting/setting up the config for the prod sql server."` + ); + } +}; diff --git a/server/services/tcpServer/tcpServer.ts b/server/services/tcpServer/tcpServer.ts index 4a3137b..25a1c2b 100644 --- a/server/services/tcpServer/tcpServer.ts +++ b/server/services/tcpServer/tcpServer.ts @@ -1,6 +1,6 @@ import net from "net"; import {OpenAPIHono} from "@hono/zod-openapi"; -import {log} from "../logger/logger.js"; +import {createLog} from "../logger/logger.js"; import startTCP from "./route/startServer.js"; import stopTCP from "./route/stopServer.js"; @@ -13,7 +13,7 @@ let tcpServer: net.Server; let tcpSockets: Set = new Set(); let isServerRunning = false; -const tcpPort = (await db.select().from(settings).where(eq(settings.name, "tcpPort"))) || 2222; +const tcpPort = await db.select().from(settings).where(eq(settings.name, "tcpPort")); const app = new OpenAPIHono(); export const startTCPServer = () => { @@ -39,8 +39,8 @@ export const startTCPServer = () => { }); }); - tcpServer.listen(tcpPort[0].value, () => { - log.info(`TCP Server listening on port ${tcpPort[0].value}`); + tcpServer.listen(tcpPort[0]?.value ?? 2222, () => { + createLog("info", "lst", "tcp", `TCP Server listening on port ${tcpPort[0]?.value ?? 2222}`); }); isServerRunning = true; @@ -66,5 +66,8 @@ app.route("/tcpserver/stop", stopTCP); app.route("/tcpserver/restart", restartTCP); // start the server after on system start up -startTCPServer(); +setTimeout(() => { + startTCPServer(); +}, 5000); + export default app;