refactor(old app): login migration to new app

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

View File

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

View File

@@ -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<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
username: username || "",
password: "",
rememberMe: rememeberMe,
},
});
const {
register,
handleSubmit,
control,
formState: { errors },
} = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
username: username || "",
password: "",
rememberMe: rememeberMe,
},
});
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
// Do something with form data
const onSubmitLogin = async (value: z.infer<typeof FormSchema>) => {
// 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 (
<div className="ml-[25%]">
<LstCard className="p-3 w-96">
<CardHeader>
<div>
<p className="text-2xl">Login to LST</p>
</div>
</CardHeader>
<hr className="rounded"></hr>
<form onSubmit={handleSubmit(onSubmitLogin)}>
<div>
<Label htmlFor="username" className="m-1">
Username
</Label>
<Input
placeholder="smith001"
{...register("username")}
className={errors.username ? "border-red-500" : ""}
aria-invalid={!!errors.username}
/>
{errors.username && (
<p className="text-red-500 text-sm mt-1">
{errors.username.message}
</p>
)}
</div>
<div>
<>
<Label htmlFor={"password"} className="m-1">
Password
</Label>
<Input
type="password"
{...register("password")}
className={errors.password ? "border-red-500" : ""}
aria-invalid={!!errors.password}
/>
{errors.password && (
<p className="text-red-500 text-sm mt-1">
{errors.password.message}
</p>
)}
</>
</div>
<div className="flex justify-between pt-2">
<div className="flex">
<Controller
render={({ field }) => (
<>
<Checkbox
id="remember"
checked={field.value}
onCheckedChange={field.onChange}
/>
<label
htmlFor="remember"
className="pl-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
remember me
</label>
</>
)}
control={control}
name="rememberMe"
defaultValue={rememeberMe}
/>
</div>
return (
<div className="ml-[25%]">
<LstCard className="p-3 w-96">
<CardHeader>
<div>
<p className="text-2xl">Login to LST</p>
</div>
</CardHeader>
<hr className="rounded"></hr>
<form onSubmit={handleSubmit(onSubmitLogin)}>
<div>
<Label htmlFor="username" className="m-1">
Username
</Label>
<Input
placeholder="smith001"
{...register("username")}
className={errors.username ? "border-red-500" : ""}
aria-invalid={!!errors.username}
/>
{errors.username && (
<p className="text-red-500 text-sm mt-1">
{errors.username.message}
</p>
)}
</div>
<div>
<>
<Label htmlFor={"password"} className="m-1">
Password
</Label>
<Input
type="password"
{...register("password")}
className={
errors.password ? "border-red-500" : ""
}
aria-invalid={!!errors.password}
/>
{errors.password && (
<p className="text-red-500 text-sm mt-1">
{errors.password.message}
</p>
)}
</>
</div>
<div className="flex justify-between pt-2">
<div className="flex">
<Controller
render={({ field }) => (
<>
<Checkbox
id="remember"
checked={field.value}
onCheckedChange={field.onChange}
/>
<label
htmlFor="remember"
className="pl-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
remember me
</label>
</>
)}
control={control}
name="rememberMe"
defaultValue={rememeberMe}
/>
</div>
<div className="flex justify-end">
<Button type="submit">Submit</Button>
</div>
</div>
</form>
</LstCard>
</div>
);
<div className="flex justify-end">
<Button type="submit">Submit</Button>
</div>
</div>
</form>
</LstCard>
</div>
);
};
export default LoginForm;

View File

@@ -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 (
<Sidebar collapsible="icon">
<SidebarContent>
<Header />
{moduleActive("production") && (
<ProductionSideBar
user={user}
moduleID={
modules.filter((n) => n.name === "production")[0]
.module_id as string
}
/>
)}
{moduleActive("logistics") && (
<LogisticsSideBar
user={user}
moduleID={
modules.filter((n) => n.name === "logistics")[0]
.module_id as string
}
/>
)}
{moduleActive("forklift") &&
hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
{moduleActive("eom") && hasAccess(user, "eom", modules) && (
<EomSideBar />
)}
{moduleActive("quality") &&
hasAccess(user, "quality", modules) && <QualitySideBar />}
{moduleActive("admin") && hasAccess(user, "admin", modules) && (
<AdminSideBar />
)}
</SidebarContent>
<SidebarFooter>
<SidebarTrigger />
</SidebarFooter>
</Sidebar>
);
return (
<Sidebar collapsible="icon">
<SidebarContent>
<Header />
{moduleActive("production") && (
<ProductionSideBar
user={user}
moduleID={
modules.filter((n) => n.name === "production")[0]
.module_id as string
}
/>
)}
{moduleActive("logistics") && hasAccess(user, "logistics") && (
<LogisticsSideBar user={user} />
)}
{moduleActive("forklift") && hasAccess(user, "forklift") && (
<ForkliftSideBar />
)}
{moduleActive("eom") && hasAccess(user, "eom") && <EomSideBar />}
{moduleActive("quality") && hasAccess(user, "quality") && (
<QualitySideBar />
)}
{moduleActive("admin") && hasAccess(user || [], "admin") && (
<AdminSideBar />
)}
</SidebarContent>
<SidebarFooter>
<SidebarTrigger />
</SidebarFooter>
</Sidebar>
);
}

