This commit is contained in:
@@ -2,3 +2,4 @@ DATA_DIR=./data
|
||||
ROOT_DIR=./data
|
||||
APP_PORT=4321
|
||||
IMAGE=git.atri.dad/atash/chronus:latest
|
||||
JWT_SECRET=some-secret
|
||||
@@ -9,6 +9,7 @@ export default defineConfig({
|
||||
output: "server",
|
||||
integrations: [vue()],
|
||||
security: {
|
||||
checkOrigin: false,
|
||||
csp: process.env.NODE_ENV === "production",
|
||||
},
|
||||
vite: {
|
||||
|
||||
@@ -8,6 +8,7 @@ services:
|
||||
- HOST=0.0.0.0
|
||||
- PORT=4321
|
||||
- DATA_DIR=/app/data
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
volumes:
|
||||
- ${ROOT_DIR}:/app/data
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"daisyui": "^5.5.18",
|
||||
"dotenv": "^17.3.0",
|
||||
"drizzle-orm": "0.45.1",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"nanoid": "^5.1.6",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"typescript": "^5.9.3",
|
||||
@@ -35,6 +36,7 @@
|
||||
"devDependencies": {
|
||||
"@catppuccin/daisyui": "^2.1.1",
|
||||
"@react-pdf/types": "^2.9.2",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"drizzle-kit": "0.31.9"
|
||||
}
|
||||
}
|
||||
|
||||
132
pnpm-lock.yaml
generated
132
pnpm-lock.yaml
generated
@@ -50,6 +50,9 @@ importers:
|
||||
drizzle-orm:
|
||||
specifier: 0.45.1
|
||||
version: 0.45.1(@libsql/client@0.17.0)(@types/better-sqlite3@7.6.13)(better-sqlite3@12.6.0)
|
||||
jsonwebtoken:
|
||||
specifier: ^9.0.3
|
||||
version: 9.0.3
|
||||
nanoid:
|
||||
specifier: ^5.1.6
|
||||
version: 5.1.6
|
||||
@@ -72,6 +75,9 @@ importers:
|
||||
'@react-pdf/types':
|
||||
specifier: ^2.9.2
|
||||
version: 2.9.2
|
||||
'@types/jsonwebtoken':
|
||||
specifier: ^9.0.10
|
||||
version: 9.0.10
|
||||
drizzle-kit:
|
||||
specifier: 0.31.9
|
||||
version: 0.31.9
|
||||
@@ -804,89 +810,105 @@ packages:
|
||||
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.2.4':
|
||||
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.4':
|
||||
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.2.4':
|
||||
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.2.4':
|
||||
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.2.4':
|
||||
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
|
||||
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.34.5':
|
||||
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-ppc64@0.34.5':
|
||||
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-riscv64@0.34.5':
|
||||
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.34.5':
|
||||
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.34.5':
|
||||
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.34.5':
|
||||
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-wasm32@0.34.5':
|
||||
resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
|
||||
@@ -1118,66 +1140,79 @@ packages:
|
||||
resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.57.1':
|
||||
resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.57.1':
|
||||
resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.57.1':
|
||||
resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.57.1':
|
||||
resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.57.1':
|
||||
resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.57.1':
|
||||
resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.57.1':
|
||||
resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.57.1':
|
||||
resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.57.1':
|
||||
resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.57.1':
|
||||
resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.57.1':
|
||||
resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.57.1':
|
||||
resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.57.1':
|
||||
resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==}
|
||||
@@ -1278,24 +1313,28 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
|
||||
resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
|
||||
resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
|
||||
resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
|
||||
resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
|
||||
@@ -1342,6 +1381,9 @@ packages:
|
||||
'@types/hast@3.0.4':
|
||||
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
|
||||
|
||||
'@types/jsonwebtoken@9.0.10':
|
||||
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
|
||||
|
||||
@@ -1620,6 +1662,9 @@ packages:
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||
|
||||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
@@ -1989,6 +2034,9 @@ packages:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||
|
||||
ee-first@1.1.1:
|
||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||
|
||||
@@ -2380,6 +2428,16 @@ packages:
|
||||
jsonify@0.0.1:
|
||||
resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==}
|
||||
|
||||
jsonwebtoken@9.0.3:
|
||||
resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==}
|
||||
engines: {node: '>=12', npm: '>=6'}
|
||||
|
||||
jwa@2.0.1:
|
||||
resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
|
||||
|
||||
jws@4.0.1:
|
||||
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
|
||||
|
||||
klaw-sync@6.0.0:
|
||||
resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==}
|
||||
|
||||
@@ -2434,24 +2492,28 @@ packages:
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.30.2:
|
||||
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.30.2:
|
||||
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-musl@1.30.2:
|
||||
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.30.2:
|
||||
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
|
||||
@@ -2472,6 +2534,27 @@ packages:
|
||||
linebreak@1.1.0:
|
||||
resolution: {integrity: sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==}
|
||||
|
||||
lodash.includes@4.3.0:
|
||||
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||
|
||||
lodash.isboolean@3.0.3:
|
||||
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
|
||||
|
||||
lodash.isinteger@4.0.4:
|
||||
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
|
||||
|
||||
lodash.isnumber@3.0.3:
|
||||
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
|
||||
|
||||
lodash.isplainobject@4.0.6:
|
||||
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||
|
||||
lodash.isstring@4.0.1:
|
||||
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||
|
||||
lodash.once@4.1.1:
|
||||
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||
|
||||
lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
|
||||
@@ -4817,6 +4900,11 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
'@types/jsonwebtoken@9.0.10':
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
'@types/node': 25.2.3
|
||||
|
||||
'@types/mdast@4.0.4':
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
@@ -5280,6 +5368,8 @@ snapshots:
|
||||
node-releases: 2.0.27
|
||||
update-browserslist-db: 1.2.3(browserslist@4.28.1)
|
||||
|
||||
buffer-equal-constant-time@1.0.1: {}
|
||||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
buffer@5.7.1:
|
||||
@@ -5538,6 +5628,10 @@ snapshots:
|
||||
es-errors: 1.3.0
|
||||
gopd: 1.2.0
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
ee-first@1.1.1: {}
|
||||
|
||||
electron-to-chromium@1.5.286: {}
|
||||
@@ -6010,6 +6104,30 @@ snapshots:
|
||||
|
||||
jsonify@0.0.1: {}
|
||||
|
||||
jsonwebtoken@9.0.3:
|
||||
dependencies:
|
||||
jws: 4.0.1
|
||||
lodash.includes: 4.3.0
|
||||
lodash.isboolean: 3.0.3
|
||||
lodash.isinteger: 4.0.4
|
||||
lodash.isnumber: 3.0.3
|
||||
lodash.isplainobject: 4.0.6
|
||||
lodash.isstring: 4.0.1
|
||||
lodash.once: 4.1.1
|
||||
ms: 2.1.3
|
||||
semver: 7.7.4
|
||||
|
||||
jwa@2.0.1:
|
||||
dependencies:
|
||||
buffer-equal-constant-time: 1.0.1
|
||||
ecdsa-sig-formatter: 1.0.11
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
jws@4.0.1:
|
||||
dependencies:
|
||||
jwa: 2.0.1
|
||||
safe-buffer: 5.2.1
|
||||
|
||||
klaw-sync@6.0.0:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
@@ -6089,6 +6207,20 @@ snapshots:
|
||||
base64-js: 0.0.8
|
||||
unicode-trie: 2.0.0
|
||||
|
||||
lodash.includes@4.3.0: {}
|
||||
|
||||
lodash.isboolean@3.0.3: {}
|
||||
|
||||
lodash.isinteger@4.0.4: {}
|
||||
|
||||
lodash.isnumber@3.0.3: {}
|
||||
|
||||
lodash.isplainobject@4.0.6: {}
|
||||
|
||||
lodash.isstring@4.0.1: {}
|
||||
|
||||
lodash.once@4.1.1: {}
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
||||
longest-streak@3.1.0: {}
|
||||
|
||||
1
src/env.d.ts
vendored
1
src/env.d.ts
vendored
@@ -14,7 +14,6 @@ interface ImportMeta {
|
||||
declare namespace App {
|
||||
interface Locals {
|
||||
user: import("./db/schema").User | null;
|
||||
session: import("./db/schema").Session | null;
|
||||
scopes: string[] | null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,14 +194,12 @@ function isActive(item: { href: string; exact?: boolean }) {
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Team switcher - sets cookie and reloads
|
||||
const teamSwitcher = document.getElementById('team-switcher') as HTMLSelectElement | null;
|
||||
teamSwitcher?.addEventListener('change', () => {
|
||||
document.cookie = 'currentTeamId=' + teamSwitcher.value + '; path=/';
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
|
||||
const logoutBtn = document.getElementById('logout-btn');
|
||||
logoutBtn?.addEventListener('click', async () => {
|
||||
await fetch('/api/auth/logout', { method: 'POST' });
|
||||
|
||||
@@ -1,50 +1,58 @@
|
||||
import { db } from '../db';
|
||||
import { users, sessions } from '../db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { db } from "../db";
|
||||
import { users } from "../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import bcrypt from "bcryptjs";
|
||||
import jwt from "jsonwebtoken";
|
||||
import type { AstroCookies } from "astro";
|
||||
|
||||
const SESSION_DURATION = 1000 * 60 * 60 * 24 * 30; // 30 days
|
||||
const JWT_SECRET =
|
||||
process.env.JWT_SECRET || "chronus-dev-secret-change-in-production";
|
||||
const JWT_EXPIRES_IN = "30d";
|
||||
|
||||
export async function createSession(userId: string) {
|
||||
const sessionId = nanoid();
|
||||
const expiresAt = new Date(Date.now() + SESSION_DURATION);
|
||||
interface JwtPayload {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
await db.insert(sessions).values({
|
||||
id: sessionId,
|
||||
userId,
|
||||
expiresAt,
|
||||
export function createToken(userId: string): string {
|
||||
return jwt.sign({ userId } satisfies JwtPayload, JWT_SECRET, {
|
||||
expiresIn: JWT_EXPIRES_IN,
|
||||
});
|
||||
|
||||
return { sessionId, expiresAt };
|
||||
}
|
||||
|
||||
export async function validateSession(sessionId: string) {
|
||||
const result = await db.select({
|
||||
user: users,
|
||||
session: sessions
|
||||
})
|
||||
.from(sessions)
|
||||
.innerJoin(users, eq(sessions.userId, users.id))
|
||||
.where(eq(sessions.id, sessionId))
|
||||
.get();
|
||||
|
||||
if (!result) {
|
||||
export function verifyToken(token: string): JwtPayload | null {
|
||||
try {
|
||||
return jwt.verify(token, JWT_SECRET) as JwtPayload;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { session, user } = result;
|
||||
|
||||
if (Date.now() >= session.expiresAt.getTime()) {
|
||||
await db.delete(sessions).where(eq(sessions.id, sessionId));
|
||||
return null;
|
||||
}
|
||||
|
||||
return { session, user };
|
||||
}
|
||||
|
||||
export async function invalidateSession(sessionId: string) {
|
||||
await db.delete(sessions).where(eq(sessions.id, sessionId));
|
||||
export function setAuthCookie(cookies: AstroCookies, userId: string) {
|
||||
const token = createToken(userId);
|
||||
cookies.set("auth_token", token, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: import.meta.env.PROD,
|
||||
sameSite: "lax",
|
||||
maxAge: 60 * 60 * 24 * 30,
|
||||
});
|
||||
}
|
||||
|
||||
export function clearAuthCookie(cookies: AstroCookies) {
|
||||
cookies.delete("auth_token", { path: "/" });
|
||||
}
|
||||
|
||||
export async function getUserFromToken(token: string) {
|
||||
const payload = verifyToken(token);
|
||||
if (!payload) return null;
|
||||
|
||||
const user = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.id, payload.userId))
|
||||
.get();
|
||||
|
||||
return user ?? null;
|
||||
}
|
||||
|
||||
export async function hashPassword(password: string) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineMiddleware } from "astro/middleware";
|
||||
import { validateSession } from "./lib/auth";
|
||||
import { getUserFromToken } from "./lib/auth";
|
||||
import { validateApiToken } from "./lib/api-auth";
|
||||
|
||||
const PUBLIC_ROUTES = ["/", "/login", "/signup"];
|
||||
@@ -14,32 +14,20 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
||||
|
||||
if (result) {
|
||||
context.locals.user = result.user;
|
||||
context.locals.session = null;
|
||||
context.locals.scopes = result.scopes;
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
const sessionId = context.cookies.get("session_id")?.value;
|
||||
const token = context.cookies.get("auth_token")?.value;
|
||||
|
||||
if (sessionId) {
|
||||
const result = await validateSession(sessionId);
|
||||
|
||||
if (result) {
|
||||
context.locals.user = result.user;
|
||||
context.locals.session = result.session;
|
||||
context.locals.scopes = null;
|
||||
} else {
|
||||
context.locals.user = null;
|
||||
context.locals.session = null;
|
||||
context.locals.scopes = null;
|
||||
context.cookies.delete("session_id", { path: "/" });
|
||||
}
|
||||
if (token) {
|
||||
const user = await getUserFromToken(token);
|
||||
context.locals.user = user;
|
||||
} else {
|
||||
context.locals.user = null;
|
||||
context.locals.session = null;
|
||||
context.locals.scopes = null;
|
||||
}
|
||||
context.locals.scopes = null;
|
||||
|
||||
const isPublic =
|
||||
PUBLIC_ROUTES.includes(pathname) || pathname.startsWith("/api/");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { APIRoute } from "astro";
|
||||
import { db } from "../../../db";
|
||||
import { users } from "../../../db/schema";
|
||||
import { verifyPassword, createSession } from "../../../lib/auth";
|
||||
import { verifyPassword, setAuthCookie } from "../../../lib/auth";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
export const POST: APIRoute = async ({ request, cookies, redirect }) => {
|
||||
@@ -23,15 +23,7 @@ export const POST: APIRoute = async ({ request, cookies, redirect }) => {
|
||||
return redirect("/login?error=invalid_credentials");
|
||||
}
|
||||
|
||||
const { sessionId, expiresAt } = await createSession(user.id);
|
||||
|
||||
cookies.set("session_id", sessionId, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: import.meta.env.PROD,
|
||||
sameSite: "lax",
|
||||
expires: expiresAt,
|
||||
});
|
||||
setAuthCookie(cookies, user.id);
|
||||
|
||||
return redirect("/dashboard");
|
||||
};
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { invalidateSession } from '../../../lib/auth';
|
||||
import { clearAuthCookie } from '../../../lib/auth';
|
||||
|
||||
export const POST: APIRoute = async ({ cookies }) => {
|
||||
const sessionId = cookies.get('session_id')?.value;
|
||||
if (sessionId) {
|
||||
await invalidateSession(sessionId);
|
||||
cookies.delete('session_id', { path: '/' });
|
||||
}
|
||||
clearAuthCookie(cookies);
|
||||
return new Response(null, { status: 200 });
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { verifyAuthenticationResponse } from "@simplewebauthn/server";
|
||||
import { db } from "../../../../../db";
|
||||
import { users, passkeys, passkeyChallenges } from "../../../../../db/schema";
|
||||
import { eq, and, gt } from "drizzle-orm";
|
||||
import { createSession } from "../../../../../lib/auth";
|
||||
import { setAuthCookie } from "../../../../../lib/auth";
|
||||
|
||||
export const POST: APIRoute = async ({ request, cookies }) => {
|
||||
const body = await request.json();
|
||||
@@ -82,15 +82,7 @@ export const POST: APIRoute = async ({ request, cookies }) => {
|
||||
})
|
||||
.where(eq(passkeys.id, passkey.id));
|
||||
|
||||
const { sessionId, expiresAt } = await createSession(user.id);
|
||||
|
||||
cookies.set("session_id", sessionId, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: import.meta.env.PROD,
|
||||
sameSite: "lax",
|
||||
expires: expiresAt,
|
||||
});
|
||||
setAuthCookie(cookies, user.id);
|
||||
|
||||
await db
|
||||
.delete(passkeyChallenges)
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
members,
|
||||
siteSettings,
|
||||
} from "../../../db/schema";
|
||||
import { hashPassword, createSession } from "../../../lib/auth";
|
||||
import { hashPassword, setAuthCookie } from "../../../lib/auth";
|
||||
import { isValidEmail, MAX_LENGTHS } from "../../../lib/validation";
|
||||
import { eq, count, sql } from "drizzle-orm";
|
||||
import { nanoid } from "nanoid";
|
||||
@@ -86,15 +86,7 @@ export const POST: APIRoute = async ({ request, cookies, redirect }) => {
|
||||
role: "owner",
|
||||
});
|
||||
|
||||
const { sessionId, expiresAt } = await createSession(userId);
|
||||
|
||||
cookies.set("session_id", sessionId, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: import.meta.env.PROD,
|
||||
sameSite: "lax",
|
||||
expires: expiresAt,
|
||||
});
|
||||
setAuthCookie(cookies, userId);
|
||||
|
||||
return redirect("/dashboard");
|
||||
};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { APIRoute } from "astro";
|
||||
import { db } from "../../../db";
|
||||
import { users, sessions } from "../../../db/schema";
|
||||
import { users } from "../../../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { MAX_LENGTHS } from "../../../lib/validation";
|
||||
import { setAuthCookie } from "../../../lib/auth";
|
||||
|
||||
export const POST: APIRoute = async ({ request, locals, redirect, cookies }) => {
|
||||
const user = locals.user;
|
||||
@@ -98,31 +99,7 @@ export const POST: APIRoute = async ({ request, locals, redirect, cookies }) =>
|
||||
.where(eq(users.id, user.id))
|
||||
.run();
|
||||
|
||||
// Invalidate all sessions, then re-create one for the current user
|
||||
const currentSessionId = cookies.get("session_id")?.value;
|
||||
if (currentSessionId) {
|
||||
await db
|
||||
.delete(sessions)
|
||||
.where(
|
||||
eq(sessions.userId, user.id),
|
||||
)
|
||||
.run();
|
||||
|
||||
const { createSession } = await import("../../../lib/auth");
|
||||
const { sessionId, expiresAt } = await createSession(user.id);
|
||||
cookies.set("session_id", sessionId, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: import.meta.env.PROD,
|
||||
sameSite: "lax",
|
||||
expires: expiresAt,
|
||||
});
|
||||
} else {
|
||||
await db
|
||||
.delete(sessions)
|
||||
.where(eq(sessions.userId, user.id))
|
||||
.run();
|
||||
}
|
||||
setAuthCookie(cookies, user.id);
|
||||
|
||||
if (isJson) {
|
||||
return new Response(JSON.stringify({ success: true }), { status: 200 });
|
||||
|
||||
Reference in New Issue
Block a user