feat(server): settings and module crud added in

This commit is contained in:
2025-03-04 16:43:45 -06:00
parent 5b9cadb76e
commit 2ad1dcc55b
19 changed files with 701 additions and 14 deletions

View File

@@ -7,18 +7,22 @@ import session from "./routes/session.js";
import getAccess from "./routes/userRoles/getUserRoles.js";
import setAccess from "./routes/userRoles/setUserRoles.js";
import profile from "./routes/user/profileUpdate.js";
import {areRolesIn} from "./utils/roleCheck.js";
const app = new OpenAPIHono();
// run the role check
areRolesIn();
app.route("auth/login", login);
app.route("auth/register", register);
app.route("auth/session", session);
// required to login
/* User area just needs to be logged in to enter here */
app.route("/auth/profileUpdate", profile);
app.route("auth/profileUpdate", profile);
/* will need to increase to make sure the person coming here has the correct permissions */
app.route("/auth/getuseraccess", getAccess);
app.route("/auth/setuseraccess", setAccess);
app.route("auth/getuseraccess", getAccess);
app.route("auth/setuseraccess", setAccess);
export default app;

View File

@@ -12,7 +12,15 @@ export const roleCheck = async (user_id: string | undefined) => {
throw Error("Missing user_id");
}
// get the user roles by the user_id
const roles = await db.select().from(userRoles).where(eq(userRoles.user_id, user_id));
const roles = await db
.select({
user_id: userRoles.user_id,
role_id: userRoles.role_id,
module_id: userRoles.module_id,
role: userRoles.role,
})
.from(userRoles)
.where(eq(userRoles.user_id, user_id));
return roles;
};

View File

@@ -0,0 +1,38 @@
/**
* check if the roles are in and if not add them.
* this will only run on a server start up
*/
import {db} from "../../../../database/dbclient.js";
import {roles} from "../../../../database/schema/roles.js";
import {log} from "../../logger/logger.js";
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
const newRoles = [
{name: "viewer"},
{name: "technician"},
{name: "supervisor"},
{name: "manager"},
{name: "admin"},
{name: "systemAdmin"},
];
export const areRolesIn = async () => {
// get the roles
try {
const roleCheck = await db.select().from(roles);
if (roleCheck.length !== newRoles.length) {
try {
const newRole = await db
.insert(roles)
.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");
} catch (error) {
log.error(error, "There was an error adding new roles to the db");
}
}
} catch (error) {
log.error(error, "There was an error getting or adding new roles");
}
};

View File

@@ -0,0 +1,7 @@
import {log} from "../../logger/logger.js";
export const sendEmail = async () => {
log.info("Preparing to send an email");
// settings
};

View File

@@ -0,0 +1,18 @@
import {eq} from "drizzle-orm";
import {db} from "../../../../../database/dbclient.js";
import {modules} from "../../../../../database/schema/modules.js";
import {log} from "../../../logger/logger.js";
export const addModule = async (data: any, user_id: string) => {
log.info("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");
throw new Error("There was an error adding the module");
}
return module;
};

View File

@@ -0,0 +1,22 @@
import {eq} from "drizzle-orm";
import {db} from "../../../../../database/dbclient.js";
import {modules} from "../../../../../database/schema/modules.js";
import {log} from "../../../logger/logger.js";
export const updateModule = async (data: any, moduleID: string) => {
log.info("Module being updated");
let module;
try {
module = await db
.update(modules)
.set({active: data?.active})
.where(eq(modules.module_id, moduleID))
.returning({name: modules.name});
//.where(sql`${userRole} = ANY(roles)`);
} catch (error) {
log.error(error, "There was an error updating the module");
throw new Error("There was an error updating the module");
}
return module;
};

View File

@@ -0,0 +1,36 @@
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 {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");
// make sure the user is a system admin before moving forward
const sysAdmin = await db
.select()
.from(userRoles)
.where(and(eq(userRoles.user_id, user_id), eq(userRoles.role, "systemAdmin")));
if (sysAdmin) {
log.info(`Setting ${data.name} is being added`);
try {
const moduleId = await db.select().from(modules).where(eq(modules.name, data.module));
// filter out the module and add in the module id
delete data.module;
data.module_id = moduleId[0].module_id;
console.log(data);
const createSetting = await db.insert(settings).values(data);
} catch (error) {
log.error(error, "Error adding setting");
throw new Error("Error Adding Setting");
}
} else {
log.info("This user cannot add new roles");
throw new Error("The user trying to add a setting dose not have the correct permissions");
}
};

