diff --git a/.env-example b/.env-example
index cfea41c..fb68830 100644
--- a/.env-example
+++ b/.env-example
@@ -25,6 +25,12 @@ PROD_PLANT_TOKEN=test3
PROD_USER=alplaprod
PROD_PASSWORD=password
+# Auth stuff
+BETTER_AUTH_SECRET="3d2b7d64ac2f9ebd6854325a84390666f4bbd2c7c3f537bb60fca3740f081e1e"
+
+# Your APP URL
+BETTER_AUTH_URL="http://localhost:3000"
+
# Docker Related
PROD_IP=10.193.0.56
LOGISTICS_NETWORK=10.193.14.0/24
diff --git a/LogisticsSupportTool_API_DOCS/app/auth/Auth Me.bru b/LogisticsSupportTool_API_DOCS/app/auth/Auth Me.bru
new file mode 100644
index 0000000..6545d06
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/auth/Auth Me.bru
@@ -0,0 +1,19 @@
+meta {
+ name: Auth Me
+ type: http
+ seq: 1
+}
+
+get {
+ url: http://{{url}}/lst/api/me
+ body: none
+ auth: inherit
+}
+
+headers {
+ Cookie: {{session_cookie}}
+}
+
+settings {
+ encodeUrl: true
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/auth/Register.bru b/LogisticsSupportTool_API_DOCS/app/auth/Register.bru
new file mode 100644
index 0000000..915a845
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/auth/Register.bru
@@ -0,0 +1,24 @@
+meta {
+ name: Register
+ type: http
+ seq: 2
+}
+
+post {
+ url: http://{{url}}/lst/api/register
+ body: json
+ auth: inherit
+}
+
+body:json {
+ {
+ "username":"matthes01",
+ "name":"blake",
+ "email":"blake.matthes@alpla.com",
+ "password":"nova0511"
+ }
+}
+
+settings {
+ encodeUrl: true
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/auth/Sign-In - email.bru b/LogisticsSupportTool_API_DOCS/app/auth/Sign-In - email.bru
new file mode 100644
index 0000000..755d61c
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/auth/Sign-In - email.bru
@@ -0,0 +1,35 @@
+meta {
+ name: Sign-In - email
+ type: http
+ seq: 3
+}
+
+post {
+ url: http://{{url}}/lst/api/auth/sign-in/email
+ body: json
+ auth: inherit
+}
+
+body:json {
+ {
+ "email": "blake.matthes@alpla.com",
+ "password": "nova0511"
+ }
+}
+
+script:post-response {
+ // grab the raw Set-Cookie header
+ const cookies = res.headers["set-cookie"];
+
+ // cookies is usually an array, e.g. ["auth_session=abcd123; Path=/; HttpOnly; Secure; SameSite=Lax"]
+
+ // Extract just the value part ("auth_session=abcd123")
+ const sessionCookie = cookies[0].split(";")[0];
+
+ // Save it as an environment variable
+ bru.setEnvVar("session_cookie", sessionCookie);
+}
+
+settings {
+ encodeUrl: true
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/auth/Sign-In - username.bru b/LogisticsSupportTool_API_DOCS/app/auth/Sign-In - username.bru
new file mode 100644
index 0000000..4e95f35
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/auth/Sign-In - username.bru
@@ -0,0 +1,35 @@
+meta {
+ name: Sign-In - username
+ type: http
+ seq: 4
+}
+
+post {
+ url: http://{{url}}/lst/api/auth/sign-in/username
+ body: json
+ auth: inherit
+}
+
+body:json {
+ {
+ "username": "matthes01",
+ "password": "nova0511"
+ }
+}
+
+script:post-response {
+ // grab the raw Set-Cookie header
+ const cookies = res.headers["set-cookie"];
+
+ // cookies is usually an array, e.g. ["auth_session=abcd123; Path=/; HttpOnly; Secure; SameSite=Lax"]
+
+ // Extract just the value part ("auth_session=abcd123")
+ const sessionCookie = cookies[0].split(";")[0];
+
+ // Save it as an environment variable
+ bru.setEnvVar("session_cookie", sessionCookie);
+}
+
+settings {
+ encodeUrl: true
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/auth/folder.bru b/LogisticsSupportTool_API_DOCS/app/auth/folder.bru
new file mode 100644
index 0000000..8fe9662
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/auth/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: auth
+ seq: 1
+}
+
+auth {
+ mode: inherit
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/folder.bru b/LogisticsSupportTool_API_DOCS/app/folder.bru
new file mode 100644
index 0000000..0b09462
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: app
+ seq: 2
+}
+
+auth {
+ mode: inherit
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/system/Health.bru b/LogisticsSupportTool_API_DOCS/app/system/Health.bru
new file mode 100644
index 0000000..b4c3af7
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/system/Health.bru
@@ -0,0 +1,15 @@
+meta {
+ name: Health
+ type: http
+ seq: 1
+}
+
+get {
+ url: http://{{url}}/lst/api/system/health
+ body: none
+ auth: inherit
+}
+
+settings {
+ encodeUrl: true
+}
diff --git a/LogisticsSupportTool_API_DOCS/app/system/folder.bru b/LogisticsSupportTool_API_DOCS/app/system/folder.bru
new file mode 100644
index 0000000..9d9901f
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/app/system/folder.bru
@@ -0,0 +1,8 @@
+meta {
+ name: system
+ seq: 2
+}
+
+auth {
+ mode: inherit
+}
diff --git a/LogisticsSupportTool_API_DOCS/environments/lst.bru b/LogisticsSupportTool_API_DOCS/environments/lst.bru
new file mode 100644
index 0000000..347396f
--- /dev/null
+++ b/LogisticsSupportTool_API_DOCS/environments/lst.bru
@@ -0,0 +1,4 @@
+vars {
+ url: localhost:4200
+ session_cookie:
+}
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 3e84ec6..74733f7 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -10,8 +10,10 @@
"dependencies": {
"@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.13",
+ "@tanstack/react-query": "^5.89.0",
"@tanstack/react-router": "^1.131.36",
"@tanstack/react-router-devtools": "^1.131.36",
+ "better-auth": "^1.3.11",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.542.0",
@@ -500,6 +502,17 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@better-auth/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==",
+ "license": "MIT"
+ },
+ "node_modules/@better-fetch/fetch": {
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz",
+ "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA=="
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
@@ -1070,6 +1083,12 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@hexagon/base64": {
+ "version": "1.1.28",
+ "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz",
+ "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==",
+ "license": "MIT"
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1193,6 +1212,36 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@levischuck/tiny-cbor": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz",
+ "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==",
+ "license": "MIT"
+ },
+ "node_modules/@noble/ciphers": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.0.0.tgz",
+ "integrity": "sha512-j/l6jpnpaIBM87cAYPJzi/6TgqmBv9spkqPyCXvRYsu5uxqh6tPJZDnD85yo8VWqzTuTQPgfv7NgT63u7kbwAQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.0.tgz",
+ "integrity": "sha512-h8VUBlE8R42+XIDO229cgisD287im3kdY6nbNZJFjc6ZvKIXPYXe6Vc/t+kyjFdMFyt5JpapzTsEg8n63w5/lw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20.19.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -1231,6 +1280,162 @@
"node": ">= 8"
}
},
+ "node_modules/@peculiar/asn1-android": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.5.0.tgz",
+ "integrity": "sha512-t8A83hgghWQkcneRsgGs2ebAlRe54ns88p7ouv8PW2tzF1nAW4yHcL4uZKrFpIU+uszIRzTkcCuie37gpkId0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-cms": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.5.0.tgz",
+ "integrity": "sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "@peculiar/asn1-x509-attr": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-csr": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.5.0.tgz",
+ "integrity": "sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-ecc": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.5.0.tgz",
+ "integrity": "sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-pfx": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.5.0.tgz",
+ "integrity": "sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-cms": "^2.5.0",
+ "@peculiar/asn1-pkcs8": "^2.5.0",
+ "@peculiar/asn1-rsa": "^2.5.0",
+ "@peculiar/asn1-schema": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-pkcs8": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.5.0.tgz",
+ "integrity": "sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-pkcs9": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.5.0.tgz",
+ "integrity": "sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-cms": "^2.5.0",
+ "@peculiar/asn1-pfx": "^2.5.0",
+ "@peculiar/asn1-pkcs8": "^2.5.0",
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "@peculiar/asn1-x509-attr": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-rsa": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.5.0.tgz",
+ "integrity": "sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-schema": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.5.0.tgz",
+ "integrity": "sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "asn1js": "^3.0.6",
+ "pvtsutils": "^1.3.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-x509": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.5.0.tgz",
+ "integrity": "sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "pvtsutils": "^1.3.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-x509-attr": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.5.0.tgz",
+ "integrity": "sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/x509": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.0.tgz",
+ "integrity": "sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-cms": "^2.5.0",
+ "@peculiar/asn1-csr": "^2.5.0",
+ "@peculiar/asn1-ecc": "^2.5.0",
+ "@peculiar/asn1-pkcs9": "^2.5.0",
+ "@peculiar/asn1-rsa": "^2.5.0",
+ "@peculiar/asn1-schema": "^2.5.0",
+ "@peculiar/asn1-x509": "^2.5.0",
+ "pvtsutils": "^1.3.6",
+ "reflect-metadata": "^0.2.2",
+ "tslib": "^2.8.1",
+ "tsyringe": "^4.10.0"
+ }
+ },
"node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
@@ -1531,6 +1736,31 @@
"win32"
]
},
+ "node_modules/@simplewebauthn/browser": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.2.0.tgz",
+ "integrity": "sha512-N3fuA1AAnTo5gCStYoIoiasPccC+xPLx2YU88Dv0GeAmPQTWHETlZQq5xZ0DgUq1H9loXMWQH5qqUjcI7BHJ1A==",
+ "license": "MIT"
+ },
+ "node_modules/@simplewebauthn/server": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.2.0.tgz",
+ "integrity": "sha512-meBOTUhWZsQyrBcXDva82Tiyes5UlPQu+fKuMKQlhmAJwR/a+orU8xYfpTQviEaV7qEYD4aMj9He/eBj1KX9hA==",
+ "license": "MIT",
+ "dependencies": {
+ "@hexagon/base64": "^1.1.27",
+ "@levischuck/tiny-cbor": "^0.2.2",
+ "@peculiar/asn1-android": "^2.3.10",
+ "@peculiar/asn1-ecc": "^2.3.8",
+ "@peculiar/asn1-rsa": "^2.3.8",
+ "@peculiar/asn1-schema": "^2.3.8",
+ "@peculiar/asn1-x509": "^2.3.8",
+ "@peculiar/x509": "^1.13.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
"node_modules/@swc/core": {
"version": "1.13.5",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz",
@@ -2032,6 +2262,32 @@
"url": "https://github.com/sponsors/tannerlinsley"
}
},
+ "node_modules/@tanstack/query-core": {
+ "version": "5.89.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.89.0.tgz",
+ "integrity": "sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/react-query": {
+ "version": "5.89.0",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.89.0.tgz",
+ "integrity": "sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/query-core": "5.89.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19"
+ }
+ },
"node_modules/@tanstack/react-router": {
"version": "1.131.36",
"resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.131.36.tgz",
@@ -2676,6 +2932,20 @@
"dev": true,
"license": "Python-2.0"
},
+ "node_modules/asn1js": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz",
+ "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "pvtsutils": "^1.3.6",
+ "pvutils": "^1.1.3",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/ast-types": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz",
@@ -2709,6 +2979,83 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/better-auth": {
+ "version": "1.3.11",
+ "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.3.11.tgz",
+ "integrity": "sha512-7l8bHX5rnON4vsVmWB7g2UucNpRlXnDUX/n65mHeR3Zn2/lcpQvfBvGbTaHYU8UGCQadtJ7DLHW/zA3ZR7IfdA==",
+ "license": "MIT",
+ "dependencies": {
+ "@better-auth/utils": "0.3.0",
+ "@better-fetch/fetch": "^1.1.18",
+ "@noble/ciphers": "^2.0.0",
+ "@noble/hashes": "^2.0.0",
+ "@simplewebauthn/browser": "^13.1.2",
+ "@simplewebauthn/server": "^13.1.2",
+ "better-call": "1.0.19",
+ "defu": "^6.1.4",
+ "jose": "^6.1.0",
+ "kysely": "^0.28.5",
+ "nanostores": "^1.0.1",
+ "zod": "^4.1.5"
+ },
+ "peerDependencies": {
+ "@lynx-js/react": "*",
+ "@sveltejs/kit": "^2.0.0",
+ "next": "^14.0.0 || ^15.0.0",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0",
+ "solid-js": "^1.0.0",
+ "svelte": "^4.0.0 || ^5.0.0",
+ "vue": "^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@lynx-js/react": {
+ "optional": true
+ },
+ "@sveltejs/kit": {
+ "optional": true
+ },
+ "next": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "solid-js": {
+ "optional": true
+ },
+ "svelte": {
+ "optional": true
+ },
+ "vue": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/better-auth/node_modules/zod": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.9.tgz",
+ "integrity": "sha512-HI32jTq0AUAC125z30E8bQNz0RQ+9Uc+4J7V97gLYjZVKRjeydPgGt6dvQzFrav7MYOUGFqqOGiHpA/fdbd0cQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/better-call": {
+ "version": "1.0.19",
+ "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.0.19.tgz",
+ "integrity": "sha512-sI3GcA1SCVa3H+CDHl8W8qzhlrckwXOTKhqq3OOPXjgn5aTOMIqGY34zLY/pHA6tRRMjTUC3lz5Mi7EbDA24Kw==",
+ "dependencies": {
+ "@better-auth/utils": "^0.3.0",
+ "@better-fetch/fetch": "^1.1.4",
+ "rou3": "^0.5.1",
+ "set-cookie-parser": "^2.7.1",
+ "uncrypto": "^0.1.3"
+ }
+ },
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -2981,6 +3328,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/defu": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
+ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
+ "license": "MIT"
+ },
"node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
@@ -3604,6 +3957,15 @@
"jiti": "lib/jiti-cli.mjs"
}
},
+ "node_modules/jose": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz",
+ "integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -3681,6 +4043,15 @@
"json-buffer": "3.0.1"
}
},
+ "node_modules/kysely": {
+ "version": "0.28.7",
+ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.7.tgz",
+ "integrity": "sha512-u/cAuTL4DRIiO2/g4vNGRgklEKNIj5Q3CG7RoUB5DV5SfEC2hMvPxKi0GWPmnzwL2ryIeud2VTcEEmqzTzEPNw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -4072,6 +4443,21 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/nanostores": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.0.1.tgz",
+ "integrity": "sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": "^20.0.0 || >=22.0.0"
+ }
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -4262,6 +4648,24 @@
"node": ">=6"
}
},
+ "node_modules/pvtsutils": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz",
+ "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/pvutils": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz",
+ "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -4344,6 +4748,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/reflect-metadata": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
+ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
+ "license": "Apache-2.0"
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -4414,6 +4824,12 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/rou3": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/rou3/-/rou3-0.5.1.tgz",
+ "integrity": "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==",
+ "license": "MIT"
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4478,6 +4894,12 @@
"seroval": "^1.0"
}
},
+ "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/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -4699,7 +5121,6 @@
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "devOptional": true,
"license": "0BSD"
},
"node_modules/tsx": {
@@ -4722,6 +5143,24 @@
"fsevents": "~2.3.3"
}
},
+ "node_modules/tsyringe": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz",
+ "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/tsyringe/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "license": "0BSD"
+ },
"node_modules/tw-animate-css": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.3.8.tgz",
@@ -4783,6 +5222,12 @@
"typescript": ">=4.8.4 <6.0.0"
}
},
+ "node_modules/uncrypto": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz",
+ "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
+ "license": "MIT"
+ },
"node_modules/undici-types": {
"version": "7.10.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 0c207d6..fcffa85 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -12,8 +12,10 @@
"dependencies": {
"@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.13",
+ "@tanstack/react-query": "^5.89.0",
"@tanstack/react-router": "^1.131.36",
"@tanstack/react-router-devtools": "^1.131.36",
+ "better-auth": "^1.3.11",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.542.0",
diff --git a/frontend/src/lib/authClient.ts b/frontend/src/lib/authClient.ts
new file mode 100644
index 0000000..5f137da
--- /dev/null
+++ b/frontend/src/lib/authClient.ts
@@ -0,0 +1,11 @@
+import { createAuthClient } from "better-auth/client";
+import { usernameClient } from "better-auth/client/plugins";
+export const authClient = createAuthClient({
+ baseURL: `${window.location.origin}/lst/api/auth`, // 👈 This is fine
+ callbacks: {
+ onUpdate: (session: any) => console.log("Session updated", session),
+ onSignIn: (session: any) => console.log("Signed in!", session),
+ onSignOut: () => console.log("Signed out!"),
+ },
+ plugins: [usernameClient()],
+});
diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts
index bd0c391..e6a8be0 100644
--- a/frontend/src/lib/utils.ts
+++ b/frontend/src/lib/utils.ts
@@ -1,6 +1,6 @@
-import { clsx, type ClassValue } from "clsx"
-import { twMerge } from "tailwind-merge"
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
- return twMerge(clsx(inputs))
+ return twMerge(clsx(inputs));
}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 3287e7f..7d21636 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,12 +1,15 @@
import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
-
import { RouterProvider, createRouter } from "@tanstack/react-router";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
// Import the generated route tree
import { routeTree } from "./routeTree.gen";
+// Create a client
+const queryClient = new QueryClient();
+
// Create a new router instance
const router = createRouter({ routeTree, basepath: "/lst/app" });
@@ -19,6 +22,8 @@ declare module "@tanstack/react-router" {
ReactDOM.createRoot(document.getElementById("root")!).render(
-
+
+
+
);
diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts
index d204c26..6dea534 100644
--- a/frontend/src/routeTree.gen.ts
+++ b/frontend/src/routeTree.gen.ts
@@ -9,38 +9,160 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
import { Route as rootRouteImport } from './routes/__root'
+import { Route as _adminRouteImport } from './routes/__admin'
+import { Route as AdminLayoutRouteRouteImport } from './routes/_adminLayout/route'
import { Route as IndexRouteImport } from './routes/index'
+import { Route as AdminSettingsRouteImport } from './routes/admin_/settings'
+import { Route as AdminLayoutAdminIndexRouteImport } from './routes/_adminLayout/admin/index'
+import { Route as AdminLayoutAdminUsersRouteImport } from './routes/_adminLayout/admin/users'
+import { Route as AdminLayoutAdminServersRouteImport } from './routes/_adminLayout/admin/servers'
+import { Route as AdminLayoutAdminUserUserIdRouteImport } from './routes/_adminLayout/admin/user/$userId'
+import { Route as AdminLayoutAdminServersServerIdRouteImport } from './routes/_adminLayout/admin/servers/$serverId'
+import { Route as AdminLayoutAdminServersServerIdEditRouteImport } from './routes/_adminLayout/admin/servers/$serverId_/edit'
+const _adminRoute = _adminRouteImport.update({
+ id: '/__admin',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const AdminLayoutRouteRoute = AdminLayoutRouteRouteImport.update({
+ id: '/_adminLayout',
+ getParentRoute: () => rootRouteImport,
+} as any)
const IndexRoute = IndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
+const AdminSettingsRoute = AdminSettingsRouteImport.update({
+ id: '/admin_/settings',
+ path: '/admin/settings',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const AdminLayoutAdminIndexRoute = AdminLayoutAdminIndexRouteImport.update({
+ id: '/admin/',
+ path: '/admin/',
+ getParentRoute: () => AdminLayoutRouteRoute,
+} as any)
+const AdminLayoutAdminUsersRoute = AdminLayoutAdminUsersRouteImport.update({
+ id: '/admin/users',
+ path: '/admin/users',
+ getParentRoute: () => AdminLayoutRouteRoute,
+} as any)
+const AdminLayoutAdminServersRoute = AdminLayoutAdminServersRouteImport.update({
+ id: '/admin/servers',
+ path: '/admin/servers',
+ getParentRoute: () => AdminLayoutRouteRoute,
+} as any)
+const AdminLayoutAdminUserUserIdRoute =
+ AdminLayoutAdminUserUserIdRouteImport.update({
+ id: '/admin/user/$userId',
+ path: '/admin/user/$userId',
+ getParentRoute: () => AdminLayoutRouteRoute,
+ } as any)
+const AdminLayoutAdminServersServerIdRoute =
+ AdminLayoutAdminServersServerIdRouteImport.update({
+ id: '/$serverId',
+ path: '/$serverId',
+ getParentRoute: () => AdminLayoutAdminServersRoute,
+ } as any)
+const AdminLayoutAdminServersServerIdEditRoute =
+ AdminLayoutAdminServersServerIdEditRouteImport.update({
+ id: '/$serverId_/edit',
+ path: '/$serverId/edit',
+ getParentRoute: () => AdminLayoutAdminServersRoute,
+ } as any)
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
+ '/admin/settings': typeof AdminSettingsRoute
+ '/admin/servers': typeof AdminLayoutAdminServersRouteWithChildren
+ '/admin/users': typeof AdminLayoutAdminUsersRoute
+ '/admin': typeof AdminLayoutAdminIndexRoute
+ '/admin/servers/$serverId': typeof AdminLayoutAdminServersServerIdRoute
+ '/admin/user/$userId': typeof AdminLayoutAdminUserUserIdRoute
+ '/admin/servers/$serverId/edit': typeof AdminLayoutAdminServersServerIdEditRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
+ '/admin/settings': typeof AdminSettingsRoute
+ '/admin/servers': typeof AdminLayoutAdminServersRouteWithChildren
+ '/admin/users': typeof AdminLayoutAdminUsersRoute
+ '/admin': typeof AdminLayoutAdminIndexRoute
+ '/admin/servers/$serverId': typeof AdminLayoutAdminServersServerIdRoute
+ '/admin/user/$userId': typeof AdminLayoutAdminUserUserIdRoute
+ '/admin/servers/$serverId/edit': typeof AdminLayoutAdminServersServerIdEditRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
+ '/_adminLayout': typeof AdminLayoutRouteRouteWithChildren
+ '/__admin': typeof _adminRoute
+ '/admin_/settings': typeof AdminSettingsRoute
+ '/_adminLayout/admin/servers': typeof AdminLayoutAdminServersRouteWithChildren
+ '/_adminLayout/admin/users': typeof AdminLayoutAdminUsersRoute
+ '/_adminLayout/admin/': typeof AdminLayoutAdminIndexRoute
+ '/_adminLayout/admin/servers/$serverId': typeof AdminLayoutAdminServersServerIdRoute
+ '/_adminLayout/admin/user/$userId': typeof AdminLayoutAdminUserUserIdRoute
+ '/_adminLayout/admin/servers/$serverId_/edit': typeof AdminLayoutAdminServersServerIdEditRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
- fullPaths: '/'
+ fullPaths:
+ | '/'
+ | '/admin/settings'
+ | '/admin/servers'
+ | '/admin/users'
+ | '/admin'
+ | '/admin/servers/$serverId'
+ | '/admin/user/$userId'
+ | '/admin/servers/$serverId/edit'
fileRoutesByTo: FileRoutesByTo
- to: '/'
- id: '__root__' | '/'
+ to:
+ | '/'
+ | '/admin/settings'
+ | '/admin/servers'
+ | '/admin/users'
+ | '/admin'
+ | '/admin/servers/$serverId'
+ | '/admin/user/$userId'
+ | '/admin/servers/$serverId/edit'
+ id:
+ | '__root__'
+ | '/'
+ | '/_adminLayout'
+ | '/__admin'
+ | '/admin_/settings'
+ | '/_adminLayout/admin/servers'
+ | '/_adminLayout/admin/users'
+ | '/_adminLayout/admin/'
+ | '/_adminLayout/admin/servers/$serverId'
+ | '/_adminLayout/admin/user/$userId'
+ | '/_adminLayout/admin/servers/$serverId_/edit'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
+ AdminLayoutRouteRoute: typeof AdminLayoutRouteRouteWithChildren
+ _adminRoute: typeof _adminRoute
+ AdminSettingsRoute: typeof AdminSettingsRoute
}
declare module '@tanstack/react-router' {
interface FileRoutesByPath {
+ '/__admin': {
+ id: '/__admin'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof _adminRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/_adminLayout': {
+ id: '/_adminLayout'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof AdminLayoutRouteRouteImport
+ parentRoute: typeof rootRouteImport
+ }
'/': {
id: '/'
path: '/'
@@ -48,11 +170,97 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
+ '/admin_/settings': {
+ id: '/admin_/settings'
+ path: '/admin/settings'
+ fullPath: '/admin/settings'
+ preLoaderRoute: typeof AdminSettingsRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/_adminLayout/admin/': {
+ id: '/_adminLayout/admin/'
+ path: '/admin'
+ fullPath: '/admin'
+ preLoaderRoute: typeof AdminLayoutAdminIndexRouteImport
+ parentRoute: typeof AdminLayoutRouteRoute
+ }
+ '/_adminLayout/admin/users': {
+ id: '/_adminLayout/admin/users'
+ path: '/admin/users'
+ fullPath: '/admin/users'
+ preLoaderRoute: typeof AdminLayoutAdminUsersRouteImport
+ parentRoute: typeof AdminLayoutRouteRoute
+ }
+ '/_adminLayout/admin/servers': {
+ id: '/_adminLayout/admin/servers'
+ path: '/admin/servers'
+ fullPath: '/admin/servers'
+ preLoaderRoute: typeof AdminLayoutAdminServersRouteImport
+ parentRoute: typeof AdminLayoutRouteRoute
+ }
+ '/_adminLayout/admin/user/$userId': {
+ id: '/_adminLayout/admin/user/$userId'
+ path: '/admin/user/$userId'
+ fullPath: '/admin/user/$userId'
+ preLoaderRoute: typeof AdminLayoutAdminUserUserIdRouteImport
+ parentRoute: typeof AdminLayoutRouteRoute
+ }
+ '/_adminLayout/admin/servers/$serverId': {
+ id: '/_adminLayout/admin/servers/$serverId'
+ path: '/$serverId'
+ fullPath: '/admin/servers/$serverId'
+ preLoaderRoute: typeof AdminLayoutAdminServersServerIdRouteImport
+ parentRoute: typeof AdminLayoutAdminServersRoute
+ }
+ '/_adminLayout/admin/servers/$serverId_/edit': {
+ id: '/_adminLayout/admin/servers/$serverId_/edit'
+ path: '/$serverId/edit'
+ fullPath: '/admin/servers/$serverId/edit'
+ preLoaderRoute: typeof AdminLayoutAdminServersServerIdEditRouteImport
+ parentRoute: typeof AdminLayoutAdminServersRoute
+ }
}
}
+interface AdminLayoutAdminServersRouteChildren {
+ AdminLayoutAdminServersServerIdRoute: typeof AdminLayoutAdminServersServerIdRoute
+ AdminLayoutAdminServersServerIdEditRoute: typeof AdminLayoutAdminServersServerIdEditRoute
+}
+
+const AdminLayoutAdminServersRouteChildren: AdminLayoutAdminServersRouteChildren =
+ {
+ AdminLayoutAdminServersServerIdRoute: AdminLayoutAdminServersServerIdRoute,
+ AdminLayoutAdminServersServerIdEditRoute:
+ AdminLayoutAdminServersServerIdEditRoute,
+ }
+
+const AdminLayoutAdminServersRouteWithChildren =
+ AdminLayoutAdminServersRoute._addFileChildren(
+ AdminLayoutAdminServersRouteChildren,
+ )
+
+interface AdminLayoutRouteRouteChildren {
+ AdminLayoutAdminServersRoute: typeof AdminLayoutAdminServersRouteWithChildren
+ AdminLayoutAdminUsersRoute: typeof AdminLayoutAdminUsersRoute
+ AdminLayoutAdminIndexRoute: typeof AdminLayoutAdminIndexRoute
+ AdminLayoutAdminUserUserIdRoute: typeof AdminLayoutAdminUserUserIdRoute
+}
+
+const AdminLayoutRouteRouteChildren: AdminLayoutRouteRouteChildren = {
+ AdminLayoutAdminServersRoute: AdminLayoutAdminServersRouteWithChildren,
+ AdminLayoutAdminUsersRoute: AdminLayoutAdminUsersRoute,
+ AdminLayoutAdminIndexRoute: AdminLayoutAdminIndexRoute,
+ AdminLayoutAdminUserUserIdRoute: AdminLayoutAdminUserUserIdRoute,
+}
+
+const AdminLayoutRouteRouteWithChildren =
+ AdminLayoutRouteRoute._addFileChildren(AdminLayoutRouteRouteChildren)
+
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
+ AdminLayoutRouteRoute: AdminLayoutRouteRouteWithChildren,
+ _adminRoute: _adminRoute,
+ AdminSettingsRoute: AdminSettingsRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)
diff --git a/frontend/src/routes/__admin.tsx b/frontend/src/routes/__admin.tsx
new file mode 100644
index 0000000..a091070
--- /dev/null
+++ b/frontend/src/routes/__admin.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/__admin')({
+ component: RouteComponent,
+})
+
+function RouteComponent() {
+ return
-
+
);
}
diff --git a/lstDocs/static/img/ocp/lotTransfer.png b/lstDocs/static/img/ocp/lotTransfer.png
index aebdee7..d0358c1 100644
Binary files a/lstDocs/static/img/ocp/lotTransfer.png and b/lstDocs/static/img/ocp/lotTransfer.png differ
diff --git a/migrations/0003_curved_mariko_yashida.sql b/migrations/0003_curved_mariko_yashida.sql
new file mode 100644
index 0000000..f640a59
--- /dev/null
+++ b/migrations/0003_curved_mariko_yashida.sql
@@ -0,0 +1,90 @@
+CREATE TABLE "account" (
+ "id" text PRIMARY KEY NOT NULL,
+ "account_id" text NOT NULL,
+ "provider_id" text NOT NULL,
+ "user_id" text NOT NULL,
+ "access_token" text,
+ "refresh_token" text,
+ "id_token" text,
+ "access_token_expires_at" timestamp,
+ "refresh_token_expires_at" timestamp,
+ "scope" text,
+ "password" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "apikey" (
+ "id" text PRIMARY KEY NOT NULL,
+ "name" text,
+ "start" text,
+ "prefix" text,
+ "key" text NOT NULL,
+ "user_id" text NOT NULL,
+ "refill_interval" integer,
+ "refill_amount" integer,
+ "last_refill_at" timestamp,
+ "enabled" boolean DEFAULT true,
+ "rate_limit_enabled" boolean DEFAULT true,
+ "rate_limit_time_window" integer DEFAULT 86400000,
+ "rate_limit_max" integer DEFAULT 10,
+ "request_count" integer DEFAULT 0,
+ "remaining" integer,
+ "last_request" timestamp,
+ "expires_at" timestamp,
+ "created_at" timestamp NOT NULL,
+ "updated_at" timestamp NOT NULL,
+ "permissions" text,
+ "metadata" text
+);
+--> statement-breakpoint
+CREATE TABLE "jwks" (
+ "id" text PRIMARY KEY NOT NULL,
+ "public_key" text NOT NULL,
+ "private_key" text NOT NULL,
+ "created_at" timestamp NOT NULL
+);
+--> statement-breakpoint
+CREATE TABLE "session" (
+ "id" text PRIMARY KEY NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "token" text NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp NOT NULL,
+ "ip_address" text,
+ "user_agent" text,
+ "user_id" text NOT NULL,
+ "impersonated_by" text,
+ CONSTRAINT "session_token_unique" UNIQUE("token")
+);
+--> statement-breakpoint
+CREATE TABLE "user" (
+ "id" text PRIMARY KEY NOT NULL,
+ "name" text NOT NULL,
+ "email" text NOT NULL,
+ "email_verified" boolean DEFAULT false NOT NULL,
+ "image" text,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL,
+ "role" text,
+ "banned" boolean DEFAULT false,
+ "ban_reason" text,
+ "ban_expires" timestamp,
+ "username" text,
+ "display_username" text,
+ CONSTRAINT "user_email_unique" UNIQUE("email"),
+ CONSTRAINT "user_username_unique" UNIQUE("username")
+);
+--> statement-breakpoint
+CREATE TABLE "verification" (
+ "id" text PRIMARY KEY NOT NULL,
+ "identifier" text NOT NULL,
+ "value" text NOT NULL,
+ "expires_at" timestamp NOT NULL,
+ "created_at" timestamp DEFAULT now() NOT NULL,
+ "updated_at" timestamp DEFAULT now() NOT NULL
+);
+--> statement-breakpoint
+ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "apikey" ADD CONSTRAINT "apikey_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
\ No newline at end of file
diff --git a/migrations/0004_panoramic_longshot.sql b/migrations/0004_panoramic_longshot.sql
new file mode 100644
index 0000000..7fa7e9a
--- /dev/null
+++ b/migrations/0004_panoramic_longshot.sql
@@ -0,0 +1 @@
+ALTER TABLE "user" ADD COLUMN "last_login" timestamp;
\ No newline at end of file
diff --git a/migrations/0005_gorgeous_purple_man.sql b/migrations/0005_gorgeous_purple_man.sql
new file mode 100644
index 0000000..65c0302
--- /dev/null
+++ b/migrations/0005_gorgeous_purple_man.sql
@@ -0,0 +1,9 @@
+CREATE TABLE "user_role" (
+ "user_role_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
+ "user_id" text NOT NULL,
+ "module" text NOT NULL,
+ "role" text NOT NULL
+);
+--> statement-breakpoint
+ALTER TABLE "user_role" ADD CONSTRAINT "user_role_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+CREATE UNIQUE INDEX "unique_user_module" ON "user_role" USING btree ("user_id","module");
\ No newline at end of file
diff --git a/migrations/meta/0003_snapshot.json b/migrations/meta/0003_snapshot.json
new file mode 100644
index 0000000..19a06af
--- /dev/null
+++ b/migrations/meta/0003_snapshot.json
@@ -0,0 +1,744 @@
+{
+ "id": "0e050a96-8de7-4634-9f8e-0f3ba69c187a",
+ "prevId": "922093ba-6949-4d30-9c17-007257754cf2",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "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
+ }
+ },
+ "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.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
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/migrations/meta/0004_snapshot.json b/migrations/meta/0004_snapshot.json
new file mode 100644
index 0000000..0fa0329
--- /dev/null
+++ b/migrations/meta/0004_snapshot.json
@@ -0,0 +1,750 @@
+{
+ "id": "ec376ba2-db90-487c-b82a-d033a2c60244",
+ "prevId": "0e050a96-8de7-4634-9f8e-0f3ba69c187a",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "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.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
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/migrations/meta/0005_snapshot.json b/migrations/meta/0005_snapshot.json
new file mode 100644
index 0000000..53bda96
--- /dev/null
+++ b/migrations/meta/0005_snapshot.json
@@ -0,0 +1,824 @@
+{
+ "id": "639e50c0-757a-4867-a78e-48e8e1a416fc",
+ "prevId": "ec376ba2-db90-487c-b82a-d033a2c60244",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "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.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_role": {
+ "name": "user_role",
+ "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_role_user_id_user_id_fk": {
+ "name": "user_role_user_id_user_id_fk",
+ "tableFrom": "user_role",
+ "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 1509705..a1d57c5 100644
--- a/migrations/meta/_journal.json
+++ b/migrations/meta/_journal.json
@@ -22,6 +22,27 @@
"when": 1756843987534,
"tag": "0002_mean_nuke",
"breakpoints": true
+ },
+ {
+ "idx": 3,
+ "version": "7",
+ "when": 1758076031154,
+ "tag": "0003_curved_mariko_yashida",
+ "breakpoints": true
+ },
+ {
+ "idx": 4,
+ "version": "7",
+ "when": 1758079206432,
+ "tag": "0004_panoramic_longshot",
+ "breakpoints": true
+ },
+ {
+ "idx": 5,
+ "version": "7",
+ "when": 1758081790572,
+ "tag": "0005_gorgeous_purple_man",
+ "breakpoints": true
}
]
}
\ No newline at end of file