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