Merge branch 'master' into federation_optimize_logging

This commit is contained in:
einhorn_b 2024-01-19 11:46:33 +01:00
commit 5cc7483136
67 changed files with 1340 additions and 251 deletions

View File

@ -131,7 +131,7 @@ Each component (frontend, admin, backend and database) has its own `.env` file.
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.
Each component has a `.env.template` file. These files are very important on deploy. They use COMMUNITY_HOST instead of different urls for different modules because in deploy using nginx is expected for routing incoming request to the correct module
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`).

View File

@ -1,4 +1,6 @@
GRAPHQL_URI=http://localhost:4000/graphql
WALLET_AUTH_URL=http://localhost/authenticate?token={token}
WALLET_URL=http://localhost/login
GRAPHQL_URL=http://localhost:4000
GRAPHQL_PATH=/graphql
WALLET_URL=http://localhost
WALLET_AUTH_PATH=/authenticate?token={token}
WALLET_LOGIN_PATH=/login
DEBUG_DISABLE_AUTH=false

View File

@ -1,6 +1,8 @@
CONFIG_VERSION=$ADMIN_CONFIG_VERSION
GRAPHQL_URI=$GRAPHQL_URI
WALLET_AUTH_URL=$WALLET_AUTH_URL
WALLET_URL=$WALLET_URL
DEBUG_DISABLE_AUTH=false
COMMUNITY_HOST=$COMMUNITY_HOST
URL_PROTOCOL=$URL_PROTOCOL
WALLET_AUTH_PATH=$WALLET_AUTH_PATH
WALLET_LOGIN_PATH=$WALLET_LOGIN_PATH
GRAPHQL_PATH=$GRAPHQL_PATH
DEBUG_DISABLE_AUTH=false

View File

@ -38,8 +38,8 @@ export default {
name: 'navbar',
methods: {
async logout() {
window.location.assign(CONFIG.WALLET_URL)
// window.location = CONFIG.WALLET_URL
window.location.assign(CONFIG.WALLET_LOGIN_URL)
// window.location = CONFIG.WALLET_LOGIN_URL
this.$store.dispatch('logout')
await this.$apollo.mutate({
mutation: logout,

View File

@ -7,37 +7,45 @@ const pkg = require('../../package')
const constants = {
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v1.2022-03-18',
EXPECTED: 'v2.2024-01-04',
CURRENT: '',
},
}
const version = {
APP_VERSION: pkg.version,
BUILD_COMMIT: process.env.BUILD_COMMIT || null,
BUILD_COMMIT: process.env.BUILD_COMMIT ?? null,
// self reference of `version.BUILD_COMMIT` is not possible at this point, hence the duplicate code
BUILD_COMMIT_SHORT: (process.env.BUILD_COMMIT || '0000000').slice(0, 7),
PORT: process.env.PORT || 8080,
BUILD_COMMIT_SHORT: (process.env.BUILD_COMMIT ?? '0000000').slice(0, 7),
PORT: process.env.PORT ?? 8080,
}
const environment = {
NODE_ENV: process.env.NODE_ENV,
DEBUG: process.env.NODE_ENV !== 'production' || false,
PRODUCTION: process.env.NODE_ENV === 'production' || false,
DEBUG: process.env.NODE_ENV !== 'production' ?? false,
PRODUCTION: process.env.NODE_ENV === 'production' ?? false,
}
const COMMUNITY_HOST = process.env.COMMUNITY_HOST ?? undefined
const URL_PROTOCOL = process.env.URL_PROTOCOL ?? 'http'
const COMMUNITY_URL =
COMMUNITY_HOST && URL_PROTOCOL ? URL_PROTOCOL + '://' + COMMUNITY_HOST : undefined
const WALLET_URL = process.env.WALLET_URL ?? COMMUNITY_URL ?? 'http://localhost'
const endpoints = {
GRAPHQL_URI: process.env.GRAPHQL_URI || 'http://localhost:4000/graphql',
WALLET_AUTH_URL: process.env.WALLET_AUTH_URL || 'http://localhost/authenticate?token={token}',
WALLET_URL: process.env.WALLET_URL || 'http://localhost/login',
GRAPHQL_URL:
(process.env.GRAPHQL_URL ?? COMMUNITY_URL ?? 'http://localhost:4000') +
process.env.GRAPHQL_PATH ?? '/graphql',
WALLET_AUTH_URL: WALLET_URL + (process.env.WALLET_AUTH_PATH ?? '/authenticate?token={token}'),
WALLET_LOGIN_URL: WALLET_URL + (process.env.WALLET_LOGIN_PATH ?? '/login'),
}
const debug = {
DEBUG_DISABLE_AUTH: process.env.DEBUG_DISABLE_AUTH === 'true' || false,
DEBUG_DISABLE_AUTH: process.env.DEBUG_DISABLE_AUTH === 'true' ?? false,
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,

View File

@ -16,7 +16,7 @@ const authLink = new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
store.dispatch('logout', null)
window.location.assign(CONFIG.WALLET_URL)
window.location.assign(CONFIG.WALLET_LOGIN_URL)
return response
}
const newToken = operation.getContext().response.headers.get('token')

View File

@ -28,9 +28,9 @@ DLT_CONNECTOR_URL=http://localhost:6010
# Community
COMMUNITY_NAME=Gradido Entwicklung
COMMUNITY_URL=http://localhost/
COMMUNITY_REGISTER_URL=http://localhost/register
COMMUNITY_REDEEM_URL=http://localhost/redeem/{code}
COMMUNITY_REDEEM_CONTRIBUTION_URL=http://localhost/redeem/CL-{code}
COMMUNITY_REGISTER_PATH=/register
COMMUNITY_REDEEM_PATH=/redeem/{code}
COMMUNITY_REDEEM_CONTRIBUTION_PATH=/redeem/CL-{code}
COMMUNITY_DESCRIPTION=Die lokale Entwicklungsumgebung von Gradido.
COMMUNITY_SUPPORT_MAIL=support@supportmail.com
@ -47,10 +47,10 @@ EMAIL_SENDER=info@gradido.net
EMAIL_PASSWORD=xxx
EMAIL_SMTP_URL=gmail.com
EMAIL_SMTP_PORT=587
EMAIL_LINK_VERIFICATION=http://localhost/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD=http://localhost/reset-password/{optin}
EMAIL_LINK_FORGOTPASSWORD=http://localhost/forgot-password
EMAIL_LINK_OVERVIEW=http://localhost/overview
EMAIL_LINK_VERIFICATION_PATH=/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD_PATH=/reset-password/{optin}
EMAIL_LINK_FORGOTPASSWORD_PATH=/forgot-password
EMAIL_LINK_OVERVIEW_PATH=/overview
EMAIL_CODE_VALID_TIME=1440
EMAIL_CODE_REQUEST_TIME=10

View File

@ -1,5 +1,5 @@
# must match the CONFIG_VERSION.EXPECTED definition in scr/config/index.ts
CONFIG_VERSION=v20.2023-09-19
CONFIG_VERSION=$BACKEND_CONFIG_VERSION
# Server
JWT_SECRET=$JWT_SECRET
@ -25,14 +25,15 @@ KLICKTIPP_APIKEY_EN=$KLICKTIPP_APIKEY_EN
# DltConnector
DLT_CONNECTOR=$DLT_CONNECTOR
DLT_CONNECTOR_URL=$DLT_CONNECTOR_URL
DLT_CONNECTOR_PORT=$DLT_CONNECTOR_PORT
# Community
COMMUNITY_HOST=$COMMUNITY_HOST
URL_PROTOCOL=$URL_PROTOCOL
COMMUNITY_NAME=$COMMUNITY_NAME
COMMUNITY_URL=$COMMUNITY_URL
COMMUNITY_REGISTER_URL=$COMMUNITY_REGISTER_URL
COMMUNITY_REDEEM_URL=$COMMUNITY_REDEEM_URL
COMMUNITY_REDEEM_CONTRIBUTION_URL=$COMMUNITY_REDEEM_CONTRIBUTION_URL
COMMUNITY_REGISTER_PATH=$COMMUNITY_REGISTER_PATH
COMMUNITY_REDEEM_PATH=$COMMUNITY_REDEEM_PATH
COMMUNITY_REDEEM_CONTRIBUTION_PATH=$COMMUNITY_REDEEM_CONTRIBUTION_PATH
COMMUNITY_DESCRIPTION=$COMMUNITY_DESCRIPTION
COMMUNITY_SUPPORT_MAIL=$COMMUNITY_SUPPORT_MAIL
@ -48,12 +49,12 @@ EMAIL_USERNAME=$EMAIL_USERNAME
EMAIL_SENDER=$EMAIL_SENDER
EMAIL_PASSWORD=$EMAIL_PASSWORD
EMAIL_SMTP_URL=$EMAIL_SMTP_URL
EMAIL_SMTP_PORT=587
EMAIL_LINK_VERIFICATION=$EMAIL_LINK_VERIFICATION
EMAIL_LINK_SETPASSWORD=$EMAIL_LINK_SETPASSWORD
EMAIL_LINK_FORGOTPASSWORD=$EMAIL_LINK_FORGOTPASSWORD
EMAIL_LINK_OVERVIEW=$EMAIL_LINK_OVERVIEW
EMAIL_CODE_VALID_TIME=$EMAIL_CODE_VALID_TIME
EMAIL_SMTP_PORT=$EMAIL_SMTP_PORT
EMAIL_LINK_VERIFICATION_PATH=$EMAIL_LINK_VERIFICATION_PATH
EMAIL_LINK_SETPASSWORD_PATH=$EMAIL_LINK_SETPASSWORD_PATH
EMAIL_LINK_FORGOTPASSWORD_PATH=$EMAIL_LINK_FORGOTPASSWORD_PATH
EMAIL_LINK_OVERVIEW_PATH=$EMAIL_LINK_OVERVIEW_PATH
EMAIL_CODE_VALID_TIME=$EMAIL_CODE_VALID_TIME_PATH
EMAIL_CODE_REQUEST_TIME=$EMAIL_CODE_REQUEST_TIME
# Webhook

View File

@ -19,7 +19,7 @@ const constants = {
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v20.2023-09-19',
EXPECTED: 'v21.2024-01-06',
CURRENT: '',
},
}
@ -51,18 +51,23 @@ const klicktipp = {
KLICKTIPP_APIKEY_EN: process.env.KLICKTIPP_APIKEY_EN ?? 'SomeFakeKeyEN',
}
const COMMUNITY_HOST = process.env.COMMUNITY_HOST ?? 'localhost'
const URL_PROTOCOL = process.env.URL_PROTOCOL ?? 'http'
const COMMUNITY_URL = process.env.COMMUNITY_URL ?? `${URL_PROTOCOL}://${COMMUNITY_HOST}`
const DLT_CONNECTOR_PORT = process.env.DLT_CONNECTOR_PORT ?? 6010
const dltConnector = {
DLT_CONNECTOR: process.env.DLT_CONNECTOR === 'true' || false,
DLT_CONNECTOR_URL: process.env.DLT_CONNECTOR_URL ?? 'http://localhost:6010',
DLT_CONNECTOR_URL: process.env.DLT_CONNECTOR_URL ?? `${COMMUNITY_URL}:${DLT_CONNECTOR_PORT}`,
}
const community = {
COMMUNITY_NAME: process.env.COMMUNITY_NAME ?? 'Gradido Entwicklung',
COMMUNITY_URL: process.env.COMMUNITY_URL ?? 'http://localhost/',
COMMUNITY_REGISTER_URL: process.env.COMMUNITY_REGISTER_URL ?? 'http://localhost/register',
COMMUNITY_REDEEM_URL: process.env.COMMUNITY_REDEEM_URL ?? 'http://localhost/redeem/{code}',
COMMUNITY_URL,
COMMUNITY_REGISTER_URL: COMMUNITY_URL + (process.env.COMMUNITY_REGISTER_PATH ?? '/register'),
COMMUNITY_REDEEM_URL: COMMUNITY_URL + (process.env.COMMUNITY_REDEEM_PATH ?? '/redeem/{code}'),
COMMUNITY_REDEEM_CONTRIBUTION_URL:
process.env.COMMUNITY_REDEEM_CONTRIBUTION_URL ?? 'http://localhost/redeem/CL-{code}',
COMMUNITY_URL + (process.env.COMMUNITY_REDEEM_CONTRIBUTION_PATH ?? '/redeem/CL-{code}'),
COMMUNITY_DESCRIPTION:
process.env.COMMUNITY_DESCRIPTION ?? 'Die lokale Entwicklungsumgebung von Gradido.',
COMMUNITY_SUPPORT_MAIL: process.env.COMMUNITY_SUPPORT_MAIL ?? 'support@supportmail.com',
@ -74,8 +79,8 @@ const loginServer = {
}
const email = {
EMAIL: process.env.EMAIL === 'true' || false,
EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || false,
EMAIL: process.env.EMAIL === 'true' ?? false,
EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' ?? false,
EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER ?? 'stage1@gradido.net',
EMAIL_USERNAME: process.env.EMAIL_USERNAME ?? '',
EMAIL_SENDER: process.env.EMAIL_SENDER ?? 'info@gradido.net',
@ -85,19 +90,19 @@ const email = {
// eslint-disable-next-line no-unneeded-ternary
EMAIL_TLS: process.env.EMAIL_TLS === 'false' ? false : true,
EMAIL_LINK_VERIFICATION:
process.env.EMAIL_LINK_VERIFICATION ?? 'http://localhost/checkEmail/{optin}{code}',
COMMUNITY_URL + (process.env.EMAIL_LINK_VERIFICATION_PATH ?? '/checkEmail/{optin}{code}'),
EMAIL_LINK_SETPASSWORD:
process.env.EMAIL_LINK_SETPASSWORD ?? 'http://localhost/reset-password/{optin}',
COMMUNITY_URL + (process.env.EMAIL_LINK_SETPASSWORD_PATH ?? '/reset-password/{optin}'),
EMAIL_LINK_FORGOTPASSWORD:
process.env.EMAIL_LINK_FORGOTPASSWORD ?? 'http://localhost/forgot-password',
EMAIL_LINK_OVERVIEW: process.env.EMAIL_LINK_OVERVIEW ?? 'http://localhost/overview',
COMMUNITY_URL + (process.env.EMAIL_LINK_FORGOTPASSWORD_PATH ?? '/forgot-password'),
EMAIL_LINK_OVERVIEW: COMMUNITY_URL + (process.env.EMAIL_LINK_OVERVIEW_PATH ?? '/overview'),
// time in minutes a optin code is valid
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,
// time in minutes that must pass to request a new optin code
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,
}
@ -124,9 +129,9 @@ if (
const federation = {
FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API ?? '1_0',
FEDERATION_VALIDATE_COMMUNITY_TIMER:
Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) || 60000,
Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) ?? 60000,
FEDERATION_XCOM_SENDCOINS_ENABLED:
process.env.FEDERATION_XCOM_SENDCOINS_ENABLED === 'true' || false,
process.env.FEDERATION_XCOM_SENDCOINS_ENABLED === 'true' ?? false,
// default value for community-uuid is equal uuid of stage-3
FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID:
process.env.FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID ?? '56a55482-909e-46a4-bfa2-cd025e894ebc',

View File

@ -9,6 +9,6 @@ block content
h2= t('emails.addedContributionMessage.readMessage')
div(class="p_content")= t('emails.addedContributionMessage.toSeeAndAnswerMessage')
a.button-3(href=`${communityURL}community/contributions`) #{t('emails.general.toAccount')}
a.button-3(href=`${communityURL}/community/contributions`) #{t('emails.general.toAccount')}
include ../includes/doNotReply.pug

View File

@ -1,7 +1,7 @@
//-
h2= t('emails.general.contributionDetails')
div(class="p_content")= t('emails.contribution.toSeeContributionsAndMessages')
a.button-3(href=`${communityURL}community/contributions`) #{t('emails.general.toAccount')}
a.button-3(href=`${communityURL}/community/contributions`) #{t('emails.general.toAccount')}
div(class="p_content")= t('emails.general.orCopyLink')
a.clink(href=`${communityURL}community/contributions`) #{`${communityURL}community/contributions`}
a.clink(href=`${communityURL}/community/contributions`) #{`${communityURL}/community/contributions`}

View File

@ -13,6 +13,6 @@ block content
br
= t('emails.general.detailsYouFindOnLinkToYourAccount')
a.button-3(href=`${communityURL}transactions`) #{t('emails.general.toAccount')}
a.button-3(href=`${communityURL}/transactions`) #{t('emails.general.toAccount')}
include ../includes/doNotReply.pug

View File

@ -9,7 +9,7 @@ block content
h2= t('emails.general.transactionDetails')
div(class="p_content")= t('emails.general.detailsYouFindOnLinkToYourAccount')
a.button-3(href=`${communityURL}transactions`) #{t('emails.general.toAccount')}
a.button-3(href=`${communityURL}/transactions`) #{t('emails.general.toAccount')}
include ../includes/doNotReply.pug

View File

@ -1,87 +1,99 @@
GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log
# Need to adjust!
COMMUNITY_NAME="Your community name"
COMMUNITY_DESCRIPTION="Short Description from your Community."
COMMUNITY_HOST=gddhost.tld
COMMUNITY_SUPPORT_MAIL=support@supportmail.com
# setup email account for sending gradido system messages to users
EMAIL=true
EMAIL_USERNAME=peter@lustig.de
EMAIL_SENDER=peter@lustig.de
EMAIL_PASSWORD=1234
EMAIL_SMTP_URL=smtp.lustig.de
EMAIL_SMTP_PORT=587
# how many minutes email verification code is valid
# also used for password reset code
EMAIL_CODE_VALID_TIME=1440
# how many minutes user must wait before he can request the email verification code again
# also used for password reset code
EMAIL_CODE_REQUEST_TIME=10
# Need to adjust by updates
# config versions
DATABASE_CONFIG_VERSION=v1.2022-03-18
BACKEND_CONFIG_VERSION=v21.2024-01-06
FRONTEND_CONFIG_VERSION=v5.2024-01-08
ADMIN_CONFIG_VERSION=v2.2024-01-04
FEDERATION_CONFIG_VERSION=v1.2023-01-09
FEDERATION_DHT_CONFIG_VERSION=v3.2023-04-26
FEDERATION_DHT_TOPIC=GRADIDO_HUB
# Need adjustments for test system
URL_PROTOCOL=https
# start script
# only for test server
DEPLOY_SEED_DATA=false
# test email
# if true all email will be send to EMAIL_TEST_RECEIVER instead of email address of user
EMAIL_TEST_MODUS=false
EMAIL_TEST_RECEIVER=test_team@gradido.net
# nginx
NGINX_REWRITE_LEGACY_URLS=true
NGINX_SSL=true
NGINX_SERVER_NAME=stage1.gradido.net
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_DHPARAM=/etc/letsencrypt/ssl-dhparams.pem
NGINX_SSL_INCLUDE=/etc/letsencrypt/options-ssl-nginx.conf
NGINX_UPDATE_PAGE_ROOT=/home/gradido/gradido/deployment/bare_metal/nginx/update-page
# Logging
LOG_LEVEL=INFO
GRADIDO_LOG_PATH=/home/gradido/gradido/deployment/bare_metal/log
TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log
# webhook
WEBHOOK_GITHUB_SECRET=secret
WEBHOOK_GITHUB_BRANCH=master
# community
COMMUNITY_NAME="Gradido Development Stage1"
COMMUNITY_URL=https://stage1.gradido.net/
COMMUNITY_REGISTER_URL=https://stage1.gradido.net/register
COMMUNITY_REDEEM_URL=https://stage1.gradido.net/redeem/{code}
COMMUNITY_REDEEM_CONTRIBUTION_URL=https://stage1.gradido.net/redeem/CL-{code}
COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community"
COMMUNITY_SUPPORT_MAIL=support@supportmail.com
# backend
BACKEND_CONFIG_VERSION=v17.2023-07-03
# frontend and admin paths, usually don't need changes
# used in nginx config and for links in emails
COMMUNITY_REGISTER_PATH=/register
COMMUNITY_REDEEM_PATH=/redeem/{code}
COMMUNITY_REDEEM_CONTRIBUTION_PATH=/redeem/CL-{code}
WALLET_LOGIN_PATH=/login
WALLET_AUTH_PATH=/authenticate?token={token}
EMAIL_LINK_VERIFICATION_PATH=/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD_PATH=/reset-password/{optin}
EMAIL_LINK_FORGOTPASSWORD_PATH=/forgot-password
EMAIL_LINK_OVERVIEW_PATH=/overview
ADMIN_AUTH_PATH=/admin/authenticate?token={token}
GRAPHQL_PATH=/graphql
# login expire time
JWT_EXPIRES_IN=10m
# Federation
# if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen
# on an hash created from this topic
# FEDERATION_DHT_TOPIC=GRADIDO_HUB
# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f
# the api port is the baseport, which will be added with the api-version, e.g. 1_0 = 5010
FEDERATION_COMMUNITY_API_PORT=5000
FEDERATION_VALIDATE_COMMUNITY_TIMER=60000
# comma separated list of api-versions, which cause starting several federation modules
FEDERATION_COMMUNITY_APIS=1_0,1_1
# externe gradido services (more added in future)
GDT_API_URL=https://gdt.gradido.net
TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log
# DLT-Connector (still in develop)
DLT_CONNECTOR=false
DLT_CONNECTOR_PORT=6010
# used for combining a newsletter on klicktipp with this gradido community
# if used, user will be subscribed on register and can unsubscribe in his account
KLICKTIPP=false
KLICKTIPP_USER=
KLICKTIPP_PASSWORD=
KLICKTIPP_APIKEY_DE=
KLICKTIPP_APIKEY_EN=
EMAIL=true
EMAIL_TEST_MODUS=false
EMAIL_TEST_RECEIVER=test_team@gradido.net
EMAIL_USERNAME=peter@lustig.de
EMAIL_SENDER=peter@lustig.de
EMAIL_PASSWORD=1234
EMAIL_SMTP_URL=smtp.lustig.de
EMAIL_LINK_VERIFICATION=https://stage1.gradido.net/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD=https://stage1.gradido.net/reset-password/{optin}
EMAIL_LINK_FORGOTPASSWORD=https://stage1.gradido.net/forgot-password
EMAIL_LINK_OVERVIEW=https://stage1.gradido.net/overview
EMAIL_CODE_VALID_TIME=1440
EMAIL_CODE_REQUEST_TIME=10
WEBHOOK_ELOPAGE_SECRET=secret
# Federation
FEDERATION_DHT_CONFIG_VERSION=v3.2023-04-26
# if you set the value of FEDERATION_DHT_TOPIC, the DHT hyperswarm will start to announce and listen
# on an hash created from this topic
# FEDERATION_DHT_TOPIC=GRADIDO_HUB
# FEDERATION_DHT_SEED=64ebcb0e3ad547848fef4197c6e2332f
FEDERATION_COMMUNITY_URL=http://stage1.gradido.net
# the api port is the baseport, which will be added with the api-version, e.g. 1_0 = 5010
FEDERATION_COMMUNITY_API_PORT=5000
FEDERATION_CONFIG_VERSION=v1.2023-01-09
# comma separated list of api-versions, which cause starting several federation modules
FEDERATION_COMMUNITY_APIS=1_0,1_1
# database
DATABASE_CONFIG_VERSION=v1.2022-03-18
# frontend
FRONTEND_CONFIG_VERSION=v4.2022-12-20
GRAPHQL_URI=https://stage1.gradido.net/graphql
ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token}
DEFAULT_PUBLISHER_ID=2896
META_URL=http://localhost
# Meta data in frontend pages, important when shared via facebook or twitter or for search engines
META_TITLE_DE="Gradido Dein Dankbarkeitskonto"
META_TITLE_EN="Gradido - Your gratitude account"
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."
@ -90,8 +102,17 @@ META_KEYWORDS_DE="Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natü
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"
# admin
ADMIN_CONFIG_VERSION=v1.2022-03-18
# update page shown while updating gradido
# page will be fed with status changes
NGINX_UPDATE_PAGE_ROOT=/home/gradido/gradido/deployment/bare_metal/nginx/update-page
# NGINX SSL Setup with certbot
# will be generated by start.sh with $COMMUNITY_HOST, only need to setup manual if setup differ from default
#NGINX_SSL_CERTIFICATE=/etc/letsencrypt/live/gddhost.tld/fullchain.pem
#NGINX_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/gddhost.tld/privkey.pem
NGINX_SSL_DHPARAM=/etc/letsencrypt/ssl-dhparams.pem
NGINX_SSL_INCLUDE=/etc/letsencrypt/options-ssl-nginx.conf
WALLET_AUTH_URL=https://stage1.gradido.net/authenticate?token={token}
WALLET_URL=https://stage1.gradido.net/login
# LEGACY
NGINX_REWRITE_LEGACY_URLS=false
DEFAULT_PUBLISHER_ID=2896
WEBHOOK_ELOPAGE_SECRET=secret

View File

@ -0,0 +1,118 @@
<mxfile host="65bd71144e">
<diagram id="q0c1bfTOSmR5BH1DDDeU" name="Page-1">
<mxGraphModel dx="874" dy="1662" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" value="Physical Server" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="15" y="40" width="410" height="420" as="geometry"/>
</mxCell>
<mxCell id="3" value="mariadb&lt;br&gt;port: 3306" style="shape=datastore;whiteSpace=wrap;html=1;" vertex="1" parent="2">
<mxGeometry x="165" y="350" width="60" height="60" as="geometry"/>
</mxCell>
<mxCell id="4" value="nginx" style="swimlane;whiteSpace=wrap;html=1;startSize=23;" vertex="1" parent="2">
<mxGeometry x="60" y="20" width="230" height="110" as="geometry"/>
</mxCell>
<mxCell id="5" value="port 80: redirect to port 443" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="4">
<mxGeometry x="-5" y="30" width="170" height="30" as="geometry"/>
</mxCell>
<mxCell id="6" value="port 443: using ssl encryption" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="4">
<mxGeometry x="-5" y="60" width="180" height="30" as="geometry"/>
</mxCell>
<mxCell id="28" value="" style="endArrow=classic;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="4" target="15">
<mxGeometry relative="1" as="geometry">
<mxPoint x="45" y="110" as="sourcePoint"/>
<mxPoint x="145" y="90" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="29" value="/&lt;span style=&quot;color: rgb(36, 41, 46); font-family: &amp;quot;Droid Sans Mono&amp;quot;, &amp;quot;monospace&amp;quot;, monospace; font-size: 14px;&quot;&gt;graphql&lt;/span&gt;" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;" connectable="0" vertex="1" parent="28">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="41" style="edgeStyle=none;html=1;" edge="1" parent="2" source="15">
<mxGeometry relative="1" as="geometry">
<mxPoint x="185" y="350" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="15" value="Backend&lt;br&gt;runs on port: 4000" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="2">
<mxGeometry x="10" y="170" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="17" value="frontend&lt;br&gt;static files server&lt;br&gt;port: 3000" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="2">
<mxGeometry x="125" y="210" width="120" height="40" as="geometry"/>
</mxCell>
<mxCell id="18" value="admin&lt;br&gt;static files server&lt;br&gt;port: 8080" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="2">
<mxGeometry x="290" y="190" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="40" style="edgeStyle=none;html=1;" edge="1" parent="2" source="19">
<mxGeometry relative="1" as="geometry">
<mxPoint x="165" y="370" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="19" value="dht-node&lt;br&gt;use his own system" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="2">
<mxGeometry x="10" y="320" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="39" style="edgeStyle=none;html=1;entryX=0.85;entryY=0.05;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="2" source="21" target="3">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="21" value="Federation&lt;br&gt;on port per version" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="2">
<mxGeometry x="215" y="260" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="30" value="/&lt;br&gt;" style="endArrow=classic;html=1;" edge="1" parent="2" target="17">
<mxGeometry relative="1" as="geometry">
<mxPoint x="155" y="130" as="sourcePoint"/>
<mxPoint x="305" y="150" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="31" value="/" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;" connectable="0" vertex="1" parent="30">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="9" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="13" target="2">
<mxGeometry relative="1" as="geometry">
<mxPoint x="210" y="20" as="sourcePoint"/>
<mxPoint x="500" y="290" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="10" value="Extern Request&lt;br&gt;- webbrowser with frontend running&lt;br&gt;- webbrowser with admin running&lt;br&gt;- backend&lt;br&gt;- federation" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;" connectable="0" vertex="1" parent="9">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="11" value="Source" style="edgeLabel;resizable=0;html=1;align=left;verticalAlign=bottom;" connectable="0" vertex="1" parent="9">
<mxGeometry x="-1" relative="1" as="geometry">
<mxPoint y="20" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="12" value="Target" style="edgeLabel;resizable=0;html=1;align=right;verticalAlign=bottom;" connectable="0" vertex="1" parent="9">
<mxGeometry x="1" relative="1" as="geometry"/>
</mxCell>
<mxCell id="13" value="Internet" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="100" y="-180" width="120" height="80" as="geometry"/>
</mxCell>
<mxCell id="33" value="" style="endArrow=classic;html=1;" edge="1" parent="1" target="18">
<mxGeometry relative="1" as="geometry">
<mxPoint x="270" y="170" as="sourcePoint"/>
<mxPoint x="470" y="50" as="targetPoint"/>
<Array as="points">
<mxPoint x="300" y="200"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="34" value="/admin" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;" connectable="0" vertex="1" parent="33">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="35" value="" style="endArrow=classic;html=1;entryX=0.633;entryY=-0.017;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" target="21">
<mxGeometry relative="1" as="geometry">
<mxPoint x="220" y="170" as="sourcePoint"/>
<mxPoint x="470" y="170" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="36" value="/api/VERSION" style="edgeLabel;resizable=0;html=1;align=center;verticalAlign=middle;" connectable="0" vertex="1" parent="35">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="43" value="Legende:" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;fontStyle=1;fontSize=14;" vertex="1" parent="1">
<mxGeometry x="550" y="130" width="80" height="30" as="geometry"/>
</mxCell>
<mxCell id="44" value="&lt;i style=&quot;&quot;&gt;Node JS&amp;nbsp;&lt;br&gt;Express Server&lt;/i&gt;" style="shape=process;whiteSpace=wrap;html=1;backgroundOutline=1;" vertex="1" parent="1">
<mxGeometry x="540" y="170" width="120" height="60" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -1,16 +1,16 @@
server {
if ($host = $NGINX_SERVER_NAME) {
if ($host = $COMMUNITY_HOST) {
return 301 https://$host$request_uri;
}
server_name $NGINX_SERVER_NAME;
server_name $COMMUNITY_HOST;
listen 80;
listen [::]:80;
return 404;
}
server {
server_name $NGINX_SERVER_NAME;
server_name $COMMUNITY_HOST;
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;

View File

@ -1,5 +1,5 @@
server {
server_name $NGINX_SERVER_NAME;
server_name $COMMUNITY_HOST;
listen 80;
listen [::]:80;

View File

@ -1,16 +1,16 @@
server {
if ($host = $NGINX_SERVER_NAME) {
if ($host = $COMMUNITY_HOST) {
return 301 https://$host$request_uri;
}
server_name $NGINX_SERVER_NAME;
server_name $COMMUNITY_HOST;
listen 80;
listen [::]:80;
return 404;
}
server {
server_name $NGINX_SERVER_NAME;
server_name $COMMUNITY_HOST;
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;

View File

@ -1,6 +1,6 @@
server {
server_name _;
server_name $COMMUNITY_HOST;
listen 80;
listen [::]:80;

View File

@ -10,12 +10,17 @@ PROJECT_ROOT=$SCRIPT_DIR/../..
NGINX_CONFIG_DIR=$SCRIPT_DIR/nginx/sites-available
set +o allexport
# enable nvm
export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# NOTE: all config values will be in process.env when starting
# the services and will therefore take precedence over the .env
# We have to load the backend .env to get DB_USERNAME, DB_PASSWORD AND JWT_SECRET
# and the dht-node .env to get FEDERATION_DHT_SEED
export_var(){
export $1=$(grep -v '^#' $PROJECT_ROOT/backend/.env | grep -e "$1" | sed -e 's/.*=//')
export $1=$(grep -v '^#' $PROJECT_ROOT/dht-node/.env | grep -e "$1" | sed -e 's/.*=//')
}
if [ -f "$PROJECT_ROOT/backend/.env" ]; then
@ -24,6 +29,10 @@ if [ -f "$PROJECT_ROOT/backend/.env" ]; then
export_var 'JWT_SECRET'
fi
if [ -f "$PROJECT_ROOT/dht-node/.env" ]; then
export_var 'FEDERATION_DHT_SEED'
fi
# Load .env or .env.dist if not present
if [ -f "$SCRIPT_DIR/.env" ]; then
set -o allexport
@ -35,6 +44,14 @@ else
set +o allexport
fi
# set env variables dynamic if not already set in .env or .env.dist
: ${NGINX_SSL_CERTIFICATE:=/etc/letsencrypt/live/$COMMUNITY_HOST/fullchain.pem}
: ${NGINX_SSL_CERTIFICATE_KEY:=/etc/letsencrypt/live/$COMMUNITY_HOST/privkey.pem}
# export env variables
export NGINX_SSL_CERTIFICATE
export NGINX_SSL_CERTIFICATE_KEY
# lock start
if [ -f $LOCK_FILE ] ; then
echo "Already building!"
@ -54,8 +71,7 @@ exec > >(tee -a $UPDATE_HTML) 2>&1
# configure nginx for the update-page
echo 'Configuring nginx to serve the update-page' >> $UPDATE_HTML
rm /etc/nginx/sites-enabled/gradido.conf
ln -s /etc/nginx/sites-available/update-page.conf /etc/nginx/sites-enabled/
ln -sf $SCRIPT_DIR/nginx/sites-available/update-page.conf $SCRIPT_DIR/nginx/sites-enabled/default
sudo /etc/init.d/nginx restart
# stop all services
@ -100,9 +116,9 @@ export FEDERATION_NGINX_CONF=$(< $NGINX_CONFIG_DIR/gradido-federation.conf.locat
# *** 3rd generate gradido nginx config including federation modules per api-version
echo 'Generate new gradido nginx config' >> $UPDATE_HTML
case "$NGINX_SSL" in
true) TEMPLATE_FILE="gradido.conf.ssl.template" ;;
*) TEMPLATE_FILE="gradido.conf.template" ;;
case "$URL_PROTOCOL" in
'https') TEMPLATE_FILE="gradido.conf.ssl.template" ;;
*) TEMPLATE_FILE="gradido.conf.template" ;;
esac
envsubst '$FEDERATION_NGINX_CONF' < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/gradido.conf.tmp
unset FEDERATION_NGINX_CONF
@ -112,9 +128,9 @@ rm $NGINX_CONFIG_DIR/gradido-federation.conf.locations
# Generate update-page.conf from template
echo 'Generate new update-page nginx config' >> $UPDATE_HTML
case "$NGINX_SSL" in
true) TEMPLATE_FILE="update-page.conf.ssl.template" ;;
*) TEMPLATE_FILE="update-page.conf.template" ;;
case "$URL_PROTOCOL" in
'https') TEMPLATE_FILE="update-page.conf.ssl.template" ;;
*) TEMPLATE_FILE="update-page.conf.template" ;;
esac
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/update-page.conf
@ -177,8 +193,7 @@ if [ "$DEPLOY_SEED_DATA" = "true" ]; then
fi
# TODO maybe handle this differently?
export NODE_ENV=production
pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 save
# Install & build frontend
echo 'Updating frontend' >> $UPDATE_HTML
@ -189,8 +204,6 @@ yarn install
yarn build
# TODO maybe handle this differently?
export NODE_ENV=production
pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 save
# Install & build admin
echo 'Updating admin' >> $UPDATE_HTML
@ -201,8 +214,6 @@ yarn install
yarn build
# TODO maybe handle this differently?
export NODE_ENV=production
pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 save
# Install & build dht-node
echo 'Updating dht-node' >> $UPDATE_HTML
@ -213,15 +224,6 @@ yarn install
yarn build
# TODO maybe handle this differently?
export NODE_ENV=production
if [ ! -z $FEDERATION_DHT_TOPIC ]; then
pm2 start --name gradido-dht-node "yarn --cwd $PROJECT_ROOT/dht-node start" -l $GRADIDO_LOG_PATH/pm2.dht-node.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 save
else
echo "=====================================================================" >> $UPDATE_HTML
echo "WARNING: FEDERATION_DHT_TOPIC not configured. DHT-Node not started..." >> $UPDATE_HTML
echo "=====================================================================" >> $UPDATE_HTML
fi
# Install & build federation
echo 'Updating federation' >> $UPDATE_HTML
@ -233,6 +235,20 @@ yarn build
# TODO maybe handle this differently?
export NODE_ENV=production
# start after building all to use up less ressources
pm2 start --name gradido-backend "yarn --cwd $PROJECT_ROOT/backend start" -l $GRADIDO_LOG_PATH/pm2.backend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 start --name gradido-frontend "yarn --cwd $PROJECT_ROOT/frontend start" -l $GRADIDO_LOG_PATH/pm2.frontend.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 start --name gradido-admin "yarn --cwd $PROJECT_ROOT/admin start" -l $GRADIDO_LOG_PATH/pm2.admin.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 save
if [ ! -z $FEDERATION_DHT_TOPIC ]; then
pm2 start --name gradido-dht-node "yarn --cwd $PROJECT_ROOT/dht-node start" -l $GRADIDO_LOG_PATH/pm2.dht-node.$TODAY.log --log-date-format 'YYYY-MM-DD HH:mm:ss.SSS'
pm2 save
else
echo "=====================================================================" >> $UPDATE_HTML
echo "WARNING: FEDERATION_DHT_TOPIC not configured. DHT-Node not started..." >> $UPDATE_HTML
echo "=====================================================================" >> $UPDATE_HTML
fi
# set FEDERATION_PORT from FEDERATION_COMMUNITY_APIS
IFS="," read -a API_ARRAY <<< $FEDERATION_COMMUNITY_APIS
for api in "${API_ARRAY[@]}"
@ -254,13 +270,9 @@ do
pm2 save
done
# let nginx showing gradido
echo 'Configuring nginx to serve gradido again' >> $UPDATE_HTML
ln -s /etc/nginx/sites-available/gradido.conf /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/update-page.conf
ln -sf $SCRIPT_DIR/nginx/sites-available/gradido.conf $SCRIPT_DIR/nginx/sites-enabled/default
sudo /etc/init.d/nginx restart
# keep the update log