View File

@@ -0,0 +1,17 @@
import {db} from "../../../../../database/dbclient.js";
import {settings} from "../../../../../database/schema/settings.js";
import {log} from "../../../logger/logger.js";
export const getSettings = async () => {
log.info("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");
throw new Error("There was an error getting the settings");
}
return serverSettings;
};

View File

@@ -0,0 +1,114 @@
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";
// 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();
// const ParamsSchema = z.object({
// id: z
// .string()
// .min(3)
// .openapi({
// param: {
// name: "id",
// in: "path",
// },
// example: "1212121",
// }),
// });
const AddModule = z.object({
name: z.string().openapi({example: "production"}),
});
app.openapi(
createRoute({
tags: ["server"],
summary: "Adds a new module",
method: "post",
path: "/modules",
middleware: authMiddleware,
request: {
body: {
content: {
"application/json": {schema: AddModule},
},
},
},
responses: {
200: {
content: {
"application/json": {schema: responseSchema},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
401: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
},
},
description: "Unauthorized",
},
500: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
},
}),
async (c) => {
//const {id} = c.req.valid("param");
// make sure we have a vaid user being accessed thats really logged in
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
let user: User;
try {
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);
}
// now pass all the data over to update the user info
try {
const data = await c?.req.json();
await addModule(data, user.user_id ?? "");
return c.json({success: true, message: "New setting was added"}, 200);
} catch (error) {
return c.json({message: "Please make sure you are not missing your data.", error}, 400);
}
}
);
export default app;

View File

@@ -1,7 +1,7 @@
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
import {modules} from "../../../../database/schema/modules.js";
import {db} from "../../../../database/dbclient.js";
import {eq} from "drizzle-orm";
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({
@@ -27,7 +27,7 @@ app.openapi(
tags: ["server"],
summary: "Returns all modules in the server",
method: "get",
path: "/",
path: "/modules",
responses: {
200: {
content: {
@@ -41,7 +41,7 @@ app.openapi(
//console.log("system modules");
let module: any = [];
try {
module = await db.select().from(modules).where(eq(modules.active, true));
module = await db.select().from(modules); // .where(eq(modules.active, true));
} catch (error) {
console.log(error);
module = [];
@@ -50,15 +50,16 @@ app.openapi(
// parse the roles
const updateModules = module.map((m: any) => {
if (m.roles) {
return {...m, roles: JSON.parse(m?.roles)};
return {...m, roles: m?.roles};
}
return m;
}); //JSON.parse(module[0]?.roles);
// Return response with the received data
return c.json({
message: `All active modules`,
data: updateModules,
data: module,
});
}
);

View File

@@ -0,0 +1,110 @@
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";
// 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();
const ParamsSchema = z.object({
id: z
.string()
.min(3)
.openapi({
param: {
name: "id",
in: "path",
},
example: "1212121",
}),
});
app.openapi(
createRoute({
tags: ["server"],
summary: "Updates module",
method: "patch",
path: "/modules/{id}",
middleware: authMiddleware,
request: {
params: ParamsSchema,
},
responses: {
200: {
content: {
"application/json": {schema: responseSchema},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
401: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
},
},
description: "Unauthorized",
},
500: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
},
}),
async (c) => {
const {id} = c.req.valid("param");
// make sure we have a vaid user being accessed thats really logged in
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
let user: User;
try {
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);
}
// now pass all the data over to update the user info
try {
const data = await c?.req.json();
await updateModule(data, id ?? "");
return c.json({success: true, message: "New setting was added"}, 200);
} catch (error) {
return c.json({message: "Please make sure you are not missing your data.", error}, 400);
}
return c.json({
message: `Module has been updated`,
data: id,
});
}
);
export default app;

View File

@@ -0,0 +1,95 @@
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";
const app = new OpenAPIHono();
const AddSetting = z.object({
name: z.string().openapi({example: "server"}),
value: z.string().openapi({example: "localhost"}),
description: z.string().openapi({example: "The server we are going to connect to"}),
roles: z.string().openapi({example: "admin"}),
module: z.string().openapi({example: "production"}),
});
app.openapi(
createRoute({
tags: ["server"],
summary: "Add Setting",
method: "post",
path: "/settings",
middleware: authMiddleware,
request: {
body: {
content: {
"application/json": {schema: AddSetting},
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
401: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
},
},
description: "Unauthorized",
},
500: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
let user: User;
try {
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);
}
// now pass all the data over to update the user info
try {
const data = await c?.req.json();
await addSetting(data, user.user_id ?? "");
return c.json({success: true, message: "New setting was added"}, 200);
} catch (error) {
return c.json({message: "Please make sure you are not missing your data.", error}, 400);
}
}
);
export default app;

View File

@@ -0,0 +1,29 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
const app = new OpenAPIHono();
app.openapi(
createRoute({
tags: ["server"],
summary: "Returns all modules in the server",
method: "delete",
path: "/settings",
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
}),
},
},
description: "Response message",
},
},
}),
async (c) => {
return c.json({success: true, message: "Example"}, 200);
}
);
export default app;

