From afce40bd7f53b3f227512c49dceb20bf51033aac Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 25 May 2023 00:27:45 +0200 Subject: [PATCH 1/3] remove file based versioning clients --- .../src/federation/client/FederationClient.ts | 55 ------------------- .../federation/client/FederationClient_1_0.ts | 48 ---------------- .../federation/client/FederationClient_1_1.ts | 3 - 3 files changed, 106 deletions(-) delete mode 100644 backend/src/federation/client/FederationClient.ts delete mode 100644 backend/src/federation/client/FederationClient_1_0.ts delete mode 100644 backend/src/federation/client/FederationClient_1_1.ts diff --git a/backend/src/federation/client/FederationClient.ts b/backend/src/federation/client/FederationClient.ts deleted file mode 100644 index db1e5e3b2..000000000 --- a/backend/src/federation/client/FederationClient.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' - -import { ApiVersionType } from '@/federation/enum/apiVersionType' - -import { FederationClient_1_0 } from './FederationClient_1_0' -import { FederationClient_1_1 } from './FederationClient_1_1' - -type FederationClientType = FederationClient_1_0 | FederationClient_1_1 - -interface ClientInstance { - id: number - // eslint-disable-next-line no-use-before-define - client: FederationClientType -} - -// eslint-disable-next-line @typescript-eslint/no-extraneous-class -export class FederationClient { - private static instanceArray: ClientInstance[] = [] - - /** - * The Singleton's constructor should always be private to prevent direct - * construction calls with the `new` operator. - */ - // eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function - private constructor() {} - - private static createFederationClient = (dbCom: DbFederatedCommunity) => { - switch (dbCom.apiVersion) { - case ApiVersionType.V1_0: - return new FederationClient_1_0(dbCom) - case ApiVersionType.V1_1: - return new FederationClient_1_1(dbCom) - default: - return null - } - } - - /** - * The static method that controls the access to the singleton instance. - * - * This implementation let you subclass the Singleton class while keeping - * just one instance of each subclass around. - */ - public static getInstance(dbCom: DbFederatedCommunity): FederationClientType | null { - const instance = FederationClient.instanceArray.find((instance) => instance.id === dbCom.id) - if (instance) { - return instance.client - } - const client = FederationClient.createFederationClient(dbCom) - if (client) { - FederationClient.instanceArray.push({ id: dbCom.id, client } as ClientInstance) - } - return client - } -} diff --git a/backend/src/federation/client/FederationClient_1_0.ts b/backend/src/federation/client/FederationClient_1_0.ts deleted file mode 100644 index c8e878ded..000000000 --- a/backend/src/federation/client/FederationClient_1_0.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' -import { GraphQLClient } from 'graphql-request' - -import { getPublicKey } from '@/federation/query/getPublicKey' -import { backendLogger as logger } from '@/server/logger' - -export class FederationClient_1_0 { - dbCom: DbFederatedCommunity - endpoint: string - client: GraphQLClient - - constructor(dbCom: DbFederatedCommunity) { - this.dbCom = dbCom - this.endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${ - dbCom.apiVersion - }/` - this.client = new GraphQLClient(this.endpoint, { - method: 'GET', - jsonSerializer: { - parse: JSON.parse, - stringify: JSON.stringify, - }, - }) - } - - getPublicKey = async (): Promise => { - logger.info('Federation: getPublicKey from endpoint', this.endpoint) - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(getPublicKey, {}) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (!data?.getPublicKey?.publicKey) { - logger.warn('Federation: getPublicKey without response data from endpoint', this.endpoint) - return - } - logger.info( - 'Federation: getPublicKey successful from endpoint', - this.endpoint, - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - data.getPublicKey.publicKey, - ) - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access - return data.getPublicKey.publicKey - } catch (err) { - logger.warn('Federation: getPublicKey failed for endpoint', this.endpoint) - } - } -} diff --git a/backend/src/federation/client/FederationClient_1_1.ts b/backend/src/federation/client/FederationClient_1_1.ts deleted file mode 100644 index 27679b423..000000000 --- a/backend/src/federation/client/FederationClient_1_1.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { FederationClient_1_0 } from './FederationClient_1_0' - -export class FederationClient_1_1 extends FederationClient_1_0 {} From fc822332dc83e74a5f5d9d342b9785449e3d623e Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 25 May 2023 01:52:07 +0200 Subject: [PATCH 2/3] shift query in 1_0-directory --- backend/src/federation/client/1_0/FederationClient.ts | 2 +- backend/src/federation/{ => client/1_0}/query/getPublicKey.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename backend/src/federation/{ => client/1_0}/query/getPublicKey.ts (100%) diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts index bbd97300e..ba446abe8 100644 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ b/backend/src/federation/client/1_0/FederationClient.ts @@ -1,7 +1,7 @@ import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' import { GraphQLClient } from 'graphql-request' -import { getPublicKey } from '@/federation/query/getPublicKey' +import { getPublicKey } from '@/federation/client/1_0/query/getPublicKey' import { backendLogger as logger } from '@/server/logger' // eslint-disable-next-line camelcase diff --git a/backend/src/federation/query/getPublicKey.ts b/backend/src/federation/client/1_0/query/getPublicKey.ts similarity index 100% rename from backend/src/federation/query/getPublicKey.ts rename to backend/src/federation/client/1_0/query/getPublicKey.ts From 7d5b8b9b626bfad65f5a51b2a2fb26a488122746 Mon Sep 17 00:00:00 2001 From: Claus-Peter Huebner Date: Thu, 25 May 2023 01:52:42 +0200 Subject: [PATCH 3/3] additional test with matching pubKey --- .../federation/validateCommunities.test.ts | 73 +++++++++++++++++-- backend/src/federation/validateCommunities.ts | 2 +- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/backend/src/federation/validateCommunities.test.ts b/backend/src/federation/validateCommunities.test.ts index 16f396260..834f37e16 100644 --- a/backend/src/federation/validateCommunities.test.ts +++ b/backend/src/federation/validateCommunities.test.ts @@ -59,7 +59,7 @@ describe('validate Communities', () => { expect(logger.debug).toBeCalledWith(`Federation: found 0 dbCommunities`) }) - describe('with one Community of api 1_0', () => { + describe('with one Community of api 1_0 and not matching pubKey', () => { beforeEach(async () => { // eslint-disable-next-line @typescript-eslint/require-await jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => { @@ -73,7 +73,9 @@ describe('validate Communities', () => { } as Response }) const variables1 = { - publicKey: Buffer.from('11111111111111111111111111111111'), + publicKey: Buffer.from( + '1111111111111111111111111111111111111111111111111111111111111111', + ), apiVersion: '1_0', endPoint: 'http//localhost:5001/api/', lastAnnouncedAt: new Date(), @@ -106,7 +108,60 @@ describe('validate Communities', () => { expect(logger.warn).toBeCalledWith( 'Federation: received not matching publicKey:', 'somePubKey', - expect.stringMatching('11111111111111111111111111111111'), + expect.stringMatching('1111111111111111111111111111111111111111111111111111111111111111'), + ) + }) + }) + describe('with one Community of api 1_0 and matching pubKey', () => { + beforeEach(async () => { + // eslint-disable-next-line @typescript-eslint/require-await + jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return { + data: { + getPublicKey: { + publicKey: '1111111111111111111111111111111111111111111111111111111111111111', + }, + }, + } as Response + }) + const variables1 = { + publicKey: Buffer.from( + '1111111111111111111111111111111111111111111111111111111111111111', + ), + apiVersion: '1_0', + endPoint: 'http//localhost:5001/api/', + lastAnnouncedAt: new Date(), + } + await DbFederatedCommunity.createQueryBuilder() + .insert() + .into(DbFederatedCommunity) + .values(variables1) + .orUpdate({ + // eslint-disable-next-line camelcase + conflict_target: ['id', 'publicKey', 'apiVersion'], + overwrite: ['end_point', 'last_announced_at'], + }) + .execute() + await DbFederatedCommunity.update({}, { verifiedAt: null }) + jest.clearAllMocks() + await validateCommunities() + }) + + it('logs one community found', () => { + expect(logger.debug).toBeCalledWith(`Federation: found 1 dbCommunities`) + }) + it('logs requestGetPublicKey for community api 1_0 ', () => { + expect(logger.info).toBeCalledWith( + 'Federation: getPublicKey from endpoint', + 'http//localhost:5001/api/1_0/', + ) + }) + it('logs community pubKey verified', () => { + expect(logger.info).toHaveBeenNthCalledWith( + 3, + 'Federation: verified community with', + 'http//localhost:5001/api/', ) }) }) @@ -119,13 +174,15 @@ describe('validate Communities', () => { return { data: { getPublicKey: { - publicKey: '11111111111111111111111111111111', + publicKey: '1111111111111111111111111111111111111111111111111111111111111111', }, }, } as Response }) const variables2 = { - publicKey: Buffer.from('11111111111111111111111111111111'), + publicKey: Buffer.from( + '1111111111111111111111111111111111111111111111111111111111111111', + ), apiVersion: '1_1', endPoint: 'http//localhost:5001/api/', lastAnnouncedAt: new Date(), @@ -141,6 +198,7 @@ describe('validate Communities', () => { }) .execute() + await DbFederatedCommunity.update({}, { verifiedAt: null }) jest.clearAllMocks() await validateCommunities() }) @@ -164,7 +222,9 @@ describe('validate Communities', () => { let dbCom: DbFederatedCommunity beforeEach(async () => { const variables3 = { - publicKey: Buffer.from('11111111111111111111111111111111'), + publicKey: Buffer.from( + '1111111111111111111111111111111111111111111111111111111111111111', + ), apiVersion: '2_0', endPoint: 'http//localhost:5001/api/', lastAnnouncedAt: new Date(), @@ -182,6 +242,7 @@ describe('validate Communities', () => { dbCom = await DbFederatedCommunity.findOneOrFail({ where: { publicKey: variables3.publicKey, apiVersion: variables3.apiVersion }, }) + await DbFederatedCommunity.update({}, { verifiedAt: null }) jest.clearAllMocks() await validateCommunities() }) diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 8a73fd536..91c6ee724 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -45,7 +45,7 @@ export async function validateCommunities(): Promise { const pubKey = await client.getPublicKey() if (pubKey && pubKey === dbCom.publicKey.toString()) { await DbFederatedCommunity.update({ id: dbCom.id }, { verifiedAt: new Date() }) - logger.info('Federation: verified community', dbCom) + logger.info('Federation: verified community with', dbCom.endPoint) } else { logger.warn( 'Federation: received not matching publicKey:',