View File

@ -0,0 +1,124 @@
# Setup on Hetzner Cloud Server
Suggested minimal Plan: CX41
4x vCPU, 16 GB Ram, 160 GB Disk Space, 20.71 € per month (04.01.2024)
Suggested OS:
Debian 12
For Hetzner Cloud Server a cloud config can be attached, which will be run before first start
https://community.hetzner.com/tutorials/basic-cloud-config/de
https://cloudinit.readthedocs.io/en/latest/reference/examples.html
You can use our [cloudConfig.yaml](./cloudConfig.yaml) but you must insert you own ssh public key,
like this:
```yaml
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAkLGbzbG7KIGfkssKJBkc/0EVAzQ/8vjvVHzNdxhK8J yourname
```
## After Setup Cloud Server with cloudConfig.yaml
### setup your domain pointing on server ip address
### login to your new server as root
```bash
ssh -i /path/to/privKey root@gddhost.tld
```
### Change default shell
```bash
chsh -s /bin/bash
chsh -s /bin/bash gradido
```
### Set password for user `gradido`
```bash
$ passwd gradido
# enter new password twice
```
### Switch to the new user
```bash
su gradido
```
### Test authentication via SSH
If you logout from the server you can test authentication:
```bash
$ ssh -i /path/to/privKey gradido@gddhost.tld
# This should log you in and allow you to use sudo commands, which will require the user's password
```
### Disable password root login via ssh
```bash
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org
sudo sed -i -e '/^\(#\|\)PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i '$a AllowUsers gradido' /etc/ssh/sshd_config
sudo /etc/init.d/ssh restart
```
### Test SSH Access only, no root ssh access
```bash
$ ssh gradido@gddhost.tld
# Will result in in either a passphrase request for your key or the message 'Permission denied (publickey)'
$ ssh -i /path/to/privKey root@gddhost.tld
# Will result in 'Permission denied (publickey)'
$ ssh -i /path/to/privKey gradido@gddhost.tld
# Will succeed after entering the correct keys passphrase (if any)
```
### Install `Gradido` code
```bash
cd ~
git clone https://github.com/gradido/gradido.git
```
### Adjust the values in `.env`
***!!! Attention !!!***
*Don't forget this step!
All your following installations in `install.sh` will fail!*
*Notes:*
- *`;` cannot be part of any value!*
- *The GitHub secret is created on GitHub in Settings -> Webhooks.*
#### Create `.env` and set values
```bash
cd ~/gradido/deployment/bare_metal
cp .env.dist .env
nano .env
# adjust values accordingly
```
### Run `install.sh`
***!!! Attention !!!***
Don't use this script if you have custom config in /etc/nginx/conf.d, because this script
will remove it and ln ../bare_metal/nginx/conf.d
```bash
cd ~/gradido/deployment/hetzner_cloud
sudo ./install.sh
```
### Make yourself admin
- Create an account on your new gradido instance
- Click the link in the activation email
- go back to your ssh session and copy this command
```bash
sudo mysql -D gradido_community -e "insert into user_roles(user_id, role) values((select id from users order by id desc limit 1), 'ADMIN');"
```
- it will make last registered user admin
- login with you newly created user
- if you has a link to `Admin Area` it worked and you are admin

