diff --git a/LogisticsSupportTool_API_DOCS/app/auth/Request Resetpassword.bru b/LogisticsSupportTool_API_DOCS/app/auth/Request Resetpassword.bru index 8c5f699..07c30ed 100644 --- a/LogisticsSupportTool_API_DOCS/app/auth/Request Resetpassword.bru +++ b/LogisticsSupportTool_API_DOCS/app/auth/Request Resetpassword.bru @@ -5,14 +5,14 @@ meta { } post { - url: {{url}}/lst/api/user/resetPassword + url: {{url}}/lst/api/user/resetpassword body: json auth: inherit } body:json { { - "email": "blake.matthes@alpla.com", + "email": "blake.matthes@alpla.com" } } diff --git a/LogisticsSupportTool_API_DOCS/app/auth/Resetpassword.bru b/LogisticsSupportTool_API_DOCS/app/auth/Resetpassword.bru index 2ae8776..50dc00d 100644 --- a/LogisticsSupportTool_API_DOCS/app/auth/Resetpassword.bru +++ b/LogisticsSupportTool_API_DOCS/app/auth/Resetpassword.bru @@ -5,18 +5,15 @@ meta { } post { - url: http://localhost:4200/api/auth/reset-password/gCo7OUP6CH2Qu7obhvOrhuo9?callbackURL + url: http://localhost:4200/lst/api/auth/reset-password body: json auth: inherit } -params:query { - callbackURL: -} - body:json { { - "newPassword": "nova0511" + "newPassword": "nova0511", + "token": "8ZtCt8c5BRwtcqD9k5RceLhx" } } diff --git a/LogisticsSupportTool_API_DOCS/app/system/Health.bru b/LogisticsSupportTool_API_DOCS/app/system/Stats.bru similarity index 66% rename from LogisticsSupportTool_API_DOCS/app/system/Health.bru rename to LogisticsSupportTool_API_DOCS/app/system/Stats.bru index 5bdc0b5..e3724e2 100644 --- a/LogisticsSupportTool_API_DOCS/app/system/Health.bru +++ b/LogisticsSupportTool_API_DOCS/app/system/Stats.bru @@ -1,11 +1,11 @@ meta { - name: Health + name: Stats type: http seq: 1 } get { - url: {{url}}/lst/api/system/health + url: {{url}}/lst/api/system/stats body: none auth: inherit } diff --git a/LogisticsSupportTool_API_DOCS/environments/lst.bru b/LogisticsSupportTool_API_DOCS/environments/lst.bru index ce2bdba..3a7faa8 100644 --- a/LogisticsSupportTool_API_DOCS/environments/lst.bru +++ b/LogisticsSupportTool_API_DOCS/environments/lst.bru @@ -1,4 +1,4 @@ vars { - url: http://localhost:4200 + url: https://usmcd1vms036.alpla.net session_cookie: } diff --git a/app/src/internal/routerHandler/routeHandler.ts b/app/src/internal/routerHandler/routeHandler.ts index 3f4440d..2da3a3c 100644 --- a/app/src/internal/routerHandler/routeHandler.ts +++ b/app/src/internal/routerHandler/routeHandler.ts @@ -1,16 +1,13 @@ import type { Express, Request, Response } from "express"; - -import healthRoutes from "./routes/healthRoutes.js"; import { setupAuthRoutes } from "../auth/routes/routes.js"; import { setupAdminRoutes } from "../admin/routes.js"; +import { setupSystemRoutes } from "../system/routes.js"; export const setupRoutes = (app: Express, basePath: string) => { - // Root / health check - app.use(basePath + "/api/system/health", healthRoutes); - // all routes setupAuthRoutes(app, basePath); setupAdminRoutes(app, basePath); + setupSystemRoutes(app, basePath); // always try to go to the app weather we are in dev or in production. app.get(basePath + "/", (req: Request, res: Response) => { diff --git a/app/src/internal/routerHandler/routes/healthRoutes.ts b/app/src/internal/routerHandler/routes/healthRoutes.ts deleted file mode 100644 index 7e6c988..0000000 --- a/app/src/internal/routerHandler/routes/healthRoutes.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Router } from "express"; - -const router = Router(); - -// GET /health -router.get("/", (req, res) => { - res.json({ status: "ok", uptime: process.uptime() }); -}); - -export default router; \ No newline at end of file diff --git a/app/src/internal/system/routes.ts b/app/src/internal/system/routes.ts new file mode 100644 index 0000000..0bbd8fa --- /dev/null +++ b/app/src/internal/system/routes.ts @@ -0,0 +1,6 @@ +import type { Express, Request, Response } from "express"; +import stats from "./routes/stats.js"; + +export const setupSystemRoutes = (app: Express, basePath: string) => { + app.use(basePath + "/api/system/stats", stats); +}; diff --git a/app/src/internal/system/routes/stats.ts b/app/src/internal/system/routes/stats.ts new file mode 100644 index 0000000..982ce6d --- /dev/null +++ b/app/src/internal/system/routes/stats.ts @@ -0,0 +1,34 @@ +import { Router } from "express"; +import { tryCatch } from "../../../pkg/utils/tryCatch.js"; +import { db } from "../../../pkg/db/db.js"; +import { + serverStats, + type ServerStats, +} from "../../../pkg/db/schema/serverstats.js"; +import { eq } from "drizzle-orm"; +import { format } from "date-fns-tz"; +import { checkBuildUpdate } from "../utlis/checkForBuild.js"; + +const router = Router(); + +// GET /health +router.get("/", async (req, res) => { + const { data, error } = await tryCatch( + db.select().from(serverStats).where(eq(serverStats.id, "serverStats")) + ); + + if (error || !data) { + res.status(400).json({ error: error }); + } + + const statData = data as ServerStats[]; + res.json({ + status: "ok", + uptime: process.uptime(), + build: statData[0]?.build, + pendingUpdateFile: await checkBuildUpdate(["."]), + lastUpdate: format(statData[0].lastUpdate!, "MM/dd/yyyy HH:mm"), + }); +}); + +export default router; diff --git a/app/src/internal/system/utlis/checkForBuild.ts b/app/src/internal/system/utlis/checkForBuild.ts new file mode 100644 index 0000000..4f04ea5 --- /dev/null +++ b/app/src/internal/system/utlis/checkForBuild.ts @@ -0,0 +1,28 @@ +import { readdir } from "fs/promises"; +import { resolve, join } from "path"; + +/** + * Looks in one or more relative/absolute directories for a .zip file. + * Returns the **full path** to the first .zip file found, or null if none. + */ +export async function checkBuildUpdate(dirs: string[]): Promise { + for (const inputDir of dirs) { + const dir = resolve(inputDir); // resolves "../../" relative to cwd + try { + const files = await readdir(dir); + const zipFile = files.find((file) => + file.toLowerCase().endsWith(".zip") + ); + if (zipFile) { + //return join(dir, zipFile); + return zipFile; + } + } catch (err) { + // Ignore if directory doesn't exist, allow search to continue + if ((err as NodeJS.ErrnoException).code !== "ENOENT") { + throw err; + } + } + } + return null; +} diff --git a/app/src/pkg/db/schema/serverstats.ts b/app/src/pkg/db/schema/serverstats.ts new file mode 100644 index 0000000..a53d29f --- /dev/null +++ b/app/src/pkg/db/schema/serverstats.ts @@ -0,0 +1,12 @@ +import type { InferInsertModel, InferSelectModel } from "drizzle-orm"; +import { integer, pgTable, text, timestamp } from "drizzle-orm/pg-core"; +import type z from "zod"; + +export const serverStats = pgTable("serverStats", { + id: text("id").primaryKey().default("serverStats"), + build: integer("build").notNull().default(1), + lastUpdate: timestamp("lastUpdate").defaultNow(), +}); + +export type ServerStats = InferSelectModel; // SELECT type +//export type NewServerStats = InferInsertModel; // INSERT type diff --git a/controller/.env-example b/controller/.env-example index 6675001..29fda77 100644 --- a/controller/.env-example +++ b/controller/.env-example @@ -3,3 +3,10 @@ APP_MODE=dev # The port is only needed if you plan to use a different port but you will need to change it in the wrapper too PORT=8080 + +# postgres connection +DATABASE_HOST=localhost +DATABASE_PORT=5432 +DATABASE_USER=postgres +DATABASE_PASSWORD=password +DATABASE_DB=lst diff --git a/controller/bump_build.go b/controller/bump_build.go index 16d1a11..98aa360 100644 --- a/controller/bump_build.go +++ b/controller/bump_build.go @@ -5,22 +5,29 @@ import ( "os" "strconv" "strings" + + "lst.net/pkg" ) // ---- Handle Build Counter ---- func bumpBuild() (int, error) { - data, err := os.ReadFile("../.build") - buildNum := 0 - if err == nil { // if file exists, parse current number - num, err := strconv.Atoi(strings.TrimSpace(string(data))) - if err == nil { - buildNum = num - } - } - buildNum++ - err = os.WriteFile("../.build", []byte(fmt.Sprintf("%d", buildNum)), 0644) - if err != nil { - return 0, err - } - return buildNum, nil -} \ No newline at end of file + data, err := os.ReadFile("../.build") + buildNum := 0 + if err == nil { // if file exists, parse current number + num, err := strconv.Atoi(strings.TrimSpace(string(data))) + if err == nil { + buildNum = num + } + } + buildNum++ + err = os.WriteFile("../.build", []byte(fmt.Sprintf("%d", buildNum)), 0644) + if err != nil { + return 0, err + } + + // update the db so we have the build number in here going forward. + + pkg.UpdateServerStats(int64(buildNum)) + + return buildNum, nil +} diff --git a/controller/go.mod b/controller/go.mod index cf47b30..ddc1850 100644 --- a/controller/go.mod +++ b/controller/go.mod @@ -27,6 +27,9 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/hirochachacha/go-smb2 v1.1.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.7.6 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect diff --git a/controller/go.sum b/controller/go.sum index b16370d..b479bba 100644 --- a/controller/go.sum +++ b/controller/go.sum @@ -43,6 +43,12 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI= github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= +github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= diff --git a/controller/pkg/update_server_stats.go b/controller/pkg/update_server_stats.go new file mode 100644 index 0000000..6815be1 --- /dev/null +++ b/controller/pkg/update_server_stats.go @@ -0,0 +1,48 @@ +package pkg + +import ( + "context" + "fmt" + "os" + + "github.com/jackc/pgx/v5" +) + +func UpdateServerStats(buildNumber int64) { + + //url := "postgres://username:password@localhost:5432/database_name" + + url := fmt.Sprintf( + "postgres://%v:%v@%v:%v/%v", + os.Getenv("DATABASE_USER"), + os.Getenv("DATABASE_PASSWORD"), + os.Getenv("DATABASE_HOST"), + os.Getenv("DATABASE_PORT"), + os.Getenv("DATABASE_DB"), + ) + + ctx := context.Background() + conn, err := pgx.Connect(ctx, url) + + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err) + //os.Exit(1) + } + defer conn.Close(ctx) + + sql := ` + INSERT INTO public."serverStats" (id, build, "lastUpdate") + VALUES ($1, $2, NOW()) + ON CONFLICT (id) DO UPDATE + SET build = EXCLUDED.build, + "lastUpdate" = NOW(); + ` + + _, err = conn.Exec(ctx, sql, "serverStats", buildNumber) + + if err != nil { + fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) + //os.Exit(1) + } + +} diff --git a/controller/update.go b/controller/update.go index 51f1f36..0968c10 100644 --- a/controller/update.go +++ b/controller/update.go @@ -15,6 +15,7 @@ import ( "time" socketio "github.com/googollee/go-socket.io" + "lst.net/pkg" ) func UpdateApp(server *socketio.Server) <-chan string { @@ -54,6 +55,7 @@ func UpdateApp(server *socketio.Server) <-chan string { updates <- msg server.BroadcastToRoom("/", "update", "updateLogs", msg) } + msg := "Stopping the services" updates <- msg server.BroadcastToRoom("/", "update", "updateLogs", msg) @@ -127,6 +129,16 @@ func UpdateApp(server *socketio.Server) <-chan string { msg = "Deployment finished successfully" updates <- msg + // remove the prefix + cleaned := strings.Replace(strconv.Itoa(version), "release-", "", 1) + + num, err := strconv.Atoi(cleaned) + + if err != nil { + fmt.Println("Error parsing number:", err) + } + pkg.UpdateServerStats(int64(num)) + server.BroadcastToRoom("/", "update", "updateLogs", msg) default: msg := fmt.Sprintf("Error: too many zip files in root: %v\n", zips) @@ -194,6 +206,7 @@ func Unzip(srcZip, destDir string) error { if err != nil { return err } + } return nil diff --git a/migrations/0008_exotic_scrambler.sql b/migrations/0008_exotic_scrambler.sql new file mode 100644 index 0000000..f937600 --- /dev/null +++ b/migrations/0008_exotic_scrambler.sql @@ -0,0 +1,5 @@ +CREATE TABLE "serverStats" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, + "build" integer DEFAULT 1 NOT NULL, + "lastUpdate" timestamp DEFAULT now() +); diff --git a/migrations/0009_cultured_slayback.sql b/migrations/0009_cultured_slayback.sql new file mode 100644 index 0000000..f6f5410 --- /dev/null +++ b/migrations/0009_cultured_slayback.sql @@ -0,0 +1,2 @@ +ALTER TABLE "serverStats" ALTER COLUMN "id" SET DATA TYPE text;--> statement-breakpoint +ALTER TABLE "serverStats" ALTER COLUMN "id" SET DEFAULT 'serverStats'; \ No newline at end of file diff --git a/migrations/meta/0008_snapshot.json b/migrations/meta/0008_snapshot.json new file mode 100644 index 0000000..bbfbd12 --- /dev/null +++ b/migrations/meta/0008_snapshot.json @@ -0,0 +1,921 @@ +{ + "id": "164ae2f1-91c6-4c31-87eb-2f9c5a1fcf86", + "prevId": "33b56ace-aa18-498f-922f-513e13ccc6ef", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.apiHits": { + "name": "apiHits", + "schema": "", + "columns": { + "apiHit_id": { + "name": "apiHit_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "body": { + "name": "body", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.apikey": { + "name": "apikey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 86400000 + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 10 + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "apikey_user_id_user_id_fk": { + "name": "apikey_user_id_user_id_fk", + "tableFrom": "apikey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_username": { + "name": "display_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_login": { + "name": "last_login", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_username_unique": { + "name": "user_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.logs": { + "name": "logs", + "schema": "", + "columns": { + "log_id": { + "name": "log_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subModule": { + "name": "subModule", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stack": { + "name": "stack", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "checked": { + "name": "checked", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.serverStats": { + "name": "serverStats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "build": { + "name": "build", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "lastUpdate": { + "name": "lastUpdate", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "settings_id": { + "name": "settings_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "moduleName": { + "name": "moduleName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "roles": { + "name": "roles", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[\"systemAdmin\"]'::jsonb" + }, + "add_User": { + "name": "add_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "add_Date": { + "name": "add_Date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_User": { + "name": "upd_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "name": { + "name": "name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_roles": { + "name": "user_roles", + "schema": "", + "columns": { + "user_role_id": { + "name": "user_role_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "unique_user_module": { + "name": "unique_user_module", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "module", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_roles_user_id_user_id_fk": { + "name": "user_roles_user_id_user_id_fk", + "tableFrom": "user_roles", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/0009_snapshot.json b/migrations/meta/0009_snapshot.json new file mode 100644 index 0000000..13efcb6 --- /dev/null +++ b/migrations/meta/0009_snapshot.json @@ -0,0 +1,921 @@ +{ + "id": "7f5da907-4bed-4584-b32b-1f7f2ce17455", + "prevId": "164ae2f1-91c6-4c31-87eb-2f9c5a1fcf86", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.apiHits": { + "name": "apiHits", + "schema": "", + "columns": { + "apiHit_id": { + "name": "apiHit_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "path": { + "name": "path", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "body": { + "name": "body", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.apikey": { + "name": "apikey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 86400000 + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 10 + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "apikey_user_id_user_id_fk": { + "name": "apikey_user_id_user_id_fk", + "tableFrom": "apikey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_username": { + "name": "display_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_login": { + "name": "last_login", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_username_unique": { + "name": "user_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.logs": { + "name": "logs", + "schema": "", + "columns": { + "log_id": { + "name": "log_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subModule": { + "name": "subModule", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stack": { + "name": "stack", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "checked": { + "name": "checked", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.serverStats": { + "name": "serverStats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'serverStats'" + }, + "build": { + "name": "build", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "lastUpdate": { + "name": "lastUpdate", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "settings_id": { + "name": "settings_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "moduleName": { + "name": "moduleName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "roles": { + "name": "roles", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[\"systemAdmin\"]'::jsonb" + }, + "add_User": { + "name": "add_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "add_Date": { + "name": "add_Date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_User": { + "name": "upd_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "name": { + "name": "name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_roles": { + "name": "user_roles", + "schema": "", + "columns": { + "user_role_id": { + "name": "user_role_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "unique_user_module": { + "name": "unique_user_module", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "module", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_roles_user_id_user_id_fk": { + "name": "user_roles_user_id_user_id_fk", + "tableFrom": "user_roles", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json index 18956a2..d5e5648 100644 --- a/migrations/meta/_journal.json +++ b/migrations/meta/_journal.json @@ -57,6 +57,20 @@ "when": 1758755206107, "tag": "0007_common_kronos", "breakpoints": true + }, + { + "idx": 8, + "version": "7", + "when": 1758890062084, + "tag": "0008_exotic_scrambler", + "breakpoints": true + }, + { + "idx": 9, + "version": "7", + "when": 1758891252758, + "tag": "0009_cultured_slayback", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e441a27..c8e8391 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,8 @@ "@types/cors": "^2.8.19", "better-auth": "^1.3.9", "cors": "^2.8.5", + "date-fns": "^4.1.0", + "date-fns-tz": "^3.2.0", "drizzle-kit": "^0.31.4", "drizzle-orm": "^0.44.5", "drizzle-zod": "^0.8.3", @@ -4611,6 +4613,25 @@ "node": ">=8" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-tz": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz", + "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==", + "license": "MIT", + "peerDependencies": { + "date-fns": "^3.0.0 || ^4.0.0" + } + }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", diff --git a/package.json b/package.json index 3ab3a23..f1e2d2d 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,8 @@ "@types/cors": "^2.8.19", "better-auth": "^1.3.9", "cors": "^2.8.5", + "date-fns": "^4.1.0", + "date-fns-tz": "^3.2.0", "drizzle-kit": "^0.31.4", "drizzle-orm": "^0.44.5", "drizzle-zod": "^0.8.3", diff --git a/scripts/update-controller-server.ps1 b/scripts/update-controller-server.ps1 index bfb1216..01a7102 100644 --- a/scripts/update-controller-server.ps1 +++ b/scripts/update-controller-server.ps1 @@ -186,6 +186,43 @@ function Update-Server { Write-Output "[$key] already exists -> skipping" } } + + + # update the controller .env as well to make sure we have anything enw in here. + $requiredController = @( + @{ Key = "DATABASE_HOST"; Value = "localhost"; Comment = "used for better auth secrets" }, + @{ Key = "DATABASE_PORT"; Value = 5432; Comment = "The better auth url" } + @{ Key = "DATABASE_USER"; Value = "postgres"; Comment = "" } + @{ Key = "DATABASE_PASSWORD"; Value = "obelix"; Comment = "" } + @{ Key = "DATABASE_DB"; Value = "lst$(if ($token -eq "usiow2") { "_2" })"; Comment = "" } + ) + + $envFileController = "$LocalPath\controller\.env" + Write-Host $envFileController + + if (-not (Test-Path $envFileController)) { + New-Item -ItemType File -Path $envFileController -Force | Out-Null + } + + $lines = Get-Content $envFileController + + foreach ($item in $requiredController) { + $key = $item.Key + $value = $item.Value + $comment = "# $($item.Comment)" + + $exists = $lines | Where-Object { $_ -match "^\s*$key\s*=" } + + if (-not $exists) { + Write-Output "[$key] missing -> adding to .env" + Add-Content -Path $envFileController -Value "`n$comment" + Add-Content -Path $envFileController -Value "$key=$value" + } + else { + Write-Output "[$key] already exists -> skipping" + } + } + } diff --git a/scripts/update-controllers.ps1 b/scripts/update-controllers.ps1 index af6dfe8..17db648 100644 --- a/scripts/update-controllers.ps1 +++ b/scripts/update-controllers.ps1 @@ -14,7 +14,7 @@ param ( # example string to pass over, you must be in the script dir when you run this script. or it will fail to find the linked scripts # If we do not pass plant to update over it will auto do all plants if we want a specific plant we need to do like below -# .\update-controllers.ps1 -App_Path "C:\Users\matthes01\Documents\lst" -Token "test3" -BuildController yes -PlantToUpdate "usmcd1vms036" -Remote_Path "E$\LST" +# .\update-controllers.ps1 -App_Path "C:\Users\matthes01\Documents\lst" -Token "usiow2" -BuildController no -PlantToUpdate "usiow1vms006" -Remote_Path "D$\LST\lst_2" # .\update-controllers.ps1 -App_Path "C:\Users\matthes01\Documents\lst" -Token "test3" -BuildController yes $Plants = @(