This commit is contained in:
Ulf Gebhardt 2023-03-29 15:06:26 +02:00
commit 6a8e239ab0
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
28 changed files with 312 additions and 138 deletions

View File

@ -11,7 +11,7 @@ Decimal.set({
}) })
const constants = { const constants = {
DB_VERSION: '0063-event_link_fields', DB_VERSION: '0064-event_rename',
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
LOG4JS_CONFIG: 'log4js-config.json', LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info // default log level on production should be info

View File

@ -0,0 +1,6 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_ADMIN_USER_DELETE = async (user: DbUser, moderator: DbUser): Promise<DbEvent> =>
Event(EventType.ADMIN_USER_DELETE, user, moderator).save()

View File

@ -3,7 +3,7 @@ import { Event as DbEvent } from '@entity/Event'
/* eslint-disable-next-line import/no-cycle */ /* eslint-disable-next-line import/no-cycle */
import { Event, EventType } from './Event' import { Event, EventType } from './Event'
export const EVENT_ADMIN_SEND_CONFIRMATION_EMAIL = async ( export const EVENT_ADMIN_USER_ROLE_SET = async (
user: DbUser, user: DbUser,
moderator: DbUser, moderator: DbUser,
): Promise<DbEvent> => Event(EventType.ADMIN_SEND_CONFIRMATION_EMAIL, user, moderator).save() ): Promise<DbEvent> => Event(EventType.ADMIN_USER_ROLE_SET, user, moderator).save()

View File

@ -0,0 +1,8 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_ADMIN_USER_UNDELETE = async (
user: DbUser,
moderator: DbUser,
): Promise<DbEvent> => Event(EventType.ADMIN_USER_UNDELETE, user, moderator).save()

View File

@ -0,0 +1,6 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.EMAIL_ACCOUNT_MULTIREGISTRATION, user, { id: 0 } as DbUser).save()

View File

@ -0,0 +1,8 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_EMAIL_ADMIN_CONFIRMATION = async (
user: DbUser,
moderator: DbUser,
): Promise<DbEvent> => Event(EventType.EMAIL_ADMIN_CONFIRMATION, user, moderator).save()

View File

@ -0,0 +1,6 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_EMAIL_CONFIRMATION = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.EMAIL_CONFIRMATION, user, user).save()

View File

@ -0,0 +1,6 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_EMAIL_FORGOT_PASSWORD = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.EMAIL_FORGOT_PASSWORD, user, { id: 0 } as DbUser).save()

View File

@ -1,7 +0,0 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
/* eslint-disable-next-line import/no-cycle */
import { Event, EventType } from './Event'
export const EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, user, { id: 0 } as DbUser).save()

View File

@ -1,7 +0,0 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
/* eslint-disable-next-line import/no-cycle */
import { Event, EventType } from './Event'
export const EVENT_SEND_CONFIRMATION_EMAIL = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.SEND_CONFIRMATION_EMAIL, user, user).save()

View File

@ -0,0 +1,6 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_USER_ACTIVATE_ACCOUNT = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_ACTIVATE_ACCOUNT, user, user).save()

View File

@ -3,5 +3,5 @@ import { Event as DbEvent } from '@entity/Event'
/* eslint-disable-next-line import/no-cycle */ /* eslint-disable-next-line import/no-cycle */
import { Event, EventType } from './Event' import { Event, EventType } from './Event'
export const EVENT_ACTIVATE_ACCOUNT = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_INFO_UPDATE = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.ACTIVATE_ACCOUNT, user, user).save() Event(EventType.USER_INFO_UPDATE, user, user).save()

View File

@ -3,5 +3,5 @@ import { Event as DbEvent } from '@entity/Event'
/* eslint-disable-next-line import/no-cycle */ /* eslint-disable-next-line import/no-cycle */
import { Event, EventType } from './Event' import { Event, EventType } from './Event'
export const EVENT_LOGIN = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_LOGIN = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.LOGIN, user, user).save() Event(EventType.USER_LOGIN, user, user).save()

View File

@ -3,5 +3,5 @@ import { Event as DbEvent } from '@entity/Event'
/* eslint-disable-next-line import/no-cycle */ /* eslint-disable-next-line import/no-cycle */
import { Event, EventType } from './Event' import { Event, EventType } from './Event'
export const EVENT_REGISTER = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_LOGOUT = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.REGISTER, user, user).save() Event(EventType.USER_LOGOUT, user, user).save()

View File

@ -0,0 +1,6 @@
import { User as DbUser } from '@entity/User'
import { Event as DbEvent } from '@entity/Event'
import { Event, EventType } from './Event'
export const EVENT_USER_REGISTER = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_REGISTER, user, user).save()

View File

