Merge pull request #2691 from gradido/event_protocol_rework

refactor(backend): event protocol rework
This commit is contained in:
Ulf Gebhardt 2023-02-14 17:11:34 +01:00 committed by GitHub
commit db236b1d34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 516 additions and 692 deletions

View File

@ -545,7 +545,7 @@ jobs:
report_name: Coverage Backend
type: lcov
result_path: ./backend/coverage/lcov.info
min_coverage: 78
min_coverage: 80
token: ${{ github.token }}
##########################################################################

View File

@ -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'
export class EventBasic {
type: string
createdAt: Date
}
export class EventBasicUserId extends EventBasic {
userId: number
export const Event = (
type: EventProtocolType,
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 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,
transactionId: number,
amount: decimal,
xUserId: number,
xCommunityId: number,
): Event {
this.setByBasicTx(userId, transactionId, amount)
this.xUserId = xUserId
this.xCommunityId = xCommunityId
return this
}
setByBasicCt(userId: number, contributionId: number, amount: decimal): Event {
this.setByBasicUser(userId)
this.contributionId = contributionId
this.amount = amount
return this
}
setByBasicCtMsg(
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,
xCommunityId: number,
): Event {
this.setByBasicCt(userId, contributionId, amount)
this.xUserId = xUserId
this.xCommunityId = xCommunityId
return this
}
setByBasicRedeem(userId: number, transactionId?: number, contributionId?: number): Event {
this.setByBasicUser(userId)
if (transactionId) this.transactionId = transactionId
if (contributionId) this.contributionId = contributionId
return this
}
id: number
type: string
createdAt: Date
userId: number
xUserId?: number
xCommunityId?: number
transactionId?: number
contributionId?: number
amount?: decimal
messageId?: number
}
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,
amount: Decimal,
): Promise<DbEvent> =>
Event(
EventProtocolType.TRANSACTION_SEND,
userId,
xUserId,
null,
transactionId,
null,
amount,
).save()
export const EVENT_TRANSACTION_RECEIVE = async (
userId: number,
xUserId: number,
transactionId: number,
amount: Decimal,
): Promise<DbEvent> =>
Event(
EventProtocolType.TRANSACTION_RECEIVE,
userId,
xUserId,
null,
transactionId,
null,
amount,
).save()
export const EVENT_LOGIN = async (userId: number): Promise<DbEvent> =>
Event(EventProtocolType.LOGIN, userId, null, null, null, null, null, null).save()
export const EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = async (
userId: number,
): Promise<DbEvent> => Event(EventProtocolType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, userId).save()
export const EVENT_SEND_CONFIRMATION_EMAIL = async (userId: number): Promise<DbEvent> =>
Event(EventProtocolType.SEND_CONFIRMATION_EMAIL, userId).save()
export const EVENT_ADMIN_SEND_CONFIRMATION_EMAIL = async (userId: number): Promise<DbEvent> =>
Event(EventProtocolType.ADMIN_SEND_CONFIRMATION_EMAIL, userId).save()
/* export const EVENT_REDEEM_REGISTER = async (
userId: number,
transactionId: number | null = null,
contributionId: number | null = null,
): Promise<Event> =>
Event(
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()

View File

@ -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()
}

View File

@ -1,50 +1,50 @@
export enum EventProtocolType {
BASIC = 'BASIC',
VISIT_GRADIDO = 'VISIT_GRADIDO',
// VISIT_GRADIDO = 'VISIT_GRADIDO',
REGISTER = 'REGISTER',
REDEEM_REGISTER = 'REDEEM_REGISTER',
VERIFY_REDEEM = 'VERIFY_REDEEM',
INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
// VERIFY_REDEEM = 'VERIFY_REDEEM',
// INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
SEND_CONFIRMATION_EMAIL = 'SEND_CONFIRMATION_EMAIL',
ADMIN_SEND_CONFIRMATION_EMAIL = 'ADMIN_SEND_CONFIRMATION_EMAIL',
SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = 'SEND_ACCOUNT_MULTIREGISTRATION_EMAIL',
CONFIRM_EMAIL = 'CONFIRM_EMAIL',
REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
// CONFIRM_EMAIL = 'CONFIRM_EMAIL',
// REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
LOGIN = 'LOGIN',
LOGOUT = 'LOGOUT',
REDEEM_LOGIN = 'REDEEM_LOGIN',
// LOGOUT = 'LOGOUT',
// REDEEM_LOGIN = 'REDEEM_LOGIN',
ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL',
PASSWORD_CHANGE = 'PASSWORD_CHANGE',
SEND_TRANSACTION_SEND_EMAIL = 'SEND_TRANSACTION_SEND_EMAIL',
SEND_TRANSACTION_RECEIVE_EMAIL = 'SEND_TRANSACTION_RECEIVE_EMAIL',
// SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL',
// PASSWORD_CHANGE = 'PASSWORD_CHANGE',
// SEND_TRANSACTION_SEND_EMAIL = 'SEND_TRANSACTION_SEND_EMAIL',
// SEND_TRANSACTION_RECEIVE_EMAIL = 'SEND_TRANSACTION_RECEIVE_EMAIL',
TRANSACTION_SEND = 'TRANSACTION_SEND',
TRANSACTION_SEND_REDEEM = 'TRANSACTION_SEND_REDEEM',
TRANSACTION_REPEATE_REDEEM = 'TRANSACTION_REPEATE_REDEEM',
TRANSACTION_CREATION = 'TRANSACTION_CREATION',
// TRANSACTION_SEND_REDEEM = 'TRANSACTION_SEND_REDEEM',
// TRANSACTION_REPEATE_REDEEM = 'TRANSACTION_REPEATE_REDEEM',
// TRANSACTION_CREATION = 'TRANSACTION_CREATION',
TRANSACTION_RECEIVE = 'TRANSACTION_RECEIVE',
TRANSACTION_RECEIVE_REDEEM = 'TRANSACTION_RECEIVE_REDEEM',
SEND_TRANSACTION_LINK_REDEEM_EMAIL = 'SEND_TRANSACTION_LINK_REDEEM_EMAIL',
SEND_ADDED_CONTRIBUTION_EMAIL = 'SEND_ADDED_CONTRIBUTION_EMAIL',
SEND_CONTRIBUTION_CONFIRM_EMAIL = 'SEND_CONTRIBUTION_CONFIRM_EMAIL',
// TRANSACTION_RECEIVE_REDEEM = 'TRANSACTION_RECEIVE_REDEEM',
// SEND_TRANSACTION_LINK_REDEEM_EMAIL = 'SEND_TRANSACTION_LINK_REDEEM_EMAIL',
// SEND_ADDED_CONTRIBUTION_EMAIL = 'SEND_ADDED_CONTRIBUTION_EMAIL',
// SEND_CONTRIBUTION_CONFIRM_EMAIL = 'SEND_CONTRIBUTION_CONFIRM_EMAIL',
CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE',
CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM',
CONTRIBUTION_DENY = 'CONTRIBUTION_DENY',
CONTRIBUTION_LINK_DEFINE = 'CONTRIBUTION_LINK_DEFINE',
CONTRIBUTION_LINK_ACTIVATE_REDEEM = 'CONTRIBUTION_LINK_ACTIVATE_REDEEM',
// CONTRIBUTION_DENY = 'CONTRIBUTION_DENY',
// CONTRIBUTION_LINK_DEFINE = 'CONTRIBUTION_LINK_DEFINE',
// CONTRIBUTION_LINK_ACTIVATE_REDEEM = 'CONTRIBUTION_LINK_ACTIVATE_REDEEM',
CONTRIBUTION_DELETE = 'CONTRIBUTION_DELETE',
CONTRIBUTION_UPDATE = 'CONTRIBUTION_UPDATE',
ADMIN_CONTRIBUTION_CREATE = 'ADMIN_CONTRIBUTION_CREATE',
ADMIN_CONTRIBUTION_DELETE = 'ADMIN_CONTRIBUTION_DELETE',
ADMIN_CONTRIBUTION_DENY = 'ADMIN_CONTRIBUTION_DENY',
ADMIN_CONTRIBUTION_UPDATE = 'ADMIN_CONTRIBUTION_UPDATE',
USER_CREATE_CONTRIBUTION_MESSAGE = 'USER_CREATE_CONTRIBUTION_MESSAGE',
ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
DELETE_USER = 'DELETE_USER',
UNDELETE_USER = 'UNDELETE_USER',
CHANGE_USER_ROLE = 'CHANGE_USER_ROLE',
ADMIN_UPDATE_CONTRIBUTION = 'ADMIN_UPDATE_CONTRIBUTION',
ADMIN_DELETE_CONTRIBUTION = 'ADMIN_DELETE_CONTRIBUTION',
CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
// USER_CREATE_CONTRIBUTION_MESSAGE = 'USER_CREATE_CONTRIBUTION_MESSAGE',
// ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
// DELETE_USER = 'DELETE_USER',
// UNDELETE_USER = 'UNDELETE_USER',
// CHANGE_USER_ROLE = 'CHANGE_USER_ROLE',
// ADMIN_UPDATE_CONTRIBUTION = 'ADMIN_UPDATE_CONTRIBUTION',
// ADMIN_DELETE_CONTRIBUTION = 'ADMIN_DELETE_CONTRIBUTION',
// CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
// DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
// UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
}

View File

@ -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(
expect.objectContaining({
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({
query: login,
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
@ -1263,7 +1263,7 @@ describe('ContributionResolver', () => {
).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({
mutation: createContribution,
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(
expect.objectContaining({
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(
expect.objectContaining({
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(
expect.objectContaining({
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(
expect.objectContaining({
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(
expect.objectContaining({
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(
expect.objectContaining({
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,

View File

@ -37,17 +37,15 @@ import {
} from './util/creations'
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS, FULL_CREATION_AVAILABLE } from './const/const'
import {
Event,
EventContributionCreate,
EventContributionDelete,
EventContributionUpdate,
EventContributionConfirm,
EventAdminContributionCreate,
EventAdminContributionDelete,
EventAdminContributionDeny,
EventAdminContributionUpdate,
EVENT_CONTRIBUTION_CREATE,
EVENT_CONTRIBUTION_DELETE,
EVENT_CONTRIBUTION_UPDATE,
EVENT_ADMIN_CONTRIBUTION_CREATE,
EVENT_ADMIN_CONTRIBUTION_UPDATE,
EVENT_ADMIN_CONTRIBUTION_DELETE,
EVENT_CONTRIBUTION_CONFIRM,
EVENT_ADMIN_CONTRIBUTION_DENY,
} from '@/event/Event'
import { writeEvent } from '@/event/EventProtocolEmitter'
import { calculateDecay } from '@/util/decay'
import {
sendContributionConfirmedEmail,
@ -75,8 +73,6 @@ export class ContributionResolver {
throw new LogError('Memo text is too long', memo.length)
}
const event = new Event()
const user = getUser(context)
const creations = await getUserCreation(user.id, clientTimezoneOffset)
logger.trace('creations', creations)
@ -95,11 +91,7 @@ export class ContributionResolver {
logger.trace('contribution to save', contribution)
await DbContribution.save(contribution)
const eventCreateContribution = new EventContributionCreate()
eventCreateContribution.userId = user.id
eventCreateContribution.amount = amount
eventCreateContribution.contributionId = contribution.id
await writeEvent(event.setEventContributionCreate(eventCreateContribution))
await EVENT_CONTRIBUTION_CREATE(user.id, contribution.id, amount)
return new UnconfirmedContribution(contribution, user, creations)
}
@ -110,7 +102,6 @@ export class ContributionResolver {
@Arg('id', () => Int) id: number,
@Ctx() context: Context,
): Promise<boolean> {
const event = new Event()
const user = getUser(context)
const contribution = await DbContribution.findOne(id)
if (!contribution) {
@ -128,11 +119,7 @@ export class ContributionResolver {
contribution.deletedAt = new Date()
await contribution.save()
const eventDeleteContribution = new EventContributionDelete()
eventDeleteContribution.userId = user.id
eventDeleteContribution.contributionId = contribution.id
eventDeleteContribution.amount = contribution.amount
await writeEvent(event.setEventContributionDelete(eventDeleteContribution))
await EVENT_CONTRIBUTION_DELETE(user.id, contribution.id, contribution.amount)
const res = await contribution.softRemove()
return !!res
@ -279,13 +266,7 @@ export class ContributionResolver {
contributionToUpdate.updatedAt = new Date()
DbContribution.save(contributionToUpdate)
const event = new Event()
const eventUpdateContribution = new EventContributionUpdate()
eventUpdateContribution.userId = user.id
eventUpdateContribution.contributionId = contributionId
eventUpdateContribution.amount = amount
await writeEvent(event.setEventContributionUpdate(eventUpdateContribution))
await EVENT_CONTRIBUTION_UPDATE(user.id, contributionId, amount)
return new UnconfirmedContribution(contributionToUpdate, user, creations)
}
@ -321,7 +302,6 @@ export class ContributionResolver {
)
}
const event = new Event()
const moderator = getUser(context)
logger.trace('moderator: ', moderator.id)
const creations = await getUserCreation(emailContact.userId, clientTimezoneOffset)
@ -343,11 +323,7 @@ export class ContributionResolver {
await DbContribution.save(contribution)
const eventAdminCreateContribution = new EventAdminContributionCreate()
eventAdminCreateContribution.userId = moderator.id
eventAdminCreateContribution.amount = amount
eventAdminCreateContribution.contributionId = contribution.id
await writeEvent(event.setEventAdminContributionCreate(eventAdminCreateContribution))
await EVENT_ADMIN_CONTRIBUTION_CREATE(moderator.id, contribution.id, amount)
return getUserCreation(emailContact.userId, clientTimezoneOffset)
}
@ -442,12 +418,7 @@ export class ContributionResolver {
result.creation = await getUserCreation(emailContact.user.id, clientTimezoneOffset)
const event = new Event()
const eventAdminContributionUpdate = new EventAdminContributionUpdate()
eventAdminContributionUpdate.userId = emailContact.user.id
eventAdminContributionUpdate.amount = amount
eventAdminContributionUpdate.contributionId = contributionToUpdate.id
await writeEvent(event.setEventAdminContributionUpdate(eventAdminContributionUpdate))
await EVENT_ADMIN_CONTRIBUTION_UPDATE(emailContact.user.id, contributionToUpdate.id, amount)
return result
}
@ -518,12 +489,8 @@ export class ContributionResolver {
await contribution.save()
const res = await contribution.softRemove()
const event = new Event()
const eventAdminContributionDelete = new EventAdminContributionDelete()
eventAdminContributionDelete.userId = contribution.userId
eventAdminContributionDelete.amount = contribution.amount
eventAdminContributionDelete.contributionId = contribution.id
await writeEvent(event.setEventAdminContributionDelete(eventAdminContributionDelete))
await EVENT_ADMIN_CONTRIBUTION_DELETE(contribution.userId, contribution.id, contribution.amount)
sendContributionDeletedEmail({
firstName: user.firstName,
lastName: user.lastName,
@ -635,12 +602,7 @@ export class ContributionResolver {
await queryRunner.release()
}
const event = new Event()
const eventContributionConfirm = new EventContributionConfirm()
eventContributionConfirm.userId = user.id
eventContributionConfirm.amount = contribution.amount
eventContributionConfirm.contributionId = contribution.id
await writeEvent(event.setEventContributionConfirm(eventContributionConfirm))
await EVENT_CONTRIBUTION_CONFIRM(user.id, contribution.id, contribution.amount)
} finally {
releaseLock()
}
@ -730,12 +692,12 @@ export class ContributionResolver {
contributionToUpdate.deniedAt = new Date()
const res = await contributionToUpdate.save()
const event = new Event()
const eventAdminContributionDeny = new EventAdminContributionDeny()
eventAdminContributionDeny.userId = contributionToUpdate.userId
eventAdminContributionDeny.amount = contributionToUpdate.amount
eventAdminContributionDeny.contributionId = contributionToUpdate.id
await writeEvent(event.setEventAdminContributionDeny(eventAdminContributionDeny))
await EVENT_ADMIN_CONTRIBUTION_DENY(
contributionToUpdate.userId,
moderator.id,
contributionToUpdate.id,
contributionToUpdate.amount,
)
sendContributionDeniedEmail({
firstName: user.firstName,

View File

@ -334,7 +334,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)
const transaction = await Transaction.find({
userId: user[1].id,
@ -351,7 +351,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)
const transaction = await Transaction.find({
userId: user[0].id,

View File

@ -29,8 +29,7 @@ import {
sendTransactionLinkRedeemedEmail,
sendTransactionReceivedEmail,
} from '@/emails/sendEmailVariants'
import { Event, EventTransactionReceive, EventTransactionSend } from '@/event/Event'
import { writeEvent } from '@/event/EventProtocolEmitter'
import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Event'
import { BalanceResolver } from './BalanceResolver'
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
@ -141,19 +140,19 @@ export const executeTransaction = async (
await queryRunner.commitTransaction()
logger.info(`commit Transaction successful...`)
const eventTransactionSend = new EventTransactionSend()
eventTransactionSend.userId = transactionSend.userId
eventTransactionSend.xUserId = transactionSend.linkedUserId
eventTransactionSend.transactionId = transactionSend.id
eventTransactionSend.amount = transactionSend.amount.mul(-1)
await writeEvent(new Event().setEventTransactionSend(eventTransactionSend))
await EVENT_TRANSACTION_SEND(
transactionSend.userId,
transactionSend.linkedUserId,
transactionSend.id,
transactionSend.amount.mul(-1),
)
const eventTransactionReceive = new EventTransactionReceive()
eventTransactionReceive.userId = transactionReceive.userId
eventTransactionReceive.xUserId = transactionReceive.linkedUserId
eventTransactionReceive.transactionId = transactionReceive.id
eventTransactionReceive.amount = transactionReceive.amount
await writeEvent(new Event().setEventTransactionReceive(eventTransactionReceive))
await EVENT_TRANSACTION_RECEIVE(
transactionReceive.userId,
transactionReceive.linkedUserId,
transactionReceive.id,
transactionReceive.amount,
)
} catch (e) {
await queryRunner.rollbackTransaction()
logger.error(`Transaction was not successful: ${e}`)

View File

@ -19,6 +19,7 @@ import {
setUserRole,
deleteUser,
unDeleteUser,
sendActivationEmail,
} from '@/seeds/graphql/mutations'
import { verifyLogin, queryOptIn, searchAdminUsers, searchUsers } from '@/seeds/graphql/queries'
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', () => {
@ -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.objectContaining({
type: EventProtocolType.SEND_CONFIRMATION_EMAIL,
@ -206,7 +220,7 @@ describe('UserResolver', () => {
})
})
describe('email already exists', () => {
describe('user already exists', () => {
let mutation: User
beforeAll(async () => {
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', () => {
@ -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.objectContaining({
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.objectContaining({
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(
expect.objectContaining({
type: EventProtocolType.REDEEM_REGISTER,
@ -647,6 +674,19 @@ describe('UserResolver', () => {
it('sets the token in the header', () => {
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', () => {
@ -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.objectContaining({
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('unauthenticated', () => {
it('returns an error', async () => {

View File

@ -48,15 +48,14 @@ import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddle
import { klicktippSignIn } from '@/apis/KlicktippController'
import { RIGHTS } from '@/auth/RIGHTS'
import { hasElopageBuys } from '@/util/hasElopageBuys'
import { writeEvent } from '@/event/EventProtocolEmitter'
import {
Event,
EventLogin,
EventRedeemRegister,
EventRegister,
EventSendAccountMultiRegistrationEmail,
EventSendConfirmationEmail,
EventActivateAccount,
EVENT_LOGIN,
EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL,
EVENT_SEND_CONFIRMATION_EMAIL,
EVENT_REGISTER,
EVENT_ACTIVATE_ACCOUNT,
EVENT_ADMIN_SEND_CONFIRMATION_EMAIL,
} from '@/event/Event'
import { getUserCreations } from './util/creations'
import { isValidPassword } from '@/password/EncryptorUtils'
@ -64,6 +63,7 @@ import { FULL_CREATION_AVAILABLE } from './const/const'
import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
import { PasswordEncryptionType } from '../enum/PasswordEncryptionType'
import LogError from '@/server/LogError'
import { EventProtocolType } from '@/event/EventProtocolType'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sodium = require('sodium-native')
@ -177,9 +177,8 @@ export class UserResolver {
key: 'token',
value: encode(dbUser.gradidoID),
})
const ev = new EventLogin()
ev.userId = user.id
writeEvent(new Event().setEventLogin(ev))
await EVENT_LOGIN(user.id)
logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`)
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?
// default int publisher_id = 0;
const event = new Event()
// Validate Language (no throw)
if (!language || !isLanguage(language)) {
@ -249,9 +247,9 @@ export class UserResolver {
email,
language: foundUser.language, // use language of the emails owner for sending
})
const eventSendAccountMultiRegistrationEmail = new EventSendAccountMultiRegistrationEmail()
eventSendAccountMultiRegistrationEmail.userId = foundUser.id
writeEvent(event.setEventSendConfirmationEmail(eventSendAccountMultiRegistrationEmail))
await EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL(foundUser.id)
logger.info(
`sendAccountMultiRegistrationEmail by ${firstName} ${lastName} to ${foundUser.firstName} ${foundUser.lastName} <${email}>`,
)
@ -268,10 +266,7 @@ export class UserResolver {
const gradidoID = await newGradidoID()
const eventRegister = new EventRegister()
const eventRedeemRegister = new EventRedeemRegister()
const eventSendConfirmEmail = new EventSendConfirmationEmail()
const eventRegisterRedeem = Event(EventProtocolType.REDEEM_REGISTER, 0)
let dbUser = new DbUser()
dbUser.gradidoID = gradidoID
dbUser.firstName = firstName
@ -288,14 +283,14 @@ export class UserResolver {
logger.info('redeemCode found contributionLink=' + contributionLink)
if (contributionLink) {
dbUser.contributionLinkId = contributionLink.id
eventRedeemRegister.contributionId = contributionLink.id
eventRegisterRedeem.contributionId = contributionLink.id
}
} else {
const transactionLink = await DbTransactionLink.findOne({ code: redeemCode })
logger.info('redeemCode found transactionLink=' + transactionLink)
if (transactionLink) {
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),
})
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) {
logger.debug(`Account confirmation link: ${activationLink}`)
@ -351,11 +346,10 @@ export class UserResolver {
logger.info('createUser() successful...')
if (redeemCode) {
eventRedeemRegister.userId = dbUser.id
await writeEvent(event.setEventRedeemRegister(eventRedeemRegister))
eventRegisterRedeem.userId = dbUser.id
await eventRegisterRedeem.save()
} else {
eventRegister.userId = dbUser.id
await writeEvent(event.setEventRegister(eventRegister))
await EVENT_REGISTER(dbUser.id)
}
return new User(dbUser)
@ -458,8 +452,6 @@ export class UserResolver {
await queryRunner.connect()
await queryRunner.startTransaction('REPEATABLE READ')
const event = new Event()
try {
// Save user
await queryRunner.manager.save(user).catch((error) => {
@ -473,9 +465,7 @@ export class UserResolver {
await queryRunner.commitTransaction()
logger.info('User and UserContact data written successfully...')
const eventActivateAccount = new EventActivateAccount()
eventActivateAccount.userId = user.id
writeEvent(event.setEventActivateAccount(eventActivateAccount))
await EVENT_ACTIVATE_ACCOUNT(user.id)
} catch (e) {
await queryRunner.rollbackTransaction()
throw new LogError('Error on writing User and User Contact data', e)
@ -791,19 +781,12 @@ export class UserResolver {
email = email.trim().toLowerCase()
// const user = await dbUser.findOne({ id: emailContact.userId })
const user = await findUserByEmail(email)
if (!user) {
throw new LogError('Could not find user to given email contact', email)
}
if (user.deletedAt) {
if (user.deletedAt || user.emailContact.deletedAt) {
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++
await emailContact.save()
user.emailContact.emailResendCount++
await user.emailContact.save()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const emailSent = await sendAccountActivationEmail({
@ -811,7 +794,7 @@ export class UserResolver {
lastName: user.lastName,
email,
language: user.language,
activationLink: activationLink(emailContact.emailVerificationCode),
activationLink: activationLink(user.emailContact.emailVerificationCode),
timeDurationObject: getTimeDurationObject(CONFIG.EMAIL_CODE_VALID_TIME),
})
@ -819,10 +802,7 @@ export class UserResolver {
if (!emailSent) {
logger.info(`Account confirmation link: ${activationLink}`)
} else {
const event = new Event()
const eventSendConfirmationEmail = new EventSendConfirmationEmail()
eventSendConfirmationEmail.userId = user.id
await writeEvent(event.setEventSendConfirmationEmail(eventSendConfirmationEmail))
await EVENT_ADMIN_SEND_CONFIRMATION_EMAIL(user.id)
}
return true

View File

@ -68,6 +68,12 @@ export const createUser = gql`
}
`
export const sendActivationEmail = gql`
mutation ($email: String!) {
sendActivationEmail(email: $email)
}
`
export const sendCoins = gql`
mutation ($email: String!, $amount: Decimal!, $memo: String!) {
sendCoins(email: $email, amount: $amount, memo: $memo)