From 7ff87d86729ec688613b06ad3c31a0aaa57aca1b Mon Sep 17 00:00:00 2001 From: tgt Date: Sat, 18 May 2024 12:06:54 -0400 Subject: [PATCH] Auth.js v5, change theming, and other changes --- .env.example | 4 +- drizzle.config.ts | 11 +- next.config.mjs | 7 +- package.json | 8 +- pnpm-lock.yaml | 349 +++--------------- server.ts | 18 +- src/app/(main)/admin/layout.tsx | 4 +- src/app/(main)/admin/page.tsx | 10 +- src/app/(main)/layout.tsx | 4 +- src/app/(main)/page.tsx | 37 +- src/app/api/auth/[...nextauth]/route.ts | 7 +- src/app/api/session/[slug]/files/route.ts | 8 +- src/app/api/session/[slug]/keepalive/route.ts | 4 +- src/app/api/session/[slug]/preview/route.ts | 8 +- src/app/api/session/[slug]/route.ts | 4 +- src/app/auth/error/page.tsx | 16 +- src/app/auth/login/page.tsx | 46 ++- src/app/auth/logout/page.tsx | 42 +-- src/app/auth/verify/page.tsx | 4 +- src/app/globals.css | 128 +++---- src/app/layout.tsx | 12 +- src/app/providers.tsx | 5 - src/lib/auth.config.ts | 18 + src/lib/auth.ts | 26 +- src/lib/drizzle/0000_gray_johnny_storm.sql | 35 -- src/lib/drizzle/meta/0000_snapshot.json | 165 --------- src/lib/drizzle/meta/_journal.json | 13 - src/lib/drizzle/seed.ts | 12 +- src/lib/migrate.ts | 6 - src/lib/session/get-session.ts | 6 +- src/lib/session/index.ts | 20 +- src/middleware.ts | 28 +- 32 files changed, 280 insertions(+), 785 deletions(-) delete mode 100644 src/app/providers.tsx create mode 100644 src/lib/auth.config.ts delete mode 100644 src/lib/drizzle/0000_gray_johnny_storm.sql delete mode 100644 src/lib/drizzle/meta/0000_snapshot.json delete mode 100644 src/lib/drizzle/meta/_journal.json delete mode 100644 src/lib/migrate.ts diff --git a/.env.example b/.env.example index ec44fff..3e8aebf 100644 --- a/.env.example +++ b/.env.example @@ -10,10 +10,8 @@ DOCKER_PORT= DOCKER_PORT_RANGE=5000-6000 # Hostname for the container host (where the containers will be run) CONTAINER_HOST= -# Public URL for the app -NEXTAUTH_URL= # NextAuth secret, can be anything random -NEXTAUTH_SECRET= +AUTH_SECRET= # Auth0 credentials AUTH0_ID= AUTH0_SECRET= diff --git a/drizzle.config.ts b/drizzle.config.ts index 637c02b..853e3ea 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,14 +1,13 @@ import "dotenv/config"; -import type { Config } from "drizzle-kit"; +import { defineConfig } from "drizzle-kit"; -const config: Config = { - driver: "pg", +export default defineConfig({ + dialect: "postgresql", out: "./src/lib/drizzle", schema: "./src/lib/drizzle/schema.ts", dbCredentials: { - connectionString: process.env.DATABASE_URL as string, + url: process.env.DATABASE_URL as string, }, verbose: true, strict: true, -}; -export default config; +}); diff --git a/next.config.mjs b/next.config.mjs index 86211b5..bd868cd 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -35,11 +35,16 @@ const nextConfig = { }, ]; }, - webpack(config) { + webpack(config, { webpack }) { config.module.rules.push({ test: /\.node$/, loader: "node-loader", }); + config.plugins.push( + new webpack.IgnorePlugin({ + resourceRegExp: /^pg-native$|^cloudflare:sockets$/, + }), + ); return config; }, }; diff --git a/package.json b/package.json index a78964d..07d0a31 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "biome lint --apply .", "format": "biome format --write .", "drizzle-kit": "drizzle-kit", - "db:push": "drizzle-kit push:pg" + "db:push": "drizzle-kit push" }, "dependencies": { "@next/bundle-analyzer": "^14.2.3", @@ -44,11 +44,9 @@ "drizzle-orm": "^0.30.4", "lucide-react": "^0.358.0", "next": "14.2.3", - "next-auth": "4.24.7", + "next-auth": "5.0.0-beta.18", "next-themes": "^0.3.0", "node-loader": "^2.0.0", - "pg": "^8.11.3", - "pg-native": "^3.0.1", "postgres": "^3.4.4", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -69,7 +67,7 @@ "@types/react": "^18.2.67", "@types/react-dom": "^18.2.22", "autoprefixer": "^10.4.19", - "drizzle-kit": "^0.20.17", + "drizzle-kit": "^0.21.1", "postcss": "^8.4.38", "tailwindcss": "^3.4.1", "tailwindcss-dotted-background": "^1.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e83372..08df685 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -91,7 +91,7 @@ dependencies: version: 16.4.5 drizzle-orm: specifier: ^0.30.4 - version: 0.30.4(@types/pg@8.11.4)(@types/react@18.2.67)(pg@8.11.3)(postgres@3.4.4)(react@18.2.0) + version: 0.30.4(@types/pg@8.11.4)(@types/react@18.2.67)(postgres@3.4.4)(react@18.2.0) lucide-react: specifier: ^0.358.0 version: 0.358.0(react@18.2.0) @@ -99,20 +99,14 @@ dependencies: specifier: 14.2.3 version: 14.2.3(react-dom@18.2.0)(react@18.2.0) next-auth: - specifier: 4.24.7 - version: 4.24.7(next@14.2.3)(react-dom@18.2.0)(react@18.2.0) + specifier: 5.0.0-beta.18 + version: 5.0.0-beta.18(next@14.2.3)(react@18.2.0) next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.2.0)(react@18.2.0) node-loader: specifier: ^2.0.0 version: 2.0.0(webpack@5.91.0) - pg: - specifier: ^8.11.3 - version: 8.11.3(pg-native@3.0.1) - pg-native: - specifier: ^3.0.1 - version: 3.0.1 postgres: specifier: ^3.4.4 version: 3.4.4 @@ -170,8 +164,8 @@ devDependencies: specifier: ^10.4.19 version: 10.4.19(postcss@8.4.38) drizzle-kit: - specifier: ^0.20.17 - version: 0.20.17 + specifier: ^0.21.1 + version: 0.21.1 postcss: specifier: ^8.4.38 version: 8.4.38 @@ -191,6 +185,29 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} + /@auth/core@0.31.0: + resolution: {integrity: sha512-UKk3psvA1cRbk4/c9CkpWB8mdWrkKvzw0DmEYRsWolUQytQ2cRqx+hYuV6ZCsngw/xbj9hpmkZmAZEyq2g4fMg==} + peerDependencies: + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + nodemailer: ^6.8.0 + peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true + nodemailer: + optional: true + dependencies: + '@panva/hkdf': 1.1.1 + '@types/cookie': 0.6.0 + cookie: 0.6.0 + jose: 5.3.0 + oauth4webapi: 2.10.4 + preact: 10.11.3 + preact-render-to-string: 5.2.3(preact@10.11.3) + dev: false + /@babel/runtime@7.24.1: resolution: {integrity: sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==} engines: {node: '>=6.9.0'} @@ -934,21 +951,6 @@ packages: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} dev: false - /@hono/node-server@1.11.0: - resolution: {integrity: sha512-TLIJq9TMtD1NEG1mVoqNUn1Ita0qSaB5XboZErjFBcO/GJYXwWY4dVdTi9G0lbxtu0x+hJXDItcLaFHb7rlFTw==} - engines: {node: '>=18.14.1'} - dev: true - - /@hono/zod-validator@0.2.1(hono@4.2.9)(zod@3.22.4): - resolution: {integrity: sha512-HFoxln7Q6JsE64qz2WBS28SD33UB2alp3aRKmcWnNLDzEL1BLsWfbdX6e1HIiUprHYTIXf5y7ax8eYidKUwyaA==} - peerDependencies: - hono: '>=3.9.0' - zod: ^3.19.1 - dependencies: - hono: 4.2.9 - zod: 3.22.4 - dev: true - /@img/sharp-darwin-arm64@0.33.3: resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} @@ -2332,6 +2334,10 @@ packages: engines: {node: '>=12'} dev: false + /@types/cookie@0.6.0: + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + dev: false + /@types/docker-modem@3.0.6: resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==} dependencies: @@ -2657,12 +2663,6 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - /bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - dependencies: - file-uri-to-path: 1.0.0 - dev: false - /bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} dependencies: @@ -2695,11 +2695,6 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - /buffer-writer@2.0.0: - resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==} - engines: {node: '>=4'} - dev: false - /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -2725,11 +2720,6 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - /camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} - dev: true - /caniuse-lite@1.0.30001600: resolution: {integrity: sha512-+2S9/2JFhYmYaDpZvo0lKkfvuKIglrx68MwOBqMGHhQsNkLjB5xtc/TGoEPs+MxjSyN/72qer2g97nzR641mOQ==} @@ -2737,11 +2727,6 @@ packages: resolution: {integrity: sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==} dev: false - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -2846,22 +2831,11 @@ packages: engines: {node: ^14.18.0 || >=16.10.0} dev: false - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + /cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} dev: false - /copy-anything@3.0.5: - resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} - engines: {node: '>=12.13'} - dependencies: - is-what: 4.1.16 - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: false - /cpu-features@0.0.9: resolution: {integrity: sha512-AKjgn2rP2yJyfbepsmLfiYcmtNn/2eUvocUyM/09yB0YDiz39HteK/5/T4Onf0pmdYDMgkBoGvRLvEguzyL7wQ==} engines: {node: '>=10.0.0'} @@ -2968,32 +2942,24 @@ packages: wordwrap: 1.0.0 dev: true - /drizzle-kit@0.20.17: - resolution: {integrity: sha512-mLVDS4nXmO09wFVlzGrdshWnAL+U9eQGC5zRs6hTN6Q9arwQGWU2XnZ17I8BM8Quau8CQRx3Ms6VPgRWJFVp7Q==} + /drizzle-kit@0.21.1: + resolution: {integrity: sha512-Sp7OnCdROiE2ebMuHsAfrnRoHVGYCvErQxUh7/0l6R1caHssZu9oZu/hW9rLU19xnTK4/y3iSe3sL0Cc530wCg==} hasBin: true dependencies: '@esbuild-kit/esm-loader': 2.6.5 - '@hono/node-server': 1.11.0 - '@hono/zod-validator': 0.2.1(hono@4.2.9)(zod@3.22.4) - camelcase: 7.0.1 - chalk: 5.3.0 commander: 9.5.0 env-paths: 3.0.0 esbuild: 0.19.12 esbuild-register: 3.5.0(esbuild@0.19.12) glob: 8.1.0 hanji: 0.0.5 - hono: 4.2.9 json-diff: 0.9.0 - minimatch: 7.4.6 - semver: 7.6.0 - superjson: 2.2.1 zod: 3.22.4 transitivePeerDependencies: - supports-color dev: true - /drizzle-orm@0.30.4(@types/pg@8.11.4)(@types/react@18.2.67)(pg@8.11.3)(postgres@3.4.4)(react@18.2.0): + /drizzle-orm@0.30.4(@types/pg@8.11.4)(@types/react@18.2.67)(postgres@3.4.4)(react@18.2.0): resolution: {integrity: sha512-kWoSMGbrOFkmkAweLTFtHJMpN+nwhx89q0mLELqT2aEU+1szNV8jrnBmJwZ0WGNp7J7yQn/ezEtxBI/qzTSElQ==} peerDependencies: '@aws-sdk/client-rds-data': '>=3' @@ -3072,7 +3038,6 @@ packages: dependencies: '@types/pg': 8.11.4 '@types/react': 18.2.67 - pg: 8.11.3(pg-native@3.0.1) postgres: 3.4.4 react: 18.2.0 dev: false @@ -3344,10 +3309,6 @@ packages: dependencies: reusify: 1.0.4 - /file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - dev: false - /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -3464,11 +3425,6 @@ packages: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} dev: true - /hono@4.2.9: - resolution: {integrity: sha512-59FAv52UxDWUt/NlC0NzrRCjeVCThUnVlqlrKYm+k80XujBu6uJwBIa5gACKKZWobjA0MJ6Vds0I3URKf383Cw==} - engines: {node: '>=16.0.0'} - dev: true - /html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: false @@ -3536,15 +3492,6 @@ packages: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} dev: true - /is-what@4.1.16: - resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} - engines: {node: '>=12.13'} - dev: true - - /isarray@0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - dev: false - /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -3569,8 +3516,8 @@ packages: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true - /jose@4.15.5: - resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + /jose@5.3.0: + resolution: {integrity: sha512-IChe9AtAE79ru084ow8jzkN2lNrG3Ntfiv65Cvj9uOCE2m5LNsdHG+9EbxWxAoWRF9TgDOqLN5jm08++owDVRg==} dev: false /js-tokens@4.0.0: @@ -3600,14 +3547,6 @@ packages: hasBin: true dev: false - /libpq@1.8.12: - resolution: {integrity: sha512-4lUY9BD9suz76mVS0kH4rRgRy620g/c9YZH5GYC3smfIpjtj6KiPuQ4IwQSHSZMMMhMM3tBFrYUrw8mHOOZVeg==} - requiresBuild: true - dependencies: - bindings: 1.5.0 - nan: 2.19.0 - dev: false - /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3653,6 +3592,7 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 + dev: false /lru-queue@0.1.0: resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} @@ -3715,13 +3655,6 @@ packages: brace-expansion: 2.0.1 dev: true - /minimatch@7.4.6: - resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -3755,6 +3688,7 @@ packages: resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==} requiresBuild: true dev: false + optional: true /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} @@ -3765,29 +3699,25 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: false - /next-auth@4.24.7(next@14.2.3)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-iChjE8ov/1K/z98gdKbn2Jw+2vLgJtVV39X+rCP5SGnVQuco7QOr19FRNGMIrD8d3LYhHWV9j9sKLzq1aDWWQQ==} + /next-auth@5.0.0-beta.18(next@14.2.3)(react@18.2.0): + resolution: {integrity: sha512-x55L8wZb8PcPGCYA3e/l9tdpd7YL3FDuhas4W8pxq3PjrWJ9OoDxNN0otK9axJamJBbBgjfzTJjVQB6hXoe0ZQ==} peerDependencies: - next: ^12.2.5 || ^13 || ^14 + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + next: ^14 nodemailer: ^6.6.5 - react: ^17.0.2 || ^18 - react-dom: ^17.0.2 || ^18 + react: ^18.2.0 peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true nodemailer: optional: true dependencies: - '@babel/runtime': 7.24.1 - '@panva/hkdf': 1.1.1 - cookie: 0.5.0 - jose: 4.15.5 + '@auth/core': 0.31.0 next: 14.2.3(react-dom@18.2.0)(react@18.2.0) - oauth: 0.9.15 - openid-client: 5.6.5 - preact: 10.20.0 - preact-render-to-string: 5.2.6(preact@10.20.0) react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - uuid: 8.3.2 dev: false /next-themes@0.3.0(react-dom@18.2.0)(react@18.2.0): @@ -3868,19 +3798,14 @@ packages: engines: {node: '>=0.10.0'} dev: true - /oauth@0.9.15: - resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + /oauth4webapi@2.10.4: + resolution: {integrity: sha512-DSoj8QoChzOCQlJkRmYxAJCIpnXFW32R0Uq7avyghIeB6iJq0XAblOD7pcq3mx4WEBDwMuKr0Y1qveCBleG2Xw==} dev: false /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-hash@2.2.0: - resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} - engines: {node: '>= 6'} - dev: false - /object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -3888,11 +3813,6 @@ packages: /obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - /oidc-token-hash@5.0.3: - resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} - engines: {node: ^10.13.0 || >=12.0.0} - dev: false - /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -3903,19 +3823,6 @@ packages: hasBin: true dev: false - /openid-client@5.6.5: - resolution: {integrity: sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w==} - dependencies: - jose: 4.15.5 - lru-cache: 6.0.0 - object-hash: 2.2.0 - oidc-token-hash: 5.0.3 - dev: false - - /packet-reader@1.0.0: - resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} - dev: false - /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3930,64 +3837,17 @@ packages: lru-cache: 10.2.0 minipass: 7.0.4 - /pg-cloudflare@1.1.1: - resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} - requiresBuild: true - dev: false - optional: true - - /pg-connection-string@2.6.2: - resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==} - dev: false - /pg-int8@1.0.1: resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} engines: {node: '>=4.0.0'} - /pg-native@3.0.1: - resolution: {integrity: sha512-LBVNWkNh0fVx/cienARRP2y22J5OpUsKBe0TpxzAx3arEUUdIs77aLSAHS3scS7SMaqc+OkG40CEu5fN0/cjIw==} - dependencies: - libpq: 1.8.12 - pg-types: 1.13.0 - readable-stream: 1.0.31 - dev: false - /pg-numeric@1.0.2: resolution: {integrity: sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==} engines: {node: '>=4'} - /pg-pool@3.6.1(pg@8.11.3): - resolution: {integrity: sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==} - peerDependencies: - pg: '>=8.0' - dependencies: - pg: 8.11.3(pg-native@3.0.1) - dev: false - /pg-protocol@1.6.0: resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} - /pg-types@1.13.0: - resolution: {integrity: sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==} - dependencies: - pg-int8: 1.0.1 - postgres-array: 1.0.3 - postgres-bytea: 1.0.0 - postgres-date: 1.0.7 - postgres-interval: 1.2.0 - dev: false - - /pg-types@2.2.0: - resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} - engines: {node: '>=4'} - dependencies: - pg-int8: 1.0.1 - postgres-array: 2.0.0 - postgres-bytea: 1.0.0 - postgres-date: 1.0.7 - postgres-interval: 1.2.0 - dev: false - /pg-types@4.0.2: resolution: {integrity: sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==} engines: {node: '>=10'} @@ -4000,33 +3860,6 @@ packages: postgres-interval: 3.0.0 postgres-range: 1.1.4 - /pg@8.11.3(pg-native@3.0.1): - resolution: {integrity: sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==} - engines: {node: '>= 8.0.0'} - peerDependencies: - pg-native: '>=3.0.1' - peerDependenciesMeta: - pg-native: - optional: true - dependencies: - buffer-writer: 2.0.0 - packet-reader: 1.0.0 - pg-connection-string: 2.6.2 - pg-native: 3.0.1 - pg-pool: 3.6.1(pg@8.11.3) - pg-protocol: 1.6.0 - pg-types: 2.2.0 - pgpass: 1.0.5 - optionalDependencies: - pg-cloudflare: 1.1.1 - dev: false - - /pgpass@1.0.5: - resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} - dependencies: - split2: 4.2.0 - dev: false - /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -4114,47 +3947,20 @@ packages: picocolors: 1.0.0 source-map-js: 1.2.0 - /postgres-array@1.0.3: - resolution: {integrity: sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==} - engines: {node: '>=0.10.0'} - dev: false - - /postgres-array@2.0.0: - resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} - engines: {node: '>=4'} - dev: false - /postgres-array@3.0.2: resolution: {integrity: sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==} engines: {node: '>=12'} - /postgres-bytea@1.0.0: - resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} - engines: {node: '>=0.10.0'} - dev: false - /postgres-bytea@3.0.0: resolution: {integrity: sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==} engines: {node: '>= 6'} dependencies: obuf: 1.1.2 - /postgres-date@1.0.7: - resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} - engines: {node: '>=0.10.0'} - dev: false - /postgres-date@2.1.0: resolution: {integrity: sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==} engines: {node: '>=12'} - /postgres-interval@1.2.0: - resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} - engines: {node: '>=0.10.0'} - dependencies: - xtend: 4.0.2 - dev: false - /postgres-interval@3.0.0: resolution: {integrity: sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==} engines: {node: '>=12'} @@ -4167,17 +3973,17 @@ packages: engines: {node: '>=12'} dev: false - /preact-render-to-string@5.2.6(preact@10.20.0): - resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} + /preact-render-to-string@5.2.3(preact@10.11.3): + resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} peerDependencies: preact: '>=10' dependencies: - preact: 10.20.0 + preact: 10.11.3 pretty-format: 3.8.0 dev: false - /preact@10.20.0: - resolution: {integrity: sha512-wU7iZw2BjsaKDal3pDRDy/HpPB6cuFOnVUCcw9aIPKG98+ZrXx3F+szkos8BVME5bquyKDKvRlOJFG8kMkcAbg==} + /preact@10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} dev: false /pretty-format@3.8.0: @@ -4279,15 +4085,6 @@ packages: dependencies: pify: 2.3.0 - /readable-stream@1.0.31: - resolution: {integrity: sha512-tco/Dwv1f/sgIgN6CWdj/restacPKNskK6yps1981ivH2ZmLYcs5o5rVzL3qaO/cSkhN8hYOMWs7+glzOLSgRg==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - dev: false - /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -4356,6 +4153,7 @@ packages: hasBin: true dependencies: lru-cache: 6.0.0 + dev: false /serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -4459,11 +4257,6 @@ packages: resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==} dev: false - /split2@4.2.0: - resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} - engines: {node: '>= 10.x'} - dev: false - /ssh2@1.15.0: resolution: {integrity: sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==} engines: {node: '>=10.16.0'} @@ -4497,10 +4290,6 @@ packages: emoji-regex: 9.2.2 strip-ansi: 7.1.0 - /string_decoder@0.10.31: - resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} - dev: false - /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: @@ -4549,13 +4338,6 @@ packages: pirates: 4.0.6 ts-interface-checker: 0.1.13 - /superjson@2.2.1: - resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} - engines: {node: '>=16'} - dependencies: - copy-anything: 3.0.5 - dev: true - /supports-color@8.1.1: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} @@ -4812,11 +4594,6 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: false - /watchpack@2.4.1: resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} engines: {node: '>=10.13.0'} @@ -4949,13 +4726,9 @@ packages: optional: true dev: false - /xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - dev: false - /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false /yaml@2.4.1: resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} diff --git a/server.ts b/server.ts index d791635..6412119 100644 --- a/server.ts +++ b/server.ts @@ -2,10 +2,10 @@ import "dotenv/config"; import { createServer } from "node:http"; import { Socket } from "node:net"; -import { getSession as getContainerSession } from "@/lib/session/get-session"; +import { db, session } from "@/lib/drizzle/db"; import { consola } from "consola"; +import { eq } from "drizzle-orm"; import next from "next"; -import { getSession } from "next-auth/react"; import { WebSocketServer } from "ws"; const port = Number.parseInt(process.env.PORT as string) || 3000; const dev = process.env.NODE_ENV !== "production"; @@ -13,24 +13,19 @@ if (process.argv.includes("--turbo")) { process.env.TURBOPACK = "1"; } const server = createServer(); -const app = next({ dev, port, httpServer: server }); +const app = next({ dev, port, httpServer: server, hostname: process.env.HOSTNAME }); consola.start(`✨ Stardust: Starting ${dev ? "development" : "production"} server...`); await app.prepare(); const nextRequest = app.getRequestHandler(); const nextUpgrade = app.getUpgradeHandler(); const websockify = new WebSocketServer({ noServer: true }); websockify.on("connection", async (ws, req) => { - const userSession = await getSession({ req }); - if (!userSession) { - ws.close(1008, "Unauthorized"); - return; - } const id = req.url?.split("/")[2]; if (!id) { ws.close(1008, "Missing ID"); return; } - const { vncPort } = (await getContainerSession(id, userSession)) || {}; + const [{ vncPort }] = await db.select({ vncPort: session.vncPort }).from(session).where(eq(session.id, id)).limit(1); if (!vncPort) { ws.close(1008, "Session not found"); return; @@ -60,7 +55,10 @@ websockify.on("connection", async (ws, req) => { ws.close(); }); }); -server.on("request", nextRequest); +server.on("request", (req, res) => { + process.env.HOST = req.headers.host; + nextRequest(req, res); +}); server.on("upgrade", async (req, socket, head) => { if (req.url?.includes("websockify")) { websockify.handleUpgrade(req, socket, head, (ws) => { diff --git a/src/app/(main)/admin/layout.tsx b/src/app/(main)/admin/layout.tsx index cdbbb98..e7707b1 100644 --- a/src/app/(main)/admin/layout.tsx +++ b/src/app/(main)/admin/layout.tsx @@ -1,11 +1,11 @@ -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import { db, user } from "@/lib/drizzle/db"; import { eq } from "drizzle-orm"; import { redirect } from "next/navigation"; import { AdminSidebar } from "@/components/sidebar"; export default async function AdminLayout({ children }: { children: React.ReactNode }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const [{ isAdmin }] = await db .select({ isAdmin: user.isAdmin }) .from(user) diff --git a/src/app/(main)/admin/page.tsx b/src/app/(main)/admin/page.tsx index a3ad9de..bd8684b 100644 --- a/src/app/(main)/admin/page.tsx +++ b/src/app/(main)/admin/page.tsx @@ -1,10 +1,10 @@ -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; -import { getAuthSession } from "@/lib/auth"; -import { db, image, session, user } from "@/lib/drizzle/db"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { auth } from "@/lib/auth"; +import { db, user } from "@/lib/drizzle/db"; import { Container, Users } from "lucide-react"; export default async function AdminPage() { - const userSession = await getAuthSession(); + const userSession = await auth(); const { users, sessions } = await db.transaction(async (tx) => { const users = await tx.select().from(user); const sessions = await tx.query.session.findMany({ @@ -15,7 +15,7 @@ export default async function AdminPage() { const activeUsers = sessions.map((s) => s.user); return (
-

