6 Commits

Author SHA1 Message Date
759f96b0b6 chore(release): 0.0.1-alpha.5
Some checks failed
Build and Push LST Docker Image / docker (push) Failing after 1m36s
Release and Build Image / release (push) Failing after 38s
2026-04-23 07:11:50 -05:00
de5df2b00b chore(scripts): added in a helper to remove old stuff
Some checks failed
Build and Push LST Docker Image / docker (push) Has been cancelled
2026-04-23 07:10:53 -05:00
4d53af0338 feat(servers): added marked tree in to the mix 2026-04-23 07:10:27 -05:00
f7276ca2d7 feat(oidc): added in so we could use an oidc to login as well :D 2026-04-23 07:09:49 -05:00
d6328ab764 fix(gp): weird issue with db username and password
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 1m41s
2026-04-22 06:39:22 -05:00
a6d53f0266 refactor(sql): changed sql connection to ip:port
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 1m42s
this change was needed for when we run in docker so we can connect to the servers
2026-04-22 05:40:38 -05:00
14 changed files with 330 additions and 48 deletions

View File

@@ -50,3 +50,11 @@ GP_PASSWORD=
# how often to check for new/updated queries in min # how often to check for new/updated queries in min
QUERY_TIME_TYPE=m #valid options are m, h QUERY_TIME_TYPE=m #valid options are m, h
QUERY_CHECK=1 QUERY_CHECK=1
# Oauth setup
PROVIDER=""
CLIENT_ID=""
CLIENT_SECRET=""
CLIENT_SCOPES="openid profile email groups"
DISCOVERY_URL=""

View File