View File

@ -0,0 +1,46 @@
#cloud-config
users:
- name: gradido
groups: users, admin, sudo
sudo: ALL=(ALL) NOPASSWD:/etc/init.d/nginx start,/etc/init.d/nginx stop,/etc/init.d/nginx restart
shell: /bin/bash
ssh_authorized_keys:
- <public_ssh_key>
packages:
- fail2ban
- ufw
- git
- mariadb-server
- nginx
- curl
- build-essential
- gnupg
- certbot
- python3-certbot-nginx
- logrotate
- automysqlbackup
- expect
package_update: true
package_upgrade: true
runcmd:
- printf "[sshd]\nenabled = true\nbanaction = iptables-multiport" > /etc/fail2ban/jail.local
- systemctl enable fail2ban
- ufw allow OpenSSH
- ufw allow http
- ufw allow https
- ufw enable
- sed -i -e '/^\(#\|\)PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)KbdInteractiveAuthentication/s/^.*$/KbdInteractiveAuthentication no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)ChallengeResponseAuthentication/s/^.*$/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)MaxAuthTries/s/^.*$/MaxAuthTries 3/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)AllowTcpForwarding/s/^.*$/AllowTcpForwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)X11Forwarding/s/^.*$/X11Forwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)AllowAgentForwarding/s/^.*$/AllowAgentForwarding no/' /etc/ssh/sshd_config
- sed -i -e '/^\(#\|\)AuthorizedKeysFile/s/^.*$/AuthorizedKeysFile .ssh\/authorized_keys/' /etc/ssh/sshd_config
- sed -i '$a AllowUsers gradido root' /etc/ssh/sshd_config
- reboot