Welcome, {userSession.user?.name}

+

Welcome, {userSession?.user?.name}

diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index fb713e8..c33a310 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -1,9 +1,9 @@ import Navigation from "@/components/navbar"; -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import { db, user as userSchema } from "@/lib/drizzle/db"; import { eq } from "drizzle-orm"; export default async function DashboardLayout({ children }: { children: React.ReactNode }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const [dbUser] = await db .select() .from(userSchema) diff --git a/src/app/(main)/page.tsx b/src/app/(main)/page.tsx index 013496e..532c5be 100644 --- a/src/app/(main)/page.tsx +++ b/src/app/(main)/page.tsx @@ -12,12 +12,11 @@ import { import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { CreateSessionButton } from "@/components/create-session-button"; -import { SessionDate } from "./session-date"; import { SkeletionImage } from "@/components/skeleton-image"; import { AspectRatio } from "@/components/ui/aspect-ratio"; import { Button } from "@/components/ui/button"; import { Card, CardTitle } from "@/components/ui/card"; -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import docker from "@/lib/docker"; import { type SelectSession, db, image, user } from "@/lib/drizzle/db"; import { deleteSession, manageSession } from "@/lib/session"; @@ -28,9 +27,8 @@ import Image from "next/image"; import Link from "next/link"; import { redirect } from "next/navigation"; import { Suspense } from "react"; -const errorCatcher = (error: string) => { - throw new Error(error); -}; +import { SessionDate } from "./session-date"; + const ManageSessionButton = ({ session, action, @@ -45,7 +43,8 @@ const ManageSessionButton = ({
{ "use server"; - await manageSession(session.id, action).catch(errorCatcher); + await manageSession(session.id, action); + if (redirectToView) redirect(`/view/${session.id}`); }} > @@ -55,24 +54,23 @@ const ManageSessionButton = ({
); export default async function Dashboard() { - const userSession = await getAuthSession(); + const userSession = await auth(); const { sessions, images } = await db.transaction(async (tx) => { const [{ userId }] = await tx .select({ userId: user.id, }) .from(user) - .where(eq(user.email, userSession?.user?.email as string)) - .catch(errorCatcher); - const images = await db.select().from(image).catch(errorCatcher); - const sessions = await tx.query.session - .findMany({ - with: { - image: true, - }, - where: (users, { eq }) => eq(users.userId, userId), - }) - .catch(errorCatcher); + .where(eq(user.email, userSession?.user?.email as string)); + + const images = await db.select().from(image); + const sessions = await tx.query.session.findMany({ + with: { + image: true, + }, + where: (users, { eq }) => eq(users.userId, userId), + }); + return { sessions, images }; }); return ( @@ -160,6 +158,7 @@ export default async function Dashboard() { {!State.Paused && State.Running ? ( { "use server"; - await deleteSession(session.id).catch(errorCatcher); + await deleteSession(session.id); }} > diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index faa8b92..73228a0 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -1,5 +1,2 @@ -import { authConfig } from "@/lib/auth"; -import NextAuth from "next-auth"; - -const handler = NextAuth(authConfig); -export { handler as GET, handler as POST }; +import { handlers } from "@/lib/auth"; +export const { GET, POST } = handlers; diff --git a/src/app/api/session/[slug]/files/route.ts b/src/app/api/session/[slug]/files/route.ts index 3e2c72e..5ccf21e 100644 --- a/src/app/api/session/[slug]/files/route.ts +++ b/src/app/api/session/[slug]/files/route.ts @@ -1,10 +1,10 @@ -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import { getSession } from "@/lib/session/get-session"; import { sessionRunning } from "@/lib/session/session-running"; import type { NextRequest } from "next/server"; export async function GET(req: NextRequest, { params }: { params: { slug: string } }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const fileName = req.nextUrl.searchParams.get("name"); const { id, agentPort } = (await getSession(params.slug, userSession)) || {}; if (!id || !agentPort) { @@ -25,10 +25,10 @@ export async function GET(req: NextRequest, { params }: { params: { slug: string return Response.json({ error: "Download failed" }, { status: 500 }); } } - return await fetch(`http://${process.env.CONTAINER_HOST}:${agentPort}/files/list`); + return fetch(`http://${process.env.CONTAINER_HOST}:${agentPort}/files/list`); } export async function PUT(req: NextRequest, { params }: { params: { slug: string } }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const buffer = await req.arrayBuffer(); const fileName = req.nextUrl.searchParams.get("name"); const { id, agentPort } = (await getSession(params.slug, userSession)) || {}; diff --git a/src/app/api/session/[slug]/keepalive/route.ts b/src/app/api/session/[slug]/keepalive/route.ts index 3ab388a..6951d1d 100644 --- a/src/app/api/session/[slug]/keepalive/route.ts +++ b/src/app/api/session/[slug]/keepalive/route.ts @@ -1,10 +1,10 @@ -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import { getSession } from "@/lib/session/get-session"; import type { NextRequest } from "next/server"; import { db, session } from "@/lib/drizzle/db"; import { eq } from "drizzle-orm"; export async function POST(_req: NextRequest, { params }: { params: { slug: string } }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const { id } = (await getSession(params.slug, userSession)) || {}; const date = new Date(); date.setDate(date.getDate() + 7); diff --git a/src/app/api/session/[slug]/preview/route.ts b/src/app/api/session/[slug]/preview/route.ts index 9a618ef..cb16d77 100644 --- a/src/app/api/session/[slug]/preview/route.ts +++ b/src/app/api/session/[slug]/preview/route.ts @@ -1,13 +1,13 @@ -import { getAuthSession } from "@/lib/auth"; -import type { NextRequest } from "next/server"; +import { auth } from "@/lib/auth"; import { getSession } from "@/lib/session/get-session"; import { sessionRunning } from "@/lib/session/session-running"; +import type { NextRequest } from "next/server"; export async function GET(_req: NextRequest, { params }: { params: { slug: string } }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const { agentPort } = (await getSession(params.slug, userSession)) || {}; if (!agentPort) { return Response.json({ error: "Not Found" }, { status: 404 }); } await sessionRunning(agentPort); - return await fetch(`http://${process.env.CONTAINER_HOST}:${agentPort}/screenshot`); + return fetch(`http://${process.env.CONTAINER_HOST}:${agentPort}/screenshot`); } diff --git a/src/app/api/session/[slug]/route.ts b/src/app/api/session/[slug]/route.ts index 2156131..aa378da 100644 --- a/src/app/api/session/[slug]/route.ts +++ b/src/app/api/session/[slug]/route.ts @@ -1,11 +1,11 @@ -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import docker from "@/lib/docker"; import { getSession } from "@/lib/session/get-session"; import { sessionRunning } from "@/lib/session/session-running"; import type { NextRequest } from "next/server"; export async function GET(_req: NextRequest, { params }: { params: { slug: string } }) { - const userSession = await getAuthSession(); + const userSession = await auth(); const containerSession = await getSession(params.slug, userSession); if (!containerSession) { return Response.json({ exists: false, error: "Container not found" }, { status: 404 }); diff --git a/src/app/auth/error/page.tsx b/src/app/auth/error/page.tsx index cec3d20..93041f4 100644 --- a/src/app/auth/error/page.tsx +++ b/src/app/auth/error/page.tsx @@ -1,23 +1,23 @@ -"use client"; - import { CardContent, CardHeader } from "@/components/ui/card"; import { ShieldX } from "lucide-react"; -import { useSearchParams } from "next/navigation"; -export default function AuthError() { - const searchParams = useSearchParams(); - const error = searchParams.get("error"); +export default function AuthError({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined }; +}) { + const { error } = searchParams; return ( <> There was an error logging in: - {error && ( + {error ? (
{error}
- )} + ) : null}

Please try again. If the problem persists, please contact support.

diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index 374f90b..5cd3bd5 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -1,21 +1,18 @@ -"use client"; - +import { StyledSubmit } from "@/components/submit-button"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; -import { Button } from "@/components/ui/button"; import { CardContent } from "@/components/ui/card"; -import { AlertCircle, Loader2, LogIn } from "lucide-react"; -import { signIn, useSession } from "next-auth/react"; -import { redirect, useSearchParams } from "next/navigation"; -import { useState } from "react"; +import { auth, signIn } from "@/lib/auth"; +import { AlertCircle, LogIn } from "lucide-react"; +import { redirect } from "next/navigation"; -export default function Login() { - const searchParams = useSearchParams(); - const [loading, setLoading] = useState(false); - const error = searchParams.get("error"); - const { data: session } = useSession(); - if (session) { - redirect("/"); - } +export default async function Login({ + searchParams, +}: { + searchParams: { [key: string]: string | string[] | undefined }; +}) { + const session = await auth(); + if (session) redirect("/"); + const { error } = searchParams; return ( {error ? ( @@ -26,17 +23,18 @@ export default function Login() { ) : null}
- + + + Log in with Auth0 + +
); diff --git a/src/app/auth/logout/page.tsx b/src/app/auth/logout/page.tsx index 8d74564..56f268d 100644 --- a/src/app/auth/logout/page.tsx +++ b/src/app/auth/logout/page.tsx @@ -1,40 +1,36 @@ -"use client"; - +import { StyledSubmit } from "@/components/submit-button"; import { Button } from "@/components/ui/button"; import { CardContent } from "@/components/ui/card"; -import { ChevronLeft, Loader2, LogOut } from "lucide-react"; -import { signOut } from "next-auth/react"; -import { useRouter } from "next/navigation"; -import { useState } from "react"; -import { toast } from "sonner"; +import { signOut } from "@/lib/auth"; +import { ChevronLeft, LogOut } from "lucide-react"; +import Link from "next/link"; +import { redirect } from "next/navigation"; export default function SignOut() { - const [loading, setLoading] = useState(false); - const router = useRouter(); return (

Are you sure you want to log out?

- + + + Log out + +
); diff --git a/src/app/auth/verify/page.tsx b/src/app/auth/verify/page.tsx index 439f9f8..5430456 100644 --- a/src/app/auth/verify/page.tsx +++ b/src/app/auth/verify/page.tsx @@ -1,10 +1,10 @@ import { CardContent, CardFooter, CardTitle } from "@/components/ui/card"; -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import { Mail } from "lucide-react"; import { redirect } from "next/navigation"; export default async function EmailVerify() { - const session = await getAuthSession(); + const session = await auth(); if (session) { redirect("/"); } diff --git a/src/app/globals.css b/src/app/globals.css index 4c6231f..18f1ee7 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,62 +4,68 @@ @layer base { :root { - --background: 0 0% 100%; - --foreground: 240 10% 3.9%; - - --card: 0 0% 100%; - --card-foreground: 240 10% 3.9%; - - --popover: 0 0% 100%; - --popover-foreground: 240 10% 3.9%; - - --primary: 240 5.9% 10%; - --primary-foreground: 0 0% 98%; - - --secondary: 240 4.8% 95.9%; - --secondary-foreground: 240 5.9% 10%; - - --muted: 240 4.8% 95.9%; - --muted-foreground: 240 3.8% 46.1%; - - --accent: 240 4.8% 95.9%; - --accent-foreground: 240 5.9% 10%; - - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - - --border: 240 5.9% 90%; - --input: 240 5.9% 90%; - --ring: 240 10% 3.9%; + --background: 220 23.077% 94.902%; + --foreground: 233.793 16.022% 35.490%; + --muted: 222.857 15.909% 82.745%; + --muted-foreground: 233.333 12.796% 41.373%; + --popover: 220 23.077% 94.902%; + --popover-foreground: 233.793 16.022% 35.490%; + --card: 220 23.077% 94.902%; + --card-foreground: 233.793 16.022% 35.490%; + --border: 225 13.559% 76.863%; + --input: 225 13.559% 76.863%; + --primary: 266.044 85.047% 58.039%; + --primary-foreground: 220 23.077% 94.902%; + --secondary: 222.857 15.909% 82.745%; + --secondary-foreground: 233.793 16.022% 35.490%; + --accent: 222.857 15.909% 82.745%; + --accent-foreground: 233.793 16.022% 35.490%; + --destructive: 347.077 86.667% 44.118%; + --destructive-foreground: 220 21.951% 91.961%; + --ring: 233.793 16.022% 35.490%; --radius: 0.5rem; } .dark { + --background: 240 21.053% 14.902%; + --foreground: 226.154 63.934% 88.039%; + --muted: 236.842 16.239% 22.941%; + --muted-foreground: 226.667 35.294% 80%; + --popover: 240 21.053% 14.902%; + --popover-foreground: 226.154 63.934% 88.039%; + --card: 240 21.053% 14.902%; + --card-foreground: 226.154 63.934% 88.039%; + --border: 234.286 13.208% 31.176%; + --input: 234.286 13.208% 31.176%; + --primary: 267.407 83.505% 80.98%; + --primary-foreground: 240 21.053% 14.902%; + --secondary: 236.842 16.239% 22.941%; + --secondary-foreground: 226.154 63.934% 88.039%; + --accent: 236.842 16.239% 22.941%; + --accent-foreground: 226.154 63.934% 88.039%; + --destructive: 343.269 81.25% 74.902%; + --destructive-foreground: 240 21.311% 11.961%; + --ring: 226.154 63.934% 88.039%; + } + + .zinc { --background: 240 10% 3.9%; --foreground: 0 0% 98%; - --card: 240 10% 3.9%; --card-foreground: 0 0% 98%; - --popover: 240 10% 3.9%; --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; --primary-foreground: 240 5.9% 10%; - --secondary: 240 3.7% 15.9%; --secondary-foreground: 0 0% 98%; - --muted: 240 3.7% 15.9%; --muted-foreground: 240 5% 64.9%; - --accent: 240 3.7% 15.9%; --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 0% 98%; - --border: 240 3.7% 15.9%; --input: 240 3.7% 15.9%; --ring: 240 4.9% 83.9%; @@ -86,56 +92,6 @@ --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9; } - - .mocha { - --background: 240 21.053% 14.902%; - /* base */ - --foreground: 226.154 63.934% 88.039%; - /* text */ - - --muted: 236.842 16.239% 22.941%; - /* surface0 */ - --muted-foreground: 226.667 35.294% 80%; - /* subtext1 */ - - --popover: 240 21.053% 14.902%; - /* base */ - --popover-foreground: 226.154 63.934% 88.039%; - /* text */ - - --card: 240 21.053% 14.902%; - /* base */ - --card-foreground: 226.154 63.934% 88.039%; - /* text */ - - --border: 234.286 13.208% 31.176%; - /* surface1 */ - --input: 234.286 13.208% 31.176%; - /* surface1 */ - - --primary: 267.407 83.505% 80.98%; - /* mauve */ - --primary-foreground: 240 21.053% 14.902%; - /* base */ - - --secondary: 236.842 16.239% 22.941%; - /* surface0 */ - --secondary-foreground: 226.154 63.934% 88.039%; - /* text */ - - --accent: 236.842 16.239% 22.941%; - /* surface0 */ - --accent-foreground: 226.154 63.934% 88.039%; - /* text */ - - --destructive: 343.269 81.25% 74.902%; - /* red */ - --destructive-foreground: 240 21.311% 11.961%; - /* mantle */ - - --ring: 226.154 63.934% 88.039%; - /* text */ - } } @layer base { @@ -146,4 +102,4 @@ body { @apply bg-background text-foreground; } -} \ No newline at end of file +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 83ab4da..76036af 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,10 +1,10 @@ import { Toaster } from "@/components/ui/sonner"; -import { getAuthSession } from "@/lib/auth"; +import { auth } from "@/lib/auth"; import type { Metadata } from "next"; import { ThemeProvider } from "next-themes"; import { Inter, JetBrains_Mono } from "next/font/google"; import "./globals.css"; -import { Session } from "./providers"; +import { SessionProvider } from "next-auth/react"; const inter = Inter({ subsets: ["latin"] }); const jetbrains = JetBrains_Mono({ subsets: ["latin"], variable: "--mono" }); @@ -18,7 +18,7 @@ export const metadata: Metadata = { title: "Stardust", description: "Stardust is the platform for streaming isolated desktop containers.", type: "website", - url: "https://stardust.spaceness.one", // probably going to be a personal website for stardust, + url: "https://stardust.spaceness.one", }, }; export default async function RootLayout({ @@ -29,18 +29,18 @@ export default async function RootLayout({ return ( - + {children} - + ); diff --git a/src/app/providers.tsx b/src/app/providers.tsx deleted file mode 100644 index 35b3530..0000000 --- a/src/app/providers.tsx +++ /dev/null @@ -1,5 +0,0 @@ -"use client"; - -import { SessionProvider, type SessionProviderProps } from "next-auth/react"; - -export const Session = ({ ...props }: SessionProviderProps) => ; diff --git a/src/lib/auth.config.ts b/src/lib/auth.config.ts new file mode 100644 index 0000000..11d4309 --- /dev/null +++ b/src/lib/auth.config.ts @@ -0,0 +1,18 @@ +import type { NextAuthConfig } from "next-auth"; +import Auth0 from "next-auth/providers/auth0"; + +export const config: NextAuthConfig = { + trustHost: true, + pages: { + signIn: "/auth/login", + signOut: "/auth/logout", + error: "/auth/error", + }, + providers: [ + Auth0({ + clientId: process.env.AUTH0_ID as string, + clientSecret: process.env.AUTH0_SECRET as string, + issuer: process.env.AUTH0_ISSUER, + }), + ], +}; diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 440eb67..a08f11e 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,15 +1,7 @@ import { db, user } from "@/lib/drizzle/db"; -import { getServerSession } from "next-auth"; -import type { NextAuthOptions, Session } from "next-auth"; -import Auth0 from "next-auth/providers/auth0"; - -const authConfig: NextAuthOptions = { - pages: { - signIn: "/auth/login", - verifyRequest: "/auth/verify", - signOut: "/auth/logout", - error: "/auth/error", - }, +import NextAuth from "next-auth"; +import { config } from "./auth.config"; +export const { auth, handlers, signIn, signOut } = NextAuth({ callbacks: { async signIn({ profile }) { const { email, name, sub: id } = profile || {}; @@ -19,13 +11,5 @@ const authConfig: NextAuthOptions = { return true; }, }, - providers: [ - Auth0({ - clientId: process.env.AUTH0_ID as string, - clientSecret: process.env.AUTH0_SECRET as string, - issuer: process.env.AUTH0_ISSUER, - }), - ], -}; -const getAuthSession = () => getServerSession(authConfig) as Promise; -export { authConfig, getAuthSession }; + ...config, +}); diff --git a/src/lib/drizzle/0000_gray_johnny_storm.sql b/src/lib/drizzle/0000_gray_johnny_storm.sql deleted file mode 100644 index 152156f..0000000 --- a/src/lib/drizzle/0000_gray_johnny_storm.sql +++ /dev/null @@ -1,35 +0,0 @@ -CREATE TABLE IF NOT EXISTS "Image" ( - "dockerImage" text PRIMARY KEY NOT NULL, - "friendlyName" text NOT NULL, - "category" text[], - "icon" text NOT NULL, - "pulled" boolean DEFAULT false, - "supportedArch" text[] -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "Session" ( - "id" text PRIMARY KEY NOT NULL, - "dockerImage" text NOT NULL, - "createdAt" integer NOT NULL, - "expiresAt" integer NOT NULL, - "userId" text NOT NULL, - "vncPort" integer NOT NULL -); ---> statement-breakpoint -CREATE TABLE IF NOT EXISTS "User" ( - "email" text NOT NULL, - "name" text, - "isAdmin" boolean DEFAULT false NOT NULL, - "id" text PRIMARY KEY NOT NULL -); ---> statement-breakpoint -ALTER TABLE "Session" ALTER COLUMN "createdAt" integer USING "createdAt"::integer; -ALTER TABLE "Session" ALTER COLUMN "expiresAt" integer USING "expiresAt"::integer; ---> statement-breakpoint -CREATE UNIQUE INDEX IF NOT EXISTS "Image_dockerImage_key" ON "Image" ("dockerImage");--> statement-breakpoint -CREATE UNIQUE INDEX IF NOT EXISTS "User_email_key" ON "User" ("email");--> statement-breakpoint -DO $$ BEGIN - ALTER TABLE "Session" ADD CONSTRAINT "Session_userId_User_id_fk" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE no action ON UPDATE no action; -EXCEPTION - WHEN duplicate_object THEN null; -END $$; diff --git a/src/lib/drizzle/meta/0000_snapshot.json b/src/lib/drizzle/meta/0000_snapshot.json deleted file mode 100644 index 417bd73..0000000 --- a/src/lib/drizzle/meta/0000_snapshot.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "id": "b0dcb1f4-7567-4a2d-a227-672679a3d39b", - "prevId": "00000000-0000-0000-0000-000000000000", - "version": "5", - "dialect": "pg", - "tables": { - "Image": { - "name": "Image", - "schema": "", - "columns": { - "dockerImage": { - "name": "dockerImage", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "friendlyName": { - "name": "friendlyName", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "category": { - "name": "category", - "type": "text[]", - "primaryKey": false, - "notNull": false - }, - "icon": { - "name": "icon", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "pulled": { - "name": "pulled", - "type": "boolean", - "primaryKey": false, - "notNull": false, - "default": false - }, - "supportedArch": { - "name": "supportedArch", - "type": "text[]", - "primaryKey": false, - "notNull": false - } - }, - "indexes": { - "Image_dockerImage_key": { - "name": "Image_dockerImage_key", - "columns": ["dockerImage"], - "isUnique": true - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "Session": { - "name": "Session", - "schema": "", - "columns": { - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - }, - "dockerImage": { - "name": "dockerImage", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "createdAt": { - "name": "createdAt", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "expiresAt": { - "name": "expiresAt", - "type": "integer", - "primaryKey": false, - "notNull": true - }, - "userId": { - "name": "userId", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "vncPort": { - "name": "vncPort", - "type": "integer", - "primaryKey": false, - "notNull": true - } - }, - "indexes": {}, - "foreignKeys": { - "Session_userId_User_id_fk": { - "name": "Session_userId_User_id_fk", - "tableFrom": "Session", - "tableTo": "User", - "columnsFrom": ["userId"], - "columnsTo": ["id"], - "onDelete": "no action", - "onUpdate": "no action" - } - }, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - }, - "User": { - "name": "User", - "schema": "", - "columns": { - "email": { - "name": "email", - "type": "text", - "primaryKey": false, - "notNull": true - }, - "name": { - "name": "name", - "type": "text", - "primaryKey": false, - "notNull": false - }, - "isAdmin": { - "name": "isAdmin", - "type": "boolean", - "primaryKey": false, - "notNull": true, - "default": false - }, - "id": { - "name": "id", - "type": "text", - "primaryKey": true, - "notNull": true - } - }, - "indexes": { - "User_email_key": { - "name": "User_email_key", - "columns": ["email"], - "isUnique": true - } - }, - "foreignKeys": {}, - "compositePrimaryKeys": {}, - "uniqueConstraints": {} - } - }, - "enums": {}, - "schemas": {}, - "_meta": { - "columns": {}, - "schemas": {}, - "tables": {} - } -} diff --git a/src/lib/drizzle/meta/_journal.json b/src/lib/drizzle/meta/_journal.json deleted file mode 100644 index e6e15f2..0000000 --- a/src/lib/drizzle/meta/_journal.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "5", - "dialect": "pg", - "entries": [ - { - "idx": 0, - "version": "5", - "when": 1712581919067, - "tag": "0000_gray_johnny_storm", - "breakpoints": true - } - ] -} diff --git a/src/lib/drizzle/seed.ts b/src/lib/drizzle/seed.ts index 6491526..12a7b40 100644 --- a/src/lib/drizzle/seed.ts +++ b/src/lib/drizzle/seed.ts @@ -1,14 +1,7 @@ import "dotenv/config"; -import { drizzle } from "drizzle-orm/node-postgres"; -import pg from "pg"; -import * as schema from "./schema"; -const { image } = schema; -const connection = new pg.Client({ - connectionString: process.env.DATABASE_URL as string, -}); -const db = drizzle(connection, { schema }); + +import { db, image } from "@/lib/drizzle/db"; (async () => { - await connection.connect(); const insertion = await db .insert(image) .values([ @@ -29,6 +22,5 @@ const db = drizzle(connection, { schema }); .returning(); console.log(insertion); console.log("✨ Stardust: Seeded image"); - connection.end(); process.exit(); })(); diff --git a/src/lib/migrate.ts b/src/lib/migrate.ts deleted file mode 100644 index 311f794..0000000 --- a/src/lib/migrate.ts +++ /dev/null @@ -1,6 +0,0 @@ -import "dotenv/config"; -import { migrate } from "drizzle-orm/postgres-js/migrator"; -import { client, db } from "./drizzle/db"; - -await migrate(db, { migrationsFolder: `${process.cwd()}/src/lib/drizzle` }); -await client.end(); diff --git a/src/lib/session/get-session.ts b/src/lib/session/get-session.ts index 075b773..82e9423 100644 --- a/src/lib/session/get-session.ts +++ b/src/lib/session/get-session.ts @@ -7,16 +7,16 @@ import type { Session } from "next-auth"; * @param userSession An Auth.js `Session` object * @returns The database query for the session, or `null` if it doesn't exist. */ -async function getSession(containerId: string, userSession: Session) { +async function getSession(containerId: string, userSession: Session | null) { const [containerSession] = await db.transaction(async (tx) => { - if (!userSession.user) throw new Error("User not found"); + if (!userSession?.user) throw new Error("User not found"); const [{ userId }] = await tx .select({ userId: user.id, }) .from(user) .where(eq(user.email, userSession.user.email as string)); - return await tx + return tx .select() .from(session) .where(and(eq(session.id, containerId), eq(session.userId, userId))); diff --git a/src/lib/session/index.ts b/src/lib/session/index.ts index 97dbd79..b7840ce 100644 --- a/src/lib/session/index.ts +++ b/src/lib/session/index.ts @@ -1,12 +1,12 @@ "use server"; import docker from "@/lib/docker"; import { db, session, user } from "@/lib/drizzle/db"; +import { consola } from "consola"; import type Dockerode from "dockerode"; import { eq } from "drizzle-orm"; -import { getSession } from "./get-session"; -import { getAuthSession } from "../auth"; import { revalidatePath } from "next/cache"; -import { consola } from "consola"; +import { auth } from "../auth"; +import { getSession } from "./get-session"; const getRandomNumber = (min: number, max: number) => Math.floor(Math.random() * (max - min + 1)) + min; const encodeEmailLocal = (email: string) => Array.from(email) @@ -19,8 +19,8 @@ const encodeEmailLocal = (email: string) => async function createSession(Image: string) { consola.info(`✨ Stardust: Creating session with image ${Image}`); try { - const userSession = await getAuthSession(); - if (!userSession.user) throw new Error("User not found"); + const userSession = await auth(); + if (!userSession?.user) throw new Error("User not found"); if (!process.env.DOCKER_PORT_RANGE) throw new Error("Docker port range not set"); const portsRange = process.env.DOCKER_PORT_RANGE.split("-").map(Number); let vncPort: number = getRandomNumber(portsRange[0], portsRange[1]); @@ -55,7 +55,7 @@ async function createSession(Image: string) { }); const date = new Date(); date.setDate(date.getDate() + 7); - return await db.transaction(async (tx) => { + return db.transaction(async (tx) => { return await tx .insert(session) .values({ @@ -87,12 +87,12 @@ async function createSession(Image: string) { * @param admin If this is triggered by an admin */ async function manageSession(containerId: string, action: keyof Dockerode.Container, admin?: boolean) { - const userSession = await getAuthSession(); + const userSession = await auth(); if (admin) { const [{ isAdmin }] = await db .select({ isAdmin: user.isAdmin }) .from(user) - .where(eq(user.email, userSession.user?.email as string)); + .where(eq(user.email, userSession?.user?.email as string)); if (isAdmin) { const container = docker.getContainer(containerId); await container[action](); @@ -116,12 +116,12 @@ async function manageSession(containerId: string, action: keyof Dockerode.Contai * @param admin If this is triggered by an admin */ async function deleteSession(containerId: string, admin?: boolean) { - const userSession = await getAuthSession(); + const userSession = await auth(); if (admin) { const [{ isAdmin }] = await db .select({ isAdmin: user.isAdmin }) .from(user) - .where(eq(user.email, userSession.user?.email as string)); + .where(eq(user.email, userSession?.user?.email as string)); if (isAdmin) { const container = docker.getContainer(containerId); await container.remove({ force: true }); diff --git a/src/middleware.ts b/src/middleware.ts index 1bac467..3f0b408 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,13 +1,21 @@ -import { withAuth } from "next-auth/middleware"; - -export default withAuth({ - pages: { - signIn: "/auth/login", - verifyRequest: "/auth/verify", - signOut: "/auth/logout", - error: "/auth/error", - }, +import { config as authConfig } from "@/lib/auth.config"; +import NextAuth from "next-auth"; +import { NextResponse } from "next/server"; +const { auth } = NextAuth(authConfig); +export const middleware = auth(async (req) => { + if ( + req.auth || + req.nextUrl.pathname.startsWith("/auth/login") || + req.nextUrl.pathname.startsWith("/auth/error") || + req.nextUrl.pathname.startsWith("/auth/verify") + ) { + return NextResponse.next(); + } + const url = new URL("/auth/login", req.url); + url.searchParams.set("callbackUrl", req.nextUrl.pathname); + console.log(url.toString()); + return NextResponse.redirect(url); }); export const config = { - matcher: ["/((?!_next/static|_next/image|icon.svg|websockify|auth/verify|manifest.webmanifest).*)"], + matcher: ["/((?!_next/static|_next/image|icon.svg|websockify|api/auth|manifest.webmanifest).*)"], };