@ -37,7 +37,6 @@ export const Event = (
export { EventType } export { EventType }
export { EVENT_ACTIVATE_ACCOUNT } from './EVENT_ACTIVATE_ACCOUNT'
export { EVENT_ADMIN_CONTRIBUTION_CONFIRM } from './EVENT_ADMIN_CONTRIBUTION_CONFIRM' export { EVENT_ADMIN_CONTRIBUTION_CONFIRM } from './EVENT_ADMIN_CONTRIBUTION_CONFIRM'
export { EVENT_ADMIN_CONTRIBUTION_CREATE } from './EVENT_ADMIN_CONTRIBUTION_CREATE' export { EVENT_ADMIN_CONTRIBUTION_CREATE } from './EVENT_ADMIN_CONTRIBUTION_CREATE'
export { EVENT_ADMIN_CONTRIBUTION_DELETE } from './EVENT_ADMIN_CONTRIBUTION_DELETE' export { EVENT_ADMIN_CONTRIBUTION_DELETE } from './EVENT_ADMIN_CONTRIBUTION_DELETE'
@ -47,18 +46,25 @@ export { EVENT_ADMIN_CONTRIBUTION_LINK_CREATE } from './EVENT_ADMIN_CONTRIBUTION
export { EVENT_ADMIN_CONTRIBUTION_LINK_DELETE } from './EVENT_ADMIN_CONTRIBUTION_LINK_DELETE' export { EVENT_ADMIN_CONTRIBUTION_LINK_DELETE } from './EVENT_ADMIN_CONTRIBUTION_LINK_DELETE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE' export { EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE'
export { EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE' export { EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE'
export { EVENT_ADMIN_SEND_CONFIRMATION_EMAIL } from './EVENT_ADMIN_SEND_CONFIRMATION_EMAIL' export { EVENT_ADMIN_USER_DELETE } from './EVENT_ADMIN_USER_DELETE'
export { EVENT_ADMIN_USER_UNDELETE } from './EVENT_ADMIN_USER_UNDELETE'
export { EVENT_ADMIN_USER_ROLE_SET } from './EVENT_ADMIN_USER_ROLE_SET'
export { EVENT_CONTRIBUTION_CREATE } from './EVENT_CONTRIBUTION_CREATE' export { EVENT_CONTRIBUTION_CREATE } from './EVENT_CONTRIBUTION_CREATE'
export { EVENT_CONTRIBUTION_DELETE } from './EVENT_CONTRIBUTION_DELETE' export { EVENT_CONTRIBUTION_DELETE } from './EVENT_CONTRIBUTION_DELETE'
export { EVENT_CONTRIBUTION_UPDATE } from './EVENT_CONTRIBUTION_UPDATE' export { EVENT_CONTRIBUTION_UPDATE } from './EVENT_CONTRIBUTION_UPDATE'
export { EVENT_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_CONTRIBUTION_MESSAGE_CREATE' export { EVENT_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_CONTRIBUTION_MESSAGE_CREATE'
export { EVENT_CONTRIBUTION_LINK_REDEEM } from './EVENT_CONTRIBUTION_LINK_REDEEM' export { EVENT_CONTRIBUTION_LINK_REDEEM } from './EVENT_CONTRIBUTION_LINK_REDEEM'
export { EVENT_LOGIN } from './EVENT_LOGIN' export { EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION } from './EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION'
export { EVENT_REGISTER } from './EVENT_REGISTER' export { EVENT_EMAIL_ADMIN_CONFIRMATION } from './EVENT_EMAIL_ADMIN_CONFIRMATION'
export { EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL } from './EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL' export { EVENT_EMAIL_CONFIRMATION } from './EVENT_EMAIL_CONFIRMATION'
export { EVENT_SEND_CONFIRMATION_EMAIL } from './EVENT_SEND_CONFIRMATION_EMAIL' export { EVENT_EMAIL_FORGOT_PASSWORD } from './EVENT_EMAIL_FORGOT_PASSWORD'
export { EVENT_TRANSACTION_SEND } from './EVENT_TRANSACTION_SEND' export { EVENT_TRANSACTION_SEND } from './EVENT_TRANSACTION_SEND'
export { EVENT_TRANSACTION_RECEIVE } from './EVENT_TRANSACTION_RECEIVE' export { EVENT_TRANSACTION_RECEIVE } from './EVENT_TRANSACTION_RECEIVE'
export { EVENT_TRANSACTION_LINK_CREATE } from './EVENT_TRANSACTION_LINK_CREATE' export { EVENT_TRANSACTION_LINK_CREATE } from './EVENT_TRANSACTION_LINK_CREATE'
export { EVENT_TRANSACTION_LINK_DELETE } from './EVENT_TRANSACTION_LINK_DELETE' export { EVENT_TRANSACTION_LINK_DELETE } from './EVENT_TRANSACTION_LINK_DELETE'
export { EVENT_TRANSACTION_LINK_REDEEM } from './EVENT_TRANSACTION_LINK_REDEEM' export { EVENT_TRANSACTION_LINK_REDEEM } from './EVENT_TRANSACTION_LINK_REDEEM'
export { EVENT_USER_ACTIVATE_ACCOUNT } from './EVENT_USER_ACTIVATE_ACCOUNT'
export { EVENT_USER_INFO_UPDATE } from './EVENT_USER_INFO_UPDATE'
export { EVENT_USER_LOGIN } from './EVENT_USER_LOGIN'
export { EVENT_USER_LOGOUT } from './EVENT_USER_LOGOUT'
export { EVENT_USER_REGISTER } from './EVENT_USER_REGISTER'

View File

@ -1,5 +1,4 @@
export enum EventType { export enum EventType {
ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
// TODO CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM', // TODO CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM',
ADMIN_CONTRIBUTION_CONFIRM = 'ADMIN_CONTRIBUTION_CONFIRM', ADMIN_CONTRIBUTION_CONFIRM = 'ADMIN_CONTRIBUTION_CONFIRM',
ADMIN_CONTRIBUTION_CREATE = 'ADMIN_CONTRIBUTION_CREATE', ADMIN_CONTRIBUTION_CREATE = 'ADMIN_CONTRIBUTION_CREATE',
@ -10,28 +9,34 @@ export enum EventType {
ADMIN_CONTRIBUTION_LINK_DELETE = 'ADMIN_CONTRIBUTION_LINK_DELETE', ADMIN_CONTRIBUTION_LINK_DELETE = 'ADMIN_CONTRIBUTION_LINK_DELETE',
ADMIN_CONTRIBUTION_LINK_UPDATE = 'ADMIN_CONTRIBUTION_LINK_UPDATE', ADMIN_CONTRIBUTION_LINK_UPDATE = 'ADMIN_CONTRIBUTION_LINK_UPDATE',
ADMIN_CONTRIBUTION_MESSAGE_CREATE = 'ADMIN_CONTRIBUTION_MESSAGE_CREATE', ADMIN_CONTRIBUTION_MESSAGE_CREATE = 'ADMIN_CONTRIBUTION_MESSAGE_CREATE',
ADMIN_SEND_CONFIRMATION_EMAIL = 'ADMIN_SEND_CONFIRMATION_EMAIL', ADMIN_USER_DELETE = 'ADMIN_USER_DELETE',
ADMIN_USER_UNDELETE = 'ADMIN_USER_UNDELETE',
ADMIN_USER_ROLE_SET = 'ADMIN_USER_ROLE_SET',
CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE', CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE',
CONTRIBUTION_DELETE = 'CONTRIBUTION_DELETE', CONTRIBUTION_DELETE = 'CONTRIBUTION_DELETE',
CONTRIBUTION_UPDATE = 'CONTRIBUTION_UPDATE', CONTRIBUTION_UPDATE = 'CONTRIBUTION_UPDATE',
CONTRIBUTION_MESSAGE_CREATE = 'CONTRIBUTION_MESSAGE_CREATE', CONTRIBUTION_MESSAGE_CREATE = 'CONTRIBUTION_MESSAGE_CREATE',
CONTRIBUTION_LINK_REDEEM = 'CONTRIBUTION_LINK_REDEEM', CONTRIBUTION_LINK_REDEEM = 'CONTRIBUTION_LINK_REDEEM',
LOGIN = 'LOGIN', EMAIL_ACCOUNT_MULTIREGISTRATION = 'EMAIL_ACCOUNT_MULTIREGISTRATION',
REGISTER = 'REGISTER', EMAIL_ADMIN_CONFIRMATION = 'EMAIL_ADMIN_CONFIRMATION',
REDEEM_REGISTER = 'REDEEM_REGISTER', EMAIL_CONFIRMATION = 'EMAIL_CONFIRMATION',
SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = 'SEND_ACCOUNT_MULTIREGISTRATION_EMAIL', EMAIL_FORGOT_PASSWORD = 'EMAIL_FORGOT_PASSWORD',
SEND_CONFIRMATION_EMAIL = 'SEND_CONFIRMATION_EMAIL',
TRANSACTION_SEND = 'TRANSACTION_SEND', TRANSACTION_SEND = 'TRANSACTION_SEND',
TRANSACTION_RECEIVE = 'TRANSACTION_RECEIVE', TRANSACTION_RECEIVE = 'TRANSACTION_RECEIVE',
TRANSACTION_LINK_CREATE = 'TRANSACTION_LINK_CREATE', TRANSACTION_LINK_CREATE = 'TRANSACTION_LINK_CREATE',
TRANSACTION_LINK_DELETE = 'TRANSACTION_LINK_DELETE', TRANSACTION_LINK_DELETE = 'TRANSACTION_LINK_DELETE',
TRANSACTION_LINK_REDEEM = 'TRANSACTION_LINK_REDEEM', TRANSACTION_LINK_REDEEM = 'TRANSACTION_LINK_REDEEM',
USER_ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
USER_INFO_UPDATE = 'USER_INFO_UPDATE',
USER_LOGIN = 'USER_LOGIN',
USER_LOGOUT = 'USER_LOGOUT',
USER_REGISTER = 'USER_REGISTER',
USER_REGISTER_REDEEM = 'USER_REGISTER_REDEEM',
// VISIT_GRADIDO = 'VISIT_GRADIDO', // VISIT_GRADIDO = 'VISIT_GRADIDO',
// VERIFY_REDEEM = 'VERIFY_REDEEM', // VERIFY_REDEEM = 'VERIFY_REDEEM',
// INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT', // INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
// CONFIRM_EMAIL = 'CONFIRM_EMAIL', // CONFIRM_EMAIL = 'CONFIRM_EMAIL',
// REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP', // REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
// LOGOUT = 'LOGOUT',
// REDEEM_LOGIN = 'REDEEM_LOGIN', // REDEEM_LOGIN = 'REDEEM_LOGIN',
// SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL', // SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL',
// PASSWORD_CHANGE = 'PASSWORD_CHANGE', // PASSWORD_CHANGE = 'PASSWORD_CHANGE',

View File

@ -1,10 +0,0 @@
import { ArgsType, Field } from 'type-graphql'
@ArgsType()
export default class SubscribeNewsletterArgs {
@Field(() => String)
email: string
@Field(() => String)
language: string
}

View File

@ -2578,10 +2578,10 @@ describe('ContributionResolver', () => {
}) })
}) })
it('stores the SEND_CONFIRMATION_EMAIL event in the database', async () => { it('stores the EMAIL_CONFIRMATION event in the database', async () => {
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.SEND_CONFIRMATION_EMAIL, type: EventType.EMAIL_CONFIRMATION,
}), }),
) )
}) })