View File

@ -0,0 +1,38 @@
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
# `yarn` creates output in `/tmp` directory. This output is generated whenever `yarn start` is called.
# This is especially problematic on staging systems where instable versions are automatically deployed which can lead to an ever restarting,
# hence generating a lot of yarn output.
# the following hourly cron clean the /tmp folder
0 * * * * find /tmp -name "yarn--*" -exec rm -r {} \; > /dev/null
# cronjob for a daily db backup at 3:00am
0 3 * * * ~/gradido/deployment/bare_metal/backup.sh
# cronjob for a daily logfile clearance at 3:15
# remove all log files older than 30 days
15 3 * * * ~/gradido/deployment/bare_metal/removeLogFiles.sh

View File

@ -0,0 +1,153 @@
#!/bin/bash
# Note: This is needed - since there is Summer-Time included in the default server Setup - UTC is REQUIRED for production data
timedatectl set-timezone UTC
timedatectl set-ntp on
apt purge ntp
systemctl start systemd-timesyncd
set -o allexport
SCRIPT_PATH=$(realpath ../bare_metal)
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
LOCAL_SCRIPT_PATH=$(realpath $0)
LOCAL_SCRIPT_DIR=$(dirname $LOCAL_SCRIPT_PATH)
PROJECT_ROOT=$SCRIPT_DIR/..
set +o allexport
# If install.sh will be called more than once
# We have to load the backend .env to get DB_USERNAME, DB_PASSWORD AND JWT_SECRET
# and the dht-node .env to get FEDERATION_DHT_SEED
export_var(){
export $1=$(grep -v '^#' $PROJECT_ROOT/backend/.env | grep -e "$1" | sed -e 's/.*=//')
export $1=$(grep -v '^#' $PROJECT_ROOT/dht-node/.env | grep -e "$1" | sed -e 's/.*=//')
}
if [ -f "$PROJECT_ROOT/backend/.env" ]; then
export_var 'DB_USER'
export_var 'DB_PASSWORD'
export_var 'JWT_SECRET'
fi
if [ -f "$PROJECT_ROOT/dht-node/.env" ]; then
export_var 'FEDERATION_DHT_SEED'
fi
# Load .env or .env.dist if not present
# NOTE: all config values will be in process.env when starting
# the services and will therefore take precedence over the .env
if [ -f "$SCRIPT_PATH/.env" ]; then
set -o allexport
source $SCRIPT_PATH/.env
set +o allexport
else
set -o allexport
source $SCRIPT_PATH/.env.dist
set +o allexport
fi
# Configure git
git config pull.ff only
# Secure mysql https://gist.github.com/Mins/4602864
SECURE_MYSQL=$(expect -c "
set timeout 10
spawn mysql_secure_installation
expect \"Enter current password for root (enter for none):\"
send \"\r\"
expect \"Switch to unix_socket authentication:\"
send \"Y\r\"
expect \"Change the root password?\"
send \"n\r\"
expect \"Remove anonymous users?\"
send \"y\r\"
expect \"Disallow root login remotely?\"
send \"y\r\"
expect \"Remove test database and access to it?\"
send \"y\r\"
expect \"Reload privilege tables now?\"
send \"y\r\"
expect eof
")
echo "$SECURE_MYSQL"
# Configure nginx
rm /etc/nginx/sites-enabled/default
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_PATH/nginx/sites-available/gradido.conf.template > $SCRIPT_PATH/nginx/sites-available/gradido.conf
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_PATH/nginx/sites-available/update-page.conf.template > $SCRIPT_PATH/nginx/sites-available/update-page.conf
mkdir $SCRIPT_PATH/nginx/sites-enabled
ln -s $SCRIPT_PATH/nginx/sites-available/update-page.conf $SCRIPT_PATH/nginx/sites-enabled/default
ln -s $SCRIPT_PATH/nginx/sites-enabled/default /etc/nginx/sites-enabled
ln -s $SCRIPT_PATH/nginx/common /etc/nginx/
rmdir /etc/nginx/conf.d
ln -s $SCRIPT_PATH/nginx/conf.d /etc/nginx/
# setup https with certbot
certbot certonly --nginx --non-interactive --agree-tos --domains $COMMUNITY_HOST --email $COMMUNITY_SUPPORT_MAIL
# Install node 16. with nvm, with nodesource is depracted
sudo -u gradido bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash'
# Close and reopen your terminal to start using nvm or run the following to use it now:
sudo -u gradido bash -c 'export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"'
sudo -u gradido bash -c '. $HOME/.nvm/nvm.sh && nvm install 16' # first installed version will be set to default automatic
# Install yarn
sudo -u gradido bash -c '. $HOME/.nvm/nvm.sh && npm i -g yarn'
# Install pm2
sudo -u gradido bash -c '. $HOME/.nvm/nvm.sh && npm i -g pm2 && pm2 startup'
# Install logrotate
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $SCRIPT_PATH/logrotate/gradido.conf.template > $SCRIPT_PATH/logrotate/gradido.conf
cp $SCRIPT_PATH/logrotate/gradido.conf /etc/logrotate.d/gradido.conf
# create db user
export DB_USER=gradido
# create a new password only if it not already exist
if [ -z "${DB_PASSWORD}" ]; then
export DB_PASSWORD=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
fi
mysql <<EOFMYSQL
CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$DB_USER'@'localhost';
FLUSH PRIVILEGES;
EOFMYSQL
# Configure database
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/database/.env.template > $PROJECT_ROOT/database/.env
# Configure backend
export JWT_SECRET=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo);
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/backend/.env.template > $PROJECT_ROOT/backend/.env
# Configure frontend
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/frontend/.env.template > $PROJECT_ROOT/frontend/.env
# Configure admin
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/admin/.env.template > $PROJECT_ROOT/admin/.env
# Configure dht-node
export FEDERATION_DHT_SEED=$(< /dev/urandom tr -dc a-f0-9 | head -c 32;echo);
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/dht-node/.env.template > $PROJECT_ROOT/dht-node/.env
# Configure federation
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $PROJECT_ROOT/federation/.env.template > $PROJECT_ROOT/federation/.env
# set all created or modified files back to belonging to gradido
chown -R gradido:gradido $PROJECT_ROOT
# create cronjob to delete yarn output in /tmp and for making backups regulary
sudo -u gradido crontab < $LOCAL_SCRIPT_DIR/crontabs.txt
# Start gradido
# Note: on first startup some errors will occur - nothing serious
sudo -u gradido $SCRIPT_PATH/start.sh

View File

@ -21,4 +21,6 @@ FEDERATION_DHT_TOPIC=$FEDERATION_DHT_TOPIC
FEDERATION_DHT_SEED=$FEDERATION_DHT_SEED
FEDERATION_COMMUNITY_URL=$FEDERATION_COMMUNITY_URL
# comma separated values, which apis should be announced
FEDERATION_COMMUNITY_APIS=$FEDERATION_COMMUNITY_APIS
FEDERATION_COMMUNITY_APIS=$FEDERATION_COMMUNITY_APIS
COMMUNITY_HOST=$COMMUNITY_HOST
URL_PROTOCOL=$URL_PROTOCOL

View File

@ -7,7 +7,7 @@ const constants = {
DB_VERSION: '0080-fill_linked_user_gradidoId_of_contributions',
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v4.2024-01-17',
@ -16,34 +16,38 @@ const constants = {
}
const server = {
PRODUCTION: process.env.NODE_ENV === 'production' || false,
PRODUCTION: process.env.NODE_ENV === 'production' ?? false,
}
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_USER: process.env.DB_USER || 'root',
DB_PASSWORD: process.env.DB_PASSWORD || '',
DB_DATABASE: process.env.DB_DATABASE || 'gradido_community',
DB_USER: process.env.DB_USER ?? 'root',
DB_PASSWORD: process.env.DB_PASSWORD ?? '',
DB_DATABASE: process.env.DB_DATABASE ?? 'gradido_community',
TYPEORM_LOGGING_RELATIVE_PATH:
process.env.TYPEORM_LOGGING_RELATIVE_PATH || 'typeorm.dht-node.log',
process.env.TYPEORM_LOGGING_RELATIVE_PATH ?? 'typeorm.dht-node.log',
}
const community = {
COMMUNITY_NAME: process.env.COMMUNITY_NAME || 'Gradido Entwicklung',
COMMUNITY_NAME: process.env.COMMUNITY_NAME ?? 'Gradido Entwicklung',
COMMUNITY_DESCRIPTION:
process.env.COMMUNITY_DESCRIPTION || 'Gradido-Community einer lokalen Entwicklungsumgebung.',
process.env.COMMUNITY_DESCRIPTION ?? 'Gradido-Community einer lokalen Entwicklungsumgebung.',
}
const COMMUNITY_HOST = process.env.COMMUNITY_HOST ?? 'localhost'
const URL_PROTOCOL = process.env.URL_PROTOCOL ?? 'http'
const COMMUNITY_URL = process.env.COMMUNITY_URL ?? `${URL_PROTOCOL}://${COMMUNITY_HOST}`
const federation = {
FEDERATION_DHT_TOPIC: process.env.FEDERATION_DHT_TOPIC || 'GRADIDO_HUB',
FEDERATION_DHT_SEED: process.env.FEDERATION_DHT_SEED || null,
FEDERATION_COMMUNITY_URL: process.env.FEDERATION_COMMUNITY_URL || 'http://localhost',
FEDERATION_COMMUNITY_APIS: process.env.FEDERATION_COMMUNITY_APIS || '1_0',
FEDERATION_DHT_TOPIC: process.env.FEDERATION_DHT_TOPIC ?? 'GRADIDO_HUB',
FEDERATION_DHT_SEED: process.env.FEDERATION_DHT_SEED ?? null,
FEDERATION_COMMUNITY_URL: process.env.FEDERATION_COMMUNITY_URL ?? COMMUNITY_URL,
FEDERATION_COMMUNITY_APIS: process.env.FEDERATION_COMMUNITY_APIS ?? '1_0',
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,

View File

@ -6,7 +6,7 @@ module.exports = {
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
coverageThreshold: {
global: {
lines: 71,
lines: 66,
},
},
setupFiles: ['<rootDir>/test/testSetup.ts'],

View File

@ -6,7 +6,7 @@ const constants = {
LOG4JS_CONFIG: 'log4js-config.json',
DB_VERSION: '0003-refactor_transaction_recipe',
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v4.2023-09-12',
@ -15,7 +15,7 @@ const constants = {
}
const server = {
PRODUCTION: process.env.NODE_ENV === 'production' || false,
PRODUCTION: process.env.NODE_ENV === 'production' ?? false,
}
const database = {
@ -35,11 +35,11 @@ const iota = {
}
const dltConnector = {
DLT_CONNECTOR_PORT: process.env.DLT_CONNECTOR_PORT || 6010,
DLT_CONNECTOR_PORT: process.env.DLT_CONNECTOR_PORT ?? 6010,
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,

View File

@ -1,5 +1,8 @@
import { Field, Message } from 'protobufjs'
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
import { TransactionError } from '@/graphql/model/TransactionError'
import { logger } from '@/logging/logger'
import { LogError } from '@/server/LogError'
import { SignatureMap } from './SignatureMap'
@ -41,4 +44,16 @@ export class GradidoTransaction extends Message<GradidoTransaction> {
}
return sigPair[0]
}
getTransactionBody(): TransactionBody {
try {
return TransactionBody.decode(new Uint8Array(this.bodyBytes))
} catch (error) {
logger.error('error decoding body from gradido transaction: %s', error)
throw new TransactionError(
TransactionErrorType.PROTO_DECODE_ERROR,
'cannot decode body from gradido transaction',
)
}
}
}

View File

@ -9,8 +9,8 @@ import { TransactionResult } from '@model/TransactionResult'
import { CommunityRepository } from '@/data/Community.repository'
import { AddCommunityContext } from '@/interactions/backendToDb/community/AddCommunity.context'
import { logger } from '@/logging/logger'
import { LogError } from '@/server/LogError'
import { logger } from '@/server/logger'
import { iotaTopicFromCommunityUUID } from '@/utils/typeConverter'
@Resolver()

View File

@ -4,6 +4,9 @@ import { TransactionDraft } from '@input/TransactionDraft'
import { TransactionRepository } from '@/data/Transaction.repository'
import { CreateTransactionRecipeContext } from '@/interactions/backendToDb/transaction/CreateTransationRecipe.context'
import { BackendTransactionLoggingView } from '@/logging/BackendTransactionLogging.view'
import { logger } from '@/logging/logger'
import { TransactionLoggingView } from '@/logging/TransactionLogging.view'
import { LogError } from '@/server/LogError'
import { TransactionError } from '../model/TransactionError'
@ -35,8 +38,13 @@ export class TransactionResolver {
}
const backendTransaction = transactionRecipe.backendTransactions[0]
backendTransaction.transactionId = transactionRecipe.id
logger.debug(
'store backendTransaction',
new BackendTransactionLoggingView(backendTransaction),
)
await backendTransaction.save()
} else {
logger.debug('store transaction recipe', new TransactionLoggingView(transactionRecipe))
// we can store the transaction and with that automatic the backend transaction
await transactionRecipe.save()
}

View File

@ -10,7 +10,6 @@ export const schema = async (): Promise<GraphQLSchema> => {
return buildSchema({
resolvers: [TransactionResolver, CommunityResolver],
scalarsMap: [{ type: Decimal, scalar: DecimalScalar }],
emitSchemaFile: true,
validate: {
validationError: { target: false },
skipMissingProperties: true,

View File

@ -3,7 +3,8 @@ import { Community } from '@entity/Community'
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
import { TransactionError } from '@/graphql/model/TransactionError'
import { logger } from '@/server/logger'
import { CommunityLoggingView } from '@/logging/CommunityLogging.view'
import { logger } from '@/logging/logger'
export abstract class CommunityRole {
protected self: Community
@ -17,9 +18,11 @@ export abstract class CommunityRole {
this.self.foreign = communityDraft.foreign
}
public store(): Promise<Community> {
public async store(): Promise<Community> {
try {
return this.self.save()
const community = await this.self.save()
logger.debug('store community', new CommunityLoggingView(community))
return community
} catch (error) {
logger.error('error saving new community into db: %s', error)
throw new TransactionError(TransactionErrorType.DB_ERROR, 'error saving community into db')

View File

@ -8,7 +8,8 @@ import { Mnemonic } from '@/data/Mnemonic'
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
import { TransactionError } from '@/graphql/model/TransactionError'
import { logger } from '@/server/logger'
import { CommunityLoggingView } from '@/logging/CommunityLogging.view'
import { logger } from '@/logging/logger'
import { getDataSource } from '@/typeorm/DataSource'
import { CreateTransactionRecipeContext } from '../transaction/CreateTransationRecipe.context'
@ -38,6 +39,7 @@ export class HomeCommunityRole extends CommunityRole {
return await getDataSource().transaction(async (transactionalEntityManager) => {
const community = await transactionalEntityManager.save(this.self)
await transactionalEntityManager.save(this.transactionRecipe)
logger.debug('store home community', new CommunityLoggingView(community))
return community
})
} catch (error) {

View File

@ -0,0 +1,49 @@
import util from 'util'
import { Decimal } from 'decimal.js-light'
import { Timestamp } from '@/data/proto/3_3/Timestamp'
import { TimestampSeconds } from '@/data/proto/3_3/TimestampSeconds'
import { timestampSecondsToDate, timestampToDate } from '@/utils/typeConverter'
export abstract class AbstractLoggingView {
protected bufferStringFormat: BufferEncoding = 'hex'
// This function gets called automatically when JSON.stringify() is called on this class instance
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public abstract toJSON(): any
public toString(): string {
return JSON.stringify(this.toJSON(), null, 2)
}
// called form console.log or log4js logging functions
[util.inspect.custom](): string {
return this.toString()
}
protected dateToString(date: Date | undefined | null): string | undefined {
if (date) {
return date.toISOString()
}
return undefined
}
protected decimalToString(number: Decimal | undefined | null): string | undefined {
if (number) {
return number.toString()
}
return undefined
}
protected timestampSecondsToDateString(timestamp: TimestampSeconds): string | undefined {
if (timestamp && timestamp.seconds) {
return timestampSecondsToDate(timestamp).toISOString()
}
}
protected timestampToDateString(timestamp: Timestamp): string | undefined {
if (timestamp && (timestamp.seconds || timestamp.nanoSeconds)) {
return timestampToDate(timestamp).toISOString()
}
}
}

View File

@ -0,0 +1,29 @@
import { Account } from '@entity/Account'
import { AddressType } from '@/data/proto/3_3/enum/AddressType'
import { getEnumValue } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
import { UserLoggingView } from './UserLogging.view'
export class AccountLoggingView extends AbstractLoggingView {
public constructor(private account: Account) {
super()
}
public toJSON() {
return {
id: this.account.id,
user: this.account.user ? new UserLoggingView(this.account.user).toJSON() : null,
derivationIndex: this.account.derivationIndex,
derive2pubkey: this.account.derive2Pubkey.toString(this.bufferStringFormat),
type: getEnumValue(AddressType, this.account.type),
createdAt: this.dateToString(this.account.createdAt),
confirmedAt: this.dateToString(this.account.confirmedAt),
balanceOnConfirmation: this.decimalToString(this.account.balanceOnConfirmation),
balanceConfirmedAt: this.dateToString(this.account.balanceConfirmedAt),
balanceOnCreation: this.decimalToString(this.account.balanceOnCreation),
balanceCreatedAt: this.dateToString(this.account.balanceCreatedAt),
}
}
}

View File

@ -0,0 +1,30 @@
import { BackendTransaction } from '@entity/BackendTransaction'
import { InputTransactionType } from '@/graphql/enum/InputTransactionType'
import { getEnumValue } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
import { TransactionLoggingView } from './TransactionLogging.view'
export class BackendTransactionLoggingView extends AbstractLoggingView {
public constructor(private self: BackendTransaction) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(showTransaction = true): any {
return {
id: this.self.id,
backendTransactionId: this.self.backendTransactionId,
transaction:
showTransaction && this.self.transaction
? new TransactionLoggingView(this.self.transaction).toJSON(false)
: undefined,
type: getEnumValue(InputTransactionType, this.self.typeId),
balance: this.decimalToString(this.self.balance),
createdAt: this.dateToString(this.self.createdAt),
confirmedAt: this.dateToString(this.self.confirmedAt),
verifiedOnBackend: this.self.verifiedOnBackend,
}
}
}

View File

@ -0,0 +1,24 @@
import { Community } from '@entity/Community'
import { AbstractLoggingView } from './AbstractLogging.view'
import { AccountLoggingView } from './AccountLogging.view'
export class CommunityLoggingView extends AbstractLoggingView {
public constructor(private self: Community) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
id: this.self.id,
iotaTopic: this.self.iotaTopic,
foreign: this.self.foreign,
publicKey: this.self.rootPubkey?.toString(this.bufferStringFormat),
createdAt: this.dateToString(this.self.createdAt),
confirmedAt: this.dateToString(this.self.confirmedAt),
aufAccount: this.self.aufAccount ? new AccountLoggingView(this.self.aufAccount) : undefined,
gmwAccount: this.self.gmwAccount ? new AccountLoggingView(this.self.gmwAccount) : undefined,
}
}
}

View File

@ -0,0 +1,18 @@
import { CommunityRoot } from '@/data/proto/3_3/CommunityRoot'
import { AbstractLoggingView } from './AbstractLogging.view'
export class CommunityRootLoggingView extends AbstractLoggingView {
public constructor(private self: CommunityRoot) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
rootPubkey: Buffer.from(this.self.rootPubkey).toString(this.bufferStringFormat),
gmwPubkey: Buffer.from(this.self.gmwPubkey).toString(this.bufferStringFormat),
aufPubkey: Buffer.from(this.self.aufPubkey).toString(this.bufferStringFormat),
}
}
}

View File

@ -0,0 +1,24 @@
import { ConfirmedTransaction } from '@/data/proto/3_3/ConfirmedTransaction'
import { timestampSecondsToDate } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
import { GradidoTransactionLoggingView } from './GradidoTransactionLogging.view'
export class ConfirmedTransactionLoggingView extends AbstractLoggingView {
public constructor(private self: ConfirmedTransaction) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
id: this.self.id.toString(),
transaction: new GradidoTransactionLoggingView(this.self.transaction).toJSON(),
confirmedAt: this.dateToString(timestampSecondsToDate(this.self.confirmedAt)),
versionNumber: this.self.versionNumber,
runningHash: Buffer.from(this.self.runningHash).toString(this.bufferStringFormat),
messageId: Buffer.from(this.self.messageId).toString(this.bufferStringFormat),
accountBalance: this.self.accountBalance,
}
}
}

View File

@ -0,0 +1,18 @@
import { GradidoCreation } from '@/data/proto/3_3/GradidoCreation'
import { AbstractLoggingView } from './AbstractLogging.view'
import { TransferAmountLoggingView } from './TransferAmountLogging.view'
export class GradidoCreationLoggingView extends AbstractLoggingView {
public constructor(private self: GradidoCreation) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
recipient: new TransferAmountLoggingView(this.self.recipient).toJSON(),
targetDate: this.timestampSecondsToDateString(this.self.targetDate),
}
}
}

View File

@ -0,0 +1,18 @@
import { GradidoDeferredTransfer } from '@/data/proto/3_3/GradidoDeferredTransfer'
import { AbstractLoggingView } from './AbstractLogging.view'
import { GradidoTransferLoggingView } from './GradidoTransferLogging.view'
export class GradidoDeferredTransferLoggingView extends AbstractLoggingView {
public constructor(private self: GradidoDeferredTransfer) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
...new GradidoTransferLoggingView(this.self.transfer).toJSON(),
...{ timeout: this.timestampSecondsToDateString(this.self.timeout) },
}
}
}

View File

@ -0,0 +1,29 @@
import { GradidoTransaction } from '@/data/proto/3_3/GradidoTransaction'
import { TransactionBody } from '@/data/proto/3_3/TransactionBody'
import { AbstractLoggingView } from './AbstractLogging.view'
import { SignatureMapLoggingView } from './SignatureMapLogging.view'
import { TransactionBodyLoggingView } from './TransactionBodyLogging.view'
export class GradidoTransactionLoggingView extends AbstractLoggingView {
public constructor(private self: GradidoTransaction) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
let transactionBody: TransactionBody | null | unknown = null
try {
transactionBody = new TransactionBodyLoggingView(this.self.getTransactionBody())
} catch (e) {
transactionBody = e
}
return {
sigMap: new SignatureMapLoggingView(this.self.sigMap).toJSON(),
bodyBytes: transactionBody,
parentMessageId: this.self.parentMessageId
? Buffer.from(this.self.parentMessageId).toString(this.bufferStringFormat)
: undefined,
}
}
}

