Compare commits

..

19 Commits

Author SHA1 Message Date
63b1151cb7 fix(misc): work on ocp to improve the errors that were missed and better logging 2025-03-30 10:11:58 -05:00
a5dee58223 refactor(server): removed console logs 2025-03-30 10:11:29 -05:00
9784072aab refactor(format changes): changes to the file formats to match across computers 2025-03-30 10:10:53 -05:00
f9096b54f5 fix(admin auth): added in role change for v1 2025-03-30 10:10:01 -05:00
11e5cf4d86 refactor(lst): added huston backin 2025-03-30 10:09:32 -05:00
a647d05d3b chore(release): bump build number to 125 2025-03-30 10:03:20 -05:00
098c477119 chore(release): bump build number to 124 2025-03-30 09:44:19 -05:00
3228ad7892 feat(lst): script added for the test server to readd the permissions once it boots up 2025-03-30 08:41:55 -05:00
c27ad7cf6a refactor(lst): added in a removal of old files so we can keep the server clean 2025-03-30 08:41:26 -05:00
a48d4bd5af feat(auth): admin user updates added
if a password change happens then an email will be sent to the user.
2025-03-30 08:40:49 -05:00
09c0825194 chore(release): bump build number to 123 2025-03-30 05:09:52 -05:00
28fbf2c1e4 chore(release): bump build number to 122 2025-03-29 18:26:57 -05:00
af5dc9266f chore(release): bump build number to 121 2025-03-29 12:16:23 -05:00
b903c8ee2d chore(release): bump build number to 120 2025-03-29 12:15:02 -05:00
035eda9aa8 chore(release): bump build number to 119 2025-03-29 12:13:16 -05:00
1f7c33d871 chore(release): bump build number to 118 2025-03-29 07:54:44 -05:00
d046c4ea41 chore(release): bump build number to 117 2025-03-29 07:39:34 -05:00
88258baf9d chore(release): bump build number to 116 2025-03-28 14:50:34 -05:00
82acfcc4a9 chore(release): bump build number to 116 2025-03-28 14:20:37 -05:00
31 changed files with 2277 additions and 316 deletions

View File

@@ -1,7 +1,14 @@
import {text, pgTable, timestamp, uuid, uniqueIndex, jsonb} from "drizzle-orm/pg-core";
import {createSelectSchema} from "drizzle-zod";
import {z} from "zod";
import {modules} from "./modules.js";
import {
text,
pgTable,
timestamp,
uuid,
uniqueIndex,
jsonb,
} from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
import { z } from "zod";
import { modules } from "./modules.js";
export const settings = pgTable(
"settings",

File diff suppressed because it is too large Load Diff

View File

@@ -8,11 +8,12 @@
"build": "rimraf dist && tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview",
"shad": "npx shadcn@canary add ",
"shad": "npx shadcn@latest add ",
"checkupdates": "npm-check-updates"
},
"dependencies": {
"@hookform/resolvers": "^4.1.3",
"@radix-ui/react-accordion": "^1.2.3",
"@radix-ui/react-avatar": "^1.1.3",
"@radix-ui/react-checkbox": "^1.1.4",
"@radix-ui/react-collapsible": "^1.1.3",
@@ -27,6 +28,7 @@
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-tooltip": "^1.1.8",
"@tailwindcss/vite": "^4.0.15",
"@tanstack/react-form": "^1.2.1",
"@tanstack/react-query": "^5.69.0",
"@tanstack/react-router": "^1.114.27",
"@tanstack/react-table": "^8.21.2",
@@ -46,6 +48,7 @@
"react-dom": "^19.0.0",
"react-grid-layout": "^1.5.1",
"react-hook-form": "^7.54.2",
"react-resizable-panels": "^2.1.7",
"sonner": "^2.0.1",
"tailwind-merge": "^3.0.2",
"tailwindcss": "^4.0.15",

View File

@@ -1,12 +1,12 @@
import { LstCard } from "@/components/extendedUI/LstCard";
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 { useModuleStore } from "@/lib/store/useModuleStore";
@@ -21,105 +21,121 @@ import StopServer from "./StopServer";
import StartServer from "./StartServer";
export type Servers = {
server_id?: string;
sName?: string;
serverDNS?: string;
plantToken?: string;
idAddress: string;
lastUpdated: string;
isUpgrading: boolean;
server_id?: string;
sName?: string;
serverDNS?: string;
plantToken?: string;
idAddress: string;
lastUpdated: string;
isUpgrading: boolean;
};
export default function ServerPage() {
const { user, token } = useSessionStore();
const { modules } = useModuleStore();
const router = useRouter();
const { user, token } = useSessionStore();
const { modules } = useModuleStore();
const router = useRouter();
const { data, isError, error, isLoading } = useQuery(getServers(token ?? ""));
const { data, isError, error, isLoading } = useQuery(
getServers(token ?? "")
);
const adminModule = modules.filter((n) => n.name === "admin");
const userLevel =
user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) || [];
const adminModule = modules.filter((n) => n.name === "admin");
const userLevel =
user?.roles?.filter((r) => r.module_id === adminModule[0].module_id) ||
[];
if (!adminModule[0]?.roles?.includes(userLevel[0]?.role)) {
router.navigate({ to: "/" });
}
if (!adminModule[0]?.roles?.includes(userLevel[0]?.role)) {
router.navigate({ to: "/" });
}
if (isError) {
return <div>{JSON.stringify(error)}</div>;
}
if (isError) {
return <div>{JSON.stringify(error)}</div>;
}
console.log(data);
return (
<LstCard className="m-2 flex place-content-center w-dvh">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Server</TableHead>
<TableHead>PlantToken</TableHead>
<TableHead>IP Address</TableHead>
<TableHead>Date Last updated</TableHead>
<TableHead>Update Server</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>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{data?.map((server: Servers) => {
const strippedDate = server.lastUpdated.replace("Z", ""); // Remove Z
const formattedDate = format(strippedDate, "MM/dd/yyyy hh:mm a");
return (
<TableRow key={server.server_id}>
<TableCell className="font-medium">{server.sName}</TableCell>
<TableCell className="font-medium">
{server.serverDNS}
</TableCell>
<TableCell className="font-medium">
{server.plantToken}
</TableCell>
<TableCell className="font-medium">
{server.idAddress}
</TableCell>
<TableCell className="font-medium">{formattedDate}</TableCell>
<TableCell className="font-medium">
{adminUrlCheck() && (
<div className="flex flex-row">
<UpdateServer server={server} token={token as string} />
<StartServer />
<StopServer />
<RestartServer />
</div>
)}
</TableCell>
</TableRow>
);
})}
</TableBody>
)}
</Table>
</LstCard>
);
//console.log(data);
return (
<LstCard className="m-2 flex place-content-center w-dvh">
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Server</TableHead>
<TableHead>PlantToken</TableHead>
<TableHead>IP Address</TableHead>
<TableHead>Date Last updated</TableHead>
<TableHead>Update Server</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>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{data?.map((server: Servers) => {
const strippedDate = server.lastUpdated.replace(
"Z",
""
); // Remove Z
const formattedDate = format(
strippedDate,
"MM/dd/yyyy hh:mm a"
);
return (
<TableRow key={server.server_id}>
<TableCell className="font-medium">
{server.sName}
</TableCell>
<TableCell className="font-medium">
{server.serverDNS}
</TableCell>
<TableCell className="font-medium">
{server.plantToken}
</TableCell>
<TableCell className="font-medium">
{server.idAddress}
</TableCell>
<TableCell className="font-medium">
{formattedDate}
</TableCell>
<TableCell className="font-medium">
{adminUrlCheck() && (
<div className="flex flex-row">
<UpdateServer
server={server}
token={token as string}
/>
<StartServer />
<StopServer />
<RestartServer />
</div>
)}
</TableCell>
</TableRow>
);
})}
</TableBody>
)}
</Table>
</LstCard>
);
}