View File

@ -1,7 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-return */
import { Resolver, Query, Authorized, Arg, Mutation, Args } from 'type-graphql' import { Resolver, Query, Authorized, Arg, Mutation, Ctx } from 'type-graphql'
import SubscribeNewsletterArgs from '@arg/SubscribeNewsletterArgs'
import { import {
getKlickTippUser, getKlickTippUser,
@ -10,6 +8,7 @@ import {
klicktippSignIn, klicktippSignIn,
} from '@/apis/KlicktippController' } from '@/apis/KlicktippController'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
import { Context, getUser } from '@/server/context'
@Resolver() @Resolver()
export class KlicktippResolver { export class KlicktippResolver {
@ -27,15 +26,15 @@ export class KlicktippResolver {
@Authorized([RIGHTS.UNSUBSCRIBE_NEWSLETTER]) @Authorized([RIGHTS.UNSUBSCRIBE_NEWSLETTER])
@Mutation(() => Boolean) @Mutation(() => Boolean)
async unsubscribeNewsletter(@Arg('email') email: string): Promise<boolean> { async unsubscribeNewsletter(@Ctx() context: Context): Promise<boolean> {
return await unsubscribe(email) const user = getUser(context)
return unsubscribe(user.emailContact.email)
} }
@Authorized([RIGHTS.SUBSCRIBE_NEWSLETTER]) @Authorized([RIGHTS.SUBSCRIBE_NEWSLETTER])
@Mutation(() => Boolean) @Mutation(() => Boolean)
async subscribeNewsletter( async subscribeNewsletter(@Ctx() context: Context): Promise<boolean> {
@Args() { email, language }: SubscribeNewsletterArgs, const user = getUser(context)
): Promise<boolean> { return klicktippSignIn(user.emailContact.email, user.language)
return await klicktippSignIn(email, language)
} }
} }

View File

@ -182,14 +182,14 @@ describe('UserResolver', () => {
}) })
}) })
it('stores the REGISTER event in the database', async () => { it('stores the USER_REGISTER event in the database', async () => {
const userConatct = await UserContact.findOneOrFail( const userConatct = await UserContact.findOneOrFail(
{ email: 'peter@lustig.de' }, { email: 'peter@lustig.de' },
{ relations: ['user'] }, { relations: ['user'] },
) )
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.REGISTER, type: EventType.USER_REGISTER,
affectedUserId: userConatct.user.id, affectedUserId: userConatct.user.id,
actingUserId: userConatct.user.id, actingUserId: userConatct.user.id,
}), }),
@ -216,10 +216,10 @@ describe('UserResolver', () => {
}) })
}) })
it('stores the SEND_CONFIRMATION_EMAIL event in the database', async () => { it('stores the EMAIL_CONFIRMATION event in the database', async () => {
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.SEND_CONFIRMATION_EMAIL, type: EventType.EMAIL_CONFIRMATION,
affectedUserId: user[0].id, affectedUserId: user[0].id,
actingUserId: user[0].id, actingUserId: user[0].id,
}), }),
@ -258,14 +258,14 @@ describe('UserResolver', () => {
) )
}) })
it('stores the SEND_ACCOUNT_MULTIREGISTRATION_EMAIL event in the database', async () => { it('stores the EMAIL_ACCOUNT_MULTIREGISTRATION event in the database', async () => {
const userConatct = await UserContact.findOneOrFail( const userConatct = await UserContact.findOneOrFail(
{ email: 'peter@lustig.de' }, { email: 'peter@lustig.de' },
{ relations: ['user'] }, { relations: ['user'] },
) )
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, type: EventType.EMAIL_ACCOUNT_MULTIREGISTRATION,
affectedUserId: userConatct.user.id, affectedUserId: userConatct.user.id,
actingUserId: 0, actingUserId: 0,
}), }),
@ -363,20 +363,20 @@ describe('UserResolver', () => {
) )
}) })
it('stores the ACTIVATE_ACCOUNT event in the database', async () => { it('stores the USER_ACTIVATE_ACCOUNT event in the database', async () => {
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.ACTIVATE_ACCOUNT, type: EventType.USER_ACTIVATE_ACCOUNT,
affectedUserId: user[0].id, affectedUserId: user[0].id,
actingUserId: user[0].id, actingUserId: user[0].id,
}), }),
) )
}) })
it('stores the REDEEM_REGISTER event in the database', async () => { it('stores the USER_REGISTER_REDEEM event in the database', async () => {
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.REDEEM_REGISTER, type: EventType.USER_REGISTER_REDEEM,
affectedUserId: result.data.createUser.id, affectedUserId: result.data.createUser.id,
actingUserId: result.data.createUser.id, actingUserId: result.data.createUser.id,
involvedContributionLinkId: link.id, involvedContributionLinkId: link.id,
@ -458,10 +458,10 @@ describe('UserResolver', () => {
) )
}) })
it('stores the REDEEM_REGISTER event in the database', async () => { it('stores the USER_REGISTER_REDEEM event in the database', async () => {
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.REDEEM_REGISTER, type: EventType.USER_REGISTER_REDEEM,
affectedUserId: newUser.data.createUser.id, affectedUserId: newUser.data.createUser.id,
actingUserId: newUser.data.createUser.id, actingUserId: newUser.data.createUser.id,
involvedTransactionLinkId: transactionLink.id, involvedTransactionLinkId: transactionLink.id,
@ -687,14 +687,14 @@ describe('UserResolver', () => {
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 () => { it('stores the USER_LOGIN event in the database', async () => {
const userConatct = await UserContact.findOneOrFail( const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' }, { email: 'bibi@bloxberg.de' },
{ relations: ['user'] }, { relations: ['user'] },
) )
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.LOGIN, type: EventType.USER_LOGIN,
affectedUserId: userConatct.user.id, affectedUserId: userConatct.user.id,
actingUserId: userConatct.user.id, actingUserId: userConatct.user.id,
}), }),
@ -868,6 +868,20 @@ describe('UserResolver', () => {
}), }),
) )
}) })
it('stores the USER_LOGOUT event in the database', async () => {
const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' },
{ relations: ['user'] },
)
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.USER_LOGOUT,
affectedUserId: userConatct.user.id,
actingUserId: userConatct.user.id,
}),
)
})
}) })
}) })
@ -941,10 +955,10 @@ describe('UserResolver', () => {
) )
}) })
it('stores the LOGIN event in the database', async () => { it('stores the USER_LOGIN event in the database', async () => {
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.LOGIN, type: EventType.USER_LOGIN,
affectedUserId: user[0].id, affectedUserId: user[0].id,
actingUserId: user[0].id, actingUserId: user[0].id,
}), }),
@ -1023,6 +1037,20 @@ describe('UserResolver', () => {
}), }),
}) })
}) })
it('stores the EMAIL_FORGOT_PASSWORD event in the database', async () => {
const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' },
{ relations: ['user'] },
)
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.EMAIL_FORGOT_PASSWORD,
affectedUserId: userConatct.user.id,
actingUserId: 0,
}),
)
})
}) })
describe('request reset password again', () => { describe('request reset password again', () => {
@ -1147,6 +1175,20 @@ describe('UserResolver', () => {
}), }),
) )
}) })
it('stores the USER_INFO_UPDATE event in the database', async () => {
const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' },
{ relations: ['user'] },
)
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.USER_INFO_UPDATE,
affectedUserId: userConatct.user.id,
actingUserId: userConatct.user.id,
}),
)
})
}) })
describe('language is not valid', () => { describe('language is not valid', () => {
@ -1517,6 +1559,24 @@ describe('UserResolver', () => {
) )
expect(new Date(result.data.setUserRole)).toEqual(expect.any(Date)) expect(new Date(result.data.setUserRole)).toEqual(expect.any(Date))
}) })
it('stores the ADMIN_USER_ROLE_SET event in the database', async () => {
const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' },
{ relations: ['user'] },
)
const adminConatct = await UserContact.findOneOrFail(
{ email: 'peter@lustig.de' },
{ relations: ['user'] },
)
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.ADMIN_USER_ROLE_SET,
affectedUserId: userConatct.user.id,
actingUserId: adminConatct.user.id,
}),
)
})
}) })
describe('to usual user', () => { describe('to usual user', () => {
@ -1702,6 +1762,24 @@ describe('UserResolver', () => {
expect(new Date(result.data.deleteUser)).toEqual(expect.any(Date)) expect(new Date(result.data.deleteUser)).toEqual(expect.any(Date))
}) })
it('stores the ADMIN_USER_DELETE event in the database', async () => {
const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' },
{ relations: ['user'], withDeleted: true },
)
const adminConatct = await UserContact.findOneOrFail(
{ email: 'peter@lustig.de' },
{ relations: ['user'] },
)
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.ADMIN_USER_DELETE,
affectedUserId: userConatct.user.id,
actingUserId: adminConatct.user.id,
}),
)
})
describe('delete deleted user', () => { describe('delete deleted user', () => {
it('throws an error', async () => { it('throws an error', async () => {
jest.clearAllMocks() jest.clearAllMocks()
@ -1857,14 +1935,14 @@ describe('UserResolver', () => {
}) })
}) })
it('stores the ADMIN_SEND_CONFIRMATION_EMAIL event in the database', async () => { it('stores the EMAIL_ADMIN_CONFIRMATION event in the database', async () => {
const userConatct = await UserContact.findOneOrFail( const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' }, { email: 'bibi@bloxberg.de' },
{ relations: ['user'] }, { relations: ['user'] },
) )
await expect(DbEvent.find()).resolves.toContainEqual( await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({ expect.objectContaining({
type: EventType.ADMIN_SEND_CONFIRMATION_EMAIL, type: EventType.EMAIL_ADMIN_CONFIRMATION,
affectedUserId: userConatct.user.id, affectedUserId: userConatct.user.id,
actingUserId: admin.id, actingUserId: admin.id,
}), }),
@ -1977,6 +2055,24 @@ describe('UserResolver', () => {
}), }),
) )
}) })
it('stores the ADMIN_USER_UNDELETE event in the database', async () => {
const userConatct = await UserContact.findOneOrFail(
{ email: 'bibi@bloxberg.de' },
{ relations: ['user'] },
)
const adminConatct = await UserContact.findOneOrFail(
{ email: 'peter@lustig.de' },
{ relations: ['user'] },
)
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.ADMIN_USER_UNDELETE,
affectedUserId: userConatct.user.id,
actingUserId: adminConatct.user.id,
}),
)
})
}) })
}) })
}) })

