Merge remote-tracking branch 'origin/master' into

1794-feature-event-protocol-1-implement-the-basics-of-the-business-event-protocol
This commit is contained in:
Claus-Peter Hübner 2022-07-13 01:28:53 +02:00
commit f3eb73bf8d
19 changed files with 2302 additions and 121 deletions

View File

@ -26,6 +26,7 @@ export enum RIGHTS {
LIST_TRANSACTION_LINKS = 'LIST_TRANSACTION_LINKS',
GDT_BALANCE = 'GDT_BALANCE',
CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION',
LIST_CONTRIBUTIONS = 'LIST_CONTRIBUTIONS',
// Admin
SEARCH_USERS = 'SEARCH_USERS',
SET_USER_ROLE = 'SET_USER_ROLE',

View File

@ -24,6 +24,7 @@ export const ROLE_USER = new Role('user', [
RIGHTS.LIST_TRANSACTION_LINKS,
RIGHTS.GDT_BALANCE,
RIGHTS.CREATE_CONTRIBUTION,
RIGHTS.LIST_CONTRIBUTIONS,
])
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights

View File

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

View File

@ -0,0 +1,43 @@
import { ObjectType, Field, Int } from 'type-graphql'
import Decimal from 'decimal.js-light'
import { Contribution as dbContribution } from '@entity/Contribution'
import { User } from './User'
@ObjectType()
export class Contribution {
constructor(contribution: dbContribution, user: User) {
this.id = contribution.id
this.user = user
this.amount = contribution.amount
this.memo = contribution.memo
this.createdAt = contribution.createdAt
this.deletedAt = contribution.deletedAt
}
@Field(() => Number)
id: number
@Field(() => User)
user: User
@Field(() => Decimal)
amount: Decimal
@Field(() => String)
memo: string
@Field(() => Date)
createdAt: Date
@Field(() => Date, { nullable: true })
deletedAt: Date | null
}
@ObjectType()
export class ContributionListResult {
@Field(() => Int)
linkCount: number
@Field(() => [Contribution])
linkList: Contribution[]
}

View File

@ -1,10 +1,12 @@
import { ObjectType, Field } from 'type-graphql'
import { KlickTipp } from './KlickTipp'
import { User as dbUser } from '@entity/User'
import Decimal from 'decimal.js-light'
import { FULL_CREATION_AVAILABLE } from '../resolver/const/const'
@ObjectType()
export class User {
constructor(user: dbUser) {
constructor(user: dbUser, creation: Decimal[] = FULL_CREATION_AVAILABLE) {
this.id = user.id
this.email = user.email
this.firstName = user.firstName
@ -17,6 +19,7 @@ export class User {
this.isAdmin = user.isAdmin
this.klickTipp = null
this.hasElopage = null
this.creation = creation
}
@Field(() => Number)
@ -64,4 +67,7 @@ export class User {
@Field(() => Boolean, { nullable: true })
hasElopage: boolean | null
@Field(() => [Decimal])
creation: Decimal[]
}

View File

@ -3,10 +3,13 @@
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { createContribution } from '@/seeds/graphql/mutations'
import { login } from '@/seeds/graphql/queries'
import { listContributions, login } from '@/seeds/graphql/queries'
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
import { GraphQLError } from 'graphql'
import { userFactory } from '@/seeds/factory/user'
import { creationFactory } from '@/seeds/factory/creation'
import { creations } from '@/seeds/creation/index'
import { peterLustig } from '@/seeds/users/peter-lustig'
let mutate: any, query: any, con: any
let testEnv: any
@ -111,6 +114,7 @@ describe('ContributionResolver', () => {
expect.objectContaining({
data: {
createContribution: {
id: expect.any(Number),
amount: '100',
memo: 'Test env contribution',
},
@ -121,4 +125,109 @@ describe('ContributionResolver', () => {
})
})
})
describe('listContributions', () => {
describe('unauthenticated', () => {
it('returns an error', async () => {
await expect(
query({
query: listContributions,
variables: {
currentPage: 1,
pageSize: 25,
order: 'DESC',
filterConfirmed: false,
},
}),
).resolves.toEqual(
expect.objectContaining({
errors: [new GraphQLError('401 Unauthorized')],
}),
)
})
})
describe('authenticated', () => {
beforeAll(async () => {
await userFactory(testEnv, bibiBloxberg)
await userFactory(testEnv, peterLustig)
const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de')
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await creationFactory(testEnv, bibisCreation!)
await query({
query: login,
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
})
await mutate({
mutation: createContribution,
variables: {
amount: 100.0,
memo: 'Test env contribution',
creationDate: new Date().toString(),
},
})
})
describe('filter confirmed is false', () => {
it('returns creations', async () => {
await expect(
query({
query: listContributions,
variables: {
currentPage: 1,
pageSize: 25,
order: 'DESC',
filterConfirmed: false,
},
}),
).resolves.toEqual(
expect.objectContaining({
data: {
listContributions: expect.arrayContaining([
expect.objectContaining({
id: expect.any(Number),
memo: 'Herzlich Willkommen bei Gradido!',
amount: '1000',
}),
expect.objectContaining({
id: expect.any(Number),
memo: 'Test env contribution',
amount: '100',
}),
]),
},
}),
)
})
})
describe('filter confirmed is true', () => {
it('returns only unconfirmed creations', async () => {
await expect(
query({
query: listContributions,
variables: {
currentPage: 1,
pageSize: 25,
order: 'DESC',
filterConfirmed: true,
},
}),
).resolves.toEqual(
expect.objectContaining({
data: {
listContributions: expect.arrayContaining([
expect.objectContaining({
id: expect.any(Number),
memo: 'Test env contribution',
amount: '100',
}),
]),
},
}),
)
})
})
})
})
})

View File

@ -1,10 +1,15 @@
import { RIGHTS } from '@/auth/RIGHTS'
import { Context, getUser } from '@/server/context'
import { backendLogger as logger } from '@/server/logger'
import { Contribution } from '@entity/Contribution'
import { Args, Authorized, Ctx, Mutation, Resolver } from 'type-graphql'
import ContributionArgs from '../arg/ContributionArgs'
import { UnconfirmedContribution } from '../model/UnconfirmedContribution'
import { Contribution as dbContribution } from '@entity/Contribution'
import { Arg, Args, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql'
import { FindOperator, IsNull } from '@dbTools/typeorm'
import ContributionArgs from '@arg/ContributionArgs'
import Paginated from '@arg/Paginated'
import { Order } from '@enum/Order'
import { Contribution } from '@model/Contribution'
import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
import { User } from '@model/User'
import { validateContribution, getUserCreation } from './util/creations'
@Resolver()
@ -21,7 +26,7 @@ export class ContributionResolver {
const creationDateObj = new Date(creationDate)
validateContribution(creations, amount, creationDateObj)
const contribution = Contribution.create()
const contribution = dbContribution.create()
contribution.userId = user.id
contribution.amount = amount
contribution.createdAt = new Date()
@ -29,7 +34,33 @@ export class ContributionResolver {
contribution.memo = memo
logger.trace('contribution to save', contribution)
await Contribution.save(contribution)
await dbContribution.save(contribution)
return new UnconfirmedContribution(contribution, user, creations)
}
@Authorized([RIGHTS.LIST_CONTRIBUTIONS])
@Query(() => [Contribution])
async listContributions(
@Args()
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
@Arg('filterConfirmed', () => Boolean)
filterConfirmed: boolean | null,
@Ctx() context: Context,
): Promise<Contribution[]> {
const user = getUser(context)
const where: {
userId: number
confirmedBy?: FindOperator<number> | null
} = { userId: user.id }
if (filterConfirmed) where.confirmedBy = IsNull()
const contributions = await dbContribution.find({
where,
order: {
createdAt: order,
},
skip: (currentPage - 1) * pageSize,
take: pageSize,
})
return contributions.map((contribution) => new Contribution(contribution, new User(user)))
}
}

View File

@ -25,6 +25,7 @@ import { RIGHTS } from '@/auth/RIGHTS'
import { hasElopageBuys } from '@/util/hasElopageBuys'
import { eventProtocol } from '@/event/EventProtocolEmitter'
import { Event, EventLogin, EventRedeemRegister, EventRegister } from '@/event/Event'
import { getUserCreation } from './util/creations'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const sodium = require('sodium-native')
@ -226,7 +227,7 @@ export class UserResolver {
logger.info('verifyLogin...')
// TODO refactor and do not have duplicate code with login(see below)
const userEntity = getUser(context)
const user = new User(userEntity)
const user = new User(userEntity, await getUserCreation(userEntity.id))
// user.pubkey = userEntity.pubKey.toString('hex')
// Elopage Status & Stored PublisherId
user.hasElopage = await this.hasElopage(context)
@ -276,7 +277,7 @@ export class UserResolver {
logger.addContext('user', dbUser.id)
logger.debug('login credentials valid...')
const user = new User(dbUser)
const user = new User(dbUser, await getUserCreation(dbUser.id))
logger.debug('user=' + user)
// Elopage Status & Stored PublisherId

View File

@ -234,6 +234,7 @@ export const deleteContributionLink = gql`
export const createContribution = gql`
mutation ($amount: Decimal!, $memo: String!, $creationDate: String!) {
createContribution(amount: $amount, memo: $memo, creationDate: $creationDate) {
id
amount
memo
}

View File

@ -172,6 +172,25 @@ export const queryTransactionLink = gql`
}
`
export const listContributions = gql`
query (
$currentPage: Int = 1
$pageSize: Int = 5
$order: Order
$filterConfirmed: Boolean = false
) {
listContributions(
currentPage: $currentPage
pageSize: $pageSize
order: $order
filterConfirmed: $filterConfirmed
) {
id
amount
memo
}
}
`
// from admin interface
export const listUnconfirmedContributions = gql`

View File

@ -1 +1 @@
export { EventProtocol } from './0041-add_event_protocol_table/EventProtocol'
export { EventProtocol } from './0043-add_event_protocol_table/EventProtocol'

View File

@ -1,104 +0,0 @@
/* MIGRATION TO ADD EVENT_PROTOCOL
*
* This migration adds the table `event_protocol` in order to store all sorts of business event data
*/
/* 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(`
CREATE TABLE IF NOT EXISTS \`event_protocol\` (
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
\`type\` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
\`created_at\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`user_id\` int(10) unsigned NOT NULL,
\`x_user_id\` int(10) unsigned NULL DEFAULT NULL,
\`x_community_id\` int(10) unsigned NULL DEFAULT NULL,
\`transaction_id\` int(10) unsigned NULL DEFAULT NULL,
\`contribution_id\` int(10) unsigned NULL DEFAULT NULL,
\`amount\` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (\`id\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
/*
await queryFn(`
CREATE TABLE IF NOT EXISTS \`enum_event_type\` (
\`key\` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
\`value\` int(10) unsigned NOT NULL,
\`description\` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (\`key\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('BASIC', 0, 'BasicEvent: the basic event is the root of all further extending event types');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('VISIT_GRADIDO', 10, 'VisitGradidoEvent: if a user visits a gradido page without login or register');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('REGISTER', 20, 'RegisterEvent: the user presses the register button');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('REDEEM_REGISTER', 21, 'RedeemRegisterEvent: the user presses the register button initiated by the redeem link');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('INACTIVE_ACCOUNT', 22, 'InActiveAccountEvent: the systems create an inactive account during the register process');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('SEND_CONFIRMATION_EMAIL', 23, 'SendConfirmEmailEvent: the system send a confirmation email to the user during the register process');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('CONFIRM_EMAIL', 24, 'ConfirmEmailEvent: the user confirms his email during the register process');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('REGISTER_EMAIL_KLICKTIPP', 25, 'RegisterEmailKlickTippEvent: the system registers the confirmed email at klicktipp');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('LOGIN', 30, 'LoginEvent: the user presses the login button');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('REDEEM_LOGIN', 31, 'RedeemLoginEvent: the user presses the login button initiated by the redeem link');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('ACTIVATE_ACCOUNT', 32, 'ActivateAccountEvent: the system activates the users account during the first login process');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('PASSWORD_CHANGE', 33, 'PasswordChangeEvent: the user changes his password');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('TRANSACTION_SEND', 40, 'TransactionSendEvent: the user creates a transaction and sends it online');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('TRANSACTION_SEND_REDEEM', 41, 'TransactionSendRedeemEvent: the user creates a transaction and sends it per redeem link');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('TRANSACTION_REPEATE_REDEEM', 42, 'TransactionRepeateRedeemEvent: the user recreates a redeem link of a still open transaction');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('TRANSACTION_CREATION', 50, 'TransactionCreationEvent: the user receives a creation transaction for his confirmed contribution');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('TRANSACTION_RECEIVE', 51, 'TransactionReceiveEvent: the user receives a transaction from an other user and posts the amount on his account');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('TRANSACTION_RECEIVE_REDEEM', 52, 'TransactionReceiveRedeemEvent: the user activates the redeem link and receives the transaction and posts the amount on his account');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('CONTRIBUTION_CREATE', 60, 'ContributionCreateEvent: the user enters his contribution and asks for confirmation');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('CONTRIBUTION_CONFIRM', 61, 'ContributionConfirmEvent: the user confirms a contribution of an other user (for future multi confirmation from several users)');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('CONTRIBUTION_LINK_DEFINE', 70, 'ContributionLinkDefineEvent: the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium');`,
)
await queryFn(
`INSERT INTO \`enum_event_type\` (\`key\`, \`value\`, \`description\`) VALUES ('CONTRIBUTION_LINK_ACTIVATE_REDEEM', 71, 'ContributionLinkActivateRedeemEvent: the user activates a received contributionLink to create a contribution entry for the contributionLink');`,
)
*/
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
// write downgrade logic as parameter of queryFn
await queryFn(`DROP TABLE IF EXISTS \`event_protocol\`;`)
// await queryFn(`DROP TABLE IF EXISTS \`enum_event_type\`;`)
}

View File

@ -0,0 +1,130 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
/*
Move forward the creation date of the users by 1 or 2 hours,
for which there are transactions created before their account creation.
Because of a error by importing data from old db format into new, all older transactions balance_date
are 1 or 2 hours off
*/
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
/* generate raw mysql queries
const usersToMove = await queryFn(
`
SELECT u.id, u.created, t.balance_date
FROM \`users\` as u
LEFT JOIN \`transactions\` as t
ON t.user_id = u.id where t.balance_date < u.created
order by id
`
)
let downgradeQueries = ''
for(const id in usersToMove) {
const user = usersToMove[id]
const diff = (user.created - user.balance_date) / 1000
const correcture = diff < 3600 ? 1: 2
const correctedDate = new Date(user.created)
correctedDate.setHours(correctedDate.getHours() - correcture)
//console.log("%d, %s, %s, %s, %d", user.id, user.created, user.balance_date, diff, correcture)
console.log('await queryFn(`UPDATE \\`users\\` SET \\`created\\` = \'%s\' WHERE \\`id\\` = %d`)',
correctedDate.toISOString().slice(0, 19).replace('T', ' '),
user.id
)
downgradeQueries += 'await queryFn(`UPDATE \\`users\\` SET \\`created\\` = \''
downgradeQueries += user.created.toISOString().slice(0, 19).replace('T', ' ')
downgradeQueries += '\' WHERE \\`id\\` = '
downgradeQueries += user.id
downgradeQueries += '`)\n'
}
console.log('downgrade: \n%s', downgradeQueries)
*/
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-01-25 08:01:52' WHERE \`id\` = 179`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-05-26 10:21:57' WHERE \`id\` = 443`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-08 17:04:41' WHERE \`id\` = 490`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-12 20:07:17' WHERE \`id\` = 508`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-07-17 19:20:36' WHERE \`id\` = 621`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-11-22 16:31:48' WHERE \`id\` = 788`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-12-17 20:09:16' WHERE \`id\` = 825`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-01-26 13:09:35' WHERE \`id\` = 949`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-03-20 16:55:46' WHERE \`id\` = 1057`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 15:59:30' WHERE \`id\` = 1228`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:38:47' WHERE \`id\` = 1229`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:38:47' WHERE \`id\` = 1229`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:38:47' WHERE \`id\` = 1229`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:58:15' WHERE \`id\` = 1230`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:58:15' WHERE \`id\` = 1230`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 14:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-17 22:51:19' WHERE \`id\` = 1239`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-03 07:23:28' WHERE \`id\` = 1273`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-09 06:16:18' WHERE \`id\` = 1287`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-17 11:26:41' WHERE \`id\` = 1298`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 15:56:27' WHERE \`id\` = 1315`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 15:56:27' WHERE \`id\` = 1315`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 15:56:27' WHERE \`id\` = 1315`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 07:24:57' WHERE \`id\` = 1326`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 07:24:57' WHERE \`id\` = 1326`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-13 12:07:29' WHERE \`id\` = 1342`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-16 15:32:48' WHERE \`id\` = 1348`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-09-30 14:06:40' WHERE \`id\` = 1470`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-15 14:35:37' WHERE \`id\` = 1490`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 06:42:00' WHERE \`id\` = 1492`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 06:42:00' WHERE \`id\` = 1492`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-22 09:45:15' WHERE \`id\` = 1576`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-23 13:55:37' WHERE \`id\` = 1582`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 14:58:12' WHERE \`id\` = 1729`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 18:03:10' WHERE \`id\` = 1732`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 15:00:38' WHERE \`id\` = 1756`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 20:01:58' WHERE \`id\` = 1757`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-21 15:58:48' WHERE \`id\` = 1762`)
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-01-25 09:01:52' WHERE \`id\` = 179`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-05-26 11:21:57' WHERE \`id\` = 443`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-08 19:04:41' WHERE \`id\` = 490`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-06-12 22:07:17' WHERE \`id\` = 508`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-07-17 21:20:36' WHERE \`id\` = 621`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-11-22 17:31:48' WHERE \`id\` = 788`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2020-12-17 21:09:16' WHERE \`id\` = 825`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-01-26 14:09:35' WHERE \`id\` = 949`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-03-20 17:55:46' WHERE \`id\` = 1057`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 17:59:30' WHERE \`id\` = 1228`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:38:47' WHERE \`id\` = 1229`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:38:47' WHERE \`id\` = 1229`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:38:47' WHERE \`id\` = 1229`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:58:15' WHERE \`id\` = 1230`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-13 19:58:15' WHERE \`id\` = 1230`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-14 16:27:49' WHERE \`id\` = 1231`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-05-18 00:51:19' WHERE \`id\` = 1239`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-03 09:23:28' WHERE \`id\` = 1273`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-09 08:16:18' WHERE \`id\` = 1287`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-17 13:26:41' WHERE \`id\` = 1298`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 17:56:27' WHERE \`id\` = 1315`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 17:56:27' WHERE \`id\` = 1315`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-06-30 17:56:27' WHERE \`id\` = 1315`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 09:24:57' WHERE \`id\` = 1326`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-08 09:24:57' WHERE \`id\` = 1326`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-13 14:07:29' WHERE \`id\` = 1342`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-07-16 16:32:48' WHERE \`id\` = 1348`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-09-30 16:06:40' WHERE \`id\` = 1470`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-15 16:35:37' WHERE \`id\` = 1490`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 08:42:00' WHERE \`id\` = 1492`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-10-16 08:42:00' WHERE \`id\` = 1492`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-22 10:45:15' WHERE \`id\` = 1576`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2021-11-23 14:55:37' WHERE \`id\` = 1582`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 15:58:12' WHERE \`id\` = 1729`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-11 19:03:10' WHERE \`id\` = 1732`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 16:00:38' WHERE \`id\` = 1756`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-19 21:01:58' WHERE \`id\` = 1757`)
await queryFn(`UPDATE \`users\` SET \`created\` = '2022-01-21 16:58:48' WHERE \`id\` = 1762`)
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/* MIGRATION TO ADD EVENT_PROTOCOL
*
* This migration adds the table `event_protocol` in order to store all sorts of business event data
*/
/* 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(`
CREATE TABLE IF NOT EXISTS \`event_protocol\` (
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
\`type\` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
\`created_at\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
\`user_id\` int(10) unsigned NOT NULL,
\`x_user_id\` int(10) unsigned NULL DEFAULT NULL,
\`x_community_id\` int(10) unsigned NULL DEFAULT NULL,
\`transaction_id\` int(10) unsigned NULL DEFAULT NULL,
\`contribution_id\` int(10) unsigned NULL DEFAULT NULL,
\`amount\` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (\`id\`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
// write downgrade logic as parameter of queryFn
await queryFn(`DROP TABLE IF EXISTS \`event_protocol\`;`)
}

View File

@ -6,7 +6,7 @@
{{ $t('auth.left.gratitude') }}
</div>
<div class="position-absolute h2 text-white zindex1000 w-100 text-center mt-9">
{{ $t('auth.left.newCurrency') }}
{{ $t('auth.left.oneGratitude') }}
</div>
<img
src="/img/template/Blaetter.png"

View File

@ -12,10 +12,9 @@
"hasAccount": "Du hast schon einen Account?",
"hereLogin": "Hier Anmelden",
"learnMore": "Erfahre mehr …",
"newCurrency": "Die neue Währung",
"oneDignity": "Wir schenken einander und danken mit Gradido.",
"oneDonation": "Du bist ein Geschenk für die Gemeinschaft. 1000 Dank, weil du bei uns bist.",
"oneGratitude": "Die neue Währung. Für einander, für alle Menschen, für die Natur."
"oneGratitude": "Für einander, für alle Menschen, für die Natur."
},
"navbar": {
"aboutGradido": "Über Gradido"

View File

@ -12,10 +12,9 @@
"hasAccount": "You already have an account?",
"hereLogin": "Log in here",
"learnMore": "Learn more …",
"newCurrency": "The new currency",
"oneDignity": "We gift to each other and give thanks with Gradido.",
"oneDonation": "You are a gift for the community. 1000 thanks because you are with us.",
"oneGratitude": "The new currency. For each other, for all people, for nature."
"oneGratitude": "For each other, for all people, for nature."
},
"navbar": {
"aboutGradido": "About Gradido"