From 17a067e99b57b4fe9f69f95e812ed3cb987b2394 Mon Sep 17 00:00:00 2001 From: einhorn_b Date: Thu, 18 Jan 2024 13:10:58 +0100 Subject: [PATCH] add and use logging view class, annonce only configured api version --- .../client/1_0/AuthenticationClient.ts | 6 +- .../federation/client/1_0/FederationClient.ts | 26 +++--- .../federation/client/1_0/SendCoinsClient.ts | 72 ++++++++++------- .../PublicCommunityInfoLogging.view.ts | 19 +++++ .../1_0/logging/SendCoinsArgsLogging.view.ts | 24 ++++++ .../logging/SendCoinsResultLogging.view.ts | 20 +++++ .../client/1_0/model/GetPublicKeyResult.ts | 13 +++ backend/src/federation/validateCommunities.ts | 16 ++-- backend/tsconfig.json | 3 +- database/logging/AbstractLogging.view.ts | 9 ++- .../logging/FederatedCommunityLogging.view.ts | 24 ++++++ dht-node/.env.dist | 4 +- dht-node/.env.template | 3 +- dht-node/src/config/index.ts | 4 +- dht-node/src/dht_node/index.ts | 10 ++- ...etPublicCommunityInfoResultLogging.view.ts | 18 +++++ .../1_0/logger/SendCoinsArgsLogging.view.ts | 23 ++++++ .../1_0/model/GetPublicCommunityInfoResult.ts | 2 +- .../1_0/resolver/AuthenticationResolver.ts | 17 ++-- .../resolver/PublicCommunityInfoResolver.ts | 7 +- .../api/1_0/resolver/PublicKeyResolver.ts | 6 +- .../api/1_0/resolver/SendCoinsResolver.ts | 81 +++++-------------- .../api/1_0/util/authenticateCommunity.ts | 22 ++++- federation/tsconfig.json | 3 +- 24 files changed, 292 insertions(+), 140 deletions(-) create mode 100644 backend/src/federation/client/1_0/logging/PublicCommunityInfoLogging.view.ts create mode 100644 backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts create mode 100644 backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts create mode 100644 backend/src/federation/client/1_0/model/GetPublicKeyResult.ts create mode 100644 database/logging/FederatedCommunityLogging.view.ts create mode 100644 federation/src/graphql/api/1_0/logger/GetPublicCommunityInfoResultLogging.view.ts create mode 100644 federation/src/graphql/api/1_0/logger/SendCoinsArgsLogging.view.ts diff --git a/backend/src/federation/client/1_0/AuthenticationClient.ts b/backend/src/federation/client/1_0/AuthenticationClient.ts index abc903778..f73393255 100644 --- a/backend/src/federation/client/1_0/AuthenticationClient.ts +++ b/backend/src/federation/client/1_0/AuthenticationClient.ts @@ -28,9 +28,9 @@ export class AuthenticationClient { async openConnection(args: OpenConnectionArgs): Promise { logger.debug(`Authentication: openConnection at ${this.endpoint} for args:`, args) try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(openConnection, { args }) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const { data } = await this.client.rawRequest<{ openConnection: boolean }>(openConnection, { + args, + }) if (!data?.openConnection) { logger.warn( 'Authentication: openConnection without response data from endpoint', diff --git a/backend/src/federation/client/1_0/FederationClient.ts b/backend/src/federation/client/1_0/FederationClient.ts index 8d915c751..4a10ddc7e 100644 --- a/backend/src/federation/client/1_0/FederationClient.ts +++ b/backend/src/federation/client/1_0/FederationClient.ts @@ -5,9 +5,10 @@ import { getPublicCommunityInfo } from '@/federation/client/1_0/query/getPublicC import { getPublicKey } from '@/federation/client/1_0/query/getPublicKey' import { backendLogger as logger } from '@/server/logger' +import { PublicCommunityInfoLoggingView } from './logging/PublicCommunityInfoLogging.view' +import { GetPublicKeyResult } from './model/GetPublicKeyResult' import { PublicCommunityInfo } from './model/PublicCommunityInfo' -// eslint-disable-next-line camelcase export class FederationClient { dbCom: DbFederatedCommunity endpoint: string @@ -30,9 +31,10 @@ export class FederationClient { getPublicKey = async (): Promise => { logger.debug('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 + const { data } = await this.client.rawRequest<{ getPublicKey: GetPublicKeyResult }>( + getPublicKey, + {}, + ) if (!data?.getPublicKey?.publicKey) { logger.warn('Federation: getPublicKey without response data from endpoint', this.endpoint) return @@ -40,10 +42,8 @@ export class FederationClient { logger.debug( '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) @@ -53,9 +53,10 @@ export class FederationClient { getPublicCommunityInfo = async (): Promise => { logger.debug(`Federation: getPublicCommunityInfo with endpoint='${this.endpoint}'...`) try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(getPublicCommunityInfo, {}) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const { data } = await this.client.rawRequest<{ + getPublicCommunityInfo: PublicCommunityInfo + }>(getPublicCommunityInfo, {}) + if (!data?.getPublicCommunityInfo?.name) { logger.warn( 'Federation: getPublicCommunityInfo without response data from endpoint', @@ -64,9 +65,10 @@ export class FederationClient { return } logger.debug(`Federation: getPublicCommunityInfo successful from endpoint=${this.endpoint}`) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - logger.debug(`publicCommunityInfo:`, data.getPublicCommunityInfo) - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access + logger.debug( + `publicCommunityInfo:`, + new PublicCommunityInfoLoggingView(data.getPublicCommunityInfo), + ) return data.getPublicCommunityInfo } catch (err) { logger.warn('Federation: getPublicCommunityInfo failed for endpoint', this.endpoint) diff --git a/backend/src/federation/client/1_0/SendCoinsClient.ts b/backend/src/federation/client/1_0/SendCoinsClient.ts index c96961103..bcf303584 100644 --- a/backend/src/federation/client/1_0/SendCoinsClient.ts +++ b/backend/src/federation/client/1_0/SendCoinsClient.ts @@ -4,6 +4,8 @@ import { GraphQLClient } from 'graphql-request' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' +import { SendCoinsArgsLoggingView } from './logging/SendCoinsArgsLogging.view' +import { SendCoinsResultLoggingView } from './logging/SendCoinsResultLogging.view' import { SendCoinsArgs } from './model/SendCoinsArgs' import { SendCoinsResult } from './model/SendCoinsResult' import { revertSendCoins as revertSendCoinsQuery } from './query/revertSendCoins' @@ -11,7 +13,6 @@ import { revertSettledSendCoins as revertSettledSendCoinsQuery } from './query/r import { settleSendCoins as settleSendCoinsQuery } from './query/settleSendCoins' import { voteForSendCoins as voteForSendCoinsQuery } from './query/voteForSendCoins' -// eslint-disable-next-line camelcase export class SendCoinsClient { dbCom: DbFederatedCommunity endpoint: string @@ -34,26 +35,26 @@ export class SendCoinsClient { async voteForSendCoins(args: SendCoinsArgs): Promise { logger.debug('X-Com: voteForSendCoins against endpoint=', this.endpoint) try { - logger.debug(`X-Com: SendCoinsClient: voteForSendCoins with args=`, args) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(voteForSendCoinsQuery, { args }) - logger.debug(`X-Com: SendCoinsClient: after rawRequest...data:`, data) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + logger.debug( + `X-Com: SendCoinsClient: voteForSendCoins with args=`, + new SendCoinsArgsLoggingView(args), + ) + const { data } = await this.client.rawRequest<{ voteForSendCoins: SendCoinsResult }>( + voteForSendCoinsQuery, + { args }, + ) + const result = data.voteForSendCoins if (!data?.voteForSendCoins?.vote) { - logger.debug('X-Com: voteForSendCoins failed with: ', data) + logger.debug( + 'X-Com: voteForSendCoins failed with: ', + new SendCoinsResultLoggingView(result), + ) return new SendCoinsResult() } - const result = new SendCoinsResult() - result.vote = true - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - result.recipGradidoID = data.voteForSendCoins.recipGradidoID - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - result.recipFirstName = data.voteForSendCoins.recipFirstName - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - result.recipLastName = data.voteForSendCoins.recipLastName - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - result.recipAlias = data.voteForSendCoins.recipAlias - logger.debug('X-Com: voteForSendCoins successful with result=', result) + logger.debug( + 'X-Com: voteForSendCoins successful with result=', + new SendCoinsResultLoggingView(result), + ) return result } catch (err) { throw new LogError(`X-Com: voteForSendCoins failed for endpoint=${this.endpoint}:`, err) @@ -63,11 +64,15 @@ export class SendCoinsClient { async revertSendCoins(args: SendCoinsArgs): Promise { logger.debug('X-Com: revertSendCoins against endpoint=', this.endpoint) try { - logger.debug(`X-Com: SendCoinsClient: revertSendCoins with args=`, args) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(revertSendCoinsQuery, { args }) + logger.debug( + `X-Com: SendCoinsClient: revertSendCoins with args=`, + new SendCoinsArgsLoggingView(args), + ) + const { data } = await this.client.rawRequest<{ revertSendCoins: boolean }>( + revertSendCoinsQuery, + { args }, + ) logger.debug(`X-Com: SendCoinsClient: after revertSendCoins: data=`, data) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!data?.revertSendCoins) { logger.warn('X-Com: revertSendCoins without response data from endpoint', this.endpoint) return false @@ -88,11 +93,15 @@ export class SendCoinsClient { async settleSendCoins(args: SendCoinsArgs): Promise { logger.debug(`X-Com: settleSendCoins against endpoint='${this.endpoint}'...`) try { - logger.debug(`X-Com: SendCoinsClient: settleSendCoins with args=`, args) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(settleSendCoinsQuery, { args }) + logger.debug( + `X-Com: SendCoinsClient: settleSendCoins with args=`, + new SendCoinsArgsLoggingView(args), + ) + const { data } = await this.client.rawRequest<{ settleSendCoins: boolean }>( + settleSendCoinsQuery, + { args }, + ) logger.debug(`X-Com: SendCoinsClient: after settleSendCoins: data=`, data) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!data?.settleSendCoins) { logger.warn( 'X-Com: SendCoinsClient: settleSendCoins without response data from endpoint', @@ -115,9 +124,14 @@ export class SendCoinsClient { async revertSettledSendCoins(args: SendCoinsArgs): Promise { logger.debug(`X-Com: revertSettledSendCoins against endpoint='${this.endpoint}'...`) try { - logger.debug(`X-Com: SendCoinsClient: revertSettledSendCoins with args=`, args) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { data } = await this.client.rawRequest(revertSettledSendCoinsQuery, { args }) + logger.debug( + `X-Com: SendCoinsClient: revertSettledSendCoins with args=`, + new SendCoinsArgsLoggingView(args), + ) + const { data } = await this.client.rawRequest<{ revertSettledSendCoins: boolean }>( + revertSettledSendCoinsQuery, + { args }, + ) logger.debug(`X-Com: SendCoinsClient: after revertSettledSendCoins: data=`, data) // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!data?.revertSettledSendCoins) { diff --git a/backend/src/federation/client/1_0/logging/PublicCommunityInfoLogging.view.ts b/backend/src/federation/client/1_0/logging/PublicCommunityInfoLogging.view.ts new file mode 100644 index 000000000..3151bbb31 --- /dev/null +++ b/backend/src/federation/client/1_0/logging/PublicCommunityInfoLogging.view.ts @@ -0,0 +1,19 @@ +import { AbstractLoggingView } from '@logging/AbstractLogging.view' + +import { PublicCommunityInfo } from '@/federation/client/1_0/model/PublicCommunityInfo' + +export class PublicCommunityInfoLoggingView extends AbstractLoggingView { + public constructor(private self: PublicCommunityInfo) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + name: this.self.name, + description: this.self.description, + creationDate: this.dateToString(this.self.creationDate), + publicKey: this.self.publicKey, + } + } +} diff --git a/backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts b/backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts new file mode 100644 index 000000000..2df149133 --- /dev/null +++ b/backend/src/federation/client/1_0/logging/SendCoinsArgsLogging.view.ts @@ -0,0 +1,24 @@ +import { AbstractLoggingView } from '@logging/AbstractLogging.view' + +import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs' + +export class SendCoinsArgsLoggingView extends AbstractLoggingView { + public constructor(private self: SendCoinsArgs) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + recipientCommunityUuid: this.self.recipientCommunityUuid, + recipientUserIdentifier: this.self.recipientUserIdentifier, + creationDate: this.self.creationDate, + amount: this.decimalToString(this.self.amount), + memoLength: this.self.memo.length, + senderCommunityUuid: this.self.senderCommunityUuid, + senderUserUuid: this.self.senderUserUuid, + senderUserName: this.self.senderUserName.substring(0, 3), + senderAlias: this.self.senderAlias?.substring(0, 3), + } + } +} diff --git a/backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts b/backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts new file mode 100644 index 000000000..b605eb1db --- /dev/null +++ b/backend/src/federation/client/1_0/logging/SendCoinsResultLogging.view.ts @@ -0,0 +1,20 @@ +import { AbstractLoggingView } from '@logging/AbstractLogging.view' + +import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult' + +export class SendCoinsResultLoggingView extends AbstractLoggingView { + public constructor(private self: SendCoinsResult) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + vote: this.self.vote, + recipGradidoID: this.self.recipGradidoID, + recipFirstName: this.self.recipFirstName?.substring(0, 3), + recipLastName: this.self.recipLastName?.substring(0, 3), + recipAlias: this.self.recipAlias?.substring(0, 3), + } + } +} diff --git a/backend/src/federation/client/1_0/model/GetPublicKeyResult.ts b/backend/src/federation/client/1_0/model/GetPublicKeyResult.ts new file mode 100644 index 000000000..696c96cfe --- /dev/null +++ b/backend/src/federation/client/1_0/model/GetPublicKeyResult.ts @@ -0,0 +1,13 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { Field, ObjectType } from 'type-graphql' + +@ObjectType() +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export class GetPublicKeyResult { + constructor(pubKey: string) { + this.publicKey = pubKey + } + + @Field(() => String) + publicKey: string +} diff --git a/backend/src/federation/validateCommunities.ts b/backend/src/federation/validateCommunities.ts index 69b69070a..f19d606bd 100644 --- a/backend/src/federation/validateCommunities.ts +++ b/backend/src/federation/validateCommunities.ts @@ -3,14 +3,15 @@ import { IsNull } from '@dbTools/typeorm' import { Community as DbCommunity } from '@entity/Community' import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity' +import { FederatedCommunityLoggingView } from '@logging/FederatedCommunityLogging.view' -// eslint-disable-next-line camelcase import { FederationClient as V1_0_FederationClient } from '@/federation/client/1_0/FederationClient' import { PublicCommunityInfo } from '@/federation/client/1_0/model/PublicCommunityInfo' import { FederationClientFactory } from '@/federation/client/FederationClientFactory' import { backendLogger as logger } from '@/server/logger' import { startCommunityAuthentication } from './authenticateCommunities' +import { PublicCommunityInfoLoggingView } from './client/1_0/logging/PublicCommunityInfoLogging.view' import { ApiVersionType } from './enum/apiVersionType' export async function startValidateCommunities(timerInterval: number): Promise { @@ -37,7 +38,7 @@ export async function validateCommunities(): Promise { logger.debug(`Federation: found ${dbFederatedCommunities.length} dbCommunities`) for (const dbCom of dbFederatedCommunities) { - logger.debug('Federation: dbCom', dbCom) + logger.debug('Federation: dbCom', new FederatedCommunityLoggingView(dbCom)) const apiValueStrings: string[] = Object.values(ApiVersionType) logger.debug(`suppported ApiVersions=`, apiValueStrings) if (!apiValueStrings.includes(dbCom.apiVersion)) { @@ -53,7 +54,7 @@ export async function validateCommunities(): Promise { // eslint-disable-next-line camelcase if (client instanceof V1_0_FederationClient) { const pubKey = await client.getPublicKey() - if (pubKey && pubKey === dbCom.publicKey.toString()) { + if (pubKey && pubKey === dbCom.publicKey.toString('hex')) { await DbFederatedCommunity.update({ id: dbCom.id }, { verifiedAt: new Date() }) logger.debug(`Federation: verified community with:`, dbCom.endPoint) const pubComInfo = await client.getPublicCommunityInfo() @@ -68,7 +69,7 @@ export async function validateCommunities(): Promise { logger.debug( 'Federation: received not matching publicKey:', pubKey, - dbCom.publicKey.toString(), + dbCom.publicKey.toString('hex'), ) } } @@ -82,10 +83,11 @@ async function writeForeignCommunity( dbCom: DbFederatedCommunity, pubInfo: PublicCommunityInfo, ): Promise { - if (!dbCom || !pubInfo || !(dbCom.publicKey.toString() === pubInfo.publicKey)) { + if (!dbCom || !pubInfo || !(dbCom.publicKey.toString('hex') === pubInfo.publicKey)) { + const pubInfoView = new PublicCommunityInfoLoggingView(pubInfo) logger.error( - `Error in writeForeignCommunity: missmatching parameters or publicKey. pubInfo:${JSON.stringify( - pubInfo, + `Error in writeForeignCommunity: missmatching parameters or publicKey. pubInfo:${pubInfoView.toString( + true, )}`, ) } else { diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 7e329926b..28ddf1c38 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -58,7 +58,8 @@ "@test/*": ["test/*"], /* external */ "@dbTools/*": ["../database/src/*", "../../database/build/src/*"], - "@entity/*": ["../database/entity/*", "../../database/build/entity/*"] + "@entity/*": ["../database/entity/*", "../../database/build/entity/*"], + "@logging/*": ["../database/logging/*", "../../database/build/logging/*"] }, // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ "typeRoots": ["@types", "node_modules/@types"], /* List of folders to include type definitions from. */ diff --git a/database/logging/AbstractLogging.view.ts b/database/logging/AbstractLogging.view.ts index a30254b86..e51f3823d 100644 --- a/database/logging/AbstractLogging.view.ts +++ b/database/logging/AbstractLogging.view.ts @@ -3,13 +3,18 @@ import util from 'util' import { Decimal } from 'decimal.js-light' export abstract class AbstractLoggingView { + // eslint-disable-next-line no-undef protected bufferStringFormat: BufferEncoding = 'hex' // This function gets called automatically when JSON.stringify() is called on this class instance // eslint-disable-next-line @typescript-eslint/no-explicit-any public abstract toJSON(): any - public toString(): string { - return JSON.stringify(this.toJSON(), null, 2) + public toString(compact = false): string { + if (compact) { + return JSON.stringify(this.toJSON()) + } else { + return JSON.stringify(this.toJSON(), null, 2) + } } // called form console.log or log4js logging functions diff --git a/database/logging/FederatedCommunityLogging.view.ts b/database/logging/FederatedCommunityLogging.view.ts new file mode 100644 index 000000000..4e36cc236 --- /dev/null +++ b/database/logging/FederatedCommunityLogging.view.ts @@ -0,0 +1,24 @@ +import { FederatedCommunity } from '../entity/FederatedCommunity' +import { AbstractLoggingView } from './AbstractLogging.view' + +export class FederatedCommunityLoggingView extends AbstractLoggingView { + public constructor(private self: FederatedCommunity) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + id: this.self.id, + foreign: this.self.foreign, + publicKey: this.self.publicKey.toString(this.bufferStringFormat), + apiVersion: this.self.apiVersion, + endPoint: this.self.endPoint, + lastAnnouncedAt: this.dateToString(this.self.lastAnnouncedAt), + verifiedAt: this.self.verifiedAt, + lastErrorAt: this.self.lastErrorAt, + createdAt: this.dateToString(this.self.createdAt), + updatedAt: this.dateToString(this.self.updatedAt), + } + } +} diff --git a/dht-node/.env.dist b/dht-node/.env.dist index 51728d3e1..fa07fc904 100644 --- a/dht-node/.env.dist +++ b/dht-node/.env.dist @@ -15,5 +15,5 @@ TYPEORM_LOGGING_RELATIVE_PATH=typeorm.dht-node.log FEDERATION_DHT_TOPIC=GRADIDO_HUB # FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f FEDERATION_COMMUNITY_URL=http://localhost -# the api port is the dht baseport, which will be added with the supported api-versions, e.g. 1_0 = 5010 -FEDERATION_COMMUNITY_API_PORT=5000 +# comma separated values, which apis should be announced +FEDERATION_COMMUNITY_APIS=1_0 \ No newline at end of file diff --git a/dht-node/.env.template b/dht-node/.env.template index 1278f61be..324d2c3a7 100644 --- a/dht-node/.env.template +++ b/dht-node/.env.template @@ -20,4 +20,5 @@ FEDERATION_DHT_CONFIG_VERSION=$FEDERATION_DHT_CONFIG_VERSION FEDERATION_DHT_TOPIC=$FEDERATION_DHT_TOPIC FEDERATION_DHT_SEED=$FEDERATION_DHT_SEED FEDERATION_COMMUNITY_URL=$FEDERATION_COMMUNITY_URL -FEDERATION_COMMUNITY_API_PORT=$FEDERATION_COMMUNITY_API_PORT +# comma separated values, which apis should be announced +FEDERATION_COMMUNITY_APIS=$FEDERATION_COMMUNITY_APIS \ No newline at end of file diff --git a/dht-node/src/config/index.ts b/dht-node/src/config/index.ts index 3459ec058..3599dd3c4 100644 --- a/dht-node/src/config/index.ts +++ b/dht-node/src/config/index.ts @@ -10,7 +10,7 @@ const constants = { LOG_LEVEL: process.env.LOG_LEVEL || 'info', CONFIG_VERSION: { DEFAULT: 'DEFAULT', - EXPECTED: 'v3.2023-04-26', + EXPECTED: 'v4.2024-01-17', CURRENT: '', }, } @@ -39,7 +39,7 @@ const federation = { FEDERATION_DHT_TOPIC: process.env.FEDERATION_DHT_TOPIC || 'GRADIDO_HUB', FEDERATION_DHT_SEED: process.env.FEDERATION_DHT_SEED || null, FEDERATION_COMMUNITY_URL: process.env.FEDERATION_COMMUNITY_URL || 'http://localhost', - FEDERATION_COMMUNITY_API_PORT: process.env.FEDERATION_COMMUNITY_API_PORT || '5000', + FEDERATION_COMMUNITY_APIS: process.env.FEDERATION_COMMUNITY_APIS || '1_0', } // Check config version diff --git a/dht-node/src/dht_node/index.ts b/dht-node/src/dht_node/index.ts index 536966591..dd17b7049 100644 --- a/dht-node/src/dht_node/index.ts +++ b/dht-node/src/dht_node/index.ts @@ -18,8 +18,8 @@ const ANNOUNCETIME = 30000 enum ApiVersionType { V1_0 = '1_0', - V1_1 = '1_1', - V2_0 = '2_0', + V1_1 = '1_1', // currently no changes + V2_0 = '2_0', // not exist } type CommunityApi = { api: string @@ -191,9 +191,11 @@ export const startDHT = async (topic: string): Promise => { } async function writeFederatedHomeCommunityEntries(pubKey: string): Promise { - const homeApiVersions: CommunityApi[] = Object.values(ApiVersionType).map(function (apiEnum) { + const homeApiVersions: CommunityApi[] = CONFIG.FEDERATION_COMMUNITY_APIS.split(',').map(function ( + api, + ) { const comApi: CommunityApi = { - api: apiEnum, + api, url: CONFIG.FEDERATION_COMMUNITY_URL + '/api/', } return comApi diff --git a/federation/src/graphql/api/1_0/logger/GetPublicCommunityInfoResultLogging.view.ts b/federation/src/graphql/api/1_0/logger/GetPublicCommunityInfoResultLogging.view.ts new file mode 100644 index 000000000..669170b98 --- /dev/null +++ b/federation/src/graphql/api/1_0/logger/GetPublicCommunityInfoResultLogging.view.ts @@ -0,0 +1,18 @@ +import { GetPublicCommunityInfoResult } from '@/graphql/api/1_0/model/GetPublicCommunityInfoResult' +import { AbstractLoggingView } from '@logging/AbstractLogging.view' + +export class GetPublicCommunityInfoResultLoggingView extends AbstractLoggingView { + public constructor(private self: GetPublicCommunityInfoResult) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + name: this.self.name, + description: this.self.description, + creationDate: this.dateToString(this.self.creationDate), + publicKey: this.self.publicKey, + } + } +} diff --git a/federation/src/graphql/api/1_0/logger/SendCoinsArgsLogging.view.ts b/federation/src/graphql/api/1_0/logger/SendCoinsArgsLogging.view.ts new file mode 100644 index 000000000..a12ff6372 --- /dev/null +++ b/federation/src/graphql/api/1_0/logger/SendCoinsArgsLogging.view.ts @@ -0,0 +1,23 @@ +import { AbstractLoggingView } from '@logging/AbstractLogging.view' +import { SendCoinsArgs } from '@/graphql/api/1_0/model/SendCoinsArgs' + +export class SendCoinsArgsLoggingView extends AbstractLoggingView { + public constructor(private self: SendCoinsArgs) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + recipientCommunityUuid: this.self.recipientCommunityUuid, + recipientUserIdentifier: this.self.recipientUserIdentifier, + creationDate: this.self.creationDate, + amount: this.decimalToString(this.self.amount), + memoLength: this.self.memo.length, + senderCommunityUuid: this.self.senderCommunityUuid, + senderUserUuid: this.self.senderUserUuid, + senderUserName: this.self.senderUserName.substring(0, 3), + senderAlias: this.self.senderAlias?.substring(0, 3), + } + } +} diff --git a/federation/src/graphql/api/1_0/model/GetPublicCommunityInfoResult.ts b/federation/src/graphql/api/1_0/model/GetPublicCommunityInfoResult.ts index 86ea480df..d51b3af93 100644 --- a/federation/src/graphql/api/1_0/model/GetPublicCommunityInfoResult.ts +++ b/federation/src/graphql/api/1_0/model/GetPublicCommunityInfoResult.ts @@ -7,7 +7,7 @@ import { Field, ObjectType } from 'type-graphql' // eslint-disable-next-line @typescript-eslint/no-unused-vars export class GetPublicCommunityInfoResult { constructor(dbCom: DbCommunity) { - this.publicKey = dbCom.publicKey.toString() + this.publicKey = dbCom.publicKey.toString('hex') this.name = dbCom.name this.description = dbCom.description this.creationDate = dbCom.creationDate diff --git a/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts b/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts index 8f7b510cf..393fe3b65 100644 --- a/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts @@ -3,6 +3,8 @@ import { Arg, Mutation, Resolver } from 'type-graphql' import { federationLogger as logger } from '@/server/logger' import { Community as DbCommunity } from '@entity/Community' import { FederatedCommunity as DbFedCommunity } from '@entity/FederatedCommunity' +import { CommunityLoggingView } from '@logging/CommunityLogging.view' +import { FederatedCommunityLoggingView } from '@logging/FederatedCommunityLogging.view' import { LogError } from '@/server/LogError' import { OpenConnectionArgs } from '../model/OpenConnectionArgs' import { startAuthentication, startOpenConnectionCallback } from '../util/authenticateCommunity' @@ -11,7 +13,6 @@ import { CONFIG } from '@/config' import { AuthenticationArgs } from '../model/AuthenticationArgs' @Resolver() -// eslint-disable-next-line @typescript-eslint/no-unused-vars export class AuthenticationResolver { @Mutation(() => Boolean) async openConnection( @@ -28,7 +29,7 @@ export class AuthenticationResolver { if (!comA) { throw new LogError(`unknown requesting community with publicKey`, pubKeyBuf.toString('hex')) } - logger.debug(`Authentication: found requestedCom:`, comA) + logger.debug(`Authentication: found requestedCom:`, new CommunityLoggingView(comA)) // no await to respond immediatly and invoke callback-request asynchron void startOpenConnectionCallback(args, comA, CONFIG.FEDERATION_API) return true @@ -48,7 +49,10 @@ export class AuthenticationResolver { if (!fedComB) { throw new LogError(`unknown callback community with url`, args.url) } - logger.debug(`Authentication: found fedComB and start authentication:`, fedComB) + logger.debug( + `Authentication: found fedComB and start authentication:`, + new FederatedCommunityLoggingView(fedComB), + ) // no await to respond immediatly and invoke authenticate-request asynchron void startAuthentication(args.oneTimeCode, fedComB) return true @@ -61,13 +65,16 @@ export class AuthenticationResolver { ): Promise { logger.debug(`Authentication: authenticate() via apiVersion=1_0 ...`, args) const authCom = await DbCommunity.findOneByOrFail({ communityUuid: args.oneTimeCode }) - logger.debug('Authentication: found authCom:', authCom) + logger.debug('Authentication: found authCom:', new CommunityLoggingView(authCom)) if (authCom) { // TODO decrypt args.uuid with authCom.publicKey authCom.communityUuid = args.uuid authCom.authenticatedAt = new Date() await DbCommunity.save(authCom) - logger.debug('Authentication: store authCom.uuid successfully:', authCom) + logger.debug( + 'Authentication: store authCom.uuid successfully:', + new CommunityLoggingView(authCom), + ) const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) // TODO encrypt homeCom.uuid with homeCom.privateKey if (homeCom.communityUuid) { diff --git a/federation/src/graphql/api/1_0/resolver/PublicCommunityInfoResolver.ts b/federation/src/graphql/api/1_0/resolver/PublicCommunityInfoResolver.ts index 339314f86..c1535b713 100644 --- a/federation/src/graphql/api/1_0/resolver/PublicCommunityInfoResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/PublicCommunityInfoResolver.ts @@ -3,16 +3,19 @@ import { Query, Resolver } from 'type-graphql' import { federationLogger as logger } from '@/server/logger' import { Community as DbCommunity } from '@entity/Community' import { GetPublicCommunityInfoResult } from '../model/GetPublicCommunityInfoResult' +import { GetPublicCommunityInfoResultLoggingView } from '../logger/GetPublicCommunityInfoResultLogging.view' @Resolver() -// eslint-disable-next-line @typescript-eslint/no-unused-vars export class PublicCommunityInfoResolver { @Query(() => GetPublicCommunityInfoResult) async getPublicCommunityInfo(): Promise { logger.debug(`getPublicCommunityInfo() via apiVersion=1_0 ...`) const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) const result = new GetPublicCommunityInfoResult(homeCom) - logger.debug(`getPublicCommunityInfo()-1_0... return publicInfo=${JSON.stringify(result)}`) + const publicInfoView = new GetPublicCommunityInfoResultLoggingView(result) + logger.debug( + `getPublicCommunityInfo()-1_0... return publicInfo=${publicInfoView.toString(true)}`, + ) return result } } diff --git a/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts b/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts index bab0e25f5..3fb3b2c0d 100644 --- a/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/PublicKeyResolver.ts @@ -5,7 +5,6 @@ import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCom import { GetPublicKeyResult } from '../model/GetPublicKeyResult' @Resolver() -// eslint-disable-next-line @typescript-eslint/no-unused-vars export class PublicKeyResolver { @Query(() => GetPublicKeyResult) async getPublicKey(): Promise { @@ -16,7 +15,8 @@ export class PublicKeyResolver { apiVersion: '1_0', }, }) - logger.debug(`getPublicKey()-1_0... return publicKey=${homeCom.publicKey}`) - return new GetPublicKeyResult(homeCom.publicKey.toString()) + const publicKeyHex = homeCom.publicKey.toString('hex') + logger.debug(`getPublicKey()-1_0... return publicKey=${publicKeyHex}`) + return new GetPublicKeyResult(publicKeyHex) } } diff --git a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts index aa6e2300e..dd5a81a45 100644 --- a/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/SendCoinsResolver.ts @@ -1,5 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { Arg, Args, Mutation, Resolver } from 'type-graphql' +import { Arg, Mutation, Resolver } from 'type-graphql' import { federationLogger as logger } from '@/server/logger' import { Community as DbCommunity } from '@entity/Community' import { PendingTransaction as DbPendingTransaction } from '@entity/PendingTransaction' @@ -16,27 +15,16 @@ import { findUserByIdentifier } from '@/graphql/util/findUserByIdentifier' import { SendCoinsResult } from '../model/SendCoinsResult' import Decimal from 'decimal.js-light' import { storeForeignUser } from '../util/storeForeignUser' +import { SendCoinsArgsLoggingView } from '../logger/SendCoinsArgsLogging.view' @Resolver() -// eslint-disable-next-line @typescript-eslint/no-unused-vars export class SendCoinsResolver { @Mutation(() => SendCoinsResult) async voteForSendCoins( @Arg('data') args: SendCoinsArgs, ): Promise { - logger.debug( - `voteForSendCoins() via apiVersion=1_0 ...`, - args.recipientCommunityUuid, - args.recipientUserIdentifier, - args.creationDate, - args.amount.toString(), - args.memo, - args.senderCommunityUuid, - args.senderUserUuid, - args.senderUserName, - args.senderAlias, - ) + logger.debug(`voteForSendCoins() via apiVersion=1_0 ...`, new SendCoinsArgsLoggingView(args)) const result = new SendCoinsResult() // first check if receiver community is correct const homeCom = await DbCommunity.findOneBy({ @@ -167,19 +155,11 @@ export class SendCoinsResolver { pendingTx?.amount.toString(), args.amount.toString(), ) - throw new LogError( - `Can't find in revertSendCoins the pending receiver TX for args=`, - args.recipientCommunityUuid, - args.recipientUserIdentifier, - PendingTransactionState.NEW, - TransactionTypeId.RECEIVE, - args.creationDate, - args.amount, - args.memo, - args.senderCommunityUuid, - args.senderUserUuid, - args.senderUserName, - ) + throw new LogError(`Can't find in revertSendCoins the pending receiver TX for `, { + args: new SendCoinsArgsLoggingView(args), + pendingTransactionState: PendingTransactionState.NEW, + transactionType: TransactionTypeId.RECEIVE, + }) } logger.debug(`revertSendCoins()-1_0... successfull`) return true @@ -193,15 +173,7 @@ export class SendCoinsResolver { @Arg('data') args: SendCoinsArgs, ): Promise { - logger.debug( - `settleSendCoins() via apiVersion=1_0 ...userCommunityUuid=${ - args.recipientCommunityUuid - }, userGradidoID=${args.recipientUserIdentifier}, balanceDate=${ - args.creationDate - },amount=${args.amount.valueOf()}, memo=${args.memo}, linkedUserCommunityUuid = ${ - args.senderCommunityUuid - }, userSenderIdentifier=${args.senderUserUuid}, userSenderName=${args.senderUserName}`, - ) + logger.debug(`settleSendCoins() via apiVersion=1_0 ...`, new SendCoinsArgsLoggingView(args)) // first check if receiver community is correct const homeCom = await DbCommunity.findOneBy({ communityUuid: args.recipientCommunityUuid, @@ -256,17 +228,12 @@ export class SendCoinsResolver { } else { logger.debug('XCom: settlePendingReceiveTransaction NOT matching pendingTX for settlement...') throw new LogError( - `Can't find in settlePendingReceiveTransaction the pending receiver TX for args=`, - args.recipientCommunityUuid, - args.recipientUserIdentifier, - PendingTransactionState.NEW, - TransactionTypeId.RECEIVE, - args.creationDate, - args.amount, - args.memo, - args.senderCommunityUuid, - args.senderUserUuid, - args.senderUserName, + `Can't find in settlePendingReceiveTransaction the pending receiver TX for `, + { + args: new SendCoinsArgsLoggingView(args), + pendingTransactionState: PendingTransactionState.NEW, + transactionTypeId: TransactionTypeId.RECEIVE, + }, ) } } @@ -322,19 +289,11 @@ export class SendCoinsResolver { } } else { logger.debug('XCom: revertSettledSendCoins NOT matching pendingTX...') - throw new LogError( - `Can't find in revertSettledSendCoins the pending receiver TX for args=`, - args.recipientCommunityUuid, - args.recipientUserIdentifier, - PendingTransactionState.SETTLED, - TransactionTypeId.RECEIVE, - args.creationDate, - args.amount, - args.memo, - args.senderCommunityUuid, - args.senderUserUuid, - args.senderUserName, - ) + throw new LogError(`Can't find in revertSettledSendCoins the pending receiver TX for `, { + args: new SendCoinsArgsLoggingView(args), + pendingTransactionState: PendingTransactionState.SETTLED, + transactionTypeId: TransactionTypeId.RECEIVE, + }) } logger.debug(`revertSendCoins()-1_0... successfull`) return true diff --git a/federation/src/graphql/api/1_0/util/authenticateCommunity.ts b/federation/src/graphql/api/1_0/util/authenticateCommunity.ts index 0af3475ef..b672fe7fd 100644 --- a/federation/src/graphql/api/1_0/util/authenticateCommunity.ts +++ b/federation/src/graphql/api/1_0/util/authenticateCommunity.ts @@ -9,13 +9,18 @@ import { AuthenticationClientFactory } from '@/client/AuthenticationClientFactor // eslint-disable-next-line camelcase import { AuthenticationClient as V1_0_AuthenticationClient } from '@/client/1_0/AuthenticationClient' import { AuthenticationArgs } from '../model/AuthenticationArgs' +import { CommunityLoggingView } from '@logging/CommunityLogging.view' +import { FederatedCommunityLoggingView } from '@logging/FederatedCommunityLogging.view' export async function startOpenConnectionCallback( args: OpenConnectionArgs, comA: DbCommunity, api: string, ): Promise { - logger.debug(`Authentication: startOpenConnectionCallback() with:`, args, comA) + logger.debug(`Authentication: startOpenConnectionCallback() with:`, { + args, + comA: new CommunityLoggingView(comA), + }) try { const homeFedCom = await DbFedCommunity.findOneByOrFail({ foreign: false, @@ -30,7 +35,10 @@ export async function startOpenConnectionCallback( // store oneTimeCode in requestedCom.community_uuid as authenticate-request-identifier comA.communityUuid = oneTimeCode.toString() await DbCommunity.save(comA) - logger.debug(`Authentication: stored oneTimeCode in requestedCom:`, comA) + logger.debug( + `Authentication: stored oneTimeCode in requestedCom:`, + new CommunityLoggingView(comA), + ) const client = AuthenticationClientFactory.getInstance(fedComA) // eslint-disable-next-line camelcase @@ -57,7 +65,10 @@ export async function startAuthentication( oneTimeCode: string, fedComB: DbFedCommunity, ): Promise { - logger.debug(`Authentication: startAuthentication()...`, oneTimeCode, fedComB) + logger.debug(`Authentication: startAuthentication()...`, { + oneTimeCode, + fedComB: new FederatedCommunityLoggingView(fedComB), + }) try { const homeCom = await DbCommunity.findOneByOrFail({ foreign: false }) @@ -88,7 +99,10 @@ export async function startAuthentication( callbackCom.communityUuid = fedComUuid callbackCom.authenticatedAt = new Date() await DbCommunity.save(callbackCom) - logger.debug('Authentication: Community Authentication successful:', callbackCom) + logger.debug( + 'Authentication: Community Authentication successful:', + new CommunityLoggingView(callbackCom), + ) } else { logger.error('Authentication: Community Authentication failed:', authenticationArgs) } diff --git a/federation/tsconfig.json b/federation/tsconfig.json index 50ce9d0c7..0f96e80e5 100644 --- a/federation/tsconfig.json +++ b/federation/tsconfig.json @@ -60,7 +60,8 @@ /* external */ "@typeorm/*": ["../backend/src/typeorm/*", "../../backend/src/typeorm/*"], "@dbTools/*": ["../database/src/*", "../../database/build/src/*"], - "@entity/*": ["../database/entity/*", "../../database/build/entity/*"] + "@entity/*": ["../database/entity/*", "../../database/build/entity/*"], + "@logging/*": ["../database/logging/*", "../../database/build/logging/*"] }, // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ "typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */