Merge branch 'master' into 2000-contribution-delete

This commit is contained in:
Hannes Heine 2022-07-19 12:25:12 +02:00 committed by GitHub
commit d5a2c24d7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 844 additions and 339 deletions

View File

@ -121,6 +121,19 @@ After generating a new version you should commit the changes. This will be the C
Note: The Changelog will be regenerated with all tags on release on the external builder tool, but will not be checked in there. The Changelog on the github release will therefore always be correct, on the repo it might be incorrect due to missing tags when executing the `yarn release` command. Note: The Changelog will be regenerated with all tags on release on the external builder tool, but will not be checked in there. The Changelog on the github release will therefore always be correct, on the repo it might be incorrect due to missing tags when executing the `yarn release` command.
## How the different .env work on deploy
Each component (frontend, admin, backend and database) has its own `.env` file. When running in development with docker and nginx you usually do not have to care about the `.env`. The defaults are set by the respective config file, found in the `src/config/` folder of each component. But if you have a local `.env`, the defaults set in the config are overwritten by the `.env`. If you do not use docker, you need the `.env` in the frontend and admin interface because nginx is not running in order to find the backend.
Each component has a `.env.dist` file. This file contains all environment variables used by the component and can be used as pattern. If you want to use a local `.env`, copy the `.env.dist` and adjust the variables accordingly.
Each component has a `.env.template` file. These files are very important on deploy.
There is one `.env.dist` in the `deployment/bare_metal/` folder. This `.env.dist` contains all variables used by the components, e.g. unites all `.env.dist` from the components. On deploy, we copy this `.env.dist` to `.env` and set all variables in this new file. The deploy script loads this variables and provides them by the `.env.templates` of each component, creating an `.env` for each component (see in `deployment/bare_metal/start.sh` the `envsubst`).
To avoid forgetting to update an existing `.env` in the `deployment/bare_metal/` folder when deploying, we have an environment version variable inside the codebase of each component. You should update this version, when environment variables must be changed or added on deploy. The code checks, that the environement version provided by the `.env` is the one expected by the codebase.
## Troubleshooting ## Troubleshooting
| Problem | Issue | Solution | Description | | Problem | Issue | Solution | Description |

View File

@ -1,57 +1,60 @@
CONFIG_VERSION=v8.2022-06-20 CONFIG_VERSION=v9.2022-07-07
# Server # Server
PORT=4000 PORT=4000
JWT_SECRET=secret123 JWT_SECRET=secret123
JWT_EXPIRES_IN=10m JWT_EXPIRES_IN=10m
GRAPHIQL=false GRAPHIQL=false
GDT_API_URL=https://gdt.gradido.net GDT_API_URL=https://gdt.gradido.net
# Database # Database
DB_HOST=localhost DB_HOST=localhost
DB_PORT=3306 DB_PORT=3306
DB_USER=root DB_USER=root
DB_PASSWORD= DB_PASSWORD=
DB_DATABASE=gradido_community DB_DATABASE=gradido_community
TYPEORM_LOGGING_RELATIVE_PATH=typeorm.backend.log TYPEORM_LOGGING_RELATIVE_PATH=typeorm.backend.log
# Klicktipp # Klicktipp
KLICKTIPP=false KLICKTIPP=false
KLICKTTIPP_API_URL=https://api.klicktipp.com KLICKTTIPP_API_URL=https://api.klicktipp.com
KLICKTIPP_USER=gradido_test KLICKTIPP_USER=gradido_test
KLICKTIPP_PASSWORD=secret321 KLICKTIPP_PASSWORD=secret321
KLICKTIPP_APIKEY_DE=SomeFakeKeyDE KLICKTIPP_APIKEY_DE=SomeFakeKeyDE
KLICKTIPP_APIKEY_EN=SomeFakeKeyEN KLICKTIPP_APIKEY_EN=SomeFakeKeyEN
# Community # Community
COMMUNITY_NAME=Gradido Entwicklung COMMUNITY_NAME=Gradido Entwicklung
COMMUNITY_URL=http://localhost/ COMMUNITY_URL=http://localhost/
COMMUNITY_REGISTER_URL=http://localhost/register COMMUNITY_REGISTER_URL=http://localhost/register
COMMUNITY_REDEEM_URL=http://localhost/redeem/{code} COMMUNITY_REDEEM_URL=http://localhost/redeem/{code}
COMMUNITY_REDEEM_CONTRIBUTION_URL=http://localhost/redeem/CL-{code} COMMUNITY_REDEEM_CONTRIBUTION_URL=http://localhost/redeem/CL-{code}
COMMUNITY_DESCRIPTION=Die lokale Entwicklungsumgebung von Gradido. COMMUNITY_DESCRIPTION=Die lokale Entwicklungsumgebung von Gradido.
# Login Server # Login Server
LOGIN_APP_SECRET=21ffbbc616fe LOGIN_APP_SECRET=21ffbbc616fe
LOGIN_SERVER_KEY=a51ef8ac7ef1abf162fb7a65261acd7a LOGIN_SERVER_KEY=a51ef8ac7ef1abf162fb7a65261acd7a
# EMail # EMail
EMAIL=false EMAIL=false
EMAIL_USERNAME=gradido_email EMAIL_USERNAME=gradido_email
EMAIL_SENDER=info@gradido.net EMAIL_SENDER=info@gradido.net
EMAIL_PASSWORD=xxx EMAIL_PASSWORD=xxx
EMAIL_SMTP_URL=gmail.com EMAIL_SMTP_URL=gmail.com
EMAIL_SMTP_PORT=587 EMAIL_SMTP_PORT=587
EMAIL_LINK_VERIFICATION=http://localhost/checkEmail/{optin}{code} EMAIL_LINK_VERIFICATION=http://localhost/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD=http://localhost/reset-password/{optin} EMAIL_LINK_SETPASSWORD=http://localhost/reset-password/{optin}
EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password
EMAIL_LINK_OVERVIEW=http://localhost/overview EMAIL_LINK_OVERVIEW=http://localhost/overview
EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_VALID_TIME=1440
EMAIL_CODE_REQUEST_TIME=10 EMAIL_CODE_REQUEST_TIME=10
# Webhook # Webhook
WEBHOOK_ELOPAGE_SECRET=secret WEBHOOK_ELOPAGE_SECRET=secret
# SET LOG LEVEL AS NEEDED IN YOUR .ENV # EventProtocol
# POSSIBLE VALUES: all | trace | debug | info | warn | error | fatal EVENT_PROTOCOL_DISABLED=false
# LOG_LEVEL=info
# SET LOG LEVEL AS NEEDED IN YOUR .ENV
# POSSIBLE VALUES: all | trace | debug | info | warn | error | fatal
# LOG_LEVEL=info

