From e1fd389c6098becb1ccb34e72feddeefd35bb64f Mon Sep 17 00:00:00 2001 From: Chris Wilkinson Date: Mon, 6 Jan 2025 16:07:33 +0000 Subject: [PATCH] Redact a secret Note the key is used as part of the URL so it's currently still logged. Refs #1834 --- integration/base.ts | 2 +- src/ghost.ts | 10 ++++++---- src/index.ts | 2 +- test/AboutUsPage/AboutUsPage.test.ts | 6 +++--- test/clubs.test.ts | 5 +++-- test/code-of-conduct.test.ts | 5 +++-- test/edia-statement.test.ts | 5 +++-- test/funding.test.ts | 5 +++-- test/ghost.test.ts | 19 ++++++++++--------- test/how-to-use.test.ts | 5 +++-- test/live-reviews.test.ts | 5 +++-- test/people.test.ts | 5 +++-- test/privacy-policy.test.ts | 5 +++-- test/resources.test.ts | 5 +++-- test/trainings.test.ts | 5 +++-- 15 files changed, 51 insertions(+), 38 deletions(-) diff --git a/integration/base.ts b/integration/base.ts index 827b10eca..1d584442e 100644 --- a/integration/base.ts +++ b/integration/base.ts @@ -1321,7 +1321,7 @@ const appFixtures: Fixtures, PlaywrightTestArg useCrowdinInContext: false, }), ), - Effect.provideService(GhostApi, { key: 'key' }), + Effect.provideService(GhostApi, { key: Redacted.make('key') }), Effect.provide(Nodemailer.layer(nodemailer)), Effect.provideService(PublicUrl, new URL(`http://localhost:${port}`)), Effect.provideService(SessionSecret, Redacted.make('')), diff --git a/src/ghost.ts b/src/ghost.ts index 08dfd1d71..24e9194ce 100644 --- a/src/ghost.ts +++ b/src/ghost.ts @@ -1,5 +1,5 @@ import { FetchHttpClient, HttpClient, HttpClientResponse } from '@effect/platform' -import { Context, Data, Effect, flow, identity, Match, Schema } from 'effect' +import { Context, Data, Effect, flow, identity, Match, Redacted, Schema } from 'effect' import type * as F from 'fetch-fp-ts' import * as E from 'fp-ts/lib/Either.js' import * as R from 'fp-ts/lib/Reader.js' @@ -11,7 +11,7 @@ import { type Html, rawHtml, sanitizeHtml } from './html.js' export interface GhostApiEnv { ghostApi: { - key: string + key: Redacted.Redacted } } @@ -50,7 +50,7 @@ export const getPage = ( ), ) -export class GhostApi extends Context.Tag('GhostApi')() {} +export class GhostApi extends Context.Tag('GhostApi')() {} class GhostPageNotFound extends Data.TaggedError('GhostPageNotFound') {} @@ -62,7 +62,9 @@ const getPageWithEffect = (id: string) => const ghostApi = yield* GhostApi return yield* pipe( - client.get(new URL(`https://content.prereview.org/ghost/api/content/pages/${id}?key=${ghostApi.key}`)), + client.get( + new URL(`https://content.prereview.org/ghost/api/content/pages/${id}?key=${Redacted.value(ghostApi.key)}`), + ), Effect.filterOrFail(response => response.status === 200, identity), Effect.andThen(HttpClientResponse.schemaBodyJson(GhostPageSchema)), Effect.scoped, diff --git a/src/index.ts b/src/index.ts index 6066017c3..ec3222635 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,7 +45,7 @@ pipe( Layer.scopedDiscard(Effect.addFinalizer(() => Effect.logDebug('Database disconnected'))), ), ), - Effect.provideServiceEffect(GhostApi, Config.all({ key: Config.string('GHOST_API_KEY') })), + Effect.provideServiceEffect(GhostApi, Config.all({ key: Config.redacted('GHOST_API_KEY') })), Effect.provide(Nodemailer.layerConfig(Config.redacted(Config.url('SMTP_URI')))), Effect.provide(Redis.layerConfig(Config.redacted(Config.url('REDIS_URI')))), Effect.provideServiceEffect( diff --git a/test/AboutUsPage/AboutUsPage.test.ts b/test/AboutUsPage/AboutUsPage.test.ts index e8d01c373..ceec3a699 100644 --- a/test/AboutUsPage/AboutUsPage.test.ts +++ b/test/AboutUsPage/AboutUsPage.test.ts @@ -1,7 +1,7 @@ import { FetchHttpClient } from '@effect/platform' import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' -import { Effect, pipe, TestContext } from 'effect' +import { Effect, pipe, Redacted, TestContext } from 'effect' import fetchMock from 'fetch-mock' import { Status } from 'hyper-ts' import * as _ from '../../src/AboutUsPage/index.js' @@ -40,7 +40,7 @@ describe('AboutUsPage', () => { }) }).pipe( Effect.provideService(Locale, locale), - Effect.provideService(GhostApi, { key }), + Effect.provideService(GhostApi, { key: Redacted.make(key) }), Effect.provide(TestContext.TestContext), Effect.runPromise, ), @@ -74,7 +74,7 @@ describe('AboutUsPage', () => { expect(fetch.done()).toBeTruthy() }).pipe( Effect.provideService(Locale, locale), - Effect.provideService(GhostApi, { key }), + Effect.provideService(GhostApi, { key: Redacted.make(key) }), Effect.provide(TestContext.TestContext), Effect.runPromise, ), diff --git a/test/clubs.test.ts b/test/clubs.test.ts index 932109875..a8d171acd 100644 --- a/test/clubs.test.ts +++ b/test/clubs.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('clubs', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.clubs({ fetch, ghostApi: { key } })() + const actual = await _.clubs({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('clubs', () => { response, ) - const actual = await _.clubs({ fetch, ghostApi: { key } })() + const actual = await _.clubs({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/code-of-conduct.test.ts b/test/code-of-conduct.test.ts index 3137967f7..868e41073 100644 --- a/test/code-of-conduct.test.ts +++ b/test/code-of-conduct.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('codeOfConduct', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.codeOfConduct({ fetch, ghostApi: { key } })() + const actual = await _.codeOfConduct({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('codeOfConduct', () => { response, ) - const actual = await _.codeOfConduct({ fetch, ghostApi: { key } })() + const actual = await _.codeOfConduct({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/edia-statement.test.ts b/test/edia-statement.test.ts index b679091a4..ff4f36b19 100644 --- a/test/edia-statement.test.ts +++ b/test/edia-statement.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('ediaStatement', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.ediaStatement({ fetch, ghostApi: { key } })() + const actual = await _.ediaStatement({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('ediaStatement', () => { response, ) - const actual = await _.ediaStatement({ fetch, ghostApi: { key } })() + const actual = await _.ediaStatement({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/funding.test.ts b/test/funding.test.ts index 13a4ee5f6..dea81848c 100644 --- a/test/funding.test.ts +++ b/test/funding.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('funding', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.funding({ fetch, ghostApi: { key } })() + const actual = await _.funding({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('funding', () => { response, ) - const actual = await _.funding({ fetch, ghostApi: { key } })() + const actual = await _.funding({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/ghost.test.ts b/test/ghost.test.ts index 917b413a7..7c9474290 100644 --- a/test/ghost.test.ts +++ b/test/ghost.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import * as E from 'fp-ts/lib/Either.js' import { Status } from 'hyper-ts' @@ -20,7 +21,7 @@ describe('getPage', () => { { url: `https://content.prereview.org/ghost/api/content/pages/${id}`, query: { key } }, { body: { pages: [{ html: html.toString() }] } }, ), - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.right(html)) @@ -43,7 +44,7 @@ describe('getPage', () => { }, }, ), - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual( @@ -72,7 +73,7 @@ describe('getPage', () => { }, }, ), - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual( @@ -101,7 +102,7 @@ describe('getPage', () => { }, }, ), - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.right(rawHtml('Donate'))) @@ -124,7 +125,7 @@ describe('getPage', () => { }, }, ), - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.right(rawHtml('

Some heading

'))) @@ -141,7 +142,7 @@ describe('getPage', () => { const actual = await _.getPage(id)({ fetch, - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.left('unavailable')) @@ -158,7 +159,7 @@ describe('getPage', () => { const actual = await _.getPage(id)({ fetch, - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.left('not-found')) @@ -175,7 +176,7 @@ describe('getPage', () => { const actual = await _.getPage(id)({ fetch, - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.left('unavailable')) @@ -189,7 +190,7 @@ describe('getPage', () => { ])('when fetch throws an error', async (id, key, error) => { const actual = await _.getPage(id)({ fetch: () => Promise.reject(error), - ghostApi: { key }, + ghostApi: { key: Redacted.make(key) }, })() expect(actual).toStrictEqual(E.left('unavailable')) diff --git a/test/how-to-use.test.ts b/test/how-to-use.test.ts index 8af1df187..10aaa8d3b 100644 --- a/test/how-to-use.test.ts +++ b/test/how-to-use.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('howToUse', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.howToUse({ fetch, ghostApi: { key } })() + const actual = await _.howToUse({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('howToUse', () => { response, ) - const actual = await _.howToUse({ fetch, ghostApi: { key } })() + const actual = await _.howToUse({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/live-reviews.test.ts b/test/live-reviews.test.ts index 9a8e2c083..27b0d7fd4 100644 --- a/test/live-reviews.test.ts +++ b/test/live-reviews.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('liveReviews', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.liveReviews({ fetch, ghostApi: { key } })() + const actual = await _.liveReviews({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('liveReviews', () => { response, ) - const actual = await _.liveReviews({ fetch, ghostApi: { key } })() + const actual = await _.liveReviews({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/people.test.ts b/test/people.test.ts index b0dd3b61f..21c0b1c78 100644 --- a/test/people.test.ts +++ b/test/people.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('people', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.people({ fetch, ghostApi: { key } })() + const actual = await _.people({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('people', () => { response, ) - const actual = await _.people({ fetch, ghostApi: { key } })() + const actual = await _.people({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/privacy-policy.test.ts b/test/privacy-policy.test.ts index 63b10841f..231b235a8 100644 --- a/test/privacy-policy.test.ts +++ b/test/privacy-policy.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('privacyPolicy', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.privacyPolicy({ fetch, ghostApi: { key } })() + const actual = await _.privacyPolicy({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('privacyPolicy', () => { response, ) - const actual = await _.privacyPolicy({ fetch, ghostApi: { key } })() + const actual = await _.privacyPolicy({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/resources.test.ts b/test/resources.test.ts index 5d1a686a1..cf8928b6f 100644 --- a/test/resources.test.ts +++ b/test/resources.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('resources', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.resources({ fetch, ghostApi: { key } })() + const actual = await _.resources({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('resources', () => { response, ) - const actual = await _.resources({ fetch, ghostApi: { key } })() + const actual = await _.resources({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', diff --git a/test/trainings.test.ts b/test/trainings.test.ts index 90a7aa053..45834f26e 100644 --- a/test/trainings.test.ts +++ b/test/trainings.test.ts @@ -1,5 +1,6 @@ import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Redacted } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' @@ -17,7 +18,7 @@ describe('trainings', () => { { body: { pages: [{ html: '

Foo

' }] } }, ) - const actual = await _.trainings({ fetch, ghostApi: { key } })() + const actual = await _.trainings({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse', @@ -42,7 +43,7 @@ describe('trainings', () => { response, ) - const actual = await _.trainings({ fetch, ghostApi: { key } })() + const actual = await _.trainings({ fetch, ghostApi: { key: Redacted.make(key) } })() expect(actual).toStrictEqual({ _tag: 'PageResponse',