View File

@ -58,12 +58,18 @@ import { hasElopageBuys } from '@/util/hasElopageBuys'
import { import {
Event, Event,
EventType, EventType,
EVENT_LOGIN, EVENT_USER_LOGIN,
EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION,
EVENT_SEND_CONFIRMATION_EMAIL, EVENT_EMAIL_CONFIRMATION,
EVENT_REGISTER, EVENT_USER_REGISTER,
EVENT_ACTIVATE_ACCOUNT, EVENT_USER_ACTIVATE_ACCOUNT,
EVENT_ADMIN_SEND_CONFIRMATION_EMAIL, EVENT_EMAIL_ADMIN_CONFIRMATION,
EVENT_USER_LOGOUT,
EVENT_EMAIL_FORGOT_PASSWORD,
EVENT_USER_INFO_UPDATE,
EVENT_ADMIN_USER_ROLE_SET,
EVENT_ADMIN_USER_DELETE,
EVENT_ADMIN_USER_UNDELETE,
} from '@/event/Event' } from '@/event/Event'
import { isValidPassword } from '@/password/EncryptorUtils' import { isValidPassword } from '@/password/EncryptorUtils'
import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor' import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
@ -182,22 +188,16 @@ export class UserResolver {
value: encode(dbUser.gradidoID), value: encode(dbUser.gradidoID),
}) })
await EVENT_LOGIN(dbUser) await EVENT_USER_LOGIN(dbUser)
logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`) logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`)
return user return user
} }
@Authorized([RIGHTS.LOGOUT]) @Authorized([RIGHTS.LOGOUT])
@Mutation(() => Boolean) @Mutation(() => Boolean)
logout(): boolean { async logout(@Ctx() context: Context): Promise<boolean> {
// TODO: Event still missing here!! await EVENT_USER_LOGOUT(getUser(context))
// TODO: We dont need this anymore, but might need this in the future in oder to invalidate a valid JWT-Token. // remove user from logger context
// Furthermore this hook can be useful for tracking user behaviour (did he logout or not? Warn him if he didn't on next login)
// The functionality is fully client side - the client just needs to delete his token with the current implementation.
// we could try to force this by sending `token: null` or `token: ''` with this call. But since it bares no real security
// we should just return true for now.
logger.info('Logout...')
// remove user.pubKey from logger-context to ensure a correct filter on log-messages belonging to the same user
logger.addContext('user', 'unknown') logger.addContext('user', 'unknown')
return true return true
} }
@ -251,8 +251,7 @@ 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
}) })
await EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION(foundUser)
await EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL(foundUser)
logger.info( logger.info(
`sendAccountMultiRegistrationEmail by ${firstName} ${lastName} to ${foundUser.firstName} ${foundUser.lastName} <${email}>`, `sendAccountMultiRegistrationEmail by ${firstName} ${lastName} to ${foundUser.firstName} ${foundUser.lastName} <${email}>`,
@ -271,7 +270,7 @@ export class UserResolver {
const gradidoID = await newGradidoID() const gradidoID = await newGradidoID()
const eventRegisterRedeem = Event( const eventRegisterRedeem = Event(
EventType.REDEEM_REGISTER, EventType.USER_REGISTER_REDEEM,
{ id: 0 } as DbUser, { id: 0 } as DbUser,
{ id: 0 } as DbUser, { id: 0 } as DbUser,
) )
@ -337,7 +336,7 @@ export class UserResolver {
}) })
logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`)
await EVENT_SEND_CONFIRMATION_EMAIL(dbUser) await EVENT_EMAIL_CONFIRMATION(dbUser)
if (!emailSent) { if (!emailSent) {
logger.debug(`Account confirmation link: ${activationLink}`) logger.debug(`Account confirmation link: ${activationLink}`)
@ -358,7 +357,7 @@ export class UserResolver {
eventRegisterRedeem.actingUser = dbUser eventRegisterRedeem.actingUser = dbUser
await eventRegisterRedeem.save() await eventRegisterRedeem.save()
} else { } else {
await EVENT_REGISTER(dbUser) await EVENT_USER_REGISTER(dbUser)
} }
return new User(dbUser) return new User(dbUser)
@ -411,6 +410,7 @@ export class UserResolver {
) )
} }
logger.info(`forgotPassword(${email}) successful...`) logger.info(`forgotPassword(${email}) successful...`)
await EVENT_EMAIL_FORGOT_PASSWORD(user)
return true return true
} }
@ -473,8 +473,6 @@ 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...')
await EVENT_ACTIVATE_ACCOUNT(user)
} 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)
@ -492,13 +490,9 @@ export class UserResolver {
) )
} catch (e) { } catch (e) {
logger.error('Error subscribing to klicktipp', e) logger.error('Error subscribing to klicktipp', e)
// TODO is this a problem?
// eslint-disable-next-line no-console
/* uncomment this, when you need the activation link on the console
console.log('Could not subscribe to klicktipp')
*/
} }
} }
await EVENT_USER_ACTIVATE_ACCOUNT(user)
return true return true
} }
@ -535,21 +529,21 @@ export class UserResolver {
@Ctx() context: Context, @Ctx() context: Context,
): Promise<boolean> { ): Promise<boolean> {
logger.info(`updateUserInfos(${firstName}, ${lastName}, ${language}, ***, ***)...`) logger.info(`updateUserInfos(${firstName}, ${lastName}, ${language}, ***, ***)...`)
const userEntity = getUser(context) const user = getUser(context)
if (firstName) { if (firstName) {
userEntity.firstName = firstName user.firstName = firstName
} }
if (lastName) { if (lastName) {
userEntity.lastName = lastName user.lastName = lastName
} }
if (language) { if (language) {
if (!isLanguage(language)) { if (!isLanguage(language)) {
throw new LogError('Given language is not a valid language', language) throw new LogError('Given language is not a valid language', language)
} }
userEntity.language = language user.language = language
i18n.setLocale(language) i18n.setLocale(language)
} }
@ -561,22 +555,22 @@ export class UserResolver {
) )
} }
if (!verifyPassword(userEntity, password)) { if (!verifyPassword(user, password)) {
throw new LogError(`Old password is invalid`) throw new LogError(`Old password is invalid`)
} }
// Save new password hash and newly encrypted private key // Save new password hash and newly encrypted private key
userEntity.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID user.passwordEncryptionType = PasswordEncryptionType.GRADIDO_ID
userEntity.password = encryptPassword(userEntity, passwordNew) user.password = encryptPassword(user, passwordNew)
} }
// Save hideAmountGDD value // Save hideAmountGDD value
if (hideAmountGDD !== undefined) { if (hideAmountGDD !== undefined) {
userEntity.hideAmountGDD = hideAmountGDD user.hideAmountGDD = hideAmountGDD
} }
// Save hideAmountGDT value // Save hideAmountGDT value
if (hideAmountGDT !== undefined) { if (hideAmountGDT !== undefined) {
userEntity.hideAmountGDT = hideAmountGDT user.hideAmountGDT = hideAmountGDT
} }
const queryRunner = getConnection().createQueryRunner() const queryRunner = getConnection().createQueryRunner()
@ -584,7 +578,7 @@ export class UserResolver {
await queryRunner.startTransaction('REPEATABLE READ') await queryRunner.startTransaction('REPEATABLE READ')
try { try {
await queryRunner.manager.save(userEntity).catch((error) => { await queryRunner.manager.save(user).catch((error) => {
throw new LogError('Error saving user', error) throw new LogError('Error saving user', error)
}) })
@ -597,6 +591,8 @@ export class UserResolver {
await queryRunner.release() await queryRunner.release()
} }
logger.info('updateUserInfos() successfully finished...') logger.info('updateUserInfos() successfully finished...')
await EVENT_USER_INFO_UPDATE(user)
return true return true
} }
@ -722,8 +718,8 @@ export class UserResolver {
throw new LogError('Could not find user with given ID', userId) throw new LogError('Could not find user with given ID', userId)
} }
// administrator user changes own role? // administrator user changes own role?
const moderatorUser = getUser(context) const moderator = getUser(context)
if (moderatorUser.id === userId) { if (moderator.id === userId) {
throw new LogError('Administrator can not change his own role') throw new LogError('Administrator can not change his own role')
} }
// change isAdmin // change isAdmin
@ -744,6 +740,7 @@ export class UserResolver {
break break
} }
await user.save() await user.save()
await EVENT_ADMIN_USER_ROLE_SET(user, moderator)
const newUser = await DbUser.findOne({ id: userId }) const newUser = await DbUser.findOne({ id: userId })
return newUser ? newUser.isAdmin : null return newUser ? newUser.isAdmin : null
} }
@ -760,19 +757,23 @@ export class UserResolver {
throw new LogError('Could not find user with given ID', userId) throw new LogError('Could not find user with given ID', userId)
} }
// moderator user disabled own account? // moderator user disabled own account?
const moderatorUser = getUser(context) const moderator = getUser(context)
if (moderatorUser.id === userId) { if (moderator.id === userId) {
throw new LogError('Moderator can not delete his own account') throw new LogError('Moderator can not delete his own account')
} }
// soft-delete user // soft-delete user
await user.softRemove() await user.softRemove()
await EVENT_ADMIN_USER_DELETE(user, moderator)
const newUser = await DbUser.findOne({ id: userId }, { withDeleted: true }) const newUser = await DbUser.findOne({ id: userId }, { withDeleted: true })
return newUser ? newUser.deletedAt : null return newUser ? newUser.deletedAt : null
} }
@Authorized([RIGHTS.UNDELETE_USER]) @Authorized([RIGHTS.UNDELETE_USER])
@Mutation(() => Date, { nullable: true }) @Mutation(() => Date, { nullable: true })
async unDeleteUser(@Arg('userId', () => Int) userId: number): Promise<Date | null> { async unDeleteUser(
@Arg('userId', () => Int) userId: number,
@Ctx() context: Context,
): Promise<Date | null> {
const user = await DbUser.findOne({ id: userId }, { withDeleted: true }) const user = await DbUser.findOne({ id: userId }, { withDeleted: true })
if (!user) { if (!user) {
throw new LogError('Could not find user with given ID', userId) throw new LogError('Could not find user with given ID', userId)
@ -781,6 +782,7 @@ export class UserResolver {
throw new LogError('User is not deleted') throw new LogError('User is not deleted')
} }
await user.recover() await user.recover()
await EVENT_ADMIN_USER_UNDELETE(user, getUser(context))
return null return null
} }
@ -814,9 +816,8 @@ export class UserResolver {
// In case EMails are disabled log the activation link for the user // In case EMails are disabled log the activation link for the user
if (!emailSent) { if (!emailSent) {
logger.info(`Account confirmation link: ${activationLink}`) logger.info(`Account confirmation link: ${activationLink}`)
} else {
await EVENT_ADMIN_SEND_CONFIRMATION_EMAIL(user, getUser(context))
} }
await EVENT_EMAIL_ADMIN_CONFIRMATION(user, getUser(context))
return true return true
} }

View File

@ -0,0 +1,50 @@
/* MIGRATION TO CHANGE EVENT NAMES
*
* This migration renames several events to ensure consistent
* naming conventions.
*/
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
await queryFn(
'UPDATE `events` SET `type` = "USER_ACTIVATE_ACCOUNT" WHERE `type` = "ACTIVATE_ACCOUNT";',
)
await queryFn('UPDATE `events` SET `type` = "USER_LOGIN" WHERE `type` = "LOGIN";')
await queryFn('UPDATE `events` SET `type` = "USER_LOGOUT" WHERE `type` = "LOGOUT";')
await queryFn('UPDATE `events` SET `type` = "USER_REGISTER" WHERE `type` = "REGISTER";')
await queryFn(
'UPDATE `events` SET `type` = "EMAIL_ACCOUNT_MULTIREGISTRATION" WHERE `type` = "SEND_ACCOUNT_MULTIREGISTRATION_EMAIL";',
)
await queryFn(
'UPDATE `events` SET `type` = "EMAIL_CONFIRMATION" WHERE `type` = "SEND_CONFIRMATION_EMAIL";',
)
await queryFn(
'UPDATE `events` SET `type` = "EMAIL_ADMIN_CONFIRMATION" WHERE `type` = "ADMIN_SEND_CONFIRMATION_EMAIL";',
)
await queryFn(
'UPDATE `events` SET `type` = "USER_REGISTER_REDEEM" WHERE `type` = "REDEEM_REGISTER";',
)
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
await queryFn(
'UPDATE `events` SET `type` = "REDEEM_REGISTER" WHERE `type` = "USER_REGISTER_REDEEM";',
)
await queryFn(
'UPDATE `events` SET `type` = "ADMIN_SEND_CONFIRMATION_EMAIL" WHERE `type` = "EMAIL_ADMIN_CONFIRMATION";',
)
await queryFn(
'UPDATE `events` SET `type` = "SEND_CONFIRMATION_EMAIL" WHERE `type` = "EMAIL_CONFIRMATION";',
)
await queryFn(
'UPDATE `events` SET `type` = "SEND_ACCOUNT_MULTIREGISTRATION_EMAIL" WHERE `type` = "EMAIL_ACCOUNT_MULTIREGISTRATION";',
)
await queryFn('UPDATE `events` SET `type` = "REGISTER" WHERE `type` = "USER_REGISTER";')
await queryFn('UPDATE `events` SET `type` = "LOGOUT" WHERE `type` = "USER_LOGOUT";')
await queryFn('UPDATE `events` SET `type` = "LOGIN" WHERE `type` = "USER_LOGIN";')
await queryFn(
'UPDATE `events` SET `type` = "ACTIVATE_ACCOUNT" WHERE `type` = "USER_ACTIVATE_ACCOUNT";',
)
}

View File

@ -3,7 +3,7 @@ import dotenv from 'dotenv'
dotenv.config() dotenv.config()
const constants = { const constants = {
DB_VERSION: '0063-event_link_fields', DB_VERSION: '0064-event_rename',
LOG4JS_CONFIG: 'log4js-config.json', LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info // default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL || 'info', LOG_LEVEL: process.env.LOG_LEVEL || 'info',

View File

@ -11,7 +11,7 @@ Decimal.set({
*/ */
const constants = { const constants = {
DB_VERSION: '0063-event_link_fields', DB_VERSION: '0064-event_rename',
// DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 // DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
LOG4JS_CONFIG: 'log4js-config.json', LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info // default log level on production should be info

View File

@ -60,9 +60,6 @@ describe('UserCard_Newsletter', () => {
it('calls the unsubscribe mutation', () => { it('calls the unsubscribe mutation', () => {
expect(mockAPIcall).toBeCalledWith({ expect(mockAPIcall).toBeCalledWith({
mutation: unsubscribeNewsletter, mutation: unsubscribeNewsletter,
variables: {
email: 'peter@lustig.de',
},
}) })
}) })
@ -89,10 +86,6 @@ describe('UserCard_Newsletter', () => {
it('calls the subscribe mutation', () => { it('calls the subscribe mutation', () => {
expect(mockAPIcall).toBeCalledWith({ expect(mockAPIcall).toBeCalledWith({
mutation: subscribeNewsletter, mutation: subscribeNewsletter,
variables: {
email: 'peter@lustig.de',
language: 'de',
},
}) })
}) })

View File

@ -41,10 +41,6 @@ export default {
this.$apollo this.$apollo
.mutate({ .mutate({
mutation: this.newsletterState ? subscribeNewsletter : unsubscribeNewsletter, mutation: this.newsletterState ? subscribeNewsletter : unsubscribeNewsletter,
variables: {
email: this.$store.state.email,
language: this.newsletterState ? this.$store.state.language : undefined,
},
}) })
.then(() => { .then(() => {
this.$store.commit('newsletterState', this.newsletterState) this.$store.commit('newsletterState', this.newsletterState)

View File

@ -1,14 +1,14 @@
import gql from 'graphql-tag' import gql from 'graphql-tag'
export const subscribeNewsletter = gql` export const subscribeNewsletter = gql`
mutation($email: String!, $language: String!) { mutation {
subscribeNewsletter(email: $email, language: $language) subscribeNewsletter
} }
` `
export const unsubscribeNewsletter = gql` export const unsubscribeNewsletter = gql`
mutation($email: String!) { mutation {
unsubscribeNewsletter(email: $email) unsubscribeNewsletter
} }
` `