From f830bab4ec14f3fe814962a6a2dee180149c3a6a Mon Sep 17 00:00:00 2001 From: Kevin J Hoerr Date: Mon, 20 Sep 2021 19:43:18 +0000 Subject: The Whole Barnshow Commit - Use yarn-berry instead of npm, with Zero Install feature and goodies - Add `initializeToken` to post unique token to logs on startup - Package upgrades - Fix index.html.template tests I will never do this again --- src/index.ts | 9 ++++- src/metadata.ts | 4 +- src/routes.test.ts | 6 +-- src/util/config.test.ts | 97 ++++++++++++++++++++++++++++++++++++++++++++----- src/util/config.ts | 20 ++++++++-- 5 files changed, 117 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/index.ts b/src/index.ts index a488538..5f688f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,12 @@ dotenv.config(); import routes from "./routes"; import Metadata, { EnvConfig } from "./metadata"; import loggerConfig from "./util/logger"; -import { configOrError, handleStartup, handleShutdown } from "./util/config"; +import { + configOrError, + handleStartup, + handleShutdown, + initializeToken +} from "./util/config"; // Start-up configuration const BIND_ADDRESS = process.env.BIND_ADDRESS ?? "localhost"; @@ -18,7 +23,7 @@ const PORT = Number(process.env.PORT ?? 3000); const MONGO_URI = configOrError("MONGO_URI"); const TARGET_URL = process.env.TARGET_URL ?? "http://localhost:3000"; const ENV_CONFIG: EnvConfig = { - token: process.env.TOKEN ?? "", + token: process.env.TOKEN ?? initializeToken(), uploadLimit: Number(process.env.UPLOAD_LIMIT ?? 4194304), publicDir: path.join(__dirname, "..", "public"), hostDir: configOrError("HOST_DIR"), diff --git a/src/metadata.ts b/src/metadata.ts index 6a0addc..8f2ea3e 100644 --- a/src/metadata.ts +++ b/src/metadata.ts @@ -136,11 +136,11 @@ class Metadata { branches: { [branch]: { head } } }; - const { result } = await this.database + const result = await this.database .collection("repository") .insertOne(repo); - return result.ok === 1; + return result.acknowledged; } } diff --git a/src/routes.test.ts b/src/routes.test.ts index d761602..7f275b9 100644 --- a/src/routes.test.ts +++ b/src/routes.test.ts @@ -85,7 +85,7 @@ const request = async ( }; const HOST_DIR = configOrError("HOST_DIR"); -const TARGET_URL = process.env.TARGET_URL ?? "http://localhost:3000"; +const TARGET_URL = "https://localhost:3000"; describe("templates", () => { describe("GET /sh", () => { @@ -120,7 +120,7 @@ describe("templates", () => { "index.html.template" ), outputFile: path.join(HOST_DIR, "index.html"), - context: { TARGET_URL } + context: { TARGET_URL, CURL_HTTPS: "--https " } } as Template); const res = await (await request()) @@ -129,7 +129,7 @@ describe("templates", () => { .expect(200); expect(exit).not.toHaveBeenCalled(); expect(res.text).toMatch( - `curl --proto '=https' --tlsv1.2 -sSf ${TARGET_URL}/sh | sh` + `curl --https -sSf ${TARGET_URL}/sh | sh` ); }); }); diff --git a/src/util/config.test.ts b/src/util/config.test.ts index e385bce..3f6d671 100644 --- a/src/util/config.test.ts +++ b/src/util/config.test.ts @@ -2,13 +2,36 @@ const exit = jest .spyOn(process, "exit") .mockImplementation(() => undefined as never); +import { Writable } from "stream"; +import winston from "winston"; + +let output = ""; + +jest.mock("./logger", () => { + const stream = new Writable(); + stream._write = (chunk, _encoding, next) => { + output = output += chunk.toString(); + next(); + }; + const streamTransport = new winston.transports.Stream({ stream }); + + return { + __esModule: true, + default: () => ({ + format: winston.format.combine(winston.format.splat(), winston.format.simple()), + transports: [streamTransport] + }) + } +}); + import { configOrError, persistTemplate, handleStartup, - handleShutdown + handleShutdown, + initializeToken } from "./config"; -import { MongoClient, MongoError, ReadPreference } from "mongodb"; +import { Logger, MongoClient, MongoError, ReadConcern, ReadPreference, WriteConcern } from "mongodb"; import { Server } from "http"; import path from "path"; import fs from "fs"; @@ -43,14 +66,56 @@ const MongoMock = (p: Promise): jest.Mock => jest.fn(() => ({ ...CommonMocks, close: jest.fn(() => p), - readPreference: { - mode: ReadPreference.NEAREST, - tags: [], - isValid: jest.fn(), - slaveOk: jest.fn(), - equals: jest.fn() + readPreference: ReadPreference.nearest, + bsonOptions: {}, + logger: new Logger("a"), + getLogger: jest.fn(), + options: { + hosts: [], + readPreference: ReadPreference.nearest, + readConcern: new ReadConcern("local"), + loadBalanced: true, + serverApi: { version: "1" }, + compressors: [], + writeConcern: new WriteConcern(), + dbName: "", + metadata: {driver: {name: "", version: ""}, os: {type: "", name: "linux", architecture: "", version: ""}, platform: "linx"}, + tls: true, + toURI: jest.fn(), + autoEncryption: {}, + connectTimeoutMS: 0, + directConnection: true, + driverInfo: {}, + forceServerObjectId: true, + minHeartbeatFrequencyMS: 0, + heartbeatFrequencyMS: 0, + keepAlive: false, + keepAliveInitialDelay: 0, + localThresholdMS: 0, + logger: new Logger("a"), + maxIdleTimeMS: 0, + maxPoolSize: 0, + minPoolSize: 0, + monitorCommands: true, + noDelay: true, + pkFactory: { createPk: jest.fn() }, + promiseLibrary: {}, + raw: true, + replicaSet: "", + retryReads: true, + retryWrites: true, + serverSelectionTimeoutMS: 0, + socketTimeoutMS: 0, + tlsAllowInvalidCertificates: true, + tlsAllowInvalidHostnames: true, + tlsInsecure: false, + waitQueueTimeoutMS: 0, + zlibCompressionLevel: 0, }, - writeConcern: {}, + serverApi: { version: "1" }, + autoEncrypter: undefined, + readConcern: new ReadConcern("local"), + writeConcern: new WriteConcern(), db: jest.fn() })); const ServerMock = (mockErr: Error | undefined): jest.Mock => @@ -76,6 +141,20 @@ const ServerMock = (mockErr: Error | undefined): jest.Mock => unref: jest.fn() })); +describe("initializeToken", () => { + it("Should generate a UUID", () => { + // Arrange + output = ""; + + // Act + let result = initializeToken(); + + // Assert + expect(result).toMatch(/([a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8})/); + expect(output).toContain(result); + }); +}); + describe("configOrError", () => { beforeEach(() => { exit.mockClear(); diff --git a/src/util/config.ts b/src/util/config.ts index 3b09590..e83eab7 100644 --- a/src/util/config.ts +++ b/src/util/config.ts @@ -3,6 +3,7 @@ import { MongoClient, MongoError } from "mongodb"; import { Server } from "http"; import path from "path"; import fs from "fs"; +import { v4 as uuid } from "uuid"; import loggerConfig from "./logger"; import processTemplate, { Template } from "../templates"; @@ -10,6 +11,21 @@ import { EnvConfig } from "../metadata"; const logger = winston.createLogger(loggerConfig("ROOT")); +export const initializeToken = (): string => { + //TODO check for token in hostDir/persist created token in hostDir so it's not regenerated on startup + const newToken = uuid(); + + logger.warn( + "TOKEN variable not provided, using this value instead: %s", + newToken + ); + logger.warn( + "Use this provided token to push your coverage reports to the server." + ); + + return newToken; +}; + export const configOrError = (varName: string): string => { const value = process.env[varName]; if (value !== undefined) { @@ -58,9 +74,7 @@ export const handleStartup = async ( await Promise.reject("hostDir must be an absolute path"); } - const mongo = await MongoClient.connect(mongoUri, { - useUnifiedTopology: true - }).catch((err: MongoError) => + const mongo = await MongoClient.connect(mongoUri).catch((err: MongoError) => Promise.reject(err.message ?? "Unable to connect to database") ); -- cgit