mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
move code for update contribution message into context/role/logic/builder classes, reduce double code
This commit is contained in:
parent
8418e55c99
commit
b1d99c5fb4
52
backend/src/data/Contribution.logic.ts
Normal file
52
backend/src/data/Contribution.logic.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import {
|
||||
getUserCreation,
|
||||
updateCreations,
|
||||
validateContribution,
|
||||
} from '@/graphql/resolver/util/creations'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
export class ContributionLogic {
|
||||
// how much gradido can be still created
|
||||
private availableCreationSums?: Decimal[]
|
||||
public constructor(private self: Contribution) {}
|
||||
|
||||
/**
|
||||
* retrieve from db and return available creation sums array
|
||||
* @param clientTimezoneOffset
|
||||
* @param putThisBack if true, amount from this contribution will be added back to the availableCreationSums array,
|
||||
* as if this creation wasn't part of it, used for update contribution
|
||||
* @returns
|
||||
*/
|
||||
public async getAvailableCreationSums(
|
||||
clientTimezoneOffset: number,
|
||||
putThisBack = false,
|
||||
): Promise<Decimal[]> {
|
||||
// TODO: move code from getUserCreation and updateCreations inside this function/class
|
||||
this.availableCreationSums = await getUserCreation(this.self.userId, clientTimezoneOffset)
|
||||
if (putThisBack) {
|
||||
this.availableCreationSums = updateCreations(
|
||||
this.availableCreationSums,
|
||||
this.self,
|
||||
clientTimezoneOffset,
|
||||
)
|
||||
}
|
||||
return this.availableCreationSums
|
||||
}
|
||||
|
||||
public checkAvailableCreationSumsNotExceeded(
|
||||
amount: Decimal,
|
||||
creationDate: Date,
|
||||
clientTimezoneOffset: number,
|
||||
): void {
|
||||
if (!this.availableCreationSums) {
|
||||
throw new LogError(
|
||||
'missing available creation sums, please call getAvailableCreationSums first',
|
||||
)
|
||||
}
|
||||
// all possible cases not to be true are thrown in this function
|
||||
validateContribution(this.availableCreationSums, amount, creationDate, clientTimezoneOffset)
|
||||
}
|
||||
}
|
||||
89
backend/src/data/ContributionMessage.builder.ts
Normal file
89
backend/src/data/ContributionMessage.builder.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { ContributionMessage } from '@entity/ContributionMessage'
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
||||
export class ContributionMessageBuilder {
|
||||
private contributionMessage: ContributionMessage
|
||||
|
||||
// https://refactoring.guru/design-patterns/builder/typescript/example
|
||||
/**
|
||||
* A fresh builder instance should contain a blank product object, which is
|
||||
* used in further assembly.
|
||||
*/
|
||||
constructor() {
|
||||
this.reset()
|
||||
}
|
||||
|
||||
public reset(): void {
|
||||
this.contributionMessage = ContributionMessage.create()
|
||||
}
|
||||
|
||||
/**
|
||||
* Concrete Builders are supposed to provide their own methods for
|
||||
* retrieving results. That's because various types of builders may create
|
||||
* entirely different products that don't follow the same interface.
|
||||
* Therefore, such methods cannot be declared in the base Builder interface
|
||||
* (at least in a statically typed programming language).
|
||||
*
|
||||
* Usually, after returning the end result to the client, a builder instance
|
||||
* is expected to be ready to start producing another product. That's why
|
||||
* it's a usual practice to call the reset method at the end of the
|
||||
* `getProduct` method body. However, this behavior is not mandatory, and
|
||||
* you can make your builders wait for an explicit reset call from the
|
||||
* client code before disposing of the previous result.
|
||||
*/
|
||||
public build(): ContributionMessage {
|
||||
const result = this.contributionMessage
|
||||
this.reset()
|
||||
return result
|
||||
}
|
||||
|
||||
public setParentContribution(contribution: Contribution): this {
|
||||
this.contributionMessage.contributionId = contribution.id
|
||||
this.contributionMessage.createdAt = contribution.updatedAt
|
||||
? contribution.updatedAt
|
||||
: contribution.createdAt
|
||||
this.contributionMessage.isModerator = false
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* set contribution message type to history and create message from contribution
|
||||
* @param contribution
|
||||
* @returns ContributionMessageBuilder for chaining function calls
|
||||
*/
|
||||
public setHistoryType(contribution: Contribution): this {
|
||||
const changeMessage = `${contribution.contributionDate.toString()}
|
||||
---
|
||||
${contribution.memo}
|
||||
---
|
||||
${contribution.amount.toString()}`
|
||||
this.contributionMessage.message = changeMessage
|
||||
this.contributionMessage.type = ContributionMessageType.HISTORY
|
||||
return this
|
||||
}
|
||||
|
||||
public setUser(user: User): this {
|
||||
this.contributionMessage.user = user
|
||||
this.contributionMessage.userId = user.id
|
||||
return this
|
||||
}
|
||||
|
||||
public setUserId(userId: number): this {
|
||||
this.contributionMessage.userId = userId
|
||||
return this
|
||||
}
|
||||
|
||||
public setType(type: ContributionMessageType): this {
|
||||
this.contributionMessage.type = type
|
||||
return this
|
||||
}
|
||||
|
||||
public setIsModerator(value: boolean): this {
|
||||
this.contributionMessage.isModerator = value
|
||||
return this
|
||||
}
|
||||
}
|
||||
11
backend/src/data/UserLogic.ts
Normal file
11
backend/src/data/UserLogic.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { User } from '@entity/User'
|
||||
import { UserRole } from '@entity/UserRole'
|
||||
|
||||
import { RoleNames } from '@enum/RoleNames'
|
||||
|
||||
export class UserLogic {
|
||||
public constructor(private self: User) {}
|
||||
public isRole(role: RoleNames): boolean {
|
||||
return this.self.userRoles.some((value: UserRole) => value.role === role.toString())
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,8 @@ export class Contribution {
|
||||
this.deniedBy = contribution.deniedBy
|
||||
this.deletedAt = contribution.deletedAt
|
||||
this.deletedBy = contribution.deletedBy
|
||||
this.updatedAt = contribution.updatedAt
|
||||
this.updatedBy = contribution.updatedBy
|
||||
this.moderatorId = contribution.moderatorId
|
||||
this.userId = contribution.userId
|
||||
}
|
||||
@ -61,6 +63,12 @@ export class Contribution {
|
||||
@Field(() => Int, { nullable: true })
|
||||
deletedBy: number | null
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
updatedAt: Date | null
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
updatedBy: number | null
|
||||
|
||||
@Field(() => Date)
|
||||
contributionDate: Date
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { IsNull, getConnection } from '@dbTools/typeorm'
|
||||
import { EntityManager, IsNull, getConnection } from '@dbTools/typeorm'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { ContributionMessage } from '@entity/ContributionMessage'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { UserContact } from '@entity/UserContact'
|
||||
@ -38,6 +37,7 @@ import {
|
||||
EVENT_ADMIN_CONTRIBUTION_CONFIRM,
|
||||
EVENT_ADMIN_CONTRIBUTION_DENY,
|
||||
} from '@/event/Events'
|
||||
import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUnconfirmedContribution/UpdateUnconfirmedContribution.context'
|
||||
import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
@ -45,12 +45,7 @@ import { calculateDecay } from '@/util/decay'
|
||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||
import { fullName } from '@/util/utilities'
|
||||
|
||||
import {
|
||||
getUserCreation,
|
||||
validateContribution,
|
||||
updateCreations,
|
||||
getOpenCreations,
|
||||
} from './util/creations'
|
||||
import { getUserCreation, validateContribution, getOpenCreations } from './util/creations'
|
||||
import { findContributions } from './util/findContributions'
|
||||
import { getLastTransaction } from './util/getLastTransaction'
|
||||
import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector'
|
||||
@ -169,75 +164,26 @@ export class ContributionResolver {
|
||||
async updateContribution(
|
||||
@Arg('contributionId', () => Int)
|
||||
contributionId: number,
|
||||
@Args() { amount, memo, creationDate }: ContributionArgs,
|
||||
@Args() contributionArgs: ContributionArgs,
|
||||
@Ctx() context: Context,
|
||||
): Promise<UnconfirmedContribution> {
|
||||
const clientTimezoneOffset = getClientTimezoneOffset(context)
|
||||
|
||||
const user = getUser(context)
|
||||
|
||||
const contributionToUpdate = await DbContribution.findOne({
|
||||
where: { id: contributionId, confirmedAt: IsNull(), deniedAt: IsNull() },
|
||||
const updateUnconfirmedContributionContext = new UpdateUnconfirmedContributionContext(
|
||||
contributionId,
|
||||
contributionArgs,
|
||||
context,
|
||||
)
|
||||
const { contribution, contributionMessage, availableCreationSums } =
|
||||
await updateUnconfirmedContributionContext.run()
|
||||
await getConnection().transaction(async (transactionalEntityManager: EntityManager) => {
|
||||
await Promise.all([
|
||||
transactionalEntityManager.save(contribution),
|
||||
transactionalEntityManager.save(contributionMessage),
|
||||
])
|
||||
})
|
||||
if (!contributionToUpdate) {
|
||||
throw new LogError('Contribution not found', contributionId)
|
||||
}
|
||||
if (contributionToUpdate.userId !== user.id) {
|
||||
throw new LogError(
|
||||
'Can not update contribution of another user',
|
||||
contributionToUpdate,
|
||||
user.id,
|
||||
)
|
||||
}
|
||||
if (contributionToUpdate.moderatorId) {
|
||||
throw new LogError('Cannot update contribution of moderator', contributionToUpdate, user.id)
|
||||
}
|
||||
if (
|
||||
contributionToUpdate.contributionStatus !== ContributionStatus.IN_PROGRESS &&
|
||||
contributionToUpdate.contributionStatus !== ContributionStatus.PENDING
|
||||
) {
|
||||
throw new LogError(
|
||||
'Contribution can not be updated due to status',
|
||||
contributionToUpdate.contributionStatus,
|
||||
)
|
||||
}
|
||||
const creationDateObj = new Date(creationDate)
|
||||
let creations = await getUserCreation(user.id, clientTimezoneOffset)
|
||||
if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) {
|
||||
creations = updateCreations(creations, contributionToUpdate, clientTimezoneOffset)
|
||||
} else {
|
||||
throw new LogError('Month of contribution can not be changed')
|
||||
}
|
||||
const user = getUser(context)
|
||||
await EVENT_CONTRIBUTION_UPDATE(user, contribution, contributionArgs.amount)
|
||||
|
||||
// all possible cases not to be true are thrown in this function
|
||||
validateContribution(creations, amount, creationDateObj, clientTimezoneOffset)
|
||||
|
||||
const contributionMessage = ContributionMessage.create()
|
||||
contributionMessage.contributionId = contributionId
|
||||
contributionMessage.createdAt = contributionToUpdate.updatedAt
|
||||
? contributionToUpdate.updatedAt
|
||||
: contributionToUpdate.createdAt
|
||||
const changeMessage = `${contributionToUpdate.contributionDate.toString()}
|
||||
---
|
||||
${contributionToUpdate.memo}
|
||||
---
|
||||
${contributionToUpdate.amount.toString()}`
|
||||
contributionMessage.message = changeMessage
|
||||
contributionMessage.isModerator = false
|
||||
contributionMessage.userId = user.id
|
||||
contributionMessage.type = ContributionMessageType.HISTORY
|
||||
await ContributionMessage.save(contributionMessage)
|
||||
|
||||
contributionToUpdate.amount = amount
|
||||
contributionToUpdate.memo = memo
|
||||
contributionToUpdate.contributionDate = new Date(creationDate)
|
||||
contributionToUpdate.contributionStatus = ContributionStatus.PENDING
|
||||
contributionToUpdate.updatedAt = new Date()
|
||||
await DbContribution.save(contributionToUpdate)
|
||||
|
||||
await EVENT_CONTRIBUTION_UPDATE(user, contributionToUpdate, amount)
|
||||
|
||||
return new UnconfirmedContribution(contributionToUpdate, user, creations)
|
||||
return new UnconfirmedContribution(contribution, user, availableCreationSums)
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.ADMIN_CREATE_CONTRIBUTION])
|
||||
@ -294,54 +240,33 @@ export class ContributionResolver {
|
||||
@Authorized([RIGHTS.ADMIN_UPDATE_CONTRIBUTION])
|
||||
@Mutation(() => AdminUpdateContribution)
|
||||
async adminUpdateContribution(
|
||||
@Args() { id, amount, memo, creationDate }: AdminUpdateContributionArgs,
|
||||
@Args() adminUpdateContributionArgs: AdminUpdateContributionArgs,
|
||||
@Ctx() context: Context,
|
||||
): Promise<AdminUpdateContribution> {
|
||||
const clientTimezoneOffset = getClientTimezoneOffset(context)
|
||||
|
||||
const moderator = getUser(context)
|
||||
|
||||
const contributionToUpdate = await DbContribution.findOne({
|
||||
where: { id, confirmedAt: IsNull(), deniedAt: IsNull() },
|
||||
const updateUnconfirmedContributionContext = new UpdateUnconfirmedContributionContext(
|
||||
adminUpdateContributionArgs.id,
|
||||
adminUpdateContributionArgs,
|
||||
context,
|
||||
)
|
||||
const { contribution, contributionMessage } = await updateUnconfirmedContributionContext.run()
|
||||
await getConnection().transaction(async (transactionalEntityManager: EntityManager) => {
|
||||
await Promise.all([
|
||||
transactionalEntityManager.save(contribution),
|
||||
transactionalEntityManager.save(contributionMessage),
|
||||
])
|
||||
})
|
||||
|
||||
if (!contributionToUpdate) {
|
||||
throw new LogError('Contribution not found', id)
|
||||
}
|
||||
|
||||
if (contributionToUpdate.moderatorId === null) {
|
||||
throw new LogError('An admin is not allowed to update an user contribution')
|
||||
}
|
||||
|
||||
const creationDateObj = new Date(creationDate)
|
||||
let creations = await getUserCreation(contributionToUpdate.userId, clientTimezoneOffset)
|
||||
|
||||
// TODO: remove this restriction
|
||||
if (contributionToUpdate.contributionDate.getMonth() === creationDateObj.getMonth()) {
|
||||
creations = updateCreations(creations, contributionToUpdate, clientTimezoneOffset)
|
||||
} else {
|
||||
throw new LogError('Month of contribution can not be changed')
|
||||
}
|
||||
|
||||
// all possible cases not to be true are thrown in this function
|
||||
validateContribution(creations, amount, creationDateObj, clientTimezoneOffset)
|
||||
contributionToUpdate.amount = amount
|
||||
contributionToUpdate.memo = memo
|
||||
contributionToUpdate.contributionDate = new Date(creationDate)
|
||||
contributionToUpdate.moderatorId = moderator.id
|
||||
contributionToUpdate.contributionStatus = ContributionStatus.PENDING
|
||||
|
||||
await DbContribution.save(contributionToUpdate)
|
||||
const moderator = getUser(context)
|
||||
const { amount } = adminUpdateContributionArgs
|
||||
|
||||
const result = new AdminUpdateContribution()
|
||||
result.amount = amount
|
||||
result.memo = contributionToUpdate.memo
|
||||
result.date = contributionToUpdate.contributionDate
|
||||
result.memo = contribution.memo
|
||||
result.date = contribution.contributionDate
|
||||
|
||||
await EVENT_ADMIN_CONTRIBUTION_UPDATE(
|
||||
{ id: contributionToUpdate.userId } as DbUser,
|
||||
{ id: contribution.userId } as DbUser,
|
||||
moderator,
|
||||
contributionToUpdate,
|
||||
contribution,
|
||||
amount,
|
||||
)
|
||||
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { User } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Role } from '@/auth/Role'
|
||||
import { ContributionLogic } from '@/data/Contribution.logic'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
export abstract class UnconfirmedContributionRole {
|
||||
private availableCreationSums?: Decimal[]
|
||||
|
||||
public constructor(
|
||||
protected self: Contribution,
|
||||
private updatedAmount: Decimal,
|
||||
private updatedCreationDate: Date,
|
||||
) {
|
||||
if (self.confirmedAt || self.deniedAt) {
|
||||
throw new LogError("this contribution isn't unconfirmed!")
|
||||
}
|
||||
}
|
||||
|
||||
// steps which return void throw on each error
|
||||
// first, check if it can be updated
|
||||
public abstract checkAuthorization(user: User, role: Role): void
|
||||
// second, check if contribution is still valid after update
|
||||
public async validate(clientTimezoneOffset: number): Promise<void> {
|
||||
// TODO: remove this restriction
|
||||
if (this.self.contributionDate.getMonth() !== this.updatedCreationDate.getMonth()) {
|
||||
throw new LogError('Month of contribution can not be changed')
|
||||
}
|
||||
|
||||
const contributionLogic = new ContributionLogic(this.self)
|
||||
this.availableCreationSums = await contributionLogic.getAvailableCreationSums(
|
||||
clientTimezoneOffset,
|
||||
true,
|
||||
)
|
||||
contributionLogic.checkAvailableCreationSumsNotExceeded(
|
||||
this.updatedAmount,
|
||||
this.updatedCreationDate,
|
||||
clientTimezoneOffset,
|
||||
)
|
||||
}
|
||||
|
||||
// third, actually update entity
|
||||
public abstract update(): void
|
||||
|
||||
public getAvailableCreationSums(): Decimal[] {
|
||||
if (!this.availableCreationSums) {
|
||||
throw new LogError('availableCreationSums is empty, please call validate before!')
|
||||
}
|
||||
return this.availableCreationSums
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { RIGHTS } from '@/auth/RIGHTS'
|
||||
import { Role } from '@/auth/Role'
|
||||
import { AdminUpdateContributionArgs } from '@/graphql/arg/AdminUpdateContributionArgs'
|
||||
import { ContributionStatus } from '@/graphql/enum/ContributionStatus'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { UnconfirmedContributionRole } from './UnconfirmedContribution.role'
|
||||
|
||||
export class UnconfirmedContributionAdminRole extends UnconfirmedContributionRole {
|
||||
public constructor(
|
||||
contribution: Contribution,
|
||||
private updateData: AdminUpdateContributionArgs,
|
||||
private moderator: User,
|
||||
) {
|
||||
super(contribution, updateData.amount, new Date(updateData.creationDate))
|
||||
}
|
||||
|
||||
public update(): void {
|
||||
this.self.amount = this.updateData.amount
|
||||
this.self.memo = this.updateData.memo
|
||||
this.self.contributionDate = new Date(this.updateData.creationDate)
|
||||
this.self.contributionStatus = ContributionStatus.PENDING
|
||||
this.self.updatedAt = new Date()
|
||||
this.self.updatedBy = this.moderator.id
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public checkAuthorization(user: User, role: Role): UnconfirmedContributionRole {
|
||||
if (
|
||||
!role.hasRight(RIGHTS.MODERATOR_UPDATE_CONTRIBUTION_MEMO) &&
|
||||
this.self.moderatorId === null
|
||||
) {
|
||||
throw new LogError('An admin is not allowed to update an user contribution')
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { User } from '@entity/User'
|
||||
|
||||
import { ContributionArgs } from '@/graphql/arg/ContributionArgs'
|
||||
import { ContributionStatus } from '@/graphql/enum/ContributionStatus'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { UnconfirmedContributionRole } from './UnconfirmedContribution.role'
|
||||
|
||||
export class UnconfirmedContributionUserRole extends UnconfirmedContributionRole {
|
||||
public constructor(contribution: Contribution, private updateData: ContributionArgs) {
|
||||
super(contribution, updateData.amount, new Date(updateData.creationDate))
|
||||
}
|
||||
|
||||
public update(): void {
|
||||
this.self.amount = this.updateData.amount
|
||||
this.self.memo = this.updateData.memo
|
||||
this.self.contributionDate = new Date(this.updateData.creationDate)
|
||||
this.self.contributionStatus = ContributionStatus.PENDING
|
||||
this.self.updatedAt = new Date()
|
||||
// null because updated by user them self
|
||||
this.self.updatedBy = undefined
|
||||
}
|
||||
|
||||
public checkAuthorization(user: User): UnconfirmedContributionRole {
|
||||
if (this.self.userId !== user.id) {
|
||||
throw new LogError('Can not update contribution of another user', this.self, user.id)
|
||||
}
|
||||
// only admins and moderators can update it when status is other than progress or pending
|
||||
if (
|
||||
this.self.contributionStatus !== ContributionStatus.IN_PROGRESS &&
|
||||
this.self.contributionStatus !== ContributionStatus.PENDING
|
||||
) {
|
||||
throw new LogError(
|
||||
'Contribution can not be updated due to status',
|
||||
this.self.contributionStatus,
|
||||
)
|
||||
}
|
||||
// if a contribution was created from a moderator, user cannot init it
|
||||
// TODO: rethink
|
||||
if (this.self.moderatorId) {
|
||||
throw new LogError('Cannot update contribution of moderator', this.self, user.id)
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
import { Contribution } from '@entity/Contribution'
|
||||
import { ContributionMessage } from '@entity/ContributionMessage'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { AdminUpdateContributionArgs } from '@arg/AdminUpdateContributionArgs'
|
||||
import { ContributionArgs } from '@arg/ContributionArgs'
|
||||
|
||||
import { ContributionMessageBuilder } from '@/data/ContributionMessage.builder'
|
||||
import { Context, getClientTimezoneOffset } from '@/server/context'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { UnconfirmedContributionRole } from './UnconfirmedContribution.role'
|
||||
import { UnconfirmedContributionAdminRole } from './UnconfirmedContributionAdmin.role'
|
||||
import { UnconfirmedContributionUserRole } from './UnconfirmedContributionUser.role'
|
||||
|
||||
export class UpdateUnconfirmedContributionContext {
|
||||
/**
|
||||
*
|
||||
* @param id contribution id for update
|
||||
* @param input ContributionArgs or AdminUpdateContributionArgs depending on calling resolver function
|
||||
* @param context
|
||||
*/
|
||||
public constructor(
|
||||
private id: number,
|
||||
private input: ContributionArgs | AdminUpdateContributionArgs,
|
||||
private context: Context,
|
||||
) {
|
||||
if (!context.role || !context.user) {
|
||||
throw new LogError("context didn't contain role or user")
|
||||
}
|
||||
}
|
||||
|
||||
public async run(): Promise<{
|
||||
contribution: Contribution
|
||||
contributionMessage: ContributionMessage
|
||||
availableCreationSums: Decimal[]
|
||||
}> {
|
||||
if (!this.context.role || !this.context.user) {
|
||||
throw new LogError("context didn't contain role or user")
|
||||
}
|
||||
const contributionToUpdate = await Contribution.findOne({
|
||||
where: { id: this.id },
|
||||
})
|
||||
if (!contributionToUpdate) {
|
||||
throw new LogError('Contribution not found', this.id)
|
||||
}
|
||||
const contributionMessageBuilder = new ContributionMessageBuilder()
|
||||
contributionMessageBuilder
|
||||
.setParentContribution(contributionToUpdate)
|
||||
.setHistoryType(contributionToUpdate)
|
||||
.setUser(this.context.user)
|
||||
|
||||
// choose correct role
|
||||
let unconfirmedContributionRole: UnconfirmedContributionRole | null = null
|
||||
if (this.input instanceof ContributionArgs) {
|
||||
unconfirmedContributionRole = new UnconfirmedContributionUserRole(
|
||||
contributionToUpdate,
|
||||
this.input,
|
||||
)
|
||||
contributionMessageBuilder.setIsModerator(false)
|
||||
} else if (this.input instanceof AdminUpdateContributionArgs) {
|
||||
unconfirmedContributionRole = new UnconfirmedContributionAdminRole(
|
||||
contributionToUpdate,
|
||||
this.input,
|
||||
this.context.user,
|
||||
)
|
||||
contributionMessageBuilder.setIsModerator(true)
|
||||
}
|
||||
if (!unconfirmedContributionRole) {
|
||||
throw new LogError("don't recognize input type, maybe not implemented yet?")
|
||||
}
|
||||
// run steps
|
||||
// all possible cases not to be true are thrown in the next functions
|
||||
unconfirmedContributionRole.checkAuthorization(this.context.user, this.context.role)
|
||||
await unconfirmedContributionRole.validate(getClientTimezoneOffset(this.context))
|
||||
unconfirmedContributionRole.update()
|
||||
|
||||
return {
|
||||
contribution: contributionToUpdate,
|
||||
contributionMessage: contributionMessageBuilder.build(),
|
||||
availableCreationSums: unconfirmedContributionRole.getAvailableCreationSums(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user