View File

@ -0,0 +1,18 @@
import { GradidoTransfer } from '@/data/proto/3_3/GradidoTransfer'
import { AbstractLoggingView } from './AbstractLogging.view'
import { TransferAmountLoggingView } from './TransferAmountLogging.view'
export class GradidoTransferLoggingView extends AbstractLoggingView {
public constructor(private self: GradidoTransfer) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
sender: new TransferAmountLoggingView(this.self.sender),
recipient: Buffer.from(this.self.recipient).toString(this.bufferStringFormat),
}
}
}

View File

@ -0,0 +1,16 @@
import { GroupFriendsUpdate } from '@/data/proto/3_3/GroupFriendsUpdate'
import { AbstractLoggingView } from './AbstractLogging.view'
export class GroupFriendsUpdateLoggingView extends AbstractLoggingView {
public constructor(private self: GroupFriendsUpdate) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
colorFusion: this.self.colorFusion,
}
}
}

View File

@ -0,0 +1,22 @@
import { AddressType } from '@/data/proto/3_3/enum/AddressType'
import { RegisterAddress } from '@/data/proto/3_3/RegisterAddress'
import { getEnumValue } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
export class RegisterAddressLoggingView extends AbstractLoggingView {
public constructor(private self: RegisterAddress) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
userPublicKey: Buffer.from(this.self.userPubkey).toString(this.bufferStringFormat),
addressType: getEnumValue(AddressType, this.self.addressType),
nameHash: Buffer.from(this.self.nameHash).toString(this.bufferStringFormat),
accountPublicKey: Buffer.from(this.self.accountPubkey).toString(this.bufferStringFormat),
derivationIndex: this.self.derivationIndex,
}
}
}

