diff --git a/backend/src/event/Event.ts b/backend/src/event/Event.ts index 6a1233224..786d48eed 100644 --- a/backend/src/event/Event.ts +++ b/backend/src/event/Event.ts @@ -298,6 +298,13 @@ export class Event { return this } + public setEventAdminContributionDeny(ev: EventAdminContributionDeny): Event { + this.setByBasicCt(ev.userId, ev.contributionId, ev.amount) + this.type = EventProtocolType.ADMIN_CONTRIBUTION_DENY + + return this + } + public setEventAdminContributionUpdate(ev: EventAdminContributionUpdate): Event { this.setByBasicCt(ev.userId, ev.contributionId, ev.amount) this.type = EventProtocolType.ADMIN_CONTRIBUTION_UPDATE diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index bf80bcb4d..01a681e52 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -44,6 +44,7 @@ import { EventContributionConfirm, EventAdminContributionCreate, EventAdminContributionDelete, + EventAdminContributionDeny, EventAdminContributionUpdate, } from '@/event/Event' import { writeEvent } from '@/event/EventProtocolEmitter' @@ -559,6 +560,56 @@ export class ContributionResolver { return !!res } + @Authorized([RIGHTS.ADMIN_DENY_CONTRIBUTION]) + @Mutation(() => Boolean) + async adminDenyContribution( + @Arg('id', () => Int) id: number, + @Ctx() context: Context, + ): Promise { + const contribution = await DbContribution.findOne(id) + if (!contribution) { + logger.error(`Contribution not found for given id: ${id}`) + throw new Error('Contribution not found for given id.') + } + if (contribution.confirmedAt) { + logger.error('A confirmed contribution can not be denied') + throw new Error('A confirmed contribution can not be denied') + } + const moderator = getUser(context) + if ( + contribution.contributionType === ContributionType.USER && + contribution.userId === moderator.id + ) { + throw new Error('Own contribution can not be denied as admin') + } + const user = await DbUser.findOneOrFail( + { id: contribution.userId }, + { relations: ['emailContact'] }, + ) + contribution.contributionStatus = ContributionStatus.DENIED + contribution.deniedBy = moderator.id + await contribution.save() + const res = await contribution.softRemove() + + const event = new Event() + const eventAdminContributionDeny = new EventAdminContributionDeny() + eventAdminContributionDeny.userId = contribution.userId + eventAdminContributionDeny.amount = contribution.amount + eventAdminContributionDeny.contributionId = contribution.id + await writeEvent(event.setEventAdminContributionDeny(eventAdminContributionDeny)) + sendContributionDeniedEmail({ + firstName: user.firstName, + lastName: user.lastName, + email: user.emailContact.email, + language: user.language, + senderFirstName: moderator.firstName, + senderLastName: moderator.lastName, + contributionMemo: contribution.memo, + }) + + return !!res + } + @Authorized([RIGHTS.CONFIRM_CONTRIBUTION]) @Mutation(() => Boolean) async confirmContribution(