View File

@@ -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 (
<SidebarGroup>
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => {
const Icon = iconMap[item.icon];
return (
<SidebarMenuItem key={item.submodule_id}>
<>
{hasPageAccess(
user,
item.roles,
moduleID
) &&
item.active && (
<SidebarMenuButton asChild>
<a href={item.link}>
<Icon />
<span>{item.name}</span>
</a>
</SidebarMenuButton>
)}
</>
</SidebarMenuItem>
);
})}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
);
return (
<SidebarGroup>
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => {
const Icon = iconMap[item.icon];
return (
<SidebarMenuItem key={item.submodule_id}>
<>
{hasPageAccess(user, item.roles, item.name) && (
<SidebarMenuButton asChild>
<a href={item.link}>
<Icon />
<span>{item.name}</span>
</a>
</SidebarMenuButton>
)}
</>
</SidebarMenuItem>
);
})}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
);
}

View File

@@ -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 (
<LstCard>
<div className="flex flex-row">
<LstCard className="grow m-1 max-w-[400px]">
<CardHeader>{silo.Description}</CardHeader>
<div className="m-1">
<hr className="m-2" />
<span>Current Stock: </span>
{silo.Stock_Total}
<hr className="m-2" />
<span>Last date adjusted </span>
{format(silo.LastAdjustment, "M/dd/yyyy")}
<hr className="m-2" />
</div>
<div>
{silo.Stock_Total === 0 ? (
<div className="flex justify-center flex-col">
<span>
The silo is currently empty you will not be
able to do an adjustment until you have
received material in.
</span>
<hr />
<ul>
<li>
-Someone click "Take inventory on a
empty location" in stock.
</li>
<li>
-Silo virtualy ran empty due to
production over consumption.
</li>
<li>
-Someone forgot to move a railcar
compartment over to this location.
</li>
</ul>
</div>
) : (
<>
{user &&
roles.includes(accessRoles[0]?.role) && (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<form.Field
name="newLevel"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 1
? undefined
: "You must enter a value greate than 1",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<div className="flex flex-row">
<Label htmlFor="newLevel">
New level
</Label>
<div>
<Disclaimer />
</div>
</div>
<div className="flex flex-row">
<Input
name={
field.name
}
value={
field
.state
.value
}
onBlur={
field.handleBlur
}
type="decimal"
onChange={(
e
) =>
field.handleChange(
e
.target
.value
)
}
/>
<Button
className="ml-1"
variant="outline"
type="submit"
onClick={
form.handleSubmit
}
disabled={
submitting
}
>
{submitting ? (
<span className="w-24">
Submitting...
</span>
) : (
<span className="w-24">
Submit
</span>
)}
</Button>
</div>
return (
<LstCard>
<div className="flex flex-row">
<LstCard className="grow m-1 max-w-[400px]">
<CardHeader>{silo.Description}</CardHeader>
<div className="m-1">
<hr className="m-2" />
<span>Current Stock: </span>
{silo.Stock_Total}
<hr className="m-2" />
<span>Last date adjusted </span>
{format(silo.LastAdjustment, "M/dd/yyyy")}
<hr className="m-2" />
</div>
<div>
{silo.Stock_Total === 0 ? (
<div className="flex justify-center flex-col">
<span>
The silo is currently empty you will not be able to do an
adjustment until you have received material in.
</span>
<hr />
<ul>
<li>
-Someone click "Take inventory on a empty location" in
stock.
</li>
<li>
-Silo virtualy ran empty due to production over consumption.
</li>
<li>
-Someone forgot to move a railcar compartment over to this
location.
</li>
</ul>
</div>
) : (
<>
{user && roles.includes(accessRoles[0]?.role) && (
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<form.Field
name="newLevel"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 1
? undefined
: "You must enter a value greate than 1",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<div className="flex flex-row">
<Label htmlFor="newLevel">New level</Label>
<div>
<Disclaimer />
</div>
</div>
<div className="flex flex-row">
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
type="decimal"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
<Button
className="ml-1"
variant="outline"
type="submit"
onClick={form.handleSubmit}
disabled={submitting}
>
{submitting ? (
<span className="w-24">Submitting...</span>
) : (
<span className="w-24">Submit</span>
)}
</Button>
</div>
{field.state.meta
.errors
.length ? (
<em>
{field.state.meta.errors.join(
","
)}
</em>
) : null}
</div>
);
}}
/>
</form>
)}
</>
)}
</div>
</LstCard>
<div className="grow max-w-[600px]">
<ChartData laneId={silo.LocationID} />
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
</form>
)}
</>
)}
</div>
</LstCard>
<div className="grow max-w-[600px]">
<ChartData laneId={silo.LocationID} />
<div className="flex justify-end m-1 gap-3">
<AttachSilo silo={silo} />
<DetachSilo silo={silo} />
<Button variant="outline">
<Link
to={"/siloAdjustments/$hist"}
params={{ hist: silo.LocationID }}
>
Historical Data
</Link>
</Button>
</div>
</div>
</div>
</LstCard>
);
<div className="flex justify-end m-1 gap-3">
<AttachSilo silo={silo} />
<DetachSilo silo={silo} />
<Button variant="outline">
<Link
to={"/siloAdjustments/$hist"}
params={{ hist: silo.LocationID }}
>
Historical Data
</Link>
</Button>
</div>
</div>
</div>
</LstCard>
);
}
const Disclaimer = () => {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<CircleAlert className="ml-1 w-[14px]" />
</TooltipTrigger>
<TooltipContent className="max-w-48">
<p className="text-pretty">
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
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<CircleAlert className="ml-1 w-[14px]" />
</TooltipTrigger>
<TooltipContent className="max-w-48">
<p className="text-pretty">
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
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};