View File

@ -50,3 +50,6 @@ EMAIL_CODE_REQUEST_TIME=$EMAIL_CODE_REQUEST_TIME
# Webhook # Webhook
WEBHOOK_ELOPAGE_SECRET=$WEBHOOK_ELOPAGE_SECRET WEBHOOK_ELOPAGE_SECRET=$WEBHOOK_ELOPAGE_SECRET
# EventProtocol
EVENT_PROTOCOL_DISABLED=$EVENT_PROTOCOL_DISABLED

View File

@ -1,123 +1,129 @@
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env) // ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
import dotenv from 'dotenv' import dotenv from 'dotenv'
import Decimal from 'decimal.js-light' import Decimal from 'decimal.js-light'
dotenv.config() dotenv.config()
Decimal.set({ Decimal.set({
precision: 25, precision: 25,
rounding: Decimal.ROUND_HALF_UP, rounding: Decimal.ROUND_HALF_UP,
}) })
const constants = { const constants = {
DB_VERSION: '0042-update_transactions_for_blockchain', DB_VERSION: '0043-add_event_protocol_table',
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
LOG_LEVEL: process.env.LOG_LEVEL || 'info', LOG_LEVEL: process.env.LOG_LEVEL || 'info',
CONFIG_VERSION: { CONFIG_VERSION: {
DEFAULT: 'DEFAULT', DEFAULT: 'DEFAULT',
EXPECTED: 'v8.2022-06-20', EXPECTED: 'v9.2022-07-07',
CURRENT: '', CURRENT: '',
}, },
} }
const server = { const server = {
PORT: process.env.PORT || 4000, PORT: process.env.PORT || 4000,
JWT_SECRET: process.env.JWT_SECRET || 'secret123', JWT_SECRET: process.env.JWT_SECRET || 'secret123',
JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '10m', JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '10m',
GRAPHIQL: process.env.GRAPHIQL === 'true' || false, GRAPHIQL: process.env.GRAPHIQL === 'true' || false,
GDT_API_URL: process.env.GDT_API_URL || 'https://gdt.gradido.net', GDT_API_URL: process.env.GDT_API_URL || 'https://gdt.gradido.net',
PRODUCTION: process.env.NODE_ENV === 'production' || false, PRODUCTION: process.env.NODE_ENV === 'production' || false,
} }
const database = { const database = {
DB_HOST: process.env.DB_HOST || 'localhost', DB_HOST: process.env.DB_HOST || 'localhost',
DB_PORT: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 3306, DB_PORT: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 3306,
DB_USER: process.env.DB_USER || 'root', DB_USER: process.env.DB_USER || 'root',
DB_PASSWORD: process.env.DB_PASSWORD || '', DB_PASSWORD: process.env.DB_PASSWORD || '',
DB_DATABASE: process.env.DB_DATABASE || 'gradido_community', DB_DATABASE: process.env.DB_DATABASE || 'gradido_community',
TYPEORM_LOGGING_RELATIVE_PATH: process.env.TYPEORM_LOGGING_RELATIVE_PATH || 'typeorm.backend.log', TYPEORM_LOGGING_RELATIVE_PATH: process.env.TYPEORM_LOGGING_RELATIVE_PATH || 'typeorm.backend.log',
} }
const klicktipp = { const klicktipp = {
KLICKTIPP: process.env.KLICKTIPP === 'true' || false, KLICKTIPP: process.env.KLICKTIPP === 'true' || false,
KLICKTTIPP_API_URL: process.env.KLICKTIPP_API_URL || 'https://api.klicktipp.com', KLICKTTIPP_API_URL: process.env.KLICKTIPP_API_URL || 'https://api.klicktipp.com',
KLICKTIPP_USER: process.env.KLICKTIPP_USER || 'gradido_test', KLICKTIPP_USER: process.env.KLICKTIPP_USER || 'gradido_test',
KLICKTIPP_PASSWORD: process.env.KLICKTIPP_PASSWORD || 'secret321', KLICKTIPP_PASSWORD: process.env.KLICKTIPP_PASSWORD || 'secret321',
KLICKTIPP_APIKEY_DE: process.env.KLICKTIPP_APIKEY_DE || 'SomeFakeKeyDE', KLICKTIPP_APIKEY_DE: process.env.KLICKTIPP_APIKEY_DE || 'SomeFakeKeyDE',
KLICKTIPP_APIKEY_EN: process.env.KLICKTIPP_APIKEY_EN || 'SomeFakeKeyEN', KLICKTIPP_APIKEY_EN: process.env.KLICKTIPP_APIKEY_EN || 'SomeFakeKeyEN',
} }
const community = { const community = {
COMMUNITY_NAME: process.env.COMMUNITY_NAME || 'Gradido Entwicklung', COMMUNITY_NAME: process.env.COMMUNITY_NAME || 'Gradido Entwicklung',
COMMUNITY_URL: process.env.COMMUNITY_URL || 'http://localhost/', COMMUNITY_URL: process.env.COMMUNITY_URL || 'http://localhost/',
COMMUNITY_REGISTER_URL: process.env.COMMUNITY_REGISTER_URL || 'http://localhost/register', COMMUNITY_REGISTER_URL: process.env.COMMUNITY_REGISTER_URL || 'http://localhost/register',
COMMUNITY_REDEEM_URL: process.env.COMMUNITY_REDEEM_URL || 'http://localhost/redeem/{code}', COMMUNITY_REDEEM_URL: process.env.COMMUNITY_REDEEM_URL || 'http://localhost/redeem/{code}',
COMMUNITY_REDEEM_CONTRIBUTION_URL: COMMUNITY_REDEEM_CONTRIBUTION_URL:
process.env.COMMUNITY_REDEEM_CONTRIBUTION_URL || 'http://localhost/redeem/CL-{code}', process.env.COMMUNITY_REDEEM_CONTRIBUTION_URL || 'http://localhost/redeem/CL-{code}',
COMMUNITY_DESCRIPTION: COMMUNITY_DESCRIPTION:
process.env.COMMUNITY_DESCRIPTION || 'Die lokale Entwicklungsumgebung von Gradido.', process.env.COMMUNITY_DESCRIPTION || 'Die lokale Entwicklungsumgebung von Gradido.',
} }
const loginServer = { const loginServer = {
LOGIN_APP_SECRET: process.env.LOGIN_APP_SECRET || '21ffbbc616fe', LOGIN_APP_SECRET: process.env.LOGIN_APP_SECRET || '21ffbbc616fe',
LOGIN_SERVER_KEY: process.env.LOGIN_SERVER_KEY || 'a51ef8ac7ef1abf162fb7a65261acd7a', LOGIN_SERVER_KEY: process.env.LOGIN_SERVER_KEY || 'a51ef8ac7ef1abf162fb7a65261acd7a',
} }
const email = { const email = {
EMAIL: process.env.EMAIL === 'true' || false, EMAIL: process.env.EMAIL === 'true' || false,
EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'gradido_email', EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'gradido_email',
EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net', EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net',
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'xxx', EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || 'xxx',
EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'gmail.com', EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'gmail.com',
EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '587', EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '587',
EMAIL_LINK_VERIFICATION: EMAIL_LINK_VERIFICATION:
process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/checkEmail/{optin}{code}', process.env.EMAIL_LINK_VERIFICATION || 'http://localhost/checkEmail/{optin}{code}',
EMAIL_LINK_SETPASSWORD: EMAIL_LINK_SETPASSWORD:
process.env.EMAIL_LINK_SETPASSWORD || 'http://localhost/reset-password/{optin}', process.env.EMAIL_LINK_SETPASSWORD || 'http://localhost/reset-password/{optin}',
EMAIL_LINK_FORGOTPASSWORD: EMAIL_LINK_FORGOTPASSWORD:
process.env.EMAIL_LINK_FORGOTPASSWORD || 'http://localhost/forgot-password', process.env.EMAIL_LINK_FORGOTPASSWORD || 'http://localhost/forgot-password',
EMAIL_LINK_OVERVIEW: process.env.EMAIL_LINK_OVERVIEW || 'http://localhost/overview', EMAIL_LINK_OVERVIEW: process.env.EMAIL_LINK_OVERVIEW || 'http://localhost/overview',
// time in minutes a optin code is valid // time in minutes a optin code is valid
EMAIL_CODE_VALID_TIME: process.env.EMAIL_CODE_VALID_TIME EMAIL_CODE_VALID_TIME: process.env.EMAIL_CODE_VALID_TIME
? parseInt(process.env.EMAIL_CODE_VALID_TIME) || 1440 ? parseInt(process.env.EMAIL_CODE_VALID_TIME) || 1440
: 1440, : 1440,
// time in minutes that must pass to request a new optin code // time in minutes that must pass to request a new optin code
EMAIL_CODE_REQUEST_TIME: process.env.EMAIL_CODE_REQUEST_TIME EMAIL_CODE_REQUEST_TIME: process.env.EMAIL_CODE_REQUEST_TIME
? parseInt(process.env.EMAIL_CODE_REQUEST_TIME) || 10 ? parseInt(process.env.EMAIL_CODE_REQUEST_TIME) || 10
: 10, : 10,
} }
const webhook = { const webhook = {
// Elopage // Elopage
WEBHOOK_ELOPAGE_SECRET: process.env.WEBHOOK_ELOPAGE_SECRET || 'secret', WEBHOOK_ELOPAGE_SECRET: process.env.WEBHOOK_ELOPAGE_SECRET || 'secret',
} }
// This is needed by graphql-directive-auth const eventProtocol = {
process.env.APP_SECRET = server.JWT_SECRET // global switch to enable writing of EventProtocol-Entries
EVENT_PROTOCOL_DISABLED: process.env.EVENT_PROTOCOL_DISABLED === 'true' || false,
// Check config version }
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
if ( // This is needed by graphql-directive-auth
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes( process.env.APP_SECRET = server.JWT_SECRET
constants.CONFIG_VERSION.CURRENT,
) // Check config version
) { constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
throw new Error( if (
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`, ![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
) constants.CONFIG_VERSION.CURRENT,
} )
) {
const CONFIG = { throw new Error(
...constants, `Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
...server, )
...database, }
...klicktipp,
...community, const CONFIG = {
...email, ...constants,
...loginServer, ...server,
...webhook, ...database,
} ...klicktipp,
...community,
export default CONFIG ...email,
...loginServer,
...webhook,
...eventProtocol,
}
export default CONFIG

