From eb3fa4dd528427da49e2212bfa304ef9cdb06cc2 Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Tue, 21 Oct 2025 20:22:21 -0500 Subject: [PATCH] refactor(old app): login migration to new app --- .../src/components/admin/user/UserPage.tsx | 44 +- .../src/components/auth/LoginForm.tsx | 305 +++++------ .../src/components/layout/lst-sidebar.tsx | 98 ++-- .../layout/side-components/logistics.tsx | 101 ++-- .../logistics/siloAdjustments/SiloCard.tsx | 440 ++++++++-------- .../src/components/production/ocp/Lots.tsx | 485 +++++++++-------- .../src/components/providers/Providers.tsx | 79 ++- lstV2/frontend/src/hooks/useLogout.ts | 25 +- lstV2/frontend/src/hooks/useSession.ts | 119 +++-- lstV2/frontend/src/lib/store/sessionStore.ts | 69 +-- lstV2/frontend/src/lib/store/useAuthStore.ts | 15 + lstV2/frontend/src/lib/store/useGetRoles.ts | 55 +- lstV2/frontend/src/utils/userAccess.ts | 70 +-- lstV2/server/index.ts | 220 ++++---- .../auth/middleware/authMiddleware.ts | 91 ++-- .../services/auth/middleware/roleCheck.ts | 178 ++++--- lstV2/server/services/auth/routes/login.ts | 180 ++++--- lstV2/server/services/auth/routes/session.ts | 217 ++++---- .../services/auth/routes/user/getUserRoles.ts | 95 ++-- .../siloAdjustments/createSiloAdjustment.ts | 258 +++++---- .../siloAdjustments/postAdjustment.ts | 178 +++---- .../logistics/route/dm/bulkOrdersIn.ts | 103 ++-- .../services/logistics/route/dm/forecastIn.ts | 104 ++-- .../route/dm/getStandardForecastTemplate.ts | 96 ++-- .../siloAdjustments/createSiloAdjustment.ts | 120 +++-- .../route/siloAdjustments/postComment.ts | 133 +++-- .../routes/getActiveNotifications.ts | 46 +- .../services/server/utils/subModuleCheck.ts | 489 +++++++++--------- 28 files changed, 2273 insertions(+), 2140 deletions(-) create mode 100644 lstV2/frontend/src/lib/store/useAuthStore.ts diff --git a/lstV2/frontend/src/components/admin/user/UserPage.tsx b/lstV2/frontend/src/components/admin/user/UserPage.tsx index 6338fc2..72e0778 100644 --- a/lstV2/frontend/src/components/admin/user/UserPage.tsx +++ b/lstV2/frontend/src/components/admin/user/UserPage.tsx @@ -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() { - const { data, isError, error, isLoading } = useQuery(getUsers()); + //const { data, isError, error, isLoading } = useQuery(getUsers()); - if (isLoading) return
Loading users...
; + // if (isLoading) return
Loading users...
; - if (isError) - return ( -
- There was an error getting the users.... {JSON.stringify(error)} -
- ); + // if (isError) + // return ( + //
+ // There was an error getting the users.... {JSON.stringify(error)} + //
+ // ); - return ( -
- {data.map((u: any) => { - return ( -
- -
- ); - })} -
- ); + return ( +
+ This has been moved to the new system + {/* {data.map((u: any) => { + return ( +
+ + +
+ ); + })} */} +
+ ); } diff --git a/lstV2/frontend/src/components/auth/LoginForm.tsx b/lstV2/frontend/src/components/auth/LoginForm.tsx index 26bc3a7..22bde4a 100644 --- a/lstV2/frontend/src/components/auth/LoginForm.tsx +++ b/lstV2/frontend/src/components/auth/LoginForm.tsx @@ -1,172 +1,177 @@ -import { useSessionStore } from "../../lib/store/sessionStore"; -import { LstCard } from "../extendedUI/LstCard"; -import { CardHeader } from "../ui/card"; -import { toast } from "sonner"; -import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; import { useRouter, useSearch } from "@tanstack/react-router"; import { Controller, useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { Label } from "../ui/label"; -import { Input } from "../ui/input"; -import { Checkbox } from "../ui/checkbox"; +import { toast } from "sonner"; +import { z } from "zod"; +import { useAuthStore } from "@/lib/store/useAuthStore"; +import { useSessionStore } from "../../lib/store/sessionStore"; +import { LstCard } from "../extendedUI/LstCard"; 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({ - username: z.string().min(1, "You must enter a valid username"), - password: z.string().min(4, "You must enter a valid password"), - rememberMe: z.boolean(), + username: z.string().min(1, "You must enter a valid username"), + password: z.string().min(4, "You must enter a valid password"), + rememberMe: z.boolean(), }); const LoginForm = () => { - const { setSession } = useSessionStore(); - const rememeberMe = localStorage.getItem("rememberMe") === "true"; - const username = localStorage.getItem("username") || ""; - const router = useRouter(); - const search = useSearch({ from: "/login" }); + const { setSession } = useSessionStore(); + const { setUserInfo } = useAuthStore(); + const rememeberMe = localStorage.getItem("rememberMe") === "true"; + const username = localStorage.getItem("username") || ""; + const router = useRouter(); + const search = useSearch({ from: "/login" }); - const { - register, - handleSubmit, - control, - formState: { errors }, - } = useForm>({ - resolver: zodResolver(FormSchema), - defaultValues: { - username: username || "", - password: "", - rememberMe: rememeberMe, - }, - }); + const { + register, + handleSubmit, + control, + formState: { errors }, + } = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + username: username || "", + password: "", + rememberMe: rememeberMe, + }, + }); - const onSubmitLogin = async (value: z.infer) => { - // Do something with form data + const onSubmitLogin = async (value: z.infer) => { + // Do something with form data - // first update the rememberMe incase it was selected - if (value.rememberMe) { - localStorage.setItem("rememberMe", value.rememberMe.toString()); - localStorage.setItem("username", value.username); - } else { - localStorage.removeItem("rememberMe"); - localStorage.removeItem("username"); - } + // first update the rememberMe incase it was selected + if (value.rememberMe) { + localStorage.setItem("rememberMe", value.rememberMe.toString()); + localStorage.setItem("username", value.username); + } else { + localStorage.removeItem("rememberMe"); + localStorage.removeItem("username"); + } - try { - const response = await fetch("/api/auth/login", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - username: value.username, - password: value.password, - }), - }); + try { + const response = await fetch("/api/auth/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + username: value.username, + password: value.password, + }), + }); - const data = await response.json(); + const data = await response.json(); - // Store token in localStorage - // localStorage.setItem("auth_token", data.data.token); - if (data.success) { - const prod = btoa( - `${value.username.toLowerCase()}:${value.password}` - ); - const prodUser = { ...data.user, prod: prod }; + // Store token in localStorage + // localStorage.setItem("auth_token", data.data.token); + if (data.success) { + const prod = btoa(`${value.username.toLowerCase()}:${value.password}`); + 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); - toast.success(`You are logged in as ${data.user.username}`); + //console.log(search.redirect ? search.redirect : "oops"); + router.history.push(search.redirect ? search.redirect : "/"); + } - console.log(search.redirect ? search.redirect : "oops"); - router.history.push(search.redirect ? search.redirect : "/"); - } + if (!data.success) { + toast.error(`${data.message}`); + } - if (!data.success) { - toast.error(`${data.message}`); - } + //console.log(data); + } catch (err) { + // @ts-ignore + if (!err.response.success) { + // @ts-ignore + toast.error(err.response.data.message); + } else { + // @ts-ignore + toast.error(err?.message); + } + } + }; - //console.log(data); - } catch (err) { - toast.error("Invalid credentials"); - } - }; + return ( +
+ + +
+

Login to LST

+
+
+
+
+
+ + + {errors.username && ( +

+ {errors.username.message} +

+ )} +
+
+ <> + + + {errors.password && ( +

+ {errors.password.message} +

+ )} + +
+
+
+ ( + <> + + + + )} + control={control} + name="rememberMe" + defaultValue={rememeberMe} + /> +
- return ( -
- - -
-

Login to LST

-
-
-
- -
- - - {errors.username && ( -

- {errors.username.message} -

- )} -
-
- <> - - - {errors.password && ( -

- {errors.password.message} -

- )} - -
-
-
- ( - <> - - - - )} - control={control} - name="rememberMe" - defaultValue={rememeberMe} - /> -
- -
- -
-
- -
-
- ); +
+ +
+
+ +
+
+ ); }; export default LoginForm; diff --git a/lstV2/frontend/src/components/layout/lst-sidebar.tsx b/lstV2/frontend/src/components/layout/lst-sidebar.tsx index 45926fd..bdc66d8 100644 --- a/lstV2/frontend/src/components/layout/lst-sidebar.tsx +++ b/lstV2/frontend/src/components/layout/lst-sidebar.tsx @@ -1,61 +1,55 @@ +import { useSessionStore } from "../../lib/store/sessionStore"; +import { useModuleStore } from "../../lib/store/useModuleStore"; +import { moduleActive } from "../../utils/moduleActive"; +import { hasAccess } from "../../utils/userAccess"; import { - Sidebar, - SidebarContent, - SidebarFooter, - SidebarTrigger, + Sidebar, + SidebarContent, + SidebarFooter, + SidebarTrigger, } 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 { LogisticsSideBar } from "./side-components/logistics"; +import { ProductionSideBar } from "./side-components/production"; 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() { - const { user } = useSessionStore(); - const { modules } = useModuleStore(); + const { user } = useSessionStore(); + const { modules } = useModuleStore(); - return ( - - -
- {moduleActive("production") && ( - n.name === "production")[0] - .module_id as string - } - /> - )} - {moduleActive("logistics") && ( - n.name === "logistics")[0] - .module_id as string - } - /> - )} - {moduleActive("forklift") && - hasAccess(user, "forklift", modules) && } - {moduleActive("eom") && hasAccess(user, "eom", modules) && ( - - )} - {moduleActive("quality") && - hasAccess(user, "quality", modules) && } - {moduleActive("admin") && hasAccess(user, "admin", modules) && ( - - )} - - - - - - ); + return ( + + +
+ {moduleActive("production") && ( + n.name === "production")[0] + .module_id as string + } + /> + )} + {moduleActive("logistics") && hasAccess(user, "logistics") && ( + + )} + {moduleActive("forklift") && hasAccess(user, "forklift") && ( + + )} + {moduleActive("eom") && hasAccess(user, "eom") && } + {moduleActive("quality") && hasAccess(user, "quality") && ( + + )} + {moduleActive("admin") && hasAccess(user || [], "admin") && ( + + )} + + + + + + ); } diff --git a/lstV2/frontend/src/components/layout/side-components/logistics.tsx b/lstV2/frontend/src/components/layout/side-components/logistics.tsx index 892a8b1..78ef02c 100644 --- a/lstV2/frontend/src/components/layout/side-components/logistics.tsx +++ b/lstV2/frontend/src/components/layout/side-components/logistics.tsx @@ -1,64 +1,53 @@ -import { Barcode, Cylinder, Package, Truck, Command } from "lucide-react"; -import { - SidebarGroup, - SidebarGroupContent, - SidebarGroupLabel, - SidebarMenu, - SidebarMenuButton, - SidebarMenuItem, -} from "../../ui/sidebar"; -import { hasPageAccess } from "@/utils/userAccess"; -import { User } from "@/types/users"; +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 { + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from "../../ui/sidebar"; const iconMap: any = { - Package: Package, - Truck: Truck, - Cylinder: Cylinder, - Barcode: Barcode, - Command: Command, + Package: Package, + Truck: Truck, + Cylinder: Cylinder, + Barcode: Barcode, + Command: Command, }; -export function LogisticsSideBar({ - user, - moduleID, -}: { - user: User | null; - moduleID: string; -}) { - const { subModules } = useSubModuleStore(); +export function LogisticsSideBar({ user }: { user: User | null }) { + const { subModules } = useSubModuleStore(); - const items = subModules.filter((m) => m.moduleName === "logistics"); + const items = subModules.filter((m) => m.moduleName === "logistics"); - return ( - - Logistics - - - {items.map((item) => { - const Icon = iconMap[item.icon]; - return ( - - <> - {hasPageAccess( - user, - item.roles, - moduleID - ) && - item.active && ( - - - - {item.name} - - - )} - - - ); - })} - - - - ); + return ( + + Logistics + + + {items.map((item) => { + const Icon = iconMap[item.icon]; + return ( + + <> + {hasPageAccess(user, item.roles, item.name) && ( + + + + {item.name} + + + )} + + + ); + })} + + + + ); } diff --git a/lstV2/frontend/src/components/logistics/siloAdjustments/SiloCard.tsx b/lstV2/frontend/src/components/logistics/siloAdjustments/SiloCard.tsx index 1b788f1..e9b17b5 100644 --- a/lstV2/frontend/src/components/logistics/siloAdjustments/SiloCard.tsx +++ b/lstV2/frontend/src/components/logistics/siloAdjustments/SiloCard.tsx @@ -1,15 +1,3 @@ -import { LstCard } from "@/components/extendedUI/LstCard"; -import { Button } from "@/components/ui/button"; -import { CardHeader } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} 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"; @@ -18,246 +6,222 @@ 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 { LstCard } from "@/components/extendedUI/LstCard"; +import { Button } from "@/components/ui/button"; +import { CardHeader } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { useSessionStore } from "@/lib/store/sessionStore"; -import { useModuleStore } from "@/lib/store/useModuleStore"; 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) { - const token = localStorage.getItem("auth_token"); - const [submitting, setSubmitting] = useState(false); - const { refetch } = useQuery(getStockSilo()); - const { user } = useSessionStore(); - const { userRoles } = useGetUserRoles(); - const { modules } = useModuleStore(); - const silo = data.silo; + const [submitting, setSubmitting] = useState(false); + const { refetch } = useQuery(getStockSilo()); + const { user } = useSessionStore(); + const { userRoles } = useGetUserRoles(); + const { modules } = useModuleStore(); + const silo = data.silo; - // roles that can do the silo adjustments - const roles = ["systemAdmin", "technician", "admin", "manager"]; + // roles that can do the silo adjustments + const roles = ["systemAdmin", "technician", "admin", "manager"]; - const module = modules.filter((n) => n.name === "logistics"); + const module = modules.filter((n) => n.name === "logistics"); - const accessRoles = userRoles.filter( - (n) => n.module_id === module[0]?.module_id - ) as any; + const accessRoles = userRoles.filter( + (n: any) => n.module === module[0]?.name, + ) as any; - const form = useForm({ - defaultValues: { - newLevel: "", - }, - onSubmit: async ({ value }) => { - setSubmitting(true); - const dataToSubmit = { - quantity: parseFloat(value.newLevel), - warehouseId: silo.WarehouseID, - laneId: silo.LocationID, - }; + const form = useForm({ + defaultValues: { + newLevel: "", + }, + onSubmit: async ({ value }) => { + setSubmitting(true); + const dataToSubmit = { + quantity: parseFloat(value.newLevel), + warehouseId: silo.WarehouseID, + laneId: silo.LocationID, + }; - try { - const res = await axios.post( - "/api/logistics/createsiloadjustment", - dataToSubmit, - { headers: { Authorization: `Bearer ${token}` } } - ); - //console.log(res.data); + try { + const res = await axios.post( + "/api/logistics/createsiloadjustment", + dataToSubmit, + { withCredentials: true }, + ); + //console.log(res.data); - if (res.data.success) { - toast.success(res.data.message); - refetch(); - form.reset(); - } - if (!res.data.success && res.data.data?.status === 400) { - if (res.data.data.status === 400) { - toast.error(res.data.data.data.errors[0].message); - } - } else if (!res.data.success) { - toast.error(res.data.message); - } - setSubmitting(false); - } catch (error: any) { - //console.log(error); - if (error.status === 401) { - toast.error(error.response.statusText); - setSubmitting(false); - } - } - }, - }); + if (res.data.success) { + toast.success(res.data.message); + refetch(); + form.reset(); + } + if (!res.data.success && res.data.data?.status === 400) { + if (res.data.data.status === 400) { + toast.error(res.data.data.data.errors[0].message); + } + } else if (!res.data.success) { + toast.error(res.data.message); + } + setSubmitting(false); + } catch (error: any) { + //console.log(error); + if (error.status === 401) { + toast.error(error.response.statusText); + setSubmitting(false); + } + } + }, + }); - console.log(accessRoles); - return ( - -
- - {silo.Description} -
-
- Current Stock: - {silo.Stock_Total} -
- Last date adjusted - {format(silo.LastAdjustment, "M/dd/yyyy")} -
-
-
- {silo.Stock_Total === 0 ? ( -
- - The silo is currently empty you will not be - able to do an adjustment until you have - received material in. - -
-
    -
  • - -Someone click "Take inventory on a - empty location" in stock. -
  • -
  • - -Silo virtualy ran empty due to - production over consumption. -
  • -
  • - -Someone forgot to move a railcar - compartment over to this location. -
  • -
-
- ) : ( - <> - {user && - roles.includes(accessRoles[0]?.role) && ( -
{ - e.preventDefault(); - e.stopPropagation(); - }} - > - - value.length > 1 - ? undefined - : "You must enter a value greate than 1", - }} - children={(field) => { - return ( -
-
- -
- -
-
-
- - field.handleChange( - e - .target - .value - ) - } - /> - -
+ return ( + +
+ + {silo.Description} +
+
+ Current Stock: + {silo.Stock_Total} +
+ Last date adjusted + {format(silo.LastAdjustment, "M/dd/yyyy")} +
+
+
+ {silo.Stock_Total === 0 ? ( +
+ + The silo is currently empty you will not be able to do an + adjustment until you have received material in. + +
+
    +
  • + -Someone click "Take inventory on a empty location" in + stock. +
  • +
  • + -Silo virtualy ran empty due to production over consumption. +
  • +
  • + -Someone forgot to move a railcar compartment over to this + location. +
  • +
+
+ ) : ( + <> + {user && roles.includes(accessRoles[0]?.role) && ( + { + e.preventDefault(); + e.stopPropagation(); + }} + > + + value.length > 1 + ? undefined + : "You must enter a value greate than 1", + }} + children={(field) => { + return ( +
+
+ +
+ +
+
+
+ + field.handleChange(e.target.value) + } + /> + +
- {field.state.meta - .errors - .length ? ( - - {field.state.meta.errors.join( - "," - )} - - ) : null} -
- ); - }} - /> - - )} - - )} -
-
-
- + {field.state.meta.errors.length ? ( + {field.state.meta.errors.join(",")} + ) : null} +
+ ); + }} + /> + + )} + + )} +
+
+
+ -
- - - -
-
-
- - ); +
+ + + +
+
+
+
+ ); } const Disclaimer = () => { - return ( - - - - - - -

- If you have had this page open for a period of time - before submitting your data, there is a chance that the - stock levels will be different from the ones you see - above -

-
-
-
- ); + return ( + + + + + + +

+ If you have had this page open for a period of time before + submitting your data, there is a chance that the stock levels will + be different from the ones you see above +

+
+
+
+ ); }; diff --git a/lstV2/frontend/src/components/production/ocp/Lots.tsx b/lstV2/frontend/src/components/production/ocp/Lots.tsx index e4cb203..588d209 100644 --- a/lstV2/frontend/src/components/production/ocp/Lots.tsx +++ b/lstV2/frontend/src/components/production/ocp/Lots.tsx @@ -1,273 +1,256 @@ +import { useQuery } from "@tanstack/react-query"; import { LstCard } from "@/components/extendedUI/LstCard"; - +import { ScrollArea } from "@/components/ui/scroll-area"; import { Skeleton } from "@/components/ui/skeleton"; import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, } from "@/components/ui/table"; 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 { LotType } from "@/types/lots"; import { getlots } from "@/utils/querys/production/lots"; -import { useQuery } from "@tanstack/react-query"; import ManualPrint from "./ManualPrinting/ManualPrint"; 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 = [ - { - key: "MachineDescription", - label: "Machine", - }, - { - key: "AV", - label: "AV", - }, - { - key: "Alias", - label: "AvDescription", - }, - { - key: "lot", - label: "LotNumber", - }, - { - key: "ProlinkLot", - label: "ProlinkLot", - }, - { - key: "PlannedQTY", - label: "PlannedQTY", - }, - { - key: "Produced", - label: "Produced", - }, - { - key: "Remaining", - label: "Remaining", - }, - { - key: "overPrinting", - label: "Overprinting", - }, - // { - // key: "lastProlinkUpdate", - // label: "Last ProlinkCheck", - // }, - // { - // key: "printLabel", - // label: "Print Label", - // }, + { + key: "MachineDescription", + label: "Machine", + }, + { + key: "AV", + label: "AV", + }, + { + key: "Alias", + label: "AvDescription", + }, + { + key: "lot", + label: "LotNumber", + }, + { + key: "ProlinkLot", + label: "ProlinkLot", + }, + { + key: "PlannedQTY", + label: "PlannedQTY", + }, + { + key: "Produced", + label: "Produced", + }, + { + key: "Remaining", + label: "Remaining", + }, + { + key: "overPrinting", + label: "Overprinting", + }, + // { + // key: "lastProlinkUpdate", + // label: "Last ProlinkCheck", + // }, + // { + // key: "printLabel", + // label: "Print Label", + // }, ]; export default function Lots() { - const { data, isError, isLoading } = useQuery(getlots()); - const { user } = useSessionStore(); - const { settings } = useSettingStore(); - const { userRoles } = useGetUserRoles(); - const { modules } = useModuleStore(); + const { data, isError, isLoading } = useQuery(getlots()); + const { user } = useSessionStore(); + const { settings } = useSettingStore(); + const { userRoles } = useGetUserRoles(); + const { modules } = useModuleStore(); - const server = settings.filter((n) => n.name === "server")[0]?.value || ""; + const server = settings.filter((n) => n.name === "server")[0]?.value || ""; - const roles = ["systemAdmin", "technician", "admin", "manager", "operator"]; - const lotdata = data ? data : []; + const roles = ["systemAdmin", "technician", "admin", "manager", "operator"]; + const lotdata = data ? data : []; - const module = modules.filter((n) => n.name === "logistics"); + const module = modules.filter((n) => n.name === "logistics"); - const accessRoles = userRoles.filter( - (n) => n.module_id === module[0]?.module_id - ) as any; + const accessRoles = userRoles.filter( + (n: any) => n.module === module[0]?.name, + ) as any; - if (user && roles.includes(accessRoles[0]?.role)) { - //width = 1280; - const checkCol = lotColumns.some((l) => l.key === "printLabel"); - if (!checkCol) { - lotColumns = [ - ...lotColumns, - { - key: "printLabel", - label: "Print Label", - }, - ]; - } - } + if (user && roles.includes(accessRoles[0]?.role)) { + //width = 1280; + const checkCol = lotColumns.some((l) => l.key === "printLabel"); + if (!checkCol) { + lotColumns = [ + ...lotColumns, + { + key: "printLabel", + label: "Print Label", + }, + ]; + } + } - if (isError) { - return ( -
- - -

Current Assigned lots

- - - - {lotColumns.map((l) => ( - - {l.label} - - ))} - - + if (isError) { + return ( +
+ + +

Current Assigned lots

+
+ + + {lotColumns.map((l) => ( + {l.label} + ))} + + - - {Array(10) - .fill(0) - .map((_, i) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ))} - -
-
-
-
- ); - } - return ( - - -

Current Assigned lots

- - - - {lotColumns.map((l) => ( - {l.label} - ))} - - - {isLoading ? ( - <> - - {Array(10) - .fill(0) - .map((_, i) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ))} - - - ) : ( - - {lotdata.map((lot: LotType) => ( - - - {lot.MachineLocation} - - - {lot.AV} - - - {lot.Alias} - - - {lot.lot} - - - {lot.ProlinkLot} - - - {lot.PlannedQTY} - - - {lot.Produced} - - - {lot.Remaining} - - - {lot.overPrinting} - - {user && - roles.includes( - accessRoles[0]?.role - ) && ( - <> - {server === "usday1vms006" || - server === "localhost" ? ( - <> - - - - - ) : ( - - - - )} - - )} - - ))} - - )} -
-
-
- ); + + {Array(10) + .fill(0) + .map((_, i) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + + + + + ); + } + return ( + + +

Current Assigned lots

+ + + + {lotColumns.map((l) => ( + {l.label} + ))} + + + {isLoading ? ( + <> + + {Array(10) + .fill(0) + .map((_, i) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + + ) : ( + + {lotdata.map((lot: LotType) => ( + + + {lot.MachineLocation} + + {lot.AV} + {lot.Alias} + + {lot.lot} + + + {lot.ProlinkLot} + + + {lot.PlannedQTY} + + {lot.Produced} + {lot.Remaining} + + {lot.overPrinting} + + {user && roles.includes(accessRoles[0]?.role) && ( + <> + {server === "usday1vms006" || server === "localhost" ? ( + <> + + + + + ) : ( + + + + )} + + )} + + ))} + + )} +
+
+
+ ); } diff --git a/lstV2/frontend/src/components/providers/Providers.tsx b/lstV2/frontend/src/components/providers/Providers.tsx index 5e7a548..b3a38a7 100644 --- a/lstV2/frontend/src/components/providers/Providers.tsx +++ b/lstV2/frontend/src/components/providers/Providers.tsx @@ -1,32 +1,67 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { useModuleStore } from "../../lib/store/useModuleStore"; 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 { useSettingStore } from "@/lib/store/useSettings"; import { useSubModuleStore } from "@/lib/store/useSubModuleStore"; +import { useModuleStore } from "../../lib/store/useModuleStore"; const queryClient = new QueryClient(); -export const SessionProvider = ({ - children, -}: { - children: React.ReactNode; -}) => { - const { fetchModules } = useModuleStore(); - const { fetchSettings } = useSettingStore(); - const { fetchUserRoles } = useGetUserRoles(); - const { fetchSubModules } = useSubModuleStore(); +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, + }), + }); - useEffect(() => { - fetchModules(); - fetchSettings(); - fetchUserRoles(); - fetchSubModules(); - }, []); + const data = await response.json(); - return ( - - {children} - - ); + // 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 = ({ + children, +}: { + children: React.ReactNode; +}) => { + const { fetchModules } = useModuleStore(); + const { fetchSettings } = useSettingStore(); + const { fetchUserRoles } = useGetUserRoles(); + const { fetchSubModules } = useSubModuleStore(); + const { username, password } = useAuthStore(); + + useEffect(() => { + if (username !== "") { + reAuth(username, password); + } + + fetchModules(); + fetchSettings(); + fetchUserRoles(); + fetchSubModules(); + }, []); + + return ( + {children} + ); }; diff --git a/lstV2/frontend/src/hooks/useLogout.ts b/lstV2/frontend/src/hooks/useLogout.ts index 728709c..206e578 100644 --- a/lstV2/frontend/src/hooks/useLogout.ts +++ b/lstV2/frontend/src/hooks/useLogout.ts @@ -1,16 +1,19 @@ -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 = () => { - const {clearSession} = useSessionStore(); - const router = useRouter(); - const logout = async () => { - router.invalidate(); - router.clearCache(); - clearSession(); + const { clearSession } = useSessionStore(); + const { clearUser } = useAuthStore(); + const router = useRouter(); + const logout = async () => { + router.invalidate(); + router.clearCache(); + clearSession(); + clearUser(); - window.location.reload(); - }; + window.location.reload(); + }; - return logout; + return logout; }; diff --git a/lstV2/frontend/src/hooks/useSession.ts b/lstV2/frontend/src/hooks/useSession.ts index 7c30b88..90e3fbf 100644 --- a/lstV2/frontend/src/hooks/useSession.ts +++ b/lstV2/frontend/src/hooks/useSession.ts @@ -1,60 +1,87 @@ import { useQuery } from "@tanstack/react-query"; -import { useSessionStore } from "../lib/store/sessionStore"; +import axios from "axios"; import { useEffect } from "react"; +import { useSessionStore } from "../lib/store/sessionStore"; const fetchSession = async () => { - const token = localStorage.getItem("auth_token"); + const token = localStorage.getItem("auth_token"); - if (!token) { - throw new Error("No token found"); - } + if (!token) { + throw new Error("No token found"); + } + try { + const res = await axios.get("/api/auth/session", { + headers: { + "Content-Type": "application/json", + }, + withCredentials: true, + }); - const res = await fetch("/api/auth/session", { - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - }); - // console.log(res); - if (!res.ok) { - 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"); + if (res.status === 401) { + 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"); - } + 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 = () => { - const { setSession, clearSession, token } = useSessionStore(); + const { setSession, clearSession, token } = useSessionStore(); - // Fetch session only if token is available - const { data, status, error } = useQuery({ - queryKey: ["session"], - queryFn: fetchSession, - enabled: !!token, // Prevents query if token is null - staleTime: 60 * 1000, - gcTime: 10 * 60 * 1000, // 10 mins - refetchOnWindowFocus: true, - //refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes - }); - useEffect(() => { - if (data) { - setSession(data.data.user, data.data.token); - } - if (error) { - clearSession(); - } - }, [data, error]); + // Fetch session only if token is available + const { data, status, error } = useQuery({ + queryKey: ["session"], + queryFn: fetchSession, + enabled: !!token, // Prevents query if token is null + staleTime: 60 * 1000, + //gcTime: 10 * 60 * 1000, // 10 mins + refetchOnWindowFocus: true, + refetchInterval: 1000 * 60 * 2, // Auto-refetch every 2 minutes + }); + useEffect(() => { + if (data) { + setSession(data.data.user, data.data.token); + } + if (error) { + clearSession(); + } + }, [data, error]); - return { - session: data && token ? { user: data.user, token: data.token } : null, - status, - error, - }; + return { + session: data && token ? { user: data.user, token: data.token } : null, + status, + error, + }; }; diff --git a/lstV2/frontend/src/lib/store/sessionStore.ts b/lstV2/frontend/src/lib/store/sessionStore.ts index 669320e..222619e 100644 --- a/lstV2/frontend/src/lib/store/sessionStore.ts +++ b/lstV2/frontend/src/lib/store/sessionStore.ts @@ -1,43 +1,52 @@ -import {User} from "@/types/users"; import axios from "axios"; -import {create} from "zustand"; +import { create } from "zustand"; +import { User } from "@/types/users"; export type SessionState = { - user: User | null; - token: string | null; - setSession: (user: User | null, token: string | null) => void; - clearSession: () => void; + user: User | null; + token: string | null; + setSession: (user: User | null, token: string | null) => void; + clearSession: () => void; }; export const useSessionStore = create((set) => { - // Initialize token from localStorage, but user remains in memory only - const storedToken = localStorage.getItem("auth_token"); + // Initialize token from localStorage, but user remains in memory only + const storedToken = localStorage.getItem("auth_token"); - return { - user: null, // User is NOT stored in localStorage - token: storedToken || null, + return { + user: null, // User is NOT stored in localStorage + token: storedToken || null, - setSession: async (user: any, token) => { - if (token) { - localStorage.setItem("auth_token", token); - const response = await axios.get("/api/auth/getuseraccess", { - headers: {Authorization: `Bearer ${token}`}, - }); - const data = response.data; //await response.json(); - user = {...user, roles: data.data}; - } else { - localStorage.removeItem("auth_token"); - } + setSession: async (user: any, token) => { + if (token) { + localStorage.setItem("auth_token", token); + const response = await axios.get("/api/auth/session", { + withCredentials: true, + }); + const userRoles = await axios.get("/api/auth/getuseraccess", { + withCredentials: true, + }); + const data = response.data; //await response.json(); - //console.log("Setting session:", {user, token}); - set({user, token}); - }, + const rawUser = data.data.user; + // user.map((u: any) => ({ + // ...u, + // roles: userRoles.data.data, + // })); + user = { ...rawUser, roles: userRoles.data.data }; + } else { + localStorage.removeItem("auth_token"); + } - clearSession: () => { - localStorage.removeItem("auth_token"); - set({user: null, token: null}); - }, - }; + //console.log("Setting session:", {user, token}); + set({ user, token }); + }, + + clearSession: () => { + localStorage.removeItem("auth_token"); + set({ user: null, token: null }); + }, + }; }); export type SessionType = ReturnType; diff --git a/lstV2/frontend/src/lib/store/useAuthStore.ts b/lstV2/frontend/src/lib/store/useAuthStore.ts new file mode 100644 index 0000000..bb3c5d2 --- /dev/null +++ b/lstV2/frontend/src/lib/store/useAuthStore.ts @@ -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()((set) => ({ + username: "", + password: "", + setUserInfo: (username, password) => set({ username, password }), + clearUser: () => set({ username: "", password: "" }), +})); diff --git a/lstV2/frontend/src/lib/store/useGetRoles.ts b/lstV2/frontend/src/lib/store/useGetRoles.ts index 0744b04..bb460f5 100644 --- a/lstV2/frontend/src/lib/store/useGetRoles.ts +++ b/lstV2/frontend/src/lib/store/useGetRoles.ts @@ -1,38 +1,41 @@ +import axios from "axios"; import { create } from "zustand"; import { Modules } from "@/types/modules"; -import axios from "axios"; interface SettingState { - userRoles: Modules[]; + userRoles: Modules[]; - fetchUserRoles: () => Promise; - setUserRoles: (userRoles: Modules[]) => void; + fetchUserRoles: () => Promise; + setUserRoles: (userRoles: Modules[]) => void; } interface FetchModulesResponse { - data: Modules[]; + data: Modules[]; } export const useGetUserRoles = create()((set) => ({ - userRoles: [], - setUserRoles: (userRoles) => set({ userRoles }), - fetchUserRoles: async () => { - try { - //const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`); - const token = localStorage.getItem("auth_token"); - if (token) { - const response = await axios.get("/api/auth/getuseraccess", { - headers: { Authorization: `Bearer ${token}` }, - }); - const data: FetchModulesResponse = response.data; //await response.json(); + userRoles: [], + setUserRoles: (userRoles) => set({ userRoles }), + fetchUserRoles: async () => { + try { + //const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`); + const token = localStorage.getItem("auth_token"); + if (token) { + const response = await axios.get("/api/auth/getuseraccess", { + withCredentials: true, + }); + const data: FetchModulesResponse = response?.data; //await response.json(); - //console.log(data); - set({ userRoles: data.data }); - } else { - //console.log(data); - set({ userRoles: [] }); - } - } catch (error) { - console.error("Failed to fetch settings:", error); - } - }, + if (response.status === 401) { + set({ userRoles: [] }); + } + set({ userRoles: data?.data }); + } else { + //console.log(data); + set({ userRoles: [] }); + } + } catch (error) { + set({ userRoles: [] }); + console.error("Failed to fetch settings:", error); + } + }, })); diff --git a/lstV2/frontend/src/utils/userAccess.ts b/lstV2/frontend/src/utils/userAccess.ts index 2db897c..db72e53 100644 --- a/lstV2/frontend/src/utils/userAccess.ts +++ b/lstV2/frontend/src/utils/userAccess.ts @@ -1,44 +1,52 @@ -import { Modules } from "@/types/modules"; import { User } from "@/types/users"; // user will need access to the module. // users role will determine there visual access -export function hasAccess( - user: User | null, - moduleName: string | null, - modules: Modules[] -): boolean { - // get the modules for the id - const filteredModule = modules?.filter((f) => f.name === moduleName); - //console.log(filteredModule[0]); - // userroles and filter out by the module id, +export function hasAccess(user: any, moduleName: string | null): boolean { + //console.log("has access user", user, moduleName); + // get the modules for the id - const roleCheck: any = user?.roles.find( - (role) => role.module_id === filteredModule[0].module_id - ); + const filteredModule = user?.roles?.filter( + (f: any) => f.module === moduleName, + ); + //console.log(filteredModule[0]); + // 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, + // ); - if (filteredModule[0].roles.includes(roleCheck?.role)) { - return true; - } - //if(filteredModule[0].roles.includes(roleCheck.)) - return false; + if (filteredModule && filteredModule.length > 0) { + return true; + } + //if(filteredModule[0].roles.includes(roleCheck.)) + return false; } export function hasPageAccess( - user: User | null, - role: any, - module_id: string + user: User | null, + role: any, + moduleName: string, ): boolean { - if (role.includes("viewer")) return true; - if (!user) return false; + if (role.includes("viewer")) return true; + if (!user) return false; - // get only the module in the user profile - //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)) { + const userRole = user?.roles.filter( + (role: any) => role.module === moduleName, + ); - // return true}; - if (userRole.length !== 0) return true; - return false; + //console.log(user); + + // if (role.includes(userRole[0]?.role)) { + + // return true}; + //if (userRole.length > 0) return true; + if (userRole.length >= 1) { + //console.log(userRole); + return true; + } else { + return false; + } + + //return false; } diff --git a/lstV2/server/index.ts b/lstV2/server/index.ts index f4bb354..49da68f 100644 --- a/lstV2/server/index.ts +++ b/lstV2/server/index.ts @@ -1,35 +1,34 @@ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + import { serve } from "@hono/node-server"; -import { OpenAPIHono } from "@hono/zod-openapi"; - 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 { 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 import scalar from "./services/general/route/scalar.js"; -import system from "./services/server/systemServer.js"; -import auth from "./services/auth/authService.js"; -import tcpServer from "./services/tcpServer/tcpServer.js"; -import ocme from "./services/ocme/ocmeService.js"; -import sqlService from "./services/sqlServer/sqlService.js"; -import logistics from "./services/logistics/logisticsService.js"; -import rfid from "./services/rfid/rfidService.js"; -import printers from "./services/printers/printerService.js"; +import { createLog } from "./services/logger/logger.js"; import loggerService from "./services/logger/loggerService.js"; -import ocpService from "./services/ocp/ocpService.js"; -import os from "os"; +import logistics from "./services/logistics/logisticsService.js"; import { sendEmail } from "./services/notifications/controller/sendMail.js"; import notify from "./services/notifications/notifyService.js"; -import eom from "./services/eom/eomService.js"; -import dataMart from "./services/dataMart/dataMartService.js"; -import qualityRequest from "./services/quality/qualityService.js"; +import ocme from "./services/ocme/ocmeService.js"; +import ocpService from "./services/ocp/ocpService.js"; +import printers from "./services/printers/printerService.js"; import produser from "./services/prodUser/prodUser.js"; +import qualityRequest from "./services/quality/qualityService.js"; +import rfid from "./services/rfid/rfidService.js"; import { - getSettings, - serverSettings, + getSettings, + serverSettings, } 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 const username = "lst_user"; @@ -48,28 +47,33 @@ export const lstAuth = btoa(`${username}:${password}`); const serverIntialized: any = await getSettings(); export const installed = - serverIntialized.length === 0 && process.env.NODE_ENV !== "development" - ? false - : true; + serverIntialized.length === 0 && process.env.NODE_ENV !== "development" + ? false + : true; createLog("info", "LST", "server", `Server is installed: ${installed}`); const app = new OpenAPIHono({ strict: false }); // middle ware if (process.env.NODE_ENV === "development") { - app.use("*", logger()); + app.use("*", logger()); } app.use( - "*", - cors({ - origin: "*", // Allow all origins - allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"], - allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], - //exposeHeaders: ["Content-Length", "X-Kuma-Revision"], - credentials: true, // Allow credentials if needed - maxAge: 600, - }) + "*", + cors({ + origin: [ + "http://localhost:3000", + "http://localhost:5173", + "http://localhost:4000", + "http://localhost:4200", + ], // Allow all origins + allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"], + allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"], + //exposeHeaders: ["Content-Length", "X-Kuma-Revision"], + credentials: true, // Allow credentials if needed + maxAge: 600, + }), ); // Middleware to normalize route case @@ -86,34 +90,34 @@ app.use( // }); app.doc("/api/ref", { - openapi: "3.0.0", - info: { - version: "2.0.0", - title: "LST API", - }, + openapi: "3.0.0", + info: { + version: "2.0.0", + title: "LST API", + }, }); const routes = [ - scalar, - auth, - // apiHits, - system, - tcpServer, - sqlService, - logistics, - rfid, - printers, - loggerService, - ocpService, - notify, - eom, - dataMart, - qualityRequest, - produser, + scalar, + auth, + // apiHits, + system, + tcpServer, + sqlService, + logistics, + rfid, + printers, + loggerService, + ocpService, + notify, + eom, + dataMart, + qualityRequest, + produser, ] as const; const appRoutes = routes.forEach((route) => { - app.route("/api/", route); + app.route("/api/", route); }); app.route("/ocme/", ocme); @@ -154,60 +158,60 @@ app.use("*", serveStatic({ path: "./frontend/dist/index.html" })); // Handle app exit signals process.on("SIGINT", async () => { - console.log("\nGracefully shutting down..."); - //await closePool(); - process.exit(0); + console.log("\nGracefully shutting down..."); + //await closePool(); + process.exit(0); }); process.on("SIGTERM", async () => { - console.log("Received termination signal, closing database..."); - //await closePool(); - process.exit(0); + console.log("Received termination signal, closing database..."); + //await closePool(); + process.exit(0); }); process.on("uncaughtException", async (err) => { - console.log("Uncaught Exception:", err); - //await closePool(); - const emailData = { - email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused. - subject: `${os.hostname()} has just encountered a crash.`, - template: "serverCrash", - context: { - error: err, - plant: `${os.hostname()}`, - }, - }; + console.log("Uncaught Exception:", err); + //await closePool(); + const emailData = { + email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused. + subject: `${os.hostname()} has just encountered a crash.`, + template: "serverCrash", + context: { + error: err, + plant: `${os.hostname()}`, + }, + }; - await sendEmail(emailData); - //process.exit(1); + await sendEmail(emailData); + //process.exit(1); }); process.on("beforeExit", async () => { - console.log("Process is about to exit..."); - //await closePool(); - process.exit(0); + console.log("Process is about to exit..."); + //await closePool(); + process.exit(0); }); const port = - process.env.NODE_ENV === "development" - ? process.env.VITE_SERVER_PORT - : process.env.PROD_PORT; + process.env.NODE_ENV === "development" + ? process.env.VITE_SERVER_PORT + : process.env.PROD_PORT; const ocmeport = process.env.OCME_PORT; serve( - { - fetch: app.fetch, - port: Number(port), - hostname: "0.0.0.0", - }, - (info) => { - createLog( - "info", - "LST", - "server", - `Server is running on http://${info.address}:${info.port}` - ); - } + { + fetch: app.fetch, + port: Number(port), + hostname: "0.0.0.0", + }, + (info) => { + createLog( + "info", + "LST", + "server", + `Server is running on http://${info.address}:${info.port}`, + ); + }, ); /** @@ -217,21 +221,21 @@ serve( const setting = serverSettings; const isActive = setting.filter((n) => n.name === "ocmeService"); if (ocmeport && isActive[0]?.value === "1") { - serve( - { - fetch: app.fetch, - port: Number(ocmeport), - hostname: "0.0.0.0", - }, - (info) => { - createLog( - "info", - "LST", - "server", - `Ocme section is listening on http://${info.address}:${info.port}` - ); - } - ); + serve( + { + fetch: app.fetch, + port: Number(ocmeport), + hostname: "0.0.0.0", + }, + (info) => { + createLog( + "info", + "LST", + "server", + `Ocme section is listening on http://${info.address}:${info.port}`, + ); + }, + ); } export type AppRoutes = typeof appRoutes; diff --git a/lstV2/server/services/auth/middleware/authMiddleware.ts b/lstV2/server/services/auth/middleware/authMiddleware.ts index bb37288..1553408 100644 --- a/lstV2/server/services/auth/middleware/authMiddleware.ts +++ b/lstV2/server/services/auth/middleware/authMiddleware.ts @@ -1,45 +1,62 @@ -import {type MiddlewareHandler} from "hono"; +import axios from "axios"; +import { type MiddlewareHandler } from "hono"; import jwt from "jsonwebtoken"; -const {sign, verify} = jwt; +const { sign, verify } = jwt; 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 ")) { - return c.json({error: "Unauthorized"}, 401); - } + const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/me`, { + headers: { Cookie: cookieHeader }, + }); - const token = authHeader.split(" ")[1]; + if (res.status === 401) return c.json({ error: "Unauthorized" }, 401); - 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); - } + //const user = await resp.json(); + c.set("user", res.data.user); + return next(); }; + +// 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); +// } +// }; diff --git a/lstV2/server/services/auth/middleware/roleCheck.ts b/lstV2/server/services/auth/middleware/roleCheck.ts index 31f07b6..0a076ff 100644 --- a/lstV2/server/services/auth/middleware/roleCheck.ts +++ b/lstV2/server/services/auth/middleware/roleCheck.ts @@ -1,85 +1,111 @@ +import axios from "axios"; import { createMiddleware } from "hono/factory"; -import type { CustomJwtPayload } from "../../../types/jwtToken.js"; -import { verify } from "hono/jwt"; -import { db } from "../../../../database/dbclient.js"; -import { modules } from "../../../../database/schema/modules.js"; -import { and, eq } from "drizzle-orm"; -import { userRoles } from "../../../../database/schema/userRoles.js"; -import { tryCatch } from "../../../globalUtils/tryCatch.js"; +// const hasCorrectRole = (requiredRole: string[], module: string) => +// createMiddleware(async (c, next) => { +// /** +// * We want to check to make sure you have the correct role to be here +// */ +// const authHeader = c.req.header("Authorization"); + +// 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) => - createMiddleware(async (c, next) => { - /** - * We want to check to make sure you have the correct role to be here - */ - const authHeader = c.req.header("Authorization"); + createMiddleware(async (c, next) => { + const cookieHeader = c.req.header("Cookie"); + if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401); - if (!authHeader || !authHeader.startsWith("Bearer ")) { - return c.json({ error: "Unauthorized" }, 401); - } + const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/roles`, { + headers: { Cookie: cookieHeader }, + }); - const token = authHeader.split(" ")[1]; + const currentRoles: UserRole[] = res.data.data; + const canAccess = currentRoles.some( + (r) => r.module === module && requiredRole.includes(r.role), + ); + if (!canAccess) { + return c.json( + { + error: "Unauthorized", + message: `You do not have access to ${module}`, + }, + 400, + ); + } - // 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(); - }); + return next(); + }); export default hasCorrectRole; diff --git a/lstV2/server/services/auth/routes/login.ts b/lstV2/server/services/auth/routes/login.ts index 60bc304..4706e78 100644 --- a/lstV2/server/services/auth/routes/login.ts +++ b/lstV2/server/services/auth/routes/login.ts @@ -1,97 +1,117 @@ -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"; const app = new OpenAPIHono(); const UserSchema = z - .object({ - username: z.string().optional().openapi({ example: "smith002" }), - //email: z.string().optional().openapi({example: "s.smith@example.com"}), - password: z.string().openapi({ example: "password123" }), - }) - .openapi("User"); + .object({ + username: z.string().optional().openapi({ example: "smith002" }), + //email: z.string().optional().openapi({example: "s.smith@example.com"}), + password: z.string().openapi({ example: "password123" }), + }) + .openapi("User"); const route = createRoute({ - tags: ["Auth"], - summary: "Login as user", - description: "Login as a user to get a JWT token", - method: "post", - path: "/login", - request: { - body: { - content: { - "application/json": { schema: UserSchema }, - }, - }, - }, - responses: { - 200: { - content: { - "application/json": { - schema: z.object({ - success: z.boolean().openapi({ example: true }), - message: z.string().openapi({ example: "Logged in" }), - }), - }, - }, - description: "Response message", - }, + tags: ["Auth"], + summary: "Login as user", + description: "Login as a user to get a JWT token", + method: "post", + path: "/login", + request: { + body: { + content: { + "application/json": { schema: UserSchema }, + }, + }, + }, + responses: { + 200: { + content: { + "application/json": { + schema: z.object({ + success: z.boolean().openapi({ example: true }), + message: z.string().openapi({ example: "Logged in" }), + }), + }, + }, + description: "Response message", + }, - 400: { - content: { - "application/json": { - schema: z.object({ - success: z.boolean().openapi({ example: false }), - message: z - .string() - .openapi({ example: "Username and password required" }), - }), - }, - }, - description: "Bad request", - }, - 401: { - content: { - "application/json": { - schema: z.object({ - success: z.boolean().openapi({ example: false }), - message: z - .string() - .openapi({ example: "Username and password required" }), - }), - }, - }, - description: "Bad request", - }, - }, + 400: { + content: { + "application/json": { + schema: z.object({ + success: z.boolean().openapi({ example: false }), + message: z + .string() + .openapi({ example: "Username and password required" }), + }), + }, + }, + description: "Bad request", + }, + 401: { + content: { + "application/json": { + schema: z.object({ + success: z.boolean().openapi({ example: false }), + message: z + .string() + .openapi({ example: "Username and password required" }), + }), + }, + }, + description: "Bad request", + }, + }, }); -app.openapi(route, async (c) => { - const { username, password, email } = await c.req.json(); +app.openapi(route, async (c: any) => { + const { username, password, email } = await c.req.json(); - if (!username || !password) { - return c.json( - { - success: false, - message: "Username and password are required", - }, - 400 - ); - } + if (!username || !password) { + return c.json( + { + success: false, + message: "Username and password are required", + }, + 400, + ); + } - try { - const { token, user } = await login(username.toLowerCase(), password); + try { + 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 - //c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`); + // Set the JWT as an HTTP-only cookie + //c.header("Set-Cookie", `auth_token=${token}; HttpOnly; Secure; Path=/; SameSite=None; Max-Age=3600`); - return c.json( - { success: true, message: "Login successful", user, token }, - 200 - ); - } catch (err) { - return c.json({ success: false, message: "Incorrect Credentials" }, 401); - } + const setCookie = loginResp.headers["set-cookie"] as any; + + if (setCookie) { + c.header("Set-Cookie", setCookie); + } + return c.json( + { success: true, message: "Login successful", data: loginResp.data }, + 200, + ); + } 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); + } + } }); export default app; diff --git a/lstV2/server/services/auth/routes/session.ts b/lstV2/server/services/auth/routes/session.ts index e7fd8a2..81364a3 100644 --- a/lstV2/server/services/auth/routes/session.ts +++ b/lstV2/server/services/auth/routes/session.ts @@ -1,110 +1,149 @@ -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 { authMiddleware } from "../middleware/authMiddleware.js"; import jwt from "jsonwebtoken"; +import { authMiddleware } from "../middleware/authMiddleware.js"; const session = new OpenAPIHono(); const expiresIn = Number(process.env.JWT_EXPIRES!) || 60; const secret: string = process.env.JWT_SECRET!; const { sign } = jwt; + const UserSchema = z.object({ - username: z - .string() - .regex(/^[a-zA-Z0-9_]{3,30}$/) - .openapi({ example: "smith034" }), - email: z.string().email().openapi({ example: "smith@example.com" }), - password: z - .string() - .min(6, { message: "Passwords must be longer than 3 characters" }) - .regex(/[A-Z]/, { - message: "Password must contain at least one uppercase letter", - }) - .regex(/[\W_]/, { - message: "Password must contain at least one special character", - }) - .openapi({ example: "Password1!" }), + username: z + .string() + .regex(/^[a-zA-Z0-9_]{3,30}$/) + .openapi({ example: "smith034" }), + email: z.string().email().openapi({ example: "smith@example.com" }), + password: z + .string() + .min(6, { message: "Passwords must be longer than 3 characters" }) + .regex(/[A-Z]/, { + message: "Password must contain at least one uppercase letter", + }) + .regex(/[\W_]/, { + message: "Password must contain at least one special character", + }) + .openapi({ example: "Password1!" }), }); +const activeSessions: Record = + {}; +const SESSION_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour + session.openapi( - createRoute({ - tags: ["Auth"], - summary: "Checks a user session based on there token", - description: "Can post there via Authentiaction header or cookies", - method: "get", - path: "/session", - middleware: authMiddleware, - // request: { - // body: { - // content: { - // "application/json": {schema: UserSchema}, - // }, - // }, - // }, - responses: { - 200: { - content: { - "application/json": { - schema: z.object({ - data: z.object({ - token: z - .string() - .openapi({ - example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads", - }), - // user: z.object({ - // user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}), - // username: z.string().openapi({example: "smith"}), - // email: z.string().openapi({example: "smith@example.com"}).optional(), - // }), - }), - }), - }, - }, - description: "Login successful", - }, - 401: { - content: { - "application/json": { - schema: z.object({ - message: z.string().openapi({ example: "Unathenticated" }), - }), - }, - }, - description: "Error of why you were not logged in.", - }, - }, - }), - async (c) => { - const authHeader = c.req.header("Authorization"); + createRoute({ + tags: ["Auth"], + summary: "Checks a user session based on there token", + description: "Can post there via Authentiaction header or cookies", + method: "get", + path: "/session", + middleware: authMiddleware, + // request: { + // body: { + // content: { + // "application/json": {schema: UserSchema}, + // }, + // }, + // }, + responses: { + 200: { + content: { + "application/json": { + schema: z.object({ + data: z.object({ + token: z.string().openapi({ + example: "sdkjhgsldkvhdakl;jvhs;adkjfhvds.kvnsad;ovhads", + }), + // user: z.object({ + // user_id: z.string().openapi({example: "04316c86-f086-4cc6-b3d4-cca164a26f3f"}), + // username: z.string().openapi({example: "smith"}), + // email: z.string().openapi({example: "smith@example.com"}).optional(), + // }), + }), + }), + }, + }, + description: "Login successful", + }, + 401: { + content: { + "application/json": { + schema: z.object({ + message: z.string().openapi({ example: "Unathenticated" }), + }), + }, + }, + description: "Error of why you were not logged in.", + }, + }, + }), + async (c: any) => { + const cookieHeader = c.req.header("Cookie"); + if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401); - if (authHeader?.includes("Basic")) { - return c.json( - { message: "You are a Basic user! Please login to get a token" }, - 401 - ); - } + const res = await axios.get(`${process.env.LST_BASE_URL}/api/user/me`, { + headers: { Cookie: cookieHeader }, + withCredentials: true, + }); - if (!authHeader) { - return c.json({ message: "Unauthorized" }, 401); - } + if (res.status === 401) return c.json({ error: "Unauthorized" }, 401); - const token = authHeader?.split("Bearer ")[1] || ""; + const user = res.data.user; - try { - const payload = await verify(token, process.env.JWT_SECRET!); + // ── record session heartbeat ─────────────────────────────────────────── + activeSessions[user.id] = { + lastSeen: Date.now(), + expiresAt: Date.now() + SESSION_TIMEOUT_MS, + }; - // If it's valid, return a new token - const newToken = sign({ user: payload.user }, secret, { - expiresIn: expiresIn * 60, - }); + // clean up stale sessions in the background + for (const [key, sess] of Object.entries(activeSessions)) { + if (Date.now() > sess.expiresAt) delete activeSessions[key]; + } - return c.json({ data: { token: newToken, user: payload.user } }, 200); - } catch (error) { - return c.json({ message: "Unauthorized" }, 401); - } - } + 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] || ""; diff --git a/lstV2/server/services/auth/routes/user/getUserRoles.ts b/lstV2/server/services/auth/routes/user/getUserRoles.ts index ea17bee..831cd37 100644 --- a/lstV2/server/services/auth/routes/user/getUserRoles.ts +++ b/lstV2/server/services/auth/routes/user/getUserRoles.ts @@ -1,59 +1,72 @@ -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 type { CustomJwtPayload } from "../../../../types/jwtToken.js"; -import { authMiddleware } from "../../middleware/authMiddleware.js"; import { roleCheck } from "../../controllers/userRoles/getUserAccess.js"; +import { authMiddleware } from "../../middleware/authMiddleware.js"; const { verify } = jwt; const app = new OpenAPIHono(); const responseSchema = z.object({ - message: z.string().optional().openapi({ example: "User Created" }), + message: z.string().optional().openapi({ example: "User Created" }), }); app.openapi( - createRoute({ - tags: ["auth:user"], - summary: "returns the users access", - method: "get", - path: "/getuseraccess", - middleware: [authMiddleware], - responses: { - 200: { - content: { "application/json": { schema: responseSchema } }, - description: "Retrieve the user", - }, - }, - }), - async (c) => { - // apit hit - //apiHit(c, { endpoint: "api/auth/getUserRoles" }); - const authHeader = c.req.header("Authorization"); - const token = authHeader?.split("Bearer ")[1] || ""; - try { - const secret = process.env.JWT_SECRET!; - if (!secret) { - throw new Error("JWT_SECRET is not defined in environment variables"); - } + createRoute({ + tags: ["auth:user"], + summary: "returns the users access", + method: "get", + path: "/getuseraccess", + middleware: [authMiddleware], + responses: { + 200: { + content: { "application/json": { schema: responseSchema } }, + description: "Retrieve the user", + }, + }, + }), + async (c: any) => { + // apit hit + //apiHit(c, { endpoint: "api/auth/getUserRoles" }); + const authHeader = c.req.header("Authorization"); - const payload = verify(token, secret) as CustomJwtPayload; + const user = c.get("user"); - const canAccess = await roleCheck(payload.user?.user_id); + if (!user) { + return c.json( + { + success: true, + message: `Unauthorized`, + }, + 401, + ); + } + try { + const cookieHeader = c.req.header("Cookie"); + if (!cookieHeader) return c.json({ error: "Unauthorized" }, 401); - return c.json( - { - sucess: true, - message: `User ${payload.user?.username} can access`, - data: canAccess, - }, - 200 - ); - } catch (error) { - console.log(error); - } + const res = await axios.get( + `${process.env.LST_BASE_URL}/api/user/roles`, + { + headers: { Cookie: cookieHeader }, + }, + ); - return c.json({ message: "UserRoles coming over" }); - } + return c.json( + { + success: true, + message: `User ${user.username} can access`, + data: res.data.data, + }, + 200, + ); + } catch (error) { + console.log(error); + } + + return c.json({ message: "UserRoles coming over" }); + }, ); export default app; diff --git a/lstV2/server/services/logistics/controller/siloAdjustments/createSiloAdjustment.ts b/lstV2/server/services/logistics/controller/siloAdjustments/createSiloAdjustment.ts index 764935d..8d0f1f9 100644 --- a/lstV2/server/services/logistics/controller/siloAdjustments/createSiloAdjustment.ts +++ b/lstV2/server/services/logistics/controller/siloAdjustments/createSiloAdjustment.ts @@ -1,154 +1,152 @@ +import { eq } from "drizzle-orm"; import { db } from "../../../../../database/dbclient.js"; +import { settings } from "../../../../../database/schema/settings.js"; +import { siloAdjustments } from "../../../../../database/schema/siloAdjustments.js"; +import { greetingStuff } from "../../../../globalUtils/greetingEmail.js"; +import { generateOneTimeKey } from "../../../../globalUtils/singleUseKey.js"; import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +import { sendEmail } from "../../../notifications/controller/sendMail.js"; +import { + getSettings, + serverSettings, +} 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"; -import { siloAdjustments } from "../../../../../database/schema/siloAdjustments.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 { eq } from "drizzle-orm"; -import { - getSettings, - serverSettings, -} from "../../../server/controller/settings/getSettings.js"; export const createSiloAdjustment = async ( - data: any | null, - user: any | null + data: any | null, + user: any | null, ) => { - /** - * Creates a silo adjustment based off warehouse, location, and qty. - * qty will come from the hmi, prolink, or silo patrol - */ - // const { data: set, error: setError } = await tryCatch( - // db.select().from(settings) - // ); + /** + * Creates a silo adjustment based off warehouse, location, and qty. + * qty will come from the hmi, prolink, or silo patrol + */ + // const { data: set, error: setError } = await tryCatch( + // db.select().from(settings) + // ); - // const { data: set, error: setError } = await tryCatch(getSettings()); + // const { data: set, error: setError } = await tryCatch(getSettings()); - // if (setError) { - // return { - // success: false, - // message: `There was an error getting setting data to post to the server.`, - // data: setError, - // }; - // } + // if (setError) { + // return { + // success: false, + // message: `There was an error getting setting data to post to the server.`, + // data: setError, + // }; + // } - const set = serverSettings.length === 0 ? [] : serverSettings; - // getting stock data first so we have it prior to the adjustment - const { data: s, error: stockError } = await tryCatch( - query(siloQuery, "Silo data Query") - ); + const set = serverSettings.length === 0 ? [] : serverSettings; + // getting stock data first so we have it prior to the adjustment + const { data: s, error: stockError } = await tryCatch( + query(siloQuery, "Silo data Query"), + ); - if (stockError) { - return { - success: false, - message: `There was an error getting stock data to post to the server.`, - data: stockError, - }; - } - const stock: any = s?.data as any; - const { data: a, error: errorAdj } = await tryCatch( - postAdjustment(data, user.prod) - ); + if (stockError) { + return { + success: false, + message: `There was an error getting stock data to post to the server.`, + data: stockError, + }; + } + const stock: any = s?.data as any; + const { data: a, error: errorAdj } = await tryCatch(postAdjustment(data)); - if (errorAdj) { - return { - success: false, - message: `There was an error doing the silo adjustment.`, - data: errorAdj, - }; - } - /** - * Checking to see the difference, and send email if +/- 5% will change later if needed - */ + if (errorAdj) { + return { + success: false, + message: `There was an error doing the silo adjustment.`, + data: errorAdj, + }; + } + /** + * Checking to see the difference, and send email if +/- 5% will change later if needed + */ - const sa: any = a; + const sa: any = a; - if (!sa.success) { - console.log(`insde error`); - return { - success: sa.success, - message: sa.message, - data: sa.data, - }; - } + if (!sa.success) { + console.log(`inside error`); + return { + success: sa.success, + message: sa.message, + data: sa.data, + }; + } - const stockNummy = stock.filter((s: any) => s.LocationID === data.laneId); - const theDiff = - ((data.quantity - stockNummy[0].Stock_Total) / - ((data.quantity + stockNummy[0].Stock_Total) / 2)) * - 100; + const stockNummy = stock.filter((s: any) => s.LocationID === data.laneId); + const theDiff = + ((data.quantity - stockNummy[0].Stock_Total) / + ((data.quantity + stockNummy[0].Stock_Total) / 2)) * + 100; - /** - * Post the data to our db. - */ + /** + * Post the data to our db. + */ - //console.log(stockNummy); - const { data: postAdj, error: postAdjError } = await tryCatch( - db - .insert(siloAdjustments) - .values({ - warehouseID: data.warehouseId, - locationID: data.laneId, - currentStockLevel: stockNummy[0].Stock_Total, - newLevel: data.quantity, - lastDateAdjusted: new Date(stockNummy[0].LastAdjustment), - add_user: user.username, - }) - .returning({ id: siloAdjustments.siloAdjust_id }) - ); + //console.log(stockNummy); + const { data: postAdj, error: postAdjError } = await tryCatch( + db + .insert(siloAdjustments) + .values({ + warehouseID: data.warehouseId, + locationID: data.laneId, + currentStockLevel: stockNummy[0].Stock_Total, + newLevel: data.quantity, + lastDateAdjusted: new Date(stockNummy[0].LastAdjustment), + add_user: user.username, + }) + .returning({ id: siloAdjustments.siloAdjust_id }), + ); - if (postAdjError) { - //console.log(postAdjError); - return { - success: false, - message: `There was an error posting the new adjustment.`, - data: postAdjError, - }; - } - let adj: any = a; - if (Math.abs(theDiff) > 5) { - // console.log(`Send for comment due to being: ${theDiff.toFixed(2)}%`); - const server = set.filter((n: any) => n.name === "server"); + if (postAdjError) { + //console.log(postAdjError); + return { + success: false, + message: `There was an error posting the new adjustment.`, + data: postAdjError, + }; + } + let adj: any = a; + if (Math.abs(theDiff) > 5) { + // console.log(`Send for comment due to being: ${theDiff.toFixed(2)}%`); + const server = set.filter((n: any) => n.name === "server"); - const port = set.filter((n: any) => n.name === "serverPort"); - const key = await generateOneTimeKey(); - const updateKey = await db - .update(siloAdjustments) - .set({ commentKey: key }) - .where(eq(siloAdjustments.siloAdjust_id, postAdj[0].id)); + const port = set.filter((n: any) => n.name === "serverPort"); + const key = await generateOneTimeKey(); + const updateKey = await db + .update(siloAdjustments) + .set({ commentKey: key }) + .where(eq(siloAdjustments.siloAdjust_id, postAdj[0].id)); - const emailSetup = { - email: user.email, - subject: `Alert - Siloadjustment was done with a descrepancy of 5% or greater`, - template: "siloAdjustmentComment", - context: { - greeting: await greetingStuff(), - siloName: stockNummy[0].Description, - variance: `${theDiff.toFixed(2)}%`, - currentLevel: stockNummy[0].Stock_Total, - newLevel: data.quantity, - variancePer: 5, - adjustID: `${postAdj[0].id}&${key}`, - server: server[0].value, - port: port[0].value, - }, - }; + const emailSetup = { + email: user.email, + subject: `Alert - Siloadjustment was done with a descrepancy of 5% or greater`, + template: "siloAdjustmentComment", + context: { + greeting: await greetingStuff(), + siloName: stockNummy[0].Description, + variance: `${theDiff.toFixed(2)}%`, + currentLevel: stockNummy[0].Stock_Total, + newLevel: data.quantity, + variancePer: 5, + adjustID: `${postAdj[0].id}&${key}`, + server: server[0].value, + port: port[0].value, + }, + }; - //console.log(emailSetup); + //console.log(emailSetup); - await sendEmail(emailSetup); - return { - success: adj.success, - message: `Silo adjustmnet was completed you will also receive and email due to the adjustment having a variation of ${Math.abs( - theDiff - ).toFixed(2)}%`, - data: adj.data, - }; - } else { - return { success: adj.success, message: adj.message, data: adj.data }; - } + await sendEmail(emailSetup); + return { + success: adj.success, + message: `Silo adjustmnet was completed you will also receive and email due to the adjustment having a variation of ${Math.abs( + theDiff, + ).toFixed(2)}%`, + data: adj.data, + }; + } else { + return { success: adj.success, message: adj.message, data: adj.data }; + } }; diff --git a/lstV2/server/services/logistics/controller/siloAdjustments/postAdjustment.ts b/lstV2/server/services/logistics/controller/siloAdjustments/postAdjustment.ts index 81e0a13..da40d4e 100644 --- a/lstV2/server/services/logistics/controller/siloAdjustments/postAdjustment.ts +++ b/lstV2/server/services/logistics/controller/siloAdjustments/postAdjustment.ts @@ -2,99 +2,99 @@ import axios from "axios"; import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js"; import { tryCatch } from "../../../../globalUtils/tryCatch.js"; -export const postAdjustment = async (data: any, prod: any) => { - if (data.warehouseId === undefined) { - return { - sucess: false, - message: `Missing mandatory field: warehouseID`, - data: { error: `Missing mandatory field: warehouseID` }, - }; - } +export const postAdjustment = async (data: any) => { + if (data.warehouseId === undefined) { + return { + sucess: false, + message: `Missing mandatory field: warehouseID`, + data: { error: `Missing mandatory field: warehouseID` }, + }; + } - if (data.laneId === undefined) { - return { - sucess: false, - message: `Missing mandatory field: locationID`, - data: { error: `Missing mandatory field: locationID` }, - }; - } + if (data.laneId === undefined) { + return { + sucess: false, + message: `Missing mandatory field: locationID`, + data: { error: `Missing mandatory field: locationID` }, + }; + } - if (data.quantity == "0") { - return { - sucess: false, - message: `You entered 0 for the quantity to post, quantity needs to be at leave 1`, - data: { - error: `You entered 0 for the quantity to post, quantity needs to be at leave 1`, - }, - }; - } + if (data.quantity == "0") { + return { + sucess: false, + message: `You entered 0 for the quantity to post, quantity needs to be at leave 1`, + data: { + error: `You entered 0 for the quantity to post, quantity needs to be at leave 1`, + }, + }; + } - const siloAdjustment = { - warehouseId: data.warehouseId, - laneId: data.laneId, - quantity: data.quantity, - }; + const siloAdjustment = { + warehouseId: data.warehouseId, + laneId: data.laneId, + quantity: data.quantity, + }; - let url = await prodEndpointCreation( - "/public/v1.0/Warehousing/AdjustSiloStockLevel" - ); + let url = await prodEndpointCreation( + "/public/v1.0/Warehousing/AdjustSiloStockLevel", + ); - const { data: silo, error } = await tryCatch( - axios.post(url, siloAdjustment, { - headers: { - "X-API-Key": process.env.TEC_API_KEY || "", - "Content-Type": "application/json", - }, - }) - ); - let e = error as any; - if (e) { - console.log(e.response); - if (e.status === 401) { - const data = { - success: false, - message: `There was error posting the data: ${JSON.stringify( - e.response?.data - )}`, - data: { - status: e.response?.status, - statusText: e.response?.statusText, - data: e.response?.data, - }, - }; - return data; - } else { - return { - success: false, - message: "Error in posting the silo adjustment.", - data: { - status: e.response?.status, - statusText: e.response?.statusText, - data: e.response?.data, - }, - }; - } - } + const { data: silo, error } = await tryCatch( + axios.post(url, siloAdjustment, { + headers: { + "X-API-Key": process.env.TEC_API_KEY || "", + "Content-Type": "application/json", + }, + }), + ); + let e = error as any; + if (e) { + console.log(e.response); + if (e.status === 401) { + const data = { + success: false, + message: `There was error posting the data: ${JSON.stringify( + e.response?.data, + )}`, + data: { + status: e.response?.status, + statusText: e.response?.statusText, + data: e.response?.data, + }, + }; + return data; + } else { + return { + success: false, + message: "Error in posting the silo adjustment.", + data: { + status: e.response?.status, + statusText: e.response?.statusText, + data: e.response?.data, + }, + }; + } + } - if (silo?.status !== 200) { - return { - success: false, - message: "Error in posting the silo adjustment", - data: { - status: silo?.status, - statusText: silo?.statusText, - data: silo?.data, - }, - }; - } else { - return { - success: true, - message: "Adjustment was completed", - data: { - status: silo.status, - statusText: silo.statusText, - data: silo.data, - }, - }; - } + if (silo?.status !== 200) { + return { + success: false, + message: "Error in posting the silo adjustment", + data: { + status: silo?.status, + statusText: silo?.statusText, + data: silo?.data, + }, + }; + } else { + return { + success: true, + message: "Adjustment was completed", + data: { + status: silo.status, + statusText: silo.statusText, + data: silo.data, + }, + }; + } }; diff --git a/lstV2/server/services/logistics/route/dm/bulkOrdersIn.ts b/lstV2/server/services/logistics/route/dm/bulkOrdersIn.ts index 810926c..960b29e 100644 --- a/lstV2/server/services/logistics/route/dm/bulkOrdersIn.ts +++ b/lstV2/server/services/logistics/route/dm/bulkOrdersIn.ts @@ -1,9 +1,10 @@ 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 { tryCatch } from "../../../../globalUtils/tryCatch.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(); @@ -15,61 +16,53 @@ const app = new OpenAPIHono(); // }) // .openapi("User"); app.openapi( - createRoute({ - tags: ["logistics"], - summary: "Post orders to DM", - method: "post", - path: "/postbulkorders", - // request: { - // body: { - // content: { - // "application/json": { schema: Body }, - // }, - // }, - // }, - // description: - // "Provided a running number and lot number you can consume material.", - responses: responses(), - }), - async (c) => { - apiHit(c, { endpoint: "/postbulkorders" }); - const body = await c.req.parseBody(); - const authHeader = c.req.header("Authorization"); - const token = authHeader?.split("Bearer ")[1] || ""; - //console.log(body); // File | string + createRoute({ + tags: ["logistics"], + summary: "Post orders to DM", + method: "post", + path: "/postbulkorders", + middleware: authMiddleware, + // request: { + // body: { + // content: { + // "application/json": { schema: Body }, + // }, + // }, + // }, + // description: + // "Provided a running number and lot number you can consume material.", + responses: responses(), + }), + async (c) => { + apiHit(c, { endpoint: "/postbulkorders" }); + const body = await c.req.parseBody(); + //console.log(body); // File | string - // if (body["fileType"] === "standard") { - // console.log(`doing standard orders in.`); - // } - const { data: payload, error: pe } = await tryCatch( - verify(token, process.env.JWT_SECRET!) - ); + // if (body["fileType"] === "standard") { + // console.log(`doing standard orders in.`); + // } - if (pe) { - return c.json({ success: false, message: "Unauthorized" }, 401); - } + const { data: orders, error } = await tryCatch( + ordersIn(body, c.get("user")), + ); - const { data: orders, error } = await tryCatch( - ordersIn(body, payload.user) - ); + if (error) { + console.log(error); + return c.json( + { + success: false, + message: "Error posting Orders", + data: error, + }, + 400, + ); + } - if (error) { - console.log(error); - return c.json( - { - success: false, - message: "Error posting Orders", - data: error, - }, - 400 - ); - } - - return c.json({ - success: orders?.success ?? false, - message: orders?.message ?? "Error posting forecast", - data: orders?.data ?? [], - }); - } + return c.json({ + success: orders?.success ?? false, + message: orders?.message ?? "Error posting forecast", + data: orders?.data ?? [], + }); + }, ); export default app; diff --git a/lstV2/server/services/logistics/route/dm/forecastIn.ts b/lstV2/server/services/logistics/route/dm/forecastIn.ts index 6a37c52..15b7712 100644 --- a/lstV2/server/services/logistics/route/dm/forecastIn.ts +++ b/lstV2/server/services/logistics/route/dm/forecastIn.ts @@ -1,10 +1,11 @@ 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 { forecastIn } from "../../controller/dm/forecast/forecastIn.js"; -import { tryCatch } from "../../../../globalUtils/tryCatch.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(); @@ -16,61 +17,54 @@ const app = new OpenAPIHono(); // }) // .openapi("User"); app.openapi( - createRoute({ - tags: ["logistics"], - summary: "Post forecast to DM", - method: "post", - path: "/postforecastin", - // request: { - // body: { - // content: { - // "application/json": { schema: Body }, - // }, - // }, - // }, - // description: - // "Provided a running number and lot number you can consume material.", - responses: responses(), - }), - async (c) => { - apiHit(c, { endpoint: "/postforecastin" }); - const body = await c.req.parseBody(); - const authHeader = c.req.header("Authorization"); - const token = authHeader?.split("Bearer ")[1] || ""; - //console.log(body); // File | string + createRoute({ + tags: ["logistics"], + summary: "Post forecast to DM", + method: "post", + path: "/postforecastin", + middleware: authMiddleware, + // request: { + // body: { + // content: { + // "application/json": { schema: Body }, + // }, + // }, + // }, + // description: + // "Provided a running number and lot number you can consume material.", + responses: responses(), + }), + async (c) => { + apiHit(c, { endpoint: "/postforecastin" }); + const body = await c.req.parseBody(); - // if (body["fileType"] === "standard") { - // console.log(`doing standard orders in.`); - // } - const { data: payload, error: pe } = await tryCatch( - verify(token, process.env.JWT_SECRET!) - ); + //console.log(body); // File | string - if (pe) { - return c.json({ success: false, message: "Unauthorized" }, 401); - } + // if (body["fileType"] === "standard") { + // console.log(`doing standard orders in.`); + // } - const { data: orders, error } = await tryCatch( - forecastIn(body, payload.user) - ); + const { data: orders, error } = await tryCatch( + forecastIn(body, c.get("user")), + ); - if (error) { - console.log(error); - return c.json( - { - success: false, - message: "Error posting forecast", - data: error, - }, - 400 - ); - } + if (error) { + console.log(error); + return c.json( + { + success: false, + message: "Error posting forecast", + data: error, + }, + 400, + ); + } - return c.json({ - success: orders?.success ?? false, - message: orders?.message ?? "Error posting forecast", - data: orders?.data ?? [], - }); - } + return c.json({ + success: orders?.success ?? false, + message: orders?.message ?? "Error posting forecast", + data: orders?.data ?? [], + }); + }, ); export default app; diff --git a/lstV2/server/services/logistics/route/dm/getStandardForecastTemplate.ts b/lstV2/server/services/logistics/route/dm/getStandardForecastTemplate.ts index 80f994b..3d7e919 100644 --- a/lstV2/server/services/logistics/route/dm/getStandardForecastTemplate.ts +++ b/lstV2/server/services/logistics/route/dm/getStandardForecastTemplate.ts @@ -1,10 +1,10 @@ import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; 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 { responses } from "../../../../globalUtils/routeDefs/responses.js"; +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; + +import { standardForCastTemplate } from "../../controller/dm/forecast/createTemplate.js"; const app = new OpenAPIHono(); @@ -16,52 +16,52 @@ const app = new OpenAPIHono(); // }) // .openapi("User"); app.openapi( - createRoute({ - tags: ["logistics"], - summary: "Gets the standard Forecast Template", - method: "get", - path: "/bulkforcasttemplate", - // request: { - // body: { - // content: { - // "application/json": { schema: Body }, - // }, - // }, - // }, - // description: - // "Provided a running number and lot number you can consume material.", - responses: responses(), - }), - async (c: any) => { - apiHit(c, { endpoint: "/bulkforcasttemplate" }); - const defaultFilename = `bulkForcastTemplate-${format( - new Date(Date.now()), - "M-d-yyyy" - )}.xlsx`; - const filename = c.req.query("filename") || defaultFilename; - const { data, error } = await tryCatch(standardForCastTemplate()); + createRoute({ + tags: ["logistics"], + summary: "Gets the standard Forecast Template", + method: "get", + path: "/bulkforcasttemplate", + // request: { + // body: { + // content: { + // "application/json": { schema: Body }, + // }, + // }, + // }, + // description: + // "Provided a running number and lot number you can consume material.", + responses: responses(), + }), + async (c: any) => { + apiHit(c, { endpoint: "/bulkforcasttemplate" }); + const defaultFilename = `bulkForcastTemplate-${format( + new Date(Date.now()), + "M-d-yyyy", + )}.xlsx`; + const filename = c.req.query("filename") || defaultFilename; + const { data, error } = await tryCatch(standardForCastTemplate()); - if (error) { - return c.json({ - success: false, - message: "Error creating template", - data: error, - }); - } + if (error) { + return c.json({ + success: false, + message: "Error creating template", + data: error, + }); + } - return new Response(data, { - headers: { - "Content-Type": - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "Content-Disposition": `attachment; filename="${filename}"`, - }, - }); + return new Response(data, { + headers: { + "Content-Type": + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "Content-Disposition": `attachment; filename="${filename}"`, + }, + }); - // return c.json({ - // success: data.success, - // message: data.message, - // data: data.data, - // }); - } + // return c.json({ + // success: data.success, + // message: data.message, + // data: data.data, + // }); + }, ); export default app; diff --git a/lstV2/server/services/logistics/route/siloAdjustments/createSiloAdjustment.ts b/lstV2/server/services/logistics/route/siloAdjustments/createSiloAdjustment.ts index 5a0b5f6..959010a 100644 --- a/lstV2/server/services/logistics/route/siloAdjustments/createSiloAdjustment.ts +++ b/lstV2/server/services/logistics/route/siloAdjustments/createSiloAdjustment.ts @@ -1,78 +1,74 @@ import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; 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 { responses } from "../../../../globalUtils/routeDefs/responses.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 responseSchema = z.object({ - success: z.boolean().optional().openapi({ example: true }), - message: z.string().optional().openapi({ example: "user access" }), + success: z.boolean().optional().openapi({ example: true }), + message: z.string().optional().openapi({ example: "user access" }), }); app.openapi( - createRoute({ - tags: ["logistics"], - summary: "Creates silo adjustmennt", - method: "post", - path: "/createsiloadjustment", - middleware: authMiddleware, - description: - "Creates a silo adjustment for the silo if and stores the stock numbers.", - responses: responses(), - }), - async (c) => { - const { data, error } = await tryCatch(c.req.json()); + createRoute({ + tags: ["logistics"], + summary: "Creates silo adjustmennt", + method: "post", + path: "/createsiloadjustment", + middleware: authMiddleware, + description: + "Creates a silo adjustment for the silo if and stores the stock numbers.", + responses: responses(), + }), + async (c) => { + const { data, error } = await tryCatch(c.req.json()); - if (error) { - return c.json( - { - success: false, - message: "Missing data please try again", - error, - }, - 400 - ); - } - apiHit(c, { endpoint: "/createsiloadjustment", lastBody: data }); - const authHeader = c.req.header("Authorization"); - const token = authHeader?.split("Bearer ")[1] || ""; + if (error) { + return c.json( + { + success: false, + message: "Missing data please try again", + error, + }, + 400, + ); + } + apiHit(c, { endpoint: "/createsiloadjustment", lastBody: data }); - try { - const payload = await verify(token, process.env.JWT_SECRET!); - try { - //return apiReturn(c, true, access?.message, access?.data, 200); - const createSiloAdj = await createSiloAdjustment( - data, - payload.user - ); + const user = c.get("user"); - return c.json( - { - success: createSiloAdj.success, - message: createSiloAdj.message, - data: createSiloAdj.data, - }, - 200 - ); - } catch (error) { - //console.log(error); - //return apiReturn(c, false, "Error in setting the user access", error, 400); - return c.json( - { - success: false, - message: "Missing data please try again", - error, - }, - 400 - ); - } - } catch (error) { - return c.json({ success: false, message: "Unauthorized" }, 401); - } - } + try { + try { + //return apiReturn(c, true, access?.message, access?.data, 200); + const createSiloAdj = await createSiloAdjustment(data, c.get("user")); + + return c.json( + { + success: createSiloAdj.success, + message: createSiloAdj.message, + data: createSiloAdj.data, + }, + 200, + ); + } catch (error) { + //console.log(error); + //return apiReturn(c, false, "Error in setting the user access", error, 400); + return c.json( + { + success: false, + message: "Missing data please try again", + error, + }, + 400, + ); + } + } catch (error) { + return c.json({ success: false, message: "Unauthorized" }, 401); + } + }, ); export default app; diff --git a/lstV2/server/services/logistics/route/siloAdjustments/postComment.ts b/lstV2/server/services/logistics/route/siloAdjustments/postComment.ts index bedd559..dec203f 100644 --- a/lstV2/server/services/logistics/route/siloAdjustments/postComment.ts +++ b/lstV2/server/services/logistics/route/siloAdjustments/postComment.ts @@ -1,88 +1,85 @@ import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; 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 { authMiddleware } from "../../../auth/middleware/authMiddleware.js"; import { createSiloAdjustment } from "../../controller/siloAdjustments/createSiloAdjustment.js"; import { postSiloComment } from "../../controller/siloAdjustments/postComment.js"; -import { apiHit } from "../../../../globalUtils/apiHits.js"; const app = new OpenAPIHono(); const ParamsSchema = z.object({ - adjId: z - .string() - .min(3) - .openapi({ - param: { - name: "adjId", - in: "path", - }, - example: "3b555052-a960-4301-8d38-a6f1acb98dbe", - }), + adjId: z + .string() + .min(3) + .openapi({ + param: { + name: "adjId", + in: "path", + }, + example: "3b555052-a960-4301-8d38-a6f1acb98dbe", + }), }); const Body = z.object({ - comment: z - .string() - .openapi({ example: "Reason to why i had a badd adjustment." }), + comment: z + .string() + .openapi({ example: "Reason to why i had a badd adjustment." }), }); app.openapi( - createRoute({ - tags: ["logistics"], - summary: "Post a comment to why you had a discrepancy", - method: "post", - path: "/postcomment/:adjId", - middleware: authMiddleware, - request: { - params: ParamsSchema, - body: { content: { "application/json": { schema: Body } } }, - }, - // description: - // "Creates a silo adjustment for the silo if and stores the stock numbers.", - responses: responses(), - }), - async (c: any) => { - apiHit(c, { endpoint: "/postcomment" }); - const authHeader = c.req.header("Authorization"); - const token = authHeader?.split("Bearer ")[1] || ""; - const { adjId } = c.req.valid("param"); + createRoute({ + tags: ["logistics"], + summary: "Post a comment to why you had a discrepancy", + method: "post", + path: "/postcomment/:adjId", + middleware: authMiddleware, + request: { + params: ParamsSchema, + body: { content: { "application/json": { schema: Body } } }, + }, + // description: + // "Creates a silo adjustment for the silo if and stores the stock numbers.", + responses: responses(), + }), + async (c: any) => { + apiHit(c, { endpoint: "/postcomment" }); + const { adjId } = c.req.valid("param"); - try { - const payload = await verify(token, process.env.JWT_SECRET!); - try { - //return apiReturn(c, true, access?.message, access?.data, 200); - const data = await c.req.json(); + try { + try { + //return apiReturn(c, true, access?.message, access?.data, 200); + const data = await c.req.json(); - const addComment = await postSiloComment( - adjId, - data.comment, - data.key, - payload.user - ); + const addComment = await postSiloComment( + adjId, + data.comment, + data.key, + c.get("user"), + ); - console.log(addComment); - return c.json( - { - success: addComment.success, - message: addComment.message, - data: addComment.data, - }, - 200 - ); - } catch (error) { - return c.json( - { - success: false, - message: "Missing data please try again", - error, - }, - 400 - ); - } - } catch (error) { - return c.json({ success: false, message: "Unauthorized" }, 401); - } - } + console.log(addComment); + return c.json( + { + success: addComment.success, + message: addComment.message, + data: addComment.data, + }, + 200, + ); + } catch (error) { + return c.json( + { + success: false, + message: "Missing data please try again", + error, + }, + 400, + ); + } + } catch (error) { + return c.json({ success: false, message: "Unauthorized" }, 401); + } + }, ); export default app; diff --git a/lstV2/server/services/notifications/routes/getActiveNotifications.ts b/lstV2/server/services/notifications/routes/getActiveNotifications.ts index 04ae043..b352105 100644 --- a/lstV2/server/services/notifications/routes/getActiveNotifications.ts +++ b/lstV2/server/services/notifications/routes/getActiveNotifications.ts @@ -1,31 +1,33 @@ // an external way to creating logs 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 { 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 }); app.openapi( - createRoute({ - tags: ["server"], - summary: "Returns current active notifications.", - method: "get", - path: "/activenotifications", - //middleware: authMiddleware, - responses: responses(), - }), - async (c) => { - apiHit(c, { endpoint: "/activenotifications" }); - const jobs = getAllJobs(); - return c.json({ - success: true, - message: - jobs.length === 0 - ? "There are no active Notifications Currently." - : "Current Active notifications", - data: jobs, - }); - } + createRoute({ + tags: ["server"], + summary: "Returns current active notifications.", + method: "get", + path: "/activenotifications", + middleware: [authMiddleware, hasCorrectRole(["systemAdmin"], "admin")], + responses: responses(), + }), + async (c) => { + apiHit(c, { endpoint: "/activenotifications" }); + const jobs = getAllJobs(); + return c.json({ + success: true, + message: + jobs.length === 0 + ? "There are no active Notifications Currently." + : "Current Active notifications", + data: jobs, + }); + }, ); export default app; diff --git a/lstV2/server/services/server/utils/subModuleCheck.ts b/lstV2/server/services/server/utils/subModuleCheck.ts index ca3546d..0c28f85 100644 --- a/lstV2/server/services/server/utils/subModuleCheck.ts +++ b/lstV2/server/services/server/utils/subModuleCheck.ts @@ -6,253 +6,254 @@ import { db } from "../../../../database/dbclient.js"; import { subModules } from "../../../../database/schema/subModules.js"; import { createLog } from "../../logger/logger.js"; + // "view", "technician", "supervisor","manager", "admin", "systemAdmin" const newSubModules = [ - { - name: "RFID", - moduleName: "prodcution", - description: "RFID stuff", - link: "/rfid", - icon: "Tags", - active: true, - roles: [ - "viewer", - "technician", - "supervisor", - "manager", - "admin", - "systemAdmin", - ], - subSubModule: [], - }, - { - name: "Silo Adjustments", - moduleName: "logistics", - description: "Do a silo adjustmnet", - link: "/siloAdjustments", - icon: "Cylinder", - active: false, - roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - subSubModule: [], - }, - { - name: "Demand Management", - moduleName: "logistics", - description: "Bulk order and Forecast imports", - link: "/dm", - icon: "Truck", - roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - active: false, - subSubModule: [], - }, - { - name: "Forecast", - moduleName: "logistics", - description: "", - link: "#", - icon: "Truck", - roles: ["systemAdmin"], - active: false, - subSubModule: [], - }, - { - name: "Material Helper", - moduleName: "logistics", - description: "", - link: "/materialHelper/consumption", - icon: "Package", - roles: [ - "viewer", - "technician", - "supervisor", - "manager", - "admin", - "systemAdmin", - ], - active: false, - subSubModule: [], - }, - { - name: "Ocme Cyclecount", - moduleName: "logistics", - description: "", - link: "/cyclecount", - icon: "Package", - roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - active: false, - subSubModule: [], - }, - { - name: "Open Orders", - moduleName: "logistics", - description: "Open orders", - link: "/openOrders", - icon: "Truck", - roles: [ - "viewer", - "technician", - "supervisor", - "manager", - "admin", - "systemAdmin", - ], - active: false, - subSubModule: [], - }, - { - name: "Barcodes", - moduleName: "logistics", - description: "Barcodes, lanes and scanable", - link: "/barcodegen", - icon: "Barcode", - roles: [ - "viewer", - "technician", - "supervisor", - "manager", - "admin", - "systemAdmin", - ], - active: true, - subSubModule: [], - }, - { - name: "Helper Commands", - moduleName: "logistics", - description: "Commands to assist when a scanner is not avalible", - link: "/helpercommands", - icon: "Command", - roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], - active: true, - subSubModule: [], - }, + { + name: "RFID", + moduleName: "prodcution", + description: "RFID stuff", + link: "/rfid", + icon: "Tags", + active: true, + roles: [ + "viewer", + "technician", + "supervisor", + "manager", + "admin", + "systemAdmin", + ], + subSubModule: [], + }, + { + name: "siloAdjustments", + moduleName: "logistics", + description: "Do a silo adjustments", + link: "/siloAdjustments", + icon: "Cylinder", + active: false, + roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], + subSubModule: [], + }, + { + name: "demandManagement", + moduleName: "logistics", + description: "Bulk order and Forecast imports", + link: "/dm", + icon: "Truck", + roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], + active: false, + subSubModule: [], + }, + { + name: "Forecast", + moduleName: "logistics", + description: "", + link: "#", + icon: "Truck", + roles: ["systemAdmin"], + active: false, + subSubModule: [], + }, + { + name: "Material Helper", + moduleName: "logistics", + description: "", + link: "/materialHelper/consumption", + icon: "Package", + roles: [ + "viewer", + "technician", + "supervisor", + "manager", + "admin", + "systemAdmin", + ], + active: false, + subSubModule: [], + }, + { + name: "Ocme Cyclecount", + moduleName: "logistics", + description: "", + link: "/cyclecount", + icon: "Package", + roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], + active: false, + subSubModule: [], + }, + { + name: "Open Orders", + moduleName: "logistics", + description: "Open orders", + link: "/openOrders", + icon: "Truck", + roles: [ + "viewer", + "technician", + "supervisor", + "manager", + "admin", + "systemAdmin", + ], + active: false, + subSubModule: [], + }, + { + name: "Barcodes", + moduleName: "logistics", + description: "Barcodes, lanes and scanable", + link: "/barcodegen", + icon: "Barcode", + roles: [ + "viewer", + "technician", + "supervisor", + "manager", + "admin", + "systemAdmin", + ], + active: true, + subSubModule: [], + }, + { + name: "Helper Commands", + moduleName: "logistics", + description: "Commands to assist when a scanner is not avalible", + link: "/helpercommands", + icon: "Command", + roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"], + active: true, + subSubModule: [], + }, - // admin module - { - name: "Servers", - moduleName: "admin", - description: "Do a silo adjustmnet", - link: "/servers", - icon: "Server", - roles: ["tester", "systemAdmin"], - isActive: true, - subSubModule: [], - }, - { - name: "Admin", - moduleName: "admin", - description: "Do a silo adjustmnet", - link: "#", // when link is # this will mean its a button - icon: "ShieldCheck", - active: true, - roles: ["tester", "admin", "systemAdmin"], - subSubModule: [ - { - name: "Settings", - link: "/settings", - icon: "Settings", - newWindow: false, - isActive: true, - }, - { - name: "Modules", - link: "/modules", - icon: "Settings", - newWindow: false, - isActive: true, - }, - { - name: "Sub Modules", - link: "/subModules", - icon: "Settings", - newWindow: false, - isActive: true, - }, - { - name: "Notifcations", - link: "notificationMGT", - icon: "Webhook", - newWindow: false, - isActive: true, - }, - { - name: "Swagger", - link: "#", - icon: "Webhook", - newWindow: true, - isActive: true, - }, - { - name: "Logs", - link: "#", - icon: "Logs", - newWindow: false, - isActive: false, - }, - { - name: "Users", - link: "/users", - icon: "Users", - newWindow: false, - isActive: true, - }, - { - name: "Prod Perms", - link: "/produsers", - icon: "Users", - newWindow: false, - isActive: true, - }, - { - name: "UCD", - link: "https://ucd.alpla.net:8443/", - icon: "Atom", - newWindow: false, - isActive: true, - }, - { - name: "Lst Api", - link: "/api/docs", - icon: "Webhook", - newWindow: false, - isActive: true, - }, - ], - }, + // admin module + { + name: "Servers", + moduleName: "admin", + description: "Do a silo adjustmnet", + link: "/servers", + icon: "Server", + roles: ["tester", "systemAdmin"], + isActive: true, + subSubModule: [], + }, + { + name: "Admin", + moduleName: "admin", + description: "Do a silo adjustmnet", + link: "#", // when link is # this will mean its a button + icon: "ShieldCheck", + active: true, + roles: ["tester", "admin", "systemAdmin"], + subSubModule: [ + { + name: "Settings", + link: "/settings", + icon: "Settings", + newWindow: false, + isActive: true, + }, + { + name: "Modules", + link: "/modules", + icon: "Settings", + newWindow: false, + isActive: true, + }, + { + name: "Sub Modules", + link: "/subModules", + icon: "Settings", + newWindow: false, + isActive: true, + }, + { + name: "Notifcations", + link: "notificationMGT", + icon: "Webhook", + newWindow: false, + isActive: true, + }, + { + name: "Swagger", + link: "#", + icon: "Webhook", + newWindow: true, + isActive: true, + }, + { + name: "Logs", + link: "#", + icon: "Logs", + newWindow: false, + isActive: false, + }, + { + name: "Users", + link: "/users", + icon: "Users", + newWindow: false, + isActive: true, + }, + { + name: "Prod Perms", + link: "/produsers", + icon: "Users", + newWindow: false, + isActive: true, + }, + { + name: "UCD", + link: "https://ucd.alpla.net:8443/", + icon: "Atom", + newWindow: false, + isActive: true, + }, + { + name: "Lst Api", + link: "/api/docs", + icon: "Webhook", + newWindow: false, + isActive: true, + }, + ], + }, ]; export const areSubModulesIn = async () => { - try { - for (let i = 0; i < newSubModules.length; i++) { - const subModuleUpdate = await db - .insert(subModules) - .values(newSubModules[i]) - .onConflictDoUpdate({ - target: subModules.name, - set: { - name: newSubModules[i].name, - moduleName: newSubModules[i].moduleName, - description: newSubModules[i].description, - roles: newSubModules[i].roles, - link: newSubModules[i].link, - subSubModule: newSubModules[i].subSubModule, - icon: newSubModules[i].icon, - }, - }) // this will only update the ones that are new :D - .returning({ name: subModules.name }); - } - createLog( - "info", - "lst", - "server", - "SubModules were just added due to missing them on server startup" - ); - } catch (error) { - console.log(error); - createLog( - "error", - "lst", - "server", - "There was an error adding new subModules to the db" - ); - } + try { + for (let i = 0; i < newSubModules.length; i++) { + const subModuleUpdate = await db + .insert(subModules) + .values(newSubModules[i]) + .onConflictDoUpdate({ + target: subModules.name, + set: { + name: newSubModules[i].name, + moduleName: newSubModules[i].moduleName, + description: newSubModules[i].description, + roles: newSubModules[i].roles, + link: newSubModules[i].link, + subSubModule: newSubModules[i].subSubModule, + icon: newSubModules[i].icon, + }, + }) // this will only update the ones that are new :D + .returning({ name: subModules.name }); + } + createLog( + "info", + "lst", + "server", + "SubModules were just added due to missing them on server startup", + ); + } catch (error) { + console.log(error); + createLog( + "error", + "lst", + "server", + "There was an error adding new subModules to the db", + ); + } };