View File

@ -0,0 +1,17 @@
import { SignatureMap } from '@/data/proto/3_3/SignatureMap'
import { AbstractLoggingView } from './AbstractLogging.view'
import { SignaturePairLoggingView } from './SignaturePairLogging.view'
export class SignatureMapLoggingView extends AbstractLoggingView {
public constructor(private self: SignatureMap) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
sigPair: this.self.sigPair.map((value) => new SignaturePairLoggingView(value).toJSON()),
}
}
}

View File

@ -0,0 +1,18 @@
import { SignaturePair } from '@/data/proto/3_3/SignaturePair'
import { AbstractLoggingView } from './AbstractLogging.view'
export class SignaturePairLoggingView extends AbstractLoggingView {
public constructor(private self: SignaturePair) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
pubkey: Buffer.from(this.self.pubKey).toString(this.bufferStringFormat),
signature:
Buffer.from(this.self.signature).subarray(0, 31).toString(this.bufferStringFormat) + '..',
}
}
}

View File

@ -0,0 +1,46 @@
import { CrossGroupType } from '@/data/proto/3_3/enum/CrossGroupType'
import { TransactionBody } from '@/data/proto/3_3/TransactionBody'
import { getEnumValue } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
import { CommunityRootLoggingView } from './CommunityRootLogging.view'
import { GradidoCreationLoggingView } from './GradidoCreationLogging.view'
import { GradidoDeferredTransferLoggingView } from './GradidoDeferredTransferLogging.view'
import { GradidoTransferLoggingView } from './GradidoTransferLogging.view'
import { GroupFriendsUpdateLoggingView } from './GroupFriendsUpdateLogging.view'
import { RegisterAddressLoggingView } from './RegisterAddressLogging.view'
export class TransactionBodyLoggingView extends AbstractLoggingView {
public constructor(private self: TransactionBody) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
memo: this.self.memo,
createdAt: this.timestampToDateString(this.self.createdAt),
versionNumber: this.self.versionNumber,
type: getEnumValue(CrossGroupType, this.self.type),
otherGroup: this.self.otherGroup,
transfer: this.self.transfer
? new GradidoTransferLoggingView(this.self.transfer).toJSON()
: undefined,
creation: this.self.creation
? new GradidoCreationLoggingView(this.self.creation).toJSON()
: undefined,
groupFriendsUpdate: this.self.groupFriendsUpdate
? new GroupFriendsUpdateLoggingView(this.self.groupFriendsUpdate).toJSON()
: undefined,
registerAddress: this.self.registerAddress
? new RegisterAddressLoggingView(this.self.registerAddress).toJSON()
: undefined,
deferredTransfer: this.self.deferredTransfer
? new GradidoDeferredTransferLoggingView(this.self.deferredTransfer).toJSON()
: undefined,
communityRoot: this.self.communityRoot
? new CommunityRootLoggingView(this.self.communityRoot).toJSON()
: undefined,
}
}
}

View File

@ -0,0 +1,25 @@
import { InputTransactionType } from '@/graphql/enum/InputTransactionType'
import { TransactionDraft } from '@/graphql/input/TransactionDraft'
import { getEnumValue } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
import { UserIdentifierLoggingView } from './UserIdentifierLogging.view'
export class TransactionDraftLoggingView extends AbstractLoggingView {
public constructor(private self: TransactionDraft) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
user: new UserIdentifierLoggingView(this.self.user).toJSON(),
linkedUser: new UserIdentifierLoggingView(this.self.linkedUser).toJSON(),
backendTransactionId: this.self.backendTransactionId,
amount: this.decimalToString(this.self.amount),
type: getEnumValue(InputTransactionType, this.self.type),
createdAt: this.self.createdAt,
targetDate: this.self.targetDate,
}
}
}

View File

@ -0,0 +1,59 @@
import { Transaction } from '@entity/Transaction'
import { TransactionType } from '@/data/proto/3_3/enum/TransactionType'
import { LogError } from '@/server/LogError'
import { getEnumValue } from '@/utils/typeConverter'
import { AbstractLoggingView } from './AbstractLogging.view'
import { AccountLoggingView } from './AccountLogging.view'
import { BackendTransactionLoggingView } from './BackendTransactionLogging.view'
import { CommunityLoggingView } from './CommunityLogging.view'
export class TransactionLoggingView extends AbstractLoggingView {
public constructor(private self: Transaction) {
super()
if (this.self.community === undefined) {
throw new LogError('sender community is zero')
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(showBackendTransactions = true): any {
return {
id: this.self.id,
nr: this.self.nr,
bodyBytesLength: this.self.bodyBytes.length,
createdAt: this.dateToString(this.self.createdAt),
confirmedAt: this.dateToString(this.self.confirmedAt),
protocolVersion: this.self.protocolVersion,
type: getEnumValue(TransactionType, this.self.type),
signature: this.self.signature.subarray(0, 31).toString(this.bufferStringFormat) + '..',
community: new CommunityLoggingView(this.self.community).toJSON(),
otherCommunity: this.self.otherCommunity
? new CommunityLoggingView(this.self.otherCommunity)
: undefined,
iotaMessageId: this.self.iotaMessageId
? this.self.iotaMessageId.toString(this.bufferStringFormat)
: undefined,
signingAccount: this.self.signingAccount
? new AccountLoggingView(this.self.signingAccount)
: undefined,
recipientAccount: this.self.recipientAccount
? new AccountLoggingView(this.self.recipientAccount)
: undefined,
amount: this.decimalToString(this.self.amount),
accountBalanceOnCreation: this.decimalToString(this.self.accountBalanceOnCreation),
accountBalanceOnConfirmation: this.decimalToString(this.self.accountBalanceOnConfirmation),
runningHash: this.self.runningHash
? this.self.runningHash.toString(this.bufferStringFormat)
: undefined,
iotaMilestone: this.self.iotaMilestone,
backendTransactions:
showBackendTransactions && this.self.backendTransactions
? this.self.backendTransactions.map((backendTransaction) =>
new BackendTransactionLoggingView(backendTransaction).toJSON(false),
)
: undefined,
}
}
}

View File

@ -0,0 +1,18 @@
import { TransferAmount } from '@/data/proto/3_3/TransferAmount'
import { AbstractLoggingView } from './AbstractLogging.view'
export class TransferAmountLoggingView extends AbstractLoggingView {
public constructor(private self: TransferAmount) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
publicKey: Buffer.from(this.self.pubkey).toString(this.bufferStringFormat),
amount: this.self.amount,
communityId: this.self.communityId,
}
}
}

View File

@ -0,0 +1,18 @@
import { UserIdentifier } from '@/graphql/input/UserIdentifier'
import { AbstractLoggingView } from './AbstractLogging.view'
export class UserIdentifierLoggingView extends AbstractLoggingView {
public constructor(private self: UserIdentifier) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
uuid: this.self.uuid,
communityUuid: this.self.communityUuid,
accountNr: this.self.accountNr,
}
}
}

View File

