From 870c97ce71231febd4ab4781eb51c8b6271a6f90 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 3 May 2023 13:02:32 +0200 Subject: [PATCH 01/20] rfactor federation clients --- .../federation/client/1_0/FederationClient.ts | 42 -------------- .../federation/client/1_1/FederationClient.ts | 42 -------------- backend/src/federation/client/Client.ts | 57 +++++++++++++++++++ backend/src/federation/client/Client_1_0.ts | 54 ++++++++++++++++++ backend/src/federation/client/Client_1_1.ts | 5 ++ .../src/federation/client/GraphQLGetClient.ts | 43 -------------- backend/src/federation/validateCommunities.ts | 18 +----- 7 files changed, 118 insertions(+), 143 deletions(-) delete mode 100644 backend/src/federation/client/1_0/FederationClient.ts delete mode 100644 backend/src/federation/client/1_1/FederationClient.ts create mode 100644 backend/src/federation/client/Client.ts create mode 100644 backend/src/federation/client/Client_1_0.ts create mode 100644 backend/src/federation/client/Client_1_1.ts delete mode 100644 backend/src/federation/client/GraphQLGetClient.ts diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts deleted file mode 100644 index 13f05e761..000000000 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import { Community as DbCommunity } from '@entity/Community' -import { gql } from 'graphql-request' - -import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient' -import { LogError } from '@/server/LogError' -import { backendLogger as logger } from '@/server/logger' - -export async function requestGetPublicKey(dbCom: DbCommunity): Promise { - let endpoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/' - endpoint = `${endpoint}${dbCom.apiVersion}/` - logger.info(`requestGetPublicKey with endpoint='${endpoint}'...`) - - const graphQLClient = GraphQLGetClient.getInstance(endpoint) - logger.debug(`graphQLClient=${JSON.stringify(graphQLClient)}`) - const query = gql` - query { - getPublicKey { - publicKey - } - } - ` - const variables = {} - - try { - const { data, errors, extensions, headers, status } = await graphQLClient.rawRequest( - query, - variables, - ) - logger.debug(`Response-Data:`, data, errors, extensions, headers, status) - if (data) { - logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey) - logger.info(`requestGetPublicKey processed successfully`) - return data.getPublicKey.publicKey - } - logger.warn(`requestGetPublicKey processed without response data`) - } catch (err) { - throw new LogError(`Request-Error:`, err) - } -} diff --git a/backend/src/federation/client/1_1/FederationClient.ts b/backend/src/federation/client/1_1/FederationClient.ts deleted file mode 100644 index bda185fba..000000000 --- a/backend/src/federation/client/1_1/FederationClient.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import { Community as DbCommunity } from '@entity/Community' -import { gql } from 'graphql-request' - -import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient' -import { LogError } from '@/server/LogError' -import { backendLogger as logger } from '@/server/logger' - -export async function requestGetPublicKey(dbCom: DbCommunity): Promise { - let endpoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/' - endpoint = `${endpoint}${dbCom.apiVersion}/` - logger.info(`requestGetPublicKey with endpoint='${endpoint}'...`) - - const graphQLClient = GraphQLGetClient.getInstance(endpoint) - logger.debug(`graphQLClient=${JSON.stringify(graphQLClient)}`) - const query = gql` - query { - getPublicKey { - publicKey - } - } - ` - const variables = {} - - try { - const { data, errors, extensions, headers, status } = await graphQLClient.rawRequest( - query, - variables, - ) - logger.debug(`Response-Data:`, data, errors, extensions, headers, status) - if (data) { - logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey) - logger.info(`requestGetPublicKey processed successfully`) - return data.getPublicKey.publicKey - } - logger.warn(`requestGetPublicKey processed without response data`) - } catch (err) { - throw new LogError(`Request-Error:`, err) - } -} diff --git a/backend/src/federation/client/Client.ts b/backend/src/federation/client/Client.ts new file mode 100644 index 000000000..e285b591c --- /dev/null +++ b/backend/src/federation/client/Client.ts @@ -0,0 +1,57 @@ +import { Community as DbCommunity } from '@entity/Community' + +import { ApiVersionType } from '@/federation/enum/apiVersionType' + +// eslint-disable-next-line camelcase +import { Client_1_0 } from './Client_1_0' +// eslint-disable-next-line camelcase +import { Client_1_1 } from './Client_1_1' + +// eslint-disable-next-line camelcase +type FederationClient = Client_1_0 | Client_1_1 + +type ClientInstance = { + dbCom: DbCommunity + // eslint-disable-next-line no-use-before-define + client: FederationClient +} + +export class Client { + 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: DbCommunity) => { + switch (dbCom.apiVersion) { + case ApiVersionType.V1_0: + return new Client_1_0(dbCom) + case ApiVersionType.V1_1: + return new Client_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: DbCommunity): FederationClient | null { + const instance = Client.instanceArray.find((instance) => instance.dbCom === dbCom) + if (instance) { + return instance.client + } + const client = Client.createFederationClient(dbCom) + if (client) { + Client.instanceArray.push({ dbCom, client } as ClientInstance) + } + return client + } +} diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts new file mode 100644 index 000000000..6adfaa48c --- /dev/null +++ b/backend/src/federation/client/Client_1_0.ts @@ -0,0 +1,54 @@ +import { Community as DbCommunity } from '@entity/Community' +import { GraphQLClient, gql } from 'graphql-request' + +import { LogError } from '@/server/LogError' +import { backendLogger as logger } from '@/server/logger' + +// eslint-disable-next-line camelcase +export class Client_1_0 { + dbCom: DbCommunity + endpoint: string + client: GraphQLClient + + constructor(dbCom: DbCommunity) { + 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, + }, + }) + } + + requestGetPublicKey = async (): Promise => { + logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) + + const query = gql` + query { + getPublicKey { + publicKey + } + } + ` + + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const { data, errors, headers, status } = await this.client.rawRequest(query) + logger.debug(`Response-Data:`, data, errors, headers, status) + if (data) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey) + logger.info(`requestGetPublicKey processed successfully`) + // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access + return data.getPublicKey.publicKey + } + logger.warn(`requestGetPublicKey processed without response data`) + } catch (err) { + throw new LogError(`Request-Error:`, err) + } + } +} diff --git a/backend/src/federation/client/Client_1_1.ts b/backend/src/federation/client/Client_1_1.ts new file mode 100644 index 000000000..8525acc5d --- /dev/null +++ b/backend/src/federation/client/Client_1_1.ts @@ -0,0 +1,5 @@ +// eslint-disable-next-line camelcase +import { Client_1_0 } from './Client_1_0' + +// eslint-disable-next-line camelcase +export class Client_1_1 extends Client_1_0 {} diff --git a/backend/src/federation/client/GraphQLGetClient.ts b/backend/src/federation/client/GraphQLGetClient.ts deleted file mode 100644 index 2f5281532..000000000 --- a/backend/src/federation/client/GraphQLGetClient.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { GraphQLClient } from 'graphql-request' -import { PatchedRequestInit } from 'graphql-request/dist/types' - -type ClientInstance = { - url: string - // eslint-disable-next-line no-use-before-define - client: GraphQLGetClient -} - -export class GraphQLGetClient extends GraphQLClient { - 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 - private constructor(url: string, options?: PatchedRequestInit) { - super(url, options) - } - - /** - * 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(url: string): GraphQLGetClient { - const instance = GraphQLGetClient.instanceArray.find((instance) => instance.url === url) - if (instance) { - return instance.client - } - const client = new GraphQLGetClient(url, { - method: 'GET', - jsonSerializer: { - parse: JSON.parse, - stringify: JSON.stringify, - }, - }) - GraphQLGetClient.instanceArray.push({ url, client } as ClientInstance) - return client - } -} diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 0e8c7cb12..11406199d 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -4,10 +4,7 @@ import { Community as DbCommunity } from '@entity/Community' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' -// eslint-disable-next-line camelcase -import { requestGetPublicKey as v1_0_requestGetPublicKey } from './client/1_0/FederationClient' -// eslint-disable-next-line camelcase -import { requestGetPublicKey as v1_1_requestGetPublicKey } from './client/1_1/FederationClient' +import { Client } from './client/Client' import { ApiVersionType } from './enum/apiVersionType' export function startValidateCommunities(timerInterval: number): void { @@ -38,7 +35,7 @@ export async function validateCommunities(): Promise { `Federation: validate publicKey for dbCom: ${dbCom.id} with apiVersion=${dbCom.apiVersion}`, ) try { - const pubKey = await invokeVersionedRequestGetPublicKey(dbCom) + const pubKey = await Client.getInstance(dbCom)?.requestGetPublicKey() logger.info( 'Federation: received publicKey from endpoint', pubKey, @@ -73,14 +70,3 @@ export async function validateCommunities(): Promise { function isLogError(err: unknown) { return err instanceof LogError } - -async function invokeVersionedRequestGetPublicKey(dbCom: DbCommunity): Promise { - switch (dbCom.apiVersion) { - case ApiVersionType.V1_0: - return v1_0_requestGetPublicKey(dbCom) - case ApiVersionType.V1_1: - return v1_1_requestGetPublicKey(dbCom) - default: - return undefined - } -} From d3a2df2878d9f2ebdcce8c8018672f08a76ac133 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 3 May 2023 13:03:27 +0200 Subject: [PATCH 02/20] remove obsolete function --- backend/src/federation/validateCommunities.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 11406199d..dfd14bdac 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -54,7 +54,7 @@ export async function validateCommunities(): Promise { // DbCommunity.delete({ id: dbCom.id }) } } catch (err) { - if (!isLogError(err)) { + if (!(err instanceof LogError)) { logger.error(`Error:`, err) } } @@ -66,7 +66,3 @@ export async function validateCommunities(): Promise { } } } - -function isLogError(err: unknown) { - return err instanceof LogError -} From 4850923f17078a81d31ffee2b35dfda14e706751 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 3 May 2023 13:29:56 +0200 Subject: [PATCH 03/20] variables must be defined --- backend/src/federation/client/Client_1_0.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 6adfaa48c..efbe497c8 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -35,9 +35,11 @@ export class Client_1_0 { } ` + const variables = {} + try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data, errors, headers, status } = await this.client.rawRequest(query) + const { data, errors, headers, status } = await this.client.rawRequest(query, variables) logger.debug(`Response-Data:`, data, errors, headers, status) if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access From 1c6142220f5b86a23fc35cbee2631f9855e07730 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 01:40:50 +0200 Subject: [PATCH 04/20] rename getPublicKey function --- backend/src/federation/client/Client_1_0.ts | 2 +- backend/src/federation/validateCommunities.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index efbe497c8..9ce3b6b12 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -24,7 +24,7 @@ export class Client_1_0 { }) } - requestGetPublicKey = async (): Promise => { + getPublicKey = async (): Promise => { logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) const query = gql` diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index dfd14bdac..14bf4dd3d 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -35,7 +35,7 @@ export async function validateCommunities(): Promise { `Federation: validate publicKey for dbCom: ${dbCom.id} with apiVersion=${dbCom.apiVersion}`, ) try { - const pubKey = await Client.getInstance(dbCom)?.requestGetPublicKey() + const pubKey = await Client.getInstance(dbCom)?.getPublicKey() logger.info( 'Federation: received publicKey from endpoint', pubKey, From 81552e51ddd50949ffa26efb7470e721a9d93c26 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 01:51:36 +0200 Subject: [PATCH 05/20] properly reuse graphql client --- backend/src/federation/client/Client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/federation/client/Client.ts b/backend/src/federation/client/Client.ts index e285b591c..a33cb4832 100644 --- a/backend/src/federation/client/Client.ts +++ b/backend/src/federation/client/Client.ts @@ -11,7 +11,7 @@ import { Client_1_1 } from './Client_1_1' type FederationClient = Client_1_0 | Client_1_1 type ClientInstance = { - dbCom: DbCommunity + id: number // eslint-disable-next-line no-use-before-define client: FederationClient } @@ -44,13 +44,13 @@ export class Client { * just one instance of each subclass around. */ public static getInstance(dbCom: DbCommunity): FederationClient | null { - const instance = Client.instanceArray.find((instance) => instance.dbCom === dbCom) + const instance = Client.instanceArray.find((instance) => instance.id === dbCom.id) if (instance) { return instance.client } const client = Client.createFederationClient(dbCom) if (client) { - Client.instanceArray.push({ dbCom, client } as ClientInstance) + Client.instanceArray.push({ id: dbCom.id, client } as ClientInstance) } return client } From 1fa33963966fbb0185e5e530242d544ac883410c Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 01:55:14 +0200 Subject: [PATCH 06/20] externalize the graphql query --- backend/src/federation/client/Client_1_0.ts | 16 ++++++---------- backend/src/federation/query/getPublicKey.ts | 9 +++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 backend/src/federation/query/getPublicKey.ts diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 9ce3b6b12..b0fb825ee 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -1,6 +1,7 @@ import { Community as DbCommunity } from '@entity/Community' -import { GraphQLClient, gql } from 'graphql-request' +import { GraphQLClient } from 'graphql-request' +import { getPublicKey } from '@/federation/query/getPublicKey' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' @@ -27,19 +28,14 @@ export class Client_1_0 { getPublicKey = async (): Promise => { logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) - const query = gql` - query { - getPublicKey { - publicKey - } - } - ` - const variables = {} try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data, errors, headers, status } = await this.client.rawRequest(query, variables) + const { data, errors, headers, status } = await this.client.rawRequest( + getPublicKey, + variables, + ) logger.debug(`Response-Data:`, data, errors, headers, status) if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access diff --git a/backend/src/federation/query/getPublicKey.ts b/backend/src/federation/query/getPublicKey.ts new file mode 100644 index 000000000..a772a0cf1 --- /dev/null +++ b/backend/src/federation/query/getPublicKey.ts @@ -0,0 +1,9 @@ +import { gql } from 'graphql-request' + +export const getPublicKey = gql` + query { + getPublicKey { + publicKey + } + } +` From d636f922618b62bc352806a08cbbc1153566a164 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 01:57:43 +0200 Subject: [PATCH 07/20] fix problem in federation when variables are not defined --- backend/src/federation/client/Client_1_0.ts | 6 +----- federation/src/server/plugins.ts | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index b0fb825ee..df239db92 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -27,14 +27,10 @@ export class Client_1_0 { getPublicKey = async (): Promise => { logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) - - const variables = {} - try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { data, errors, headers, status } = await this.client.rawRequest( - getPublicKey, - variables, + getPublicKey ) logger.debug(`Response-Data:`, data, errors, headers, status) if (data) { diff --git a/federation/src/server/plugins.ts b/federation/src/server/plugins.ts index 541c68ca2..38fdfbe9f 100644 --- a/federation/src/server/plugins.ts +++ b/federation/src/server/plugins.ts @@ -23,8 +23,8 @@ const setHeadersPlugin = { const filterVariables = (variables: any) => { const vars = clonedeep(variables) - if (vars.password) vars.password = '***' - if (vars.passwordNew) vars.passwordNew = '***' + if (vars && vars.password) vars.password = '***' + if (vars && vars.passwordNew) vars.passwordNew = '***' return vars } From 950ff2f9b680e29e79c5d4a8e415e2e212f3be23 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 02:01:45 +0200 Subject: [PATCH 08/20] lint --- backend/src/federation/client/Client_1_0.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index df239db92..317306048 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -29,9 +29,7 @@ export class Client_1_0 { logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data, errors, headers, status } = await this.client.rawRequest( - getPublicKey - ) + const { data, errors, headers, status } = await this.client.rawRequest(getPublicKey) logger.debug(`Response-Data:`, data, errors, headers, status) if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access From 0a6c29bca3012f5e763cd69bd24fb2b67db64e8e Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 11:28:53 +0200 Subject: [PATCH 09/20] variables must be transmitted due to backward compatibility --- backend/src/federation/client/Client_1_0.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 317306048..d425ccea1 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -29,7 +29,7 @@ export class Client_1_0 { logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data, errors, headers, status } = await this.client.rawRequest(getPublicKey) + const { data, errors, headers, status } = await this.client.rawRequest(getPublicKey, {}) logger.debug(`Response-Data:`, data, errors, headers, status) if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access From 2d03ae938ab7d05dfa449b09f0cd376481a08ad5 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 22:50:06 +0200 Subject: [PATCH 10/20] merge conflict --- backend/src/federation/client/Client.ts | 6 +++--- backend/src/federation/client/Client_1_0.ts | 6 +++--- backend/src/federation/validateCommunities.ts | 13 ------------- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/backend/src/federation/client/Client.ts b/backend/src/federation/client/Client.ts index a33cb4832..515945eb5 100644 --- a/backend/src/federation/client/Client.ts +++ b/backend/src/federation/client/Client.ts @@ -1,4 +1,4 @@ -import { Community as DbCommunity } from '@entity/Community' +import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' import { ApiVersionType } from '@/federation/enum/apiVersionType' @@ -26,7 +26,7 @@ export class Client { // eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function private constructor() {} - private static createFederationClient = (dbCom: DbCommunity) => { + private static createFederationClient = (dbCom: DbFederatedCommunity) => { switch (dbCom.apiVersion) { case ApiVersionType.V1_0: return new Client_1_0(dbCom) @@ -43,7 +43,7 @@ export class Client { * This implementation let you subclass the Singleton class while keeping * just one instance of each subclass around. */ - public static getInstance(dbCom: DbCommunity): FederationClient | null { + public static getInstance(dbCom: DbFederatedCommunity): FederationClient | null { const instance = Client.instanceArray.find((instance) => instance.id === dbCom.id) if (instance) { return instance.client diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index d425ccea1..456196bcb 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -1,4 +1,4 @@ -import { Community as DbCommunity } from '@entity/Community' +import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' import { GraphQLClient } from 'graphql-request' import { getPublicKey } from '@/federation/query/getPublicKey' @@ -7,11 +7,11 @@ import { backendLogger as logger } from '@/server/logger' // eslint-disable-next-line camelcase export class Client_1_0 { - dbCom: DbCommunity + dbCom: DbFederatedCommunity endpoint: string client: GraphQLClient - constructor(dbCom: DbCommunity) { + constructor(dbCom: DbFederatedCommunity) { this.dbCom = dbCom this.endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${ dbCom.apiVersion diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 2bc531eaf..6879f98e7 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -69,16 +69,3 @@ export async function validateCommunities(): Promise { } } } - -async function invokeVersionedRequestGetPublicKey( - dbCom: DbFederatedCommunity, -): Promise { - switch (dbCom.apiVersion) { - case ApiVersionType.V1_0: - return v1_0_requestGetPublicKey(dbCom) - case ApiVersionType.V1_1: - return v1_1_requestGetPublicKey(dbCom) - default: - return undefined - } -} From 2abf228ca9f943f9f3e73c748f9526ffe7d651a3 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 22:53:55 +0200 Subject: [PATCH 11/20] merge --- backend/src/federation/client/Client_1_0.ts | 26 ++++++----- backend/src/federation/validateCommunities.ts | 46 ++++++------------- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 456196bcb..77a72cce8 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -26,21 +26,25 @@ export class Client_1_0 { } getPublicKey = async (): Promise => { - logger.info(`requestGetPublicKey with endpoint='${this.endpoint}'...`) + logger.info('Federation: getPublicKey from endpoint', this.endpoint) try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data, errors, headers, status } = await this.client.rawRequest(getPublicKey, {}) - logger.debug(`Response-Data:`, data, errors, headers, status) - if (data) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey) - logger.info(`requestGetPublicKey processed successfully`) - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access - return data.getPublicKey.publicKey + 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.warn(`requestGetPublicKey processed without response data`) + logger.info( + 'Federation: getPublicKey successfull 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) { - throw new LogError(`Request-Error:`, err) + logger.warn('Federation: getPublicKey failed for endpoint', this.endpoint) } } } diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 6879f98e7..fcce9d0d8 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -3,7 +3,6 @@ import { IsNull } from '@dbTools/typeorm' import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' -import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' import { Client } from './client/Client' @@ -33,39 +32,24 @@ export async function validateCommunities(): Promise { logger.debug('Federation: dbCom', dbCom) const apiValueStrings: string[] = Object.values(ApiVersionType) logger.debug(`suppported ApiVersions=`, apiValueStrings) - if (apiValueStrings.includes(dbCom.apiVersion)) { - logger.debug( - `Federation: validate publicKey for dbCom: ${dbCom.id} with apiVersion=${dbCom.apiVersion}`, - ) - try { - const pubKey = await Client.getInstance(dbCom)?.getPublicKey() - logger.info( - 'Federation: received publicKey from endpoint', + if (!apiValueStrings.includes(dbCom.apiVersion)) { + logger.warn('Federation: dbCom with unsupported apiVersion', dbCom.endPoint, dbCom.apiVersion) + continue + } + try { + const client = Client.getInstance(dbCom) + const pubKey = await client?.getPublicKey() + if (pubKey && pubKey === dbCom.publicKey.toString()) { + await DbFederatedCommunity.update({ id: dbCom.id }, { verifiedAt: new Date() }) + } else { + logger.warn( + 'Federation: received not matching publicKey:', pubKey, - `${dbCom.endPoint}/${dbCom.apiVersion}`, + dbCom.publicKey.toString(), ) - if (pubKey && pubKey === dbCom.publicKey.toString()) { - logger.info(`Federation: matching publicKey: ${pubKey}`) - await DbFederatedCommunity.update({ id: dbCom.id }, { verifiedAt: new Date() }) - logger.debug(`Federation: updated dbCom: ${JSON.stringify(dbCom)}`) - } else { - logger.warn( - `Federation: received not matching publicKey -> received: ${ - pubKey || 'null' - }, expected: ${dbCom.publicKey.toString()} `, - ) - // DbCommunity.delete({ id: dbCom.id }) - } - } catch (err) { - if (!(err instanceof LogError)) { - logger.error(`Error:`, err) - } } - } else { - logger.warn( - `Federation: dbCom: ${dbCom.id} with unsupported apiVersion=${dbCom.apiVersion}; supported versions`, - apiValueStrings, - ) + } catch (err) { + logger.error(`Error:`, err) } } } From cd7cef4fbf0f022db1d7e7ac11099ddc176dc6a5 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 12:09:12 +0200 Subject: [PATCH 12/20] typo --- backend/src/federation/client/Client_1_0.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 77a72cce8..ad6641f1c 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -36,7 +36,7 @@ export class Client_1_0 { return } logger.info( - 'Federation: getPublicKey successfull from endpoint', + 'Federation: getPublicKey successful from endpoint', this.endpoint, // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access data.getPublicKey.publicKey, From 6c7243758f885282be5786ea851dfbedb9d64832 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 12:26:11 +0200 Subject: [PATCH 13/20] fix tests --- .../federation/validateCommunities.test.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/backend/src/federation/validateCommunities.test.ts b/backend/src/federation/validateCommunities.test.ts index ed4897e09..77d0cc2ad 100644 --- a/backend/src/federation/validateCommunities.test.ts +++ b/backend/src/federation/validateCommunities.test.ts @@ -84,7 +84,8 @@ describe('validate Communities', () => { }) it('logs requestGetPublicKey for community api 1_0 ', () => { expect(logger.info).toBeCalledWith( - `requestGetPublicKey with endpoint='http//localhost:5001/api/1_0/'...`, + 'Federation: getPublicKey from endpoint', + 'http//localhost:5001/api/1_0/', ) }) }) @@ -114,12 +115,14 @@ describe('validate Communities', () => { }) it('logs requestGetPublicKey for community api 1_0 ', () => { expect(logger.info).toBeCalledWith( - `requestGetPublicKey with endpoint='http//localhost:5001/api/1_0/'...`, + 'Federation: getPublicKey from endpoint', + 'http//localhost:5001/api/1_0/', ) }) it('logs requestGetPublicKey for community api 1_1 ', () => { expect(logger.info).toBeCalledWith( - `requestGetPublicKey with endpoint='http//localhost:5001/api/1_1/'...`, + 'Federation: getPublicKey from endpoint', + 'http//localhost:5001/api/1_1/', ) }) }) @@ -152,18 +155,21 @@ describe('validate Communities', () => { }) it('logs requestGetPublicKey for community api 1_0 ', () => { expect(logger.info).toBeCalledWith( - `requestGetPublicKey with endpoint='http//localhost:5001/api/1_0/'...`, + 'Federation: getPublicKey from endpoint', + 'http//localhost:5001/api/1_0/', ) }) it('logs requestGetPublicKey for community api 1_1 ', () => { expect(logger.info).toBeCalledWith( - `requestGetPublicKey with endpoint='http//localhost:5001/api/1_1/'...`, + 'Federation: getPublicKey from endpoint', + 'http//localhost:5001/api/1_1/', ) }) it('logs unsupported api for community with api 2_0 ', () => { expect(logger.warn).toBeCalledWith( - `Federation: dbCom: ${dbCom.id} with unsupported apiVersion=2_0; supported versions`, - ['1_0', '1_1'], + 'Federation: dbCom with unsupported apiVersion', + dbCom.endPoint, + '2_0', ) }) }) From 97b3a88065c6f7d899e745b309d991e664451eaa Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 12:27:41 +0200 Subject: [PATCH 14/20] 86% line coverage --- backend/jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/jest.config.js b/backend/jest.config.js index ca12668fa..3b251916a 100644 --- a/backend/jest.config.js +++ b/backend/jest.config.js @@ -7,7 +7,7 @@ module.exports = { collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'], coverageThreshold: { global: { - lines: 85, + lines: 86, }, }, setupFiles: ['/test/testSetup.ts'], From d3ba23e1e4c5da32cde11a39bea2070ffaf20f4a Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 12:56:46 +0200 Subject: [PATCH 15/20] fix lint --- backend/src/federation/client/Client_1_0.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index ad6641f1c..0c0d458c8 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -2,7 +2,6 @@ import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCom import { GraphQLClient } from 'graphql-request' import { getPublicKey } from '@/federation/query/getPublicKey' -import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' // eslint-disable-next-line camelcase From 2bf839f36212216dc970f32381247c890b09e082 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 4 May 2023 13:51:08 +0200 Subject: [PATCH 16/20] lint fixes From 6519b4b75e9c9f37eab79e26b44655e54c8a6c1f Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 9 May 2023 10:18:01 +0200 Subject: [PATCH 17/20] Update backend/src/federation/client/Client_1_0.ts Co-authored-by: Hannes Heine --- backend/src/federation/client/Client_1_0.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 456196bcb..19d58de89 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -30,7 +30,7 @@ export class Client_1_0 { try { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const { data, errors, headers, status } = await this.client.rawRequest(getPublicKey, {}) - logger.debug(`Response-Data:`, data, errors, headers, status) + logger.debug('Response-Data:', data, errors, headers, status) if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey) From f8a63f9b71c2830d7d09905d634adb7c6aa898bf Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Tue, 9 May 2023 10:18:43 +0200 Subject: [PATCH 18/20] Update backend/src/federation/client/Client_1_0.ts Co-authored-by: Hannes Heine --- backend/src/federation/client/Client_1_0.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/federation/client/Client_1_0.ts b/backend/src/federation/client/Client_1_0.ts index 19d58de89..fd2f941a3 100644 --- a/backend/src/federation/client/Client_1_0.ts +++ b/backend/src/federation/client/Client_1_0.ts @@ -33,7 +33,7 @@ export class Client_1_0 { logger.debug('Response-Data:', data, errors, headers, status) if (data) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - logger.debug(`Response-PublicKey:`, data.getPublicKey.publicKey) + logger.debug('Response-PublicKey:', data.getPublicKey.publicKey) logger.info(`requestGetPublicKey processed successfully`) // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access return data.getPublicKey.publicKey From 8c62dd1a4f2883a44d640320e379d8e8a0c23389 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Thu, 11 May 2023 10:27:43 +0200 Subject: [PATCH 19/20] lint fixes --- backend/src/federation/client/Client.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/federation/client/Client.ts b/backend/src/federation/client/Client.ts index 515945eb5..98f63c127 100644 --- a/backend/src/federation/client/Client.ts +++ b/backend/src/federation/client/Client.ts @@ -10,12 +10,13 @@ import { Client_1_1 } from './Client_1_1' // eslint-disable-next-line camelcase type FederationClient = Client_1_0 | Client_1_1 -type ClientInstance = { +interface ClientInstance { id: number // eslint-disable-next-line no-use-before-define client: FederationClient } +// eslint-disable-next-line @typescript-eslint/no-extraneous-class export class Client { private static instanceArray: ClientInstance[] = [] From e924d0bb97c67ae5b1e3192192149319aca11f7e Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Fri, 12 May 2023 15:35:22 +0200 Subject: [PATCH 20/20] log when a community is verified successfully --- backend/src/federation/validateCommunities.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index fcce9d0d8..4b337eda9 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -41,6 +41,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) } else { logger.warn( 'Federation: received not matching publicKey:',