301
backend/src/event/Event.ts Normal file
View File

@ -0,0 +1,301 @@
import { EventProtocol } 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 class EventBasicTx extends EventBasicUserId {
xUserId: number
xCommunityId: number
transactionId: number
amount: decimal
}
export class EventBasicCt extends EventBasicUserId {
contributionId: number
amount: decimal
}
export class EventBasicRedeem extends EventBasicUserId {
transactionId?: number
contributionId?: number
}
export class EventVisitGradido extends EventBasic {}
export class EventRegister extends EventBasicUserId {}
export class EventRedeemRegister extends EventBasicRedeem {}
export class EventInactiveAccount extends EventBasicUserId {}
export class EventSendConfirmationEmail extends EventBasicUserId {}
export class EventConfirmationEmail extends EventBasicUserId {}
export class EventRegisterEmailKlicktipp extends EventBasicUserId {}
export class EventLogin extends EventBasicUserId {}
export class EventRedeemLogin extends EventBasicRedeem {}
export class EventActivateAccount extends EventBasicUserId {}
export class EventPasswordChange extends EventBasicUserId {}
export class EventTransactionSend extends EventBasicTx {}
export class EventTransactionSendRedeem extends EventBasicTx {}
export class EventTransactionRepeateRedeem extends EventBasicTx {}
export class EventTransactionCreation extends EventBasicUserId {
transactionId: number
amount: decimal
}
export class EventTransactionReceive extends EventBasicTx {}
export class EventTransactionReceiveRedeem extends EventBasicTx {}
export class EventContributionCreate extends EventBasicCt {}
export class EventContributionConfirm extends EventBasicCt {
xUserId: number
xCommunityId: number
}
export class EventContributionLinkDefine extends EventBasicCt {}
export class EventContributionLinkActivateRedeem extends EventBasicCt {}
export class Event {
constructor()
constructor(event?: EventProtocol) {
if (event) {
this.id = event.id
this.type = event.type
this.createdAt = event.createdAt
this.userId = event.userId
this.xUserId = event.xUserId
this.xCommunityId = event.xCommunityId
this.transactionId = event.transactionId
this.contributionId = event.contributionId
this.amount = event.amount
}
}
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 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 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 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.setByBasicTx(ev.userId, ev.xUserId, ev.xCommunityId, ev.transactionId, ev.amount)
this.type = EventProtocolType.TRANSACTION_SEND
return this
}
public setEventTransactionSendRedeem(ev: EventTransactionSendRedeem): Event {
this.setByBasicTx(ev.userId, ev.xUserId, ev.xCommunityId, ev.transactionId, ev.amount)
this.type = EventProtocolType.TRANSACTION_SEND_REDEEM
return this
}
public setEventTransactionRepeateRedeem(ev: EventTransactionRepeateRedeem): Event {
this.setByBasicTx(ev.userId, ev.xUserId, ev.xCommunityId, ev.transactionId, ev.amount)
this.type = EventProtocolType.TRANSACTION_REPEATE_REDEEM
return this
}
public setEventTransactionCreation(ev: EventTransactionCreation): Event {
this.setByBasicUser(ev.userId)
if (ev.transactionId) this.transactionId = ev.transactionId
if (ev.amount) this.amount = ev.amount
this.type = EventProtocolType.TRANSACTION_CREATION
return this
}
public setEventTransactionReceive(ev: EventTransactionReceive): Event {
this.setByBasicTx(ev.userId, ev.xUserId, ev.xCommunityId, ev.transactionId, ev.amount)
this.type = EventProtocolType.TRANSACTION_RECEIVE
return this
}
public setEventTransactionReceiveRedeem(ev: EventTransactionReceiveRedeem): Event {
this.setByBasicTx(ev.userId, ev.xUserId, ev.xCommunityId, ev.transactionId, ev.amount)
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 setEventContributionConfirm(ev: EventContributionConfirm): Event {
this.setByBasicCt(ev.userId, ev.contributionId, ev.amount)
if (ev.xUserId) this.xUserId = ev.xUserId
if (ev.xCommunityId) this.xCommunityId = ev.xCommunityId
this.type = EventProtocolType.CONTRIBUTION_CONFIRM
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
}
setByBasicUser(userId: number): Event {
this.setEventBasic()
this.userId = userId
return this
}
setByBasicTx(
userId: number,
xUserId?: number,
xCommunityId?: number,
transactionId?: number,
amount?: decimal,
): Event {
this.setByBasicUser(userId)
if (xUserId) this.xUserId = xUserId
if (xCommunityId) this.xCommunityId = xCommunityId
if (transactionId) this.transactionId = transactionId
if (amount) this.amount = amount
return this
}
setByBasicCt(userId: number, contributionId: number, amount?: decimal): Event {
this.setByBasicUser(userId)
if (contributionId) this.contributionId = contributionId
if (amount) this.amount = amount
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
}
setByEventTransactionCreation(event: EventTransactionCreation): Event {
this.type = event.type
this.createdAt = event.createdAt
this.userId = event.userId
this.transactionId = event.transactionId
this.amount = event.amount
return this
}
setByEventContributionConfirm(event: EventContributionConfirm): Event {
this.type = event.type
this.createdAt = event.createdAt
this.userId = event.userId
this.xUserId = event.xUserId
this.xCommunityId = event.xCommunityId
this.amount = event.amount
return this
}
id: number
type: string
createdAt: Date
userId: number
xUserId?: number
xCommunityId?: number
transactionId?: number
contributionId?: number
amount?: decimal
}