View File

@@ -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 (
<div className="m-2 p-2 min-h-2/5">
<ScrollArea className="max-h-1/2 rounded-md border p-4">
<LstCard>
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>
{l.label}
</TableHead>
))}
</TableRow>
</TableHeader>
if (isError) {
return (
<div className="m-2 p-2 min-h-2/5">
<ScrollArea className="max-h-1/2 rounded-md border p-4">
<LstCard>
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
</ScrollArea>
</div>
);
}
return (
<LstCard className="m-2 p-2 min-h-2/5">
<ScrollArea className="h-[400px]">
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{lotdata.map((lot: LotType) => (
<TableRow key={lot.LabelOnlineID}>
<TableCell className="font-medium">
{lot.MachineLocation}
</TableCell>
<TableCell className="font-medium">
{lot.AV}
</TableCell>
<TableCell className="font-medium">
{lot.Alias}
</TableCell>
<TableCell
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
>
{lot.lot}
</TableCell>
<TableCell
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
>
{lot.ProlinkLot}
</TableCell>
<TableCell className="font-medium">
{lot.PlannedQTY}
</TableCell>
<TableCell className="font-medium">
{lot.Produced}
</TableCell>
<TableCell className="font-medium">
{lot.Remaining}
</TableCell>
<TableCell className="font-medium">
{lot.overPrinting}
</TableCell>
{user &&
roles.includes(
accessRoles[0]?.role
) && (
<>
{server === "usday1vms006" ||
server === "localhost" ? (
<>
<TableCell className="flex justify-center">
<ManualPrintForm />
</TableCell>
</>
) : (
<TableCell className="flex justify-center">
<ManualPrint
lot={lot}
/>
</TableCell>
)}
</>
)}
</TableRow>
))}
</TableBody>
)}
</Table>
</ScrollArea>
</LstCard>
);
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
</ScrollArea>
</div>
);
}
return (
<LstCard className="m-2 p-2 min-h-2/5">
<ScrollArea className="h-[400px]">
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{lotdata.map((lot: LotType) => (
<TableRow key={lot.LabelOnlineID}>
<TableCell className="font-medium">
{lot.MachineLocation}
</TableCell>
<TableCell className="font-medium">{lot.AV}</TableCell>
<TableCell className="font-medium">{lot.Alias}</TableCell>
<TableCell
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
>
{lot.lot}
</TableCell>
<TableCell
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
>
{lot.ProlinkLot}
</TableCell>
<TableCell className="font-medium">
{lot.PlannedQTY}
</TableCell>
<TableCell className="font-medium">{lot.Produced}</TableCell>
<TableCell className="font-medium">{lot.Remaining}</TableCell>
<TableCell className="font-medium">
{lot.overPrinting}
</TableCell>
{user && roles.includes(accessRoles[0]?.role) && (
<>
{server === "usday1vms006" || server === "localhost" ? (
<>
<TableCell className="flex justify-center">
<ManualPrintForm />
</TableCell>
</>
) : (
<TableCell className="flex justify-center">
<ManualPrint lot={lot} />
</TableCell>
)}
</>
)}
</TableRow>
))}
</TableBody>
)}
</Table>
</ScrollArea>
</LstCard>
);
}

View File

@@ -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 (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
// 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 (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
};

View File

@@ -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;
};

View File

@@ -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,
};
};

View File

@@ -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<SessionState>((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<typeof useSessionStore>;

View File

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

View File

@@ -1,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<void>;
setUserRoles: (userRoles: Modules[]) => void;
fetchUserRoles: () => Promise<void>;
setUserRoles: (userRoles: Modules[]) => void;
}
interface FetchModulesResponse {
data: Modules[];
data: Modules[];
}
export const useGetUserRoles = create<SettingState>()((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);
}
},
}));

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
// }
// };

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<string, { lastSeen: number; expiresAt: number }> =
{};
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] || "";

View File

@@ -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;

View File

@@ -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 };
}
};

View File

@@ -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,
},
};
}
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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",
);
}
};