@ -0,0 +1,20 @@
import { User } from '@entity/User'
import { AbstractLoggingView } from './AbstractLogging.view'
export class UserLoggingView extends AbstractLoggingView {
public constructor(private user: User) {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
id: this.user.id,
gradidoId: this.user.gradidoID,
derive1Pubkey: this.user.derive1Pubkey.toString(this.bufferStringFormat),
createdAt: this.dateToString(this.user.createdAt),
confirmedAt: this.dateToString(this.user.confirmedAt),
}
}
}

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { logger } from './logger'
import { logger } from '@/logging/logger'
export class LogError extends Error {
// eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@ -9,10 +9,9 @@ import express, { Express } from 'express'
import { Logger } from 'log4js'
import { schema } from '@/graphql/schema'
import { logger as dltLogger } from '@/logging/logger'
import { Connection } from '@/typeorm/DataSource'
import { logger as dltLogger } from './logger'
type ServerDef = { apollo: ApolloServer; app: Express }
interface MyContext {

View File

@ -5,8 +5,8 @@ import { entities } from '@entity/index'
import { Migration } from '@entity/Migration'
import { CONFIG } from '@/config'
import { logger } from '@/logging/logger'
import { LogError } from '@/server/LogError'
import { logger } from '@/server/logger'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class Connection {

View File

@ -7,8 +7,8 @@ import { TransactionBody } from '@/data/proto/3_3/TransactionBody'
import { AccountType } from '@/graphql/enum/AccountType'
import { TransactionErrorType } from '@/graphql/enum/TransactionErrorType'
import { TransactionError } from '@/graphql/model/TransactionError'
import { logger } from '@/logging/logger'
import { LogError } from '@/server/LogError'
import { logger } from '@/server/logger'
export const uuid4ToBuffer = (uuid: string): Buffer => {
// Remove dashes from the UUIDv4 string

View File

@ -1,9 +1,9 @@
import { logger } from '@/server/logger'
import { logger } from '@/logging/logger'
jest.setTimeout(1000000)
jest.mock('@/server/logger', () => {
const originalModule = jest.requireActual('@/server/logger')
jest.mock('@/logging/logger', () => {
const originalModule = jest.requireActual('@/logging/logger')
return {
__esModule: true,
...originalModule,

View File

@ -13,19 +13,19 @@ const constants = {
}
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_USER: process.env.DB_USER || 'root',
DB_PASSWORD: process.env.DB_PASSWORD || '',
DB_DATABASE: process.env.DB_DATABASE || 'gradido_dlt',
DB_USER: process.env.DB_USER ?? 'root',
DB_PASSWORD: process.env.DB_PASSWORD ?? '',
DB_DATABASE: process.env.DB_DATABASE ?? 'gradido_dlt',
}
const migrations = {
MIGRATIONS_TABLE: process.env.MIGRATIONS_TABLE || 'migrations',
MIGRATIONS_TABLE: process.env.MIGRATIONS_TABLE ?? 'migrations',
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,

View File

@ -13,7 +13,8 @@ DB_PASSWORD=$DB_PASSWORD
DB_DATABASE=gradido_community
# Federation
FEDERATION_COMMUNITY_URL=$FEDERATION_COMMUNITY_URL
COMMUNITY_HOST=$COMMUNITY_HOST
URL_PROTOCOL=$URL_PROTOCOL
FEDERATION_CONFIG_VERSION=$FEDERATION_CONFIG_VERSION
# comma separated list of api-versions, which cause starting several federation modules
FEDERATION_COMMUNITY_APIS=$FEDERATION_COMMUNITY_APIS

View File

@ -14,7 +14,7 @@ const constants = {
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
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v2.2023-08-24',
@ -25,21 +25,21 @@ const constants = {
const server = {
// JWT_SECRET: process.env.JWT_SECRET || 'secret123',
// 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',
PRODUCTION: process.env.NODE_ENV === 'production' || false,
PRODUCTION: process.env.NODE_ENV === 'production' ?? false,
}
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_USER: process.env.DB_USER || 'root',
DB_PASSWORD: process.env.DB_PASSWORD || '',
DB_DATABASE: process.env.DB_DATABASE || 'gradido_community',
TYPEORM_LOGGING_RELATIVE_PATH: process.env.TYPEORM_LOGGING_RELATIVE_PATH || 'typeorm.backend.log',
DB_USER: process.env.DB_USER ?? 'root',
DB_PASSWORD: process.env.DB_PASSWORD ?? '',
DB_DATABASE: process.env.DB_DATABASE ?? 'gradido_community',
TYPEORM_LOGGING_RELATIVE_PATH: process.env.TYPEORM_LOGGING_RELATIVE_PATH ?? 'typeorm.backend.log',
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,
@ -50,10 +50,14 @@ if (
)
}
const COMMUNITY_HOST = process.env.COMMUNITY_HOST ?? 'localhost'
const URL_PROTOCOL = process.env.URL_PROTOCOL ?? 'http'
const COMMUNITY_URL = process.env.COMMUNITY_URL ?? `${URL_PROTOCOL}://${COMMUNITY_HOST}`
const federation = {
FEDERATION_API: process.env.FEDERATION_API || '1_0',
FEDERATION_PORT: process.env.FEDERATION_PORT || 5010,
FEDERATION_COMMUNITY_URL: process.env.FEDERATION_COMMUNITY_URL || null,
FEDERATION_API: process.env.FEDERATION_API ?? '1_0',
FEDERATION_PORT: process.env.FEDERATION_PORT ?? 5010,
FEDERATION_COMMUNITY_URL: process.env.FEDERATION_COMMUNITY_URL ?? COMMUNITY_URL,
FEDERATION_TRADING_LEVEL: {
RECEIVER_COMMUNITY_URL: 'https://stage3.gradido.net/api/',
SEND_COINS: true,

View File

@ -2,13 +2,13 @@
DEFAULT_PUBLISHER_ID=2896
# Endpoints
GRAPHQL_URI=http://localhost/graphql
ADMIN_AUTH_URL=http://localhost/admin/authenticate?token={token}
GRAPHQL_PATH=/graphql
ADMIN_AUTH_PATH=/admin/authenticate?token={token}
# Community
COMMUNITY_NAME=Gradido Entwicklung
COMMUNITY_URL=http://localhost/
COMMUNITY_REGISTER_URL=http://localhost/register
COMMUNITY_REGISTER_PATH=/register
COMMUNITY_DESCRIPTION=Die lokale Entwicklungsumgebung von Gradido.
COMMUNITY_SUPPORT_MAIL=support@supportmail.com

View File

@ -4,18 +4,19 @@ CONFIG_VERSION=$FRONTEND_CONFIG_VERSION
DEFAULT_PUBLISHER_ID=$DEFAULT_PUBLISHER_ID
# Endpoints
GRAPHQL_URI=$GRAPHQL_URI
ADMIN_AUTH_URL=$ADMIN_AUTH_URL
GRAPHQL_PATH=$GRAPHQL_PATH
ADMIN_AUTH_PATH=$ADMIN_AUTH_PATH
# Community
COMMUNITY_NAME=$COMMUNITY_NAME
COMMUNITY_URL=$COMMUNITY_URL
COMMUNITY_REGISTER_URL=$COMMUNITY_REGISTER_URL
COMMUNITY_HOST=$COMMUNITY_HOST
URL_PROTOCOL=$URL_PROTOCOL
COMMUNITY_REGISTER_PATH=$COMMUNITY_REGISTER_PATH
COMMUNITY_DESCRIPTION=$COMMUNITY_DESCRIPTION
COMMUNITY_SUPPORT_MAIL=$COMMUNITY_SUPPORT_MAIL
# Meta
META_URL=$META_URL
META_URL=$COMMUNITY_HOST
META_TITLE_DE=$META_TITLE_DE
META_TITLE_EN=$META_TITLE_EN
META_DESCRIPTION_DE=$META_DESCRIPTION_DE

View File

@ -8,61 +8,66 @@ const constants = {
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v4.2022-12-20',
EXPECTED: 'v5.2024-01-08',
CURRENT: '',
},
}
const version = {
APP_VERSION: pkg.version,
BUILD_COMMIT: process.env.BUILD_COMMIT || null,
BUILD_COMMIT: process.env.BUILD_COMMIT ?? null,
// self reference of `version.BUILD_COMMIT` is not possible at this point, hence the duplicate code
BUILD_COMMIT_SHORT: (process.env.BUILD_COMMIT || '0000000').slice(0, 7),
BUILD_COMMIT_SHORT: (process.env.BUILD_COMMIT ?? '0000000').slice(0, 7),
}
const environment = {
NODE_ENV: process.env.NODE_ENV,
DEBUG: process.env.NODE_ENV !== 'production' || false,
PRODUCTION: process.env.NODE_ENV === 'production' || false,
DEFAULT_PUBLISHER_ID: process.env.DEFAULT_PUBLISHER_ID || 2896,
PORT: process.env.PORT || 3000,
DEBUG: process.env.NODE_ENV !== 'production' ?? false,
PRODUCTION: process.env.NODE_ENV === 'production' ?? false,
DEFAULT_PUBLISHER_ID: process.env.DEFAULT_PUBLISHER_ID ?? 2896,
PORT: process.env.PORT ?? 3000,
}
const COMMUNITY_HOST = process.env.COMMUNITY_HOST ?? 'localhost'
const URL_PROTOCOL = process.env.URL_PROTOCOL ?? 'http'
const COMMUNITY_URL = process.env.COMMUNITY_URL ?? `${URL_PROTOCOL}://${COMMUNITY_HOST}`
const endpoints = {
GRAPHQL_URI: process.env.GRAPHQL_URI || 'http://localhost/graphql',
ADMIN_AUTH_URL: process.env.ADMIN_AUTH_URL || 'http://localhost/admin/authenticate?token={token}',
GRAPHQL_URI: COMMUNITY_URL + (process.env.GRAPHQL_PATH ?? '/graphql'),
ADMIN_AUTH_URL:
COMMUNITY_URL + (process.env.ADMIN_AUTH_PATH ?? '/admin/authenticate?token={token}'),
}
const community = {
COMMUNITY_NAME: process.env.COMMUNITY_NAME || 'Gradido Entwicklung',
COMMUNITY_URL: process.env.COMMUNITY_URL || 'http://localhost/',
COMMUNITY_REGISTER_URL: process.env.COMMUNITY_REGISTER_URL || 'http://localhost/register',
COMMUNITY_NAME: process.env.COMMUNITY_NAME ?? 'Gradido Entwicklung',
COMMUNITY_URL: COMMUNITY_URL,
COMMUNITY_REGISTER_URL: COMMUNITY_URL + (process.env.COMMUNITY_REGISTER_PATH ?? '/register'),
COMMUNITY_DESCRIPTION:
process.env.COMMUNITY_DESCRIPTION || 'Die lokale Entwicklungsumgebung von Gradido.',
COMMUNITY_SUPPORT_MAIL: process.env.COMMUNITY_SUPPORT_MAIL || 'support@supportmail.com',
process.env.COMMUNITY_DESCRIPTION ?? 'Die lokale Entwicklungsumgebung von Gradido.',
COMMUNITY_SUPPORT_MAIL: process.env.COMMUNITY_SUPPORT_MAIL ?? 'support@supportmail.com',
}
const meta = {
META_URL: process.env.META_URL || 'http://localhost',
META_TITLE_DE: process.env.META_TITLE_DE || 'Gradido Dein Dankbarkeitskonto',
META_TITLE_EN: process.env.META_TITLE_EN || 'Gradido - Your gratitude account',
META_URL: process.env.META_URL ?? 'http://localhost',
META_TITLE_DE: process.env.META_TITLE_DE ?? 'Gradido Dein Dankbarkeitskonto',
META_TITLE_EN: process.env.META_TITLE_EN ?? 'Gradido - Your gratitude account',
META_DESCRIPTION_DE:
process.env.META_DESCRIPTION_DE ||
process.env.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:
process.env.META_DESCRIPTION_EN ||
process.env.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_KEYWORDS_DE:
process.env.META_KEYWORDS_DE ||
process.env.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_KEYWORDS_EN:
process.env.META_KEYWORDS_EN ||
process.env.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: process.env.META_AUTHOR || 'Bernd Hückstädt - Gradido-Akademie',
META_AUTHOR: process.env.META_AUTHOR ?? 'Bernd Hückstädt - Gradido-Akademie',
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION || constants.CONFIG_VERSION.DEFAULT
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,

View File

@ -1,5 +1,5 @@
server {
server_name $NGINX_SERVER_NAME;
server_name _;
listen 80;
listen [::]:80;