From e9d2eae51af1be0a496c74860d082477fc3088f7 Mon Sep 17 00:00:00 2001
From: clauspeterhuebner
Date: Fri, 11 Apr 2025 19:02:23 +0200
Subject: [PATCH] correct handling of receiverCommunity updates
---
backend/src/graphql/arg/RedeemJwtArgs.ts | 37 --------
.../resolver/TransactionLinkResolver.ts | 14 ++--
.../RedeemCommunitySelection.vue | 84 ++++++++++++++-----
.../RedeemSelectCommunity.vue | 16 ++--
frontend/src/graphql/mutations.js | 10 ++-
5 files changed, 91 insertions(+), 70 deletions(-)
delete mode 100644 backend/src/graphql/arg/RedeemJwtArgs.ts
diff --git a/backend/src/graphql/arg/RedeemJwtArgs.ts b/backend/src/graphql/arg/RedeemJwtArgs.ts
deleted file mode 100644
index e9634d8ec..000000000
--- a/backend/src/graphql/arg/RedeemJwtArgs.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { MaxLength, MinLength } from 'class-validator'
-import { Decimal } from 'decimal.js-light'
-import { Field, ArgsType, InputType } from 'type-graphql'
-
-import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from '@/graphql/resolver/const/const'
-import { IsPositiveDecimal } from '@/graphql/validator/Decimal'
-
-@InputType()
-@ArgsType()
-export class RedeemJwtArgs {
- @Field(() => String, { nullable: false })
- gradidoID!: string
-
- @Field(() => String, { nullable: true })
- firstName?: string
-
- @Field(() => String, { nullable: true })
- alias?: string
-
- @Field(() => String, { nullable: false })
- communityUuid!: string
-
- @Field(() => String, { nullable: false })
- communityName!: string
-
- @Field(() => String, { nullable: false })
- code!: string
-
- @Field(() => Decimal, { nullable: false })
- @IsPositiveDecimal()
- amount!: Decimal
-
- @Field(() => String, { nullable: false })
- @MaxLength(MEMO_MAX_CHARS)
- @MinLength(MEMO_MIN_CHARS)
- memo!: string
-}
diff --git a/backend/src/graphql/resolver/TransactionLinkResolver.ts b/backend/src/graphql/resolver/TransactionLinkResolver.ts
index e51181021..7a0f65db9 100644
--- a/backend/src/graphql/resolver/TransactionLinkResolver.ts
+++ b/backend/src/graphql/resolver/TransactionLinkResolver.ts
@@ -403,8 +403,9 @@ export class TransactionLinkResolver {
@Mutation(() => String)
async createRedeemJwt(
@Arg('gradidoID') gradidoID: string,
- @Arg('communityUuid') communityUuid: string,
- @Arg('communityName') communityName: string,
+ @Arg('senderCommunityUuid') senderCommunityUuid: string,
+ @Arg('senderCommunityName') senderCommunityName: string,
+ @Arg('receiverCommunityUuid') receiverCommunityUuid: string,
@Arg('code') code: string,
@Arg('amount') amount: string,
@Arg('memo') memo: string,
@@ -413,8 +414,9 @@ export class TransactionLinkResolver {
): Promise {
logger.debug('TransactionLinkResolver.queryRedeemJwt... args=', {
gradidoID,
- communityUuid,
- communityName,
+ senderCommunityUuid,
+ senderCommunityName,
+ receiverCommunityUuid,
code,
amount,
memo,
@@ -423,18 +425,20 @@ export class TransactionLinkResolver {
})
const disbursementJwtPayloadType = new DisbursementJwtPayloadType(
- communityUuid,
+ senderCommunityUuid,
gradidoID,
alias ?? firstName ?? '',
code,
amount,
memo,
)
+ // encode/sign the jwt with the private key of the sender/home community
const homeCom = await getHomeCommunity()
if (!homeCom.privateKey) {
throw new LogError('Home community private key is not set')
}
const redeemJwt = await encode(disbursementJwtPayloadType, homeCom.privateKey)
+ // TODO: encrypt the payload with the public key of the target community
return redeemJwt
}
diff --git a/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue b/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue
index 0ef16f25a..edf7f08a4 100644
--- a/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue
+++ b/frontend/src/components/LinkInformations/RedeemCommunitySelection.vue
@@ -16,11 +16,11 @@
-
+
{{ $t('gdd_per_link.switchCommunity') }}
{{ $t('gdd_per_link.to-switch') }}
@@ -47,25 +47,69 @@ const props = defineProps({
linkData: { type: Object, required: true },
redeemCode: { type: String, required: true },
isContributionLink: { type: Boolean, default: false },
- targetCommunity: {
+ receiverCommunity: {
type: Object,
- required: true,
- default: () => ({ uuid: '', name: CONFIG.COMMUNITY_NAME }),
+ required: false,
},
})
-const emit = defineEmits(['update:targetCommunity'])
+const senderCommunity = computed(() => extractHomeCommunityFromLinkData(props.linkData))
+const currentReceiverCommunity = computed(
+ () =>
+ props.receiverCommunity || {
+ uuid: senderCommunity.value.uuid,
+ name: senderCommunity.value.name,
+ url: senderCommunity.value.url,
+ foreign: senderCommunity.value.foreign,
+ },
+)
+
+const emit = defineEmits(['update:receiverCommunity'])
const isForeignCommunitySelected = computed(() => {
- if (props.targetCommunity.name !== CONFIG.COMMUNITY_NAME) {
- return true
- }
- return false
+ console.log(
+ 'RedeemCommunitySelection.isForeignCommunitySelected...receiverCommunity=',
+ currentReceiverCommunity.value,
+ )
+ return currentReceiverCommunity.value.foreign
})
-function setTargetCommunity(community) {
- console.log('RedeemCommunitySelection.setTargetCommunity...community=', community)
- emit('update:targetCommunity', community)
+function setReceiverCommunity(community) {
+ console.log('RedeemCommunitySelection.setReceiverCommunity...community=', community)
+ emit('update:receiverCommunity', {
+ uuid: community.uuid,
+ name: community.name,
+ url: community.url,
+ foreign: community.foreign,
+ })
+}
+
+function extractHomeCommunityFromLinkData(linkData) {
+ console.log('RedeemCommunitySelection.extractHomeCommunityFromLinkData...linkData=', linkData)
+ if (linkData.communities.length === 0) {
+ return {
+ uuid: '',
+ name: CONFIG.COMMUNITY_NAME,
+ url: CONFIG.COMMUNITY_URL,
+ foreign: false,
+ }
+ }
+ const communities = linkData.communities
+ console.log(
+ 'RedeemCommunitySelection.extractHomeCommunityFromLinkData...communities=',
+ communities,
+ )
+ const homeCommunity = communities.find((c) => c.foreign === false)
+ console.log(
+ 'RedeemCommunitySelection.extractHomeCommunityFromLinkData...homeCommunity=',
+ homeCommunity,
+ )
+ return {
+ uuid: homeCommunity.uuid,
+ name: homeCommunity.name,
+ url: homeCommunity.url,
+ foreign: homeCommunity.foreign,
+ }
}
const { mutate: createRedeemJwt } = useMutation(createRedeemJwtMutation)
@@ -76,8 +120,9 @@ async function onSwitch(event) {
if (isForeignCommunitySelected.value) {
console.log('RedeemCommunitySelection.onSwitch vor createRedeemJwt params:', {
gradidoID: props.linkData.user.gradidoID,
- communityUuid: props.targetCommunity.uuid,
- communityName: props.targetCommunity.name,
+ senderCommunityUuid: senderCommunity.value.uuid,
+ senderCommunityName: senderCommunity.value.name,
+ receiverCommunityUuid: currentReceiverCommunity.value.uuid,
code: props.redeemCode,
amount: props.linkData.amount,
memo: props.linkData.memo,
@@ -87,8 +132,9 @@ async function onSwitch(event) {
try {
const { data } = await createRedeemJwt({
gradidoID: props.linkData.user.gradidoID,
- communityUuid: props.targetCommunity.uuid,
- communityName: props.targetCommunity.name,
+ senderCommunityUuid: senderCommunity.value.uuid,
+ senderCommunityName: senderCommunity.value.name,
+ receiverCommunityUuid: currentReceiverCommunity.value.uuid,
code: props.redeemCode,
amount: props.linkData.amount,
memo: props.linkData.memo,
@@ -99,7 +145,7 @@ async function onSwitch(event) {
if (!data?.createRedeemJwt) {
throw new Error('Failed to get redeem token')
}
- const targetUrl = props.targetCommunity.url.replace(/\/api\/?$/, '')
+ const targetUrl = currentReceiverCommunity.value.url.replace(/\/api\/?$/, '')
window.location.href = targetUrl + '/redeem/' + data.createRedeemJwt
} catch (error) {
console.error('RedeemCommunitySelection.onSwitch error:', error)
diff --git a/frontend/src/components/LinkInformations/RedeemSelectCommunity.vue b/frontend/src/components/LinkInformations/RedeemSelectCommunity.vue
index d956dce1a..7910a4032 100644
--- a/frontend/src/components/LinkInformations/RedeemSelectCommunity.vue
+++ b/frontend/src/components/LinkInformations/RedeemSelectCommunity.vue
@@ -1,7 +1,7 @@