refactor(old app): login migration to new app

This commit is contained in:
2025-10-21 20:22:21 -05:00
parent a2a8e0ef9f
commit eb3fa4dd52
28 changed files with 2273 additions and 2140 deletions

View File

@@ -1,28 +1,26 @@
import { getUsers } from "@/utils/querys/admin/users";
import { useQuery } from "@tanstack/react-query";
import UserCard from "./components/UserCard";
export default function UserPage() { export default function UserPage() {
const { data, isError, error, isLoading } = useQuery(getUsers()); //const { data, isError, error, isLoading } = useQuery(getUsers());
if (isLoading) return <div className="m-auto">Loading users...</div>; // if (isLoading) return <div className="m-auto">Loading users...</div>;
if (isError) // if (isError)
return ( // return (
<div className="m-auto"> // <div className="m-auto">
There was an error getting the users.... {JSON.stringify(error)} // There was an error getting the users.... {JSON.stringify(error)}
</div> // </div>
); // );
return ( return (
<div className="m-2 w-dvw"> <div className="m-2 w-dvw">
{data.map((u: any) => { <span>This has been moved to the new system</span>
{/* {data.map((u: any) => {
return ( return (
<div> <div>
<UserCard user={u} /> <UserCard user={u} />
</div> </div>
); );
})} })} */}
</div> </div>
); );
} }

View File

@@ -1,15 +1,16 @@
import { useSessionStore } from "../../lib/store/sessionStore"; import { zodResolver } from "@hookform/resolvers/zod";
import { LstCard } from "../extendedUI/LstCard";
import { CardHeader } from "../ui/card";
import { toast } from "sonner";
import { z } from "zod";
import { useRouter, useSearch } from "@tanstack/react-router"; import { useRouter, useSearch } from "@tanstack/react-router";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod"; import { toast } from "sonner";
import { Label } from "../ui/label"; import { z } from "zod";
import { Input } from "../ui/input"; import { useAuthStore } from "@/lib/store/useAuthStore";
import { Checkbox } from "../ui/checkbox"; import { useSessionStore } from "../../lib/store/sessionStore";
import { LstCard } from "../extendedUI/LstCard";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { CardHeader } from "../ui/card";
import { Checkbox } from "../ui/checkbox";
import { Input } from "../ui/input";
import { Label } from "../ui/label";
const FormSchema = z.object({ const FormSchema = z.object({
username: z.string().min(1, "You must enter a valid username"), username: z.string().min(1, "You must enter a valid username"),
@@ -19,6 +20,7 @@ const FormSchema = z.object({
const LoginForm = () => { const LoginForm = () => {
const { setSession } = useSessionStore(); const { setSession } = useSessionStore();
const { setUserInfo } = useAuthStore();
const rememeberMe = localStorage.getItem("rememberMe") === "true"; const rememeberMe = localStorage.getItem("rememberMe") === "true";
const username = localStorage.getItem("username") || ""; const username = localStorage.getItem("username") || "";
const router = useRouter(); const router = useRouter();
@@ -67,15 +69,13 @@ const LoginForm = () => {
// Store token in localStorage // Store token in localStorage
// localStorage.setItem("auth_token", data.data.token); // localStorage.setItem("auth_token", data.data.token);
if (data.success) { if (data.success) {
const prod = btoa( const prod = btoa(`${value.username.toLowerCase()}:${value.password}`);
`${value.username.toLowerCase()}:${value.password}`
);
const prodUser = { ...data.user, prod: prod }; const prodUser = { ...data.user, prod: prod };
setUserInfo(value.username.toLowerCase(), value.password);
setSession(prodUser, data.data.token);
toast.success(`You are logged in as ${data.data.user.username}`);
setSession(prodUser, data.token); //console.log(search.redirect ? search.redirect : "oops");
toast.success(`You are logged in as ${data.user.username}`);
console.log(search.redirect ? search.redirect : "oops");
router.history.push(search.redirect ? search.redirect : "/"); router.history.push(search.redirect ? search.redirect : "/");
} }
@@ -85,7 +85,14 @@ const LoginForm = () => {
//console.log(data); //console.log(data);
} catch (err) { } catch (err) {
toast.error("Invalid credentials"); // @ts-ignore
if (!err.response.success) {
// @ts-ignore
toast.error(err.response.data.message);
} else {
// @ts-ignore
toast.error(err?.message);
}
} }
}; };
@@ -123,9 +130,7 @@ const LoginForm = () => {
<Input <Input
type="password" type="password"
{...register("password")} {...register("password")}
className={ className={errors.password ? "border-red-500" : ""}
errors.password ? "border-red-500" : ""
}
aria-invalid={!!errors.password} aria-invalid={!!errors.password}
/> />
{errors.password && ( {errors.password && (

View File

@@ -1,20 +1,20 @@
import { useSessionStore } from "../../lib/store/sessionStore";
import { useModuleStore } from "../../lib/store/useModuleStore";
import { moduleActive } from "../../utils/moduleActive";
import { hasAccess } from "../../utils/userAccess";
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,
SidebarFooter, SidebarFooter,
SidebarTrigger, SidebarTrigger,
} from "../ui/sidebar"; } from "../ui/sidebar";
import { ProductionSideBar } from "./side-components/production"; import { AdminSideBar } from "./side-components/admin";
import { EomSideBar } from "./side-components/eom";
import { ForkliftSideBar } from "./side-components/forklift";
import { Header } from "./side-components/header"; import { Header } from "./side-components/header";
import { LogisticsSideBar } from "./side-components/logistics"; import { LogisticsSideBar } from "./side-components/logistics";
import { ProductionSideBar } from "./side-components/production";
import { QualitySideBar } from "./side-components/quality"; import { QualitySideBar } from "./side-components/quality";
import { ForkliftSideBar } from "./side-components/forklift";
import { EomSideBar } from "./side-components/eom";
import { AdminSideBar } from "./side-components/admin";
import { useSessionStore } from "../../lib/store/sessionStore";
import { hasAccess } from "../../utils/userAccess";
import { moduleActive } from "../../utils/moduleActive";
import { useModuleStore } from "../../lib/store/useModuleStore";
export function AppSidebar() { export function AppSidebar() {
const { user } = useSessionStore(); const { user } = useSessionStore();
@@ -33,23 +33,17 @@ export function AppSidebar() {
} }
/> />
)} )}
{moduleActive("logistics") && ( {moduleActive("logistics") && hasAccess(user, "logistics") && (
<LogisticsSideBar <LogisticsSideBar user={user} />
user={user}
moduleID={
modules.filter((n) => n.name === "logistics")[0]
.module_id as string
}
/>
)} )}
{moduleActive("forklift") && {moduleActive("forklift") && hasAccess(user, "forklift") && (
hasAccess(user, "forklift", modules) && <ForkliftSideBar />} <ForkliftSideBar />
{moduleActive("eom") && hasAccess(user, "eom", modules) && (
<EomSideBar />
)} )}
{moduleActive("quality") && {moduleActive("eom") && hasAccess(user, "eom") && <EomSideBar />}
hasAccess(user, "quality", modules) && <QualitySideBar />} {moduleActive("quality") && hasAccess(user, "quality") && (
{moduleActive("admin") && hasAccess(user, "admin", modules) && ( <QualitySideBar />
)}
{moduleActive("admin") && hasAccess(user || [], "admin") && (
<AdminSideBar /> <AdminSideBar />
)} )}
</SidebarContent> </SidebarContent>

View File

@@ -1,4 +1,7 @@
import { Barcode, Cylinder, Package, Truck, Command } from "lucide-react"; import { Barcode, Command, Cylinder, Package, Truck } from "lucide-react";
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
import { User } from "@/types/users";
import { hasPageAccess } from "@/utils/userAccess";
import { import {
SidebarGroup, SidebarGroup,
SidebarGroupContent, SidebarGroupContent,
@@ -7,9 +10,6 @@ import {
SidebarMenuButton, SidebarMenuButton,
SidebarMenuItem, SidebarMenuItem,
} from "../../ui/sidebar"; } from "../../ui/sidebar";
import { hasPageAccess } from "@/utils/userAccess";
import { User } from "@/types/users";
import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
const iconMap: any = { const iconMap: any = {
Package: Package, Package: Package,
@@ -19,13 +19,7 @@ const iconMap: any = {
Command: Command, Command: Command,
}; };
export function LogisticsSideBar({ export function LogisticsSideBar({ user }: { user: User | null }) {
user,
moduleID,
}: {
user: User | null;
moduleID: string;
}) {
const { subModules } = useSubModuleStore(); const { subModules } = useSubModuleStore();
const items = subModules.filter((m) => m.moduleName === "logistics"); const items = subModules.filter((m) => m.moduleName === "logistics");
@@ -40,12 +34,7 @@ export function LogisticsSideBar({
return ( return (
<SidebarMenuItem key={item.submodule_id}> <SidebarMenuItem key={item.submodule_id}>
<> <>
{hasPageAccess( {hasPageAccess(user, item.roles, item.name) && (
user,
item.roles,
moduleID
) &&
item.active && (
<SidebarMenuButton asChild> <SidebarMenuButton asChild>
<a href={item.link}> <a href={item.link}>
<Icon /> <Icon />

View File

@@ -1,3 +1,11 @@
import { useForm } from "@tanstack/react-form";
import { useQuery } from "@tanstack/react-query";
import { Link } from "@tanstack/react-router";
import axios from "axios";
import { format } from "date-fns";
import { CircleAlert } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { LstCard } from "@/components/extendedUI/LstCard"; import { LstCard } from "@/components/extendedUI/LstCard";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { CardHeader } from "@/components/ui/card"; import { CardHeader } from "@/components/ui/card";
@@ -9,24 +17,15 @@ import {
TooltipProvider, TooltipProvider,
TooltipTrigger, TooltipTrigger,
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
import { useForm } from "@tanstack/react-form";
import { useQuery } from "@tanstack/react-query";
import { Link } from "@tanstack/react-router";
import axios from "axios";
import { format } from "date-fns";
import { CircleAlert } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import ChartData from "./ChartData";
import { AttachSilo } from "./AttachSilo";
import { DetachSilo } from "./DetachSilo";
import { useSessionStore } from "@/lib/store/sessionStore"; import { useSessionStore } from "@/lib/store/sessionStore";
import { useModuleStore } from "@/lib/store/useModuleStore";
import { useGetUserRoles } from "@/lib/store/useGetRoles"; import { useGetUserRoles } from "@/lib/store/useGetRoles";
import { useModuleStore } from "@/lib/store/useModuleStore";
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
import { AttachSilo } from "./AttachSilo";
import ChartData from "./ChartData";
import { DetachSilo } from "./DetachSilo";
export default function SiloCard(data: any) { export default function SiloCard(data: any) {
const token = localStorage.getItem("auth_token");
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const { refetch } = useQuery(getStockSilo()); const { refetch } = useQuery(getStockSilo());
const { user } = useSessionStore(); const { user } = useSessionStore();
@@ -40,7 +39,7 @@ export default function SiloCard(data: any) {
const module = modules.filter((n) => n.name === "logistics"); const module = modules.filter((n) => n.name === "logistics");
const accessRoles = userRoles.filter( const accessRoles = userRoles.filter(
(n) => n.module_id === module[0]?.module_id (n: any) => n.module === module[0]?.name,
) as any; ) as any;
const form = useForm({ const form = useForm({
@@ -59,7 +58,7 @@ export default function SiloCard(data: any) {
const res = await axios.post( const res = await axios.post(
"/api/logistics/createsiloadjustment", "/api/logistics/createsiloadjustment",
dataToSubmit, dataToSubmit,
{ headers: { Authorization: `Bearer ${token}` } } { withCredentials: true },
); );
//console.log(res.data); //console.log(res.data);
@@ -86,7 +85,6 @@ export default function SiloCard(data: any) {
}, },
}); });
console.log(accessRoles);
return ( return (
<LstCard> <LstCard>
<div className="flex flex-row"> <div className="flex flex-row">
@@ -105,30 +103,27 @@ export default function SiloCard(data: any) {
{silo.Stock_Total === 0 ? ( {silo.Stock_Total === 0 ? (
<div className="flex justify-center flex-col"> <div className="flex justify-center flex-col">
<span> <span>
The silo is currently empty you will not be The silo is currently empty you will not be able to do an
able to do an adjustment until you have adjustment until you have received material in.
received material in.
</span> </span>
<hr /> <hr />
<ul> <ul>
<li> <li>
-Someone click "Take inventory on a -Someone click "Take inventory on a empty location" in
empty location" in stock. stock.
</li> </li>
<li> <li>
-Silo virtualy ran empty due to -Silo virtualy ran empty due to production over consumption.
production over consumption.
</li> </li>
<li> <li>
-Someone forgot to move a railcar -Someone forgot to move a railcar compartment over to this
compartment over to this location. location.
</li> </li>
</ul> </ul>
</div> </div>
) : ( ) : (
<> <>
{user && {user && roles.includes(accessRoles[0]?.role) && (
roles.includes(accessRoles[0]?.role) && (
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
@@ -148,68 +143,38 @@ export default function SiloCard(data: any) {
return ( return (
<div className="m-2 min-w-48 max-w-96 p-2"> <div className="m-2 min-w-48 max-w-96 p-2">
<div className="flex flex-row"> <div className="flex flex-row">
<Label htmlFor="newLevel"> <Label htmlFor="newLevel">New level</Label>
New level
</Label>
<div> <div>
<Disclaimer /> <Disclaimer />
</div> </div>
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
<Input <Input
name={ name={field.name}
field.name value={field.state.value}
} onBlur={field.handleBlur}
value={
field
.state
.value
}
onBlur={
field.handleBlur
}
type="decimal" type="decimal"
onChange={( onChange={(e) =>
e field.handleChange(e.target.value)
) =>
field.handleChange(
e
.target
.value
)
} }
/> />
<Button <Button
className="ml-1" className="ml-1"
variant="outline" variant="outline"
type="submit" type="submit"
onClick={ onClick={form.handleSubmit}
form.handleSubmit disabled={submitting}
}
disabled={
submitting
}
> >
{submitting ? ( {submitting ? (
<span className="w-24"> <span className="w-24">Submitting...</span>
Submitting...
</span>
) : ( ) : (
<span className="w-24"> <span className="w-24">Submit</span>
Submit
</span>
)} )}
</Button> </Button>
</div> </div>
{field.state.meta {field.state.meta.errors.length ? (
.errors <em>{field.state.meta.errors.join(",")}</em>
.length ? (
<em>
{field.state.meta.errors.join(
","
)}
</em>
) : null} ) : null}
</div> </div>
); );
@@ -251,10 +216,9 @@ const Disclaimer = () => {
</TooltipTrigger> </TooltipTrigger>
<TooltipContent className="max-w-48"> <TooltipContent className="max-w-48">
<p className="text-pretty"> <p className="text-pretty">
If you have had this page open for a period of time If you have had this page open for a period of time before
before submitting your data, there is a chance that the submitting your data, there is a chance that the stock levels will
stock levels will be different from the ones you see be different from the ones you see above
above
</p> </p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>

View File

@@ -1,5 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import { LstCard } from "@/components/extendedUI/LstCard"; import { LstCard } from "@/components/extendedUI/LstCard";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { import {
Table, Table,
@@ -10,15 +11,13 @@ import {
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import { useSessionStore } from "@/lib/store/sessionStore"; import { useSessionStore } from "@/lib/store/sessionStore";
import { useGetUserRoles } from "@/lib/store/useGetRoles";
import { useModuleStore } from "@/lib/store/useModuleStore";
import { useSettingStore } from "@/lib/store/useSettings"; import { useSettingStore } from "@/lib/store/useSettings";
import { LotType } from "@/types/lots"; import { LotType } from "@/types/lots";
import { getlots } from "@/utils/querys/production/lots"; import { getlots } from "@/utils/querys/production/lots";
import { useQuery } from "@tanstack/react-query";
import ManualPrint from "./ManualPrinting/ManualPrint"; import ManualPrint from "./ManualPrinting/ManualPrint";
import ManualPrintForm from "./ManualPrinting/ManualPrintForm"; import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
import { ScrollArea } from "@/components/ui/scroll-area";
import { useGetUserRoles } from "@/lib/store/useGetRoles";
import { useModuleStore } from "@/lib/store/useModuleStore";
let lotColumns = [ let lotColumns = [
{ {
@@ -81,7 +80,7 @@ export default function Lots() {
const module = modules.filter((n) => n.name === "logistics"); const module = modules.filter((n) => n.name === "logistics");
const accessRoles = userRoles.filter( const accessRoles = userRoles.filter(
(n) => n.module_id === module[0]?.module_id (n: any) => n.module === module[0]?.name,
) as any; ) as any;
if (user && roles.includes(accessRoles[0]?.role)) { if (user && roles.includes(accessRoles[0]?.role)) {
@@ -108,9 +107,7 @@ export default function Lots() {
<TableHeader> <TableHeader>
<TableRow> <TableRow>
{lotColumns.map((l) => ( {lotColumns.map((l) => (
<TableHead key={l.key}> <TableHead key={l.key}>{l.label}</TableHead>
{l.label}
</TableHead>
))} ))}
</TableRow> </TableRow>
</TableHeader> </TableHeader>
@@ -213,12 +210,8 @@ export default function Lots() {
<TableCell className="font-medium"> <TableCell className="font-medium">
{lot.MachineLocation} {lot.MachineLocation}
</TableCell> </TableCell>
<TableCell className="font-medium"> <TableCell className="font-medium">{lot.AV}</TableCell>
{lot.AV} <TableCell className="font-medium">{lot.Alias}</TableCell>
</TableCell>
<TableCell className="font-medium">
{lot.Alias}
</TableCell>
<TableCell <TableCell
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`} className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
> >
@@ -232,22 +225,14 @@ export default function Lots() {
<TableCell className="font-medium"> <TableCell className="font-medium">
{lot.PlannedQTY} {lot.PlannedQTY}
</TableCell> </TableCell>
<TableCell className="font-medium"> <TableCell className="font-medium">{lot.Produced}</TableCell>
{lot.Produced} <TableCell className="font-medium">{lot.Remaining}</TableCell>
</TableCell>
<TableCell className="font-medium">
{lot.Remaining}
</TableCell>
<TableCell className="font-medium"> <TableCell className="font-medium">
{lot.overPrinting} {lot.overPrinting}
</TableCell> </TableCell>
{user && {user && roles.includes(accessRoles[0]?.role) && (
roles.includes(
accessRoles[0]?.role
) && (
<> <>
{server === "usday1vms006" || {server === "usday1vms006" || server === "localhost" ? (
server === "localhost" ? (
<> <>
<TableCell className="flex justify-center"> <TableCell className="flex justify-center">
<ManualPrintForm /> <ManualPrintForm />
@@ -255,9 +240,7 @@ export default function Lots() {
</> </>
) : ( ) : (
<TableCell className="flex justify-center"> <TableCell className="flex justify-center">
<ManualPrint <ManualPrint lot={lot} />
lot={lot}
/>
</TableCell> </TableCell>
)} )}
</> </>

View File

@@ -1,12 +1,44 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useModuleStore } from "../../lib/store/useModuleStore";
import { useEffect } from "react"; import { useEffect } from "react";
import { useSettingStore } from "@/lib/store/useSettings"; import { useSessionStore } from "@/lib/store/sessionStore";
import { useAuthStore } from "@/lib/store/useAuthStore";
import { useGetUserRoles } from "@/lib/store/useGetRoles"; import { useGetUserRoles } from "@/lib/store/useGetRoles";
import { useSettingStore } from "@/lib/store/useSettings";
import { useSubModuleStore } from "@/lib/store/useSubModuleStore"; import { useSubModuleStore } from "@/lib/store/useSubModuleStore";
import { useModuleStore } from "../../lib/store/useModuleStore";
const queryClient = new QueryClient(); const queryClient = new QueryClient();
const reAuth = async (username: string, password: string) => {
const { setSession } = useSessionStore();
try {
const response = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: username,
password: password,
}),
});
const data = await response.json();
// Store token in localStorage
// localStorage.setItem("auth_token", data.data.token);
if (data.success) {
const prod = btoa(`${username.toLowerCase()}:${password}`);
const prodUser = { ...data.user, prod: prod };
setSession(prodUser, data.data.token);
}
//console.log(data);
} catch (err) {
console.log(err);
}
};
export const SessionProvider = ({ export const SessionProvider = ({
children, children,
}: { }: {
@@ -16,8 +48,13 @@ export const SessionProvider = ({
const { fetchSettings } = useSettingStore(); const { fetchSettings } = useSettingStore();
const { fetchUserRoles } = useGetUserRoles(); const { fetchUserRoles } = useGetUserRoles();
const { fetchSubModules } = useSubModuleStore(); const { fetchSubModules } = useSubModuleStore();
const { username, password } = useAuthStore();
useEffect(() => { useEffect(() => {
if (username !== "") {
reAuth(username, password);
}
fetchModules(); fetchModules();
fetchSettings(); fetchSettings();
fetchUserRoles(); fetchUserRoles();
@@ -25,8 +62,6 @@ export const SessionProvider = ({
}, []); }, []);
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
{children}
</QueryClientProvider>
); );
}; };

View File

@@ -1,13 +1,16 @@
import {useSessionStore} from "@/lib/store/sessionStore";
import { useRouter } from "@tanstack/react-router"; import { useRouter } from "@tanstack/react-router";
import { useSessionStore } from "@/lib/store/sessionStore";
import { useAuthStore } from "@/lib/store/useAuthStore";
export const useLogout = () => { export const useLogout = () => {
const { clearSession } = useSessionStore(); const { clearSession } = useSessionStore();
const { clearUser } = useAuthStore();
const router = useRouter(); const router = useRouter();
const logout = async () => { const logout = async () => {
router.invalidate(); router.invalidate();
router.clearCache(); router.clearCache();
clearSession(); clearSession();
clearUser();
window.location.reload(); window.location.reload();
}; };

View File

@@ -1,6 +1,7 @@
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { useSessionStore } from "../lib/store/sessionStore"; import axios from "axios";
import { useEffect } from "react"; import { useEffect } from "react";
import { useSessionStore } from "../lib/store/sessionStore";
const fetchSession = async () => { const fetchSession = async () => {
const token = localStorage.getItem("auth_token"); const token = localStorage.getItem("auth_token");
@@ -8,15 +9,15 @@ const fetchSession = async () => {
if (!token) { if (!token) {
throw new Error("No token found"); throw new Error("No token found");
} }
try {
const res = await fetch("/api/auth/session", { const res = await axios.get("/api/auth/session", {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
Authorization: `Bearer ${token}`,
}, },
withCredentials: true,
}); });
// console.log(res);
if (!res.ok) { if (res.status === 401) {
localStorage.removeItem("auth_token"); localStorage.removeItem("auth_token");
// remove these for a while if no session just until fully to 2.0 and clearly no one has ran lstv1 in a long time // remove these for a while if no session just until fully to 2.0 and clearly no one has ran lstv1 in a long time
localStorage.removeItem("ally-supports-cache"); localStorage.removeItem("ally-supports-cache");
@@ -27,7 +28,33 @@ const fetchSession = async () => {
throw new Error("Session not found"); throw new Error("Session not found");
} }
return res.json(); const userRoles = await axios.get("/api/auth/getuseraccess", {
withCredentials: true,
});
const userData = {
...res.data,
data: {
...res.data.data,
user: {
...res.data.data.user,
roles: userRoles.data.data,
},
token: "Just a token as this will be removed in the future",
},
};
return userData;
} catch (error) {
localStorage.removeItem("auth_token");
// remove these for a while if no session just until fully to 2.0 and clearly no one has ran lstv1 in a long time
localStorage.removeItem("ally-supports-cache");
localStorage.removeItem("auth-storage");
localStorage.removeItem("nextauth.message");
localStorage.removeItem("prod");
throw new Error("Session not found");
}
}; };
export const useSession = () => { export const useSession = () => {
@@ -39,9 +66,9 @@ export const useSession = () => {
queryFn: fetchSession, queryFn: fetchSession,
enabled: !!token, // Prevents query if token is null enabled: !!token, // Prevents query if token is null
staleTime: 60 * 1000, staleTime: 60 * 1000,
gcTime: 10 * 60 * 1000, // 10 mins //gcTime: 10 * 60 * 1000, // 10 mins
refetchOnWindowFocus: true, refetchOnWindowFocus: true,
//refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes
}); });
useEffect(() => { useEffect(() => {
if (data) { if (data) {

View File

@@ -1,6 +1,6 @@
import {User} from "@/types/users";
import axios from "axios"; import axios from "axios";
import { create } from "zustand"; import { create } from "zustand";
import { User } from "@/types/users";
export type SessionState = { export type SessionState = {
user: User | null; user: User | null;
@@ -20,11 +20,20 @@ export const useSessionStore = create<SessionState>((set) => {
setSession: async (user: any, token) => { setSession: async (user: any, token) => {
if (token) { if (token) {
localStorage.setItem("auth_token", token); localStorage.setItem("auth_token", token);
const response = await axios.get("/api/auth/getuseraccess", { const response = await axios.get("/api/auth/session", {
headers: {Authorization: `Bearer ${token}`}, withCredentials: true,
});
const userRoles = await axios.get("/api/auth/getuseraccess", {
withCredentials: true,
}); });
const data = response.data; //await response.json(); const data = response.data; //await response.json();
user = {...user, roles: data.data};
const rawUser = data.data.user;
// user.map((u: any) => ({
// ...u,
// roles: userRoles.data.data,
// }));
user = { ...rawUser, roles: userRoles.data.data };
} else { } else {
localStorage.removeItem("auth_token"); localStorage.removeItem("auth_token");
} }

View File

@@ -0,0 +1,15 @@
import { create } from "zustand";
interface SettingState {
username: string;
password: string;
clearUser: () => void;
setUserInfo: (username: string, password: string) => void;
}
export const useAuthStore = create<SettingState>()((set) => ({
username: "",
password: "",
setUserInfo: (username, password) => set({ username, password }),
clearUser: () => set({ username: "", password: "" }),
}));

View File

@@ -1,6 +1,6 @@
import axios from "axios";
import { create } from "zustand"; import { create } from "zustand";
import { Modules } from "@/types/modules"; import { Modules } from "@/types/modules";
import axios from "axios";
interface SettingState { interface SettingState {
userRoles: Modules[]; userRoles: Modules[];
@@ -21,17 +21,20 @@ export const useGetUserRoles = create<SettingState>()((set) => ({
const token = localStorage.getItem("auth_token"); const token = localStorage.getItem("auth_token");
if (token) { if (token) {
const response = await axios.get("/api/auth/getuseraccess", { const response = await axios.get("/api/auth/getuseraccess", {
headers: { Authorization: `Bearer ${token}` }, withCredentials: true,
}); });
const data: FetchModulesResponse = response.data; //await response.json(); const data: FetchModulesResponse = response?.data; //await response.json();
//console.log(data); if (response.status === 401) {
set({ userRoles: data.data }); set({ userRoles: [] });
}
set({ userRoles: data?.data });
} else { } else {
//console.log(data); //console.log(data);
set({ userRoles: [] }); set({ userRoles: [] });
} }
} catch (error) { } catch (error) {
set({ userRoles: [] });
console.error("Failed to fetch settings:", error); console.error("Failed to fetch settings:", error);
} }
}, },

View File

@@ -1,23 +1,22 @@
import { Modules } from "@/types/modules";
import { User } from "@/types/users"; import { User } from "@/types/users";
// user will need access to the module. // user will need access to the module.
// users role will determine there visual access // users role will determine there visual access
export function hasAccess( export function hasAccess(user: any, moduleName: string | null): boolean {
user: User | null, //console.log("has access user", user, moduleName);
moduleName: string | null,
modules: Modules[]
): boolean {
// get the modules for the id // get the modules for the id
const filteredModule = modules?.filter((f) => f.name === moduleName);
const filteredModule = user?.roles?.filter(
(f: any) => f.module === moduleName,
);
//console.log(filteredModule[0]); //console.log(filteredModule[0]);
// userroles and filter out by the module id, // userroles and filter out by the module id,
//console.log("Has Module access", filteredModule);
// const roleCheck: any = user?.roles.find(
// (role) => role.module_id === filteredModule[0].module_id,
// );
const roleCheck: any = user?.roles.find( if (filteredModule && filteredModule.length > 0) {
(role) => role.module_id === filteredModule[0].module_id
);
if (filteredModule[0].roles.includes(roleCheck?.role)) {
return true; return true;
} }
//if(filteredModule[0].roles.includes(roleCheck.)) //if(filteredModule[0].roles.includes(roleCheck.))
@@ -27,18 +26,27 @@ export function hasAccess(
export function hasPageAccess( export function hasPageAccess(
user: User | null, user: User | null,
role: any, role: any,
module_id: string moduleName: string,
): boolean { ): boolean {
if (role.includes("viewer")) return true; if (role.includes("viewer")) return true;
if (!user) return false; if (!user) return false;
// get only the module in the user profile const userRole = user?.roles.filter(
(role: any) => role.module === moduleName,
);
//console.log(user); //console.log(user);
const userRole = user?.roles.filter((role) => role.module_id === module_id);
//console.log(userRole[0]?.role);
// if (role.includes(userRole[0]?.role)) { // if (role.includes(userRole[0]?.role)) {
// return true}; // return true};
if (userRole.length !== 0) return true; //if (userRole.length > 0) return true;
if (userRole.length >= 1) {
//console.log(userRole);
return true;
} else {
return false; return false;
} }
//return false;
}

View File

@@ -1,35 +1,34 @@
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
import { serve } from "@hono/node-server"; import { serve } from "@hono/node-server";
import { OpenAPIHono } from "@hono/zod-openapi";
import { serveStatic } from "@hono/node-server/serve-static"; import { serveStatic } from "@hono/node-server/serve-static";
import { logger } from "hono/logger"; import { OpenAPIHono } from "@hono/zod-openapi";
import { cors } from "hono/cors"; import { cors } from "hono/cors";
import { createLog } from "./services/logger/logger.js"; import { logger } from "hono/logger";
import os from "os";
import auth from "./services/auth/authService.js";
import dataMart from "./services/dataMart/dataMartService.js";
import eom from "./services/eom/eomService.js";
// custom routes // custom routes
import scalar from "./services/general/route/scalar.js"; import scalar from "./services/general/route/scalar.js";
import system from "./services/server/systemServer.js"; import { createLog } from "./services/logger/logger.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";
import rfid from "./services/rfid/rfidService.js";
import printers from "./services/printers/printerService.js";
import loggerService from "./services/logger/loggerService.js"; import loggerService from "./services/logger/loggerService.js";
import ocpService from "./services/ocp/ocpService.js"; import logistics from "./services/logistics/logisticsService.js";
import os from "os";
import { sendEmail } from "./services/notifications/controller/sendMail.js"; import { sendEmail } from "./services/notifications/controller/sendMail.js";
import notify from "./services/notifications/notifyService.js"; import notify from "./services/notifications/notifyService.js";
import eom from "./services/eom/eomService.js"; import ocme from "./services/ocme/ocmeService.js";
import dataMart from "./services/dataMart/dataMartService.js"; import ocpService from "./services/ocp/ocpService.js";
import qualityRequest from "./services/quality/qualityService.js"; import printers from "./services/printers/printerService.js";
import produser from "./services/prodUser/prodUser.js"; import produser from "./services/prodUser/prodUser.js";
import qualityRequest from "./services/quality/qualityService.js";
import rfid from "./services/rfid/rfidService.js";
import { import {
getSettings, getSettings,
serverSettings, serverSettings,
} from "./services/server/controller/settings/getSettings.js"; } from "./services/server/controller/settings/getSettings.js";
import system from "./services/server/systemServer.js";
import sqlService from "./services/sqlServer/sqlService.js";
import tcpServer from "./services/tcpServer/tcpServer.js";
// create the main prodlogin here // create the main prodlogin here
const username = "lst_user"; const username = "lst_user";
@@ -63,13 +62,18 @@ if (process.env.NODE_ENV === "development") {
app.use( app.use(
"*", "*",
cors({ cors({
origin: "*", // Allow all origins origin: [
"http://localhost:3000",
"http://localhost:5173",
"http://localhost:4000",
"http://localhost:4200",
], // Allow all origins
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"], allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"], //exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
credentials: true, // Allow credentials if needed credentials: true, // Allow credentials if needed
maxAge: 600, maxAge: 600,
}) }),
); );
// Middleware to normalize route case // Middleware to normalize route case
@@ -205,9 +209,9 @@ serve(
"info", "info",
"LST", "LST",
"server", "server",
`Server is running on http://${info.address}:${info.port}` `Server is running on http://${info.address}:${info.port}`,
); );
} },
); );
/** /**
@@ -228,9 +232,9 @@ if (ocmeport && isActive[0]?.value === "1") {
"info", "info",
"LST", "LST",
"server", "server",
`Ocme section is listening on http://${info.address}:${info.port}` `Ocme section is listening on http://${info.address}:${info.port}`,
); );
} },
); );
} }

View File

@@ -1,45 +1,62 @@
import axios from "axios";
import { type MiddlewareHandler } from "hono"; import { type MiddlewareHandler } from "hono";
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
const { sign, verify } = jwt; const { sign, verify } = jwt;
export const authMiddleware: MiddlewareHandler = async (c, next) => { export const authMiddleware: MiddlewareHandler = async (c, next) => {
const authHeader = c.req.header("Authorization"); console.log("middleware checked");
const cookieHeader = c.req.header("Cookie");
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
if (!authHeader || !authHeader.startsWith("Bearer ")) { const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/me`, {
return c.json({error: "Unauthorized"}, 401); headers: { Cookie: cookieHeader },
}
const token = authHeader.split(" ")[1];
try {
const decoded = verify(token, process.env.JWT_SECRET!, {ignoreExpiration: false}) as {
userId: number;
exp: number;
};
const currentTime = Math.floor(Date.now() / 1000); // Get current timestamp
const timeLeft = decoded.exp - currentTime;
// If the token has less than REFRESH_THRESHOLD seconds left, refresh it
let newToken = null;
if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD!)) {
newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET!, {
expiresIn: parseInt(process.env.EXPIRATION_TIME!),
}); });
c.res.headers.set("Authorization", `Bearer ${newToken}`);
}
c.set("user", {id: decoded.userId}); if (res.status === 401) return c.json({ error: "Unauthorized" }, 401);
await next();
// If a new token was generated, send it in response headers //const user = await resp.json();
if (newToken) { c.set("user", res.data.user);
console.log("token was refreshed"); return next();
c.res.headers.set("X-Refreshed-Token", newToken);
}
} catch (err) {
return c.json({error: "Invalid token"}, 401);
}
}; };
// export const authMiddleware: MiddlewareHandler = async (c, next) => {
// const authHeader = c.req.header("Authorization");
// if (!authHeader || !authHeader.startsWith("Bearer ")) {
// return c.json({error: "Unauthorized"}, 401);
// }
// const token = authHeader.split(" ")[1];
// try {
// const decoded = verify(token, process.env.JWT_SECRET!, {ignoreExpiration: false}) as {
// userId: number;
// exp: number;
// };
// const currentTime = Math.floor(Date.now() / 1000); // Get current timestamp
// const timeLeft = decoded.exp - currentTime;
// // If the token has less than REFRESH_THRESHOLD seconds left, refresh it
// let newToken = null;
// if (timeLeft < parseInt(process.env.REFRESH_THRESHOLD!)) {
// newToken = sign({userId: decoded.userId}, process.env.JWT_SECRET!, {
// expiresIn: parseInt(process.env.EXPIRATION_TIME!),
// });
// c.res.headers.set("Authorization", `Bearer ${newToken}`);
// }
// c.set("user", {id: decoded.userId});
// await next();
// // If a new token was generated, send it in response headers
// if (newToken) {
// console.log("token was refreshed");
// c.res.headers.set("X-Refreshed-Token", newToken);
// }
// } catch (err) {
// return c.json({error: "Invalid token"}, 401);
// }
// };

View File

@@ -1,85 +1,111 @@
import axios from "axios";
import { createMiddleware } from "hono/factory"; import { createMiddleware } from "hono/factory";
import type { CustomJwtPayload } from "../../../types/jwtToken.js"; // const hasCorrectRole = (requiredRole: string[], module: string) =>
import { verify } from "hono/jwt"; // createMiddleware(async (c, next) => {
import { db } from "../../../../database/dbclient.js"; // /**
import { modules } from "../../../../database/schema/modules.js"; // * We want to check to make sure you have the correct role to be here
import { and, eq } from "drizzle-orm"; // */
import { userRoles } from "../../../../database/schema/userRoles.js"; // const authHeader = c.req.header("Authorization");
import { tryCatch } from "../../../globalUtils/tryCatch.js";
// if (!authHeader || !authHeader.startsWith("Bearer ")) {
// return c.json({ error: "Unauthorized" }, 401);
// }
// const token = authHeader.split(" ")[1];
// // deal with token data
// const { data: tokenData, error: tokenError } = await tryCatch(
// verify(token, process.env.JWT_SECRET!),
// );
// if (tokenError) {
// return c.json({ error: "Invalid token" }, 401);
// }
// const customToken = tokenData as CustomJwtPayload;
// // Get the module
// const { data: mod, error: modError } = await tryCatch(
// db.select().from(modules).where(eq(modules.name, module)),
// );
// if (modError) {
// console.log(modError);
// return;
// }
// if (mod.length === 0) {
// return c.json({ error: "You have entered an invalid module name" }, 403);
// }
// // check if the user has the role needed to get into this module
// const { data: userRole, error: userRoleError } = await tryCatch(
// db
// .select()
// .from(userRoles)
// .where(
// and(
// eq(userRoles.module_id, mod[0].module_id),
// eq(userRoles.user_id, customToken.user?.user_id!),
// ),
// ),
// );
// if (userRoleError) {
// return;
// }
// if (!userRole) {
// return c.json(
// {
// error:
// "The module you are trying to access is not active or is invalid.",
// },
// 403,
// );
// }
// if (!requiredRole.includes(userRole[0]?.role)) {
// return c.json(
// { error: "You do not have access to this part of the app." },
// 403,
// );
// }
// await next();
// });
interface UserRole {
userRoleId: string;
userId: string;
module: string;
role: string;
}
const hasCorrectRole = (requiredRole: string[], module: string) => const hasCorrectRole = (requiredRole: string[], module: string) =>
createMiddleware(async (c, next) => { createMiddleware(async (c, next) => {
/** const cookieHeader = c.req.header("Cookie");
* We want to check to make sure you have the correct role to be here if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
*/
const authHeader = c.req.header("Authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) { const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/roles`, {
return c.json({ error: "Unauthorized" }, 401); headers: { Cookie: cookieHeader },
} });
const token = authHeader.split(" ")[1]; const currentRoles: UserRole[] = res.data.data;
const canAccess = currentRoles.some(
// deal with token data (r) => r.module === module && requiredRole.includes(r.role),
const { data: tokenData, error: tokenError } = await tryCatch(
verify(token, process.env.JWT_SECRET!)
); );
if (!canAccess) {
if (tokenError) {
return c.json({ error: "Invalid token" }, 401);
}
const customToken = tokenData as CustomJwtPayload;
// Get the module
const { data: mod, error: modError } = await tryCatch(
db.select().from(modules).where(eq(modules.name, module))
);
if (modError) {
console.log(modError);
return;
}
if (mod.length === 0) {
return c.json({ error: "You have entered an invalid module name" }, 403);
}
// check if the user has the role needed to get into this module
const { data: userRole, error: userRoleError } = await tryCatch(
db
.select()
.from(userRoles)
.where(
and(
eq(userRoles.module_id, mod[0].module_id),
eq(userRoles.user_id, customToken.user?.user_id!)
)
)
);
if (userRoleError) {
return;
}
if (!userRole) {
return c.json( return c.json(
{ {
error: error: "Unauthorized",
"The module you are trying to access is not active or is invalid.", message: `You do not have access to ${module}`,
}, },
403 400,
); );
} }
if (!requiredRole.includes(userRole[0]?.role)) { return next();
return c.json(
{ error: "You do not have access to this part of the app." },
403
);
}
await next();
}); });
export default hasCorrectRole; export default hasCorrectRole;

View File

@@ -1,4 +1,5 @@
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import axios from "axios";
import { login } from "../controllers/login.js"; import { login } from "../controllers/login.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -66,7 +67,7 @@ const route = createRoute({
}, },
}); });
app.openapi(route, async (c) => { app.openapi(route, async (c: any) => {
const { username, password, email } = await c.req.json(); const { username, password, email } = await c.req.json();
if (!username || !password) { if (!username || !password) {
@@ -75,23 +76,42 @@ app.openapi(route, async (c) => {
success: false, success: false,
message: "Username and password are required", message: "Username and password are required",
}, },
400 400,
); );
} }
try { try {
const { token, user } = await login(username.toLowerCase(), password); const loginResp = await axios.post(
`${process.env.LST_BASE_URL}/api/user/login`,
{ username: username.toLowerCase(), password },
{ withCredentials: true },
);
// Set the JWT as an HTTP-only cookie // Set the JWT as an HTTP-only cookie
//c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`); //c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`);
const setCookie = loginResp.headers["set-cookie"] as any;
if (setCookie) {
c.header("Set-Cookie", setCookie);
}
return c.json( return c.json(
{ success: true, message: "Login successful", user, token }, { success: true, message: "Login successful", data: loginResp.data },
200 200,
); );
} catch (err) { } catch (err) {
// @ts-ignore
if (!err.response.data.success) {
// @ts-ignore
return c.json(
// @ts-ignore
{ success: false, message: err.response.data.message },
401,
);
} else {
return c.json({ success: false, message: "Incorrect Credentials" }, 401); return c.json({ success: false, message: "Incorrect Credentials" }, 401);
} }
}
}); });
export default app; export default app;

View File

@@ -1,14 +1,15 @@
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import axios from "axios";
import { verify } from "hono/jwt"; import { verify } from "hono/jwt";
import { authMiddleware } from "../middleware/authMiddleware.js";
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import { authMiddleware } from "../middleware/authMiddleware.js";
const session = new OpenAPIHono(); const session = new OpenAPIHono();
const expiresIn = Number(process.env.JWT_EXPIRES!) || 60; const expiresIn = Number(process.env.JWT_EXPIRES!) || 60;
const secret: string = process.env.JWT_SECRET!; const secret: string = process.env.JWT_SECRET!;
const { sign } = jwt; const { sign } = jwt;
const UserSchema = z.object({ const UserSchema = z.object({
username: z username: z
.string() .string()
@@ -27,6 +28,10 @@ const UserSchema = z.object({
.openapi({ example: "Password1!" }), .openapi({ example: "Password1!" }),
}); });
const activeSessions: Record<string, { lastSeen: number; expiresAt: number }> =
{};
const SESSION_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
session.openapi( session.openapi(
createRoute({ createRoute({
tags: ["Auth"], tags: ["Auth"],
@@ -48,9 +53,7 @@ session.openapi(
"application/json": { "application/json": {
schema: z.object({ schema: z.object({
data: z.object({ data: z.object({
token: z token: z.string().openapi({
.string()
.openapi({
example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads", example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads",
}), }),
// user: z.object({ // user: z.object({
@@ -76,35 +79,71 @@ session.openapi(
}, },
}, },
}), }),
async (c) => { async (c: any) => {
const authHeader = c.req.header("Authorization"); const cookieHeader = c.req.header("Cookie");
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
if (authHeader?.includes("Basic")) { const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/me`, {
return c.json( headers: { Cookie: cookieHeader },
{ message: "You are a Basic user! Please login to get a token" }, withCredentials: true,
401
);
}
if (!authHeader) {
return c.json({ message: "Unauthorized" }, 401);
}
const token = authHeader?.split("Bearer ")[1] || "";
try {
const payload = await verify(token, process.env.JWT_SECRET!);
// If it's valid, return a new token
const newToken = sign({ user: payload.user }, secret, {
expiresIn: expiresIn * 60,
}); });
return c.json({ data: { token: newToken, user: payload.user } }, 200); if (res.status === 401) return c.json({ error: "Unauthorized" }, 401);
} catch (error) {
return c.json({ message: "Unauthorized" }, 401); const user = res.data.user;
}
// ── record session heartbeat ───────────────────────────────────────────
activeSessions[user.id] = {
lastSeen: Date.now(),
expiresAt: Date.now() + SESSION_TIMEOUT_MS,
};
// clean up stale sessions in the background
for (const [key, sess] of Object.entries(activeSessions)) {
if (Date.now() > sess.expiresAt) delete activeSessions[key];
} }
const setCookie =
res.headers &&
((res.headers["set-cookie"] || res.headers["Set-Cookie"]) as
| string[]
| undefined);
if (setCookie) c.header("Set-Cookie", setCookie);
return c.json(
{ data: { token: res.data.token, user: res.data.user } },
200,
);
// 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] || "";
// try {
// const payload = await verify(token, process.env.JWT_SECRET!);
// // If it's valid, return a new token
// const newToken = sign({ user: payload.user }, secret, {
// expiresIn: expiresIn * 60,
// });
// return c.json({ data: { token: newToken, user: payload.user } }, 200);
// } catch (error) {
// return c.json({ message: "Unauthorized" }, 401);
// }
},
); );
// const token = authHeader?.split("Bearer ")[1] || ""; // const token = authHeader?.split("Bearer ")[1] || "";

View File

@@ -1,8 +1,9 @@
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import axios from "axios";
import jwt from "jsonwebtoken"; import jwt from "jsonwebtoken";
import type { CustomJwtPayload } from "../../../../types/jwtToken.js"; import type { CustomJwtPayload } from "../../../../types/jwtToken.js";
import { authMiddleware } from "../../middleware/authMiddleware.js";
import { roleCheck } from "../../controllers/userRoles/getUserAccess.js"; import { roleCheck } from "../../controllers/userRoles/getUserAccess.js";
import { authMiddleware } from "../../middleware/authMiddleware.js";
const { verify } = jwt; const { verify } = jwt;
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -25,35 +26,47 @@ app.openapi(
}, },
}, },
}), }),
async (c) => { async (c: any) => {
// apit hit // apit hit
//apiHit(c, { endpoint: "api/auth/getUserRoles" }); //apiHit(c, { endpoint: "api/auth/getUserRoles" });
const authHeader = c.req.header("Authorization"); const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
try { const user = c.get("user");
const secret = process.env.JWT_SECRET!;
if (!secret) { if (!user) {
throw new Error("JWT_SECRET is not defined in environment variables"); return c.json(
{
success: true,
message: `Unauthorized`,
},
401,
);
} }
try {
const cookieHeader = c.req.header("Cookie");
if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401);
const payload = verify(token, secret) as CustomJwtPayload; const res = await axios.get(
`${process.env.LST_BASE_URL}/api/user/roles`,
const canAccess = await roleCheck(payload.user?.user_id); {
headers: { Cookie: cookieHeader },
},
);
return c.json( return c.json(
{ {
sucess: true, success: true,
message: `User ${payload.user?.username} can access`, message: `User ${user.username} can access`,
data: canAccess, data: res.data.data,
}, },
200 200,
); );
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
return c.json({ message: "UserRoles coming over" }); return c.json({ message: "UserRoles coming over" });
} },
); );
export default app; export default app;

View File

@@ -1,22 +1,22 @@
import { eq } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js"; import { db } from "../../../../../database/dbclient.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js"; import { settings } from "../../../../../database/schema/settings.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { siloQuery } from "../../../sqlServer/querys/silo/siloQuery.js";
import { postAdjustment } from "./postAdjustment.js";
import { siloAdjustments } from "../../../../../database/schema/siloAdjustments.js"; import { siloAdjustments } from "../../../../../database/schema/siloAdjustments.js";
import { greetingStuff } from "../../../../globalUtils/greetingEmail.js"; import { greetingStuff } from "../../../../globalUtils/greetingEmail.js";
import { sendEmail } from "../../../notifications/controller/sendMail.js";
import { settings } from "../../../../../database/schema/settings.js";
import { generateOneTimeKey } from "../../../../globalUtils/singleUseKey.js"; import { generateOneTimeKey } from "../../../../globalUtils/singleUseKey.js";
import { eq } from "drizzle-orm"; import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { sendEmail } from "../../../notifications/controller/sendMail.js";
import { import {
getSettings, getSettings,
serverSettings, serverSettings,
} from "../../../server/controller/settings/getSettings.js"; } from "../../../server/controller/settings/getSettings.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { siloQuery } from "../../../sqlServer/querys/silo/siloQuery.js";
import { postAdjustment } from "./postAdjustment.js";
export const createSiloAdjustment = async ( export const createSiloAdjustment = async (
data: any | null, data: any | null,
user: any | null user: any | null,
) => { ) => {
/** /**
* Creates a silo adjustment based off warehouse, location, and qty. * Creates a silo adjustment based off warehouse, location, and qty.
@@ -39,7 +39,7 @@ export const createSiloAdjustment = async (
const set = serverSettings.length === 0 ? [] : serverSettings; const set = serverSettings.length === 0 ? [] : serverSettings;
// getting stock data first so we have it prior to the adjustment // getting stock data first so we have it prior to the adjustment
const { data: s, error: stockError } = await tryCatch( const { data: s, error: stockError } = await tryCatch(
query(siloQuery, "Silo data Query") query(siloQuery, "Silo data Query"),
); );
if (stockError) { if (stockError) {
@@ -50,9 +50,7 @@ export const createSiloAdjustment = async (
}; };
} }
const stock: any = s?.data as any; const stock: any = s?.data as any;
const { data: a, error: errorAdj } = await tryCatch( const { data: a, error: errorAdj } = await tryCatch(postAdjustment(data));
postAdjustment(data, user.prod)
);
if (errorAdj) { if (errorAdj) {
return { return {
@@ -68,7 +66,7 @@ export const createSiloAdjustment = async (
const sa: any = a; const sa: any = a;
if (!sa.success) { if (!sa.success) {
console.log(`insde error`); console.log(`inside error`);
return { return {
success: sa.success, success: sa.success,
message: sa.message, message: sa.message,
@@ -98,7 +96,7 @@ export const createSiloAdjustment = async (
lastDateAdjusted: new Date(stockNummy[0].LastAdjustment), lastDateAdjusted: new Date(stockNummy[0].LastAdjustment),
add_user: user.username, add_user: user.username,
}) })
.returning({ id: siloAdjustments.siloAdjust_id }) .returning({ id: siloAdjustments.siloAdjust_id }),
); );
if (postAdjError) { if (postAdjError) {
@@ -144,7 +142,7 @@ export const createSiloAdjustment = async (
return { return {
success: adj.success, success: adj.success,
message: `Silo adjustmnet was completed you will also receive and email due to the adjustment having a variation of ${Math.abs( message: `Silo adjustmnet was completed you will also receive and email due to the adjustment having a variation of ${Math.abs(
theDiff theDiff,
).toFixed(2)}%`, ).toFixed(2)}%`,
data: adj.data, data: adj.data,
}; };

View File

@@ -2,7 +2,7 @@ import axios from "axios";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js"; import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js"; import { tryCatch } from "../../../../globalUtils/tryCatch.js";
export const postAdjustment = async (data: any, prod: any) => { export const postAdjustment = async (data: any) => {
if (data.warehouseId === undefined) { if (data.warehouseId === undefined) {
return { return {
sucess: false, sucess: false,
@@ -36,7 +36,7 @@ export const postAdjustment = async (data: any, prod: any) => {
}; };
let url = await prodEndpointCreation( let url = await prodEndpointCreation(
"/public/v1.0/Warehousing/AdjustSiloStockLevel" "/public/v1.0/Warehousing/AdjustSiloStockLevel",
); );
const { data: silo, error } = await tryCatch( const { data: silo, error } = await tryCatch(
@@ -45,7 +45,7 @@ export const postAdjustment = async (data: any, prod: any) => {
"X-API-Key": process.env.TEC_API_KEY || "", "X-API-Key": process.env.TEC_API_KEY || "",
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}) }),
); );
let e = error as any; let e = error as any;
if (e) { if (e) {
@@ -54,7 +54,7 @@ export const postAdjustment = async (data: any, prod: any) => {
const data = { const data = {
success: false, success: false,
message: `There was error posting the data: ${JSON.stringify( message: `There was error posting the data: ${JSON.stringify(
e.response?.data e.response?.data,
)}`, )}`,
data: { data: {
status: e.response?.status, status: e.response?.status,

View File

@@ -1,9 +1,10 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
import { verify } from "hono/jwt"; import { verify } from "hono/jwt";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { apiHit } from "../../../../globalUtils/apiHits.js"; import { apiHit } from "../../../../globalUtils/apiHits.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -20,6 +21,7 @@ app.openapi(
summary: "Post orders to DM", summary: "Post orders to DM",
method: "post", method: "post",
path: "/postbulkorders", path: "/postbulkorders",
middleware: authMiddleware,
// request: { // request: {
// body: { // body: {
// content: { // content: {
@@ -34,23 +36,14 @@ app.openapi(
async (c) => { async (c) => {
apiHit(c, { endpoint: "/postbulkorders" }); apiHit(c, { endpoint: "/postbulkorders" });
const body = await c.req.parseBody(); const body = await c.req.parseBody();
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
//console.log(body); // File | string //console.log(body); // File | string
// if (body["fileType"] === "standard") { // if (body["fileType"] === "standard") {
// console.log(`doing standard orders in.`); // console.log(`doing standard orders in.`);
// } // }
const { data: payload, error: pe } = await tryCatch(
verify(token, process.env.JWT_SECRET!)
);
if (pe) {
return c.json({ success: false, message: "Unauthorized" }, 401);
}
const { data: orders, error } = await tryCatch( const { data: orders, error } = await tryCatch(
ordersIn(body, payload.user) ordersIn(body, c.get("user")),
); );
if (error) { if (error) {
@@ -61,7 +54,7 @@ app.openapi(
message: "Error posting Orders", message: "Error posting Orders",
data: error, data: error,
}, },
400 400,
); );
} }
@@ -70,6 +63,6 @@ app.openapi(
message: orders?.message ?? "Error posting forecast", message: orders?.message ?? "Error posting forecast",
data: orders?.data ?? [], data: orders?.data ?? [],
}); });
} },
); );
export default app; export default app;

View File

@@ -1,10 +1,11 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
import { verify } from "hono/jwt"; import { verify } from "hono/jwt";
import { forecastIn } from "../../controller/dm/forecast/forecastIn.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { apiHit } from "../../../../globalUtils/apiHits.js"; import { apiHit } from "../../../../globalUtils/apiHits.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
import { forecastIn } from "../../controller/dm/forecast/forecastIn.js";
import { ordersIn } from "../../controller/dm/ordersIn/ordersIn.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -21,6 +22,7 @@ app.openapi(
summary: "Post forecast to DM", summary: "Post forecast to DM",
method: "post", method: "post",
path: "/postforecastin", path: "/postforecastin",
middleware: authMiddleware,
// request: { // request: {
// body: { // body: {
// content: { // content: {
@@ -35,23 +37,15 @@ app.openapi(
async (c) => { async (c) => {
apiHit(c, { endpoint: "/postforecastin" }); apiHit(c, { endpoint: "/postforecastin" });
const body = await c.req.parseBody(); const body = await c.req.parseBody();
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
//console.log(body); // File | string //console.log(body); // File | string
// if (body["fileType"] === "standard") { // if (body["fileType"] === "standard") {
// console.log(`doing standard orders in.`); // console.log(`doing standard orders in.`);
// } // }
const { data: payload, error: pe } = await tryCatch(
verify(token, process.env.JWT_SECRET!)
);
if (pe) {
return c.json({ success: false, message: "Unauthorized" }, 401);
}
const { data: orders, error } = await tryCatch( const { data: orders, error } = await tryCatch(
forecastIn(body, payload.user) forecastIn(body, c.get("user")),
); );
if (error) { if (error) {
@@ -62,7 +56,7 @@ app.openapi(
message: "Error posting forecast", message: "Error posting forecast",
data: error, data: error,
}, },
400 400,
); );
} }
@@ -71,6 +65,6 @@ app.openapi(
message: orders?.message ?? "Error posting forecast", message: orders?.message ?? "Error posting forecast",
data: orders?.data ?? [], data: orders?.data ?? [],
}); });
} },
); );
export default app; export default app;

View File

@@ -1,10 +1,10 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { format } from "date-fns"; import { format } from "date-fns";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { standardTemplate } from "../../controller/dm/ordersIn/createTemplate.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { standardForCastTemplate } from "../../controller/dm/forecast/createTemplate.js";
import { apiHit } from "../../../../globalUtils/apiHits.js"; import { apiHit } from "../../../../globalUtils/apiHits.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { standardForCastTemplate } from "../../controller/dm/forecast/createTemplate.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -36,7 +36,7 @@ app.openapi(
apiHit(c, { endpoint: "/bulkforcasttemplate" }); apiHit(c, { endpoint: "/bulkforcasttemplate" });
const defaultFilename = `bulkForcastTemplate-${format( const defaultFilename = `bulkForcastTemplate-${format(
new Date(Date.now()), new Date(Date.now()),
"M-d-yyyy" "M-d-yyyy",
)}.xlsx`; )}.xlsx`;
const filename = c.req.query("filename") || defaultFilename; const filename = c.req.query("filename") || defaultFilename;
const { data, error } = await tryCatch(standardForCastTemplate()); const { data, error } = await tryCatch(standardForCastTemplate());
@@ -62,6 +62,6 @@ app.openapi(
// message: data.message, // message: data.message,
// data: data.data, // data: data.data,
// }); // });
} },
); );
export default app; export default app;

View File

@@ -1,10 +1,10 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { verify } from "hono/jwt"; import { verify } from "hono/jwt";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
import { apiHit } from "../../../../globalUtils/apiHits.js"; import { apiHit } from "../../../../globalUtils/apiHits.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js"; import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -34,21 +34,17 @@ app.openapi(
message: "Missing data please try again", message: "Missing data please try again",
error, error,
}, },
400 400,
); );
} }
apiHit(c, { endpoint: "/createsiloadjustment", lastBody: data }); apiHit(c, { endpoint: "/createsiloadjustment", lastBody: data });
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || ""; const user = c.get("user");
try { try {
const payload = await verify(token, process.env.JWT_SECRET!);
try { try {
//return apiReturn(c, true, access?.message, access?.data, 200); //return apiReturn(c, true, access?.message, access?.data, 200);
const createSiloAdj = await createSiloAdjustment( const createSiloAdj = await createSiloAdjustment(data, c.get("user"));
data,
payload.user
);
return c.json( return c.json(
{ {
@@ -56,7 +52,7 @@ app.openapi(
message: createSiloAdj.message, message: createSiloAdj.message,
data: createSiloAdj.data, data: createSiloAdj.data,
}, },
200 200,
); );
} catch (error) { } catch (error) {
//console.log(error); //console.log(error);
@@ -67,12 +63,12 @@ app.openapi(
message: "Missing data please try again", message: "Missing data please try again",
error, error,
}, },
400 400,
); );
} }
} catch (error) { } catch (error) {
return c.json({ success: false, message: "Unauthorized" }, 401); return c.json({ success: false, message: "Unauthorized" }, 401);
} }
} },
); );
export default app; export default app;

View File

@@ -1,10 +1,10 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { verify } from "hono/jwt"; import { verify } from "hono/jwt";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js"; import { apiHit } from "../../../../globalUtils/apiHits.js";
import { responses } from "../../../../globalUtils/routeDefs/responses.js"; import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js"; import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js";
import { postSiloComment } from "../../controller/siloAdjustments/postComment.js"; import { postSiloComment } from "../../controller/siloAdjustments/postComment.js";
import { apiHit } from "../../../../globalUtils/apiHits.js";
const app = new OpenAPIHono(); const app = new OpenAPIHono();
@@ -44,12 +44,9 @@ app.openapi(
}), }),
async (c: any) => { async (c: any) => {
apiHit(c, { endpoint: "/postcomment" }); apiHit(c, { endpoint: "/postcomment" });
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
const { adjId } = c.req.valid("param"); const { adjId } = c.req.valid("param");
try { try {
const payload = await verify(token, process.env.JWT_SECRET!);
try { try {
//return apiReturn(c, true, access?.message, access?.data, 200); //return apiReturn(c, true, access?.message, access?.data, 200);
const data = await c.req.json(); const data = await c.req.json();
@@ -58,7 +55,7 @@ app.openapi(
adjId, adjId,
data.comment, data.comment,
data.key, data.key,
payload.user c.get("user"),
); );
console.log(addComment); console.log(addComment);
@@ -68,7 +65,7 @@ app.openapi(
message: addComment.message, message: addComment.message,
data: addComment.data, data: addComment.data,
}, },
200 200,
); );
} catch (error) { } catch (error) {
return c.json( return c.json(
@@ -77,12 +74,12 @@ app.openapi(
message: "Missing data please try again", message: "Missing data please try again",
error, error,
}, },
400 400,
); );
} }
} catch (error) { } catch (error) {
return c.json({ success: false, message: "Unauthorized" }, 401); return c.json({ success: false, message: "Unauthorized" }, 401);
} }
} },
); );
export default app; export default app;

View File

@@ -1,8 +1,10 @@
// an external way to creating logs // an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { getAllJobs } from "../utils/processNotifications.js";
import { apiHit } from "../../../globalUtils/apiHits.js"; import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import hasCorrectRole from "../../auth/middleware/roleCheck.js";
import { getAllJobs } from "../utils/processNotifications.js";
const app = new OpenAPIHono({ strict: false }); const app = new OpenAPIHono({ strict: false });
@@ -12,7 +14,7 @@ app.openapi(
summary: "Returns current active notifications.", summary: "Returns current active notifications.",
method: "get", method: "get",
path: "/activenotifications", path: "/activenotifications",
//middleware: authMiddleware, middleware: [authMiddleware, hasCorrectRole(["systemAdmin"], "admin")],
responses: responses(), responses: responses(),
}), }),
async (c) => { async (c) => {
@@ -26,6 +28,6 @@ app.openapi(
: "Current Active notifications", : "Current Active notifications",
data: jobs, data: jobs,
}); });
} },
); );
export default app; export default app;

View File

@@ -6,6 +6,7 @@
import { db } from "../../../../database/dbclient.js"; import { db } from "../../../../database/dbclient.js";
import { subModules } from "../../../../database/schema/subModules.js"; import { subModules } from "../../../../database/schema/subModules.js";
import { createLog } from "../../logger/logger.js"; import { createLog } from "../../logger/logger.js";
// "view", "technician", "supervisor","manager", "admin", "systemAdmin" // "view", "technician", "supervisor","manager", "admin", "systemAdmin"
const newSubModules = [ const newSubModules = [
{ {
@@ -26,9 +27,9 @@ const newSubModules = [
subSubModule: [], subSubModule: [],
}, },
{ {
name: "Silo Adjustments", name: "siloAdjustments",
moduleName: "logistics", moduleName: "logistics",
description: "Do a silo adjustmnet", description: "Do a silo adjustments",
link: "/siloAdjustments", link: "/siloAdjustments",
icon: "Cylinder", icon: "Cylinder",
active: false, active: false,
@@ -36,7 +37,7 @@ const newSubModules = [
subSubModule: [], subSubModule: [],
}, },
{ {
name: "Demand Management", name: "demandManagement",
moduleName: "logistics", moduleName: "logistics",
description: "Bulk order and Forecast imports", description: "Bulk order and Forecast imports",
link: "/dm", link: "/dm",
@@ -244,7 +245,7 @@ export const areSubModulesIn = async () => {
"info", "info",
"lst", "lst",
"server", "server",
"SubModules were just added due to missing them on server startup" "SubModules were just added due to missing them on server startup",
); );
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@@ -252,7 +253,7 @@ export const areSubModulesIn = async () => {
"error", "error",
"lst", "lst",
"server", "server",
"There was an error adding new subModules to the db" "There was an error adding new subModules to the db",
); );
} }
}; };