mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
safe current work
This commit is contained in:
parent
70455ff9e3
commit
6e5fb223d6
@ -3,7 +3,7 @@ import { GraphQLClient, gql } from 'graphql-request'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import { randombytes_random } from 'sodium-native'
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient'
|
||||
import { ensureUrlEndsWithSlash } from '@/util/utilities'
|
||||
import { ensureUrlEndsWithSlash } from 'core'
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { encryptAndSign, OpenConnectionJwtPayloadType } from 'shared'
|
||||
|
||||
48
backend/src/federation/client/1_0/DisbursementClient.ts
Normal file
48
backend/src/federation/client/1_0/DisbursementClient.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { ensureUrlEndsWithSlash } from 'core/src/util/utilities'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { EncryptedTransferArgs } from 'core'
|
||||
import { processDisburseJwtOnSenderCommunity as processDisburseJwtOnSenderCommunityQuery } from './query/processDisburseJwtOnSenderCommunity'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.client.1_0.DisbursementClient`)
|
||||
|
||||
export class DisbursementClient {
|
||||
dbCom: DbFederatedCommunity
|
||||
endpoint: string
|
||||
client: GraphQLClient
|
||||
|
||||
constructor(dbCom: DbFederatedCommunity) {
|
||||
this.dbCom = dbCom
|
||||
this.endpoint = ensureUrlEndsWithSlash(dbCom.endPoint).concat(dbCom.apiVersion).concat('/')
|
||||
this.client = new GraphQLClient(this.endpoint, {
|
||||
method: 'POST',
|
||||
jsonSerializer: {
|
||||
parse: JSON.parse,
|
||||
stringify: JSON.stringify,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async sendDisburseJwtToSenderCommunity(args: EncryptedTransferArgs): Promise<string | null> {
|
||||
logger.debug('sendDisburseJwtToSenderCommunity against endpoint=', this.endpoint)
|
||||
try {
|
||||
const { data } = await this.client.rawRequest<{ processDisburseJwtOnSenderCommunity: string }>(processDisburseJwtOnSenderCommunityQuery, { args })
|
||||
const responseJwt = data?.processDisburseJwtOnSenderCommunity
|
||||
if (responseJwt) {
|
||||
logger.debug('received response jwt', responseJwt)
|
||||
return responseJwt
|
||||
}
|
||||
} catch (err) {
|
||||
const errmsg = `sendDisburseJwtToSenderCommunity failed for endpoint=${this.endpoint}, err=${err}`
|
||||
logger.error(errmsg)
|
||||
throw new Error(errmsg)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,7 +4,7 @@ import { GraphQLClient } from 'graphql-request'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { getPublicCommunityInfo } from '@/federation/client/1_0/query/getPublicCommunityInfo'
|
||||
import { getPublicKey } from '@/federation/client/1_0/query/getPublicKey'
|
||||
import { ensureUrlEndsWithSlash } from '@/util/utilities'
|
||||
import { ensureUrlEndsWithSlash } from 'core/src/util/utilities'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
import { PublicCommunityInfoLoggingView } from './logging/PublicCommunityInfoLogging.view'
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
import { gql } from 'graphql-request'
|
||||
|
||||
export const processDisburseJwtOnSenderCommunity = gql`
|
||||
mutation ($args: EncryptedTransferArgs!) {
|
||||
processDisburseJwtOnSenderCommunity(data: $args)
|
||||
}
|
||||
`
|
||||
3
backend/src/federation/client/1_1/DisbursementClient.ts
Normal file
3
backend/src/federation/client/1_1/DisbursementClient.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient'
|
||||
|
||||
export class DisbursementClient extends V1_0_DisbursementClient {}
|
||||
@ -1,3 +0,0 @@
|
||||
import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient'
|
||||
|
||||
export class SendCoinsClient extends V1_0_SendCoinsClient {}
|
||||
@ -3,7 +3,7 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient'
|
||||
|
||||
import { AuthenticationClient as V1_1_AuthenticationClient } from '@/federation/client/1_1/AuthenticationClient'
|
||||
import { ApiVersionType } from '@/federation/enum/apiVersionType'
|
||||
import { ApiVersionType } from 'core'
|
||||
|
||||
type AuthenticationClient = V1_0_AuthenticationClient | V1_1_AuthenticationClient
|
||||
|
||||
|
||||
58
backend/src/federation/client/DisbursementClientFactory.ts
Normal file
58
backend/src/federation/client/DisbursementClientFactory.ts
Normal file
@ -0,0 +1,58 @@
|
||||
import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
|
||||
import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient'
|
||||
import { DisbursementClient as V1_1_DisbursementClient } from '@/federation/client/1_1/DisbursementClient'
|
||||
import { ApiVersionType } from 'core'
|
||||
|
||||
type DisbursementClient = V1_0_DisbursementClient | V1_1_DisbursementClient
|
||||
|
||||
interface DisbursementClientInstance {
|
||||
id: number
|
||||
|
||||
client: DisbursementClient
|
||||
}
|
||||
|
||||
export class DisbursementClientFactory {
|
||||
private static instanceArray: DisbursementClientInstance[] = []
|
||||
|
||||
/**
|
||||
* The Singleton's constructor should always be private to prevent direct
|
||||
* construction calls with the `new` operator.
|
||||
*/
|
||||
|
||||
private constructor() {}
|
||||
|
||||
private static createDisbursementClient = (dbCom: DbFederatedCommunity) => {
|
||||
switch (dbCom.apiVersion) {
|
||||
case ApiVersionType.V1_0:
|
||||
return new V1_0_DisbursementClient(dbCom)
|
||||
case ApiVersionType.V1_1:
|
||||
return new V1_1_DisbursementClient(dbCom)
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The static method that controls the access to the singleton instance.
|
||||
*
|
||||
* This implementation let you subclass the Singleton class while keeping
|
||||
* just one instance of each subclass around.
|
||||
*/
|
||||
public static getInstance(dbCom: DbFederatedCommunity): DisbursementClient | null {
|
||||
const instance = DisbursementClientFactory.instanceArray.find(
|
||||
(instance) => instance.id === dbCom.id,
|
||||
)
|
||||
if (instance) {
|
||||
return instance.client
|
||||
}
|
||||
const client = DisbursementClientFactory.createDisbursementClient(dbCom)
|
||||
if (client) {
|
||||
DisbursementClientFactory.instanceArray.push({
|
||||
id: dbCom.id,
|
||||
client,
|
||||
} as DisbursementClientInstance)
|
||||
}
|
||||
return client
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,8 @@
|
||||
import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
|
||||
import { FederationClient as V1_0_FederationClient } from '@/federation/client/1_0/FederationClient'
|
||||
|
||||
import { FederationClient as V1_1_FederationClient } from '@/federation/client/1_1/FederationClient'
|
||||
import { ApiVersionType } from '@/federation/enum/apiVersionType'
|
||||
import { ensureUrlEndsWithSlash } from '@/util/utilities'
|
||||
import { ApiVersionType, ensureUrlEndsWithSlash } from 'core'
|
||||
|
||||
type FederationClient = V1_0_FederationClient | V1_1_FederationClient
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import { createKeyPair } from 'shared'
|
||||
import { getLogger } from 'log4js'
|
||||
import { startCommunityAuthentication } from './authenticateCommunities'
|
||||
import { PublicCommunityInfoLoggingView } from './client/1_0/logging/PublicCommunityInfoLogging.view'
|
||||
import { ApiVersionType } from './enum/apiVersionType'
|
||||
import { ApiVersionType } from 'core'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.federation.validateCommunities`)
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { Transaction as dbTransaction } from 'database'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId'
|
||||
|
||||
import { Decay } from './Decay'
|
||||
import { User } from './User'
|
||||
|
||||
@ -16,11 +16,11 @@ import { Paginated } from '@arg/Paginated'
|
||||
import { SearchContributionsFilterArgs } from '@arg/SearchContributionsFilterArgs'
|
||||
import { ContributionStatus } from '@enum/ContributionStatus'
|
||||
import { ContributionType } from '@enum/ContributionType'
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { AdminUpdateContribution } from '@model/AdminUpdateContribution'
|
||||
import { Contribution, ContributionListResult } from '@model/Contribution'
|
||||
import { OpenCreation } from '@model/OpenCreation'
|
||||
import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
|
||||
import { TransactionTypeId } from 'core'
|
||||
|
||||
import { RIGHTS } from '@/auth/RIGHTS'
|
||||
import {
|
||||
@ -43,8 +43,8 @@ import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUncon
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { Context, getClientTimezoneOffset, getUser } from '@/server/context'
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { fullName } from 'core'
|
||||
import { calculateDecay, Decay } from 'shared'
|
||||
import { fullName } from '@/util/utilities'
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { ContributionMessageType } from '@enum/ContributionMessageType'
|
||||
|
||||
@ -6,22 +6,19 @@ import { TransactionLinkFilters } from '@arg/TransactionLinkFilters'
|
||||
import { ContributionCycleType } from '@enum/ContributionCycleType'
|
||||
import { ContributionStatus } from '@enum/ContributionStatus'
|
||||
import { ContributionType } from '@enum/ContributionType'
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { Community } from '@model/Community'
|
||||
import { ContributionLink } from '@model/ContributionLink'
|
||||
import { Decay } from '@model/Decay'
|
||||
import { RedeemJwtLink } from '@model/RedeemJwtLink'
|
||||
import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink'
|
||||
import { User } from '@model/User'
|
||||
import { QueryLinkResult } from '@union/QueryLinkResult'
|
||||
import { TransactionTypeId } from 'core'
|
||||
import {
|
||||
AppDatabase,
|
||||
Contribution as DbContribution,
|
||||
ContributionLink as DbContributionLink,
|
||||
Transaction as DbTransaction,
|
||||
AppDatabase, Community as DbCommunity, Contribution as DbContribution,
|
||||
ContributionLink as DbContributionLink, FederatedCommunity as DbFederatedCommunity, Transaction as DbTransaction,
|
||||
TransactionLink as DbTransactionLink,
|
||||
User as DbUser,
|
||||
getHomeCommunity,
|
||||
getHomeCommunity
|
||||
} from 'database'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
|
||||
@ -37,12 +34,16 @@ import { LogError } from '@/server/LogError'
|
||||
import { Context, getClientTimezoneOffset, getUser } from '@/server/context'
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK'
|
||||
import { fullName } from '@/util/utilities'
|
||||
import { calculateBalance } from '@/util/validate'
|
||||
import { fullName } from 'core'
|
||||
import { calculateDecay, decode, DisburseJwtPayloadType, encode, encryptAndSign, RedeemJwtPayloadType, verify } from 'shared'
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { DisbursementClient as V1_0_DisbursementClient } from '@/federation/client/1_0/DisbursementClient'
|
||||
import { DisbursementClientFactory } from '@/federation/client/DisbursementClientFactory'
|
||||
import { EncryptedTransferArgs } from 'core'
|
||||
import { getLogger, Logger } from 'log4js'
|
||||
import { randombytes_random } from 'sodium-native'
|
||||
import { executeTransaction } from './TransactionResolver'
|
||||
import {
|
||||
getAuthenticatedCommunities,
|
||||
@ -53,7 +54,7 @@ import { getLastTransaction } from './util/getLastTransaction'
|
||||
import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector'
|
||||
import { transactionLinkList } from './util/transactionLinkList'
|
||||
|
||||
const createLogger = () => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.TransactionLinkResolver`)
|
||||
const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.TransactionLinkResolver.${method}`)
|
||||
|
||||
// TODO: do not export, test it inside the resolver
|
||||
export const transactionLinkCode = (date: Date): string => {
|
||||
@ -148,9 +149,9 @@ export class TransactionLinkResolver {
|
||||
@Authorized([RIGHTS.QUERY_TRANSACTION_LINK])
|
||||
@Query(() => QueryLinkResult)
|
||||
async queryTransactionLink(@Arg('code') code: string): Promise<typeof QueryLinkResult> {
|
||||
const logger = createLogger()
|
||||
logger.addContext('code', code.substring(0, 6))
|
||||
logger.debug('TransactionLinkResolver.queryTransactionLink...')
|
||||
const methodLogger = createLogger('queryTransactionLink')
|
||||
methodLogger.addContext('code', code.substring(0, 6))
|
||||
methodLogger.debug('queryTransactionLink...')
|
||||
if (code.match(/^CL-/)) {
|
||||
const contributionLink = await DbContributionLink.findOneOrFail({
|
||||
where: { code: code.replace('CL-', '') },
|
||||
@ -171,7 +172,7 @@ export class TransactionLinkResolver {
|
||||
}
|
||||
// normal redeem code
|
||||
if (txLinkFound) {
|
||||
logger.debug(
|
||||
methodLogger.debug(
|
||||
'TransactionLinkResolver.queryTransactionLink... normal redeem code found=',
|
||||
txLinkFound,
|
||||
)
|
||||
@ -186,7 +187,7 @@ export class TransactionLinkResolver {
|
||||
return new TransactionLink(dbTransactionLink, new User(user), redeemedBy, communities)
|
||||
} else {
|
||||
// redeem jwt-token
|
||||
return await this.queryRedeemJwtLink(code, logger)
|
||||
return await this.queryRedeemJwtLink(code, methodLogger)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -197,8 +198,8 @@ export class TransactionLinkResolver {
|
||||
@Arg('code', () => String) code: string,
|
||||
@Ctx() context: Context,
|
||||
): Promise<boolean> {
|
||||
const logger = createLogger()
|
||||
logger.addContext('code', code.substring(0, 6))
|
||||
const methodLogger = createLogger('redeemTransactionLink')
|
||||
methodLogger.addContext('code', code.substring(0, 6))
|
||||
const clientTimezoneOffset = getClientTimezoneOffset(context)
|
||||
// const homeCom = await DbCommunity.findOneOrFail({ where: { foreign: false } })
|
||||
const user = getUser(context)
|
||||
@ -206,7 +207,7 @@ export class TransactionLinkResolver {
|
||||
// acquire lock
|
||||
const releaseLock = await TRANSACTIONS_LOCK.acquire()
|
||||
try {
|
||||
logger.info('redeem contribution link...')
|
||||
methodLogger.info('redeem contribution link...')
|
||||
const now = new Date()
|
||||
const queryRunner = db.getDataSource().createQueryRunner()
|
||||
await queryRunner.connect()
|
||||
@ -221,7 +222,7 @@ export class TransactionLinkResolver {
|
||||
if (!contributionLink) {
|
||||
throw new LogError('No contribution link found to given code', code)
|
||||
}
|
||||
logger.info('...contribution link found with id', contributionLink.id)
|
||||
methodLogger.info('...contribution link found with id', contributionLink.id)
|
||||
if (new Date(contributionLink.validFrom).getTime() > now.getTime()) {
|
||||
throw new LogError('Contribution link is not valid yet', contributionLink.validFrom)
|
||||
}
|
||||
@ -278,7 +279,7 @@ export class TransactionLinkResolver {
|
||||
}
|
||||
|
||||
const creations = await getUserCreation(user.id, clientTimezoneOffset)
|
||||
logger.info('open creations', creations)
|
||||
methodLogger.info('open creations', creations)
|
||||
validateContribution(creations, contributionLink.amount, now, clientTimezoneOffset)
|
||||
const contribution = new DbContribution()
|
||||
contribution.userId = user.id
|
||||
@ -383,7 +384,7 @@ export class TransactionLinkResolver {
|
||||
transactionLink.memo,
|
||||
linkedUser,
|
||||
user,
|
||||
logger,
|
||||
methodLogger,
|
||||
transactionLink,
|
||||
)
|
||||
await EVENT_TRANSACTION_LINK_REDEEM(
|
||||
@ -413,9 +414,9 @@ export class TransactionLinkResolver {
|
||||
@Arg('alias', { nullable: true }) alias?: string,
|
||||
@Arg('validUntil', { nullable: true }) validUntil?: string,
|
||||
): Promise<string> {
|
||||
const logger = createLogger()
|
||||
logger.addContext('code', code.substring(0, 6))
|
||||
logger.debug('TransactionLinkResolver.queryRedeemJwt... args=', {
|
||||
const methodLogger = createLogger('createRedeemJwt')
|
||||
methodLogger.addContext('code', code.substring(0, 6))
|
||||
methodLogger.debug('args=', {
|
||||
gradidoId,
|
||||
senderCommunityUuid,
|
||||
senderCommunityName,
|
||||
@ -466,40 +467,80 @@ export class TransactionLinkResolver {
|
||||
@Arg('validUntil', { nullable: true }) validUntil?: string,
|
||||
@Arg('recipientAlias', { nullable: true }) recipientAlias?: string,
|
||||
): Promise<boolean> {
|
||||
const logger = createLogger()
|
||||
logger.addContext('code', code.substring(0, 6))
|
||||
logger.debug('TransactionLinkResolver.disburseTransactionLink... args=', {
|
||||
senderGradidoId,
|
||||
senderCommunityUuid,
|
||||
recipientCommunityUuid,
|
||||
recipientCommunityName,
|
||||
recipientGradidoId,
|
||||
recipientFirstName,
|
||||
code,
|
||||
amount,
|
||||
memo,
|
||||
validUntil,
|
||||
const handshakeID = randombytes_random().toString()
|
||||
const methodLogger = createLogger(`disburseTransactionLink`)
|
||||
methodLogger.addContext('handshakeID', handshakeID)
|
||||
if(methodLogger.isDebugEnabled()) {
|
||||
methodLogger.debug('args=', {
|
||||
senderGradidoId,
|
||||
senderCommunityUuid,
|
||||
recipientCommunityUuid,
|
||||
recipientCommunityName,
|
||||
recipientGradidoId,
|
||||
recipientFirstName,
|
||||
code,
|
||||
amount,
|
||||
memo,
|
||||
validUntil,
|
||||
recipientAlias,
|
||||
})
|
||||
const disburseJwt = await this.createDisburseJwt(
|
||||
senderCommunityUuid,
|
||||
senderGradidoId,
|
||||
recipientCommunityUuid,
|
||||
recipientCommunityName,
|
||||
recipientGradidoId,
|
||||
recipientFirstName,
|
||||
code,
|
||||
amount,
|
||||
memo,
|
||||
validUntil ?? '',
|
||||
recipientAlias ?? '',
|
||||
)
|
||||
try {
|
||||
logger.debug('TransactionLinkResolver.disburseTransactionLink... disburseJwt=', disburseJwt)
|
||||
// now send the disburseJwt to the sender community to invoke a x-community-tx to disbures the redeemLink
|
||||
// await sendDisburseJwtToSenderCommunity(context, disburseJwt)
|
||||
} catch (e) {
|
||||
throw new LogError('Disburse JWT was not sent successfully', e)
|
||||
})
|
||||
}
|
||||
const senderCom = await DbCommunity.findOneBy({ communityUuid: senderCommunityUuid })
|
||||
if (!senderCom) {
|
||||
const errmsg = `Sender community not found with uuid=${senderCommunityUuid}`
|
||||
methodLogger.error(errmsg)
|
||||
throw new LogError(errmsg)
|
||||
}
|
||||
const senderFedCom = await DbFederatedCommunity.findOneBy({ publicKey: senderCom.publicKey })
|
||||
if (!senderFedCom) {
|
||||
const errmsg = `Sender federated community not found with publicKey=${senderCom.publicKey}`
|
||||
methodLogger.error(errmsg)
|
||||
throw new LogError(errmsg)
|
||||
}
|
||||
const recipientCom = await DbCommunity.findOneBy({ communityUuid: recipientCommunityUuid })
|
||||
if (!recipientCom) {
|
||||
const errmsg = `Recipient community not found with uuid=${recipientCommunityUuid}`
|
||||
methodLogger.error(errmsg)
|
||||
throw new LogError(errmsg)
|
||||
}
|
||||
const client = DisbursementClientFactory.getInstance(senderFedCom)
|
||||
if (client instanceof V1_0_DisbursementClient) {
|
||||
const disburseJwtPayload = new DisburseJwtPayloadType(
|
||||
handshakeID,
|
||||
senderCommunityUuid,
|
||||
senderGradidoId,
|
||||
recipientCommunityUuid,
|
||||
recipientCommunityName,
|
||||
recipientGradidoId,
|
||||
recipientFirstName,
|
||||
code,
|
||||
amount,
|
||||
memo,
|
||||
validUntil!,
|
||||
recipientAlias!,
|
||||
)
|
||||
if(methodLogger.isDebugEnabled()) {
|
||||
methodLogger.debug('disburseJwtPayload=', disburseJwtPayload)
|
||||
}
|
||||
const jws = await encryptAndSign(disburseJwtPayload, recipientCom.privateJwtKey!, senderCom.publicJwtKey!)
|
||||
if(methodLogger.isDebugEnabled()) {
|
||||
methodLogger.debug('jws=', jws)
|
||||
}
|
||||
const args = new EncryptedTransferArgs()
|
||||
args.publicKey = senderCom.publicKey.toString('hex')
|
||||
args.jwt = jws
|
||||
args.handshakeID = handshakeID
|
||||
try {
|
||||
// now send the disburseJwt to the sender community to invoke a x-community-tx to disbures the redeemLink
|
||||
const result = await client.sendDisburseJwtToSenderCommunity(args)
|
||||
if(methodLogger.isDebugEnabled()) {
|
||||
methodLogger.debug('Disburse JWT was sent successfully with result=', result)
|
||||
}
|
||||
} catch (e) {
|
||||
const errmsg = `Disburse JWT was not sent successfully with error=${e}`
|
||||
methodLogger.error(errmsg)
|
||||
throw new Error(errmsg)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -653,56 +694,4 @@ export class TransactionLinkResolver {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
async createDisburseJwt(
|
||||
handshakeId: string,
|
||||
senderCommunityUuid: string,
|
||||
senderGradidoId: string,
|
||||
recipientCommunityUuid: string,
|
||||
recipientCommunityName: string,
|
||||
recipientGradidoId: string,
|
||||
recipientFirstName: string,
|
||||
code: string,
|
||||
amount: string,
|
||||
memo: string,
|
||||
validUntil: string,
|
||||
recipientAlias: string,
|
||||
): Promise<string> {
|
||||
const logger = createLogger()
|
||||
logger.addContext('code', code.substring(0, 6))
|
||||
logger.debug('TransactionLinkResolver.createDisburseJwt... args=', {
|
||||
handshakeId,
|
||||
senderCommunityUuid,
|
||||
senderGradidoId,
|
||||
recipientCommunityUuid,
|
||||
recipientCommunityName,
|
||||
recipientGradidoId,
|
||||
recipientFirstName,
|
||||
code,
|
||||
amount,
|
||||
memo,
|
||||
validUntil,
|
||||
recipientAlias,
|
||||
})
|
||||
|
||||
const disburseJwtPayload = new DisburseJwtPayloadType(
|
||||
handshakeId,
|
||||
senderCommunityUuid,
|
||||
senderGradidoId,
|
||||
recipientCommunityUuid,
|
||||
recipientCommunityName,
|
||||
recipientGradidoId,
|
||||
recipientFirstName,
|
||||
code,
|
||||
amount,
|
||||
memo,
|
||||
validUntil,
|
||||
recipientAlias,
|
||||
)
|
||||
const disburseJwt = await encryptAndSign(disburseJwtPayload, homeComB.privateJwtKey!, authCom.publicJwtKey!)
|
||||
// TODO:encode/sign the jwt normally with the private key of the recipient community, but interims with uuid
|
||||
logger.debug('TransactionLinkResolver.createDisburseJwt... disburseJwt=', disburseJwt)
|
||||
// TODO: encrypt the payload with the public key of the target/sender community
|
||||
return disburseJwt
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@ import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
import { CONFIG } from '@/config'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { EventType } from '@/event/Events'
|
||||
import { SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient'
|
||||
import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs'
|
||||
import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult'
|
||||
import { SendCoinsClient } from 'core/src/federation/client/1_0/SendCoinsClient'
|
||||
import { SendCoinsArgs } from 'core/src/federation/client/1_0/model/SendCoinsArgs'
|
||||
import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult'
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
import {
|
||||
confirmContribution,
|
||||
|
||||
@ -2,7 +2,6 @@ import {
|
||||
AppDatabase,
|
||||
countOpenPendingTransactions,
|
||||
Community as DbCommunity,
|
||||
PendingTransaction as DbPendingTransaction,
|
||||
Transaction as dbTransaction,
|
||||
TransactionLink as dbTransactionLink,
|
||||
User as dbUser,
|
||||
@ -15,11 +14,11 @@ import { In, IsNull } from 'typeorm'
|
||||
import { Paginated } from '@arg/Paginated'
|
||||
import { TransactionSendArgs } from '@arg/TransactionSendArgs'
|
||||
import { Order } from '@enum/Order'
|
||||
import { PendingTransactionState, SendCoinsResponseJwtPayloadType } from 'shared'
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { Transaction } from '@model/Transaction'
|
||||
import { TransactionList } from '@model/TransactionList'
|
||||
import { User } from '@model/User'
|
||||
import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId'
|
||||
import { SendCoinsResponseJwtPayloadType } from 'shared'
|
||||
|
||||
import { RIGHTS } from '@/auth/RIGHTS'
|
||||
import { CONFIG } from '@/config'
|
||||
@ -28,26 +27,25 @@ import {
|
||||
sendTransactionReceivedEmail,
|
||||
} from '@/emails/sendEmailVariants'
|
||||
import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Events'
|
||||
import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { Context, getUser } from '@/server/context'
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { communityUser } from '@/util/communityUser'
|
||||
import { fullName } from '@/util/utilities'
|
||||
import { calculateBalance } from '@/util/validate'
|
||||
import { virtualDecayTransaction, virtualLinkTransaction } from '@/util/virtualTransactions'
|
||||
import { fullName, SendCoinsResult } from 'core'
|
||||
|
||||
import { Logger, getLogger } from 'log4js'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import {
|
||||
processXComCommittingSendCoins,
|
||||
processXComPendingSendCoins,
|
||||
} from 'core'
|
||||
import { getLogger, Logger } from 'log4js'
|
||||
import { BalanceResolver } from './BalanceResolver'
|
||||
import { GdtResolver } from './GdtResolver'
|
||||
import { getCommunityByIdentifier, getCommunityName, isHomeCommunity } from './util/communities'
|
||||
import { getLastTransaction } from './util/getLastTransaction'
|
||||
import { getTransactionList } from './util/getTransactionList'
|
||||
import {
|
||||
processXComCommittingSendCoins,
|
||||
processXComPendingSendCoins,
|
||||
} from './util/processXComSendCoins'
|
||||
import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector'
|
||||
import { storeForeignUser } from './util/storeForeignUser'
|
||||
import { transactionLinkSummary } from './util/transactionLinkSummary'
|
||||
|
||||
@ -12,7 +12,7 @@ import { cleanDB, testEnvironment } from '@test/helpers'
|
||||
import { i18n as localization } from '@test/testSetup'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
import { TransactionTypeId } from 'core'
|
||||
import { creations } from '@/seeds/creation'
|
||||
import { creationFactory } from '@/seeds/factory/creation'
|
||||
import { userFactory } from '@/seeds/factory/user'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Community as DbCommunity, User as DbUser } from 'database'
|
||||
|
||||
import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult'
|
||||
import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { Transaction as dbTransaction } from 'database'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { RemoveOptions, SaveOptions } from 'typeorm'
|
||||
|
||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import { TransactionTypeId } from 'core/src/graphql/enum/TransactionTypeId'
|
||||
import { Transaction } from '@model/Transaction'
|
||||
import { User } from '@model/User'
|
||||
|
||||
|
||||
1
bun.lock
1
bun.lock
@ -192,6 +192,7 @@
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"jest": "27.2.4",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typescript": "^4.9.5",
|
||||
},
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@types/node": "^17.0.21",
|
||||
"jest": "27.2.4",
|
||||
"type-graphql": "^1.1.1",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { ensureUrlEndsWithSlash } from '@/util/utilities'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
@ -83,7 +82,9 @@ export class SendCoinsClient {
|
||||
logger.debug(`settleSendCoins successful from endpoint=${this.endpoint}`)
|
||||
return true
|
||||
} catch (err) {
|
||||
throw new LogError(`settleSendCoins failed for endpoint=${this.endpoint}`, err)
|
||||
const errmsg = `settleSendCoins failed for endpoint=${this.endpoint}, err=${err}`
|
||||
logger.error(errmsg)
|
||||
throw new Error(errmsg)
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +104,9 @@ export class SendCoinsClient {
|
||||
logger.debug(`revertSettledSendCoins successful from endpoint=${this.endpoint}`)
|
||||
return true
|
||||
} catch (err) {
|
||||
throw new LogError(`revertSettledSendCoins failed for endpoint=${this.endpoint}`, err)
|
||||
const errmsg = `revertSettledSendCoins failed for endpoint=${this.endpoint}, err=${err}`
|
||||
logger.error(errmsg)
|
||||
throw new Error(errmsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { AbstractLoggingView } from 'database'
|
||||
|
||||
import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs'
|
||||
import { SendCoinsArgs } from 'core/src/federation/client/1_0/model/SendCoinsArgs'
|
||||
|
||||
export class SendCoinsArgsLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: SendCoinsArgs) {
|
||||
@ -1,6 +1,6 @@
|
||||
import { AbstractLoggingView } from 'database'
|
||||
|
||||
import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult'
|
||||
import { SendCoinsResult } from 'core/src/federation/client/1_0/model/SendCoinsResult'
|
||||
|
||||
export class SendCoinsResultLoggingView extends AbstractLoggingView {
|
||||
public constructor(private self: SendCoinsResult) {
|
||||
3
core/src/federation/client/1_1/SendCoinsClient.ts
Normal file
3
core/src/federation/client/1_1/SendCoinsClient.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { SendCoinsClient as V1_0_SendCoinsClient } from 'core/src/federation/client/1_0/SendCoinsClient'
|
||||
|
||||
export class SendCoinsClient extends V1_0_SendCoinsClient {}
|
||||
@ -1,9 +1,8 @@
|
||||
import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
|
||||
import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient'
|
||||
|
||||
import { SendCoinsClient as V1_1_SendCoinsClient } from '@/federation/client/1_1/SendCoinsClient'
|
||||
import { ApiVersionType } from '@/federation/enum/apiVersionType'
|
||||
import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient'
|
||||
import { SendCoinsClient as V1_1_SendCoinsClient } from '@federation/client/1_1/SendCoinsClient'
|
||||
import { ApiVersionType } from '@federation/enum/apiVersionType'
|
||||
|
||||
type SendCoinsClient = V1_0_SendCoinsClient | V1_1_SendCoinsClient
|
||||
|
||||
@ -10,23 +10,22 @@ import {
|
||||
} from 'database'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@config/const'
|
||||
|
||||
import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient'
|
||||
import { SendCoinsArgs } from '@/federation/client/1_0/model/SendCoinsArgs'
|
||||
import { SendCoinsResult } from '@/federation/client/1_0/model/SendCoinsResult'
|
||||
import { SendCoinsClientFactory } from '@/federation/client/SendCoinsClientFactory'
|
||||
import { SendCoinsClient as V1_0_SendCoinsClient } from '@federation/client/1_0/SendCoinsClient'
|
||||
import { SendCoinsArgs } from '@federation/client/1_0/model/SendCoinsArgs'
|
||||
import { SendCoinsResult } from '@federation/client/1_0/model/SendCoinsResult'
|
||||
import { SendCoinsClientFactory } from '@federation/client/SendCoinsClientFactory'
|
||||
import { encryptAndSign, PendingTransactionState, SendCoinsJwtPayloadType, SendCoinsResponseJwtPayloadType, verifyAndDecrypt } from 'shared'
|
||||
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { calculateSenderBalance } from '@/util/calculateSenderBalance'
|
||||
import { fullName } from '@/util/utilities'
|
||||
import { TransactionTypeId } from '@graphql/enum/TransactionTypeId'
|
||||
import { LogError } from '@server/LogError'
|
||||
import { calculateSenderBalance } from '@util/calculateSenderBalance'
|
||||
import { fullName } from '@util/utilities'
|
||||
import { getLogger } from 'log4js'
|
||||
|
||||
import { settlePendingSenderTransaction } from './settlePendingSenderTransaction'
|
||||
import { SendCoinsArgsLoggingView } from '@/federation/client/1_0/logging/SendCoinsArgsLogging.view'
|
||||
import { SendCoinsResultLoggingView } from '@/federation/client/1_0/logging/SendCoinsResultLogging.view'
|
||||
import { settlePendingSenderTransaction } from '@graphql/resolver/util/settlePendingSenderTransaction'
|
||||
import { SendCoinsArgsLoggingView } from '@federation/client/1_0/logging/SendCoinsArgsLogging.view'
|
||||
import { SendCoinsResultLoggingView } from '@federation/client/1_0/logging/SendCoinsResultLogging.view'
|
||||
import { EncryptedTransferArgs } from 'core'
|
||||
import { randombytes_random } from 'sodium-native'
|
||||
|
||||
@ -1,3 +1,17 @@
|
||||
export * from './validation/user'
|
||||
export * from './federation/client/1_0/logging/SendCoinsArgsLogging.view'
|
||||
export * from './federation/client/1_0/logging/SendCoinsResultLogging.view'
|
||||
export * from './federation/client/1_0/model/SendCoinsArgs'
|
||||
export * from './federation/client/1_0/model/SendCoinsResult'
|
||||
export * from './federation/client/1_0/query/revertSendCoins'
|
||||
export * from './federation/client/1_0/query/revertSettledSendCoins'
|
||||
export * from './federation/client/1_0/query/settleSendCoins'
|
||||
export * from './federation/client/1_0/query/voteForSendCoins'
|
||||
export * from './federation/client/SendCoinsClientFactory'
|
||||
export * from './federation/enum/apiVersionType'
|
||||
export * from './graphql/enum/TransactionTypeId'
|
||||
export * from './graphql/logic/interpretEncryptedTransferArgs'
|
||||
export * from './graphql/logic/processXComSendCoins'
|
||||
export * from './graphql/model/EncryptedTransferArgs'
|
||||
export * from './util/utilities'
|
||||
export * from './validation/user'
|
||||
|
||||
|
||||
@ -44,8 +44,15 @@
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||
"paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
"@/*": ["src/*"],
|
||||
"@config/*": ["src/config/*"],
|
||||
"@federation/*": ["src/federation/*"],
|
||||
"@graphql/*": ["src/graphql/*"],
|
||||
"@util/*": ["src/util/*"],
|
||||
"@validation/*": ["src/validation/*"],
|
||||
},
|
||||
// "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": ["bun-types"], /* Type declaration files to be included in compilation. */
|
||||
|
||||
@ -3,7 +3,7 @@ import { FederatedCommunity as DbFederatedCommunity } from 'database'
|
||||
import { AuthenticationClient as V1_0_AuthenticationClient } from './1_0/AuthenticationClient'
|
||||
|
||||
import { AuthenticationClient as V1_1_AuthenticationClient } from './1_1/AuthenticationClient'
|
||||
import { ApiVersionType } from './enum/ApiVersionType'
|
||||
import { ApiVersionType } from 'core'
|
||||
|
||||
type AuthenticationClient = V1_0_AuthenticationClient | V1_1_AuthenticationClient
|
||||
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
export enum ApiVersionType {
|
||||
V1_0 = '1_0',
|
||||
V1_1 = '1_1',
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import { getLogger } from "log4js"
|
||||
import { Arg, Mutation, Resolver } from "type-graphql"
|
||||
|
||||
import { LOG4JS_BASE_CATEGORY_NAME } from "@/config/const"
|
||||
import { interpretEncryptedTransferArgs } from "core"
|
||||
import { EncryptedTransferArgs } from "core"
|
||||
import { DisburseJwtPayloadType } from "shared"
|
||||
|
||||
const createLogger = (method: string) => getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.api.1_0.resolver.DisbursementResolver.${method}`)
|
||||
|
||||
@Resolver()
|
||||
export class DisbursementResolver {
|
||||
@Mutation(() => String)
|
||||
async processDisburseJwtOnSenderCommunity(
|
||||
@Arg('data')
|
||||
args: EncryptedTransferArgs,
|
||||
): Promise<string> {
|
||||
const methodLogger = createLogger(`processDisburseJwtOnSenderCommunity`)
|
||||
methodLogger.addContext('handshakeID', args.handshakeID)
|
||||
if(methodLogger.isDebugEnabled()) {
|
||||
methodLogger.debug(`processDisburseJwtOnSenderCommunity() via apiVersion=1_0 ...`, args)
|
||||
}
|
||||
const authArgs = await interpretEncryptedTransferArgs(args) as DisburseJwtPayloadType
|
||||
if (!authArgs) {
|
||||
const errmsg = `invalid disbursement payload of requesting community with publicKey` + args.publicKey
|
||||
methodLogger.error(errmsg)
|
||||
throw new Error(errmsg)
|
||||
}
|
||||
if(methodLogger.isDebugEnabled()) {
|
||||
methodLogger.debug(`processDisburseJwtOnSenderCommunity() via apiVersion=1_0 ...`, authArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user