View File

@@ -0,0 +1,85 @@
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";
const app = new OpenAPIHono();
app.openapi(
createRoute({
tags: ["server"],
summary: "Returns all settings based on your permissions",
method: "get",
path: "/settings",
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
401: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
},
},
description: "Unauthorized",
},
500: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
const authHeader = c.req.header("Authorization");
if (authHeader?.includes("Basic")) {
return c.json({message: "You are a Basic user! Please login to get a token"}, 401);
}
if (!authHeader) {
return c.json({message: "Unauthorized"}, 401);
}
const token = authHeader?.split("Bearer ")[1] || "";
let user: User;
try {
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);
}
// now pass all the data over to update the user info
try {
const data = await getSettings();
return c.json({success: true, message: "All Current Settings", data}, 200);
} catch (error) {
return c.json({message: "There was an error getting the settings.", error}, 400);
}
}
);
export default app;

View File

@@ -0,0 +1,29 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
const app = new OpenAPIHono();
app.openapi(
createRoute({
tags: ["server"],
summary: "Returns all modules in the server",
method: "post",
path: "/",
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
}),
},
},
description: "Response message",
},
},
}),
async (c) => {
return c.json({success: true, message: "Example"}, 200);
}
);
export default app;

View File

@@ -1,7 +1,31 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import {areModulesIn} from "./utils/moduleCheck.js";
import modules from "./route/modules.js";
// routes
import getModules from "./route/modules/getModules.js";
import updateModule from "./route/modules/updateModules.js";
import addModule from "./route/modules/addModule.js";
import addSetting from "./route/settings/addSetting.js";
import getSettings from "./route/settings/getSettings.js";
const app = new OpenAPIHono().route("server/modules", modules);
areModulesIn();
const app = new OpenAPIHono();
const routes = [
getModules,
updateModule,
addModule,
// settings
addSetting,
getSettings,
] as const;
// app.route("/server", modules);
const appRoutes = routes.forEach((route) => {
app.route("/server", route);
});
app.all("/server/*", (c) => {
return c.json({success: false, message: "You encountered a route that dose not exist on the server routes"});
});
export default app;

View File

@@ -0,0 +1,38 @@
/**
* check if the modules are in and if not add them.
* this will only run on a server start up
*/
import {db} from "../../../../database/dbclient.js";
import {modules} from "../../../../database/schema/modules.js";
import {log} from "../../logger/logger.js";
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
const newModules = [
{name: "production", active: false, roles: ["viewer", "systemAdmin"]},
{name: "logistics", active: false, roles: ["viewer", "systemAdmin"]},
{name: "quality", active: false, roles: ["viewer", "manager", "systemAdmin"]},
{name: "forklift", active: false, roles: ["manager", "admin", "systemAdmin"]},
{name: "eom", active: false, roles: ["manager", "admin", "systemAdmin"]},
{name: "admin", active: false, roles: ["admin", "systemAdmin"]},
];
export const areModulesIn = async () => {
// get the roles
try {
const moduleCheck = await db.select().from(modules);
if (moduleCheck.length !== newModules.length) {
try {
const newRole = await db
.insert(modules)
.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");
} catch (error) {
log.error(error, "There was an error adding new roles to the db");
}
}
} catch (error) {
log.error(error, "There was an error getting or adding new roles");
}
};

12
server/types/settings.ts Normal file
View File

@@ -0,0 +1,12 @@
export interface Settings {
settings_id?: string | null;
name: string | null;
value: string | null;
description: string | null;
module_id: string | null;
role: string | null;
add_User: string | null;
add_Date: Date;
upd_user: string | null;
upd_date: Date;
}