View File

@ -0,0 +1,39 @@
import { Event } from '@/event/Event'
import { backendLogger as logger } from '@/server/logger'
import { EventProtocol } from '@entity/EventProtocol'
import CONFIG from '@/config'
class EventProtocolEmitter {
/* }extends EventEmitter { */
private events: Event[]
public addEvent(event: Event) {
this.events.push(event)
}
public getEvents(): Event[] {
return this.events
}
public isDisabled() {
logger.info(`EventProtocol - isDisabled=${CONFIG.EVENT_PROTOCOL_DISABLED}`)
return CONFIG.EVENT_PROTOCOL_DISABLED === true
}
public async writeEvent(event: Event): Promise<void> {
if (!eventProtocol.isDisabled()) {
logger.info(`writeEvent(${JSON.stringify(event)})`)
const dbEvent = new EventProtocol()
dbEvent.type = event.type
dbEvent.createdAt = event.createdAt
dbEvent.userId = event.userId
if (event.xUserId) dbEvent.xUserId = event.xUserId
if (event.xCommunityId) dbEvent.xCommunityId = event.xCommunityId
if (event.contributionId) dbEvent.contributionId = event.contributionId
if (event.transactionId) dbEvent.transactionId = event.transactionId
if (event.amount) dbEvent.amount = event.amount
await dbEvent.save()
}
}
}
export const eventProtocol = new EventProtocolEmitter()

View File

@ -0,0 +1,24 @@
export enum EventProtocolType {
BASIC = 'BASIC',
VISIT_GRADIDO = 'VISIT_GRADIDO',
REGISTER = 'REGISTER',
REDEEM_REGISTER = 'REDEEM_REGISTER',
INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
SEND_CONFIRMATION_EMAIL = 'SEND_CONFIRMATION_EMAIL',
CONFIRM_EMAIL = 'CONFIRM_EMAIL',
REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
LOGIN = 'LOGIN',
REDEEM_LOGIN = 'REDEEM_LOGIN',
ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
PASSWORD_CHANGE = 'PASSWORD_CHANGE',
TRANSACTION_SEND = 'TRANSACTION_SEND',
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',
CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE',
CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM',
CONTRIBUTION_LINK_DEFINE = 'CONTRIBUTION_LINK_DEFINE',
CONTRIBUTION_LINK_ACTIVATE_REDEEM = 'CONTRIBUTION_LINK_ACTIVATE_REDEEM',
}

View File

