mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into 2598-Register-Login-buttons-not-full-size
This commit is contained in:
commit
a7b6e3c384
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -545,7 +545,7 @@ jobs:
|
|||||||
report_name: Coverage Backend
|
report_name: Coverage Backend
|
||||||
type: lcov
|
type: lcov
|
||||||
result_path: ./backend/coverage/lcov.info
|
result_path: ./backend/coverage/lcov.info
|
||||||
min_coverage: 78
|
min_coverage: 80
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|||||||
@ -1,509 +1,212 @@
|
|||||||
import decimal from 'decimal.js-light'
|
import { EventProtocol as DbEvent } from '@entity/EventProtocol'
|
||||||
|
import Decimal from 'decimal.js-light'
|
||||||
import { EventProtocolType } from './EventProtocolType'
|
import { EventProtocolType } from './EventProtocolType'
|
||||||
|
|
||||||
export class EventBasic {
|
export const Event = (
|
||||||
type: string
|
type: EventProtocolType,
|
||||||
createdAt: Date
|
|
||||||
}
|
|
||||||
export class EventBasicUserId extends EventBasic {
|
|
||||||
userId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventBasicTx extends EventBasicUserId {
|
|
||||||
transactionId: number
|
|
||||||
amount: decimal
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventBasicTxX extends EventBasicTx {
|
|
||||||
xUserId: number
|
|
||||||
xCommunityId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventBasicCt extends EventBasicUserId {
|
|
||||||
contributionId: number
|
|
||||||
amount: decimal
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventBasicCtX extends EventBasicCt {
|
|
||||||
xUserId: number
|
|
||||||
xCommunityId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventBasicRedeem extends EventBasicUserId {
|
|
||||||
transactionId?: number
|
|
||||||
contributionId?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventBasicCtMsg extends EventBasicCt {
|
|
||||||
messageId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EventVisitGradido extends EventBasic {}
|
|
||||||
export class EventRegister extends EventBasicUserId {}
|
|
||||||
export class EventRedeemRegister extends EventBasicRedeem {}
|
|
||||||
export class EventVerifyRedeem extends EventBasicRedeem {}
|
|
||||||
export class EventInactiveAccount extends EventBasicUserId {}
|
|
||||||
export class EventSendConfirmationEmail extends EventBasicUserId {}
|
|
||||||
export class EventSendAccountMultiRegistrationEmail extends EventBasicUserId {}
|
|
||||||
export class EventSendForgotPasswordEmail extends EventBasicUserId {}
|
|
||||||
export class EventSendTransactionSendEmail extends EventBasicTxX {}
|
|
||||||
export class EventSendTransactionReceiveEmail extends EventBasicTxX {}
|
|
||||||
export class EventSendTransactionLinkRedeemEmail extends EventBasicTxX {}
|
|
||||||
export class EventSendAddedContributionEmail extends EventBasicCt {}
|
|
||||||
export class EventSendContributionConfirmEmail extends EventBasicCt {}
|
|
||||||
export class EventConfirmationEmail extends EventBasicUserId {}
|
|
||||||
export class EventRegisterEmailKlicktipp extends EventBasicUserId {}
|
|
||||||
export class EventLogin extends EventBasicUserId {}
|
|
||||||
export class EventLogout extends EventBasicUserId {}
|
|
||||||
export class EventRedeemLogin extends EventBasicRedeem {}
|
|
||||||
export class EventActivateAccount extends EventBasicUserId {}
|
|
||||||
export class EventPasswordChange extends EventBasicUserId {}
|
|
||||||
export class EventTransactionSend extends EventBasicTxX {}
|
|
||||||
export class EventTransactionSendRedeem extends EventBasicTxX {}
|
|
||||||
export class EventTransactionRepeateRedeem extends EventBasicTxX {}
|
|
||||||
export class EventTransactionCreation extends EventBasicTx {}
|
|
||||||
export class EventTransactionReceive extends EventBasicTxX {}
|
|
||||||
export class EventTransactionReceiveRedeem extends EventBasicTxX {}
|
|
||||||
export class EventContributionCreate extends EventBasicCt {}
|
|
||||||
export class EventAdminContributionCreate extends EventBasicCt {}
|
|
||||||
export class EventAdminContributionDelete extends EventBasicCt {}
|
|
||||||
export class EventAdminContributionDeny extends EventBasicCt {}
|
|
||||||
export class EventAdminContributionUpdate extends EventBasicCt {}
|
|
||||||
export class EventUserCreateContributionMessage extends EventBasicCtMsg {}
|
|
||||||
export class EventAdminCreateContributionMessage extends EventBasicCtMsg {}
|
|
||||||
export class EventContributionDelete extends EventBasicCt {}
|
|
||||||
export class EventContributionUpdate extends EventBasicCt {}
|
|
||||||
export class EventContributionConfirm extends EventBasicCtX {}
|
|
||||||
export class EventContributionDeny extends EventBasicCtX {}
|
|
||||||
export class EventContributionLinkDefine extends EventBasicCt {}
|
|
||||||
export class EventContributionLinkActivateRedeem extends EventBasicCt {}
|
|
||||||
export class EventDeleteUser extends EventBasicUserId {}
|
|
||||||
export class EventUndeleteUser extends EventBasicUserId {}
|
|
||||||
export class EventChangeUserRole extends EventBasicUserId {}
|
|
||||||
export class EventAdminUpdateContribution extends EventBasicCt {}
|
|
||||||
export class EventAdminDeleteContribution extends EventBasicCt {}
|
|
||||||
export class EventCreateContributionLink extends EventBasicCt {}
|
|
||||||
export class EventDeleteContributionLink extends EventBasicCt {}
|
|
||||||
export class EventUpdateContributionLink extends EventBasicCt {}
|
|
||||||
|
|
||||||
export class Event {
|
|
||||||
public setEventBasic(): Event {
|
|
||||||
this.type = EventProtocolType.BASIC
|
|
||||||
this.createdAt = new Date()
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventVisitGradido(): Event {
|
|
||||||
this.setEventBasic()
|
|
||||||
this.type = EventProtocolType.VISIT_GRADIDO
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventRegister(ev: EventRegister): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.REGISTER
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventRedeemRegister(ev: EventRedeemRegister): Event {
|
|
||||||
this.setByBasicRedeem(ev.userId, ev.transactionId, ev.contributionId)
|
|
||||||
this.type = EventProtocolType.REDEEM_REGISTER
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventVerifyRedeem(ev: EventVerifyRedeem): Event {
|
|
||||||
this.setByBasicRedeem(ev.userId, ev.transactionId, ev.contributionId)
|
|
||||||
this.type = EventProtocolType.VERIFY_REDEEM
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventInactiveAccount(ev: EventInactiveAccount): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.INACTIVE_ACCOUNT
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendConfirmationEmail(ev: EventSendConfirmationEmail): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.SEND_CONFIRMATION_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendAccountMultiRegistrationEmail(
|
|
||||||
ev: EventSendAccountMultiRegistrationEmail,
|
|
||||||
): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendForgotPasswordEmail(ev: EventSendForgotPasswordEmail): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.SEND_FORGOT_PASSWORD_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendTransactionSendEmail(ev: EventSendTransactionSendEmail): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.SEND_TRANSACTION_SEND_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendTransactionReceiveEmail(ev: EventSendTransactionReceiveEmail): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.SEND_TRANSACTION_RECEIVE_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendTransactionLinkRedeemEmail(ev: EventSendTransactionLinkRedeemEmail): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.SEND_TRANSACTION_LINK_REDEEM_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendAddedContributionEmail(ev: EventSendAddedContributionEmail): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.SEND_ADDED_CONTRIBUTION_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventSendContributionConfirmEmail(ev: EventSendContributionConfirmEmail): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.SEND_CONTRIBUTION_CONFIRM_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventConfirmationEmail(ev: EventConfirmationEmail): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.CONFIRM_EMAIL
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventRegisterEmailKlicktipp(ev: EventRegisterEmailKlicktipp): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.REGISTER_EMAIL_KLICKTIPP
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventLogin(ev: EventLogin): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.LOGIN
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventLogout(ev: EventLogout): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.LOGOUT
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventRedeemLogin(ev: EventRedeemLogin): Event {
|
|
||||||
this.setByBasicRedeem(ev.userId, ev.transactionId, ev.contributionId)
|
|
||||||
this.type = EventProtocolType.REDEEM_LOGIN
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventActivateAccount(ev: EventActivateAccount): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.ACTIVATE_ACCOUNT
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventPasswordChange(ev: EventPasswordChange): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.PASSWORD_CHANGE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventTransactionSend(ev: EventTransactionSend): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.TRANSACTION_SEND
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventTransactionSendRedeem(ev: EventTransactionSendRedeem): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.TRANSACTION_SEND_REDEEM
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventTransactionRepeateRedeem(ev: EventTransactionRepeateRedeem): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.TRANSACTION_REPEATE_REDEEM
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventTransactionCreation(ev: EventTransactionCreation): Event {
|
|
||||||
this.setByBasicTx(ev.userId, ev.transactionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.TRANSACTION_CREATION
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventTransactionReceive(ev: EventTransactionReceive): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.TRANSACTION_RECEIVE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventTransactionReceiveRedeem(ev: EventTransactionReceiveRedeem): Event {
|
|
||||||
this.setByBasicTxX(ev.userId, ev.transactionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.TRANSACTION_RECEIVE_REDEEM
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionCreate(ev: EventContributionCreate): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_CREATE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventAdminContributionCreate(ev: EventAdminContributionCreate): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.ADMIN_CONTRIBUTION_CREATE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventAdminContributionDelete(ev: EventAdminContributionDelete): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.ADMIN_CONTRIBUTION_DELETE
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventUserCreateContributionMessage(ev: EventUserCreateContributionMessage): Event {
|
|
||||||
this.setByBasicCtMsg(ev.userId, ev.contributionId, ev.amount, ev.messageId)
|
|
||||||
this.type = EventProtocolType.USER_CREATE_CONTRIBUTION_MESSAGE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventAdminCreateContributionMessage(ev: EventAdminCreateContributionMessage): Event {
|
|
||||||
this.setByBasicCtMsg(ev.userId, ev.contributionId, ev.amount, ev.messageId)
|
|
||||||
this.type = EventProtocolType.ADMIN_CREATE_CONTRIBUTION_MESSAGE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionDelete(ev: EventContributionDelete): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_DELETE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionUpdate(ev: EventContributionUpdate): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_UPDATE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionConfirm(ev: EventContributionConfirm): Event {
|
|
||||||
this.setByBasicCtX(ev.userId, ev.contributionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_CONFIRM
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionDeny(ev: EventContributionDeny): Event {
|
|
||||||
this.setByBasicCtX(ev.userId, ev.contributionId, ev.amount, ev.xUserId, ev.xCommunityId)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_DENY
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionLinkDefine(ev: EventContributionLinkDefine): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_LINK_DEFINE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventContributionLinkActivateRedeem(ev: EventContributionLinkActivateRedeem): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.CONTRIBUTION_LINK_ACTIVATE_REDEEM
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventDeleteUser(ev: EventDeleteUser): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.DELETE_USER
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventUndeleteUser(ev: EventUndeleteUser): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.UNDELETE_USER
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventChangeUserRole(ev: EventChangeUserRole): Event {
|
|
||||||
this.setByBasicUser(ev.userId)
|
|
||||||
this.type = EventProtocolType.CHANGE_USER_ROLE
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventAdminUpdateContribution(ev: EventAdminUpdateContribution): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.ADMIN_UPDATE_CONTRIBUTION
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventAdminDeleteContribution(ev: EventAdminDeleteContribution): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.ADMIN_DELETE_CONTRIBUTION
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventCreateContributionLink(ev: EventCreateContributionLink): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.CREATE_CONTRIBUTION_LINK
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventDeleteContributionLink(ev: EventDeleteContributionLink): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.DELETE_CONTRIBUTION_LINK
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
public setEventUpdateContributionLink(ev: EventUpdateContributionLink): Event {
|
|
||||||
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
|
|
||||||
this.type = EventProtocolType.UPDATE_CONTRIBUTION_LINK
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
setByBasicUser(userId: number): Event {
|
|
||||||
this.setEventBasic()
|
|
||||||
this.userId = userId
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
setByBasicTx(userId: number, transactionId: number, amount: decimal): Event {
|
|
||||||
this.setByBasicUser(userId)
|
|
||||||
this.transactionId = transactionId
|
|
||||||
this.amount = amount
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
setByBasicTxX(
|
|
||||||
userId: number,
|
userId: number,
|
||||||
|
xUserId: number | null = null,
|
||||||
|
xCommunityId: number | null = null,
|
||||||
|
transactionId: number | null = null,
|
||||||
|
contributionId: number | null = null,
|
||||||
|
amount: Decimal | null = null,
|
||||||
|
messageId: number | null = null,
|
||||||
|
): DbEvent => {
|
||||||
|
const event = new DbEvent()
|
||||||
|
event.type = type
|
||||||
|
event.userId = userId
|
||||||
|
event.xUserId = xUserId
|
||||||
|
event.xCommunityId = xCommunityId
|
||||||
|
event.transactionId = transactionId
|
||||||
|
event.contributionId = contributionId
|
||||||
|
event.amount = amount
|
||||||
|
event.messageId = messageId
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EVENT_CONTRIBUTION_CREATE = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.CONTRIBUTION_CREATE,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_CONTRIBUTION_DELETE = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.CONTRIBUTION_DELETE,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_CONTRIBUTION_UPDATE = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.CONTRIBUTION_UPDATE,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_ADMIN_CONTRIBUTION_CREATE = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.ADMIN_CONTRIBUTION_CREATE,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.ADMIN_CONTRIBUTION_UPDATE,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_ADMIN_CONTRIBUTION_DELETE = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.ADMIN_CONTRIBUTION_DELETE,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_CONTRIBUTION_CONFIRM = async (
|
||||||
|
userId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.CONTRIBUTION_CONFIRM,
|
||||||
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_ADMIN_CONTRIBUTION_DENY = async (
|
||||||
|
userId: number,
|
||||||
|
xUserId: number,
|
||||||
|
contributionId: number,
|
||||||
|
amount: Decimal,
|
||||||
|
): Promise<DbEvent> =>
|
||||||
|
Event(
|
||||||
|
EventProtocolType.ADMIN_CONTRIBUTION_DENY,
|
||||||
|
userId,
|
||||||
|
xUserId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
contributionId,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
|
export const EVENT_TRANSACTION_SEND = async (
|
||||||
|
userId: number,
|
||||||
|
xUserId: number,
|
||||||
transactionId: number,
|
transactionId: number,
|
||||||
amount: decimal,
|
amount: Decimal,
|
||||||
xUserId: number,
|
): Promise<DbEvent> =>
|
||||||
xCommunityId: number,
|
Event(
|
||||||
): Event {
|
EventProtocolType.TRANSACTION_SEND,
|
||||||
this.setByBasicTx(userId, transactionId, amount)
|
userId,
|
||||||
this.xUserId = xUserId
|
xUserId,
|
||||||
this.xCommunityId = xCommunityId
|
null,
|
||||||
|
transactionId,
|
||||||
|
null,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
return this
|
export const EVENT_TRANSACTION_RECEIVE = async (
|
||||||
}
|
|
||||||
|
|
||||||
setByBasicCt(userId: number, contributionId: number, amount: decimal): Event {
|
|
||||||
this.setByBasicUser(userId)
|
|
||||||
this.contributionId = contributionId
|
|
||||||
this.amount = amount
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
setByBasicCtMsg(
|
|
||||||
userId: number,
|
userId: number,
|
||||||
contributionId: number,
|
|
||||||
amount: decimal,
|
|
||||||
messageId: number,
|
|
||||||
): Event {
|
|
||||||
this.setByBasicCt(userId, contributionId, amount)
|
|
||||||
this.messageId = messageId
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
setByBasicCtX(
|
|
||||||
userId: number,
|
|
||||||
contributionId: number,
|
|
||||||
amount: decimal,
|
|
||||||
xUserId: number,
|
xUserId: number,
|
||||||
xCommunityId: number,
|
transactionId: number,
|
||||||
): Event {
|
amount: Decimal,
|
||||||
this.setByBasicCt(userId, contributionId, amount)
|
): Promise<DbEvent> =>
|
||||||
this.xUserId = xUserId
|
Event(
|
||||||
this.xCommunityId = xCommunityId
|
EventProtocolType.TRANSACTION_RECEIVE,
|
||||||
|
userId,
|
||||||
|
xUserId,
|
||||||
|
null,
|
||||||
|
transactionId,
|
||||||
|
null,
|
||||||
|
amount,
|
||||||
|
).save()
|
||||||
|
|
||||||
return this
|
export const EVENT_LOGIN = async (userId: number): Promise<DbEvent> =>
|
||||||
}
|
Event(EventProtocolType.LOGIN, userId, null, null, null, null, null, null).save()
|
||||||
|
|
||||||
setByBasicRedeem(userId: number, transactionId?: number, contributionId?: number): Event {
|
export const EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = async (
|
||||||
this.setByBasicUser(userId)
|
userId: number,
|
||||||
if (transactionId) this.transactionId = transactionId
|
): Promise<DbEvent> => Event(EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, userId).save()
|
||||||
if (contributionId) this.contributionId = contributionId
|
|
||||||
|
|
||||||
return this
|
export const EVENT_SEND_CONFIRMATION_EMAIL = async (userId: number): Promise<DbEvent> =>
|
||||||
}
|
Event(EventProtocolType.SEND_CONFIRMATION_EMAIL, userId).save()
|
||||||
|
|
||||||
id: number
|
export const EVENT_ADMIN_SEND_CONFIRMATION_EMAIL = async (userId: number): Promise<DbEvent> =>
|
||||||
type: string
|
Event(EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, userId).save()
|
||||||
createdAt: Date
|
|
||||||
userId: number
|
/* export const EVENT_REDEEM_REGISTER = async (
|
||||||
xUserId?: number
|
userId: number,
|
||||||
xCommunityId?: number
|
transactionId: number | null = null,
|
||||||
transactionId?: number
|
contributionId: number | null = null,
|
||||||
contributionId?: number
|
): Promise<Event> =>
|
||||||
amount?: decimal
|
Event(
|
||||||
messageId?: number
|
EventProtocolType.REDEEM_REGISTER,
|
||||||
}
|
userId,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
transactionId,
|
||||||
|
contributionId,
|
||||||
|
).save()
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const EVENT_REGISTER = async (userId: number): Promise<DbEvent> =>
|
||||||
|
Event(EventProtocolType.REGISTER, userId).save()
|
||||||
|
|
||||||
|
export const EVENT_ACTIVATE_ACCOUNT = async (userId: number): Promise<DbEvent> =>
|
||||||
|
Event(EventProtocolType.ACTIVATE_ACCOUNT, userId).save()
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
import { Event } from '@/event/Event'
|
|
||||||
import { backendLogger as logger } from '@/server/logger'
|
|
||||||
import { EventProtocol } from '@entity/EventProtocol'
|
|
||||||
|
|
||||||
export const writeEvent = async (event: Event): Promise<EventProtocol | null> => {
|
|
||||||
logger.info('writeEvent', event)
|
|
||||||
const dbEvent = new EventProtocol()
|
|
||||||
dbEvent.type = event.type
|
|
||||||
dbEvent.createdAt = event.createdAt
|
|
||||||
dbEvent.userId = event.userId
|
|
||||||
dbEvent.xUserId = event.xUserId || null
|
|
||||||
dbEvent.xCommunityId = event.xCommunityId || null
|
|
||||||
dbEvent.contributionId = event.contributionId || null
|
|
||||||
dbEvent.transactionId = event.transactionId || null
|
|
||||||
dbEvent.amount = event.amount || null
|
|
||||||
return dbEvent.save()
|
|
||||||
}
|
|
||||||
@ -1,50 +1,50 @@
|
|||||||
export enum EventProtocolType {
|
export enum EventProtocolType {
|
||||||
BASIC = 'BASIC',
|
// VISIT_GRADIDO = 'VISIT_GRADIDO',
|
||||||
VISIT_GRADIDO = 'VISIT_GRADIDO',
|
|
||||||
REGISTER = 'REGISTER',
|
REGISTER = 'REGISTER',
|
||||||
REDEEM_REGISTER = 'REDEEM_REGISTER',
|
REDEEM_REGISTER = 'REDEEM_REGISTER',
|
||||||
VERIFY_REDEEM = 'VERIFY_REDEEM',
|
// VERIFY_REDEEM = 'VERIFY_REDEEM',
|
||||||
INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
|
// INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
|
||||||
SEND_CONFIRMATION_EMAIL = 'SEND_CONFIRMATION_EMAIL',
|
SEND_CONFIRMATION_EMAIL = 'SEND_CONFIRMATION_EMAIL',
|
||||||
|
ADMIN_SEND_CONFIRMATION_EMAIL = 'ADMIN_SEND_CONFIRMATION_EMAIL',
|
||||||
SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = 'SEND_ACCOUNT_MULTIREGISTRATION_EMAIL',
|
SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = 'SEND_ACCOUNT_MULTIREGISTRATION_EMAIL',
|
||||||
CONFIRM_EMAIL = 'CONFIRM_EMAIL',
|
// CONFIRM_EMAIL = 'CONFIRM_EMAIL',
|
||||||
REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
|
// REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
|
||||||
LOGIN = 'LOGIN',
|
LOGIN = 'LOGIN',
|
||||||
LOGOUT = 'LOGOUT',
|
// LOGOUT = 'LOGOUT',
|
||||||
REDEEM_LOGIN = 'REDEEM_LOGIN',
|
// REDEEM_LOGIN = 'REDEEM_LOGIN',
|
||||||
ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
|
ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
|
||||||
SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL',
|
// SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL',
|
||||||
PASSWORD_CHANGE = 'PASSWORD_CHANGE',
|
// PASSWORD_CHANGE = 'PASSWORD_CHANGE',
|
||||||
SEND_TRANSACTION_SEND_EMAIL = 'SEND_TRANSACTION_SEND_EMAIL',
|
// SEND_TRANSACTION_SEND_EMAIL = 'SEND_TRANSACTION_SEND_EMAIL',
|
||||||
SEND_TRANSACTION_RECEIVE_EMAIL = 'SEND_TRANSACTION_RECEIVE_EMAIL',
|
// SEND_TRANSACTION_RECEIVE_EMAIL = 'SEND_TRANSACTION_RECEIVE_EMAIL',
|
||||||
TRANSACTION_SEND = 'TRANSACTION_SEND',
|
TRANSACTION_SEND = 'TRANSACTION_SEND',
|
||||||
TRANSACTION_SEND_REDEEM = 'TRANSACTION_SEND_REDEEM',
|
// TRANSACTION_SEND_REDEEM = 'TRANSACTION_SEND_REDEEM',
|
||||||
TRANSACTION_REPEATE_REDEEM = 'TRANSACTION_REPEATE_REDEEM',
|
// TRANSACTION_REPEATE_REDEEM = 'TRANSACTION_REPEATE_REDEEM',
|
||||||
TRANSACTION_CREATION = 'TRANSACTION_CREATION',
|
// TRANSACTION_CREATION = 'TRANSACTION_CREATION',
|
||||||
TRANSACTION_RECEIVE = 'TRANSACTION_RECEIVE',
|
TRANSACTION_RECEIVE = 'TRANSACTION_RECEIVE',
|
||||||
TRANSACTION_RECEIVE_REDEEM = 'TRANSACTION_RECEIVE_REDEEM',
|
// TRANSACTION_RECEIVE_REDEEM = 'TRANSACTION_RECEIVE_REDEEM',
|
||||||
SEND_TRANSACTION_LINK_REDEEM_EMAIL = 'SEND_TRANSACTION_LINK_REDEEM_EMAIL',
|
// SEND_TRANSACTION_LINK_REDEEM_EMAIL = 'SEND_TRANSACTION_LINK_REDEEM_EMAIL',
|
||||||
SEND_ADDED_CONTRIBUTION_EMAIL = 'SEND_ADDED_CONTRIBUTION_EMAIL',
|
// SEND_ADDED_CONTRIBUTION_EMAIL = 'SEND_ADDED_CONTRIBUTION_EMAIL',
|
||||||
SEND_CONTRIBUTION_CONFIRM_EMAIL = 'SEND_CONTRIBUTION_CONFIRM_EMAIL',
|
// SEND_CONTRIBUTION_CONFIRM_EMAIL = 'SEND_CONTRIBUTION_CONFIRM_EMAIL',
|
||||||
CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE',
|
CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE',
|
||||||
CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM',
|
CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM',
|
||||||
CONTRIBUTION_DENY = 'CONTRIBUTION_DENY',
|
// CONTRIBUTION_DENY = 'CONTRIBUTION_DENY',
|
||||||
CONTRIBUTION_LINK_DEFINE = 'CONTRIBUTION_LINK_DEFINE',
|
// CONTRIBUTION_LINK_DEFINE = 'CONTRIBUTION_LINK_DEFINE',
|
||||||
CONTRIBUTION_LINK_ACTIVATE_REDEEM = 'CONTRIBUTION_LINK_ACTIVATE_REDEEM',
|
// CONTRIBUTION_LINK_ACTIVATE_REDEEM = 'CONTRIBUTION_LINK_ACTIVATE_REDEEM',
|
||||||
CONTRIBUTION_DELETE = 'CONTRIBUTION_DELETE',
|
CONTRIBUTION_DELETE = 'CONTRIBUTION_DELETE',
|
||||||
CONTRIBUTION_UPDATE = 'CONTRIBUTION_UPDATE',
|
CONTRIBUTION_UPDATE = 'CONTRIBUTION_UPDATE',
|
||||||
ADMIN_CONTRIBUTION_CREATE = 'ADMIN_CONTRIBUTION_CREATE',
|
ADMIN_CONTRIBUTION_CREATE = 'ADMIN_CONTRIBUTION_CREATE',
|
||||||
ADMIN_CONTRIBUTION_DELETE = 'ADMIN_CONTRIBUTION_DELETE',
|
ADMIN_CONTRIBUTION_DELETE = 'ADMIN_CONTRIBUTION_DELETE',
|
||||||
ADMIN_CONTRIBUTION_DENY = 'ADMIN_CONTRIBUTION_DENY',
|
ADMIN_CONTRIBUTION_DENY = 'ADMIN_CONTRIBUTION_DENY',
|
||||||
ADMIN_CONTRIBUTION_UPDATE = 'ADMIN_CONTRIBUTION_UPDATE',
|
ADMIN_CONTRIBUTION_UPDATE = 'ADMIN_CONTRIBUTION_UPDATE',
|
||||||
USER_CREATE_CONTRIBUTION_MESSAGE = 'USER_CREATE_CONTRIBUTION_MESSAGE',
|
// USER_CREATE_CONTRIBUTION_MESSAGE = 'USER_CREATE_CONTRIBUTION_MESSAGE',
|
||||||
ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
|
// ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
|
||||||
DELETE_USER = 'DELETE_USER',
|
// DELETE_USER = 'DELETE_USER',
|
||||||
UNDELETE_USER = 'UNDELETE_USER',
|
// UNDELETE_USER = 'UNDELETE_USER',
|
||||||
CHANGE_USER_ROLE = 'CHANGE_USER_ROLE',
|
// CHANGE_USER_ROLE = 'CHANGE_USER_ROLE',
|
||||||
ADMIN_UPDATE_CONTRIBUTION = 'ADMIN_UPDATE_CONTRIBUTION',
|
// ADMIN_UPDATE_CONTRIBUTION = 'ADMIN_UPDATE_CONTRIBUTION',
|
||||||
ADMIN_DELETE_CONTRIBUTION = 'ADMIN_DELETE_CONTRIBUTION',
|
// ADMIN_DELETE_CONTRIBUTION = 'ADMIN_DELETE_CONTRIBUTION',
|
||||||
CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
|
// CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
|
||||||
DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
|
// DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
|
||||||
UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
|
// UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -244,7 +244,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the create contribution event in the database', async () => {
|
it('stores the CONTRIBUTION_CREATE event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.CONTRIBUTION_CREATE,
|
type: EventProtocolType.CONTRIBUTION_CREATE,
|
||||||
@ -696,7 +696,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the update contribution event in the database', async () => {
|
it('stores the CONTRIBUTION_UPDATE event in the database', async () => {
|
||||||
bibi = await query({
|
bibi = await query({
|
||||||
query: login,
|
query: login,
|
||||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
@ -1263,7 +1263,7 @@ describe('ContributionResolver', () => {
|
|||||||
).resolves.toBeTruthy()
|
).resolves.toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the delete contribution event in the database', async () => {
|
it('stores the CONTRIBUTION_DELETE event in the database', async () => {
|
||||||
const contribution = await mutate({
|
const contribution = await mutate({
|
||||||
mutation: createContribution,
|
mutation: createContribution,
|
||||||
variables: {
|
variables: {
|
||||||
@ -1780,7 +1780,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the admin create contribution event in the database', async () => {
|
it('stores the ADMIN_CONTRIBUTION_CREATE event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.ADMIN_CONTRIBUTION_CREATE,
|
type: EventProtocolType.ADMIN_CONTRIBUTION_CREATE,
|
||||||
@ -2045,7 +2045,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the admin update contribution event in the database', async () => {
|
it('stores the ADMIN_CONTRIBUTION_UPDATE event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE,
|
type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE,
|
||||||
@ -2085,7 +2085,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the admin update contribution event in the database', async () => {
|
it('stores the ADMIN_CONTRIBUTION_UPDATE event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE,
|
type: EventProtocolType.ADMIN_CONTRIBUTION_UPDATE,
|
||||||
@ -2229,7 +2229,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the admin delete contribution event in the database', async () => {
|
it('stores the ADMIN_CONTRIBUTION_DELETE event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.ADMIN_CONTRIBUTION_DELETE,
|
type: EventProtocolType.ADMIN_CONTRIBUTION_DELETE,
|
||||||
@ -2371,7 +2371,7 @@ describe('ContributionResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the contribution confirm event in the database', async () => {
|
it('stores the CONTRIBUTION_CONFIRM event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.CONTRIBUTION_CONFIRM,
|
type: EventProtocolType.CONTRIBUTION_CONFIRM,
|
||||||
@ -2403,7 +2403,7 @@ describe('ContributionResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the send confirmation email event in the database', async () => {
|
it('stores the SEND_CONFIRMATION_EMAIL event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,
|
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,
|
||||||
|
|||||||
@ -37,17 +37,15 @@ import {
|
|||||||
} from './util/creations'
|
} from './util/creations'
|
||||||
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS, FULL_CREATION_AVAILABLE } from './const/const'
|
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS, FULL_CREATION_AVAILABLE } from './const/const'
|
||||||
import {
|
import {
|
||||||
Event,
|
EVENT_CONTRIBUTION_CREATE,
|
||||||
EventContributionCreate,
|
EVENT_CONTRIBUTION_DELETE,
|
||||||
EventContributionDelete,
|
EVENT_CONTRIBUTION_UPDATE,
|
||||||
EventContributionUpdate,
|
EVENT_ADMIN_CONTRIBUTION_CREATE,
|
||||||
EventContributionConfirm,
|
EVENT_ADMIN_CONTRIBUTION_UPDATE,
|
||||||
EventAdminContributionCreate,
|
EVENT_ADMIN_CONTRIBUTION_DELETE,
|
||||||
EventAdminContributionDelete,
|
EVENT_CONTRIBUTION_CONFIRM,
|
||||||
EventAdminContributionDeny,
|
EVENT_ADMIN_CONTRIBUTION_DENY,
|
||||||
EventAdminContributionUpdate,
|
|
||||||
} from '@/event/Event'
|
} from '@/event/Event'
|
||||||
import { writeEvent } from '@/event/EventProtocolEmitter'
|
|
||||||
import { calculateDecay } from '@/util/decay'
|
import { calculateDecay } from '@/util/decay'
|
||||||
import {
|
import {
|
||||||
sendContributionConfirmedEmail,
|
sendContributionConfirmedEmail,
|
||||||
@ -75,8 +73,6 @@ export class ContributionResolver {
|
|||||||
throw new LogError('Memo text is too long', memo.length)
|
throw new LogError('Memo text is too long', memo.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = new Event()
|
|
||||||
|
|
||||||
const user = getUser(context)
|
const user = getUser(context)
|
||||||
const creations = await getUserCreation(user.id, clientTimezoneOffset)
|
const creations = await getUserCreation(user.id, clientTimezoneOffset)
|
||||||
logger.trace('creations', creations)
|
logger.trace('creations', creations)
|
||||||
@ -95,11 +91,7 @@ export class ContributionResolver {
|
|||||||
logger.trace('contribution to save', contribution)
|
logger.trace('contribution to save', contribution)
|
||||||
await DbContribution.save(contribution)
|
await DbContribution.save(contribution)
|
||||||
|
|
||||||
const eventCreateContribution = new EventContributionCreate()
|
await EVENT_CONTRIBUTION_CREATE(user.id, contribution.id, amount)
|
||||||
eventCreateContribution.userId = user.id
|
|
||||||
eventCreateContribution.amount = amount
|
|
||||||
eventCreateContribution.contributionId = contribution.id
|
|
||||||
await writeEvent(event.setEventContributionCreate(eventCreateContribution))
|
|
||||||
|
|
||||||
return new UnconfirmedContribution(contribution, user, creations)
|
return new UnconfirmedContribution(contribution, user, creations)
|
||||||
}
|
}
|
||||||
@ -110,7 +102,6 @@ export class ContributionResolver {
|
|||||||
@Arg('id', () => Int) id: number,
|
@Arg('id', () => Int) id: number,
|
||||||
@Ctx() context: Context,
|
@Ctx() context: Context,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const event = new Event()
|
|
||||||
const user = getUser(context)
|
const user = getUser(context)
|
||||||
const contribution = await DbContribution.findOne(id)
|
const contribution = await DbContribution.findOne(id)
|
||||||
if (!contribution) {
|
if (!contribution) {
|
||||||
@ -128,11 +119,7 @@ export class ContributionResolver {
|
|||||||
contribution.deletedAt = new Date()
|
contribution.deletedAt = new Date()
|
||||||
await contribution.save()
|
await contribution.save()
|
||||||
|
|
||||||
const eventDeleteContribution = new EventContributionDelete()
|
await EVENT_CONTRIBUTION_DELETE(user.id, contribution.id, contribution.amount)
|
||||||
eventDeleteContribution.userId = user.id
|
|
||||||
eventDeleteContribution.contributionId = contribution.id
|
|
||||||
eventDeleteContribution.amount = contribution.amount
|
|
||||||
await writeEvent(event.setEventContributionDelete(eventDeleteContribution))
|
|
||||||
|
|
||||||
const res = await contribution.softRemove()
|
const res = await contribution.softRemove()
|
||||||
return !!res
|
return !!res
|
||||||
@ -279,13 +266,7 @@ export class ContributionResolver {
|
|||||||
contributionToUpdate.updatedAt = new Date()
|
contributionToUpdate.updatedAt = new Date()
|
||||||
DbContribution.save(contributionToUpdate)
|
DbContribution.save(contributionToUpdate)
|
||||||
|
|
||||||
const event = new Event()
|
await EVENT_CONTRIBUTION_UPDATE(user.id, contributionId, amount)
|
||||||
|
|
||||||
const eventUpdateContribution = new EventContributionUpdate()
|
|
||||||
eventUpdateContribution.userId = user.id
|
|
||||||
eventUpdateContribution.contributionId = contributionId
|
|
||||||
eventUpdateContribution.amount = amount
|
|
||||||
await writeEvent(event.setEventContributionUpdate(eventUpdateContribution))
|
|
||||||
|
|
||||||
return new UnconfirmedContribution(contributionToUpdate, user, creations)
|
return new UnconfirmedContribution(contributionToUpdate, user, creations)
|
||||||
}
|
}
|
||||||
@ -321,7 +302,6 @@ export class ContributionResolver {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = new Event()
|
|
||||||
const moderator = getUser(context)
|
const moderator = getUser(context)
|
||||||
logger.trace('moderator: ', moderator.id)
|
logger.trace('moderator: ', moderator.id)
|
||||||
const creations = await getUserCreation(emailContact.userId, clientTimezoneOffset)
|
const creations = await getUserCreation(emailContact.userId, clientTimezoneOffset)
|
||||||
@ -343,11 +323,7 @@ export class ContributionResolver {
|
|||||||
|
|
||||||
await DbContribution.save(contribution)
|
await DbContribution.save(contribution)
|
||||||
|
|
||||||
const eventAdminCreateContribution = new EventAdminContributionCreate()
|
await EVENT_ADMIN_CONTRIBUTION_CREATE(moderator.id, contribution.id, amount)
|
||||||
eventAdminCreateContribution.userId = moderator.id
|
|
||||||
eventAdminCreateContribution.amount = amount
|
|
||||||
eventAdminCreateContribution.contributionId = contribution.id
|
|
||||||
await writeEvent(event.setEventAdminContributionCreate(eventAdminCreateContribution))
|
|
||||||
|
|
||||||
return getUserCreation(emailContact.userId, clientTimezoneOffset)
|
return getUserCreation(emailContact.userId, clientTimezoneOffset)
|
||||||
}
|
}
|
||||||
@ -442,12 +418,7 @@ export class ContributionResolver {
|
|||||||
|
|
||||||
result.creation = await getUserCreation(emailContact.user.id, clientTimezoneOffset)
|
result.creation = await getUserCreation(emailContact.user.id, clientTimezoneOffset)
|
||||||
|
|
||||||
const event = new Event()
|
await EVENT_ADMIN_CONTRIBUTION_UPDATE(emailContact.user.id, contributionToUpdate.id, amount)
|
||||||
const eventAdminContributionUpdate = new EventAdminContributionUpdate()
|
|
||||||
eventAdminContributionUpdate.userId = emailContact.user.id
|
|
||||||
eventAdminContributionUpdate.amount = amount
|
|
||||||
eventAdminContributionUpdate.contributionId = contributionToUpdate.id
|
|
||||||
await writeEvent(event.setEventAdminContributionUpdate(eventAdminContributionUpdate))
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -518,12 +489,8 @@ export class ContributionResolver {
|
|||||||
await contribution.save()
|
await contribution.save()
|
||||||
const res = await contribution.softRemove()
|
const res = await contribution.softRemove()
|
||||||
|
|
||||||
const event = new Event()
|
await EVENT_ADMIN_CONTRIBUTION_DELETE(contribution.userId, contribution.id, contribution.amount)
|
||||||
const eventAdminContributionDelete = new EventAdminContributionDelete()
|
|
||||||
eventAdminContributionDelete.userId = contribution.userId
|
|
||||||
eventAdminContributionDelete.amount = contribution.amount
|
|
||||||
eventAdminContributionDelete.contributionId = contribution.id
|
|
||||||
await writeEvent(event.setEventAdminContributionDelete(eventAdminContributionDelete))
|
|
||||||
sendContributionDeletedEmail({
|
sendContributionDeletedEmail({
|
||||||
firstName: user.firstName,
|
firstName: user.firstName,
|
||||||
lastName: user.lastName,
|
lastName: user.lastName,
|
||||||
@ -635,12 +602,7 @@ export class ContributionResolver {
|
|||||||
await queryRunner.release()
|
await queryRunner.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = new Event()
|
await EVENT_CONTRIBUTION_CONFIRM(user.id, contribution.id, contribution.amount)
|
||||||
const eventContributionConfirm = new EventContributionConfirm()
|
|
||||||
eventContributionConfirm.userId = user.id
|
|
||||||
eventContributionConfirm.amount = contribution.amount
|
|
||||||
eventContributionConfirm.contributionId = contribution.id
|
|
||||||
await writeEvent(event.setEventContributionConfirm(eventContributionConfirm))
|
|
||||||
} finally {
|
} finally {
|
||||||
releaseLock()
|
releaseLock()
|
||||||
}
|
}
|
||||||
@ -730,12 +692,12 @@ export class ContributionResolver {
|
|||||||
contributionToUpdate.deniedAt = new Date()
|
contributionToUpdate.deniedAt = new Date()
|
||||||
const res = await contributionToUpdate.save()
|
const res = await contributionToUpdate.save()
|
||||||
|
|
||||||
const event = new Event()
|
await EVENT_ADMIN_CONTRIBUTION_DENY(
|
||||||
const eventAdminContributionDeny = new EventAdminContributionDeny()
|
contributionToUpdate.userId,
|
||||||
eventAdminContributionDeny.userId = contributionToUpdate.userId
|
moderator.id,
|
||||||
eventAdminContributionDeny.amount = contributionToUpdate.amount
|
contributionToUpdate.id,
|
||||||
eventAdminContributionDeny.contributionId = contributionToUpdate.id
|
contributionToUpdate.amount,
|
||||||
await writeEvent(event.setEventAdminContributionDeny(eventAdminContributionDeny))
|
)
|
||||||
|
|
||||||
sendContributionDeniedEmail({
|
sendContributionDeniedEmail({
|
||||||
firstName: user.firstName,
|
firstName: user.firstName,
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
redeemTransactionLink,
|
redeemTransactionLink,
|
||||||
createContribution,
|
createContribution,
|
||||||
updateContribution,
|
updateContribution,
|
||||||
|
createTransactionLink,
|
||||||
} from '@/seeds/graphql/mutations'
|
} from '@/seeds/graphql/mutations'
|
||||||
import { listTransactionLinksAdmin } from '@/seeds/graphql/queries'
|
import { listTransactionLinksAdmin } from '@/seeds/graphql/queries'
|
||||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||||
@ -24,6 +25,7 @@ import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
|
|||||||
import Decimal from 'decimal.js-light'
|
import Decimal from 'decimal.js-light'
|
||||||
import { GraphQLError } from 'graphql'
|
import { GraphQLError } from 'graphql'
|
||||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||||
|
import { logger } from '@test/testSetup'
|
||||||
|
|
||||||
// mock semaphore to allow use fake timers
|
// mock semaphore to allow use fake timers
|
||||||
jest.mock('@/util/TRANSACTIONS_LOCK')
|
jest.mock('@/util/TRANSACTIONS_LOCK')
|
||||||
@ -50,7 +52,75 @@ afterAll(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('TransactionLinkResolver', () => {
|
describe('TransactionLinkResolver', () => {
|
||||||
|
describe('createTransactionLink', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when amount is zero', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: 0,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Amount must be a positive number')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(0))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when amount is negative', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: -10,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('Amount must be a positive number')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Amount must be a positive number', new Decimal(-10))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error when user has not enough GDD', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: createTransactionLink,
|
||||||
|
variables: {
|
||||||
|
amount: 1001,
|
||||||
|
memo: 'Test',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: [new GraphQLError('User has not enough GDD')],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('User has not enough GDD', expect.any(Number))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('redeemTransactionLink', () => {
|
describe('redeemTransactionLink', () => {
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
describe('contributionLink', () => {
|
describe('contributionLink', () => {
|
||||||
describe('input not valid', () => {
|
describe('input not valid', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
@ -61,6 +131,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('throws error when link does not exists', async () => {
|
it('throws error when link does not exists', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
@ -69,16 +140,26 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
|
||||||
'Creation from contribution link was not successful. Error: No contribution link found to given code: CL-123456',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws error when link is not valid yet', async () => {
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'No contribution link found to given code',
|
||||||
|
'CL-123456',
|
||||||
|
)
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('No contribution link found to given code'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
|
const validFrom = new Date(now.getFullYear() + 1, 0, 1)
|
||||||
|
|
||||||
|
it('throws error when link is not valid yet', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
const {
|
const {
|
||||||
data: { createContributionLink: contributionLink },
|
data: { createContributionLink: contributionLink },
|
||||||
} = await mutate({
|
} = await mutate({
|
||||||
@ -88,7 +169,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
name: 'Daily Contribution Link',
|
name: 'Daily Contribution Link',
|
||||||
memo: 'Thank you for contribute daily to the community',
|
memo: 'Thank you for contribute daily to the community',
|
||||||
cycle: 'DAILY',
|
cycle: 'DAILY',
|
||||||
validFrom: new Date(now.getFullYear() + 1, 0, 1).toISOString(),
|
validFrom: validFrom.toISOString(),
|
||||||
validTo: new Date(now.getFullYear() + 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
validTo: new Date(now.getFullYear() + 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
||||||
maxAmountPerMonth: new Decimal(200),
|
maxAmountPerMonth: new Decimal(200),
|
||||||
maxPerCycle: 1,
|
maxPerCycle: 1,
|
||||||
@ -102,16 +183,21 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
|
||||||
'Creation from contribution link was not successful. Error: Contribution link not valid yet',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
await resetEntity(DbContributionLink)
|
await resetEntity(DbContributionLink)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Contribution link is not valid yet', validFrom)
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link is not valid yet'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('throws error when contributionLink cycle is invalid', async () => {
|
it('throws error when contributionLink cycle is invalid', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const {
|
const {
|
||||||
data: { createContributionLink: contributionLink },
|
data: { createContributionLink: contributionLink },
|
||||||
@ -136,17 +222,22 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
|
||||||
'Creation from contribution link was not successful. Error: Contribution link has unknown cycle',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
await resetEntity(DbContributionLink)
|
await resetEntity(DbContributionLink)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Contribution link has unknown cycle', 'INVALID')
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link has unknown cycle'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const validTo = new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59, 0)
|
||||||
it('throws error when link is no longer valid', async () => {
|
it('throws error when link is no longer valid', async () => {
|
||||||
const now = new Date()
|
jest.clearAllMocks()
|
||||||
const {
|
const {
|
||||||
data: { createContributionLink: contributionLink },
|
data: { createContributionLink: contributionLink },
|
||||||
} = await mutate({
|
} = await mutate({
|
||||||
@ -157,7 +248,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
memo: 'Thank you for contribute daily to the community',
|
memo: 'Thank you for contribute daily to the community',
|
||||||
cycle: 'DAILY',
|
cycle: 'DAILY',
|
||||||
validFrom: new Date(now.getFullYear() - 1, 0, 1).toISOString(),
|
validFrom: new Date(now.getFullYear() - 1, 0, 1).toISOString(),
|
||||||
validTo: new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59, 999).toISOString(),
|
validTo: validTo.toISOString(),
|
||||||
maxAmountPerMonth: new Decimal(200),
|
maxAmountPerMonth: new Decimal(200),
|
||||||
maxPerCycle: 1,
|
maxPerCycle: 1,
|
||||||
},
|
},
|
||||||
@ -170,14 +261,18 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
|
||||||
'Creation from contribution link was not successful. Error: Contribution link is no longer valid',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
await resetEntity(DbContributionLink)
|
await resetEntity(DbContributionLink)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Contribution link is no longer valid', validTo)
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link is no longer valid'),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: have this test separated into a transactionLink and a contributionLink part
|
// TODO: have this test separated into a transactionLink and a contributionLink part
|
||||||
@ -250,6 +345,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('does not allow the user to redeem the contribution link', async () => {
|
it('does not allow the user to redeem the contribution link', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
@ -258,13 +354,18 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
|
||||||
'Creation from contribution link was not successful. Error: The amount (5 GDD) to be created exceeds the amount (0 GDD) still available for this month.',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error(
|
||||||
|
'The amount (5 GDD) to be created exceeds the amount (0 GDD) still available for this month.',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('user has no pending contributions that would not allow to redeem the link', () => {
|
describe('user has no pending contributions that would not allow to redeem the link', () => {
|
||||||
@ -301,6 +402,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('does not allow the user to redeem the contribution link a second time on the same day', async () => {
|
it('does not allow the user to redeem the contribution link a second time on the same day', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
@ -309,14 +411,17 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
|
||||||
'Creation from contribution link was not successful. Error: Contribution link already redeemed today',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link already redeemed today'),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
describe('after one day', () => {
|
describe('after one day', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
jest.useFakeTimers()
|
jest.useFakeTimers()
|
||||||
@ -349,6 +454,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('does not allow the user to redeem the contribution link a second time on the same day', async () => {
|
it('does not allow the user to redeem the contribution link a second time on the same day', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: redeemTransactionLink,
|
mutation: redeemTransactionLink,
|
||||||
@ -357,11 +463,15 @@ describe('TransactionLinkResolver', () => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
errors: [
|
errors: [new GraphQLError('Creation from contribution link was not successful')],
|
||||||
new GraphQLError(
|
})
|
||||||
'Creation from contribution link was not successful. Error: Contribution link already redeemed today',
|
})
|
||||||
),
|
|
||||||
],
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'Creation from contribution link was not successful',
|
||||||
|
new Error('Contribution link already redeemed today'),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -369,7 +479,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('transaction links list', () => {
|
describe('listTransactionLinksAdmin', () => {
|
||||||
const variables = {
|
const variables = {
|
||||||
userId: 1, // dummy, may be replaced
|
userId: 1, // dummy, may be replaced
|
||||||
filters: null,
|
filters: null,
|
||||||
@ -377,8 +487,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
pageSize: 5,
|
pageSize: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: there is a test not cleaning up after itself! Fix it!
|
afterAll(async () => {
|
||||||
beforeAll(async () => {
|
|
||||||
await cleanDB()
|
await cleanDB()
|
||||||
resetToken()
|
resetToken()
|
||||||
})
|
})
|
||||||
@ -436,9 +545,7 @@ describe('TransactionLinkResolver', () => {
|
|||||||
variables.userId = user.id
|
variables.userId = user.id
|
||||||
variables.pageSize = 25
|
variables.pageSize = 25
|
||||||
// bibi needs GDDs
|
// bibi needs GDDs
|
||||||
const bibisCreation = creations.find(
|
const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de')
|
||||||
(creation) => creation.email === 'bibi@bloxberg.de',
|
|
||||||
)
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
await creationFactory(testEnv, bibisCreation!)
|
await creationFactory(testEnv, bibisCreation!)
|
||||||
// bibis transaktion links
|
// bibis transaktion links
|
||||||
@ -638,7 +745,6 @@ describe('TransactionLinkResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
describe('transactionLinkCode', () => {
|
describe('transactionLinkCode', () => {
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import { getUserCreation, validateContribution } from './util/creations'
|
|||||||
import { executeTransaction } from './TransactionResolver'
|
import { executeTransaction } from './TransactionResolver'
|
||||||
import QueryLinkResult from '@union/QueryLinkResult'
|
import QueryLinkResult from '@union/QueryLinkResult'
|
||||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||||
|
import LogError from '@/server/LogError'
|
||||||
|
|
||||||
import { getLastTransaction } from './util/getLastTransaction'
|
import { getLastTransaction } from './util/getLastTransaction'
|
||||||
|
|
||||||
@ -65,12 +66,16 @@ export class TransactionLinkResolver {
|
|||||||
const createdDate = new Date()
|
const createdDate = new Date()
|
||||||
const validUntil = transactionLinkExpireDate(createdDate)
|
const validUntil = transactionLinkExpireDate(createdDate)
|
||||||
|
|
||||||
|
if (amount.lessThanOrEqualTo(0)) {
|
||||||
|
throw new LogError('Amount must be a positive number', amount)
|
||||||
|
}
|
||||||
|
|
||||||
const holdAvailableAmount = amount.minus(calculateDecay(amount, createdDate, validUntil).decay)
|
const holdAvailableAmount = amount.minus(calculateDecay(amount, createdDate, validUntil).decay)
|
||||||
|
|
||||||
// validate amount
|
// validate amount
|
||||||
const sendBalance = await calculateBalance(user.id, holdAvailableAmount.mul(-1), createdDate)
|
const sendBalance = await calculateBalance(user.id, holdAvailableAmount.mul(-1), createdDate)
|
||||||
if (!sendBalance) {
|
if (!sendBalance) {
|
||||||
throw new Error("user hasn't enough GDD or amount is < 0")
|
throw new LogError('User has not enough GDD', user.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const transactionLink = DbTransactionLink.create()
|
const transactionLink = DbTransactionLink.create()
|
||||||
@ -186,24 +191,15 @@ export class TransactionLinkResolver {
|
|||||||
.where('contributionLink.code = :code', { code: code.replace('CL-', '') })
|
.where('contributionLink.code = :code', { code: code.replace('CL-', '') })
|
||||||
.getOne()
|
.getOne()
|
||||||
if (!contributionLink) {
|
if (!contributionLink) {
|
||||||
logger.error('no contribution link found to given code:', code)
|
throw new LogError('No contribution link found to given code', code)
|
||||||
throw new Error(`No contribution link found to given code: ${code}`)
|
|
||||||
}
|
}
|
||||||
logger.info('...contribution link found with id', contributionLink.id)
|
logger.info('...contribution link found with id', contributionLink.id)
|
||||||
if (new Date(contributionLink.validFrom).getTime() > now.getTime()) {
|
if (new Date(contributionLink.validFrom).getTime() > now.getTime()) {
|
||||||
logger.error(
|
throw new LogError('Contribution link is not valid yet', contributionLink.validFrom)
|
||||||
'contribution link is not valid yet. Valid from: ',
|
|
||||||
contributionLink.validFrom,
|
|
||||||
)
|
|
||||||
throw new Error('Contribution link not valid yet')
|
|
||||||
}
|
}
|
||||||
if (contributionLink.validTo) {
|
if (contributionLink.validTo) {
|
||||||
if (new Date(contributionLink.validTo).setHours(23, 59, 59) < now.getTime()) {
|
if (new Date(contributionLink.validTo).setHours(23, 59, 59) < now.getTime()) {
|
||||||
logger.error(
|
throw new LogError('Contribution link is no longer valid', contributionLink.validTo)
|
||||||
'contribution link is no longer valid. Valid to: ',
|
|
||||||
contributionLink.validTo,
|
|
||||||
)
|
|
||||||
throw new Error('Contribution link is no longer valid')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let alreadyRedeemed: DbContribution | undefined
|
let alreadyRedeemed: DbContribution | undefined
|
||||||
@ -219,11 +215,7 @@ export class TransactionLinkResolver {
|
|||||||
})
|
})
|
||||||
.getOne()
|
.getOne()
|
||||||
if (alreadyRedeemed) {
|
if (alreadyRedeemed) {
|
||||||
logger.error(
|
throw new LogError('Contribution link already redeemed', user.id)
|
||||||
'contribution link with rule ONCE already redeemed by user with id',
|
|
||||||
user.id,
|
|
||||||
)
|
|
||||||
throw new Error('Contribution link already redeemed')
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -248,17 +240,12 @@ export class TransactionLinkResolver {
|
|||||||
)
|
)
|
||||||
.getOne()
|
.getOne()
|
||||||
if (alreadyRedeemed) {
|
if (alreadyRedeemed) {
|
||||||
logger.error(
|
throw new LogError('Contribution link already redeemed today', user.id)
|
||||||
'contribution link with rule DAILY already redeemed by user with id',
|
|
||||||
user.id,
|
|
||||||
)
|
|
||||||
throw new Error('Contribution link already redeemed today')
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
logger.error('contribution link has unknown cycle', contributionLink.cycle)
|
throw new LogError('Contribution link has unknown cycle', contributionLink.cycle)
|
||||||
throw new Error('Contribution link has unknown cycle')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,8 +295,7 @@ export class TransactionLinkResolver {
|
|||||||
logger.info('creation from contribution link commited successfuly.')
|
logger.info('creation from contribution link commited successfuly.')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await queryRunner.rollbackTransaction()
|
await queryRunner.rollbackTransaction()
|
||||||
logger.error(`Creation from contribution link was not successful: ${e}`)
|
throw new LogError('Creation from contribution link was not successful', e)
|
||||||
throw new Error(`Creation from contribution link was not successful. ${e}`)
|
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release()
|
await queryRunner.release()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
|
||||||
|
import Decimal from 'decimal.js-light'
|
||||||
import { EventProtocolType } from '@/event/EventProtocolType'
|
import { EventProtocolType } from '@/event/EventProtocolType'
|
||||||
import { userFactory } from '@/seeds/factory/user'
|
import { userFactory } from '@/seeds/factory/user'
|
||||||
import {
|
import {
|
||||||
@ -118,10 +119,8 @@ describe('send coins', () => {
|
|||||||
|
|
||||||
it('logs the error thrown', async () => {
|
it('logs the error thrown', async () => {
|
||||||
// find peter to check the log
|
// find peter to check the log
|
||||||
const user = await findUserByEmail(peterData.email)
|
const user = await findUserByEmail('stephen@hawking.uk')
|
||||||
expect(logger.error).toBeCalledWith(
|
expect(logger.error).toBeCalledWith('The recipient account was deleted', user)
|
||||||
`The recipient account was deleted: recipientUser=${user}`,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -151,10 +150,8 @@ describe('send coins', () => {
|
|||||||
|
|
||||||
it('logs the error thrown', async () => {
|
it('logs the error thrown', async () => {
|
||||||
// find peter to check the log
|
// find peter to check the log
|
||||||
const user = await findUserByEmail(peterData.email)
|
const user = await findUserByEmail('garrick@ollivander.com')
|
||||||
expect(logger.error).toBeCalledWith(
|
expect(logger.error).toBeCalledWith('The recipient account is not activated', user)
|
||||||
`The recipient account is not activated: recipientUser=${user}`,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -181,37 +178,13 @@ describe('send coins', () => {
|
|||||||
}),
|
}),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
errors: [new GraphQLError('Sender and Recipient are the same.')],
|
errors: [new GraphQLError('Sender and Recipient are the same')],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
it('logs the error thrown', () => {
|
||||||
expect(logger.error).toBeCalledWith('Sender and Recipient are the same.')
|
expect(logger.error).toBeCalledWith('Sender and Recipient are the same', expect.any(Number))
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('memo text is too long', () => {
|
|
||||||
it('throws an error', async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
expect(
|
|
||||||
await mutate({
|
|
||||||
mutation: sendCoins,
|
|
||||||
variables: {
|
|
||||||
email: 'peter@lustig.de',
|
|
||||||
amount: 100,
|
|
||||||
memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test t',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
errors: [new GraphQLError('memo text is too long (255 characters maximum)')],
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
|
||||||
expect(logger.error).toBeCalledWith('memo text is too long: memo.length=256 > 255')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -229,13 +202,37 @@ describe('send coins', () => {
|
|||||||
}),
|
}),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
errors: [new GraphQLError('memo text is too short (5 characters minimum)')],
|
errors: [new GraphQLError('Memo text is too short')],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
it('logs the error thrown', () => {
|
||||||
expect(logger.error).toBeCalledWith('memo text is too short: memo.length=4 < 5')
|
expect(logger.error).toBeCalledWith('Memo text is too short', 4)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('memo text is too long', () => {
|
||||||
|
it('throws an error', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
expect(
|
||||||
|
await mutate({
|
||||||
|
mutation: sendCoins,
|
||||||
|
variables: {
|
||||||
|
email: 'peter@lustig.de',
|
||||||
|
amount: 100,
|
||||||
|
memo: 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test t',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('Memo text is too long')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('Memo text is too long', 256)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -253,15 +250,13 @@ describe('send coins', () => {
|
|||||||
}),
|
}),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
errors: [new GraphQLError(`user hasn't enough GDD or amount is < 0`)],
|
errors: [new GraphQLError('User has not enough GDD or amount is < 0')],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
it('logs the error thrown', () => {
|
||||||
expect(logger.error).toBeCalledWith(
|
expect(logger.error).toBeCalledWith('User has not enough GDD or amount is < 0', null)
|
||||||
`user hasn't enough GDD or amount is < 0 : balance=null`,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -293,6 +288,7 @@ describe('send coins', () => {
|
|||||||
|
|
||||||
describe('trying to send negative amount', () => {
|
describe('trying to send negative amount', () => {
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
expect(
|
expect(
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: sendCoins,
|
mutation: sendCoins,
|
||||||
@ -304,13 +300,13 @@ describe('send coins', () => {
|
|||||||
}),
|
}),
|
||||||
).toEqual(
|
).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
errors: [new GraphQLError(`Amount to send must be positive`)],
|
errors: [new GraphQLError('Amount to send must be positive')],
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('logs the error thrown', () => {
|
it('logs the error thrown', () => {
|
||||||
expect(logger.error).toBeCalledWith(`Amount to send must be positive`)
|
expect(logger.error).toBeCalledWith('Amount to send must be positive', new Decimal(-50))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -334,7 +330,7 @@ describe('send coins', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the send transaction event in the database', async () => {
|
it('stores the TRANSACTION_SEND event in the database', async () => {
|
||||||
// Find the exact transaction (sent one is the one with user[1] as user)
|
// Find the exact transaction (sent one is the one with user[1] as user)
|
||||||
const transaction = await Transaction.find({
|
const transaction = await Transaction.find({
|
||||||
userId: user[1].id,
|
userId: user[1].id,
|
||||||
@ -351,7 +347,7 @@ describe('send coins', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the receive event in the database', async () => {
|
it('stores the TRANSACTION_RECEIVE event in the database', async () => {
|
||||||
// Find the exact transaction (received one is the one with user[0] as user)
|
// Find the exact transaction (received one is the one with user[0] as user)
|
||||||
const transaction = await Transaction.find({
|
const transaction = await Transaction.find({
|
||||||
userId: user[0].id,
|
userId: user[0].id,
|
||||||
|
|||||||
@ -29,14 +29,14 @@ import {
|
|||||||
sendTransactionLinkRedeemedEmail,
|
sendTransactionLinkRedeemedEmail,
|
||||||
sendTransactionReceivedEmail,
|
sendTransactionReceivedEmail,
|
||||||
} from '@/emails/sendEmailVariants'
|
} from '@/emails/sendEmailVariants'
|
||||||
import { Event, EventTransactionReceive, EventTransactionSend } from '@/event/Event'
|
import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Event'
|
||||||
import { writeEvent } from '@/event/EventProtocolEmitter'
|
|
||||||
|
|
||||||
import { BalanceResolver } from './BalanceResolver'
|
import { BalanceResolver } from './BalanceResolver'
|
||||||
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
|
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
|
||||||
import { findUserByEmail } from './UserResolver'
|
import { findUserByEmail } from './UserResolver'
|
||||||
|
|
||||||
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
|
||||||
|
import LogError from '@/server/LogError'
|
||||||
|
|
||||||
import { getLastTransaction } from './util/getLastTransaction'
|
import { getLastTransaction } from './util/getLastTransaction'
|
||||||
|
|
||||||
@ -55,18 +55,15 @@ export const executeTransaction = async (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (sender.id === recipient.id) {
|
if (sender.id === recipient.id) {
|
||||||
logger.error(`Sender and Recipient are the same.`)
|
throw new LogError('Sender and Recipient are the same', sender.id)
|
||||||
throw new Error('Sender and Recipient are the same.')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memo.length > MEMO_MAX_CHARS) {
|
|
||||||
logger.error(`memo text is too long: memo.length=${memo.length} > ${MEMO_MAX_CHARS}`)
|
|
||||||
throw new Error(`memo text is too long (${MEMO_MAX_CHARS} characters maximum)`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memo.length < MEMO_MIN_CHARS) {
|
if (memo.length < MEMO_MIN_CHARS) {
|
||||||
logger.error(`memo text is too short: memo.length=${memo.length} < ${MEMO_MIN_CHARS}`)
|
throw new LogError('Memo text is too short', memo.length)
|
||||||
throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`)
|
}
|
||||||
|
|
||||||
|
if (memo.length > MEMO_MAX_CHARS) {
|
||||||
|
throw new LogError('Memo text is too long', memo.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate amount
|
// validate amount
|
||||||
@ -79,8 +76,7 @@ export const executeTransaction = async (
|
|||||||
)
|
)
|
||||||
logger.debug(`calculated Balance=${sendBalance}`)
|
logger.debug(`calculated Balance=${sendBalance}`)
|
||||||
if (!sendBalance) {
|
if (!sendBalance) {
|
||||||
logger.error(`user hasn't enough GDD or amount is < 0 : balance=${sendBalance}`)
|
throw new LogError('User has not enough GDD or amount is < 0', sendBalance)
|
||||||
throw new Error("user hasn't enough GDD or amount is < 0")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryRunner = getConnection().createQueryRunner()
|
const queryRunner = getConnection().createQueryRunner()
|
||||||
@ -141,23 +137,22 @@ export const executeTransaction = async (
|
|||||||
await queryRunner.commitTransaction()
|
await queryRunner.commitTransaction()
|
||||||
logger.info(`commit Transaction successful...`)
|
logger.info(`commit Transaction successful...`)
|
||||||
|
|
||||||
const eventTransactionSend = new EventTransactionSend()
|
await EVENT_TRANSACTION_SEND(
|
||||||
eventTransactionSend.userId = transactionSend.userId
|
transactionSend.userId,
|
||||||
eventTransactionSend.xUserId = transactionSend.linkedUserId
|
transactionSend.linkedUserId,
|
||||||
eventTransactionSend.transactionId = transactionSend.id
|
transactionSend.id,
|
||||||
eventTransactionSend.amount = transactionSend.amount.mul(-1)
|
transactionSend.amount.mul(-1),
|
||||||
await writeEvent(new Event().setEventTransactionSend(eventTransactionSend))
|
)
|
||||||
|
|
||||||
const eventTransactionReceive = new EventTransactionReceive()
|
await EVENT_TRANSACTION_RECEIVE(
|
||||||
eventTransactionReceive.userId = transactionReceive.userId
|
transactionReceive.userId,
|
||||||
eventTransactionReceive.xUserId = transactionReceive.linkedUserId
|
transactionReceive.linkedUserId,
|
||||||
eventTransactionReceive.transactionId = transactionReceive.id
|
transactionReceive.id,
|
||||||
eventTransactionReceive.amount = transactionReceive.amount
|
transactionReceive.amount,
|
||||||
await writeEvent(new Event().setEventTransactionReceive(eventTransactionReceive))
|
)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await queryRunner.rollbackTransaction()
|
await queryRunner.rollbackTransaction()
|
||||||
logger.error(`Transaction was not successful: ${e}`)
|
throw new LogError('Transaction was not successful', e)
|
||||||
throw new Error(`Transaction was not successful: ${e}`)
|
|
||||||
} finally {
|
} finally {
|
||||||
await queryRunner.release()
|
await queryRunner.release()
|
||||||
}
|
}
|
||||||
@ -316,8 +311,7 @@ export class TransactionResolver {
|
|||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
logger.info(`sendCoins(email=${email}, amount=${amount}, memo=${memo})`)
|
logger.info(`sendCoins(email=${email}, amount=${amount}, memo=${memo})`)
|
||||||
if (amount.lte(0)) {
|
if (amount.lte(0)) {
|
||||||
logger.error(`Amount to send must be positive`)
|
throw new LogError('Amount to send must be positive', amount)
|
||||||
throw new Error('Amount to send must be positive')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this is subject to replay attacks
|
// TODO this is subject to replay attacks
|
||||||
@ -326,13 +320,11 @@ export class TransactionResolver {
|
|||||||
// validate recipient user
|
// validate recipient user
|
||||||
const recipientUser = await findUserByEmail(email)
|
const recipientUser = await findUserByEmail(email)
|
||||||
if (recipientUser.deletedAt) {
|
if (recipientUser.deletedAt) {
|
||||||
logger.error(`The recipient account was deleted: recipientUser=${recipientUser}`)
|
throw new LogError('The recipient account was deleted', recipientUser)
|
||||||
throw new Error('The recipient account was deleted')
|
|
||||||
}
|
}
|
||||||
const emailContact = recipientUser.emailContact
|
const emailContact = recipientUser.emailContact
|
||||||
if (!emailContact.emailChecked) {
|
if (!emailContact.emailChecked) {
|
||||||
logger.error(`The recipient account is not activated: recipientUser=${recipientUser}`)
|
throw new LogError('The recipient account is not activated', recipientUser)
|
||||||
throw new Error('The recipient account is not activated')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await executeTransaction(amount, memo, senderUser, recipientUser)
|
await executeTransaction(amount, memo, senderUser, recipientUser)
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import {
|
|||||||
setUserRole,
|
setUserRole,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
unDeleteUser,
|
unDeleteUser,
|
||||||
|
sendActivationEmail,
|
||||||
} from '@/seeds/graphql/mutations'
|
} from '@/seeds/graphql/mutations'
|
||||||
import { verifyLogin, queryOptIn, searchAdminUsers, searchUsers } from '@/seeds/graphql/queries'
|
import { verifyLogin, queryOptIn, searchAdminUsers, searchUsers } from '@/seeds/graphql/queries'
|
||||||
import { GraphQLError } from 'graphql'
|
import { GraphQLError } from 'graphql'
|
||||||
@ -175,6 +176,19 @@ describe('UserResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('stores the REGISTER event in the database', async () => {
|
||||||
|
const userConatct = await UserContact.findOneOrFail(
|
||||||
|
{ email: 'peter@lustig.de' },
|
||||||
|
{ relations: ['user'] },
|
||||||
|
)
|
||||||
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: EventProtocolType.REGISTER,
|
||||||
|
userId: userConatct.user.id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('account activation email', () => {
|
describe('account activation email', () => {
|
||||||
@ -196,7 +210,7 @@ describe('UserResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the send confirmation event in the database', () => {
|
it('stores the SEND_CONFIRMATION_EMAIL event in the database', () => {
|
||||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,
|
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,
|
||||||
@ -206,7 +220,7 @@ describe('UserResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('email already exists', () => {
|
describe('user already exists', () => {
|
||||||
let mutation: User
|
let mutation: User
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
mutation = await mutate({ mutation: createUser, variables })
|
mutation = await mutate({ mutation: createUser, variables })
|
||||||
@ -236,6 +250,19 @@ describe('UserResolver', () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('stores the SEND_ACCOUNT_MULTIREGISTRATION_EMAIL event in the database', async () => {
|
||||||
|
const userConatct = await UserContact.findOneOrFail(
|
||||||
|
{ email: 'peter@lustig.de' },
|
||||||
|
{ relations: ['user'] },
|
||||||
|
)
|
||||||
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL,
|
||||||
|
userId: userConatct.user.id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('unknown language', () => {
|
describe('unknown language', () => {
|
||||||
@ -328,7 +355,7 @@ describe('UserResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the account activated event in the database', () => {
|
it('stores the ACTIVATE_ACCOUNT event in the database', () => {
|
||||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.ACTIVATE_ACCOUNT,
|
type: EventProtocolType.ACTIVATE_ACCOUNT,
|
||||||
@ -337,7 +364,7 @@ describe('UserResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the redeem register event in the database', () => {
|
it('stores the REDEEM_REGISTER event in the database', () => {
|
||||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.REDEEM_REGISTER,
|
type: EventProtocolType.REDEEM_REGISTER,
|
||||||
@ -421,7 +448,7 @@ describe('UserResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the redeem register event in the database', async () => {
|
it('stores the REDEEM_REGISTER event in the database', async () => {
|
||||||
await expect(EventProtocol.find()).resolves.toContainEqual(
|
await expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.REDEEM_REGISTER,
|
type: EventProtocolType.REDEEM_REGISTER,
|
||||||
@ -647,6 +674,19 @@ describe('UserResolver', () => {
|
|||||||
it('sets the token in the header', () => {
|
it('sets the token in the header', () => {
|
||||||
expect(headerPushMock).toBeCalledWith({ key: 'token', value: expect.any(String) })
|
expect(headerPushMock).toBeCalledWith({ key: 'token', value: expect.any(String) })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('stores the LOGIN event in the database', async () => {
|
||||||
|
const userConatct = await UserContact.findOneOrFail(
|
||||||
|
{ email: 'bibi@bloxberg.de' },
|
||||||
|
{ relations: ['user'] },
|
||||||
|
)
|
||||||
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: EventProtocolType.LOGIN,
|
||||||
|
userId: userConatct.user.id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('user is in database and wrong password', () => {
|
describe('user is in database and wrong password', () => {
|
||||||
@ -887,7 +927,7 @@ describe('UserResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('stores the login event in the database', () => {
|
it('stores the LOGIN event in the database', () => {
|
||||||
expect(EventProtocol.find()).resolves.toContainEqual(
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
type: EventProtocolType.LOGIN,
|
type: EventProtocolType.LOGIN,
|
||||||
@ -1668,6 +1708,157 @@ describe('UserResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
describe('sendActivationEmail', () => {
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({ mutation: sendActivationEmail, variables: { email: 'bibi@bloxberg.de' } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authenticated', () => {
|
||||||
|
describe('without admin rights', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await userFactory(testEnv, bibiBloxberg)
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({ mutation: sendActivationEmail, variables: { email: 'bibi@bloxberg.de' } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('with admin rights', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
admin = await userFactory(testEnv, peterLustig)
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('user does not exist', () => {
|
||||||
|
it('throws an error', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await expect(
|
||||||
|
mutate({ mutation: sendActivationEmail, variables: { email: 'INVALID' } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('No user with this credentials')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith('No user with this credentials', 'invalid')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('user is deleted', () => {
|
||||||
|
it('throws an error', async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await userFactory(testEnv, stephenHawking)
|
||||||
|
await expect(
|
||||||
|
mutate({ mutation: sendActivationEmail, variables: { email: 'stephen@hawking.uk' } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('User with given email contact is deleted')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('logs the error thrown', () => {
|
||||||
|
expect(logger.error).toBeCalledWith(
|
||||||
|
'User with given email contact is deleted',
|
||||||
|
'stephen@hawking.uk',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sendActivationEmail with success', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
user = await userFactory(testEnv, bibiBloxberg)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns true', async () => {
|
||||||
|
const result = await mutate({
|
||||||
|
mutation: sendActivationEmail,
|
||||||
|
variables: { email: 'bibi@bloxberg.de' },
|
||||||
|
})
|
||||||
|
expect(result).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
sendActivationEmail: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sends an account activation email', async () => {
|
||||||
|
const userConatct = await UserContact.findOneOrFail(
|
||||||
|
{ email: 'bibi@bloxberg.de' },
|
||||||
|
{ relations: ['user'] },
|
||||||
|
)
|
||||||
|
const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace(
|
||||||
|
/{optin}/g,
|
||||||
|
userConatct.emailVerificationCode.toString(),
|
||||||
|
).replace(/{code}/g, '')
|
||||||
|
expect(sendAccountActivationEmail).toBeCalledWith({
|
||||||
|
firstName: 'Bibi',
|
||||||
|
lastName: 'Bloxberg',
|
||||||
|
email: 'bibi@bloxberg.de',
|
||||||
|
language: 'de',
|
||||||
|
activationLink,
|
||||||
|
timeDurationObject: expect.objectContaining({
|
||||||
|
hours: expect.any(Number),
|
||||||
|
minutes: expect.any(Number),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('stores the ADMIN_SEND_CONFIRMATION_EMAIL event in the database', async () => {
|
||||||
|
const userConatct = await UserContact.findOneOrFail(
|
||||||
|
{ email: 'bibi@bloxberg.de' },
|
||||||
|
{ relations: ['user'] },
|
||||||
|
)
|
||||||
|
expect(EventProtocol.find()).resolves.toContainEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
type: EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL,
|
||||||
|
userId: userConatct.user.id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('unDelete user', () => {
|
describe('unDelete user', () => {
|
||||||
describe('unauthenticated', () => {
|
describe('unauthenticated', () => {
|
||||||
it('returns an error', async () => {
|
it('returns an error', async () => {
|
||||||
|
|||||||
@ -48,15 +48,14 @@ import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddle
|
|||||||
import { klicktippSignIn } from '@/apis/KlicktippController'
|
import { klicktippSignIn } from '@/apis/KlicktippController'
|
||||||
import { RIGHTS } from '@/auth/RIGHTS'
|
import { RIGHTS } from '@/auth/RIGHTS'
|
||||||
import { hasElopageBuys } from '@/util/hasElopageBuys'
|
import { hasElopageBuys } from '@/util/hasElopageBuys'
|
||||||
import { writeEvent } from '@/event/EventProtocolEmitter'
|
|
||||||
import {
|
import {
|
||||||
Event,
|
Event,
|
||||||
EventLogin,
|
EVENT_LOGIN,
|
||||||
EventRedeemRegister,
|
EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL,
|
||||||
EventRegister,
|
EVENT_SEND_CONFIRMATION_EMAIL,
|
||||||
EventSendAccountMultiRegistrationEmail,
|
EVENT_REGISTER,
|
||||||
EventSendConfirmationEmail,
|
EVENT_ACTIVATE_ACCOUNT,
|
||||||
EventActivateAccount,
|
EVENT_ADMIN_SEND_CONFIRMATION_EMAIL,
|
||||||
} from '@/event/Event'
|
} from '@/event/Event'
|
||||||
import { getUserCreations } from './util/creations'
|
import { getUserCreations } from './util/creations'
|
||||||
import { isValidPassword } from '@/password/EncryptorUtils'
|
import { isValidPassword } from '@/password/EncryptorUtils'
|
||||||
@ -64,6 +63,7 @@ import { FULL_CREATION_AVAILABLE } from './const/const'
|
|||||||
import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
|
import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
|
||||||
import { PasswordEncryptionType } from '../enum/PasswordEncryptionType'
|
import { PasswordEncryptionType } from '../enum/PasswordEncryptionType'
|
||||||
import LogError from '@/server/LogError'
|
import LogError from '@/server/LogError'
|
||||||
|
import { EventProtocolType } from '@/event/EventProtocolType'
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const sodium = require('sodium-native')
|
const sodium = require('sodium-native')
|
||||||
@ -177,9 +177,8 @@ export class UserResolver {
|
|||||||
key: 'token',
|
key: 'token',
|
||||||
value: encode(dbUser.gradidoID),
|
value: encode(dbUser.gradidoID),
|
||||||
})
|
})
|
||||||
const ev = new EventLogin()
|
|
||||||
ev.userId = user.id
|
await EVENT_LOGIN(user.id)
|
||||||
writeEvent(new Event().setEventLogin(ev))
|
|
||||||
logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`)
|
logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`)
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
@ -211,7 +210,6 @@ export class UserResolver {
|
|||||||
)
|
)
|
||||||
// TODO: wrong default value (should be null), how does graphql work here? Is it an required field?
|
// TODO: wrong default value (should be null), how does graphql work here? Is it an required field?
|
||||||
// default int publisher_id = 0;
|
// default int publisher_id = 0;
|
||||||
const event = new Event()
|
|
||||||
|
|
||||||
// Validate Language (no throw)
|
// Validate Language (no throw)
|
||||||
if (!language || !isLanguage(language)) {
|
if (!language || !isLanguage(language)) {
|
||||||
@ -249,9 +247,9 @@ export class UserResolver {
|
|||||||
email,
|
email,
|
||||||
language: foundUser.language, // use language of the emails owner for sending
|
language: foundUser.language, // use language of the emails owner for sending
|
||||||
})
|
})
|
||||||
const eventSendAccountMultiRegistrationEmail = new EventSendAccountMultiRegistrationEmail()
|
|
||||||
eventSendAccountMultiRegistrationEmail.userId = foundUser.id
|
await EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL(foundUser.id)
|
||||||
writeEvent(event.setEventSendConfirmationEmail(eventSendAccountMultiRegistrationEmail))
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`sendAccountMultiRegistrationEmail by ${firstName} ${lastName} to ${foundUser.firstName} ${foundUser.lastName} <${email}>`,
|
`sendAccountMultiRegistrationEmail by ${firstName} ${lastName} to ${foundUser.firstName} ${foundUser.lastName} <${email}>`,
|
||||||
)
|
)
|
||||||
@ -268,10 +266,7 @@ export class UserResolver {
|
|||||||
|
|
||||||
const gradidoID = await newGradidoID()
|
const gradidoID = await newGradidoID()
|
||||||
|
|
||||||
const eventRegister = new EventRegister()
|
const eventRegisterRedeem = Event(EventProtocolType.REDEEM_REGISTER, 0)
|
||||||
const eventRedeemRegister = new EventRedeemRegister()
|
|
||||||
const eventSendConfirmEmail = new EventSendConfirmationEmail()
|
|
||||||
|
|
||||||
let dbUser = new DbUser()
|
let dbUser = new DbUser()
|
||||||
dbUser.gradidoID = gradidoID
|
dbUser.gradidoID = gradidoID
|
||||||
dbUser.firstName = firstName
|
dbUser.firstName = firstName
|
||||||
@ -288,14 +283,14 @@ export class UserResolver {
|
|||||||
logger.info('redeemCode found contributionLink=' + contributionLink)
|
logger.info('redeemCode found contributionLink=' + contributionLink)
|
||||||
if (contributionLink) {
|
if (contributionLink) {
|
||||||
dbUser.contributionLinkId = contributionLink.id
|
dbUser.contributionLinkId = contributionLink.id
|
||||||
eventRedeemRegister.contributionId = contributionLink.id
|
eventRegisterRedeem.contributionId = contributionLink.id
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const transactionLink = await DbTransactionLink.findOne({ code: redeemCode })
|
const transactionLink = await DbTransactionLink.findOne({ code: redeemCode })
|
||||||
logger.info('redeemCode found transactionLink=' + transactionLink)
|
logger.info('redeemCode found transactionLink=' + transactionLink)
|
||||||
if (transactionLink) {
|
if (transactionLink) {
|
||||||
dbUser.referrerId = transactionLink.userId
|
dbUser.referrerId = transactionLink.userId
|
||||||
eventRedeemRegister.transactionId = transactionLink.id
|
eventRegisterRedeem.transactionId = transactionLink.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,8 +328,8 @@ export class UserResolver {
|
|||||||
timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME),
|
timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME),
|
||||||
})
|
})
|
||||||
logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`)
|
logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`)
|
||||||
eventSendConfirmEmail.userId = dbUser.id
|
|
||||||
writeEvent(event.setEventSendConfirmationEmail(eventSendConfirmEmail))
|
await EVENT_SEND_CONFIRMATION_EMAIL(dbUser.id)
|
||||||
|
|
||||||
if (!emailSent) {
|
if (!emailSent) {
|
||||||
logger.debug(`Account confirmation link: ${activationLink}`)
|
logger.debug(`Account confirmation link: ${activationLink}`)
|
||||||
@ -351,11 +346,10 @@ export class UserResolver {
|
|||||||
logger.info('createUser() successful...')
|
logger.info('createUser() successful...')
|
||||||
|
|
||||||
if (redeemCode) {
|
if (redeemCode) {
|
||||||
eventRedeemRegister.userId = dbUser.id
|
eventRegisterRedeem.userId = dbUser.id
|
||||||
await writeEvent(event.setEventRedeemRegister(eventRedeemRegister))
|
await eventRegisterRedeem.save()
|
||||||
} else {
|
} else {
|
||||||
eventRegister.userId = dbUser.id
|
await EVENT_REGISTER(dbUser.id)
|
||||||
await writeEvent(event.setEventRegister(eventRegister))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new User(dbUser)
|
return new User(dbUser)
|
||||||
@ -458,8 +452,6 @@ export class UserResolver {
|
|||||||
await queryRunner.connect()
|
await queryRunner.connect()
|
||||||
await queryRunner.startTransaction('REPEATABLE READ')
|
await queryRunner.startTransaction('REPEATABLE READ')
|
||||||
|
|
||||||
const event = new Event()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Save user
|
// Save user
|
||||||
await queryRunner.manager.save(user).catch((error) => {
|
await queryRunner.manager.save(user).catch((error) => {
|
||||||
@ -473,9 +465,7 @@ export class UserResolver {
|
|||||||
await queryRunner.commitTransaction()
|
await queryRunner.commitTransaction()
|
||||||
logger.info('User and UserContact data written successfully...')
|
logger.info('User and UserContact data written successfully...')
|
||||||
|
|
||||||
const eventActivateAccount = new EventActivateAccount()
|
await EVENT_ACTIVATE_ACCOUNT(user.id)
|
||||||
eventActivateAccount.userId = user.id
|
|
||||||
writeEvent(event.setEventActivateAccount(eventActivateAccount))
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await queryRunner.rollbackTransaction()
|
await queryRunner.rollbackTransaction()
|
||||||
throw new LogError('Error on writing User and User Contact data', e)
|
throw new LogError('Error on writing User and User Contact data', e)
|
||||||
@ -791,19 +781,12 @@ export class UserResolver {
|
|||||||
email = email.trim().toLowerCase()
|
email = email.trim().toLowerCase()
|
||||||
// const user = await dbUser.findOne({ id: emailContact.userId })
|
// const user = await dbUser.findOne({ id: emailContact.userId })
|
||||||
const user = await findUserByEmail(email)
|
const user = await findUserByEmail(email)
|
||||||
if (!user) {
|
if (user.deletedAt || user.emailContact.deletedAt) {
|
||||||
throw new LogError('Could not find user to given email contact', email)
|
|
||||||
}
|
|
||||||
if (user.deletedAt) {
|
|
||||||
throw new LogError('User with given email contact is deleted', email)
|
throw new LogError('User with given email contact is deleted', email)
|
||||||
}
|
}
|
||||||
const emailContact = user.emailContact
|
|
||||||
if (emailContact.deletedAt) {
|
|
||||||
throw new LogError('The given email contact for this user is deleted', email)
|
|
||||||
}
|
|
||||||
|
|
||||||
emailContact.emailResendCount++
|
user.emailContact.emailResendCount++
|
||||||
await emailContact.save()
|
await user.emailContact.save()
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const emailSent = await sendAccountActivationEmail({
|
const emailSent = await sendAccountActivationEmail({
|
||||||
@ -811,7 +794,7 @@ export class UserResolver {
|
|||||||
lastName: user.lastName,
|
lastName: user.lastName,
|
||||||
email,
|
email,
|
||||||
language: user.language,
|
language: user.language,
|
||||||
activationLink: activationLink(emailContact.emailVerificationCode),
|
activationLink: activationLink(user.emailContact.emailVerificationCode),
|
||||||
timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME),
|
timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -819,10 +802,7 @@ export class UserResolver {
|
|||||||
if (!emailSent) {
|
if (!emailSent) {
|
||||||
logger.info(`Account confirmation link: ${activationLink}`)
|
logger.info(`Account confirmation link: ${activationLink}`)
|
||||||
} else {
|
} else {
|
||||||
const event = new Event()
|
await EVENT_ADMIN_SEND_CONFIRMATION_EMAIL(user.id)
|
||||||
const eventSendConfirmationEmail = new EventSendConfirmationEmail()
|
|
||||||
eventSendConfirmationEmail.userId = user.id
|
|
||||||
await writeEvent(event.setEventSendConfirmationEmail(eventSendConfirmationEmail))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -68,6 +68,12 @@ export const createUser = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const sendActivationEmail = gql`
|
||||||
|
mutation ($email: String!) {
|
||||||
|
sendActivationEmail(email: $email)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
export const sendCoins = gql`
|
export const sendCoins = gql`
|
||||||
mutation ($email: String!, $amount: Decimal!, $memo: String!) {
|
mutation ($email: String!, $amount: Decimal!, $memo: String!) {
|
||||||
sendCoins(email: $email, amount: $amount, memo: $memo)
|
sendCoins(email: $email, amount: $amount, memo: $memo)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user