@@ -1,5 +1,41 @@
# All Changes to LST can be found below. # All Changes to LST can be found below.
## [0.0.1-alpha.5](https://git.tuffraid.net/cowch/lst_v3/compare/v0.0.1-alpha.4...v0.0.1-alpha.5) (2026-04-23)
### 🌟 Enhancements
* **admin:** moved server build/update to full app ([cb00add](https://git.tuffraid.net/cowch/lst_v3/commits/cb00addee96b3ecccf2694f85cb7882cac9c7e3d))
* **lstmobile:** intial scanner setup kinda working ([3734d9d](https://git.tuffraid.net/cowch/lst_v3/commits/3734d9daac143ad8fb4404c59990bc4f546f365b))
* **oidc:** added in so we could use an oidc to login as well :D ([f7276ca](https://git.tuffraid.net/cowch/lst_v3/commits/f7276ca2d722e30da65bbead23dc9bd57df25aa7))
* **servers:** added marked tree in to the mix ([4d53af0](https://git.tuffraid.net/cowch/lst_v3/commits/4d53af033876d81e0d38c148c15cb0af6f3d5bf0))
### 🐛 Bug fixes
* **datamart:** fixes to correct how we handle activations of new features and legacy queries ([b832d7a](https://git.tuffraid.net/cowch/lst_v3/commits/b832d7aa1ecd063be1bbb7e969617fc7a6376ffa))
* **datamart:** if we do not have 2.0 warehousing activate we need to use legacy ([5b1c885](https://git.tuffraid.net/cowch/lst_v3/commits/5b1c88546ff9a42dc572450fe05ad68015edb627))
* **gp:** weird issue with db username and password ([d6328ab](https://git.tuffraid.net/cowch/lst_v3/commits/d6328ab764c3626aef99727b873003384951d299))
* **inventory:** changes to accruatly adjust the query and check the feature set ([32517d0](https://git.tuffraid.net/cowch/lst_v3/commits/32517d0c98c42a0f0f60135b4a9951c4090ccd58))
* **logistics:** historical issue where it was being really weird ([cfbc156](https://git.tuffraid.net/cowch/lst_v3/commits/cfbc1565172f7c2e27f0a1593fe8e99b00d91bb7))
* **logistics:** purchasing monitoring was going off every 5th min instead of every 5 min ([3639c1b](https://git.tuffraid.net/cowch/lst_v3/commits/3639c1b77c597a94816bfedd0892f0c8980c6403))
* **ocp:** fixes to make sure we always hav printer.data as an array or dont do anything ([fb3cd85](https://git.tuffraid.net/cowch/lst_v3/commits/fb3cd85b411315cac0abd22d050ee88929754833))
* **psi:** refactor psi queries ([a1eeade](https://git.tuffraid.net/cowch/lst_v3/commits/a1eeadeec438f7c5c6d31f190fee5c22f83dc6b0))
### 📝 Chore
* **clean:** removed bruno api a proper api doc will be added to lst later ([f716de1](https://git.tuffraid.net/cowch/lst_v3/commits/f716de1a58a4a4c02d9a0a375444ceecea4a018b))
* **scripts:** added in a helper to remove old stuff ([de5df2b](https://git.tuffraid.net/cowch/lst_v3/commits/de5df2b00b1c6fe7c53d6ea075b4cf7e0fb845f9))
### 🛠️ Code Refactor
* **scanner:** more basic work to get the scanner just running ([82f8369](https://git.tuffraid.net/cowch/lst_v3/commits/82f8369640b2b0ff63dd640dc0aa0609a42c7dda))
* **servers:** added mcd and stp1 ([88cef2a](https://git.tuffraid.net/cowch/lst_v3/commits/88cef2a56c390b692866658ce519e59ffeaf4c17))
* **server:** server updates can now only be done from a dev pc ([7962463](https://git.tuffraid.net/cowch/lst_v3/commits/7962463927c4c5d2e12db9a0dd536b0f29fc65b2))
* **sql:** changed sql connection to ip:port ([a6d53f0](https://git.tuffraid.net/cowch/lst_v3/commits/a6d53f0266f1edc3f3946cd1f07d893c8a98d9c7))
## [0.0.1-alpha.4](https://git.tuffraid.net/cowch/lst_v3/compare/v0.0.1-alpha.3...v0.0.1-alpha.4) (2026-04-15) ## [0.0.1-alpha.4](https://git.tuffraid.net/cowch/lst_v3/compare/v0.0.1-alpha.3...v0.0.1-alpha.4) (2026-04-15)

View File

@@ -1,10 +1,16 @@
import type sql from "mssql"; import type sql from "mssql";
// TODO : Remove this later and get it onto the env
const username = "gpviewer"; const username = "gpviewer";
const password = "gp$$ViewOnly!"; const password = "gp$$ViewOnly!";
const port = process.env.SQL_PORT
? Number.parseInt(process.env.SQL_PORT, 10)
: undefined;
export const gpSqlConfig: sql.config = { export const gpSqlConfig: sql.config = {
server: `USMCD1VMS011`, server: `${process.env.GP_SERVER ?? "USMCD1VMS011"}`,
port: port,
database: `ALPLA`, database: `ALPLA`,
user: username, user: username,
password: password, password: password,

View File

@@ -1,7 +1,13 @@
import type sql from "mssql"; import type sql from "mssql";
const port = process.env.SQL_PORT
? Number.parseInt(process.env.SQL_PORT, 10)
: undefined;
export const prodSqlConfig: sql.config = { export const prodSqlConfig: sql.config = {
server: `${process.env.PROD_SERVER}`, server: `${process.env.PROD_SERVER}`,
database: `AlplaPROD_${process.env.PROD_PLANT_TOKEN}_cus`, database: `AlplaPROD_${process.env.PROD_PLANT_TOKEN}_cus`,
port: port,
user: process.env.PROD_USER, user: process.env.PROD_USER,
password: process.env.PROD_PASSWORD, password: process.env.PROD_PASSWORD,
options: { options: {

View File

@@ -53,13 +53,14 @@ export const connectGPSql = async () => {
notify: false, notify: false,
}); });
} catch (error) { } catch (error) {
console.log(error);
reconnectToSql; reconnectToSql;
return returnFunc({ return returnFunc({
success: false, success: false,
level: "error", level: "error",
module: "system", module: "system",
subModule: "db", subModule: "db",
message: "Failed to connect to the prod sql server.", message: "Failed to connect to the gp sql server.",
data: [error], data: [error],
notify: false, notify: false,
}); });

View File

@@ -105,11 +105,11 @@ const servers: NewServerData[] = [
contactEmail: "", contactEmail: "",
contactPhone: "", contactPhone: "",
serverLoc: "D$\\LST_V3", serverLoc: "D$\\LST_V3",
buildNumber: 82, buildNumber: 1,
}, },
{ {
name: "St. Peters", name: "St. Peters",
server: "USTP1VMS006", server: "USSTP1VMS006",
plantToken: "usstp1", plantToken: "usstp1",
idAddress: "10.37.0.26", idAddress: "10.37.0.26",
greatPlainsPlantCode: "45", greatPlainsPlantCode: "45",
@@ -118,8 +118,20 @@ const servers: NewServerData[] = [
serverLoc: "D$\\LST_V3", serverLoc: "D$\\LST_V3",
buildNumber: 1, buildNumber: 1,
}, },
{
name: "Marked Tree",
server: "USMAR1VMS006",
plantToken: "usmar1",
idAddress: "10.206.9.26",
greatPlainsPlantCode: "90",
contactEmail: "",
contactPhone: "",
serverLoc: "D$\\LST_V3",
buildNumber: 1,
},
]; ];
// notes here for when it comes time to pull in all the server address info [test1_AlplaPROD2.0_Read].[masterData].[Plant] has everything from every server :D
export const serversChecks = async () => { export const serversChecks = async () => {
const log = createLogger({ module: "system", subModule: "serverData" }); const log = createLogger({ module: "system", subModule: "serverData" });
const { data, error } = await tryCatch( const { data, error } = await tryCatch(
@@ -152,3 +164,9 @@ export const serversChecks = async () => {
log.info({}, "All Servers were added/updated"); log.info({}, "All Servers were added/updated");
} }
}; };
// Communication from logistic network to logisticsSupportTool (for printers and scanners)
// network justification
// scanners and printers are on dhcp

View File

@@ -2,6 +2,7 @@ import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { import {
admin as adminPlugin, admin as adminPlugin,
genericOAuth,
// apiKey, // apiKey,
// createAuthMiddleware, // createAuthMiddleware,
//customSession, //customSession,
@@ -16,6 +17,46 @@ import { ac, admin, systemAdmin, user } from "./auth.permissions.js";
import { allowedOrigins } from "./cors.utils.js"; import { allowedOrigins } from "./cors.utils.js";
import { sendEmail } from "./sendEmail.utils.js"; import { sendEmail } from "./sendEmail.utils.js";
function decodeJwtPayload<T = Record<string, unknown>>(jwt: string): T {
const parts = jwt.split(".");
if (parts.length < 2) {
throw new Error("Invalid JWT");
}
const payload = parts[1]?.replace(/-/g, "+").replace(/_/g, "/");
const padded = payload?.padEnd(
payload.length + ((4 - (payload.length % 4)) % 4),
"=",
);
const json = Buffer.from(padded ?? "", "base64").toString("utf8");
return JSON.parse(json) as T;
}
function normalizeGroups(groups?: unknown): string[] {
if (!Array.isArray(groups)) return [];
return groups
.filter((g): g is string => typeof g === "string")
.map((g) => g.trim().toLowerCase())
.filter((g) => g.length > 0);
}
type VoidAuthClaims = {
sub: string;
name?: string;
preferred_username?: string;
email?: string;
email_verified?: boolean;
groups?: string[];
picture?: string;
iss?: string;
aud?: string;
exp?: number;
iat?: number;
};
export const schema = { export const schema = {
user: rawSchema.user, user: rawSchema.user,
session: rawSchema.session, session: rawSchema.session,
@@ -25,9 +66,73 @@ export const schema = {
apiKey: rawSchema.apikey, // 🔑 rename to apiKey apiKey: rawSchema.apikey, // 🔑 rename to apiKey
}; };
const hasOAuth =
Boolean(process.env.PROVIDER) &&
Boolean(process.env.CLIENT_ID) &&
Boolean(process.env.CLIENT_SECRET) &&
Boolean(process.env.DISCOVERY_URL);
if (!hasOAuth) {
console.warn("Missing oauth data.");
}
const oauthPlugins = hasOAuth
? [
genericOAuth({
config: [
{
providerId: process.env.PROVIDER!,
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
discoveryUrl: process.env.DISCOVERY_URL!,
scopes: (process.env.CLIENT_SCOPES ?? "")
.split(/[,\s]+/)
.filter(Boolean),
pkce: true,
requireIssuerValidation: true,
redirectURI: `${process.env.URL}/lst/api/auth/oauth2/callback/${process.env.PROVIDER!}`,
getUserInfo: async (tokens) => {
if (!tokens.idToken) {
throw new Error("VoidAuth did not return an idToken");
}
const claims = decodeJwtPayload<VoidAuthClaims>(tokens.idToken);
const groups = normalizeGroups(claims.groups);
return {
id: claims.sub,
email: claims.email ?? "",
name:
claims.name ??
claims.preferred_username ??
claims.email ??
"Unknown User",
image: claims.picture ?? null,
emailVerified: Boolean(claims.email_verified),
groups,
username: claims.preferred_username ?? null,
} as any;
},
mapProfileToUser: async (profile) => {
return {
name: profile.name,
role: profile.groups?.includes("lst_admins")
? "systemAdmin"
: profile.groups?.includes("admins")
? "admin"
: "user",
};
},
},
],
}),
]
: [];
export const auth = betterAuth({ export const auth = betterAuth({
appName: "lst", appName: "lst",
baseURL: process.env.URL, baseURL: `${process.env.URL}/lst/api/auth`,
database: drizzleAdapter(db, { database: drizzleAdapter(db, {
provider: "pg", provider: "pg",
schema, schema,
@@ -42,6 +147,14 @@ export const auth = betterAuth({
}, },
}, },
}, },
account: {
encryptOAuthTokens: true,
updateAccountOnSignIn: true,
accountLinking: {
enabled: true,
trustedProviders: ["voidauth"],
},
},
plugins: [ plugins: [
jwt({ jwt: { expirationTime: "1h" } }), jwt({ jwt: { expirationTime: "1h" } }),
//apiKey(), //apiKey(),
@@ -63,6 +176,7 @@ export const auth = betterAuth({
return true; return true;
}, },
}), }),
...oauthPlugins,
// customSession(async ({ user, session }) => { // customSession(async ({ user, session }) => {
// const roles = await db // const roles = await db
@@ -121,7 +235,7 @@ export const auth = betterAuth({
}, },
}, },
cookie: { cookie: {
path: "/lst/app", path: "/lst",
sameSite: "lax", sameSite: "lax",
secure: false, secure: false,
httpOnly: true, httpOnly: true,

View File

@@ -12,48 +12,36 @@ services:
#- "${VITE_PORT:-4200}:4200" #- "${VITE_PORT:-4200}:4200"
- "3600:3000" - "3600:3000"
dns: dns:
- 10.193.9.250 - 10.44.9.250
- 10.193.9.251 # your internal DNS server - 10.44.9.251 # your internal DNS server
dns_search: - 1.1.1.1
- alpla.net # or your internal search suffix
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- LOG_LEVEL=info - LOG_LEVEL=info
- EXTERNAL_URL=http://192.168.8.222:3600 - EXTERNAL_URL=http://192.168.8.222:3600
- DATABASE_HOST=host.docker.internal # if running on the same docker then do this - DATABASE_HOST=postgres # if running on the same docker then do this
- DATABASE_PORT=5433 - DATABASE_PORT=5432
- DATABASE_USER=${DATABASE_USER} - DATABASE_USER=${DATABASE_USER}
- DATABASE_PASSWORD=${DATABASE_PASSWORD} - DATABASE_PASSWORD=${DATABASE_PASSWORD}
- DATABASE_DB=${DATABASE_DB} - DATABASE_DB=${DATABASE_DB}
- PROD_SERVER=${PROD_SERVER} - PROD_SERVER=10.75.9.56 #${PROD_SERVER}
- PROD_PLANT_TOKEN=${PROD_PLANT_TOKEN} - PROD_PLANT_TOKEN=${PROD_PLANT_TOKEN}
- PROD_USER=${PROD_USER} - PROD_USER=${PROD_USER}
- PROD_PASSWORD=${PROD_PASSWORD} - PROD_PASSWORD=${PROD_PASSWORD}
- GP_SERVER=10.193.9.31
- SQL_PORT=1433
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- BETTER_AUTH_URL=${URL} - BETTER_AUTH_URL=${URL}
# for all host including prod servers, plc's, printers, or other de - OPENDOCK_URL=${OPENDOCK_URL}
# extra_hosts: - OPENDOCK_PASSWORD=${OPENDOCK_PASSWORD}
# - "${PROD_SERVER}:${PROD_IP}" - DEFAULT_DOCK=${DEFAULT_DOCK}
- DEFAULT_LOAD_TYPE=${DEFAULT_LOAD_TYPE}
- DEFAULT_CARRIER=${DEFAULT_CARRIER}
# networks: #for all host including prod servers, plc's, printers, or other de
# - default networks:
# - logisticsNetwork - docker-network
# #- mlan1
# networks:
# logisticsNetwork:
# driver: macvlan
# driver_opts:
# parent: eth0
# ipam:
# config:
# - subnet: ${LOGISTICS_NETWORK}
# gateway: ${LOGISTICS_GATEWAY}
# mlan1: networks:
# driver: macvlan docker-network:
# driver_opts: external: true
# parent: eth0
# ipam:
# config:
# - subnet: ${MLAN1_NETWORK}
# gateway: ${MLAN1_GATEWAY}

View File

@@ -1,4 +1,4 @@
import { adminClient } from "better-auth/client/plugins"; import { adminClient, genericOAuthClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react"; import { createAuthClient } from "better-auth/react";
import { ac, admin, systemAdmin, user } from "./auth-permissions"; import { ac, admin, systemAdmin, user } from "./auth-permissions";
@@ -13,6 +13,7 @@ export const authClient = createAuthClient({
systemAdmin, systemAdmin,
}, },
}), }),
genericOAuthClient(),
], ],
}); });

View File

@@ -1,4 +1,5 @@
import { Link, useNavigate } from "@tanstack/react-router"; import { Link, useNavigate } from "@tanstack/react-router";
import { Cat, LogIn } from "lucide-react";
import { toast } from "sonner"; import { toast } from "sonner";
import { import {
Card, Card,
@@ -9,13 +10,23 @@ import {
} from "@/components/ui/card"; } from "@/components/ui/card";
import { authClient } from "@/lib/auth-client"; import { authClient } from "@/lib/auth-client";
import { useAppForm } from "@/lib/formSutff"; import { useAppForm } from "@/lib/formSutff";
import { Button } from "../../../components/ui/button";
import socket from "../../../lib/socket.io"; import socket from "../../../lib/socket.io";
export default function LoginForm({ redirectPath }: { redirectPath: string }) { export default function LoginForm({ redirectPath }: { redirectPath: string }) {
const loginEmail = localStorage.getItem("loginEmail") || ""; const loginEmail = localStorage.getItem("loginEmail") || "";
const rememberMe = localStorage.getItem("rememberMe") === "true"; const rememberMe = localStorage.getItem("rememberMe") === "true";
const navigate = useNavigate(); const navigate = useNavigate();
const oauthLogin = async () => {
await authClient.signIn.oauth2({
providerId: "voidauth",
callbackURL: "/lst/app",
errorCallbackURL: "/lst/app/login",
});
};
const form = useAppForm({ const form = useAppForm({
defaultValues: { defaultValues: {
email: loginEmail, email: loginEmail,
@@ -26,7 +37,7 @@ export default function LoginForm({ redirectPath }: { redirectPath: string }) {
// set remember me incase we want it later // set remember me incase we want it later
if (value.rememberMe) { if (value.rememberMe) {
localStorage.setItem("rememberMe", value.rememberMe.toString()); localStorage.setItem("rememberMe", value.rememberMe.toString());
localStorage.setItem("loginEmail", value.email); localStorage.setItem("loginEmail", value.email.toLocaleLowerCase());
} else { } else {
localStorage.removeItem("rememberMe"); localStorage.removeItem("rememberMe");
localStorage.removeItem("loginEmail"); localStorage.removeItem("loginEmail");
@@ -62,7 +73,17 @@ export default function LoginForm({ redirectPath }: { redirectPath: string }) {
<div> <div>
<Card className="p-3 w-96"> <Card className="p-3 w-96">
<CardHeader> <CardHeader>
<CardTitle>Login to your account</CardTitle> <CardTitle>
<div className="flex flex-row justify-center">
<Button onClick={oauthLogin} size="lg" variant="ghost">
<Cat />
</Button>
<span className="mt-2">Login to your account</span>{" "}
<Button size="lg" variant="ghost">
<Cat />
</Button>
</div>
</CardTitle>
<CardDescription> <CardDescription>
Enter your username and password below Enter your username and password below
</CardDescription> </CardDescription>
@@ -76,12 +97,19 @@ export default function LoginForm({ redirectPath }: { redirectPath: string }) {
> >
<form.AppField name="email"> <form.AppField name="email">
{(field) => ( {(field) => (
<field.InputField label="Email" inputType="email" required /> <field.InputField
label="Email"
inputType="email"
required={rememberMe}
/>
)} )}
</form.AppField> </form.AppField>
<form.AppField name="password"> <form.AppField name="password">
{(field) => ( {(field) => (
<field.InputPasswordField label="Password" required={true} /> <field.InputPasswordField
label="Password"
required={rememberMe}
/>
)} )}
</form.AppField> </form.AppField>
@@ -98,7 +126,7 @@ export default function LoginForm({ redirectPath }: { redirectPath: string }) {
</Link> </Link>
</div> </div>
<div className="flex justify-end mt-2"> <div className="flex justify-between mt-2 ">
<form.AppForm> <form.AppForm>
<form.SubmitButton>Login</form.SubmitButton> <form.SubmitButton>Login</form.SubmitButton>
</form.AppForm> </form.AppForm>

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "lst_v3", "name": "lst_v3",
"version": "0.0.1-alpha.4", "version": "0.0.1-alpha.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "lst_v3", "name": "lst_v3",
"version": "0.0.1-alpha.4", "version": "0.0.1-alpha.5",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@dotenvx/dotenvx": "^1.57.0", "@dotenvx/dotenvx": "^1.57.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "lst_v3", "name": "lst_v3",
"version": "0.0.1-alpha.4", "version": "0.0.1-alpha.5",
"description": "The tool that supports us in our everyday alplaprod", "description": "The tool that supports us in our everyday alplaprod",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -16,6 +16,7 @@ param (
# server migrations get - reminder to add to old version in pkg "start:lst": "cd lstV2 && npm start", # server migrations get - reminder to add to old version in pkg "start:lst": "cd lstV2 && npm start",
# powershell.exe -ExecutionPolicy Bypass -File .\scripts\services.ps1 -serviceName "LST_app" -option "install" -appPath "D:\LST" -description "Logistics Support Tool" -command "run start" # powershell.exe -ExecutionPolicy Bypass -File .\scripts\services.ps1 -serviceName "LST_app" -option "install" -appPath "D:\LST" -description "Logistics Support Tool" -command "run start"
# powershell.exe -ExecutionPolicy Bypass -File .\scripts\services.ps1 -serviceName "LSTV2" -option "install" -appPath "D:\LST" -description "Logistics Support Tool" -command "run start:lst" # powershell.exe -ExecutionPolicy Bypass -File .\scripts\services.ps1 -serviceName "LSTV2" -option "install" -appPath "D:\LST" -description "Logistics Support Tool" -command "run start:lst"
# powershell.exe -ExecutionPolicy Bypass -File .\scripts\services.ps1 -serviceName "LST_ctl" -option "delete" -appPath "D:\LST" -description "Logistics Support Tool" -command "run start:lst"
$nssmPath = $AppPath + "\nssm.exe" $nssmPath = $AppPath + "\nssm.exe"
$npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd $npmPath = "C:\Program Files\nodejs\npm.cmd" # Path to npm.cmd

View File

@@ -23,6 +23,8 @@ $password = $ADM_PASSWORD
$securePass = ConvertTo-SecureString $password -AsPlainText -Force $securePass = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($username, $securePass) $credentials = New-Object System.Management.Automation.PSCredential($username, $securePass)
function Update-Server { function Update-Server {
param ( param (
[string]$Destination, [string]$Destination,
@@ -84,6 +86,75 @@ function Update-Server {
$AppUpdate = { $AppUpdate = {
param ($Server, $Token, $Destination, $BuildFile) param ($Server, $Token, $Destination, $BuildFile)
function Fix-Env {
$envFile = ".env"
if (-not (Test-Path $envFile)) {
Write-Host ".env not found, creating..."
New-Item -ItemType File -Path $envFile | Out-Null
}
$envContent = Get-Content $envFile -Raw
if ([string]::IsNullOrWhiteSpace($envContent)) {
$envContent = ""
}
$envVarsToAdd = @{
"PROVIDER" = "voidauth"
"CLIENT_ID" = "crIVcUilFWIS6ME3"
"CLIENT_SECRET" = "zsJeyjMN2yDDqfyzSsh96OtlA2714F5d"
"CLIENT_SCOPES" = "openid profile email groups"
"DISCOVERY_URL" = "https://auth.tuffraid.net/oidc/.well-known/openid-configuration"
}
$linesToAppend = @()
foreach ($key in $envVarsToAdd.Keys) {
$escapedKey = [regex]::Escape($key)
if ($envContent -notmatch "(?m)^$escapedKey=") {
$linesToAppend += "$key=$($envVarsToAdd[$key])"
Write-Host "Adding missing env: $key"
}
else {
Write-Host "Env exists, skipping add: $key"
}
}
###### to replace the values of mistakens or something fun where we need to fix across all 17 servers put it here.
$envVarsToReplace = @{
# "PORT" = "3000"
#"URL" = "https://$($Token)prod.alpla.net/lst"
}
foreach ($key in $envVarsToReplace.Keys) {
$value = $envVarsToReplace[$key]
$escapedKey = [regex]::Escape($key)
if ($envContent -match "(?m)^$escapedKey=") {
Write-Host "Replacing env: $key -> $value"
$envContent = $envContent -replace "(?m)^$escapedKey=.*", "$key=$value"
}
else {
Write-Host "Env not found for replace, skipping: $key"
}
}
if ($linesToAppend.Count -gt 0) {
if ($envContent.Length -gt 0 -and -not $envContent.EndsWith("`n")) {
$envContent += "`r`n"
}
$envContent += "`r`n# ---- VoidAuth Config ----`r`n"
$envContent += ($linesToAppend -join "`r`n")
Write-Host "Appending new env vars."
}
Set-Content -Path $envFile -Value $envContent
Write-Host "Env update completed."
}
#convert everything to the server fun #convert everything to the server fun
$LocalPath = $Destination -replace '\$', ':' $LocalPath = $Destination -replace '\$', ':'
$BuildFileLoc = "$LocalPath\$BuildFile" $BuildFileLoc = "$LocalPath\$BuildFile"
@@ -122,7 +193,11 @@ function Update-Server {
npm install --omit=dev npm install --omit=dev
Start-Sleep -Seconds 3 Start-Sleep -Seconds 3
Write-Host "Install/update completed." Write-Host "Install/update completed."
# do the migrations
# update the env to include the new and missing things silly people and wanting things fixed :(
Fix-Env #-Path $LocalPath
# do the migrations
# Push-Location $LocalPath # Push-Location $LocalPath
Write-Host "Running migrations" Write-Host "Running migrations"
npm run dev:db:migrate npm run dev:db:migrate