@ -48,13 +48,13 @@ export class Contribution {
@ObjectType() @ObjectType()
export class ContributionListResult { export class ContributionListResult {
constructor(count: number, list: Contribution[]) { constructor(count: number, list: Contribution[]) {
this.linkCount = count this.contributionCount = count
this.linkList = list this.contributionList = list
} }
@Field(() => Int) @Field(() => Int)
linkCount: number contributionCount: number
@Field(() => [Contribution]) @Field(() => [Contribution])
linkList: Contribution[] contributionList: Contribution[]
} }

View File

@ -194,18 +194,21 @@ describe('ContributionResolver', () => {
).resolves.toEqual( ).resolves.toEqual(
expect.objectContaining({ expect.objectContaining({
data: { data: {
listContributions: expect.arrayContaining([ listContributions: {
expect.objectContaining({ contributionCount: 2,
id: expect.any(Number), contributionList: expect.arrayContaining([
memo: 'Herzlich Willkommen bei Gradido!', expect.objectContaining({
amount: '1000', id: expect.any(Number),
}), memo: 'Herzlich Willkommen bei Gradido!',
expect.objectContaining({ amount: '1000',
id: expect.any(Number), }),
memo: 'Test env contribution', expect.objectContaining({
amount: '100', id: expect.any(Number),
}), memo: 'Test env contribution',
]), amount: '100',
}),
]),
},
}, },
}), }),
) )
@ -227,13 +230,16 @@ describe('ContributionResolver', () => {
).resolves.toEqual( ).resolves.toEqual(
expect.objectContaining({ expect.objectContaining({
data: { data: {
listContributions: expect.arrayContaining([ listContributions: {
expect.objectContaining({ contributionCount: 1,
id: expect.any(Number), contributionList: expect.arrayContaining([
memo: 'Test env contribution', expect.objectContaining({
amount: '100', id: expect.any(Number),
}), memo: 'Test env contribution',
]), amount: '100',
}),
]),
},
}, },
}), }),
) )
@ -502,8 +508,8 @@ describe('ContributionResolver', () => {
expect.objectContaining({ expect.objectContaining({
data: { data: {
listAllContributions: { listAllContributions: {
linkCount: 2, contributionCount: 2,
linkList: expect.arrayContaining([ contributionList: expect.arrayContaining([
expect.objectContaining({ expect.objectContaining({
id: expect.any(Number), id: expect.any(Number),
memo: 'Herzlich Willkommen bei Gradido!', memo: 'Herzlich Willkommen bei Gradido!',

View File

@ -57,21 +57,21 @@ export class ContributionResolver {
} }
@Authorized([RIGHTS.LIST_CONTRIBUTIONS]) @Authorized([RIGHTS.LIST_CONTRIBUTIONS])
@Query(() => [Contribution]) @Query(() => ContributionListResult)
async listContributions( async listContributions(
@Args() @Args()
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
@Arg('filterConfirmed', () => Boolean) @Arg('filterConfirmed', () => Boolean)
filterConfirmed: boolean | null, filterConfirmed: boolean | null,
@Ctx() context: Context, @Ctx() context: Context,
): Promise<Contribution[]> { ): Promise<ContributionListResult> {
const user = getUser(context) const user = getUser(context)
const where: { const where: {
userId: number userId: number
confirmedBy?: FindOperator<number> | null confirmedBy?: FindOperator<number> | null
} = { userId: user.id } } = { userId: user.id }
if (filterConfirmed) where.confirmedBy = IsNull() if (filterConfirmed) where.confirmedBy = IsNull()
const contributions = await dbContribution.find({ const [contributions, count] = await dbContribution.findAndCount({
where, where,
order: { order: {
createdAt: order, createdAt: order,
@ -80,7 +80,10 @@ export class ContributionResolver {
skip: (currentPage - 1) * pageSize, skip: (currentPage - 1) * pageSize,
take: pageSize, take: pageSize,
}) })
return contributions.map((contribution) => new Contribution(contribution, new User(user))) return new ContributionListResult(
count,
contributions.map((contribution) => new Contribution(contribution, new User(user))),
)
} }
@Authorized([RIGHTS.LIST_ALL_CONTRIBUTIONS]) @Authorized([RIGHTS.LIST_ALL_CONTRIBUTIONS])

View File

@ -23,6 +23,14 @@ import { sendAccountMultiRegistrationEmail } from '@/mailer/sendAccountMultiRegi
import { klicktippSignIn } from '@/apis/KlicktippController' import { klicktippSignIn } from '@/apis/KlicktippController'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
import { hasElopageBuys } from '@/util/hasElopageBuys' import { hasElopageBuys } from '@/util/hasElopageBuys'
import { eventProtocol } from '@/event/EventProtocolEmitter'
import {
Event,
EventLogin,
EventRedeemRegister,
EventRegister,
EventSendConfirmationEmail,
} from '@/event/Event'
import { getUserCreation } from './util/creations' import { getUserCreation } from './util/creations'
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
@ -291,6 +299,9 @@ export class UserResolver {
key: 'token', key: 'token',
value: encode(dbUser.pubKey), value: encode(dbUser.pubKey),
}) })
const ev = new EventLogin()
ev.userId = user.id
eventProtocol.writeEvent(new Event().setEventLogin(ev))
logger.info('successful Login:' + user) logger.info('successful Login:' + user)
return user return user
} }
@ -368,6 +379,9 @@ export class UserResolver {
// const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1]) // const encryptedPrivkey = SecretKeyCryptographyEncrypt(keyPair[1], passwordHash[1])
const emailHash = getEmailHash(email) const emailHash = getEmailHash(email)
const eventRegister = new EventRegister()
const eventRedeemRegister = new EventRedeemRegister()
const eventSendConfirmEmail = new EventSendConfirmationEmail()
const dbUser = new DbUser() const dbUser = new DbUser()
dbUser.email = email dbUser.email = email
dbUser.firstName = firstName dbUser.firstName = firstName
@ -385,12 +399,14 @@ export class UserResolver {
logger.info('redeemCode found contributionLink=' + contributionLink) logger.info('redeemCode found contributionLink=' + contributionLink)
if (contributionLink) { if (contributionLink) {
dbUser.contributionLinkId = contributionLink.id dbUser.contributionLinkId = contributionLink.id
eventRedeemRegister.contributionId = contributionLink.id
} }
} else { } else {
const transactionLink = await dbTransactionLink.findOne({ code: redeemCode }) const transactionLink = await dbTransactionLink.findOne({ code: redeemCode })
logger.info('redeemCode found transactionLink=' + transactionLink) logger.info('redeemCode found transactionLink=' + transactionLink)
if (transactionLink) { if (transactionLink) {
dbUser.referrerId = transactionLink.userId dbUser.referrerId = transactionLink.userId
eventRedeemRegister.transactionId = transactionLink.id
} }
} }
} }
@ -401,6 +417,7 @@ export class UserResolver {
// loginUser.pubKey = keyPair[0] // loginUser.pubKey = keyPair[0]
// loginUser.privKey = encryptedPrivkey // loginUser.privKey = encryptedPrivkey
const event = new Event()
const queryRunner = getConnection().createQueryRunner() const queryRunner = getConnection().createQueryRunner()
await queryRunner.connect() await queryRunner.connect()
await queryRunner.startTransaction('READ UNCOMMITTED') await queryRunner.startTransaction('READ UNCOMMITTED')
@ -430,6 +447,9 @@ export class UserResolver {
duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME), duration: printTimeDuration(CONFIG.EMAIL_CODE_VALID_TIME),
}) })
logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`) logger.info(`sendAccountActivationEmail of ${firstName}.${lastName} to ${email}`)
eventSendConfirmEmail.userId = dbUser.id
eventProtocol.writeEvent(event.setEventSendConfirmationEmail(eventSendConfirmEmail))
/* uncomment this, when you need the activation link on the console */ /* uncomment this, when you need the activation link on the console */
// 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) {
@ -446,6 +466,14 @@ export class UserResolver {
} }
logger.info('createUser() successful...') logger.info('createUser() successful...')
if (redeemCode) {
eventRedeemRegister.userId = dbUser.id
eventProtocol.writeEvent(event.setEventRedeemRegister(eventRedeemRegister))
} else {
eventRegister.userId = dbUser.id
eventProtocol.writeEvent(event.setEventRegister(eventRegister))
}
return new User(dbUser) return new User(dbUser)
} }

View File

@ -185,9 +185,12 @@ export const listContributions = gql`
order: $order order: $order
filterConfirmed: $filterConfirmed filterConfirmed: $filterConfirmed
) { ) {
id contributionCount
amount contributionList {
memo id
amount
memo
}
} }
} }
` `
@ -195,8 +198,8 @@ export const listContributions = gql`
export const listAllContributions = ` export const listAllContributions = `
query ($currentPage: Int = 1, $pageSize: Int = 5, $order: Order = DESC) { query ($currentPage: Int = 1, $pageSize: Int = 5, $order: Order = DESC) {
listAllContributions(currentPage: $currentPage, pageSize: $pageSize, order: $order) { listAllContributions(currentPage: $currentPage, pageSize: $pageSize, order: $order) {
linkCount contributionCount
linkList { contributionList {
id id
firstName firstName
lastName lastName

View File

@ -0,0 +1,39 @@
import Decimal from 'decimal.js-light'
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
@Entity('event_protocol')
export class EventProtocol extends BaseEntity {
@PrimaryGeneratedColumn('increment', { unsigned: true })
id: number
@Column({ length: 100, nullable: false, collation: 'utf8mb4_unicode_ci' })
type: string
@Column({ name: 'created_at', type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
createdAt: Date
@Column({ name: 'user_id', unsigned: true, nullable: false })
userId: number
@Column({ name: 'x_user_id', unsigned: true, nullable: true })
xUserId: number
@Column({ name: 'x_community_id', unsigned: true, nullable: true })
xCommunityId: number
@Column({ name: 'transaction_id', unsigned: true, nullable: true })
transactionId: number
@Column({ name: 'contribution_id', unsigned: true, nullable: true })
contributionId: number
@Column({
type: 'decimal',
precision: 40,
scale: 20,
nullable: true,
transformer: DecimalTransformer,
})
amount: Decimal
}

View File

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

View File

@ -6,6 +6,7 @@ import { Transaction } from './Transaction'
import { TransactionLink } from './TransactionLink' import { TransactionLink } from './TransactionLink'
import { User } from './User' import { User } from './User'
import { Contribution } from './Contribution' import { Contribution } from './Contribution'
import { EventProtocol } from './EventProtocol'
export const entities = [ export const entities = [
Contribution, Contribution,
@ -16,4 +17,5 @@ export const entities = [
Transaction, Transaction,
TransactionLink, TransactionLink,
User, User,
EventProtocol,
] ]

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

@ -1,80 +1,84 @@
GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log
# start script # start script
DEPLOY_SEED_DATA=false DEPLOY_SEED_DATA=false
# nginx # nginx
NGINX_REWRITE_LEGACY_URLS=true NGINX_REWRITE_LEGACY_URLS=true
NGINX_SSL=true NGINX_SSL=true
NGINX_SERVER_NAME=stage1.gradido.net NGINX_SERVER_NAME=stage1.gradido.net
NGINX_SSL_CERTIFICATE=/etc/letsencrypt/live/stage1.gradido.net/fullchain.pem NGINX_SSL_CERTIFICATE=/etc/letsencrypt/live/stage1.gradido.net/fullchain.pem
NGINX_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/stage1.gradido.net/privkey.pem NGINX_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/stage1.gradido.net/privkey.pem
NGINX_SSL_DHPARAM=/etc/letsencrypt/ssl-dhparams.pem NGINX_SSL_DHPARAM=/etc/letsencrypt/ssl-dhparams.pem
NGINX_SSL_INCLUDE=/etc/letsencrypt/options-ssl-nginx.conf NGINX_SSL_INCLUDE=/etc/letsencrypt/options-ssl-nginx.conf
NGINX_UPDATE_PAGE_ROOT=/home/gradido/gradido/deployment/bare_metal/nginx/update-page NGINX_UPDATE_PAGE_ROOT=/home/gradido/gradido/deployment/bare_metal/nginx/update-page
# webhook # webhook
WEBHOOK_GITHUB_SECRET=secret WEBHOOK_GITHUB_SECRET=secret
WEBHOOK_GITHUB_BRANCH=master WEBHOOK_GITHUB_BRANCH=master
# community # community
COMMUNITY_NAME="Gradido Development Stage1" COMMUNITY_NAME="Gradido Development Stage1"
COMMUNITY_URL=https://stage1.gradido.net/ COMMUNITY_URL=https://stage1.gradido.net/
COMMUNITY_REGISTER_URL=https://stage1.gradido.net/register COMMUNITY_REGISTER_URL=https://stage1.gradido.net/register
COMMUNITY_REDEEM_URL=https://stage1.gradido.net/redeem/{code} COMMUNITY_REDEEM_URL=https://stage1.gradido.net/redeem/{code}
COMMUNITY_REDEEM_CONTRIBUTION_URL=https://stage1.gradido.net/redeem/CL-{code} COMMUNITY_REDEEM_CONTRIBUTION_URL=https://stage1.gradido.net/redeem/CL-{code}
COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community" COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community"
# backend # backend
BACKEND_CONFIG_VERSION=v8.2022-06-20 BACKEND_CONFIG_VERSION=v9.2022-07-07
JWT_EXPIRES_IN=10m JWT_EXPIRES_IN=10m
GDT_API_URL=https://gdt.gradido.net GDT_API_URL=https://gdt.gradido.net
TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log
KLICKTIPP=false KLICKTIPP=false
KLICKTIPP_USER= KLICKTIPP_USER=
KLICKTIPP_PASSWORD= KLICKTIPP_PASSWORD=
KLICKTIPP_APIKEY_DE= KLICKTIPP_APIKEY_DE=
KLICKTIPP_APIKEY_EN= KLICKTIPP_APIKEY_EN=
EMAIL=true EMAIL=true
EMAIL_USERNAME=peter@lustig.de EMAIL_USERNAME=peter@lustig.de
EMAIL_SENDER=peter@lustig.de EMAIL_SENDER=peter@lustig.de
EMAIL_PASSWORD=1234 EMAIL_PASSWORD=1234
EMAIL_SMTP_URL=smtp.lustig.de EMAIL_SMTP_URL=smtp.lustig.de
EMAIL_LINK_VERIFICATION=https://stage1.gradido.net/checkEmail/{optin}{code} EMAIL_LINK_VERIFICATION=https://stage1.gradido.net/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD=https://stage1.gradido.net/reset-password/{optin} EMAIL_LINK_SETPASSWORD=https://stage1.gradido.net/reset-password/{optin}
EMAIL_LINK_FORGOTPASSWORD=https://stage1.gradido.net/forgot-password EMAIL_LINK_FORGOTPASSWORD=https://stage1.gradido.net/forgot-password
EMAIL_LINK_OVERVIEW=https://stage1.gradido.net/overview EMAIL_LINK_OVERVIEW=https://stage1.gradido.net/overview
EMAIL_CODE_VALID_TIME=1440 EMAIL_CODE_VALID_TIME=1440
EMAIL_CODE_REQUEST_TIME=10 EMAIL_CODE_REQUEST_TIME=10
WEBHOOK_ELOPAGE_SECRET=secret WEBHOOK_ELOPAGE_SECRET=secret
# database # EventProtocol
DATABASE_CONFIG_VERSION=v1.2022-03-18 EVENT_PROTOCOL_DISABLED=false
# frontend
FRONTEND_CONFIG_VERSION=v2.2022-04-07 # database
DATABASE_CONFIG_VERSION=v1.2022-03-18
GRAPHQL_URI=https://stage1.gradido.net/graphql
ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token} # frontend
FRONTEND_CONFIG_VERSION=v2.2022-04-07
DEFAULT_PUBLISHER_ID=2896
GRAPHQL_URI=https://stage1.gradido.net/graphql
META_URL=http://localhost ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token}
META_TITLE_DE="Gradido Dein Dankbarkeitskonto"
META_TITLE_EN="Gradido - Your gratitude account" DEFAULT_PUBLISHER_ID=2896
META_DESCRIPTION_DE="Dankbarkeit ist die Währung der neuen Zeit. Immer mehr Menschen entfalten ihr Potenzial und gestalten eine gute Zukunft für alle."
META_DESCRIPTION_EN="Gratitude is the currency of the new age. More and more people are unleashing their potential and shaping a good future for all." META_URL=http://localhost
META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natürliche Ökonomie des Lebens, Ökonomie, Ökologie, Potenzialentfaltung, Schenken und Danken, Kreislauf des Lebens, Geldsystem" META_TITLE_DE="Gradido Dein Dankbarkeitskonto"
META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System" META_TITLE_EN="Gradido - Your gratitude account"
META_AUTHOR="Bernd Hückstädt - Gradido-Akademie" META_DESCRIPTION_DE="Dankbarkeit ist die Währung der neuen Zeit. Immer mehr Menschen entfalten ihr Potenzial und gestalten eine gute Zukunft für alle."
META_DESCRIPTION_EN="Gratitude is the currency of the new age. More and more people are unleashing their potential and shaping a good future for all."
# admin META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natürliche Ökonomie des Lebens, Ökonomie, Ökologie, Potenzialentfaltung, Schenken und Danken, Kreislauf des Lebens, Geldsystem"
ADMIN_CONFIG_VERSION=v1.2022-03-18 META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System"
META_AUTHOR="Bernd Hückstädt - Gradido-Akademie"
WALLET_AUTH_URL=https://stage1.gradido.net/authenticate?token={token}
# admin
ADMIN_CONFIG_VERSION=v1.2022-03-18
WALLET_AUTH_URL=https://stage1.gradido.net/authenticate?token={token}
WALLET_URL=https://stage1.gradido.net/login WALLET_URL=https://stage1.gradido.net/login

View File

@ -6,29 +6,30 @@ With the business event protocol the gradido application will capture and persis
The different event types will be defined as Enum. The following list is a first draft and will grow with further event types in the future. The different event types will be defined as Enum. The following list is a first draft and will grow with further event types in the future.
| EventType | Value | Description | | EventType | Value | Description |
| --------------------------- | ----- | ---------------------------------------------------------------------------------------------------- | | ----------------------------------- | ----- | ------------------------------------------------------------------------------------------------------ |
| BasicEvent | 0 | the basic event is the root of all further extending event types | | BasicEvent | 0 | the basic event is the root of all further extending event types |
| VisitGradidoEvent | 10 | if a user visits a gradido page without login or register | | VisitGradidoEvent | 10 | if a user visits a gradido page without login or register |
| RegisterEvent | 20 | the user presses the register button | | RegisterEvent | 20 | the user presses the register button |
| RedeemRegisterEvent | 21 | the user presses the register button initiated by the redeem link | | RedeemRegisterEvent | 21 | the user presses the register button initiated by the redeem link |
| InActiveAccountEvent | 22 | the systems create an inactive account during the register process | | InActiveAccountEvent | 22 | the systems create an inactive account during the register process |
| SendConfirmEmailEvent | 23 | the system send a confirmation email to the user during the register process | | SendConfirmEmailEvent | 23 | the system send a confirmation email to the user during the register process |
| ConfirmEmailEvent | 24 | the user confirms his email during the register process | | ConfirmEmailEvent | 24 | the user confirms his email during the register process |
| RegisterEmailKlickTippEvent | 25 | the system registers the confirmed email at klicktipp | | RegisterEmailKlickTippEvent | 25 | the system registers the confirmed email at klicktipp |
| LoginEvent | 30 | the user presses the login button | | LoginEvent | 30 | the user presses the login button |
| RedeemLoginEvent | 31 | the user presses the login button initiated by the redeem link | | RedeemLoginEvent | 31 | the user presses the login button initiated by the redeem link |
| ActivateAccountEvent | 32 | the system activates the users account during the first login process | | ActivateAccountEvent | 32 | the system activates the users account during the first login process |
| PasswordChangeEvent | 33 | the user changes his password | | PasswordChangeEvent | 33 | the user changes his password |
| TxSendEvent | 40 | the user creates a transaction and sends it online | | TransactionSendEvent | 40 | the user creates a transaction and sends it online |
| TxSendRedeemEvent | 41 | the user creates a transaction and sends it per redeem link | | TransactionSendRedeemEvent | 41 | the user creates a transaction and sends it per redeem link |
| TxRepeateRedeemEvent | 42 | the user recreates a redeem link of a still open transaction | | TransactionRepeateRedeemEvent | 42 | the user recreates a redeem link of a still open transaction |
| TxCreationEvent | 50 | the user receives a creation transaction for his confirmed contribution | | TransactionCreationEvent | 50 | the user receives a creation transaction for his confirmed contribution |
| TxReceiveEvent | 51 | the user receives a transaction from an other user and posts the amount on his account | | TransactionReceiveEvent | 51 | the user receives a transaction from an other user and posts the amount on his account |
| TxReceiveRedeemEvent | 52 | the user activates the redeem link and receives the transaction and posts the amount on his account | | TransactionReceiveRedeemEvent | 52 | the user activates the redeem link and receives the transaction and posts the amount on his account |
| ContribCreateEvent | 60 | the user enters his contribution and asks for confirmation | | ContributionCreateEvent | 60 | the user enters his contribution and asks for confirmation |
| ContribConfirmEvent | 61 | the user confirms a contribution of an other user (for future multi confirmation from several users) | | ContributionConfirmEvent | 61 | the user confirms a contribution of an other user (for future multi confirmation from several users) |
| | | | | ContributionLinkDefineEvent | 70 | the admin user defines a contributionLink, which could be send per Link/QR-Code on an other medium |
| ContributionLinkActivateRedeemEvent | 71 | the user activates a received contributionLink to create a contribution entry for the contributionLink |
## EventProtocol - Entity ## EventProtocol - Entity
@ -50,29 +51,30 @@ The business events will be stored in database in the new table `EventProtocol`.
The following table lists for each event type the mandatory attributes, which have to be initialized at event occurence and to be written in the database event protocol table: The following table lists for each event type the mandatory attributes, which have to be initialized at event occurence and to be written in the database event protocol table:
| EventType | id | type | createdAt | userID | XuserID | XCommunityID | transactionID | contribID | amount | | EventType | id | type | createdAt | userID | XuserID | XCommunityID | transactionID | contribID | amount |
| :-------------------------- | :-: | :--: | :-------: | :----: | :-----: | :----------: | :-----------: | :-------: | :----: | | :---------------------------------- | :-: | :--: | :-------: | :----: | :-----: | :----------: | :-----------: | :-------: | :----: |
| BasicEvent | x | x | x | | | | | | | | BasicEvent | x | x | x | | | | | | |
| VisitGradidoEvent | x | x | x | | | | | | | | VisitGradidoEvent | x | x | x | | | | | | |
| RegisterEvent | x | x | x | x | | | | | | | RegisterEvent | x | x | x | x | | | | | |
| RedeemRegisterEvent | x | x | x | x | | | | | | | RedeemRegisterEvent | x | x | x | x | | | (x) | (x) | |
| InActiveAccountEvent | x | x | x | x | | | | | | | InActiveAccountEvent | x | x | x | x | | | | | |
| SendConfirmEmailEvent | x | x | x | x | | | | | | | SendConfirmEmailEvent | x | x | x | x | | | | | |
| ConfirmEmailEvent | x | x | x | x | | | | | | | ConfirmEmailEvent | x | x | x | x | | | | | |
| RegisterEmailKlickTippEvent | x | x | x | x | | | | | | | RegisterEmailKlickTippEvent | x | x | x | x | | | | | |
| LoginEvent | x | x | x | x | | | | | | | LoginEvent | x | x | x | x | | | | | |
| RedeemLoginEvent | x | x | x | x | | | | | | | RedeemLoginEvent | x | x | x | x | | | (x) | (x) | |
| ActivateAccountEvent | x | x | x | x | | | | | | | ActivateAccountEvent | x | x | x | x | | | | | |
| PasswordChangeEvent | x | x | x | x | | | | | | | PasswordChangeEvent | x | x | x | x | | | | | |
| TxSendEvent | x | x | x | x | x | x | x | | x | | TransactionSendEvent | x | x | x | x | x | x | x | | x |
| TxSendRedeemEvent | x | x | x | x | x | x | x | | x | | TransactionSendRedeemEvent | x | x | x | x | x | x | x | | x |
| TxRepeateRedeemEvent | x | x | x | x | x | x | x | | x | | TransactionRepeateRedeemEvent | x | x | x | x | x | x | x | | x |
| TxCreationEvent | x | x | x | x | | | x | | x | | TransactionCreationEvent | x | x | x | x | | | x | | x |
| TxReceiveEvent | x | x | x | x | x | x | x | | x | | TransactionReceiveEvent | x | x | x | x | x | x | x | | x |
| TxReceiveRedeemEvent | x | x | x | x | x | x | x | | x | | TransactionReceiveRedeemEvent | x | x | x | x | x | x | x | | x |
| ContribCreateEvent | x | x | x | x | | | | x | | | ContributionCreateEvent | x | x | x | x | | | | x | x |
| ContribConfirmEvent | x | x | x | x | x | x | | x | | | ContributionConfirmEvent | x | x | x | x | x | x | | x | x |
| | | | | | | | | | | | ContributionLinkDefineEvent | x | x | x | x | | | | | x |
| ContributionLinkActivateRedeemEvent | x | x | x | x | | | | x | x |
## Event creation ## Event creation