mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 01:46:07 +00:00
Merge pull request #3272 from gradido/federation_optimize_logging
refactor(other): federation optimize logging, fix bug
This commit is contained in:
commit
4b4946ade0
@ -62,4 +62,5 @@ WEBHOOK_ELOPAGE_SECRET=secret
|
||||
# LOG_LEVEL=info
|
||||
|
||||
# Federation
|
||||
FEDERATION_VALIDATE_COMMUNITY_TIMER=60000
|
||||
FEDERATION_VALIDATE_COMMUNITY_TIMER=60000
|
||||
FEDERATION_XCOM_SENDCOINS_ENABLED=false
|
||||
@ -62,3 +62,4 @@ WEBHOOK_ELOPAGE_SECRET=$WEBHOOK_ELOPAGE_SECRET
|
||||
|
||||
# Federation
|
||||
FEDERATION_VALIDATE_COMMUNITY_TIMER=$FEDERATION_VALIDATE_COMMUNITY_TIMER
|
||||
FEDERATION_XCOM_SENDCOINS_ENABLED=$FEDERATION_XCOM_SENDCOINS_ENABLED
|
||||
@ -28,6 +28,11 @@ module.exports = {
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/entity/$1'
|
||||
: '<rootDir>/../database/build/entity/$1',
|
||||
'@logging/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/logging/$1'
|
||||
: '<rootDir>/../database/build/logging/$1',
|
||||
'@dbTools/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
|
||||
@ -28,9 +28,9 @@ export class AuthenticationClient {
|
||||
async openConnection(args: OpenConnectionArgs): Promise<boolean | undefined> {
|
||||
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',
|
||||
|
||||
@ -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
|
||||
@ -27,12 +28,17 @@ export class FederationClient {
|
||||
})
|
||||
}
|
||||
|
||||
getEndpoint = () => {
|
||||
return this.endpoint
|
||||
}
|
||||
|
||||
getPublicKey = async (): Promise<string | undefined> => {
|
||||
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,22 +46,25 @@ 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)
|
||||
const errorString = JSON.stringify(err)
|
||||
logger.warn('Federation: getPublicKey failed for endpoint', {
|
||||
endpoint: this.endpoint,
|
||||
err: errorString.length <= 200 ? errorString : errorString.substring(0, 200) + '...',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getPublicCommunityInfo = async (): Promise<PublicCommunityInfo | undefined> => {
|
||||
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,12 +73,17 @@ 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)
|
||||
const errorString = JSON.stringify(err)
|
||||
logger.warn('Federation: getPublicCommunityInfo failed for endpoint', {
|
||||
endpoint: this.endpoint,
|
||||
err: errorString.length <= 200 ? errorString : errorString.substring(0, 200) + '...',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<SendCoinsResult> {
|
||||
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<boolean> {
|
||||
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<boolean> {
|
||||
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<boolean> {
|
||||
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) {
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -47,15 +47,25 @@ export class FederationClientFactory {
|
||||
const instance = FederationClientFactory.instanceArray.find(
|
||||
(instance) => instance.id === dbCom.id,
|
||||
)
|
||||
if (instance) {
|
||||
// TODO: found a way to prevent double code with FederationClient::constructor
|
||||
const endpoint = `${dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'}${
|
||||
dbCom.apiVersion
|
||||
}/`
|
||||
// check if endpoint is still the same and not changed meanwhile
|
||||
if (instance && instance.client.getEndpoint() === endpoint) {
|
||||
return instance.client
|
||||
}
|
||||
const client = FederationClientFactory.createFederationClient(dbCom)
|
||||
if (client) {
|
||||
FederationClientFactory.instanceArray.push({
|
||||
id: dbCom.id,
|
||||
client,
|
||||
} as FederationClientInstance)
|
||||
// only update instance if we already have one
|
||||
if (instance) {
|
||||
instance.client = client
|
||||
} else {
|
||||
FederationClientFactory.instanceArray.push({
|
||||
id: dbCom.id,
|
||||
client,
|
||||
} as FederationClientInstance)
|
||||
}
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ describe('validate Communities', () => {
|
||||
return { data: {} } as Response<unknown>
|
||||
})
|
||||
const variables1 = {
|
||||
publicKey: Buffer.from('11111111111111111111111111111111'),
|
||||
publicKey: Buffer.from('11111111111111111111111111111111', 'hex'),
|
||||
apiVersion: '1_0',
|
||||
endPoint: 'http//localhost:5001/api/',
|
||||
lastAnnouncedAt: new Date(),
|
||||
@ -113,7 +113,7 @@ describe('validate Communities', () => {
|
||||
} as Response<unknown>
|
||||
})
|
||||
const variables1 = {
|
||||
publicKey: Buffer.from('11111111111111111111111111111111'),
|
||||
publicKey: Buffer.from('11111111111111111111111111111111', 'hex'),
|
||||
apiVersion: '1_0',
|
||||
endPoint: 'http//localhost:5001/api/',
|
||||
lastAnnouncedAt: new Date(),
|
||||
@ -195,7 +195,7 @@ describe('validate Communities', () => {
|
||||
} as Response<unknown>
|
||||
})
|
||||
const variables1 = {
|
||||
publicKey: Buffer.from('11111111111111111111111111111111'),
|
||||
publicKey: Buffer.from('11111111111111111111111111111111', 'hex'),
|
||||
apiVersion: '1_0',
|
||||
endPoint: 'http//localhost:5001/api/',
|
||||
lastAnnouncedAt: new Date(),
|
||||
@ -315,7 +315,7 @@ describe('validate Communities', () => {
|
||||
} as Response<unknown>
|
||||
})
|
||||
const variables3 = {
|
||||
publicKey: Buffer.from('11111111111111111111111111111111'),
|
||||
publicKey: Buffer.from('11111111111111111111111111111111', 'hex'),
|
||||
apiVersion: '2_0',
|
||||
endPoint: 'http//localhost:5001/api/',
|
||||
lastAnnouncedAt: new Date(),
|
||||
|
||||
@ -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<void> {
|
||||
@ -37,7 +38,7 @@ export async function validateCommunities(): Promise<void> {
|
||||
|
||||
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<void> {
|
||||
// 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<void> {
|
||||
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<void> {
|
||||
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 {
|
||||
|
||||
@ -6,7 +6,7 @@ export class FederatedCommunity {
|
||||
constructor(dbCom: DbFederatedCommunity) {
|
||||
this.id = dbCom.id
|
||||
this.foreign = dbCom.foreign
|
||||
this.publicKey = dbCom.publicKey.toString()
|
||||
this.publicKey = dbCom.publicKey.toString('hex')
|
||||
this.url =
|
||||
(dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/') + dbCom.apiVersion
|
||||
this.lastAnnouncedAt = dbCom.lastAnnouncedAt
|
||||
|
||||
@ -34,6 +34,60 @@ afterAll(async () => {
|
||||
await con.close()
|
||||
})
|
||||
|
||||
// real valid ed25519 key pairs
|
||||
const ed25519KeyPairStaticHex = [
|
||||
{
|
||||
public: '264c1e88914d18166cc31e8d6c2111c03ac83f5910398eb45cd425c6c3836367',
|
||||
private:
|
||||
'0ddcafd5e2da92e171ccc974af22fee3ad8407475e330586c8f259837d4fedc6264c1e88914d18166cc31e8d6c2111c03ac83f5910398eb45cd425c6c3836367',
|
||||
},
|
||||
{
|
||||
public: 'ac18a8754f725079f93d27b9054f2eff536109a2fd439f9755941abdd639baf0',
|
||||
private:
|
||||
'45325a0d0f22655095321d9d05999c65245da02130318ff51da1ee423b836117ac18a8754f725079f93d27b9054f2eff536109a2fd439f9755941abdd639baf0',
|
||||
},
|
||||
{
|
||||
public: '6f7d4ccde610db1e1a33fabbb444d5400013c168296b03fd50bc686d4c1ad0ed',
|
||||
private:
|
||||
'8ab6d5da8b666ef5b3d754559c028806a1e2f8142a3e7ada411a8b6a3fe70eeb6f7d4ccde610db1e1a33fabbb444d5400013c168296b03fd50bc686d4c1ad0ed',
|
||||
},
|
||||
{
|
||||
public: '85fbbce0763db24677cf7cb579a743013557a4fea0a9a624245f3ae8cd785e1d',
|
||||
private:
|
||||
'0369ea7c80c3134c2872c3cf77a68f12d57de57359145b550e3a0c4c8170a31785fbbce0763db24677cf7cb579a743013557a4fea0a9a624245f3ae8cd785e1d',
|
||||
},
|
||||
{
|
||||
public: 'b099d023476ece01f231c269cbe496139ca73b3b4eb705816a511a1ca09661d0',
|
||||
private:
|
||||
'015ac650157b9e9bdbe718940606242daa318a251e8417b49440495e5afe3750b099d023476ece01f231c269cbe496139ca73b3b4eb705816a511a1ca09661d0',
|
||||
},
|
||||
{
|
||||
public: '9f8dc17f1af9f71e9b9a1cd49ca295b89049863515a487578ad4f90b307abf39',
|
||||
private:
|
||||
'0c13e71c55a3c03bd5df05c92bbccde88ad4a47f3bac6bdc5383ef1ec946cfdc9f8dc17f1af9f71e9b9a1cd49ca295b89049863515a487578ad4f90b307abf39',
|
||||
},
|
||||
{
|
||||
public: '34218b2f570d341370dd2db111d0ef2415c03a110c3bf3127c6b2337af71753a',
|
||||
private:
|
||||
'60f3479bba44d035886ac21c362bceece9f9ec81859c9b37f734b6442a06c93b34218b2f570d341370dd2db111d0ef2415c03a110c3bf3127c6b2337af71753a',
|
||||
},
|
||||
{
|
||||
public: 'a447404f5e04ed4896ed64d0f704574ed780b52e90868d4b83e1afb8ea687ff6',
|
||||
private:
|
||||
'ea85ebb4332a52d87fe6f322dcd23ad4afc5eafb93dfff2216f3ffa9f0730e8aa447404f5e04ed4896ed64d0f704574ed780b52e90868d4b83e1afb8ea687ff6',
|
||||
},
|
||||
{
|
||||
public: 'b8b987c55da62b30d929672520551033eb37abdd88f9ea104db5d107c19680b4',
|
||||
private:
|
||||
'29475dbbc96d694b3c653a1e143caf084f6daf2d35267522c4096c55b47e2b76b8b987c55da62b30d929672520551033eb37abdd88f9ea104db5d107c19680b4',
|
||||
},
|
||||
{
|
||||
public: '40203d18a6ff8fb3c4c62d78e4807036fc9207782ce97a9bcf3be0755c236c37',
|
||||
private:
|
||||
'0b5c4d536d222e88b561ea495e15918fb8cba61a3f8c261ec9e587cca560804040203d18a6ff8fb3c4c62d78e4807036fc9207782ce97a9bcf3be0755c236c37',
|
||||
},
|
||||
]
|
||||
|
||||
describe('CommunityResolver', () => {
|
||||
describe('getCommunities', () => {
|
||||
let homeCom1: DbFederatedCommunity
|
||||
@ -62,7 +116,7 @@ describe('CommunityResolver', () => {
|
||||
|
||||
homeCom1 = DbFederatedCommunity.create()
|
||||
homeCom1.foreign = false
|
||||
homeCom1.publicKey = Buffer.from('publicKey-HomeCommunity')
|
||||
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
||||
homeCom1.apiVersion = '1_0'
|
||||
homeCom1.endPoint = 'http://localhost/api'
|
||||
homeCom1.createdAt = new Date()
|
||||
@ -70,7 +124,7 @@ describe('CommunityResolver', () => {
|
||||
|
||||
homeCom2 = DbFederatedCommunity.create()
|
||||
homeCom2.foreign = false
|
||||
homeCom2.publicKey = Buffer.from('publicKey-HomeCommunity')
|
||||
homeCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[1].public, 'hex')
|
||||
homeCom2.apiVersion = '1_1'
|
||||
homeCom2.endPoint = 'http://localhost/api'
|
||||
homeCom2.createdAt = new Date()
|
||||
@ -78,7 +132,7 @@ describe('CommunityResolver', () => {
|
||||
|
||||
homeCom3 = DbFederatedCommunity.create()
|
||||
homeCom3.foreign = false
|
||||
homeCom3.publicKey = Buffer.from('publicKey-HomeCommunity')
|
||||
homeCom3.publicKey = Buffer.from(ed25519KeyPairStaticHex[2].public, 'hex')
|
||||
homeCom3.apiVersion = '2_0'
|
||||
homeCom3.endPoint = 'http://localhost/api'
|
||||
homeCom3.createdAt = new Date()
|
||||
@ -92,7 +146,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 3,
|
||||
foreign: homeCom3.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-HomeCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[2].public),
|
||||
url: expect.stringMatching('http://localhost/api/2_0'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -103,7 +157,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 2,
|
||||
foreign: homeCom2.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-HomeCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[1].public),
|
||||
url: expect.stringMatching('http://localhost/api/1_1'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -114,7 +168,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 1,
|
||||
foreign: homeCom1.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-HomeCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
||||
url: expect.stringMatching('http://localhost/api/1_0'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -134,7 +188,7 @@ describe('CommunityResolver', () => {
|
||||
|
||||
foreignCom1 = DbFederatedCommunity.create()
|
||||
foreignCom1.foreign = true
|
||||
foreignCom1.publicKey = Buffer.from('publicKey-ForeignCommunity')
|
||||
foreignCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[3].public, 'hex')
|
||||
foreignCom1.apiVersion = '1_0'
|
||||
foreignCom1.endPoint = 'http://remotehost/api'
|
||||
foreignCom1.createdAt = new Date()
|
||||
@ -142,7 +196,7 @@ describe('CommunityResolver', () => {
|
||||
|
||||
foreignCom2 = DbFederatedCommunity.create()
|
||||
foreignCom2.foreign = true
|
||||
foreignCom2.publicKey = Buffer.from('publicKey-ForeignCommunity')
|
||||
foreignCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[4].public, 'hex')
|
||||
foreignCom2.apiVersion = '1_1'
|
||||
foreignCom2.endPoint = 'http://remotehost/api'
|
||||
foreignCom2.createdAt = new Date()
|
||||
@ -150,7 +204,7 @@ describe('CommunityResolver', () => {
|
||||
|
||||
foreignCom3 = DbFederatedCommunity.create()
|
||||
foreignCom3.foreign = true
|
||||
foreignCom3.publicKey = Buffer.from('publicKey-ForeignCommunity')
|
||||
foreignCom3.publicKey = Buffer.from(ed25519KeyPairStaticHex[5].public, 'hex')
|
||||
foreignCom3.apiVersion = '1_2'
|
||||
foreignCom3.endPoint = 'http://remotehost/api'
|
||||
foreignCom3.createdAt = new Date()
|
||||
@ -164,7 +218,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 3,
|
||||
foreign: homeCom3.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-HomeCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[2].public),
|
||||
url: expect.stringMatching('http://localhost/api/2_0'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -175,7 +229,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 2,
|
||||
foreign: homeCom2.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-HomeCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[1].public),
|
||||
url: expect.stringMatching('http://localhost/api/1_1'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -186,7 +240,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 1,
|
||||
foreign: homeCom1.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-HomeCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
||||
url: expect.stringMatching('http://localhost/api/1_0'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -197,7 +251,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 6,
|
||||
foreign: foreignCom3.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-ForeignCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[5].public),
|
||||
url: expect.stringMatching('http://remotehost/api/1_2'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -208,7 +262,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 5,
|
||||
foreign: foreignCom2.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-ForeignCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[4].public),
|
||||
url: expect.stringMatching('http://remotehost/api/1_1'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -219,7 +273,7 @@ describe('CommunityResolver', () => {
|
||||
{
|
||||
id: 4,
|
||||
foreign: foreignCom1.foreign,
|
||||
publicKey: expect.stringMatching('publicKey-ForeignCommunity'),
|
||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[3].public),
|
||||
url: expect.stringMatching('http://remotehost/api/1_0'),
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
@ -264,8 +318,8 @@ describe('CommunityResolver', () => {
|
||||
homeCom1 = DbCommunity.create()
|
||||
homeCom1.foreign = false
|
||||
homeCom1.url = 'http://localhost/api'
|
||||
homeCom1.publicKey = Buffer.from('publicKey-HomeCommunity')
|
||||
homeCom1.privateKey = Buffer.from('privateKey-HomeCommunity')
|
||||
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
||||
homeCom1.privateKey = Buffer.from(ed25519KeyPairStaticHex[0].private, 'hex')
|
||||
homeCom1.communityUuid = 'HomeCom-UUID'
|
||||
homeCom1.authenticatedAt = new Date()
|
||||
homeCom1.name = 'HomeCommunity-name'
|
||||
@ -302,8 +356,8 @@ describe('CommunityResolver', () => {
|
||||
homeCom1 = DbCommunity.create()
|
||||
homeCom1.foreign = false
|
||||
homeCom1.url = 'http://localhost/api'
|
||||
homeCom1.publicKey = Buffer.from('publicKey-HomeCommunity')
|
||||
homeCom1.privateKey = Buffer.from('privateKey-HomeCommunity')
|
||||
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
||||
homeCom1.privateKey = Buffer.from(ed25519KeyPairStaticHex[0].private, 'hex')
|
||||
homeCom1.communityUuid = 'HomeCom-UUID'
|
||||
homeCom1.authenticatedAt = new Date()
|
||||
homeCom1.name = 'HomeCommunity-name'
|
||||
@ -314,8 +368,8 @@ describe('CommunityResolver', () => {
|
||||
foreignCom1 = DbCommunity.create()
|
||||
foreignCom1.foreign = true
|
||||
foreignCom1.url = 'http://stage-2.gradido.net/api'
|
||||
foreignCom1.publicKey = Buffer.from('publicKey-stage-2_Community')
|
||||
foreignCom1.privateKey = Buffer.from('privateKey-stage-2_Community')
|
||||
foreignCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[3].public, 'hex')
|
||||
foreignCom1.privateKey = Buffer.from(ed25519KeyPairStaticHex[3].private, 'hex')
|
||||
// foreignCom1.communityUuid = 'Stage2-Com-UUID'
|
||||
// foreignCom1.authenticatedAt = new Date()
|
||||
foreignCom1.name = 'Stage-2_Community-name'
|
||||
@ -326,8 +380,8 @@ describe('CommunityResolver', () => {
|
||||
foreignCom2 = DbCommunity.create()
|
||||
foreignCom2.foreign = true
|
||||
foreignCom2.url = 'http://stage-3.gradido.net/api'
|
||||
foreignCom2.publicKey = Buffer.from('publicKey-stage-3_Community')
|
||||
foreignCom2.privateKey = Buffer.from('privateKey-stage-3_Community')
|
||||
foreignCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[4].public, 'hex')
|
||||
foreignCom2.privateKey = Buffer.from(ed25519KeyPairStaticHex[4].private, 'hex')
|
||||
foreignCom2.communityUuid = 'Stage3-Com-UUID'
|
||||
foreignCom2.authenticatedAt = new Date()
|
||||
foreignCom2.name = 'Stage-3_Community-name'
|
||||
|
||||
@ -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. */
|
||||
|
||||
38
database/logging/AbstractLogging.view.ts
Normal file
38
database/logging/AbstractLogging.view.ts
Normal file
@ -0,0 +1,38 @@
|
||||
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(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
|
||||
[util.inspect.custom](): string {
|
||||
return this.toString()
|
||||
}
|
||||
|
||||
public dateToString(date: Date | undefined | null): string | undefined {
|
||||
if (date) {
|
||||
return date.toISOString()
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
public decimalToString(number: Decimal | undefined | null): string | undefined {
|
||||
if (number) {
|
||||
return number.toString()
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
26
database/logging/CommunityLogging.view.ts
Normal file
26
database/logging/CommunityLogging.view.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Community } from '../entity/Community'
|
||||
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
|
||||
export class CommunityLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: Community) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
foreign: this.self.foreign,
|
||||
url: this.self.url,
|
||||
publicKey: this.self.publicKey.toString(this.bufferStringFormat),
|
||||
communityUuid: this.self.communityUuid,
|
||||
authenticatedAt: this.dateToString(this.self.authenticatedAt),
|
||||
name: this.self.name,
|
||||
description: this.self.description?.substring(0, 24),
|
||||
creationDate: this.dateToString(this.self.creationDate),
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
}
|
||||
}
|
||||
}
|
||||
45
database/logging/ContributionLogging.view.ts
Normal file
45
database/logging/ContributionLogging.view.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { Contribution } from '../entity/Contribution'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { ContributionMessageLoggingView } from './ContributionMessageLogging.view'
|
||||
import { TransactionLoggingView } from './TransactionLogging.view'
|
||||
import { UserLoggingView } from './UserLogging.view'
|
||||
|
||||
export class ContributionLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: Contribution) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
user: this.self.user
|
||||
? new UserLoggingView(this.self.user).toJSON()
|
||||
: { id: this.self.userId },
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
resubmissionAt: this.dateToString(this.self.resubmissionAt),
|
||||
contributionDate: this.dateToString(this.self.contributionDate),
|
||||
memoLength: this.self.memo.length,
|
||||
amount: this.decimalToString(this.self.amount),
|
||||
moderatorId: this.self.moderatorId,
|
||||
contributionLinkId: this.self.contributionLinkId,
|
||||
confirmedBy: this.self.confirmedBy,
|
||||
confirmedAt: this.dateToString(this.self.confirmedAt),
|
||||
deniedBy: this.self.deniedBy,
|
||||
deniedAt: this.dateToString(this.self.deniedAt),
|
||||
contributionType: this.self.contributionType,
|
||||
contributionStatus: this.self.contributionStatus,
|
||||
transactionId: this.self.transactionId,
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
updatedBy: this.self.updatedBy,
|
||||
deletedAt: this.dateToString(this.self.deletedAt),
|
||||
deletedBy: this.self.deletedBy,
|
||||
messages: this.self.messages
|
||||
? this.self.messages.map((message) => new ContributionMessageLoggingView(message).toJSON())
|
||||
: undefined,
|
||||
transaction: this.self.transaction
|
||||
? new TransactionLoggingView(this.self.transaction).toJSON()
|
||||
: { id: this.self.transactionId },
|
||||
}
|
||||
}
|
||||
}
|
||||
30
database/logging/ContributionMessageLogging.view.ts
Normal file
30
database/logging/ContributionMessageLogging.view.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { ContributionMessage } from '../entity/ContributionMessage'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { ContributionLoggingView } from './ContributionLogging.view'
|
||||
import { UserLoggingView } from './UserLogging.view'
|
||||
|
||||
export class ContributionMessageLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: ContributionMessage) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
contribution: this.self.contribution
|
||||
? new ContributionLoggingView(this.self.contribution).toJSON()
|
||||
: { id: this.self.contributionId },
|
||||
user: this.self.user
|
||||
? new UserLoggingView(this.self.user).toJSON()
|
||||
: { id: this.self.userId },
|
||||
messageLength: this.self.message.length,
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
deletedAt: this.dateToString(this.self.deletedAt),
|
||||
deletedBy: this.self.deletedBy,
|
||||
type: this.self.type,
|
||||
isModerator: this.self.isModerator,
|
||||
}
|
||||
}
|
||||
}
|
||||
23
database/logging/DltTransactionLogging.view.ts
Normal file
23
database/logging/DltTransactionLogging.view.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { DltTransaction } from '../entity/DltTransaction'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { TransactionLoggingView } from './TransactionLogging.view'
|
||||
|
||||
export class DltTransactionLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: DltTransaction) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
transaction: this.self.transaction
|
||||
? new TransactionLoggingView(this.self.transaction).toJSON()
|
||||
: { id: this.self.transactionId },
|
||||
messageId: this.self.messageId,
|
||||
verified: this.self.verified,
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
verifiedAt: this.dateToString(this.self.verifiedAt),
|
||||
}
|
||||
}
|
||||
}
|
||||
24
database/logging/FederatedCommunityLogging.view.ts
Normal file
24
database/logging/FederatedCommunityLogging.view.ts
Normal file
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
27
database/logging/PendingTransactionLogging.view.ts
Normal file
27
database/logging/PendingTransactionLogging.view.ts
Normal file
@ -0,0 +1,27 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { PendingTransaction } from '../entity/PendingTransaction'
|
||||
import { Transaction } from '../entity/Transaction'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { TransactionLoggingView } from './TransactionLogging.view'
|
||||
|
||||
// TODO: move enum into database, maybe rename database
|
||||
enum PendingTransactionState {
|
||||
NEW = 1,
|
||||
PENDING = 2,
|
||||
SETTLED = 3,
|
||||
REVERTED = 4,
|
||||
}
|
||||
|
||||
export class PendingTransactionLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: PendingTransaction) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
...new TransactionLoggingView(this.self as Transaction).toJSON(),
|
||||
state: PendingTransactionState[this.self.state],
|
||||
}
|
||||
}
|
||||
}
|
||||
56
database/logging/TransactionLogging.view.ts
Normal file
56
database/logging/TransactionLogging.view.ts
Normal file
@ -0,0 +1,56 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { Transaction } from '../entity/Transaction'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { ContributionLoggingView } from './ContributionLogging.view'
|
||||
import { DltTransactionLoggingView } from './DltTransactionLogging.view'
|
||||
|
||||
// TODO: move enum into database, maybe rename database
|
||||
enum TransactionTypeId {
|
||||
CREATION = 1,
|
||||
SEND = 2,
|
||||
RECEIVE = 3,
|
||||
// This is a virtual property, never occurring on the database
|
||||
DECAY = 4,
|
||||
LINK_SUMMARY = 5,
|
||||
}
|
||||
|
||||
export class TransactionLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: Transaction) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
previous: this.self.previous,
|
||||
typeId: TransactionTypeId[this.self.typeId],
|
||||
transactionLinkId: this.self.transactionLinkId,
|
||||
amount: this.decimalToString(this.self.amount),
|
||||
balance: this.decimalToString(this.self.balance),
|
||||
balanceDate: this.dateToString(this.self.balanceDate),
|
||||
decay: this.decimalToString(this.self.decay),
|
||||
decayStart: this.dateToString(this.self.decayStart),
|
||||
memoLength: this.self.memo.length,
|
||||
creationDate: this.dateToString(this.self.creationDate),
|
||||
userId: this.self.userId,
|
||||
userCommunityUuid: this.self.userCommunityUuid,
|
||||
userGradidoId: this.self.userGradidoID,
|
||||
userName: this.self.userName?.substring(0, 3) + '...',
|
||||
linkedUserId: this.self.linkedUserId,
|
||||
linkedUserCommunityUuid: this.self.linkedUserCommunityUuid,
|
||||
linkedUserGradidoID: this.self.linkedUserGradidoID,
|
||||
linkedUserName: this.self.linkedUserName?.substring(0, 3) + '...',
|
||||
linkedTransactionId: this.self.linkedTransactionId,
|
||||
contribution: this.self.contribution
|
||||
? new ContributionLoggingView(this.self.contribution)
|
||||
: undefined,
|
||||
dltTransaction: this.self.dltTransaction
|
||||
? new DltTransactionLoggingView(this.self.dltTransaction).toJSON()
|
||||
: undefined,
|
||||
previousTransaction: this.self.previousTransaction
|
||||
? new TransactionLoggingView(this.self.previousTransaction).toJSON()
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
35
database/logging/UserContactLogging.view.ts
Normal file
35
database/logging/UserContactLogging.view.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { UserContact } from '../entity/UserContact'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { UserLoggingView } from './UserLogging.view'
|
||||
|
||||
enum OptInType {
|
||||
EMAIL_OPT_IN_REGISTER = 1,
|
||||
EMAIL_OPT_IN_RESET_PASSWORD = 2,
|
||||
}
|
||||
|
||||
export class UserContactLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: UserContact) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
type: this.self.type,
|
||||
user: this.self.user
|
||||
? new UserLoggingView(this.self.user).toJSON()
|
||||
: { id: this.self.userId },
|
||||
email: this.self.email?.substring(0, 3) + '...',
|
||||
emailVerificationCode: this.self.emailVerificationCode?.substring(0, 4) + '...',
|
||||
emailOptInTypeId: OptInType[this.self.emailOptInTypeId],
|
||||
emailResendCount: this.self.emailResendCount,
|
||||
emailChecked: this.self.emailChecked,
|
||||
phone: this.self.phone ? this.self.phone.substring(0, 3) + '...' : undefined,
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
deletedAt: this.dateToString(this.self.deletedAt),
|
||||
}
|
||||
}
|
||||
}
|
||||
60
database/logging/UserLogging.view.ts
Normal file
60
database/logging/UserLogging.view.ts
Normal file
@ -0,0 +1,60 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import { User } from '../entity/User'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { ContributionLoggingView } from './ContributionLogging.view'
|
||||
import { ContributionMessageLoggingView } from './ContributionMessageLogging.view'
|
||||
import { UserContactLoggingView } from './UserContactLogging.view'
|
||||
import { UserRoleLoggingView } from './UserRoleLogging.view'
|
||||
|
||||
enum PasswordEncryptionType {
|
||||
NO_PASSWORD = 0,
|
||||
EMAIL = 1,
|
||||
GRADIDO_ID = 2,
|
||||
}
|
||||
|
||||
export class UserLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: User) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
foreign: this.self.foreign,
|
||||
gradidoID: this.self.gradidoID,
|
||||
communityUuid: this.self.communityUuid,
|
||||
alias: this.self.alias?.substring(0, 3) + '...',
|
||||
emailContact: this.self.emailContact
|
||||
? new UserContactLoggingView(this.self.emailContact).toJSON()
|
||||
: { id: this.self.emailId },
|
||||
firstName: this.self.firstName?.substring(0, 3) + '...',
|
||||
lastName: this.self.lastName?.substring(0, 3) + '...',
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
deletedAt: this.dateToString(this.self.deletedAt),
|
||||
passwordEncryptionType: this.self.passwordEncryptionType as PasswordEncryptionType,
|
||||
language: this.self.language,
|
||||
hideAmountGDD: this.self.hideAmountGDD,
|
||||
hideAmountGDT: this.self.hideAmountGDT,
|
||||
userRoles: this.self.userRoles
|
||||
? this.self.userRoles.map((userRole) => new UserRoleLoggingView(userRole).toJSON())
|
||||
: undefined,
|
||||
referrerId: this.self.referrerId,
|
||||
contributionLinkId: this.self.contributionLinkId,
|
||||
publisherId: this.self.publisherId,
|
||||
contributions: this.self.contributions
|
||||
? this.self.contributions.map((contribution) =>
|
||||
new ContributionLoggingView(contribution).toJSON(),
|
||||
)
|
||||
: undefined,
|
||||
messages: this.self.messages
|
||||
? this.self.messages.map((message) => new ContributionMessageLoggingView(message).toJSON())
|
||||
: undefined,
|
||||
userContacts: this.self.userContacts
|
||||
? this.self.userContacts.map((userContact) =>
|
||||
new UserContactLoggingView(userContact).toJSON(),
|
||||
)
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
22
database/logging/UserRoleLogging.view.ts
Normal file
22
database/logging/UserRoleLogging.view.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { UserRole } from '../entity/UserRole'
|
||||
import { AbstractLoggingView } from './AbstractLogging.view'
|
||||
import { UserLoggingView } from './UserLogging.view'
|
||||
|
||||
export class UserRoleLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: UserRole) {
|
||||
super()
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public toJSON(): any {
|
||||
return {
|
||||
id: this.self.id,
|
||||
user: this.self.user
|
||||
? new UserLoggingView(this.self.user).toJSON()
|
||||
: { id: this.self.userId },
|
||||
role: this.self.role,
|
||||
createdAt: this.dateToString(this.self.createdAt),
|
||||
updatedAt: this.dateToString(this.self.updatedAt),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,9 @@ EMAIL_PASSWORD=1234
|
||||
EMAIL_SMTP_URL=smtp.lustig.de
|
||||
EMAIL_SMTP_PORT=587
|
||||
|
||||
# if set to true allow sending gradidos to another communities
|
||||
FEDERATION_XCOM_SENDCOINS_ENABLED=false
|
||||
|
||||
# how many minutes email verification code is valid
|
||||
# also used for password reset code
|
||||
EMAIL_CODE_VALID_TIME=1440
|
||||
@ -25,8 +28,8 @@ DATABASE_CONFIG_VERSION=v1.2022-03-18
|
||||
BACKEND_CONFIG_VERSION=v21.2024-01-06
|
||||
FRONTEND_CONFIG_VERSION=v5.2024-01-08
|
||||
ADMIN_CONFIG_VERSION=v2.2024-01-04
|
||||
FEDERATION_CONFIG_VERSION=v1.2023-01-09
|
||||
FEDERATION_DHT_CONFIG_VERSION=v3.2023-04-26
|
||||
FEDERATION_CONFIG_VERSION=v2.2023-08-24
|
||||
FEDERATION_DHT_CONFIG_VERSION=v4.2024-01-17
|
||||
|
||||
FEDERATION_DHT_TOPIC=GRADIDO_HUB
|
||||
|
||||
@ -76,7 +79,7 @@ FEDERATION_COMMUNITY_API_PORT=5000
|
||||
FEDERATION_VALIDATE_COMMUNITY_TIMER=60000
|
||||
|
||||
# comma separated list of api-versions, which cause starting several federation modules
|
||||
FEDERATION_COMMUNITY_APIS=1_0,1_1
|
||||
FEDERATION_COMMUNITY_APIS=1_0
|
||||
|
||||
# externe gradido services (more added in future)
|
||||
GDT_API_URL=https://gdt.gradido.net
|
||||
|
||||
@ -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
|
||||
@ -1,5 +1,5 @@
|
||||
# must match the CONFIG_VERSION.EXPECTED definition in scr/config/index.ts
|
||||
CONFIG_VERSION=v3.2023-04-26
|
||||
CONFIG_VERSION=$FEDERATION_DHT_CONFIG_VERSION
|
||||
|
||||
# Database
|
||||
DB_HOST=localhost
|
||||
@ -19,6 +19,7 @@ FEDERATION_DHT_CONFIG_VERSION=$FEDERATION_DHT_CONFIG_VERSION
|
||||
# on an hash created from this topic
|
||||
FEDERATION_DHT_TOPIC=$FEDERATION_DHT_TOPIC
|
||||
FEDERATION_DHT_SEED=$FEDERATION_DHT_SEED
|
||||
# comma separated values, which apis should be announced
|
||||
FEDERATION_COMMUNITY_APIS=$FEDERATION_COMMUNITY_APIS
|
||||
COMMUNITY_HOST=$COMMUNITY_HOST
|
||||
URL_PROTOCOL=$URL_PROTOCOL
|
||||
FEDERATION_COMMUNITY_API_PORT=$FEDERATION_COMMUNITY_API_PORT
|
||||
|
||||
@ -7,7 +7,7 @@ module.exports = {
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 83,
|
||||
lines: 82,
|
||||
},
|
||||
},
|
||||
setupFiles: ['<rootDir>/test/testSetup.ts'],
|
||||
@ -21,6 +21,11 @@ module.exports = {
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/entity/$1'
|
||||
: '<rootDir>/../database/build/entity/$1',
|
||||
'@logging/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/logging/$1'
|
||||
: '<rootDir>/../database/build/logging/$1',
|
||||
'@dbTools/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
|
||||
@ -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: '',
|
||||
},
|
||||
}
|
||||
@ -43,7 +43,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 ?? COMMUNITY_URL,
|
||||
FEDERATION_COMMUNITY_API_PORT: process.env.FEDERATION_COMMUNITY_API_PORT ?? '5000',
|
||||
FEDERATION_COMMUNITY_APIS: process.env.FEDERATION_COMMUNITY_APIS ?? '1_0',
|
||||
}
|
||||
|
||||
// Check config version
|
||||
|
||||
5
dht-node/src/dht_node/ApiVersionType.ts
Normal file
5
dht-node/src/dht_node/ApiVersionType.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum ApiVersionType {
|
||||
V1_0 = '1_0',
|
||||
V1_1 = '1_1', // currently no changes
|
||||
V2_0 = '2_0', // not exist
|
||||
}
|
||||
@ -14,6 +14,7 @@ import { CONFIG } from '@/config'
|
||||
import { startDHT } from './index'
|
||||
|
||||
CONFIG.FEDERATION_DHT_SEED = '64ebcb0e3ad547848fef4197c6e2332f'
|
||||
CONFIG.FEDERATION_COMMUNITY_APIS = '1_0,1_1,2_0'
|
||||
|
||||
jest.mock('@hyperswarm/dht')
|
||||
|
||||
@ -253,6 +254,29 @@ describe('federation', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('with receiving non ascii character', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
// containing non-ascii character copyright symbol, U+00A9
|
||||
socketEventMocks.data(Buffer.from('48656C6C6F2C20C2A92048656C6C6F21', 'hex'))
|
||||
/*
|
||||
const buffer = Buffer.from('48656C6C6F2C20C2A92048656C6C6F21', 'hex')
|
||||
for (const byte of buffer) {
|
||||
console.log('byte: %o', byte)
|
||||
if (byte > 127) {
|
||||
console.log('non ascii char spotted')
|
||||
}
|
||||
}
|
||||
*/
|
||||
})
|
||||
|
||||
it('logs the binary data as hex', () => {
|
||||
expect(logger.warn).toBeCalledWith(
|
||||
'received non ascii character, content as hex: 48656c6c6f2c20c2a92048656c6c6f21',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with receiving array of strings', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
|
||||
@ -3,11 +3,14 @@
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity'
|
||||
import DHT from '@hyperswarm/dht'
|
||||
import { CommunityLoggingView } from '@logging/CommunityLogging.view'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { logger } from '@/server/logger'
|
||||
|
||||
import { ApiVersionType } from './ApiVersionType'
|
||||
|
||||
const KEY_SECRET_SEEDBYTES = 32
|
||||
|
||||
const POLLTIME = 20000
|
||||
@ -15,11 +18,6 @@ const SUCCESSTIME = 120000
|
||||
const ERRORTIME = 240000
|
||||
const ANNOUNCETIME = 30000
|
||||
|
||||
enum ApiVersionType {
|
||||
V1_0 = '1_0',
|
||||
V1_1 = '1_1',
|
||||
V2_0 = '2_0',
|
||||
}
|
||||
type CommunityApi = {
|
||||
api: string
|
||||
url: string
|
||||
@ -27,6 +25,15 @@ type CommunityApi = {
|
||||
|
||||
type KeyPair = { publicKey: Buffer; secretKey: Buffer }
|
||||
|
||||
function isAscii(buffer: Buffer): boolean {
|
||||
for (const byte of buffer) {
|
||||
if (byte > 127) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export const startDHT = async (topic: string): Promise<void> => {
|
||||
try {
|
||||
const TOPIC = DHT.hash(Buffer.from(topic))
|
||||
@ -59,6 +66,10 @@ export const startDHT = async (topic: string): Promise<void> => {
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!isAscii(data)) {
|
||||
logger.warn(`received non ascii character, content as hex: ${data.toString('hex')}`)
|
||||
return
|
||||
}
|
||||
logger.info(`data: ${data.toString('ascii')}`)
|
||||
const recApiVersions: CommunityApi[] = JSON.parse(data.toString('ascii'))
|
||||
|
||||
@ -190,9 +201,14 @@ export const startDHT = async (topic: string): Promise<void> => {
|
||||
}
|
||||
|
||||
async function writeFederatedHomeCommunityEntries(pubKey: string): Promise<CommunityApi[]> {
|
||||
const homeApiVersions: CommunityApi[] = Object.values(ApiVersionType).map(function (apiEnum) {
|
||||
const homeApiVersions: CommunityApi[] = CONFIG.FEDERATION_COMMUNITY_APIS.split(',').map(function (
|
||||
api,
|
||||
) {
|
||||
if (!Object.values(ApiVersionType).includes(api as ApiVersionType)) {
|
||||
throw new Error(`Federation: unknown api version: ${api}`)
|
||||
}
|
||||
const comApi: CommunityApi = {
|
||||
api: apiEnum,
|
||||
api,
|
||||
url: CONFIG.FEDERATION_COMMUNITY_URL + '/api/',
|
||||
}
|
||||
return comApi
|
||||
@ -227,7 +243,7 @@ async function writeHomeCommunityEntry(keyPair: KeyPair): Promise<void> {
|
||||
homeCom.name = CONFIG.COMMUNITY_NAME
|
||||
homeCom.description = CONFIG.COMMUNITY_DESCRIPTION
|
||||
await DbCommunity.save(homeCom)
|
||||
logger.info(`home-community updated successfully:`, homeCom)
|
||||
logger.info(`home-community updated successfully:`, new CommunityLoggingView(homeCom))
|
||||
} else {
|
||||
// insert a new homecommunity entry including a new ID and a new but ensured unique UUID
|
||||
homeCom = new DbCommunity()
|
||||
@ -240,7 +256,7 @@ async function writeHomeCommunityEntry(keyPair: KeyPair): Promise<void> {
|
||||
homeCom.description = CONFIG.COMMUNITY_DESCRIPTION
|
||||
homeCom.creationDate = new Date()
|
||||
await DbCommunity.insert(homeCom)
|
||||
logger.info(`home-community inserted successfully:`, homeCom)
|
||||
logger.info(`home-community inserted successfully:`, new CommunityLoggingView(homeCom))
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(`Federation: Error writing HomeCommunity-Entry: ${err}`)
|
||||
|
||||
@ -52,7 +52,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": ["src/dht_node/@types", "node_modules/@types"], /* List of folders to include type definitions from. */
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# must match the CONFIG_VERSION.EXPECTED definition in scr/config/index.ts
|
||||
CONFIG_VERSION=v2.2023-08-24
|
||||
CONFIG_VERSION=$FEDERATION_CONFIG_VERSION
|
||||
|
||||
LOG_LEVEL=$LOG_LEVEL
|
||||
# this is set fix to false, because it is important for 'production' environments. only set to true if a graphql-playground should be in use
|
||||
|
||||
@ -24,6 +24,11 @@ module.exports = {
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/entity/$1'
|
||||
: '<rootDir>/../database/build/entity/$1',
|
||||
'@logging/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/logging/$1'
|
||||
: '<rootDir>/../database/build/logging/$1',
|
||||
'@dbTools/(.*)':
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/src/$1'
|
||||
|
||||
@ -63,7 +63,10 @@ export class AuthenticationClient {
|
||||
return authUuid
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Authentication: authenticate failed for endpoint', this.endpoint)
|
||||
logger.error('Authentication: authenticate failed', {
|
||||
endpoint: this.endpoint,
|
||||
err,
|
||||
})
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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<string | null> {
|
||||
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) {
|
||||
|
||||
@ -46,7 +46,10 @@ describe('PublicCommunityInfoResolver', () => {
|
||||
homeCom.name = 'Community-Name'
|
||||
homeCom.description = 'Community-Description'
|
||||
homeCom.creationDate = new Date()
|
||||
homeCom.publicKey = Buffer.from('homeCommunity-publicKey')
|
||||
homeCom.publicKey = Buffer.from(
|
||||
'316f2951501f27c664e188d5128505917e8673e8bebce141f86e70907e782a08',
|
||||
'hex',
|
||||
)
|
||||
await DbCommunity.insert(homeCom)
|
||||
})
|
||||
|
||||
@ -57,7 +60,7 @@ describe('PublicCommunityInfoResolver', () => {
|
||||
name: 'Community-Name',
|
||||
description: 'Community-Description',
|
||||
creationDate: homeCom.creationDate?.toISOString(),
|
||||
publicKey: expect.stringMatching('homeCommunity-publicKey'),
|
||||
publicKey: '316f2951501f27c664e188d5128505917e8673e8bebce141f86e70907e782a08',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -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<GetPublicCommunityInfoResult> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +39,10 @@ describe('PublicKeyResolver', () => {
|
||||
homeCom.foreign = false
|
||||
homeCom.apiVersion = '1_0'
|
||||
homeCom.endPoint = 'endpoint-url'
|
||||
homeCom.publicKey = Buffer.from('homeCommunity-publicKey')
|
||||
homeCom.publicKey = Buffer.from(
|
||||
'9f6dcd0d985cc7105cd71c3417d9c291b126c8ca90513197de02191f928ef713',
|
||||
'hex',
|
||||
)
|
||||
await DbFederatedCommunity.insert(homeCom)
|
||||
})
|
||||
|
||||
@ -47,7 +50,7 @@ describe('PublicKeyResolver', () => {
|
||||
await expect(query({ query: getPublicKeyQuery })).resolves.toMatchObject({
|
||||
data: {
|
||||
getPublicKey: {
|
||||
publicKey: expect.stringMatching('homeCommunity-publicKey'),
|
||||
publicKey: '9f6dcd0d985cc7105cd71c3417d9c291b126c8ca90513197de02191f928ef713',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -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<GetPublicKeyResult> {
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// 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 { PendingTransactionLoggingView } from '@logging/PendingTransactionLogging.view'
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
import { PendingTransaction as DbPendingTransaction } from '@entity/PendingTransaction'
|
||||
import { SendCoinsArgs } from '../model/SendCoinsArgs'
|
||||
@ -16,27 +16,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<SendCoinsResult> {
|
||||
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({
|
||||
@ -152,7 +141,10 @@ export class SendCoinsResolver {
|
||||
linkedUserCommunityUuid: args.senderCommunityUuid,
|
||||
linkedUserGradidoID: args.senderUserUuid,
|
||||
})
|
||||
logger.debug('XCom: revertSendCoins found pendingTX=', pendingTx)
|
||||
logger.debug(
|
||||
'XCom: revertSendCoins found pendingTX=',
|
||||
pendingTx ? new PendingTransactionLoggingView(pendingTx) : 'null',
|
||||
)
|
||||
if (pendingTx && pendingTx.amount.toString() === args.amount.toString()) {
|
||||
logger.debug('XCom: revertSendCoins matching pendingTX for remove...')
|
||||
try {
|
||||
@ -167,19 +159,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 +177,7 @@ export class SendCoinsResolver {
|
||||
@Arg('data')
|
||||
args: SendCoinsArgs,
|
||||
): Promise<boolean> {
|
||||
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,
|
||||
@ -232,7 +208,10 @@ export class SendCoinsResolver {
|
||||
linkedUserCommunityUuid: args.senderCommunityUuid,
|
||||
linkedUserGradidoID: args.senderUserUuid,
|
||||
})
|
||||
logger.debug('XCom: settleSendCoins found pendingTX=', pendingTx?.toString())
|
||||
logger.debug(
|
||||
'XCom: settleSendCoins found pendingTX=',
|
||||
pendingTx ? new PendingTransactionLoggingView(pendingTx) : 'null',
|
||||
)
|
||||
if (
|
||||
pendingTx &&
|
||||
pendingTx.amount.toString() === args.amount.toString() &&
|
||||
@ -256,17 +235,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,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -307,7 +281,10 @@ export class SendCoinsResolver {
|
||||
linkedUserCommunityUuid: args.senderCommunityUuid,
|
||||
linkedUserGradidoID: args.senderUserUuid,
|
||||
})
|
||||
logger.debug('XCom: revertSettledSendCoins found pendingTX=', pendingTx)
|
||||
logger.debug(
|
||||
'XCom: revertSettledSendCoins found pendingTX=',
|
||||
pendingTx ? new PendingTransactionLoggingView(pendingTx) : 'null',
|
||||
)
|
||||
if (
|
||||
pendingTx &&
|
||||
pendingTx.amount.toString() === args.amount.toString() &&
|
||||
@ -322,19 +299,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
|
||||
|
||||
@ -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<void> {
|
||||
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<void> {
|
||||
logger.debug(`Authentication: startAuthentication()...`, oneTimeCode, fedComB)
|
||||
logger.debug(`Authentication: startAuthentication()...`, {
|
||||
oneTimeCode,
|
||||
fedComB: new FederatedCommunityLoggingView(fedComB),
|
||||
})
|
||||
try {
|
||||
const homeCom = await DbCommunity.findOneByOrFail({ foreign: false })
|
||||
|
||||
@ -78,7 +89,7 @@ export async function startAuthentication(
|
||||
logger.debug(
|
||||
`Authentication: received communityUUid for callbackFedCom:`,
|
||||
fedComUuid,
|
||||
fedComB,
|
||||
new FederatedCommunityLoggingView(fedComB),
|
||||
)
|
||||
const callbackCom = await DbCommunity.findOneByOrFail({
|
||||
foreign: true,
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -15,6 +15,10 @@ import { federationLogger as logger } from '@/server/logger'
|
||||
|
||||
import { getLastTransaction } from '@/graphql/util/getLastTransaction'
|
||||
import { TRANSACTIONS_LOCK } from '@/graphql/util/TRANSACTIONS_LOCK'
|
||||
import { CommunityLoggingView } from '@logging/CommunityLogging.view'
|
||||
import { UserLoggingView } from '@logging/UserLogging.view'
|
||||
import { PendingTransactionLoggingView } from '@logging/PendingTransactionLogging.view'
|
||||
import { TransactionLoggingView } from '@logging/TransactionLogging.view'
|
||||
|
||||
export async function revertSettledReceiveTransaction(
|
||||
homeCom: DbCommunity,
|
||||
@ -30,7 +34,11 @@ export async function revertSettledReceiveTransaction(
|
||||
logger.debug(`start Transaction for write-access...`)
|
||||
|
||||
try {
|
||||
logger.info('X-Com: revertSettledReceiveTransaction:', homeCom, receiverUser, pendingTx)
|
||||
logger.info('X-Com: revertSettledReceiveTransaction:', {
|
||||
homeCom: new CommunityLoggingView(homeCom),
|
||||
receiverUser: new UserLoggingView(receiverUser),
|
||||
pendingTx: new PendingTransactionLoggingView(pendingTx),
|
||||
})
|
||||
|
||||
// ensure that no other pendingTx with the same sender or recipient exists
|
||||
const openSenderPendingTx = await DbPendingTransaction.count({
|
||||
@ -68,6 +76,7 @@ export async function revertSettledReceiveTransaction(
|
||||
pendingTx.balanceDate.toISOString(),
|
||||
)
|
||||
logger.debug(`GradidoID:`, lastTransaction?.userGradidoID, pendingTx.userGradidoID)
|
||||
// todo: Data privacy: personal user data in log file?
|
||||
logger.debug(`Name:`, lastTransaction?.userName, pendingTx.userName)
|
||||
logger.debug(`amount:`, lastTransaction?.amount.toString(), pendingTx.amount.toString())
|
||||
logger.debug(`memo:`, lastTransaction?.memo, pendingTx.memo)
|
||||
@ -90,7 +99,10 @@ export async function revertSettledReceiveTransaction(
|
||||
lastTransaction.linkedUserName === pendingTx.linkedUserName
|
||||
) {
|
||||
await queryRunner.manager.remove(dbTransaction, lastTransaction)
|
||||
logger.debug(`X-Com: revert settlement receive Transaction removed:`, lastTransaction)
|
||||
logger.debug(
|
||||
`X-Com: revert settlement receive Transaction removed:`,
|
||||
new TransactionLoggingView(lastTransaction),
|
||||
)
|
||||
// and mark the pendingTx in the pending_transactions table as reverted
|
||||
pendingTx.state = PendingTransactionState.REVERTED
|
||||
await queryRunner.manager.save(DbPendingTransaction, pendingTx)
|
||||
@ -98,12 +110,11 @@ export async function revertSettledReceiveTransaction(
|
||||
await queryRunner.commitTransaction()
|
||||
logger.debug(`commit revert settlement recipient Transaction successful...`)
|
||||
} else {
|
||||
// TODO: if the last TX is not equivelant to pendingTX, the transactions must be corrected in EXPERT-MODE
|
||||
throw new LogError(
|
||||
`X-Com: missmatching transaction order for revert settlement!`,
|
||||
lastTransaction,
|
||||
pendingTx,
|
||||
)
|
||||
// TODO: if the last TX is not equivalent to pendingTX, the transactions must be corrected in EXPERT-MODE
|
||||
throw new LogError(`X-Com: mismatching transaction order for revert settlement!`, {
|
||||
lastTransaction: lastTransaction ? new TransactionLoggingView(lastTransaction) : 'null',
|
||||
pendingTx: new PendingTransactionLoggingView(pendingTx),
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -17,6 +17,10 @@ import { getLastTransaction } from '@/graphql/util/getLastTransaction'
|
||||
import { TRANSACTIONS_LOCK } from '@/graphql/util/TRANSACTIONS_LOCK'
|
||||
import { calculateRecipientBalance } from './calculateRecipientBalance'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { CommunityLoggingView } from '@logging/CommunityLogging.view'
|
||||
import { UserLoggingView } from '@logging/UserLogging.view'
|
||||
import { PendingTransactionLoggingView } from '@logging/PendingTransactionLogging.view'
|
||||
import { TransactionLoggingView } from '@logging/TransactionLogging.view'
|
||||
|
||||
export async function settlePendingReceiveTransaction(
|
||||
homeCom: DbCommunity,
|
||||
@ -32,7 +36,11 @@ export async function settlePendingReceiveTransaction(
|
||||
logger.debug(`start Transaction for write-access...`)
|
||||
|
||||
try {
|
||||
logger.info('X-Com: settlePendingReceiveTransaction:', homeCom, receiverUser, pendingTx)
|
||||
logger.info('X-Com: settlePendingReceiveTransaction:', {
|
||||
homeCom: new CommunityLoggingView(homeCom),
|
||||
receiverUser: new UserLoggingView(receiverUser),
|
||||
pendingTx: new PendingTransactionLoggingView(pendingTx),
|
||||
})
|
||||
|
||||
// ensure that no other pendingTx with the same sender or recipient exists
|
||||
const openSenderPendingTx = await DbPendingTransaction.count({
|
||||
@ -84,7 +92,7 @@ export async function settlePendingReceiveTransaction(
|
||||
transactionReceive.previous = receiveBalance ? receiveBalance.lastTransactionId : null
|
||||
transactionReceive.linkedTransactionId = pendingTx.linkedTransactionId
|
||||
await queryRunner.manager.insert(dbTransaction, transactionReceive)
|
||||
logger.debug(`receive Transaction inserted: ${dbTransaction}`)
|
||||
logger.debug(`receive Transaction inserted: ${new TransactionLoggingView(transactionReceive)}`)
|
||||
|
||||
// and mark the pendingTx in the pending_transactions table as settled
|
||||
pendingTx.state = PendingTransactionState.SETTLED
|
||||
|
||||
@ -2,6 +2,8 @@ import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { federationLogger as logger } from '@/server/logger'
|
||||
import { SendCoinsArgs } from '../model/SendCoinsArgs'
|
||||
import { UserLoggingView } from '@logging/UserLogging.view'
|
||||
import { SendCoinsArgsLoggingView } from '../logger/SendCoinsArgsLogging.view'
|
||||
|
||||
export async function storeForeignUser(args: SendCoinsArgs): Promise<boolean> {
|
||||
if (args.senderCommunityUuid !== null && args.senderUserUuid !== null) {
|
||||
@ -34,7 +36,7 @@ export async function storeForeignUser(args: SendCoinsArgs): Promise<boolean> {
|
||||
}
|
||||
foreignUser.gradidoID = args.senderUserUuid
|
||||
foreignUser = await DbUser.save(foreignUser)
|
||||
logger.debug('X-Com: new foreignUser inserted:', foreignUser)
|
||||
logger.debug('X-Com: new foreignUser inserted:', new UserLoggingView(foreignUser))
|
||||
|
||||
return true
|
||||
} else if (
|
||||
@ -43,14 +45,13 @@ export async function storeForeignUser(args: SendCoinsArgs): Promise<boolean> {
|
||||
args.senderUserName.slice(args.senderUserName.indexOf(' '), args.senderUserName.length) ||
|
||||
user.alias !== args.senderAlias
|
||||
) {
|
||||
logger.warn(
|
||||
'X-Com: foreignUser still exists, but with different name or alias:',
|
||||
user,
|
||||
args,
|
||||
)
|
||||
logger.warn('X-Com: foreignUser still exists, but with different name or alias:', {
|
||||
user: new UserLoggingView(user),
|
||||
args: new SendCoinsArgsLoggingView(args),
|
||||
})
|
||||
return false
|
||||
} else {
|
||||
logger.debug('X-Com: foreignUser still exists...:', user)
|
||||
logger.debug('X-Com: foreignUser still exists...:', new UserLoggingView(user))
|
||||
return true
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@ -39,7 +39,10 @@ describe('PublicKeyResolver', () => {
|
||||
homeCom.foreign = false
|
||||
homeCom.apiVersion = '1_0'
|
||||
homeCom.endPoint = 'endpoint-url'
|
||||
homeCom.publicKey = Buffer.from('homeCommunity-publicKey')
|
||||
homeCom.publicKey = Buffer.from(
|
||||
'9f6dcd0d985cc7105cd71c3417d9c291b126c8ca90513197de02191f928ef713',
|
||||
'hex',
|
||||
)
|
||||
await DbFederatedCommunity.insert(homeCom)
|
||||
})
|
||||
|
||||
@ -47,7 +50,7 @@ describe('PublicKeyResolver', () => {
|
||||
await expect(query({ query: getPublicKeyQuery })).resolves.toMatchObject({
|
||||
data: {
|
||||
getPublicKey: {
|
||||
publicKey: expect.stringMatching('homeCommunity-publicKey'),
|
||||
publicKey: '9f6dcd0d985cc7105cd71c3417d9c291b126c8ca90513197de02191f928ef713',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -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. */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user