View File

@@ -0,0 +1,43 @@
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
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());
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>
);
return (
<div className="m-2 w-dvw">
<Accordion type="single" collapsible>
{data.map((u: any) => {
return (
<AccordionItem key={u.user_id} value={u.user_id}>
<AccordionTrigger>
<span>{u.username}</span>
</AccordionTrigger>
<AccordionContent>
<div>
<UserCard user={u} />
</div>
</AccordionContent>
</AccordionItem>
);
})}
</Accordion>
</div>
);
}

View File

@@ -0,0 +1,238 @@
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { DebugButton } from "@/utils/formStuff/debugButton";
import { userFormOptions } from "@/utils/formStuff/options/userformOptions";
import { generatePassword } from "@/utils/passwordGen";
import { getUsers } from "@/utils/querys/admin/users";
import { useForm } from "@tanstack/react-form";
import { useQuery } from "@tanstack/react-query";
import axios from "axios";
import { toast } from "sonner";
export default function UserCard(data: any) {
const token = localStorage.getItem("auth_token");
const { refetch } = useQuery(getUsers());
const form = useForm({
...userFormOptions(data.user),
onSubmit: async ({ value }) => {
// Do something with form data
const userData = { ...value, user_id: data.user.user_id };
try {
const res = await axios.patch(
"/api/auth/updateuser",
userData,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
if (res.data.success) {
toast.success(res.data.message);
refetch();
form.reset();
} else {
res.data.message;
}
} catch (error) {
console.log(error);
}
},
});
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<form.Field
name="username"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 3
? undefined
: "Username must be longer than 3 letters",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<Label htmlFor="username">Username</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
<form.Field
name="email"
validators={{
// We can choose between form-wide and field-specific validators
onChange: ({ value }) =>
value.length > 3
? undefined
: "You must enter a correct ",
}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<Label htmlFor="email">Email</Label>
<Input
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
<form.Field
name="role"
//listeners={{onChange: ({value})=>{}}}
children={(field) => {
return (
<div className="m-2 min-w-48 max-w-96 p-2">
<Label htmlFor={field.name}>Select role</Label>
<Select
value={field.state.value}
onValueChange={field.handleChange}
>
<SelectTrigger className="w-[180px]">
<SelectValue
id={field.name}
placeholder="Select Role"
/>
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Roles</SelectLabel>
<SelectItem value="viewer">
Viewer
</SelectItem>
<SelectItem value="operator">
Operator
</SelectItem>
<SelectItem value="manager">
Manager
</SelectItem>
<SelectItem value="admin">
Admin
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
);
}}
/>
<form.Field
name="password"
validators={{
onChangeAsyncDebounceMs: 500,
onChangeAsync: ({ value }) => {
if (
window.location.pathname.includes("/users") &&
value.length === 0
) {
return;
}
if (value.length < 4) {
return "Password must be at least 4 characters long.";
}
if (!/[A-Z]/.test(value)) {
return "Password must contain at least one uppercase letter.";
}
if (!/[a-z]/.test(value)) {
return "Password must contain at least one lower case letter.";
}
if (!/[0-9]/.test(value)) {
return "Password must contain at least one number.";
}
if (
!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(
value
)
) {
return "Password must contain at least one special character.";
}
},
}}
children={(field) => {
return (
<div className="m-2 p-2">
<Label htmlFor="password">
Change Password
</Label>
<div className="mt-2 flex flex-row">
<Input
className="min-w-48 max-w-96"
name={field.name}
value={field.state.value}
onBlur={field.handleBlur}
//type="number"
onChange={(e) =>
field.handleChange(e.target.value)
}
/>
<Button
className="ml-2"
onClick={() =>
field.handleChange(
generatePassword(8)
)
}
>
Random password
</Button>
<DebugButton data={form.state.values} />
</div>
{field.state.meta.errors.length ? (
<em>{field.state.meta.errors.join(",")}</em>
) : null}
</div>
);
}}
/>
</form>
<div>
<Button onClick={form.handleSubmit}>Save</Button>
</div>
</div>
);
}

View File

@@ -1,4 +1,14 @@
import {Atom, Logs, Minus, Plus, Server, Settings, ShieldCheck, Users, Webhook} from "lucide-react";
import {
Atom,
Logs,
Minus,
Plus,
Server,
Settings,
ShieldCheck,
Users,
Webhook,
} from "lucide-react";
import {
SidebarGroup,
SidebarGroupContent,
@@ -10,7 +20,11 @@ import {
SidebarMenuSubButton,
SidebarMenuSubItem,
} from "../../ui/sidebar";
import {Collapsible, CollapsibleContent, CollapsibleTrigger} from "../../ui/collapsible";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "../../ui/collapsible";
const items = [
{
@@ -53,9 +67,9 @@ const data = {
},
{
title: "Users",
url: "#",
url: "/users",
icon: Users,
isActive: false,
isActive: true,
},
{
title: "UCD",
@@ -82,7 +96,11 @@ export function AdminSideBar() {
<SidebarGroupContent>
<SidebarMenu>
{data.navMain.map((item, index) => (
<Collapsible key={item.title} defaultOpen={index === 1} className="group/collapsible">
<Collapsible
key={item.title}
defaultOpen={index === 1}
className="group/collapsible"
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
@@ -96,15 +114,25 @@ export function AdminSideBar() {
<CollapsibleContent>
<SidebarMenuSub>
{item.items.map((item) => (
<SidebarMenuSubItem key={item.title}>
<SidebarMenuSubItem
key={item.title}
>
{item.isActive && (
<SidebarMenuSubButton asChild>
<SidebarMenuSubButton
asChild
>
<a
href={item.url}
target={item.newWindow ? "_blank" : "_self"}
target={
item.newWindow
? "_blank"
: "_self"
}
>
<item.icon />
<span>{item.title}</span>
<span>
{item.title}
</span>
</a>
</SidebarMenuSubButton>
)}

View File

@@ -11,14 +11,14 @@ export default function OCPPage() {
const server = settings.filter((n) => n.plantToken === "usday1");
return (
<div className="h-dvh w-full overflow-hidden">
<div className="h-screen w-full ">
<div className="flex flex-wrap gap-2">
<div className="flex flex-col w-4/5 h-dvh">
<div className="">
<Lots />
</div>
<div className="w-5/6">
<div className="w-5/6 h-1/2">
<Tabs defaultValue="ocplogs" className="w-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="ocplogs">

View File

@@ -0,0 +1,64 @@
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
import { ChevronDownIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function Accordion({
...props
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
return <AccordionPrimitive.Root data-slot="accordion" {...props} />
}
function AccordionItem({
className,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return (
<AccordionPrimitive.Item
data-slot="accordion-item"
className={cn("border-b last:border-b-0", className)}
{...props}
/>
)
}
function AccordionTrigger({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
)
}
function AccordionContent({
className,
children,
...props
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
return (
<AccordionPrimitive.Content
data-slot="accordion-content"
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
{...props}
>
<div className={cn("pt-0 pb-4", className)}>{children}</div>
</AccordionPrimitive.Content>
)
}
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }

View File

@@ -0,0 +1,45 @@
"use client";
import { GripVertical } from "lucide-react";
import * as ResizablePrimitive from "react-resizable-panels";
import { cn } from "@/lib/utils";
const ResizablePanelGroup = ({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
<ResizablePrimitive.PanelGroup
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className
)}
{...props}
/>
);
const ResizablePanel = ResizablePrimitive.Panel;
const ResizableHandle = ({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean;
}) => (
<ResizablePrimitive.PanelResizeHandle
className={cn(
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
className
)}
{...props}
>
{withHandle && (
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
<GripVertical className="h-2.5 w-2.5" />
</div>
)}
</ResizablePrimitive.PanelResizeHandle>
);
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };

View File

@@ -20,6 +20,7 @@ import { Route as IndexImport } from './routes/index'
import { Route as OcpIndexImport } from './routes/ocp/index'
import { Route as EomEomImport } from './routes/_eom/eom'
import { Route as AuthProfileImport } from './routes/_auth/profile'
import { Route as AdminUsersImport } from './routes/_admin/users'
import { Route as AdminSettingsImport } from './routes/_admin/settings'
import { Route as AdminServersImport } from './routes/_admin/servers'
import { Route as AdminModulesImport } from './routes/_admin/modules'
@@ -82,6 +83,12 @@ const AuthProfileRoute = AuthProfileImport.update({
getParentRoute: () => AuthRoute,
} as any)
const AdminUsersRoute = AdminUsersImport.update({
id: '/users',
path: '/users',
getParentRoute: () => AdminRoute,
} as any)
const AdminSettingsRoute = AdminSettingsImport.update({
id: '/settings',
path: '/settings',
@@ -200,6 +207,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AdminSettingsImport
parentRoute: typeof AdminImport
}
'/_admin/users': {
id: '/_admin/users'
path: '/users'
fullPath: '/users'
preLoaderRoute: typeof AdminUsersImport
parentRoute: typeof AdminImport
}
'/_auth/profile': {
id: '/_auth/profile'
path: '/profile'
@@ -265,12 +279,14 @@ interface AdminRouteChildren {
AdminModulesRoute: typeof AdminModulesRoute
AdminServersRoute: typeof AdminServersRoute
AdminSettingsRoute: typeof AdminSettingsRoute
AdminUsersRoute: typeof AdminUsersRoute
}
const AdminRouteChildren: AdminRouteChildren = {
AdminModulesRoute: AdminModulesRoute,
AdminServersRoute: AdminServersRoute,
AdminSettingsRoute: AdminSettingsRoute,
AdminUsersRoute: AdminUsersRoute,
}
const AdminRouteWithChildren = AdminRoute._addFileChildren(AdminRouteChildren)
@@ -305,6 +321,7 @@ export interface FileRoutesByFullPath {
'/modules': typeof AdminModulesRoute
'/servers': typeof AdminServersRoute
'/settings': typeof AdminSettingsRoute
'/users': typeof AdminUsersRoute
'/profile': typeof AuthProfileRoute
'/eom': typeof EomEomRoute
'/ocp': typeof OcpIndexRoute
@@ -323,6 +340,7 @@ export interface FileRoutesByTo {
'/modules': typeof AdminModulesRoute
'/servers': typeof AdminServersRoute
'/settings': typeof AdminSettingsRoute
'/users': typeof AdminUsersRoute
'/profile': typeof AuthProfileRoute
'/eom': typeof EomEomRoute
'/ocp': typeof OcpIndexRoute
@@ -344,6 +362,7 @@ export interface FileRoutesById {
'/_admin/modules': typeof AdminModulesRoute
'/_admin/servers': typeof AdminServersRoute
'/_admin/settings': typeof AdminSettingsRoute
'/_admin/users': typeof AdminUsersRoute
'/_auth/profile': typeof AuthProfileRoute
'/_eom/eom': typeof EomEomRoute
'/ocp/': typeof OcpIndexRoute
@@ -364,6 +383,7 @@ export interface FileRouteTypes {
| '/modules'
| '/servers'
| '/settings'
| '/users'
| '/profile'
| '/eom'
| '/ocp'
@@ -381,6 +401,7 @@ export interface FileRouteTypes {
| '/modules'
| '/servers'
| '/settings'
| '/users'
| '/profile'
| '/eom'
| '/ocp'
@@ -400,6 +421,7 @@ export interface FileRouteTypes {
| '/_admin/modules'
| '/_admin/servers'
| '/_admin/settings'
| '/_admin/users'
| '/_auth/profile'
| '/_eom/eom'
| '/ocp/'
@@ -472,7 +494,8 @@ export const routeTree = rootRoute
"children": [
"/_admin/modules",
"/_admin/servers",
"/_admin/settings"
"/_admin/settings",
"/_admin/users"
]
},
"/_auth": {
@@ -506,6 +529,10 @@ export const routeTree = rootRoute
"filePath": "_admin/settings.tsx",
"parent": "/_admin"
},
"/_admin/users": {
"filePath": "_admin/users.tsx",
"parent": "/_admin"
},
"/_auth/profile": {
"filePath": "_auth/profile.tsx",
"parent": "/_auth"

View File

@@ -0,0 +1,10 @@
import UserPage from "@/components/admin/user/UserPage";
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/_admin/users")({
component: RouteComponent,
});
function RouteComponent() {
return <UserPage />;
}

View File

@@ -0,0 +1,5 @@
import { Button } from "@/components/ui/button";
export const DebugButton = (data: any) => {
return <Button onClick={() => console.log(data.data)}>Debug</Button>;
};

View File

@@ -0,0 +1,14 @@
import { formOptions } from "@tanstack/react-form";
export const userFormOptions = (user: any) => {
return formOptions({
defaultValues: {
username: user.username,
password: "",
email: user.email,
role: user.role,
//hobbies: [],
},
// } as Person,
});
};

View File

@@ -0,0 +1,27 @@
export const generatePassword = (length: number) => {
const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const lowercase = "abcdefghijklmnopqrstuvwxyz";
const numbers = "0123456789";
const symbols = "!@#$%&()_+-={}:,.<>?/"; // Safe symbol list
// Ensure the password contains at least one of each required type
let password: any = [
uppercase[Math.floor(Math.random() * uppercase.length)],
lowercase[Math.floor(Math.random() * lowercase.length)],
numbers[Math.floor(Math.random() * numbers.length)],
symbols[Math.floor(Math.random() * symbols.length)],
];
// Fill the rest of the password with random characters from all sets
const allCharacters = uppercase + lowercase;
for (let i = password.length; i < length; i++) {
password.push(
allCharacters[Math.floor(Math.random() * allCharacters.length)]
);
}
// Shuffle the password to avoid predictable patterns
password = password.sort(() => Math.random() - 0.5).join("");
return password;
};

View File

@@ -0,0 +1,26 @@
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getUsers() {
const token = localStorage.getItem("auth_token");
return queryOptions({
queryKey: ["getUsers"],
queryFn: () => fetchUsers(token),
enabled: !!token, // Prevents query if token is null
staleTime: 1000,
//refetchInterval: 2 * 2000,
refetchOnWindowFocus: true,
});
}
const fetchUsers = async (token: string | null) => {
const { data } = await axios.get(`/api/auth/allusers`, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];
};

482
package-lock.json generated
View File

@@ -12,6 +12,7 @@
"@hono/node-server": "^1.14.0",
"@hono/zod-openapi": "^0.19.2",
"@scalar/hono-api-reference": "^0.7.2",
"@tanstack/react-form": "^1.2.1",
"@types/jsonwebtoken": "^9.0.9",
"@types/nodemailer-express-handlebars": "^4.0.5",
"adm-zip": "^0.5.16",
@@ -1548,6 +1549,132 @@
"integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==",
"license": "MIT"
},
"node_modules/@remix-run/node": {
"version": "2.16.3",
"resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.16.3.tgz",
"integrity": "sha512-6FLMNPUwVk/XMZs83li5LvXz0UGG1MXE+6p6rIh29COFASOPEy8tlhu5OSnkMWlGrnaGfjejlSr3lWmdiE864Q==",
"license": "MIT",
"dependencies": {
"@remix-run/server-runtime": "2.16.3",
"@remix-run/web-fetch": "^4.4.2",
"@web3-storage/multipart-parser": "^1.0.0",
"cookie-signature": "^1.1.0",
"source-map-support": "^0.5.21",
"stream-slice": "^0.1.2",
"undici": "^6.11.1"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@remix-run/router": {
"version": "1.23.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
"integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@remix-run/server-runtime": {
"version": "2.16.3",
"resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.16.3.tgz",
"integrity": "sha512-1CRiymt8XjGgyuxvCg1GFLEv0SLUNKeUtYF4a94xHv6Kkx5X+L/YZYxXEeJ3I0czuGcMcPqcqmdwfEo1hoMi8Q==",
"license": "MIT",
"dependencies": {
"@remix-run/router": "1.23.0",
"@types/cookie": "^0.6.0",
"@web3-storage/multipart-parser": "^1.0.0",
"cookie": "^0.6.0",
"set-cookie-parser": "^2.4.8",
"source-map": "^0.7.3",
"turbo-stream": "2.4.0"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@remix-run/server-runtime/node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">= 8"
}
},
"node_modules/@remix-run/web-blob": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@remix-run/web-blob/-/web-blob-3.1.0.tgz",
"integrity": "sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==",
"license": "MIT",
"dependencies": {
"@remix-run/web-stream": "^1.1.0",
"web-encoding": "1.1.5"
}
},
"node_modules/@remix-run/web-fetch": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/@remix-run/web-fetch/-/web-fetch-4.4.2.tgz",
"integrity": "sha512-jgKfzA713/4kAW/oZ4bC3MoLWyjModOVDjFPNseVqcJKSafgIscrYL9G50SurEYLswPuoU3HzSbO0jQCMYWHhA==",
"license": "MIT",
"dependencies": {
"@remix-run/web-blob": "^3.1.0",
"@remix-run/web-file": "^3.1.0",
"@remix-run/web-form-data": "^3.1.0",
"@remix-run/web-stream": "^1.1.0",
"@web3-storage/multipart-parser": "^1.0.0",
"abort-controller": "^3.0.0",
"data-uri-to-buffer": "^3.0.1",
"mrmime": "^1.0.0"
},
"engines": {
"node": "^10.17 || >=12.3"
}
},
"node_modules/@remix-run/web-file": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@remix-run/web-file/-/web-file-3.1.0.tgz",
"integrity": "sha512-dW2MNGwoiEYhlspOAXFBasmLeYshyAyhIdrlXBi06Duex5tDr3ut2LFKVj7tyHLmn8nnNwFf1BjNbkQpygC2aQ==",
"license": "MIT",
"dependencies": {
"@remix-run/web-blob": "^3.1.0"
}
},
"node_modules/@remix-run/web-form-data": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@remix-run/web-form-data/-/web-form-data-3.1.0.tgz",
"integrity": "sha512-NdeohLMdrb+pHxMQ/Geuzdp0eqPbea+Ieo8M8Jx2lGC6TBHsgHzYcBvr0LyPdPVycNRDEpWpiDdCOdCryo3f9A==",
"license": "MIT",
"dependencies": {
"web-encoding": "1.1.5"
}
},
"node_modules/@remix-run/web-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@remix-run/web-stream/-/web-stream-1.1.0.tgz",
"integrity": "sha512-KRJtwrjRV5Bb+pM7zxcTJkhIqWWSy+MYsIxHK+0m5atcznsf15YwUBWHWulZerV2+vvHH1Lp1DD7pw6qKW8SgA==",
"license": "MIT",
"dependencies": {
"web-streams-polyfill": "^3.1.1"
}
},
"node_modules/@scalar/core": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@scalar/core/-/core-0.2.2.tgz",
@@ -1598,6 +1725,76 @@
"node": ">=18"
}
},
"node_modules/@tanstack/form-core": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@tanstack/form-core/-/form-core-1.1.3.tgz",
"integrity": "sha512-BJPBvCB4HkNIKreAlSR3537+/mfV/rLswtMRFeOpmX2eMTriHNpbF5Mam5mblP4TxfjlrroKug50JDwd6+8CtQ==",
"license": "MIT",
"dependencies": {
"@tanstack/store": "^0.7.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-form": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@tanstack/react-form/-/react-form-1.2.1.tgz",
"integrity": "sha512-4tMCOWbPTJSqmL3E6Dt0dS7TVwxHDaScr6Z5SRbQD+eU+iSje+K4kzL17qzBpgNcA+dvXDlZqbDDpKxapXTK6A==",
"license": "MIT",
"dependencies": {
"@remix-run/node": "^2.15.3",
"@tanstack/form-core": "1.1.3",
"@tanstack/react-store": "^0.7.0",
"decode-formdata": "^0.8.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"@tanstack/react-start": "^1.112.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"vinxi": "^0.5.0"
},
"peerDependenciesMeta": {
"@tanstack/react-start": {
"optional": true
},
"vinxi": {
"optional": true
}
}
},
"node_modules/@tanstack/react-store": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.7.0.tgz",
"integrity": "sha512-S/Rq17HaGOk+tQHV/yrePMnG1xbsKZIl/VsNWnNXt4XW+tTY8dTlvpJH2ZQ3GRALsusG5K6Q3unAGJ2pd9W/Ng==",
"license": "MIT",
"dependencies": {
"@tanstack/store": "0.7.0",
"use-sync-external-store": "^1.4.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/@tanstack/store": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.0.tgz",
"integrity": "sha512-CNIhdoUsmD2NolYuaIs8VfWM467RK6oIBAW4nPEKZhg1smZ+/CwtCdpURgp7nxSqOaV9oKkzdWD80+bC66F/Jg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tediousjs/connection-string": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.5.0.tgz",
@@ -1635,6 +1832,12 @@
"@types/node": "*"
}
},
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
"license": "MIT"
},
"node_modules/@types/express-handlebars": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@types/express-handlebars/-/express-handlebars-5.3.1.tgz",
@@ -1790,6 +1993,19 @@
"url": "https://github.com/sponsors/harlan-zw"
}
},
"node_modules/@web3-storage/multipart-parser": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz",
"integrity": "sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==",
"license": "(Apache-2.0 AND MIT)"
},
"node_modules/@zxing/text-encoding": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz",
"integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==",
"license": "(Unlicense OR Apache-2.0)",
"optional": true
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -1946,6 +2162,21 @@
"node": ">=8.0.0"
}
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/axios": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
@@ -2871,6 +3102,24 @@
"node": ">=10"
}
},
"node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"license": "MIT",
"engines": {
"node": ">=6.6.0"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -2990,6 +3239,15 @@
"node": ">=8"
}
},
"node_modules/data-uri-to-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz",
"integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==",
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/date-fns": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
@@ -3063,6 +3321,12 @@
"node": ">=0.10.0"
}
},
"node_modules/decode-formdata": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/decode-formdata/-/decode-formdata-0.8.0.tgz",
"integrity": "sha512-iUzDgnWsw5ToSkFY7VPFA5Gfph6ROoOxOB7Ybna4miUSzLZ4KaSJk6IAB2AdW6+C9vCVWhjjNA4gjT6wF3eZHQ==",
"license": "MIT"
},
"node_modules/dedent": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
@@ -3920,6 +4184,21 @@
}
}
},
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"license": "MIT",
"dependencies": {
"is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -4832,6 +5111,18 @@
"dev": true,
"license": "MIT"
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-core-module": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
@@ -4898,6 +5189,24 @@
"node": ">=8"
}
},
"node_modules/is-generator-function": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
"integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
"get-proto": "^1.0.0",
"has-tostringtag": "^1.0.2",
"safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -5012,6 +5321,21 @@
"node": ">=0.10.0"
}
},
"node_modules/is-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@@ -5856,6 +6180,15 @@
"node": ">=0.10.0"
}
},
"node_modules/mrmime": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
"integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -6607,6 +6940,15 @@
"integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==",
"license": "MIT"
},
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/postgres": {
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.5.tgz",
@@ -6746,6 +7088,29 @@
"node": ">=8"
}
},
"node_modules/react": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
"peerDependencies": {
"react": "^19.1.0"
}
},
"node_modules/read-pkg": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
@@ -7110,6 +7475,23 @@
],
"license": "MIT"
},
"node_modules/safe-regex-test": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"is-regex": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/safe-stable-stringify": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
@@ -7125,6 +7507,13 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/scheduler": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"license": "MIT",
"peer": true
},
"node_modules/secure-json-parse": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz",
@@ -7143,6 +7532,12 @@
"node": ">=10"
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -7364,6 +7759,12 @@
"npm": ">=6"
}
},
"node_modules/stream-slice": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz",
"integrity": "sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==",
"license": "MIT"
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -8157,6 +8558,12 @@
"@esbuild/win32-x64": "0.25.1"
}
},
"node_modules/turbo-stream": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
"integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
"license": "ISC"
},
"node_modules/type-fest": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
@@ -8181,7 +8588,7 @@
"version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"dev": true,
"devOptional": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -8204,6 +8611,15 @@
"node": ">=0.8.0"
}
},
"node_modules/undici": {
"version": "6.21.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.2.tgz",
"integrity": "sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
@@ -8219,6 +8635,28 @@
"node": ">= 10.0.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
"integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"which-typed-array": "^1.1.2"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -8256,6 +8694,27 @@
"defaults": "^1.0.3"
}
},
"node_modules/web-encoding": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz",
"integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==",
"license": "MIT",
"dependencies": {
"util": "^0.12.3"
},
"optionalDependencies": {
"@zxing/text-encoding": "0.9.0"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -8271,6 +8730,27 @@
"node": ">= 8"
}
},
"node_modules/which-typed-array": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
"for-each": "^0.3.5",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",

View File

@@ -22,7 +22,8 @@
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"v1Build": "cd C:\\Users\\matthes01\\Documents\\logisticsSupportTool && npm run oldBuilder",
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"prodBuild": "npm run v1Build && npm run build && npm run zipServer",
"removeOld": "rimraf dist && rimraf frontend/dist",
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
"commit": "cz",
"prodinstall": "npm i --omit=dev && npm run db:migrate",
"checkupdates": "npx npm-check-updates"
@@ -33,7 +34,7 @@
}
},
"admConfig": {
"build": 115,
"build": 125,
"oldBuild": "backend-0.1.3.zip"
},
"devDependencies": {
@@ -57,6 +58,7 @@
"@hono/node-server": "^1.14.0",
"@hono/zod-openapi": "^0.19.2",
"@scalar/hono-api-reference": "^0.7.2",
"@tanstack/react-form": "^1.2.1",
"@types/jsonwebtoken": "^9.0.9",
"@types/nodemailer-express-handlebars": "^4.0.5",
"adm-zip": "^0.5.16",

View File

@@ -85,6 +85,9 @@ $plantFunness = {
$localPath = $location -replace '\$', ':'
$serverFile = "$($localPath)\$buildFile"
$serverPath = "$($localPath)"
$appPath = $extractedFolderPath
$nssmPath = $serverPath + "\nssm.exe"
$npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd
Write-Host "In the plant we go!!!!!"
@@ -92,26 +95,12 @@ $plantFunness = {
######################################################################################
# Removing the fist and frontend folder to make sure we keep them the same and clean.
######################################################################################
try {
# Delete the directories after extraction
Write-Host "Deleting Dist and Frontend..."
$distPath = "$serverPath\dist\"
$frontendPath = "$serverPath\frontend\"
if (Test-Path $distPath) {
Remove-Item -Path $distPath -Recurse -Force
}
if (Test-Path $frontendPath) {
Remove-Item -Path $frontendPath -Recurse -Force
}
} catch {
Write-Host "Error: $_"
exit 1 # Exit with a non-zero code if there's an error
}
# Delete the directories after extraction
Write-Host "Deleting Dist and Frontend..."
Set-Location $serverPath
npm run removeOld # --omit=dev
Write-Host "Unzipping the folder..."
@@ -188,10 +177,6 @@ $plantFunness = {
# Service removoal and making sure we have the new version added
#################################################################
$appPath = $extractedFolderPath
$nssmPath = $serverPath + "\nssm.exe"
$npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd
#################################################################
# Removing all the old services
#################################################################

View File

@@ -0,0 +1,22 @@
# Define the array of folders
$folders = @(
"AlplaBasis",
"AlplaBudget",
"AlplaINVOICE",
"AlplaLabel",
"AlplaOrder",
"AlplaPlanning",
"AlplaPurchase",
"AlplaStock",
"PDF24",
"Module shortcuts"
)
# Set permissions using icacls
$permissions = "Everyone:(OI)(CI)F"
# Loop through each folder and set permissions
foreach ($folder in $folders) {
$folderPath = "C:\Sources\AlplaPROD\$folder"
icacls $folderPath /grant $permissions /t /c /q
}

View File

@@ -5,64 +5,80 @@ import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import type { User } from "../../../../types/users.js";
import { createPassword } from "../../utils/createPassword.js";
import { createLog } from "../../../logger/logger.js";
import { sendEmail } from "../../../notifications/controller/sendMail.js";
export const updateUserADM = async (userData: User) => {
/**
* The user model will need to be passed over so we can update per the request on the user.
* password, username, email.
*/
/**
* The user model will need to be passed over so we can update per the request on the user.
* password, username, email.
*/
createLog(
"info",
"apiAuthedRoute",
"auth",
`${userData.user_id} is being updated.`
);
// get the orignal user info
const { data: user, error: userError } = await tryCatch(
db.select().from(users).where(eq(users.user_id, userData.user_id!))
);
console.log(userData);
createLog(
"info",
"apiAuthedRoute",
"auth",
`${userData.user_id} is being updated.`
);
// get the orignal user info
const { data: user, error: userError } = await tryCatch(
db.select().from(users).where(eq(users.user_id, userData.user_id!))
);
if (userError) {
return {
success: false,
message: "There was an error getting the user",
userError,
if (userError) {
return {
success: false,
message: "There was an error getting the user",
userError,
};
}
if (user?.length === 0) {
return {
success: false,
message:
"The user you are looking for has either been deleted or dose not exist.",
};
}
const upd_user = user as User;
const password: string = userData.password
? await createPassword(userData.password!)
: upd_user.password!;
const data = {
username: userData.username ? userData.username : upd_user?.username,
password: password,
email: userData.email ? userData.email : upd_user.email,
role: userData.role ? userData.role : upd_user.role,
};
}
if (user?.length === 0) {
// term ? ilike(posts.title, term) : undefined
const { data: updData, error: updError } = await tryCatch(
db.update(users).set(data).where(eq(users.user_id, userData.user_id!))
);
if (updError) {
return {
success: false,
message: "There was an error getting the user",
updError,
};
}
if (userData?.password!.length > 0) {
// send this user an email so they have the randomized password.
await sendEmail({
email: user[0]?.email,
subject: "LST - Password reset.",
template: "passwordReset",
context: {
password: userData.password!,
username: user[0].username!,
},
});
}
return {
success: false,
message:
"The user you are looking for has either been deleted or dose not exist.",
success: true,
message: `${userData.username} has been updated.`,
updData,
};
}
const upd_user = user as User;
const password: string = userData.password
? await createPassword(userData.password!)
: upd_user.password!;
const data = {
username: userData.username ? userData.username : upd_user?.username,
password: password,
email: userData.email ? userData.email : upd_user.email,
};
// term ? ilike(posts.title, term) : undefined
const { data: updData, error: updError } = await tryCatch(
db.update(users).set(data).where(eq(users.user_id, userData.user_id!))
);
if (updError) {
return {
success: false,
message: "There was an error getting the user",
updError,
};
}
return {
success: true,
message: `${userData.username} has been updated.`,
updData,
};
};

View File

@@ -10,82 +10,76 @@ import { updateUserADM } from "../../controllers/userAdmin/updateUserAdm.js";
const app = new OpenAPIHono();
const responseSchema = z.object({
success: z.boolean().openapi({ example: true }),
message: z.string().optional().openapi({ example: "user access" }),
data: z.array(z.object({})).optional().openapi({ example: [] }),
success: z.boolean().openapi({ example: true }),
message: z.string().optional().openapi({ example: "user access" }),
data: z.array(z.object({})).optional().openapi({ example: [] }),
});
const UserAccess = z.object({
user_id: z.string().openapi({ example: "users UUID" }),
username: z
.string()
.regex(/^[a-zA-Z0-9_]{3,30}$/)
.optional()
.openapi({ example: "smith034" }),
email: z
.string()
.email()
.optional()
.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",
})
.optional()
.openapi({ example: "Password1!" }),
user_id: z.string().openapi({ example: "users UUID" }),
username: z
.string()
.regex(/^[a-zA-Z0-9_]{3,30}$/)
.optional()
.openapi({ example: "smith034" }),
email: z
.string()
.email()
.optional()
.openapi({ example: "smith@example.com" }),
password: z
.string()
.optional()
.openapi({ example: "Password1!" }),
});
app.openapi(
createRoute({
tags: ["Auth:admin"],
summary: "updates a specific user",
method: "post",
path: "/updateuser",
middleware: [
authMiddleware,
hasCorrectRole(["admin", "systemAdmin"], "admin"),
],
//description: "When logged in you will be able to grant new permissions",
request: {
body: {
content: {
"application/json": { schema: UserAccess },
createRoute({
tags: ["Auth:admin"],
summary: "updates a specific user",
method: "patch",
path: "/updateuser",
middleware: [
authMiddleware,
hasCorrectRole(["admin", "systemAdmin"], "admin"),
],
//description: "When logged in you will be able to grant new permissions",
request: {
body: {
content: {
"application/json": { schema: UserAccess },
},
},
},
},
},
responses: responses(),
}),
async (c) => {
//apiHit(c, { endpoint: "api/auth/setUserRoles" });
const userData = await c.req.json();
try {
const userUPD: any = await updateUserADM(userData);
//return apiReturn(c, true, access?.message, access?.data, 200);
return c.json(
{
success: userUPD.success,
message: userUPD.message,
data: userUPD.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: "Error in setting the user access",
data: error,
},
400
);
responses: responses(),
}),
async (c) => {
//apiHit(c, { endpoint: "api/auth/setUserRoles" });
const userData = await c.req.json();
try {
const userUPD: any = await updateUserADM(userData);
//return apiReturn(c, true, access?.message, access?.data, 200);
return c.json(
{
success: userUPD.success,
message: userUPD.message,
data: userUPD.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: "Error in setting the user access",
data: error,
},
400
);
}
}
}
);
export default app;

View File

@@ -0,0 +1,36 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{{!--<title>Order Summary</title> --}}
{{> styles}}
<style>
pre {
background-color: #f8f9fa;
color: #d63384;
padding: 10px;
border-radius: 5px;
white-space: pre-wrap;
font-family: monospace;
}
</style>
{{!-- <link rel="stylesheet" href="styles/styles.css" /> --}}
</head>
<body>
<p>
Dear {{username}},<br/><br/>
Your password was change. Please find your new temporary password below:<br/><br/>
Temporary Password: <em><b>{{password}}</b></em><br/><br/>
For security reasons, we strongly recommend changing your password as soon as possible.<br/><br/>
You can update it by logging into your account and navigating to the password settings section.<br/><br/>
Best regards,<br/><br/>
LST team<br/>
</p>
</body>
</html>

View File

@@ -52,7 +52,7 @@ export const labelingProcess = async ({
const macId = await getMac(line);
// filter out the lot for the line
filteredLot = lots.data.filter(
(l: any) => l.MachineID === macId[0].HumanReadableId
(l: any) => l.MachineID === macId[0]?.HumanReadableId
);
if (filteredLot.length === 0) {

View File

@@ -36,7 +36,7 @@ export const dycoConnect = async () => {
plcCycle = setInterval(async () => {
if (isReading) {
createLog(
"warn",
"debug",
"dyco",
"ocp",
"Skipping cycle: previous read still in progress."

View File

@@ -7,6 +7,7 @@ import { createLog } from "../../../../../logger/logger.js";
export let strapperActive = true;
export let stapperFaulted = false;
export let strapperFaultCount = 3; // move to db so we can control it outside the app
let alreadyAlerted = false;
export const strapperFaults = async (tagData: any) => {
const { data, error } = await tryCatch(db.select().from(settings));
@@ -15,27 +16,6 @@ export const strapperFaults = async (tagData: any) => {
return { success: false, message: "Failed to get settings." };
}
if (strapperActive) {
// monitor strapper
//console.log(`Strapper fault is ${strapperError.value}`);
if (tagData.value && strapperFaultCount > 0) {
// strapper faulted we want to start the trigger to force the check
if (!stapperFaulted) {
createLog(
"error",
"dyco",
"ocp",
`Strapper errored triggering manual checks will be required for the next ${strapperFaultCount}`
);
}
stapperFaulted = true;
// change move fault count to db....
strapperFaultCount = 3;
}
}
const strapperCheckSetting = data.filter((n) => n.name === "strapperCheck");
if (strapperCheckSetting[0]?.value === "1") {
@@ -46,6 +26,7 @@ export const strapperFaults = async (tagData: any) => {
"ocp",
`There was a strapper error, remaining pallets to check ${strapperFaultCount}.`
);
alreadyAlerted = true;
strapperFaultCount = strapperFaultCount - 1;
return {
success: false,
@@ -69,4 +50,25 @@ export const strapperFaults = async (tagData: any) => {
};
}
}
if (strapperActive) {
// monitor strapper
//console.log(`Strapper fault is ${strapperError.value}`);
if (tagData.value && strapperFaultCount > 0) {
// strapper faulted we want to start the trigger to force the check
if (!stapperFaulted) {
createLog(
"error",
"dyco",
"ocp",
`Strapper errored triggering manual checks will be required for the next ${strapperFaultCount}`
);
}
stapperFaulted = true;
alreadyAlerted = true;
// change move fault count to db....
strapperFaultCount = 3;
}
}
};

View File

@@ -59,7 +59,7 @@ app.openapi(
await readTags(reader);
} else {
createLog(
"info",
"debug",
"rfid",
"rfid",
`A new trigger from ${reader} was to soon`

View File

@@ -1,5 +1,5 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import {areModulesIn} from "./utils/moduleCheck.js";
import { OpenAPIHono } from "@hono/zod-openapi";
import { areModulesIn } from "./utils/moduleCheck.js";
// routes
import getModules from "./route/modules/getModules.js";
@@ -8,16 +8,18 @@ import addModule from "./route/modules/addModule.js";
import addSetting from "./route/settings/addSetting.js";
import getSettings from "./route/settings/getSettings.js";
import updateSetting from "./route/settings/updateSetting.js";
import {areSettingsIn} from "./utils/settingsCheck.js";
import {serversCheckPoint} from "./utils/serverData.js";
import { areSettingsIn } from "./utils/settingsCheck.js";
import { serversCheckPoint } from "./utils/serverData.js";
import getServers from "./route/servers/getServers.js";
import updateServer from "./route/updates/updateServer.js";
import { setPerms } from "./utils/testServerPerms.js";
// making sure all modules are in properly
setTimeout(() => {
areSettingsIn();
areModulesIn();
serversCheckPoint();
setTimeout(async () => {
await areSettingsIn();
await areModulesIn();
await serversCheckPoint();
await setPerms();
}, 5000);
const app = new OpenAPIHono();
@@ -41,6 +43,10 @@ const appRoutes = routes.forEach((route) => {
});
app.all("/server/*", (c) => {
return c.json({success: false, message: "You encountered a route that dose not exist on the server routes"});
return c.json({
success: false,
message:
"You encountered a route that dose not exist on the server routes",
});
});
export default app;

View File

@@ -18,7 +18,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Bethlehem",
@@ -38,7 +38,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Huston",
@@ -53,12 +53,12 @@
"contactPhone": "6366970253",
"customerTiAcc": "ALPL01HOUSINT",
"lstServerPort": "4000",
"active": false,
"active": true,
"serverLoc": "E:\\LST\\lstv2",
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Bowling Green 1",
@@ -78,7 +78,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Iowa ISBM",
@@ -98,7 +98,7 @@
"oldVersion": "E:\\LST\\lst_backend_2",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Kansas City",
@@ -118,7 +118,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Bowling Green 2",
@@ -133,12 +133,12 @@
"contactPhone": "6366970253",
"customerTiAcc": "ALPL01BG2INT",
"lstServerPort": "4000",
"active": false,
"active": true,
"serverLoc": "E:\\LST\\lstv2",
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "MCDonough",
@@ -158,7 +158,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Dayton",
@@ -178,7 +178,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Salt Lake City",
@@ -198,7 +198,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Lima",
@@ -218,7 +218,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Florence",
@@ -238,7 +238,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Iowa EBM",
@@ -258,7 +258,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Jefferson city",
@@ -278,7 +278,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "Sherman",
@@ -298,7 +298,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
},
{
"sName": "West Bend",
@@ -318,7 +318,9 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti", "active": false}]
"otherSettings": [
{ "specialInstructions": "something for ti", "active": false }
]
},
{
"sName": "St Peters",
@@ -338,7 +340,7 @@
"oldVersion": "E:\\LST\\lst_backend",
"shippingHours": "[{\"early\": \"06:30\", \"late\": \"23:00\"}]",
"tiPostTime": "[{\"from\": \"24\", \"to\": \"24\"}]",
"otherSettings": [{"specialInstructions": "something for ti"}]
"otherSettings": [{ "specialInstructions": "something for ti" }]
}
]
}

View File

@@ -0,0 +1,78 @@
import { spawn } from "child_process";
import { createLog } from "../../logger/logger.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { db } from "../../../../database/dbclient.js";
import { settings } from "../../../../database/schema/settings.js";
import { eq } from "drizzle-orm";
export const setPerms = async () => {
const { data, error } = await tryCatch(
db.select().from(settings).where(eq(settings.name, "server"))
);
if (error) {
return createLog(
"error",
"lst",
"serverUpdater",
`Error getting the server settings`
);
}
if (data[0].value != "usmcd1vms036") {
return createLog(
"info",
"lst",
"serverUpdater",
`${data[0].value} will not have its permissions updated as it is not the test server.`
);
}
const scriptPath = `E:\\LST\\lstv2\\server\\scripts\\update.ps1 `;
const args = [
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-File",
scriptPath,
];
const process = spawn("powershell", args);
// Collect stdout data
process.stdout.on("data", (data) => {
const output = data.toString().trim();
createLog("info", "lst", "serverUpdater", `${output}`);
//onData(output);
});
// Collect stderr data
process.stderr.on("data", (data) => {
const output = data.toString().trim();
createLog("info", "lst", "serverUpdater", `${output}`);
//onData(output);
});
// Handle process close
process.on("close", async (code) => {
if (code === 0) {
// if (count >= servers) {
// //onClose(`Server completed with code: ${code}`);
// }
createLog("info", "lst", "serverUpdater", `Finished setting perms`);
//update the last build.
} else {
const errorMessage = `Process exited with code ${code}`;
// if (count >= servers) {
// //onClose(code);
// }
}
});
// Handle errors with the process itself
process.on("error", (error) => {
//onError(err.message);
createLog("error", "lst", "serverUpdater", `${error}`);
});
};