Merge branch 'main' into shell-updates
This commit is contained in:
commit
db8a3d1ee0
132 changed files with 3609 additions and 5150 deletions
|
|
@ -1,60 +0,0 @@
|
|||
FROM node:20-bullseye as builder
|
||||
|
||||
ARG METAMIGO_DIR=/opt/metamigo
|
||||
RUN mkdir -p ${METAMIGO_DIR}/
|
||||
WORKDIR ${METAMIGO_DIR}
|
||||
COPY package.json tsconfig.json ${METAMIGO_DIR}/
|
||||
COPY . ${METAMIGO_DIR}/
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
# RUN npx --no-install tsc --build --verbose
|
||||
|
||||
RUN rm -Rf ./node_modules
|
||||
|
||||
FROM node:20-bullseye as clean
|
||||
ARG METAMIGO_DIR=/opt/metamigo
|
||||
|
||||
COPY --from=builder ${METAMIGO_DIR} ${METAMIGO_DIR}/
|
||||
|
||||
RUN rm -Rf ./node_modules
|
||||
|
||||
FROM node:20-bullseye as pristine
|
||||
LABEL maintainer="Abel Luck <abel@guardianproject.info>"
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && \
|
||||
apt-get install -y --no-install-recommends --fix-missing \
|
||||
postgresql-client dumb-init ffmpeg
|
||||
|
||||
ARG METAMIGO_DIR=/opt/metamigo
|
||||
ENV METAMIGO_DIR ${METAMIGO_DIR}
|
||||
RUN mkdir -p ${METAMIGO_DIR}
|
||||
RUN chown -R node:node ${METAMIGO_DIR}/
|
||||
|
||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
RUN chmod +x /docker-entrypoint.sh
|
||||
|
||||
COPY --from=clean ${METAMIGO_DIR}/ ${METAMIGO_DIR}/
|
||||
|
||||
WORKDIR ${METAMIGO_DIR}
|
||||
|
||||
USER node
|
||||
|
||||
EXPOSE 3000
|
||||
EXPOSE 3001
|
||||
EXPOSE 3002
|
||||
ENV PORT 3000
|
||||
ENV NODE_ENV production
|
||||
|
||||
ARG BUILD_DATE
|
||||
ARG VCS_REF
|
||||
ARG VCS_URL="https://gitlab.com/digiresilience/link/metamigo"
|
||||
ARG VERSION
|
||||
LABEL org.label-schema.schema-version="1.0"
|
||||
LABEL org.label-schema.name="digiresilience.org/link/metamigo"
|
||||
LABEL org.label-schema.description="part of CDR Link"
|
||||
LABEL org.label-schema.build-date=$BUILD_DATE
|
||||
LABEL org.label-schema.vcs-url=$VCS_URL
|
||||
LABEL org.label-schema.vcs-ref=$VCS_REF
|
||||
LABEL org.label-schema.version=$VERSION
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cd ${AMIGO_DIR}
|
||||
|
||||
if [[ "$1" == "api" ]]; then
|
||||
echo "docker-entrypoint: starting api server"
|
||||
./cli db -- migrate
|
||||
exec dumb-init ./cli api
|
||||
elif [[ "$1" == "worker" ]]; then
|
||||
echo "docker-entrypoint: starting worker"
|
||||
exec dumb-init ./cli worker
|
||||
elif [[ "$1" == "frontend" ]]; then
|
||||
echo "docker-entrypoint: starting frontend"
|
||||
exec dumb-init yarn workspace @app/frontend start
|
||||
elif [[ "$1" == "cli" ]]; then
|
||||
echo "docker-entrypoint: starting frontend"
|
||||
shift 1
|
||||
exec ./cli "$@"
|
||||
else
|
||||
echo "docker-entrypoint: missing argument, one of: api, worker, frontend, cli"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"name": "metamigo-api",
|
||||
"name": "@digiresilience/metamigo-api",
|
||||
"version": "0.2.0",
|
||||
"main": "build/main/cli/index.js",
|
||||
"type": "module",
|
||||
"main": "build/main/main.js",
|
||||
"author": "Abel Luck <abel@guardianproject.info>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
|
|
@ -26,8 +27,8 @@
|
|||
"fluent-ffmpeg": "^2.1.2",
|
||||
"graphile-migrate": "^1.4.1",
|
||||
"graphile-worker": "^0.13.0",
|
||||
"hapi-auth-bearer-token": "^8.0.0",
|
||||
"hapi-auth-jwt2": "^10.4.0",
|
||||
"hapi-postgraphile": "^0.11.0",
|
||||
"hapi-swagger": "^16.0.1",
|
||||
"joi": "^17.9.2",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
|
|
@ -37,6 +38,7 @@
|
|||
"pg": "^8.11.0",
|
||||
"pg-monitor": "^2.0.0",
|
||||
"pg-promise": "^11.4.3",
|
||||
"postgraphile": "4.12.3",
|
||||
"postgraphile-plugin-connection-filter": "^2.3.0",
|
||||
"remeda": "^1.18.1",
|
||||
"twilio": "^4.11.1",
|
||||
|
|
@ -53,6 +55,7 @@
|
|||
"pg-monitor": "^2.0.0",
|
||||
"pino-pretty": "^10.0.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsc-watch": "^6.0.4",
|
||||
"tsconfig-link": "*",
|
||||
"typedoc": "^0.24.7",
|
||||
"typescript": "^5.0.4"
|
||||
|
|
@ -75,6 +78,7 @@
|
|||
"serve:prod": "NODE_ENV=production npm run cli server",
|
||||
"worker": "NODE_ENV=development npm run cli worker",
|
||||
"worker:prod": "NODE_ENV=production npm run cli worker",
|
||||
"watch:build": "tsc -p tsconfig.json -w"
|
||||
"watch:build": "tsc -p tsconfig.json -w",
|
||||
"dev": "tsc-watch --build --noClear --onSuccess \"node ./build/main/main.js\""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type * as Hapi from "@hapi/hapi";
|
||||
import * as Joi from "joi";
|
||||
import type { IAppConfig } from "../config";
|
||||
import * as Services from "./services";
|
||||
import * as Routes from "./routes";
|
||||
import * as Plugins from "./plugins";
|
||||
import Joi from "joi";
|
||||
import type { IAppConfig } from "../config.js";
|
||||
import * as Services from "./services/index.js";
|
||||
import * as Routes from "./routes/index.js";
|
||||
import * as Plugins from "./plugins/index.js";
|
||||
|
||||
const AppPlugin = {
|
||||
name: "App",
|
||||
|
|
|
|||
28
apps/metamigo-api/src/app/plugins/auth-bearer.ts
Normal file
28
apps/metamigo-api/src/app/plugins/auth-bearer.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import type * as Hapi from "@hapi/hapi";
|
||||
import AuthBearer from "hapi-auth-bearer-token";
|
||||
import { IAppConfig } from "@digiresilience/metamigo-config";
|
||||
import { IMetamigoRepositories } from "@digiresilience/metamigo-common";
|
||||
|
||||
export const registerAuthBearer = async (
|
||||
server: Hapi.Server,
|
||||
config: IAppConfig
|
||||
): Promise<void> => {
|
||||
await server.register(AuthBearer);
|
||||
|
||||
server.auth.strategy("session-id-bearer-token", "bearer-access-token", {
|
||||
allowQueryToken: false,
|
||||
validate: async (
|
||||
request: Hapi.Request,
|
||||
token: string,
|
||||
h: Hapi.ResponseToolkit
|
||||
) => {
|
||||
const repos = request.db() as IMetamigoRepositories;
|
||||
const session = await repos.sessions.findBy({ sessionToken: token });
|
||||
const isValid = !!session;
|
||||
if (!isValid) return { isValid, credentials: {} };
|
||||
const user = await repos.users.findById({ id: session.userId });
|
||||
const credentials = { sessionToken: token, user };
|
||||
return { isValid, credentials };
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -7,7 +7,8 @@ export const registerNextAuth = async (
|
|||
server: Hapi.Server,
|
||||
config: IAppConfig
|
||||
): Promise<void> => {
|
||||
const nextAuthAdapterFactory: any = (request: Hapi.Request) => new NextAuthAdapter(request.db());
|
||||
const nextAuthAdapterFactory: any = (request: Hapi.Request) =>
|
||||
new NextAuthAdapter(request.db());
|
||||
|
||||
await server.register({
|
||||
plugin: NextAuthPlugin,
|
||||
|
|
|
|||
71
apps/metamigo-api/src/app/plugins/hapi-postgraphile.ts
Normal file
71
apps/metamigo-api/src/app/plugins/hapi-postgraphile.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import type * as Hapi from "@hapi/hapi";
|
||||
import { IAppConfig } from "@digiresilience/metamigo-config";
|
||||
import { postgraphile, HttpRequestHandler } from "postgraphile";
|
||||
import { getPostGraphileOptions } from "@digiresilience/metamigo-db";
|
||||
|
||||
export interface HapiPostgraphileOptions {}
|
||||
|
||||
const PostgraphilePlugin: Hapi.Plugin<HapiPostgraphileOptions> = {
|
||||
name: "postgraphilePlugin",
|
||||
version: "1.0.0",
|
||||
register: async function (server, options: HapiPostgraphileOptions) {
|
||||
const config = server.config();
|
||||
const postgraphileMiddleware: HttpRequestHandler = postgraphile(
|
||||
config.postgraphile.authConnection,
|
||||
"app_public",
|
||||
{
|
||||
...getPostGraphileOptions(),
|
||||
jwtSecret: "",
|
||||
pgSettings: async (req) => {
|
||||
const auth = (req as any).hapiAuth;
|
||||
if (auth.isAuthenticated && auth.credentials.user.userRole) {
|
||||
return {
|
||||
role: `app_${auth.credentials.user.userRole}`,
|
||||
"jwt.claims.session_id": auth.credentials.sessionToken,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
role: "app_anonymous",
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
server.route({
|
||||
method: ["POST"],
|
||||
path: "/graphql",
|
||||
options: {
|
||||
auth: "session-id-bearer-token",
|
||||
payload: {
|
||||
parse: false, // this disables payload parsing
|
||||
output: "stream", // ensures the payload is a readable stream which postgraphile expects
|
||||
},
|
||||
},
|
||||
handler: (request: Hapi.Request, h: Hapi.ResponseToolkit) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const rawReq = request.raw.req as any;
|
||||
rawReq.hapiAuth = request.auth;
|
||||
postgraphileMiddleware(rawReq, request.raw.res, (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
// PostGraphile responds directly to the request
|
||||
resolve(h.abandon);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const registerPostgraphile = async (
|
||||
server: Hapi.Server,
|
||||
config: IAppConfig
|
||||
): Promise<void> => {
|
||||
await server.register({
|
||||
plugin: PostgraphilePlugin,
|
||||
options: {},
|
||||
});
|
||||
};
|
||||
|
|
@ -5,12 +5,14 @@ import { makePlugin } from "@digiresilience/hapi-pg-promise";
|
|||
|
||||
import type { IAppConfig } from "../../config";
|
||||
import { dbInitOptions, IRepositories } from "@digiresilience/metamigo-db";
|
||||
import { registerNextAuth } from "./hapi-nextauth";
|
||||
import { registerSwagger } from "./swagger";
|
||||
import { registerNextAuthJwt } from "./nextauth-jwt";
|
||||
import { registerCloudflareAccessJwt } from "./cloudflare-jwt";
|
||||
import { registerNextAuth } from "./hapi-nextauth.js";
|
||||
import { registerSwagger } from "./swagger.js";
|
||||
import { registerCloudflareAccessJwt } from "./cloudflare-jwt.js";
|
||||
import { registerAuthBearer } from "./auth-bearer.js";
|
||||
import pg from "pg-promise/typescript/pg-subset";
|
||||
|
||||
import { registerPostgraphile } from "./hapi-postgraphile.js";
|
||||
|
||||
export const register = async (
|
||||
server: Hapi.Server,
|
||||
config: IAppConfig
|
||||
|
|
@ -34,6 +36,7 @@ export const register = async (
|
|||
|
||||
await registerNextAuth(server, config);
|
||||
await registerSwagger(server);
|
||||
await registerNextAuthJwt(server, config);
|
||||
await registerCloudflareAccessJwt(server, config);
|
||||
await registerAuthBearer(server, config);
|
||||
await registerPostgraphile(server, config);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
import * as Hoek from "@hapi/hoek";
|
||||
import * as Hapi from "@hapi/hapi";
|
||||
import type { IAppConfig } from "../../config";
|
||||
|
||||
// hapi-auth-jwt2 expects the key to be a raw key
|
||||
const jwkToHapiAuthJwt2 = (jwkString) => {
|
||||
try {
|
||||
const jwk = JSON.parse(jwkString);
|
||||
return Buffer.from(jwk.k, "base64");
|
||||
} catch {
|
||||
throw new Error(
|
||||
"Failed to parse key for JWT verification. This is probably an application configuration error."
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const jwtDefaults = {
|
||||
jwkeysB64: undefined,
|
||||
validate: undefined,
|
||||
strategyName: "nextauth-jwt",
|
||||
};
|
||||
|
||||
const jwtRegister = async (server: Hapi.Server, options): Promise<void> => {
|
||||
server.dependency(["hapi-auth-jwt2"]);
|
||||
const settings = Hoek.applyToDefaults(jwtDefaults, options);
|
||||
const key = settings.jwkeysB64.map((k) => jwkToHapiAuthJwt2(k));
|
||||
|
||||
if (!settings.strategyName) {
|
||||
throw new Error("Missing strategy name in nextauth-jwt pluginsettings!");
|
||||
}
|
||||
|
||||
server.auth.strategy(settings.strategyName, "jwt", {
|
||||
key,
|
||||
cookieKey: false,
|
||||
urlKey: false,
|
||||
validate: settings.validate,
|
||||
});
|
||||
};
|
||||
|
||||
export const registerNextAuthJwt = async (
|
||||
server: Hapi.Server,
|
||||
config: IAppConfig
|
||||
): Promise<void> => {
|
||||
if (config.nextAuth.signingKey) {
|
||||
await server.register({
|
||||
plugin: {
|
||||
name: "nextauth-jwt",
|
||||
version: "0.0.2",
|
||||
register: jwtRegister,
|
||||
},
|
||||
options: {
|
||||
jwkeysB64: [config.nextAuth.signingKey],
|
||||
async validate(decoded, request: Hapi.Request) {
|
||||
const { email, name, role } = decoded;
|
||||
const user = await request.db().users.findBy({ email });
|
||||
if (!config.isProd) {
|
||||
server.logger.info(
|
||||
{
|
||||
email,
|
||||
name,
|
||||
role,
|
||||
},
|
||||
"nextauth-jwt authorizing request"
|
||||
);
|
||||
// server.logger.info({ user }, "nextauth-jwt user result");
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: Boolean(user && user.isActive),
|
||||
// this credentials object is made available in every request
|
||||
// at `request.auth.credentials`
|
||||
credentials: { email, name, role },
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (config.isProd) {
|
||||
throw new Error("Missing nextauth.signingKey configuration value.");
|
||||
} else {
|
||||
server.log(
|
||||
["warn"],
|
||||
"Missing nextauth.signingKey configuration value. Authentication of nextauth endpoints disabled!"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// @hapi/jwt expects the key in its own format
|
||||
/* UNUSED
|
||||
const _jwkToHapiJwt = (jwkString) => {
|
||||
try {
|
||||
const jwk = JSON.parse(jwkString);
|
||||
const rawKey = Buffer.from(jwk.k, "base64");
|
||||
return {
|
||||
key: rawKey,
|
||||
algorithms: [jwk.alg],
|
||||
kid: jwk.kid,
|
||||
};
|
||||
} catch {
|
||||
throw new Error(
|
||||
"Failed to parse key for JWT verification. This is probably an application configuration error."
|
||||
);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
|
@ -4,7 +4,7 @@ import Toys from "@hapipal/toys";
|
|||
export const withDefaults = Toys.withRouteDefaults({
|
||||
options: {
|
||||
cors: true,
|
||||
auth: "nextauth-jwt",
|
||||
auth: "session-id-bearer-token",
|
||||
validate: {
|
||||
failAction: Metamigo.validatingFailAction,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import isFunction from "lodash/isFunction";
|
||||
import isFunction from "lodash/isFunction.js";
|
||||
import type * as Hapi from "@hapi/hapi";
|
||||
import * as UserRoutes from "./users";
|
||||
import * as VoiceRoutes from "./voice";
|
||||
import * as WhatsappRoutes from "./whatsapp";
|
||||
import * as SignalRoutes from "./signal";
|
||||
import * as UserRoutes from "./users/index.js";
|
||||
import * as VoiceRoutes from "./voice/index.js";
|
||||
import * as WhatsappRoutes from "./whatsapp/index.js";
|
||||
import * as SignalRoutes from "./signal/index.js";
|
||||
|
||||
const loadRouteIndex = async (server, index) => {
|
||||
const routes = [];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as Hapi from "@hapi/hapi";
|
||||
import * as Joi from "joi";
|
||||
import * as Helpers from "../helpers";
|
||||
import Joi from "joi";
|
||||
import * as Helpers from "../helpers/index.js";
|
||||
import Boom from "@hapi/boom";
|
||||
|
||||
const getSignalService = (request) => request.services("app").signaldService;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import * as Joi from "joi";
|
||||
import Joi from "joi";
|
||||
import * as Hapi from "@hapi/hapi";
|
||||
import {
|
||||
UserRecord,
|
||||
crudRoutesFor,
|
||||
CrudControllerBase,
|
||||
} from "@digiresilience/metamigo-common";
|
||||
import * as RouteHelpers from "../helpers";
|
||||
import * as RouteHelpers from "../helpers/index.js";
|
||||
|
||||
class UserRecordController extends CrudControllerBase(UserRecord) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import * as Hapi from "@hapi/hapi";
|
||||
import * as Joi from "joi";
|
||||
import Joi from "joi";
|
||||
import * as Boom from "@hapi/boom";
|
||||
import * as R from "remeda";
|
||||
import * as Helpers from "../helpers";
|
||||
import * as Helpers from "../helpers/index.js";
|
||||
import Twilio from "twilio";
|
||||
import {
|
||||
crudRoutesFor,
|
||||
|
|
@ -66,7 +66,7 @@ export const VoiceProviderRoutes = Helpers.withDefaults([
|
|||
},
|
||||
]);
|
||||
|
||||
class VoiceLineRecordController extends CrudControllerBase(VoiceLineRecord) { }
|
||||
class VoiceLineRecordController extends CrudControllerBase(VoiceLineRecord) {}
|
||||
|
||||
const validator = (): Record<string, Hapi.RouteOptionsValidate> => ({
|
||||
create: {
|
||||
|
|
@ -122,4 +122,4 @@ export const VoiceLineRoutes = Helpers.withDefaults(
|
|||
)
|
||||
);
|
||||
|
||||
export * from "./twilio";
|
||||
export * from "./twilio/index.js";
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import * as Hapi from "@hapi/hapi";
|
||||
import * as Joi from "joi";
|
||||
import Joi from "joi";
|
||||
import * as Boom from "@hapi/boom";
|
||||
import Twilio from "twilio";
|
||||
import { SavedVoiceProvider } from "@digiresilience/metamigo-db";
|
||||
import pMemoize from "p-memoize";
|
||||
import ExpiryMap from "expiry-map";
|
||||
import ms from "ms";
|
||||
import * as Helpers from "../../helpers";
|
||||
import workerUtils from "../../../../worker-utils";
|
||||
import * as Helpers from "../../helpers/index.js";
|
||||
import workerUtils from "../../../../worker-utils.js";
|
||||
|
||||
const queueRecording = async (meta) =>
|
||||
workerUtils.addJob("twilio-recording", meta, { jobKey: meta.callSid });
|
||||
|
|
@ -91,7 +91,7 @@ export const TwilioRoutes = Helpers.noAuth([
|
|||
},
|
||||
async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) {
|
||||
const { voiceLineId } = request.params;
|
||||
const { To } = request.payload as { To: string; };
|
||||
const { To } = request.payload as { To: string };
|
||||
const voiceLine = await request.db().voiceLines.findBy({ number: To });
|
||||
if (!voiceLine) return Boom.notFound();
|
||||
if (voiceLine.id !== voiceLineId) return Boom.badRequest();
|
||||
|
|
@ -193,7 +193,7 @@ export const TwilioRoutes = Helpers.noAuth([
|
|||
},
|
||||
},
|
||||
async handler(request: Hapi.Request, h: Hapi.ResponseToolkit) {
|
||||
const { providerId } = request.params as { providerId: string; };
|
||||
const { providerId } = request.params as { providerId: string };
|
||||
const provider: SavedVoiceProvider = await request
|
||||
.db()
|
||||
.voiceProviders.findById({ id: providerId });
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as Hapi from "@hapi/hapi";
|
||||
import * as Helpers from "../helpers";
|
||||
import * as Helpers from "../helpers/index.js";
|
||||
import Boom from "@hapi/boom";
|
||||
|
||||
export const GetAllWhatsappBotsRoute = Helpers.withDefaults({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import type * as Hapi from "@hapi/hapi";
|
||||
import SettingsService from "./settings";
|
||||
import WhatsappService from "./whatsapp";
|
||||
import SignaldService from "./signald";
|
||||
import SettingsService from "./settings.js";
|
||||
import WhatsappService from "./whatsapp.js";
|
||||
import SignaldService from "./signald.js";
|
||||
|
||||
export const register = async (server: Hapi.Server): Promise<void> => {
|
||||
// register your services here
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
ClientMessageWrapperv1,
|
||||
} from "@digiresilience/node-signald";
|
||||
import { SavedSignalBot as Bot } from "@digiresilience/metamigo-db";
|
||||
import workerUtils from "../../worker-utils";
|
||||
import workerUtils from "../../worker-utils.js";
|
||||
|
||||
export default class SignaldService extends Service {
|
||||
signald: SignaldAPI;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import makeWASocket, {
|
|||
useMultiFileAuthState,
|
||||
} from "@adiwajshing/baileys";
|
||||
import fs from "fs";
|
||||
import workerUtils from "../../worker-utils";
|
||||
import workerUtils from "../../worker-utils.js";
|
||||
|
||||
export type AuthCompleteCallback = (error?: string) => void;
|
||||
|
||||
|
|
|
|||
2
apps/metamigo-api/src/index.ts
Normal file
2
apps/metamigo-api/src/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./server/index.js";
|
||||
export * from "./logger.js";
|
||||
8
apps/metamigo-api/src/main.ts
Normal file
8
apps/metamigo-api/src/main.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { startWithout } from "@digiresilience/montar";
|
||||
import "./index.js";
|
||||
|
||||
async function runServer(): Promise<void> {
|
||||
await startWithout(["worker"]);
|
||||
}
|
||||
|
||||
runServer();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import * as Metamigo from "@digiresilience/metamigo-common";
|
||||
import { defState } from "@digiresilience/montar";
|
||||
import Manifest from "./manifest";
|
||||
import config, { IAppConfig } from "../config";
|
||||
import Manifest from "./manifest.js";
|
||||
import config, { IAppConfig } from "../config.js";
|
||||
|
||||
export const deployment = async (
|
||||
config: IAppConfig,
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@ import * as Glue from "@hapi/glue";
|
|||
import * as Metamigo from "@digiresilience/metamigo-common";
|
||||
import * as Blipp from "blipp";
|
||||
import HapiBasic from "@hapi/basic";
|
||||
import HapiJwt from "hapi-auth-jwt2";
|
||||
import HapiPostgraphile from "hapi-postgraphile";
|
||||
import { getPostGraphileOptions } from "@digiresilience/metamigo-db";
|
||||
import AppPlugin from "../app";
|
||||
import type { IAppConfig } from "../config";
|
||||
import AppPlugin from "../app/index.js";
|
||||
import type { IAppConfig } from "../config.js";
|
||||
|
||||
const build = async (config: IAppConfig): Promise<Glue.Manifest> => {
|
||||
const { port, address } = config.server;
|
||||
|
|
@ -24,9 +21,6 @@ const build = async (config: IAppConfig): Promise<Glue.Manifest> => {
|
|||
},
|
||||
register: {
|
||||
plugins: [
|
||||
// jwt plugin, required for our jwt auth plugin
|
||||
{ plugin: HapiJwt },
|
||||
|
||||
// Blipp prints the nicely formatted list of endpoints at app boot
|
||||
{ plugin: Blipp },
|
||||
|
||||
|
|
@ -43,30 +37,6 @@ const build = async (config: IAppConfig): Promise<Glue.Manifest> => {
|
|||
config,
|
||||
},
|
||||
},
|
||||
// load Postgraphile
|
||||
{
|
||||
plugin: HapiPostgraphile,
|
||||
options: {
|
||||
route: {
|
||||
path: "/graphql",
|
||||
options: {
|
||||
auth: {
|
||||
strategies: ["nextauth-jwt"],
|
||||
mode: "optional",
|
||||
},
|
||||
},
|
||||
},
|
||||
pgConfig: config.postgraphile.authConnection,
|
||||
schemaName: "app_public",
|
||||
schemaOptions: {
|
||||
...getPostGraphileOptions(),
|
||||
jwtAudiences: [config.nextAuth.audience],
|
||||
jwtSecret: "",
|
||||
// unauthenticated users will hit the database with this role
|
||||
pgDefaultRole: "app_anonymous",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as Worker from "graphile-worker";
|
||||
import { defState } from "@digiresilience/montar";
|
||||
import config from "./config";
|
||||
import config from "./config.js";
|
||||
|
||||
const startWorkerUtils = async (): Promise<Worker.WorkerUtils> => {
|
||||
const workerUtils = await Worker.makeWorkerUtils({
|
||||
|
|
|
|||
|
|
@ -5,8 +5,18 @@
|
|||
"rootDir": "src",
|
||||
"skipLibCheck": true,
|
||||
"types": ["jest", "node", "long"],
|
||||
"lib": ["es2020", "DOM"]
|
||||
"lib": ["es2020", "DOM"],
|
||||
"composite": true,
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/.*.ts"],
|
||||
"exclude": ["node_modules/**"]
|
||||
"exclude": ["node_modules/**"],
|
||||
"references": [
|
||||
{"path": "../../packages/metamigo-common" },
|
||||
{"path": "../../packages/metamigo-config" },
|
||||
{"path": "../../packages/metamigo-db" },
|
||||
{"path": "../../packages/hapi-nextauth" },
|
||||
{"path": "../../packages/hapi-pg-promise" },
|
||||
{"path": "../../packages/node-signald" },
|
||||
{"path": "../../packages/montar" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue