diff --git a/README.md b/README.md index 8b961f0..0b96834 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,9 @@ npm install --workspace=metamigo-common ``` turbo run build --filter metamigo-cli -``` \ No newline at end of file + + +npm run dev -- --filter @digiresilience/metamigo-cli +npm run migrate + +``` diff --git a/apps/metamigo-cli/package.json b/apps/metamigo-cli/package.json index 2f3b047..fcbcef6 100644 --- a/apps/metamigo-cli/package.json +++ b/apps/metamigo-cli/package.json @@ -11,6 +11,7 @@ "dependencies": { "@digiresilience/montar": "*", "@digiresilience/metamigo-config": "*", + "@digiresilience/metamigo-common": "*", "@digiresilience/metamigo-db": "*", "@digiresilience/metamigo-api": "*", "@digiresilience/metamigo-worker": "*", @@ -32,7 +33,9 @@ "typescript": "^5.0.4" }, "scripts": { + "migrate": "NODE_ENV=development node --unhandled-rejections=strict build/main/index.js db -- migrate", "build": "tsc -p tsconfig.json", + "dev": "NODE_ENV=development node --unhandled-rejections=strict build/main/index.js api", "cli": "NODE_ENV=development node --unhandled-rejections=strict build/main/index.js", "fix:lint": "eslint src --ext .ts --fix", "fmt": "prettier \"src/**/*.ts\" --write", diff --git a/apps/metamigo-cli/src/config.ts b/apps/metamigo-cli/src/config.ts index 0627ab0..b09250a 100644 --- a/apps/metamigo-cli/src/config.ts +++ b/apps/metamigo-cli/src/config.ts @@ -6,7 +6,7 @@ import { IAppConfig, IAppConvict } from "@digiresilience/metamigo-config"; import { loadConfigRaw } from "@digiresilience/metamigo-config"; export const genConf = async (): Promise => { - const c = await loadConfigRaw() as any; + const c = (await loadConfigRaw()) as any; const generated = generateConfig(c) as any; console.log(generated); }; @@ -17,6 +17,6 @@ export const genSchema = async (): Promise => { }; export const listConfig = async (): Promise => { - const c = await loadConfigRaw() as any; + const c = (await loadConfigRaw()) as any; printConfigOptions(c); }; diff --git a/apps/metamigo-cli/src/metamigo-postgraphile.ts b/apps/metamigo-cli/src/metamigo-postgraphile.ts index 58948c5..78f12f4 100644 --- a/apps/metamigo-cli/src/metamigo-postgraphile.ts +++ b/apps/metamigo-cli/src/metamigo-postgraphile.ts @@ -11,7 +11,7 @@ import pg from "pg"; import { loadConfig } from "@digiresilience/metamigo-config"; import { getPostGraphileOptions } from "@digiresilience/metamigo-db"; -const {Pool} = pg; +const { Pool } = pg; export const exportGraphqlSchema = async (): Promise => { const config = await loadConfig(); diff --git a/apps/metamigo-frontend/.env.local b/apps/metamigo-frontend/.env.local deleted file mode 100644 index 1e634a5..0000000 --- a/apps/metamigo-frontend/.env.local +++ /dev/null @@ -1 +0,0 @@ -METAMIGO_CONFIG=.metamigo.local.json diff --git a/apps/metamigo-frontend/lib/nextauth-adapter.ts b/apps/metamigo-frontend/lib/nextauth-adapter.ts index 2a121f2..3a8d17a 100644 --- a/apps/metamigo-frontend/lib/nextauth-adapter.ts +++ b/apps/metamigo-frontend/lib/nextauth-adapter.ts @@ -1,8 +1,5 @@ /* eslint-disable unicorn/no-null */ -/* eslint-disable max-params */ -import type { Adapter } from "next-auth/adapters"; -// @ts-expect-error: Missing export -import type { AppOptions } from "next-auth"; +import type { Adapter, AdapterAccount, AdapterSession, AdapterUser } from "next-auth/adapters"; import * as Wreck from "@hapi/wreck"; import * as Boom from "@hapi/boom"; @@ -70,7 +67,7 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => { json: "force", }); - async function getAdapter(_appOptions: AppOptions) { + function getAdapter(): Adapter { async function createUser(profile: Profile) { try { if (!profile.createdBy) profile = { ...profile, createdBy: "nextauth" }; @@ -106,19 +103,17 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => { } } - async function getUserByProviderAccountId( - providerId: string, - providerAccountId: string - ) { + async function getUserByAccount({ providerAccountId, provider }: { providerAccountId: string, provider: string }) { try { const { payload } = await wreck.get( - `getUserByProviderAccountId/${providerId}/${providerAccountId}` + `getUserByAccount/${provider}/${providerAccountId}` ); return payload; } catch (error) { if (Boom.isBoom(error, 404)) return null; - throw new Error("GET_USER_BY_PROVIDER_ACCOUNT_ID"); + console.log(error) + throw new Error("GET_USER_BY_ACCOUNT"); } } @@ -135,51 +130,39 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => { } async function linkAccount( - userId: string, - providerId: string, - providerType: string, - providerAccountId: string, - refreshToken: string, - accessToken: string, - accessTokenExpires: number + account: AdapterAccount ) { try { - const payload = { - userId, - providerId, - providerType, - providerAccountId: `${providerAccountId}`, // must be a string - refreshToken, - accessToken, - accessTokenExpires, - }; - await wreck.put("linkAccount", { - payload, - }); - } catch { + await wreck.put("linkAccount", {payload: account} as any ); + } catch(error) { + console.log(error); throw new Error("LINK_ACCOUNT_ERROR"); } } async function createSession(user: User) { try { - const { payload } = await wreck.post("createSession", { + const { payload }: {payload: AdapterSession} = await wreck.post("createSession", { payload: user, }); - + payload.expires = new Date(payload.expires) return payload; - } catch { + } catch(error) { + console.log(error) throw new Error("CREATE_SESSION_ERROR"); } } - async function getSession(sessionToken: string) { + async function getSessionAndUser(sessionToken: string) { try { - const { payload } = await wreck.get(`getSession/${sessionToken}`); - return payload; + const {payload}: {payload: any} = await wreck.get(`getSessionAndUser/${sessionToken}`); + const { session, user }: {session: AdapterSession, user: AdapterUser} = payload; + session.expires = new Date(session.expires) + return {session, user} } catch (error) { + console.log(error) if (Boom.isBoom(error, 404)) return null; - throw new Error("GET_SESSION_ERROR"); + throw new Error("GET_SESSION_AND_USER_ERROR"); } } @@ -213,21 +196,18 @@ export const MetamigoAdapter = (config: IAppConfig): Adapter => { createUser, getUser, getUserByEmail, - getUserByProviderAccountId, + getUserByAccount, updateUser, // deleteUser, linkAccount, // unlinkAccount, createSession, - getSession, + getSessionAndUser, updateSession, deleteSession, // @ts-expect-error: Type error } as AdapterInstance; } - return { - // @ts-expect-error: non-existent property - getAdapter, - }; + return getAdapter(); }; diff --git a/apps/metamigo-frontend/pages/api/auth/[...nextauth].ts b/apps/metamigo-frontend/pages/api/auth/[...nextauth].ts index 35427b3..e33fb01 100644 --- a/apps/metamigo-frontend/pages/api/auth/[...nextauth].ts +++ b/apps/metamigo-frontend/pages/api/auth/[...nextauth].ts @@ -7,6 +7,7 @@ import Cognito from "next-auth/providers/cognito"; import { loadConfig, IAppConfig } from "@digiresilience/metamigo-config"; import { MetamigoAdapter } from "../../../lib/nextauth-adapter"; import { CloudflareAccessProvider } from "../../../lib/cloudflare"; +import { AdapterSession, AdapterUser } from "next-auth/adapters"; const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => { const { nextAuth, cfaccess } = config; @@ -72,11 +73,6 @@ const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => { providers, adapter, callbacks: { - async session(session: any, token: any) { - // make the user id available in the react client - session.user.id = token.userId; - return session; - }, async jwt(token: any, user: any) { const isSignIn = Boolean(user); // Add auth_time to token on signin in diff --git a/package-lock.json b/package-lock.json index 90cbb59..9103273 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "packages/*" ], "devDependencies": { + "dotenv-cli": "latest", "prettier": "^2.8.8" } }, @@ -8189,8 +8190,7 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/comma-separated-tokens": { "version": "2.0.3", @@ -8433,7 +8433,6 @@ "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "dev": true, "engines": { "node": "*" } @@ -8964,6 +8963,30 @@ "node": ">=12" } }, + "node_modules/dotenv-cli": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.2.1.tgz", + "integrity": "sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "dotenv": "^16.0.0", + "dotenv-expand": "^10.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "dotenv": "cli.js" + } + }, + "node_modules/dotenv-expand": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -10233,8 +10256,7 @@ "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==", - "dev": true + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -10319,8 +10341,7 @@ "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "node_modules/fastq": { "version": "1.15.0", @@ -11635,7 +11656,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dev": true, "dependencies": { "glob": "^8.0.0", "readable-stream": "^3.6.0" @@ -11645,7 +11665,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -11654,7 +11673,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11673,7 +11691,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -11685,7 +11702,6 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -11699,7 +11715,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -14216,7 +14231,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "dev": true, "engines": { "node": ">=10" } @@ -16980,7 +16994,6 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.0.tgz", "integrity": "sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==", - "dev": true, "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", @@ -17005,7 +17018,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.0.tgz", "integrity": "sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==", - "dev": true, "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -21976,6 +21988,7 @@ "next-auth": "^4.22.1", "pg-promise": "^11.4.3", "pino": "^8.14.1", + "pino-pretty": "^10.0.0", "prom-client": "^14.x.x", "uuid": "^9.0.0" }, diff --git a/package.json b/package.json index c7783e1..d90643b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "dev": "dotenv -- turbo run dev" + "dev": "dotenv -- turbo run dev", + "migrate": "dotenv -- npm run migrate --workspace=@digiresilience/metamigo-cli" }, "packageManager": "npm@9.3.1", "workspaces": [ @@ -16,7 +17,7 @@ "url": "git+https://gitlab.com/digiresilience/link/link-stack.git" }, "author": "Darren Clarke", - "license": "ISC", + "dlicense": "ISC", "overrides": { "@mui/styles": { "react": "18.2.0" @@ -29,6 +30,7 @@ } }, "devDependencies": { - "prettier": "^2.8.8" + "prettier": "^2.8.8", + "dotenv-cli": "latest" } } diff --git a/packages/hapi-nextauth/src/index.ts b/packages/hapi-nextauth/src/index.ts index be870ab..e593556 100644 --- a/packages/hapi-nextauth/src/index.ts +++ b/packages/hapi-nextauth/src/index.ts @@ -13,7 +13,7 @@ const minimumProfileSchema = Joi.object() const minimumUserSchema = Joi.object() .keys({ - id: Joi.string().required(), + userId: Joi.string().required(), email: Joi.string().email().required(), }) .unknown(true); diff --git a/packages/hapi-nextauth/src/routes.ts b/packages/hapi-nextauth/src/routes.ts index a6a2ea2..ef652dd 100644 --- a/packages/hapi-nextauth/src/routes.ts +++ b/packages/hapi-nextauth/src/routes.ts @@ -93,13 +93,13 @@ export const register = async ( }, { method: "GET", - path: `${basePath}/getUserByProviderAccountId/{providerId}/{providerAccountId}`, + path: `${basePath}/getUserByAccount/{provider}/{providerAccountId}`, options: { auth, tags, validate: { params: { - providerId: Joi.string(), + provider: Joi.string(), providerAccountId: Joi.string(), }, }, @@ -107,10 +107,10 @@ export const register = async ( request: Hapi.Request, h: ResponseToolkit ): Promise { - const { providerId, providerAccountId } = request.params; + const { provider, providerAccountId } = request.params; const r = await opts .nextAuthAdapterFactory(request) - .getUserByProviderAccountId(providerId, providerAccountId); + .getUserByAccount(provider, providerAccountId); if (!r) return h.response().code(404); return h.response(r as object); }, @@ -148,14 +148,15 @@ export const register = async ( tags, validate: { payload: Joi.object({ - userId, - providerId: Joi.string(), - providerType: Joi.string(), - providerAccountId: Joi.string(), - refreshToken: Joi.string().optional().allow(null), - accessToken: Joi.string().optional().allow(null), - accessTokenExpires: Joi.number().optional().allow(null), - }).options({ presence: "required" }), + // https://next-auth.js.org/getting-started/upgrade-v4#schema-changes + userId: Joi.string().required(), + provider: Joi.string().required(), + type: Joi.string().required(), + providerAccountId: Joi.string().required(), + refresh_token: Joi.string().optional().allow(null), + access_token: Joi.string().optional().allow(null), + expires_at: Joi.number().optional().allow(null), + }).unknown(true), }, async handler( request: Hapi.Request, @@ -193,7 +194,11 @@ export const register = async ( auth, tags, validate: { - payload: user, + payload: Joi.object({ + userId: Joi.string().required(), + sessionToken: Joi.string().required(), + expires: Joi.string().isoDate().required(), + }), }, async handler( request: Hapi.Request, @@ -210,7 +215,7 @@ export const register = async ( }, { method: "GET", - path: `${basePath}/getSession/{sessionToken}`, + path: `${basePath}/getSessionAndUser/{sessionToken}`, options: { auth, tags, @@ -226,7 +231,7 @@ export const register = async ( const token = request.params.sessionToken; const r = await opts .nextAuthAdapterFactory(request) - .getSession(token); + .getSessionAndUser(token); if (!r) return h.response().code(404); return h.response(r as object); }, diff --git a/packages/metamigo-common/src/controllers/nextauth-adapter.ts b/packages/metamigo-common/src/controllers/nextauth-adapter.ts index 6079e19..6c77a37 100644 --- a/packages/metamigo-common/src/controllers/nextauth-adapter.ts +++ b/packages/metamigo-common/src/controllers/nextauth-adapter.ts @@ -1,10 +1,16 @@ /* eslint-disable unicorn/no-null,max-params */ import { createHash, randomBytes } from "node:crypto"; import omit from "lodash/omit.js"; -import type { IMetamigoRepositories } from "../records/index.js"; +import { IMetamigoRepositories, idKeysOf } from "../records/index.js"; import type { UnsavedAccount } from "../records/account.js"; import type { UserId, UnsavedUser, SavedUser } from "../records/user.js"; import type { UnsavedSession, SavedSession } from "../records/session.js"; +import { + AdapterAccount, + AdapterSession, + AdapterUser, +} from "next-auth/adapters.js"; +import { ReadableStreamDefaultController } from "stream/web"; // Sessions expire after 30 days of being idle export const defaultSessionMaxAge = 30 * 24 * 60 * 60 * 1000; @@ -23,7 +29,7 @@ export class NextAuthAdapter { private repos: TRepositories, private readonly sessionMaxAge = defaultSessionMaxAge, private readonly sessionUpdateAge = defaulteSessionUpdateAge - ) { } + ) {} async createUser(profile: UnsavedUser): Promise { // @ts-expect-error Typescript doesn't like lodash's omit() @@ -56,12 +62,12 @@ export class NextAuthAdapter { return user; } - async getUserByProviderAccountId( - providerId: string, + async getUserByAccount( + provider: string, providerAccountId: string ): Promise { const account = await this.repos.accounts.findBy({ - compoundId: getCompoundId(providerId, providerAccountId), + compoundId: getCompoundId(provider, providerAccountId), }); if (!account) return null; @@ -72,15 +78,16 @@ export class NextAuthAdapter { return this.repos.users.update(user); } - async linkAccount( - userId: string, - providerId: string, - providerType: string, - providerAccountId: string, - refreshToken: string, - accessToken: string, - accessTokenExpires: number - ): Promise { + async linkAccount(adapterAccount: AdapterAccount): Promise { + const { + userId, + access_token: accessToken, + refresh_token: refreshToken, + provider: providerId, + providerAccountId, + expires_at: accessTokenExpires, + type: providerType, + } = adapterAccount; const exists = await this.repos.users.existsById({ id: userId }); if (!exists) return; const account: UnsavedAccount = { @@ -109,7 +116,13 @@ export class NextAuthAdapter { }); } - createSession(user: SavedUser): Promise { + createSession({ + sessionToken, + userId, + }: { + sessionToken: string; + userId: string; + }): Promise { let expires; if (this.sessionMaxAge) { const dateExpires = new Date(Date.now() + this.sessionMaxAge); @@ -118,22 +131,41 @@ export class NextAuthAdapter { const session: UnsavedSession = { expires, - userId: user.id, - sessionToken: randomToken(), + userId, + sessionToken, + //sessionToken: randomToken(), accessToken: randomToken(), }; return this.repos.sessions.insert(session); } - async getSession(sessionToken: string): Promise { + async getSessionAndUser( + sessionToken: string + ): Promise<{ session: AdapterSession; user: AdapterUser } | null> { const session = await this.repos.sessions.findBy({ sessionToken }); + if (!session) return null; if (session && session.expires && new Date() > session.expires) { this.repos.sessions.remove(session); return null; } - return session; + const user = await this.repos.users.findById({ id: session.userId }); + if (!user) return null; + + const adapterSession: AdapterSession = { + userId: session.userId, + expires: session.expires, + sessionToken: sessionToken, + }; + + const adapterUser: AdapterUser = { + id: user.id, + email: user.email, + emailVerified: user.emailVerified, + }; + + return { session: adapterSession, user: adapterUser }; } async updateSession( diff --git a/packages/metamigo-config/src/index.ts b/packages/metamigo-config/src/index.ts index 4872559..d3c008e 100644 --- a/packages/metamigo-config/src/index.ts +++ b/packages/metamigo-config/src/index.ts @@ -9,20 +9,20 @@ export const configSchema = { doc: "The postgres connection url.", format: "uri", default: "postgresql://metamigo:metamigo@127.0.0.1:5435/metamigo_dev", - env: "DATABASE_URL", + env: "METAMIGO_DATABASE_URL", sensitive: true, }, name: { doc: "The name of the postgres database", format: String, default: "metamigo_dev", - env: "DATABASE_NAME", + env: "METAMIGO_DATABASE_NAME", }, owner: { doc: "The username of the postgres database owner", format: String, default: "metamigo", - env: "DATABASE_OWNER", + env: "METAMIGO_DATABASE_OWNER", }, }, worker: { @@ -30,19 +30,19 @@ export const configSchema = { doc: "The postgres connection url for the worker database.", format: "uri", default: "postgresql://metamigo:metamigo@127.0.0.1:5435/metamigo_dev", - env: "WORKER_DATABASE_URL", + env: "METAMIGO_WORKER_DATABASE_URL", }, concurrency: { doc: "The number of jobs to run concurrently", default: 1, format: "positiveInt", - env: "WORKER_CONCURRENT_JOBS", + env: "METAMIGO_WORKER_CONCURRENT_JOBS", }, pollInterval: { doc: "How long to wait between polling for jobs in milliseconds (for jobs scheduled in the future/retries)", default: 2000, format: "positiveInt", - env: "WORKER_POLL_INTERVAL_MS", + env: "METAMIGO_WORKER_POLL_INTERVAL_MS", }, }, postgraphile: { @@ -50,26 +50,26 @@ export const configSchema = { doc: "The postgres role that postgraphile logs in with", format: String, default: "metamigo_graphile_auth", - env: "DATABASE_AUTHENTICATOR", + env: "METAMIGO_DATABASE_AUTHENTICATOR", }, appRootConnection: { doc: "The postgres root/superuser connection url for development mode so PG can watch the schema changes, this is strangely named in the postgraphile API 'ownerConnectionString'", format: String, default: "postgresql://postgres:metamigo@127.0.0.1:5435/metamigo_dev", - env: "APP_ROOT_DATABASE_URL", + env: "METAMIGO_APP_ROOT_DATABASE_URL", }, authConnection: { doc: "The postgres connection URL for postgraphile, must not be superuser and must have limited privs.", format: String, default: "postgresql://metamigo_graphile_auth:metamigo@127.0.0.1:5435/metamigo_dev", - env: "DATABASE_AUTH_URL", + env: "METAMIGO_DATABASE_AUTH_URL", }, visitor: { doc: "The postgres role that postgraphile switches to", format: String, default: "app_postgraphile", - env: "DATABASE_VISITOR", + env: "METAMIGO_DATABASE_VISITOR", }, schema: { doc: "The schema postgraphile should expose with graphql", @@ -80,7 +80,7 @@ export const configSchema = { doc: "Whether to enable the graphiql web interface or not", format: "Boolean", default: false, - env: "ENABLE_GRAPHIQL", + env: "METAMIGO_ENABLE_GRAPHIQL", }, }, @@ -89,14 +89,14 @@ export const configSchema = { doc: "The shadow databse connection url used by postgraphile-migrate. Not needed in production.", format: "uri", default: "postgresql://metamigo:metamigo@127.0.0.1:5435/metamigo_shadow", - env: "SHADOW_DATABASE_URL", + env: "METAMIGO_SHADOW_DATABASE_URL", sensitive: true, }, rootConnection: { doc: "The postgres root/superuser connection url for testing only, database must NOT be the app database. Not needed in production.", format: "uri", default: "postgresql://postgres:metamigo@127.0.0.1:5435/template1", - env: "ROOT_DATABASE_URL", + env: "METAMIGO_ROOT_DATABASE_URL", sensitive: true, }, }, @@ -105,13 +105,13 @@ export const configSchema = { doc: "The url the frontend can be accessed at", format: "url", default: "http://localhost:3000", - env: "FRONTEND_URL", + env: "METAMIGO_FRONTEND_URL", }, apiUrl: { doc: "The url the api backend can be accessed at from the frontend server", format: "url", default: "http://localhost:3001", - env: "API_URL", + env: "METAMIGO_API_URL", }, }, nextAuth: {