Merge remote-tracking branch 'origin/master' into 3427-feature-correct-user-data-transfer-to-gms

This commit is contained in:
clauspeterhuebner 2025-01-28 21:15:48 +01:00
commit fd5b02c6a8
81 changed files with 2423 additions and 470 deletions

3
.dockerignore Normal file
View File

@ -0,0 +1,3 @@
**/node_modules
**/build
**/coverage

View File

@ -33,7 +33,7 @@ jobs:
uses: actions/checkout@v3
- name: Admin Interface | Build 'test' image
run: docker build --target test -t "gradido/admin:test" admin/ --build-arg NODE_ENV="test"
run: docker build -f ./admin/Dockerfile --target test -t "gradido/admin:test" --build-arg NODE_ENV="test" .
unit_test:
if: needs.files-changed.outputs.admin == 'true'

View File

@ -44,7 +44,7 @@ jobs:
uses: actions/checkout@v3
- name: Backend | docker-compose mariadb
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb mailserver
- name: Sleep for 30 seconds
run: sleep 30s
@ -54,7 +54,7 @@ jobs:
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
- name: Backend | Unit tests
run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
run: cd database && yarn && yarn build && cd ../config && yarn install && cd ../backend && yarn && yarn test
lint:
if: needs.files-changed.outputs.backend == 'true'
@ -66,7 +66,7 @@ jobs:
uses: actions/checkout@v3
- name: Backend | Lint
run: cd database && yarn && cd ../backend && yarn && yarn run lint
run: cd database && yarn && cd ../config && yarn install && cd ../backend && yarn && yarn run lint
locales:
if: needs.files-changed.outputs.backend == 'true'

View File

@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@v3
- name: Lint
run: cd database && yarn && cd ../dht-node && yarn && yarn run lint
run: cd database && yarn && cd ../config && yarn install && cd ../dht-node && yarn && yarn run lint
unit_test:
name: Unit Tests - DHT Node

View File

@ -21,6 +21,8 @@ jobs:
sudo chown runner:docker -R *
cd database
yarn && yarn dev_reset
cd ../config
yarn install
cd ../backend
yarn && yarn seed

View File

@ -33,7 +33,7 @@ jobs:
uses: actions/checkout@v3
- name: Frontend | Build 'test' image
run: docker build --target test -t "gradido/frontend:test" frontend/ --build-arg NODE_ENV="test"
run: docker build -f ./frontend/Dockerfile --target test -t "gradido/frontend:test" --build-arg NODE_ENV="test" .
unit_test:
if: needs.files-changed.outputs.frontend == 'true'

View File

@ -11,7 +11,7 @@ ENV BUILD_DATE="1970-01-01T00:00:00.00Z"
## We cannot do $(npm run version).${BUILD_NUMBER} here so we default to 0.0.0.0
ENV BUILD_VERSION="0.0.0.0"
## We cannot do `$(git rev-parse --short HEAD)` here so we default to 0000000
ENV BUILD_COMMIT="0000000"
ENV BUILD_COMMIT_SHORT="0000000"
## SET NODE_ENV
ARG NODE_ENV="production"
## App relevant Envs
@ -42,6 +42,8 @@ EXPOSE ${PORT}
RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
RUN mkdir -p /config
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
##################################################################################
@ -53,7 +55,7 @@ FROM base as development
# Run command
# (for development we need to execute yarn install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "yarn install && yarn run dev"
CMD /bin/sh -c "cd /config && yarn install && cd /app && yarn && yarn run dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
@ -61,9 +63,16 @@ CMD /bin/sh -c "yarn install && yarn run dev"
FROM base as build
# Copy everything
COPY . .
# yarn install
COPY ./admin/ .
# Copy everything from config
COPY ./config/ ../config/
# yarn install and build config
RUN cd ../config && yarn install --production=false --frozen-lockfile --non-interactive && yarn build
# yarn install admin
RUN yarn install --production=false --frozen-lockfile --non-interactive
# yarn build
RUN yarn run build
@ -85,6 +94,7 @@ FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
COPY --from=build ${DOCKER_WORKDIR}/../config/build ../config/build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
# Copy static files

View File

@ -74,6 +74,8 @@
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-vue": "8.7.1",
"gradido-config": "../config",
"joi": "^17.13.3",
"jsdom": "^25.0.0",
"mock-apollo-client": "^1.2.1",
"postcss": "^8.4.8",

View File

@ -21,6 +21,7 @@ vi.mock('@vue/apollo-composable', () => ({
vi.mock('vue-i18n', () => ({
useI18n: () => ({
locale: { value: 'en' },
t: (key) => key,
}),
}))

View File

@ -9,7 +9,13 @@
</BFormGroup>
<BFormGroup v-if="showResubmissionDate">
<div class="d-flex my-2">
<Datepicker v-model="resubmissionDate" :lower-limit="now" class="form-control" />
<Datepicker
v-model="resubmissionDate"
:locale="dateLocale"
input-format="P"
:lower-limit="now"
class="form-control"
/>
<time-picker v-model="resubmissionTime" class="ms-2" />
</div>
</BFormGroup>
@ -80,9 +86,9 @@
<script setup>
import { ref, computed } from 'vue'
import { useDateLocale } from '@/composables/useDateLocale'
import { useMutation } from '@vue/apollo-composable'
import { useI18n } from 'vue-i18n'
import Datepicker from 'vue3-datepicker'
import TimePicker from '@/components/input/TimePicker'
import { adminCreateContributionMessage } from '@/graphql/adminCreateContributionMessage'
@ -117,6 +123,7 @@ const emit = defineEmits([
])
const { t } = useI18n()
const dateLocale = useDateLocale()
const { toastError, toastSuccess } = useAppToast()
const form = ref({
text: '',

View File

@ -89,9 +89,9 @@
<script setup>
import { ref, computed, toRefs } from 'vue'
import { useI18n } from 'vue-i18n'
import { useDateLocale } from '@/composables/useDateLocale'
import { useMutation } from '@vue/apollo-composable'
import { formatDistanceToNow } from 'date-fns'
import { de, enUS as en, fr, es, nl } from 'date-fns/locale'
import EditableGroup from '@/components/input/EditableGroup.vue'
import FederationVisualizeItem from './FederationVisualizeItem.vue'
import { updateHomeCommunity } from '@/graphql/updateHomeCommunity'
@ -99,15 +99,13 @@ import Coordinates from '../input/Coordinates.vue'
import EditableGroupableLabel from '../input/EditableGroupableLabel.vue'
import { useAppToast } from '@/composables/useToast'
const locales = { en, de, es, fr, nl }
const props = defineProps({
item: { type: Object, required: true },
})
const { item } = toRefs(props)
const { t, locale } = useI18n()
const { t } = useI18n()
const { toastSuccess, toastError } = useAppToast()
@ -147,7 +145,7 @@ const lastAnnouncedAt = computed(() => {
return formatDistanceToNow(lastAnnouncedAt, {
includeSecond: true,
addSuffix: true,
locale: locales[locale.value],
locale: useDateLocale(),
})
}
return ''
@ -158,7 +156,7 @@ const createdAt = computed(() => {
return formatDistanceToNow(new Date(item.value.createdAt), {
includeSecond: true,
addSuffix: true,
locale: locales[locale.value],
locale: useDateLocale(),
})
}
return ''

View File

@ -30,11 +30,9 @@
</template>
<script>
import { formatDistanceToNow } from 'date-fns'
import { de, enUS as en, fr, es, nl } from 'date-fns/locale'
import { useDateLocale } from '@/composables/useDateLocale'
import VariantIcon from '@/components/VariantIcon.vue'
const locales = { en, de, es, fr, nl }
export default {
name: 'FederationVisualizeItem',
components: { VariantIcon },
@ -58,7 +56,7 @@ export default {
? formatDistanceToNow(new Date(dateString), {
includeSecond: true,
addSuffix: true,
locale: locales[this.$i18n.locale],
locale: useDateLocale,
})
: ''
},

View File

@ -114,7 +114,7 @@ describe('NavBar', () => {
it('changes window location to wallet and dispatches logout', async () => {
const dispatchSpy = vi.spyOn(store, 'dispatch')
await wrapper.vm.handleWallet()
expect(window.location).toBe(CONFIG.WALLET_AUTH_URL.replace('{token}', 'valid-token'))
expect(window.location).toBe(CONFIG.WALLET_AUTH_URL + 'valid-token')
expect(dispatchSpy).toHaveBeenCalledWith('logout')
})
})

View File

@ -80,7 +80,7 @@ const handleLogout = async () => {
}
const handleWallet = () => {
window.location = CONFIG.WALLET_AUTH_URL.replace('{token}', store.state.token)
window.location = CONFIG.WALLET_AUTH_URL + store.state.token
store.dispatch('logout') // logout without redirect
}

View File

@ -0,0 +1,10 @@
import { useI18n } from 'vue-i18n'
import { de, enUS as en, fr, es, nl } from 'date-fns/locale'
const locales = { en, de, es, fr, nl }
export function useDateLocale() {
const { locale } = useI18n()
const dateLocale = locales[locale.value] || en
return dateLocale
}

View File

@ -4,20 +4,12 @@
// Load Package Details for some default values
const pkg = require('../../package')
const constants = {
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v3.2024-08-06',
CURRENT: '',
},
}
const version = {
ADMIN_MODULE_PROTOCOL: process.env.ADMIN_MODULE_PROTOCOL ?? 'http',
ADMIN_MODULE_HOST: process.env.ADMIN_MODULE_HOST ?? 'localhost',
ADMIN_MODULE_PORT: process.env.ADMIN_MODULE_PORT ?? '8080',
APP_VERSION: pkg.version,
BUILD_COMMIT: process.env.BUILD_COMMIT ?? null,
BUILD_COMMIT: process.env.BUILD_COMMIT ?? undefined,
// 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),
}
@ -47,11 +39,11 @@ const environment = {
// const COMMUNITY_URL =
// COMMUNITY_HOST && URL_PROTOCOL ? URL_PROTOCOL + '://' + COMMUNITY_HOST : undefined
const COMMUNITY_URL = process.env.COMMUNITY_URL ?? ADMIN_MODULE_URL
const WALLET_URL = process.env.WALLET_URL ?? COMMUNITY_URL ?? 'http://localhost'
const WALLET_URL = process.env.WALLET_URL ?? COMMUNITY_URL ?? 'http://0.0.0.0'
const endpoints = {
GRAPHQL_URI: process.env.GRAPHQL_URL ?? COMMUNITY_URL + (process.env.GRAPHQL_PATH ?? '/graphql'),
WALLET_AUTH_URL: WALLET_URL + (process.env.WALLET_AUTH_PATH ?? '/authenticate?token={token}'),
WALLET_AUTH_URL: WALLET_URL + (process.env.WALLET_AUTH_PATH ?? '/authenticate?token='),
WALLET_LOGIN_URL: WALLET_URL + (process.env.WALLET_LOGIN_PATH ?? '/login'),
}
@ -59,24 +51,13 @@ const debug = {
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
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,
)
) {
throw new Error(
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
)
}
const CONFIG = {
...constants,
...version,
...environment,
...endpoints,
...debug,
ADMIN_MODULE_URL,
COMMUNITY_URL,
}
module.exports = CONFIG

106
admin/src/config/schema.js Normal file
View File

@ -0,0 +1,106 @@
const {
APP_VERSION,
BUILD_COMMIT,
BUILD_COMMIT_SHORT,
COMMUNITY_URL,
DEBUG,
GRAPHQL_URI,
NODE_ENV,
PRODUCTION,
} = require('gradido-config/build/src/commonSchema.js')
const Joi = require('joi')
module.exports = Joi.object({
APP_VERSION,
BUILD_COMMIT,
BUILD_COMMIT_SHORT,
COMMUNITY_URL,
DEBUG,
GRAPHQL_URI,
NODE_ENV,
PRODUCTION,
ADMIN_HOSTING: Joi.string()
.valid('nodejs', 'nginx')
.description('set to `nodejs` if admin is hosted by vite with a own nodejs instance')
.optional(),
ADMIN_MODULE_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.when('COMMUNITY_URL', {
is: Joi.exist(),
then: Joi.optional(), // not required if COMMUNITY_URL is provided
otherwise: Joi.required(), // required if COMMUNITY_URL is missing
})
.description("Base Url for reaching admin in browser, only needed if COMMUNITY_URL wasn't set")
.optional(), // optional in general, but conditionally required
ADMIN_MODULE_PROTOCOL: Joi.string()
.when('ADMIN_HOSTING', {
is: Joi.valid('nodejs'),
then: Joi.valid('http').required(),
otherwise: Joi.valid('http', 'https').required(),
})
.description(
`
Protocol for admin module hosting
- it has to be the same as for backend api url and frontend to prevent mixed block errors,
- if admin is served with nodejs:
is have to be http or setup must be updated to include a ssl certificate
`,
)
.default('http')
.required(),
ADMIN_MODULE_HOST: Joi.alternatives()
.try(
Joi.string().valid('localhost').messages({ 'any.invalid': 'Must be localhost' }),
Joi.string()
.ip({ version: ['ipv4'] })
.messages({ 'string.ip': 'Must be a valid IPv4 address' }),
Joi.string().domain().messages({ 'string.domain': 'Must be a valid domain' }),
)
.when('ADMIN_HOSTING', {
is: 'nodejs',
then: Joi.required(),
otherwise: Joi.optional(),
})
.when('COMMUNITY_URL', {
is: null,
then: Joi.required(),
otherwise: Joi.optional(),
})
.description(
'Host (domain, IPv4, or localhost) for the admin, default is 0.0.0.0 for local hosting during develop',
)
.default('0.0.0.0'),
ADMIN_MODULE_PORT: Joi.number()
.integer()
.min(1024)
.max(49151)
.description('Port for hosting Admin with Vite as a Node.js instance, default: 8080')
.default(8080)
.when('ADMIN_HOSTING', {
is: 'nodejs',
then: Joi.required(),
otherwise: Joi.optional(),
}),
WALLET_AUTH_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.description('Extern Url from wallet-frontend for forwarding from admin')
.default('http://0.0.0.0/authenticate?token=')
.required(),
WALLET_LOGIN_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.description('Extern Url from wallet-frontend for forwarding after logout')
.default('http://0.0.0.0/login')
.required(),
DEBUG_DISABLE_AUTH: Joi.boolean()
.description('Flag for disable authorization during development')
.default(false)
.optional(), // true is only allowed in not-production setup
})

View File

@ -6,6 +6,8 @@ import Components from 'unplugin-vue-components/vite'
import IconsResolve from 'unplugin-icons/resolver'
import { BootstrapVueNextResolver } from 'bootstrap-vue-next'
import EnvironmentPlugin from 'vite-plugin-environment'
import schema from './src/config/schema'
import { validate, browserUrls } from 'gradido-config/build/src/index.js'
import dotenv from 'dotenv'
@ -15,56 +17,74 @@ const CONFIG = require('./src/config')
const path = require('path')
export default defineConfig({
base: '/admin/',
server: {
host: CONFIG.ADMIN_MODULE_HOST, // '0.0.0.0',
port: CONFIG.ADMIN_MODULE_PORT, // 8080,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
assets: path.join(__dirname, 'src/assets'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
export default defineConfig(({ command }) => {
if (command === 'serve') {
CONFIG.ADMIN_HOSTING = 'nodejs'
} else {
CONFIG.ADMIN_HOSTING = 'nginx'
}
// Check config
validate(schema, CONFIG)
// make sure that all urls used in browser have the same protocol to prevent mixed content errors
validate(browserUrls, [
CONFIG.ADMIN_AUTH_URL,
CONFIG.COMMUNITY_URL,
CONFIG.COMMUNITY_REGISTER_URL,
CONFIG.GRAPHQL_URI,
CONFIG.FRONTEND_MODULE_URL,
])
plugins: [
vue({
template: {
compilerOptions: {
compatConfig: {
MODE: 2,
return {
base: '/admin/',
server: {
host: CONFIG.ADMIN_MODULE_HOST, // '0.0.0.0',
port: CONFIG.ADMIN_MODULE_PORT, // 8080,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
assets: path.join(__dirname, 'src/assets'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
plugins: [
vue({
template: {
compilerOptions: {
compatConfig: {
MODE: 2,
},
},
},
},
}),
Components({
resolvers: [IconsResolve(), BootstrapVueNextResolver()],
dts: true,
}),
Icons({
compiler: 'vue3',
}),
EnvironmentPlugin({
BUILD_COMMIT: null,
PORT: CONFIG.ADMIN_MODULE_PORT ?? null, // null,
COMMUNITY_HOST: CONFIG.ADMIN_MODULE_HOST ?? null, // null,
COMMUNITY_URL: CONFIG.COMMUNITY_URL ?? null,
URL_PROTOCOL: CONFIG.ADMIN_MODULE_PROTOCOL ?? null, // null,
WALLET_AUTH_URL: CONFIG.WALLET_AUTH_URL ?? null,
GRAPHQL_URL: CONFIG.GRAPHQL_URI ?? null, // null,
GRAPHQL_PATH: process.env.GRAPHQL_PATH ?? '/graphql', // null,
WALLET_AUTH_PATH: CONFIG.WALLET_AUTH_PATH ?? null,
WALLET_LOGIN_PATH: CONFIG.WALLET_LOGIN_URL ?? null, // null,
DEBUG_DISABLE_AUTH: CONFIG.DEBUG_DISABLE_AUTH ?? null, // null,
// CONFIG_VERSION: CONFIG.CONFIG_VERSION, // null,
}),
commonjs(),
],
build: {
outDir: path.resolve(__dirname, './build'),
chunkSizeWarningLimit: 1600,
},
publicDir: '/admin',
}),
Components({
resolvers: [IconsResolve(), BootstrapVueNextResolver()],
dts: true,
}),
Icons({
compiler: 'vue3',
}),
EnvironmentPlugin({
BUILD_COMMIT: null,
PORT: CONFIG.ADMIN_MODULE_PORT ?? null, // null,
COMMUNITY_HOST: CONFIG.ADMIN_MODULE_HOST ?? null, // null,
COMMUNITY_URL: CONFIG.COMMUNITY_URL ?? null,
URL_PROTOCOL: CONFIG.ADMIN_MODULE_PROTOCOL ?? null, // null,
WALLET_AUTH_URL: CONFIG.WALLET_AUTH_URL ?? null,
GRAPHQL_URL: CONFIG.GRAPHQL_URI ?? null, // null,
GRAPHQL_PATH: process.env.GRAPHQL_PATH ?? '/graphql', // null,
WALLET_AUTH_PATH: CONFIG.WALLET_AUTH_PATH ?? null,
WALLET_LOGIN_PATH: CONFIG.WALLET_LOGIN_URL ?? null, // null,
DEBUG_DISABLE_AUTH: CONFIG.DEBUG_DISABLE_AUTH ?? null, // null,
// CONFIG_VERSION: CONFIG.CONFIG_VERSION, // null,
}),
commonjs(),
],
build: {
outDir: path.resolve(__dirname, './build'),
chunkSizeWarningLimit: 1600,
},
publicDir: '/admin',
}
})

View File

@ -1072,6 +1072,18 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@humanwhocodes/config-array@^0.11.14":
version "0.11.14"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
@ -1471,6 +1483,23 @@
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@types/estree@1.0.6", "@types/estree@^1.0.0":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
@ -4195,6 +4224,11 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
gradido-config@../config:
version "1.0.0"
dependencies:
joi "^17.13.3"
graphemer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
@ -4712,6 +4746,17 @@ jest-canvas-mock@~2.5.2:
cssfontparser "^1.2.1"
moo-color "^1.0.2"
joi@^17.13.3:
version "17.13.3"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
dependencies:
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.5"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
js-beautify@^1.14.9:
version "1.15.1"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.15.1.tgz#4695afb508c324e1084ee0b952a102023fc65b64"

View File

@ -3,7 +3,7 @@ PORT=4000
JWT_SECRET=secret123
JWT_EXPIRES_IN=10m
GRAPHIQL=false
GDT_API_URL=https://gdt.gradido.net
GDT_ACTIVE=false
# Database
DB_HOST=localhost
@ -45,7 +45,7 @@ EMAIL_TEST_RECEIVER=stage1@gradido.net
EMAIL_USERNAME=gradido_email
EMAIL_SENDER=info@gradido.net
EMAIL_PASSWORD=xxx
EMAIL_SMTP_URL=gmail.com
EMAIL_SMTP_HOST=gmail.com
EMAIL_SMTP_PORT=587
EMAIL_LINK_VERIFICATION_PATH=/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD_PATH=/reset-password/{optin}

View File

@ -45,7 +45,7 @@ EMAIL_TEST_RECEIVER=stage1@gradido.net
EMAIL_USERNAME=gradido_email
EMAIL_SENDER=info@gradido.net
EMAIL_PASSWORD=xxx
EMAIL_SMTP_URL=gmail.com
EMAIL_SMTP_HOST=gmail.com
EMAIL_SMTP_PORT=587
EMAIL_LINK_VERIFICATION_PATH=/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD_PATH=/reset-password/{optin}

View File

@ -49,7 +49,7 @@ EMAIL_TEST_RECEIVER=$EMAIL_TEST_RECEIVER
EMAIL_USERNAME=$EMAIL_USERNAME
EMAIL_SENDER=$EMAIL_SENDER
EMAIL_PASSWORD=$EMAIL_PASSWORD
EMAIL_SMTP_URL=$EMAIL_SMTP_URL
EMAIL_SMTP_HOST=$EMAIL_SMTP_HOST
EMAIL_SMTP_PORT=$EMAIL_SMTP_PORT
EMAIL_LINK_VERIFICATION_PATH=$EMAIL_LINK_VERIFICATION_PATH
EMAIL_LINK_SETPASSWORD_PATH=$EMAIL_LINK_SETPASSWORD_PATH

View File

@ -1,6 +1,8 @@
# Server
JWT_EXPIRES_IN=2m
GDT_ACTIVE=false
# Email
EMAIL=true
EMAIL_TEST_MODUS=false

View File

@ -43,6 +43,7 @@ RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
RUN mkdir -p /database
RUN mkdir -p /config
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
@ -55,7 +56,7 @@ FROM base as development
# Run command
# (for development we need to execute yarn install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "cd /database && yarn install && yarn build && cd /app && yarn install && yarn run dev"
CMD /bin/sh -c "cd /database && yarn install && yarn build && cd /config && yarn install && cd /app && yarn install && yarn run dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
@ -66,6 +67,11 @@ FROM base as build
COPY ./backend/ ./
# Copy everything from database
COPY ./database/ ../database/
# Copy everything from config
COPY ./config/ ../config/
# yarn install and build config
RUN cd ../config && yarn install --production=false --frozen-lockfile --non-interactive && yarn build
# yarn install backend
RUN yarn install --production=false --frozen-lockfile --non-interactive
@ -74,10 +80,10 @@ RUN yarn install --production=false --frozen-lockfile --non-interactive
RUN cd ../database && yarn install --production=false --frozen-lockfile --non-interactive
# yarn build
RUN yarn run build
RUN yarn build
# yarn build database
RUN cd ../database && yarn run build
RUN cd ../database && yarn build
##################################################################################
# TEST ###########################################################################
@ -95,9 +101,11 @@ FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
COPY --from=build ${DOCKER_WORKDIR}/../database/build ../database/build
COPY --from=build ${DOCKER_WORKDIR}/../config/build ../config/build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
COPY --from=build ${DOCKER_WORKDIR}/../database/node_modules ../database/node_modules
COPY --from=build ${DOCKER_WORKDIR}/../config/node_modules ../config/node_modules
# Copy static files
# COPY --from=build ${DOCKER_WORKDIR}/public ./public

View File

@ -7,7 +7,7 @@ module.exports = {
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
coverageThreshold: {
global: {
lines: 81,
lines: 80,
},
},
setupFiles: ['<rootDir>/test/testSetup.ts'],
@ -39,5 +39,10 @@ module.exports = {
process.env.NODE_ENV === 'development'
? '<rootDir>/../database/src/$1'
: '<rootDir>/../database/build/src/$1',
'@config/(.*)':
// eslint-disable-next-line n/no-process-env
process.env.NODE_ENV === 'development'
? '<rootDir>/../config/src/$1'
: '<rootDir>/../config/build/$1',
},
}

View File

@ -33,12 +33,14 @@
"email-templates": "^10.0.1",
"express": "^4.17.1",
"express-slow-down": "^2.0.1",
"gradido-config": "file:../config",
"gradido-database": "file:../database",
"graphql": "^15.5.1",
"graphql-request": "5.0.0",
"graphql-type-json": "0.3.2",
"helmet": "^5.1.1",
"i18n": "^0.15.1",
"joi": "^17.13.3",
"jose": "^4.14.4",
"lodash.clonedeep": "^4.5.0",
"log4js": "^6.4.6",
@ -61,8 +63,9 @@
"@types/faker": "^5.5.9",
"@types/i18n": "^0.13.4",
"@types/jest": "^27.0.2",
"@types/joi": "^17.2.3",
"@types/lodash.clonedeep": "^4.5.6",
"@types/node": "^16.10.3",
"@types/node": "^17.0.21",
"@types/nodemailer": "^6.4.4",
"@types/sodium-native": "^2.3.5",
"@types/uuid": "^8.3.4",

View File

@ -1,9 +1,14 @@
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
/* eslint-disable n/no-process-env */
// eslint-disable-next-line import/no-unresolved
import { validate } from '@config/index'
import { latestDbVersion } from '@dbTools/config/detectLastDBVersion'
import { Decimal } from 'decimal.js-light'
import dotenv from 'dotenv'
import { schema } from './schema'
dotenv.config()
Decimal.set({
@ -12,16 +17,10 @@ Decimal.set({
})
const constants = {
DB_VERSION: '0087-add_index_on_user_roles',
// DB_VERSION: '0087-add_index_on_user_roles',
DB_VERSION: latestDbVersion,
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',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v23.2024-04-04',
CURRENT: '',
},
}
const server = {
@ -29,8 +28,11 @@ const server = {
JWT_SECRET: process.env.JWT_SECRET ?? 'secret123',
JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN ?? '10m',
GRAPHIQL: process.env.GRAPHIQL === 'true' || false,
GDT_ACTIVE: process.env.GDT_ACTIVE === 'true' || false,
GDT_API_URL: process.env.GDT_API_URL ?? 'https://gdt.gradido.net',
PRODUCTION: process.env.NODE_ENV === 'production' || false,
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
}
const database = {
@ -64,10 +66,9 @@ const dltConnector = {
const community = {
COMMUNITY_NAME: process.env.COMMUNITY_NAME ?? 'Gradido Entwicklung',
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_URL: COMMUNITY_URL + (process.env.COMMUNITY_REDEEM_PATH ?? '/redeem/'),
COMMUNITY_REDEEM_CONTRIBUTION_URL:
COMMUNITY_URL + (process.env.COMMUNITY_REDEEM_CONTRIBUTION_PATH ?? '/redeem/CL-{code}'),
COMMUNITY_URL + (process.env.COMMUNITY_REDEEM_CONTRIBUTION_PATH ?? '/redeem/CL-'),
COMMUNITY_DESCRIPTION:
process.env.COMMUNITY_DESCRIPTION ?? 'Die lokale Entwicklungsumgebung von Gradido.',
COMMUNITY_SUPPORT_MAIL: process.env.COMMUNITY_SUPPORT_MAIL ?? 'support@supportmail.com',
@ -86,14 +87,14 @@ const email = {
EMAIL_USERNAME: process.env.EMAIL_USERNAME ?? '',
EMAIL_SENDER: process.env.EMAIL_SENDER ?? 'info@gradido.net',
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD ?? '',
EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL ?? 'mailserver',
EMAIL_SMTP_HOST: process.env.EMAIL_SMTP_HOST ?? 'mailserver',
EMAIL_SMTP_PORT: Number(process.env.EMAIL_SMTP_PORT) || 1025,
// eslint-disable-next-line no-unneeded-ternary
EMAIL_TLS: process.env.EMAIL_TLS === 'false' ? false : true,
EMAIL_LINK_VERIFICATION:
COMMUNITY_URL + (process.env.EMAIL_LINK_VERIFICATION_PATH ?? '/checkEmail/{optin}{code}'),
COMMUNITY_URL + (process.env.EMAIL_LINK_VERIFICATION_PATH ?? '/checkEmail/'),
EMAIL_LINK_SETPASSWORD:
COMMUNITY_URL + (process.env.EMAIL_LINK_SETPASSWORD_PATH ?? '/reset-password/{optin}'),
COMMUNITY_URL + (process.env.EMAIL_LINK_SETPASSWORD_PATH ?? '/reset-password/'),
EMAIL_LINK_FORGOTPASSWORD:
COMMUNITY_URL + (process.env.EMAIL_LINK_FORGOTPASSWORD_PATH ?? '/forgot-password'),
EMAIL_LINK_OVERVIEW: COMMUNITY_URL + (process.env.EMAIL_LINK_OVERVIEW_PATH ?? '/overview'),
@ -115,18 +116,6 @@ const webhook = {
// This is needed by graphql-directive-auth
process.env.APP_SECRET = server.JWT_SECRET
// Check config version
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,
)
) {
throw new Error(
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
)
}
const federation = {
FEDERATION_BACKEND_SEND_ON_API: process.env.FEDERATION_BACKEND_SEND_ON_API ?? '1_0',
// ?? operator don't work here as expected
@ -172,3 +161,5 @@ export const CONFIG = {
...gms,
...humhub,
}
validate(schema, CONFIG)

View File

@ -0,0 +1,355 @@
// eslint-disable-next-line import/no-unresolved
import {
COMMUNITY_NAME,
COMMUNITY_URL,
COMMUNITY_DESCRIPTION,
COMMUNITY_SUPPORT_MAIL,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
DB_DATABASE,
DECAY_START_TIME,
GDT_API_URL,
GDT_ACTIVE,
GMS_ACTIVE,
GRAPHIQL,
HUMHUB_ACTIVE,
LOG4JS_CONFIG,
LOGIN_APP_SECRET,
LOGIN_SERVER_KEY,
LOG_LEVEL,
NODE_ENV,
PRODUCTION,
TYPEORM_LOGGING_RELATIVE_PATH,
} from '@config/commonSchema'
import Joi from 'joi'
export const schema = Joi.object({
COMMUNITY_NAME,
COMMUNITY_URL,
COMMUNITY_DESCRIPTION,
COMMUNITY_SUPPORT_MAIL,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
DB_DATABASE,
DECAY_START_TIME,
GDT_API_URL,
GDT_ACTIVE,
GMS_ACTIVE,
GRAPHIQL,
HUMHUB_ACTIVE,
LOG4JS_CONFIG,
LOGIN_APP_SECRET,
LOGIN_SERVER_KEY,
LOG_LEVEL,
NODE_ENV,
PRODUCTION,
TYPEORM_LOGGING_RELATIVE_PATH,
COMMUNITY_REDEEM_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.description('The url for redeeming link transactions, must start with frontend base url')
.default('http://0.0.0.0/redeem/')
.custom((value: string, helpers: Joi.CustomHelpers<string>): string | Joi.ErrorReport => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
if (!value.startsWith(helpers.state.ancestors[0].COMMUNITY_URL)) {
return helpers.error('string.pattern.base', { value, communityUrl: COMMUNITY_URL })
}
return value
})
.required(),
COMMUNITY_REDEEM_CONTRIBUTION_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.custom((value: string, helpers: Joi.CustomHelpers<string>): string | Joi.ErrorReport => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
if (!value.startsWith(helpers.state.ancestors[0].COMMUNITY_URL)) {
return helpers.error('string.pattern.base', { value, communityUrl: COMMUNITY_URL })
}
return value
})
.description(
'The url for redeeming contribution link transactions, must start with frontend base url.',
)
.default('http://0.0.0.0/redeem/CL-')
.required(),
DLT_CONNECTOR: Joi.boolean()
.description('Flag to indicate if DLT-Connector is used. (Still in development)')
.default(false)
.required(),
DLT_CONNECTOR_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.default('http://localhost:6010')
.when('DLT_CONNECTOR', { is: true, then: Joi.required() })
.description('The URL for GDT API endpoint'),
EMAIL: Joi.boolean()
.default(false)
.description('Enable or disable email functionality')
.required(),
EMAIL_TEST_MODUS: Joi.boolean()
.default(false)
.description('When enabled, all emails are sended to EMAIL_TEST_RECEIVER')
.optional(),
EMAIL_TEST_RECEIVER: Joi.string()
.email()
.default('stage1@gradido.net')
.when('EMAIL_TEST_MODUS', { is: true, then: Joi.required() })
.description('Email address used in test mode'),
EMAIL_USERNAME: Joi.alternatives().conditional(Joi.ref('EMAIL'), {
is: true,
then: Joi.alternatives().conditional(Joi.ref('NODE_ENV'), {
is: 'development',
then: Joi.string()
.allow('')
.description('Username for SMTP authentication (optional in development)'),
otherwise: Joi.string()
.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)
.description('Valid SMTP username required in production')
.required(),
}),
otherwise: Joi.string().allow('').optional(),
}),
EMAIL_SENDER: Joi.string()
.email()
.when('EMAIL', { is: true, then: Joi.required() })
.default('info@gradido.net')
.description('Email address used as sender'),
EMAIL_PASSWORD: Joi.alternatives().conditional(Joi.ref('EMAIL'), {
is: true,
then: Joi.alternatives().conditional(Joi.ref('NODE_ENV'), {
is: 'development',
then: Joi.string()
.allow('')
.description('Password for SMTP authentication (optional in development)'),
otherwise: Joi.string()
.min(8)
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&#]).{8,}$/)
.description(
'Password must be at least 8 characters long, include uppercase and lowercase letters, a number, and a special character',
)
.required(),
}),
otherwise: Joi.string().allow('').optional(),
}),
EMAIL_SMTP_HOST: Joi.string()
.hostname()
.when('EMAIL', { is: true, then: Joi.required() })
.default('mailserver')
.description('SMTP server hostname'),
EMAIL_SMTP_PORT: Joi.number()
.integer()
.positive()
.when('EMAIL', { is: true, then: Joi.required() })
.default(1025)
.description('SMTP server port'),
EMAIL_TLS: Joi.boolean().default(true).description('Enable or disable TLS for SMTP').optional(),
EMAIL_LINK_VERIFICATION: Joi.string()
.uri({ scheme: ['http', 'https'] })
.custom((value: string, helpers: Joi.CustomHelpers<string>): string | Joi.ErrorReport => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
if (!value.startsWith(helpers.state.ancestors[0].COMMUNITY_URL)) {
return helpers.error('string.pattern.base', { value, communityUrl: COMMUNITY_URL })
}
return value
})
.description('Email Verification link for activate Email.')
.required(),
EMAIL_LINK_SETPASSWORD: Joi.string()
.uri({ scheme: ['http', 'https'] })
.custom((value: string, helpers: Joi.CustomHelpers<string>): string | Joi.ErrorReport => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
if (!value.startsWith(helpers.state.ancestors[0].COMMUNITY_URL)) {
return helpers.error('string.pattern.base', { value, communityUrl: COMMUNITY_URL })
}
return value
})
.description('Email Verification link for set initial Password.')
.required(),
EMAIL_LINK_FORGOTPASSWORD: Joi.string()
.uri({ scheme: ['http', 'https'] })
.custom((value: string, helpers: Joi.CustomHelpers<string>): string | Joi.ErrorReport => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
if (!value.startsWith(helpers.state.ancestors[0].COMMUNITY_URL)) {
return helpers.error('string.pattern.base', { value, communityUrl: COMMUNITY_URL })
}
return value
})
.description('Email Verification link for set new Password, when old Password was forgotten.')
.required(),
EMAIL_LINK_OVERVIEW: Joi.string()
.uri({ scheme: ['http', 'https'] })
.custom((value: string, helpers: Joi.CustomHelpers<string>): string | Joi.ErrorReport => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
if (!value.startsWith(helpers.state.ancestors[0].COMMUNITY_URL)) {
return helpers.error('string.pattern.base', { value, communityUrl: COMMUNITY_URL })
}
return value
})
.description('Link to Wallet Overview')
.required(),
EMAIL_CODE_VALID_TIME: Joi.number()
.integer()
.positive()
.max(43200) // max at 30 days
.default(1440)
.description('Time in minutes a code is valid')
.required(),
EMAIL_CODE_REQUEST_TIME: Joi.number()
.integer()
.positive()
.max(43200) // max at 30 days
.default(10)
.description('Time in minutes before a new code can be requested')
.required(),
FEDERATION_BACKEND_SEND_ON_API: Joi.string()
.pattern(/^\d+_\d+$/)
.default('1_0')
.description('API Version of sending requests to another communities, e.g., "1_0"')
.required(),
FEDERATION_VALIDATE_COMMUNITY_TIMER: Joi.number()
.integer()
.min(1000)
.default(60000)
.description('Timer interval in milliseconds for community validation')
.required(),
FEDERATION_XCOM_SENDCOINS_ENABLED: Joi.boolean()
.default(false)
.description('Enable or disable the federation send coins feature')
.optional(),
FEDERATION_XCOM_RECEIVER_COMMUNITY_UUID: Joi.string()
.uuid()
.default('56a55482-909e-46a4-bfa2-cd025e894ebc')
.description(
'UUID of the receiver community for federation cross-community transactions if the receiver is unknown',
)
.required(),
FEDERATION_XCOM_MAXREPEAT_REVERTSENDCOINS: Joi.number()
.integer()
.min(0)
.default(3)
.description('Maximum number of retries for reverting send coins transactions')
.required(),
GMS_CREATE_USER_THROW_ERRORS: Joi.boolean()
.default(false)
.when('GMS_ACTIVE', { is: true, then: Joi.required(), otherwise: Joi.optional() })
.description('Whether errors should be thrown when creating users in GMS'),
GMS_API_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.when('GMS_ACTIVE', { is: true, then: Joi.required(), otherwise: Joi.optional() })
.default('http://localhost:4044/')
.description('The API URL for the GMS service'),
GMS_DASHBOARD_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.when('GMS_ACTIVE', { is: true, then: Joi.required(), otherwise: Joi.optional() })
.default('http://localhost:8080/')
.description('The URL for the GMS dashboard'),
GMS_WEBHOOK_SECRET: Joi.string()
.min(1)
.default('secret')
.when('GMS_ACTIVE', { is: true, then: Joi.required(), otherwise: Joi.optional() })
.description('The secret postfix for the GMS webhook endpoint'),
HUMHUB_API_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.when('HUMHUB_ACTIVE', { is: true, then: Joi.required(), otherwise: Joi.optional() })
.description('The API URL for HumHub integration'),
HUMHUB_JWT_KEY: Joi.string()
.min(1)
.when('HUMHUB_ACTIVE', {
is: true,
then: Joi.required(),
otherwise: Joi.string().allow('').optional(),
})
.description('JWT key for HumHub integration, must be the same as configured in humhub'),
PORT: Joi.number()
.integer()
.min(1024)
.max(49151)
.description('Port for hosting backend, default: 4000')
.default(4000)
.required(),
KLICKTIPP: Joi.boolean()
.default(false)
.description("Indicates whether Klicktipp integration is enabled, 'true' or 'false'"),
KLICKTTIPP_API_URL: Joi.string()
.uri({ scheme: ['https'] }) // Sicherstellen, dass es eine gültige HTTPS-URL ist
.default('https://api.klicktipp.com')
.description("The API URL for Klicktipp, must be a valid URL starting with 'https'"),
KLICKTIPP_USER: Joi.string().default('gradido_test').description('The username for Klicktipp'),
KLICKTIPP_PASSWORD: Joi.string()
.min(6)
.default('secret321')
.description('The password for Klicktipp, should be at least 6 characters'),
KLICKTIPP_APIKEY_DE: Joi.string()
.default('SomeFakeKeyDE')
.description('The API key for Klicktipp (German version)'),
KLICKTIPP_APIKEY_EN: Joi.string()
.default('SomeFakeKeyEN')
.description('The API key for Klicktipp (English version)'),
USE_CRYPTO_WORKER: Joi.boolean()
.default(false)
.description(
'Flag to enable or disable password encryption in separate thread, should be enabled if possible',
),
// TODO: check format
JWT_SECRET: Joi.string()
.default('secret123')
.description('jwt secret for jwt tokens used for login')
.required(),
JWT_EXPIRES_IN: Joi.alternatives()
.try(
Joi.string()
.pattern(/^\d+[smhdw]$/) // Time specification such as “10m”, “1h”, “2d”, etc.
.description('Expiration time for JWT login token, in format like "10m", "1h", "1d"')
.default('10m'),
Joi.number()
.positive() // positive number to accept seconds
.description('Expiration time for JWT login token in seconds'),
)
.required()
.description('Time for JWT token to expire, auto logout'),
WEBHOOK_ELOPAGE_SECRET: Joi.string().description("isn't really used any more").optional(),
})

View File

@ -68,9 +68,9 @@ export class PublishNameLogic {
*/
public getUsername(publishNameType: PublishNameType): string {
if (this.isUsernameFromInitials(publishNameType)) {
return this.filterOutInvalidChar(
this.firstUpperCaseSecondLowerCase(this.user.firstName) +
this.firstUpperCaseSecondLowerCase(this.user.lastName),
return (
this.firstUpperCaseSecondLowerCase(this.filterOutInvalidChar(this.user.firstName)) +
this.firstUpperCaseSecondLowerCase(this.filterOutInvalidChar(this.user.lastName))
)
} else if (this.isUsernameFromAlias(publishNameType)) {
return this.filterOutInvalidChar(this.user.alias)

View File

@ -7,9 +7,12 @@ import { CONFIG } from '@/config'
import { sendEmailTranslated } from './sendEmailTranslated'
const testMailServerHost = 'localhost'
const testMailServerPort = 1025
CONFIG.EMAIL = false
CONFIG.EMAIL_SMTP_URL = 'EMAIL_SMTP_URL'
CONFIG.EMAIL_SMTP_PORT = 1234
CONFIG.EMAIL_SMTP_HOST = testMailServerHost
CONFIG.EMAIL_SMTP_PORT = testMailServerPort
CONFIG.EMAIL_SENDER = 'info@gradido.net'
CONFIG.EMAIL_USERNAME = 'user'
CONFIG.EMAIL_PASSWORD = 'pwd'
@ -73,8 +76,8 @@ describe('sendEmailTranslated', () => {
it('calls the transporter', () => {
expect(createTransport).toBeCalledWith({
host: 'EMAIL_SMTP_URL',
port: 1234,
host: testMailServerHost,
port: testMailServerPort,
secure: false,
requireTLS: true,
auth: {
@ -87,11 +90,6 @@ describe('sendEmailTranslated', () => {
describe('call of "sendEmailTranslated"', () => {
it('has expected result', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['receiver@mail.org', 'support@gradido.net'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'receiver@mail.org',
cc: 'support@gradido.net',
@ -135,11 +133,6 @@ describe('sendEmailTranslated', () => {
it('call of "sendEmailTranslated" with faked "to"', () => {
expect(result).toMatchObject({
envelope: {
from: CONFIG.EMAIL_SENDER,
to: [CONFIG.EMAIL_TEST_RECEIVER, 'support@gradido.net'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: CONFIG.EMAIL_TEST_RECEIVER,
cc: 'support@gradido.net',

View File

@ -45,7 +45,7 @@ export const sendEmailTranslated = async ({
receiver.to = CONFIG.EMAIL_TEST_RECEIVER
}
const transport = createTransport({
host: CONFIG.EMAIL_SMTP_URL,
host: CONFIG.EMAIL_SMTP_HOST,
port: CONFIG.EMAIL_SMTP_PORT,
secure: false, // true for 465, false for other ports
requireTLS: CONFIG.EMAIL_TLS,
@ -62,6 +62,7 @@ export const sendEmailTranslated = async ({
message: {
from: `Gradido (${i18n.__('emails.general.doNotAnswer')}) <${CONFIG.EMAIL_SENDER}>`,
},
send: CONFIG.EMAIL,
transport,
preview: false,
// i18n, // is only needed if you don't install i18n

View File

@ -25,7 +25,14 @@ import {
sendContributionChangedByModeratorEmail,
} from './sendEmailVariants'
const testMailServerHost = 'localhost'
const testMailServerPort = 1025
const testMailTLS = false
CONFIG.EMAIL_SENDER = 'info@gradido.net'
CONFIG.EMAIL_SMTP_HOST = testMailServerHost
CONFIG.EMAIL_SMTP_PORT = testMailServerPort
CONFIG.EMAIL_TLS = testMailTLS
let con: Connection
let testEnv: {
@ -93,11 +100,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -151,11 +153,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -204,11 +201,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -267,11 +259,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -329,11 +316,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -389,11 +371,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('has expected result', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -449,11 +426,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -507,11 +479,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -571,11 +538,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',
@ -633,11 +595,6 @@ describe('sendEmailVariants', () => {
describe('result', () => {
it('is the expected object', () => {
expect(result).toMatchObject({
envelope: {
from: 'info@gradido.net',
to: ['peter@lustig.de'],
},
message: expect.any(String),
originalMessage: expect.objectContaining({
to: 'Peter Lustig <peter@lustig.de>',
from: 'Gradido (emails.general.doNotAnswer) <info@gradido.net>',

View File

@ -19,7 +19,7 @@ export class ContributionLink {
this.cycle = contributionLink.cycle
this.maxPerCycle = contributionLink.maxPerCycle
this.code = contributionLink.code
this.link = CONFIG.COMMUNITY_REDEEM_CONTRIBUTION_URL.replace(/{code}/g, this.code)
this.link = CONFIG.COMMUNITY_REDEEM_CONTRIBUTION_URL + this.code
}
@Field(() => Int)

View File

@ -20,7 +20,7 @@ export class TransactionLink {
this.deletedAt = transactionLink.deletedAt
this.redeemedAt = transactionLink.redeemedAt
this.redeemedBy = redeemedBy
this.link = CONFIG.COMMUNITY_REDEEM_URL.replace(/{code}/g, this.code)
this.link = CONFIG.COMMUNITY_REDEEM_URL + this.code
}
@Field(() => Int)

View File

@ -24,6 +24,16 @@ export class GdtResolver {
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
@Ctx() context: Context,
): Promise<GdtEntryList> {
if (!CONFIG.GDT_ACTIVE) {
return new GdtEntryList(
'disabled',
0,
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
[],
0,
0,
)
}
const userEntity = getUser(context)
try {
@ -51,6 +61,9 @@ export class GdtResolver {
@Authorized([RIGHTS.GDT_BALANCE])
@Query(() => Float, { nullable: true })
async gdtBalance(@Ctx() context: Context): Promise<number | null> {
if (!CONFIG.GDT_ACTIVE) {
return null
}
const user = getUser(context)
try {
const resultGDTSum = await apiPost(`${CONFIG.GDT_API_URL}/GdtEntries/sumPerEmailApi`, {
@ -71,6 +84,9 @@ export class GdtResolver {
@Query(() => Int)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async existPid(@Arg('pid', () => Int) pid: number): Promise<number> {
if (!CONFIG.GDT_ACTIVE) {
return 0
}
// load user
const resultPID = await apiGet(`${CONFIG.GDT_API_URL}/publishers/checkPidApi/${pid}`)
if (!resultPID.success) {

View File

@ -230,8 +230,11 @@ export class TransactionResolver {
logger.addContext('user', user.id)
logger.info(`transactionList(user=${user.firstName}.${user.lastName}, ${user.emailId})`)
const gdtResolver = new GdtResolver()
const balanceGDTPromise = gdtResolver.gdtBalance(context)
let balanceGDTPromise: Promise<number | null> = Promise.resolve(null)
if (CONFIG.GDT_ACTIVE) {
const gdtResolver = new GdtResolver()
balanceGDTPromise = gdtResolver.gdtBalance(context)
}
// find current balance
const lastTransaction = await getLastTransaction(user.id)
@ -418,8 +421,10 @@ export class TransactionResolver {
).toDecimalPlaces(2, Decimal.ROUND_HALF_UP)
}
})
const balanceGDT = await balanceGDTPromise
context.balanceGDT = balanceGDT
if (CONFIG.GDT_ACTIVE) {
const balanceGDT = await balanceGDTPromise
context.balanceGDT = balanceGDT
}
// Construct Result
return new TransactionList(await balanceResolver.balance(context), transactions)

View File

@ -244,10 +244,10 @@ describe('UserResolver', () => {
describe('account activation email', () => {
it('sends an account activation email', () => {
const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace(
/{optin}/g,
emailVerificationCode,
).replace(/{code}/g, '')
const activationLink = `${
CONFIG.EMAIL_LINK_VERIFICATION
}${emailVerificationCode.toString()}`
expect(sendAccountActivationEmail).toBeCalledWith({
firstName: 'Peter',
lastName: 'Lustig',
@ -2230,14 +2230,13 @@ describe('UserResolver', () => {
})
it('sends an account activation email', async () => {
const userConatct = await UserContact.findOneOrFail({
const userContact = await UserContact.findOneOrFail({
where: { email: 'bibi@bloxberg.de' },
relations: ['user'],
})
const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace(
/{optin}/g,
userConatct.emailVerificationCode.toString(),
).replace(/{code}/g, '')
const activationLink = `${
CONFIG.EMAIL_LINK_VERIFICATION
}${userContact.emailVerificationCode.toString()}`
expect(sendAccountActivationEmail).toBeCalledWith({
firstName: 'Bibi',
lastName: 'Bloxberg',
@ -2252,14 +2251,14 @@ describe('UserResolver', () => {
})
it('stores the EMAIL_ADMIN_CONFIRMATION event in the database', async () => {
const userConatct = await UserContact.findOneOrFail({
const userContact = await UserContact.findOneOrFail({
where: { email: 'bibi@bloxberg.de' },
relations: ['user'],
})
await expect(DbEvent.find()).resolves.toContainEqual(
expect.objectContaining({
type: EventType.EMAIL_ADMIN_CONFIRMATION,
affectedUserId: userConatct.user.id,
affectedUserId: userContact.user.id,
actingUserId: admin.id,
}),
)

View File

@ -109,7 +109,7 @@ const newEmailContact = (email: string, userId: number): DbUserContact => {
// eslint-disable-next-line @typescript-eslint/ban-types
export const activationLink = (verificationCode: string): string => {
logger.debug(`activationLink(${verificationCode})...`)
return CONFIG.EMAIL_LINK_SETPASSWORD.replace(/{optin}/g, verificationCode.toString())
return CONFIG.EMAIL_LINK_SETPASSWORD + verificationCode.toString()
}
const newGradidoID = async (): Promise<string> => {
@ -371,10 +371,9 @@ export class UserResolver {
throw new LogError('Error while updating dbUser', error)
})
const activationLink = CONFIG.EMAIL_LINK_VERIFICATION.replace(
/{optin}/g,
emailContact.emailVerificationCode.toString(),
).replace(/{code}/g, redeemCode ? '/' + redeemCode : '')
const activationLink = `${
CONFIG.EMAIL_LINK_VERIFICATION
}${emailContact.emailVerificationCode.toString()}${redeemCode ? `/${redeemCode}` : ''}`
void sendAccountActivationEmail({
firstName,

View File

@ -15,6 +15,7 @@
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./build", /* Redirect output structure to the directory. */
// "rootDir" : ".",
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
@ -60,7 +61,8 @@
/* external */
"@dbTools/*": ["../database/src/*", "../../database/build/src/*"],
"@entity/*": ["../database/entity/*", "../../database/build/entity/*"],
"@logging/*": ["../database/logging/*", "../../database/build/logging/*"]
"@logging/*": ["../database/logging/*", "../../database/build/logging/*"],
"@config/*": ["../config/src/*", "../../config/build/src/*"]
},
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": ["@types", "node_modules/@types"], /* List of folders to include type definitions from. */
@ -86,9 +88,12 @@
},
"references": [
{
"path": "../database/tsconfig.json",
"path": "../database/tsconfig.json"
// add 'prepend' if you want to include the referenced project in your output file
// "prepend": true
},
{
"path": "../config/tsconfig.json"
}
]
}

View File

@ -332,13 +332,6 @@
core-js-pure "^3.30.2"
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.21.0":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
dependencies:
regenerator-runtime "^0.13.11"
"@babel/template@^7.15.4", "@babel/template@^7.3.3":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
@ -454,6 +447,18 @@
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-10.0.1.tgz#ee9da297fabc557e1c040a0f44ee89c266ccc306"
integrity sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@humanwhocodes/config-array@^0.11.8":
version "0.11.8"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
@ -473,6 +478,18 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@isaacs/cliui@^8.0.2":
version "8.0.2"
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
dependencies:
string-width "^5.1.2"
string-width-cjs "npm:string-width@^4.2.0"
strip-ansi "^7.0.1"
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
wrap-ansi "^8.1.0"
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -750,6 +767,11 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@pkgr/utils@^2.3.1":
version "2.3.1"
resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03"
@ -823,6 +845,23 @@
domhandler "^4.2.0"
selderee "^0.6.0"
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sindresorhus/is@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
@ -1064,6 +1103,13 @@
jest-diff "^27.0.0"
pretty-format "^27.0.0"
"@types/joi@^17.2.3":
version "17.2.3"
resolved "https://registry.yarnpkg.com/@types/joi/-/joi-17.2.3.tgz#b7768ed9d84f1ebd393328b9f97c1cf3d2b94798"
integrity sha512-dGjs/lhrWOa+eO0HwgxCSnDm5eMGCsXuvLglMghJq32F6q5LyyNuXb41DHzrg501CKNOSSAHmfB7FDGeUnDmzw==
dependencies:
joi "*"
"@types/json-schema@^7.0.9":
version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
@ -1128,13 +1174,13 @@
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
"@types/mysql@^2.15.8":
version "2.15.21"
resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.21.tgz#7516cba7f9d077f980100c85fd500c8210bd5e45"
integrity sha512-NPotx5CVful7yB+qZbWtXL2fA4e7aEHkihHLjklc6ID8aq7bhguHgeIoC1EmSNTAuCgI6ZXrjt2ZSaXnYX0EUg==
version "2.15.26"
resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.26.tgz#f0de1484b9e2354d587e7d2bd17a873cc8300836"
integrity sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==
dependencies:
"@types/node" "*"
"@types/node@*", "@types/node@^16.10.3":
"@types/node@*":
version "16.10.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5"
integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ==
@ -1149,6 +1195,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.21.tgz#6359d8cf73481e312a43886fa50afc70ce5592c6"
integrity sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA==
"@types/node@^17.0.21":
version "17.0.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
"@types/nodemailer@*":
version "6.4.6"
resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.6.tgz#ce21b4b474a08f672f182e15982b7945dde1f288"
@ -1528,6 +1579,11 @@ ansi-regex@^5.0.1:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-regex@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@ -1547,6 +1603,11 @@ ansi-styles@^5.0.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
ansi-styles@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@ -2396,6 +2457,15 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.0:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@ -2469,18 +2539,16 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
date-fns@^2.29.3:
version "2.30.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
dependencies:
"@babel/runtime" "^7.21.0"
date-format@^4.0.9:
version "4.0.9"
resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.9.tgz#4788015ac56dedebe83b03bc361f00c1ddcf1923"
integrity sha512-+8J+BOUpSrlKLQLeF8xJJVTxS8QfRSuJgwxSVvslzgO3E6khbI0F5mMEPf5mTYhCCm4h99knYP6H3W9n3BQFrg==
dayjs@^1.11.9:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
debug@2.6.9, debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -2714,15 +2782,20 @@ dotenv@^10.0.0:
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
dotenv@^16.0.3:
version "16.3.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e"
integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==
version "16.4.7"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
eastasianwidth@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -2757,6 +2830,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
emoji-regex@^9.2.2:
version "9.2.2"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@ -3421,6 +3499,14 @@ for-each@^0.3.3:
dependencies:
is-callable "^1.1.3"
foreground-child@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77"
integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==
dependencies:
cross-spawn "^7.0.0"
signal-exit "^4.0.1"
form-data@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
@ -3592,6 +3678,18 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
glob@^10.3.10:
version "10.4.5"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956"
integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==
dependencies:
foreground-child "^3.1.0"
jackspeak "^3.1.2"
minimatch "^9.0.4"
minipass "^7.1.2"
package-json-from-dist "^1.0.0"
path-scurry "^1.11.1"
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
version "7.2.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
@ -3604,17 +3702,6 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
global-dirs@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686"
@ -3708,8 +3795,13 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
"gradido-config@file:../config":
version "1.0.0"
dependencies:
joi "^17.13.3"
"gradido-database@file:../database":
version "2.4.1"
version "2.4.4"
dependencies:
"@types/uuid" "^8.3.4"
cross-env "^7.0.3"
@ -4451,6 +4543,15 @@ iterall@^1.1.3, iterall@^1.2.1, iterall@^1.3.0:
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea"
integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==
jackspeak@^3.1.2:
version "3.4.3"
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==
dependencies:
"@isaacs/cliui" "^8.0.2"
optionalDependencies:
"@pkgjs/parseargs" "^0.11.0"
jest-changed-files@^27.2.5:
version "27.2.5"
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.2.5.tgz#9dfd550d158260bcb6fa80aff491f5647f7daeca"
@ -4862,6 +4963,17 @@ jest@^27.2.4:
import-local "^3.0.2"
jest-cli "^27.2.5"
joi@*, joi@^17.13.3:
version "17.13.3"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
dependencies:
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.5"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
jose@^4.14.4:
version "4.14.4"
resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.4.tgz#59e09204e2670c3164ee24cbfe7115c6f8bff9ca"
@ -5148,6 +5260,11 @@ lowercase-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
lru-cache@^10.2.0:
version "10.4.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
lru-cache@^4.1.3:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
@ -5300,10 +5417,10 @@ minimatch@^3.0.5, minimatch@^3.1.2:
dependencies:
brace-expansion "^1.1.7"
minimatch@^5.0.1:
version "5.1.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
minimatch@^9.0.4:
version "9.0.5"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
dependencies:
brace-expansion "^2.0.1"
@ -5317,6 +5434,11 @@ minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
mkdirp@^2.1.3:
version "2.1.6"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19"
@ -5740,6 +5862,11 @@ p-wait-for@3.2.0:
dependencies:
p-timeout "^3.0.0"
package-json-from-dist@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==
package-json@^6.3.0:
version "6.5.0"
resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
@ -5812,6 +5939,14 @@ path-parse@^1.0.6, path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-scurry@^1.11.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
dependencies:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
@ -6173,10 +6308,10 @@ reflect-metadata@^0.1.13:
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
regenerator-runtime@^0.13.11:
version "0.13.11"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
reflect-metadata@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b"
integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==
regenerator-runtime@^0.14.0:
version "0.14.1"
@ -6479,6 +6614,11 @@ signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f"
integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==
signal-exit@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
@ -6578,6 +6718,15 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@ -6587,6 +6736,15 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
dependencies:
eastasianwidth "^0.2.0"
emoji-regex "^9.2.2"
strip-ansi "^7.0.1"
string.prototype.trimend@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
@ -6628,6 +6786,13 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@ -6635,6 +6800,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
dependencies:
ansi-regex "^6.0.1"
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
@ -6874,9 +7046,9 @@ ts-jest@^27.0.5:
yargs-parser "20.x"
ts-mysql-migrate@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/ts-mysql-migrate/-/ts-mysql-migrate-1.0.2.tgz#736d37c3aa3fef92f226b869098e939950d0e18c"
integrity sha512-zDW6iQsfPCJfQ3JMhfUGjhy8aK+VNTvPrXmJH66PB2EGEvyn4m7x2nBdhDNhKuwYU9LMxW1p+l39Ei+btXNpxA==
version "1.1.2"
resolved "https://registry.yarnpkg.com/ts-mysql-migrate/-/ts-mysql-migrate-1.1.2.tgz#6f280f4684cb95440ffa7254b926b494badb8cf3"
integrity sha512-jwhVaMrYBNNhAoZ5XISxzqbnXTHqwazqu/r1UQ6kUaGNPGL43ZFnBiXVj4Gm3pfe3xtCGIaNInehDfdDuigPgw==
dependencies:
"@types/mysql" "^2.15.8"
mysql "^2.18.1"
@ -7033,21 +7205,21 @@ typedarray-to-buffer@^3.1.5:
is-typedarray "^1.0.0"
typeorm@^0.3.16:
version "0.3.17"
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.17.tgz#a73c121a52e4fbe419b596b244777be4e4b57949"
integrity sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==
version "0.3.20"
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.20.tgz#4b61d737c6fed4e9f63006f88d58a5e54816b7ab"
integrity sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==
dependencies:
"@sqltools/formatter" "^1.2.5"
app-root-path "^3.1.0"
buffer "^6.0.3"
chalk "^4.1.2"
cli-highlight "^2.1.11"
date-fns "^2.29.3"
dayjs "^1.11.9"
debug "^4.3.4"
dotenv "^16.0.3"
glob "^8.1.0"
glob "^10.3.10"
mkdirp "^2.1.3"
reflect-metadata "^0.1.13"
reflect-metadata "^0.2.1"
sha.js "^2.4.11"
tslib "^2.5.0"
uuid "^9.0.0"
@ -7193,9 +7365,9 @@ uuid@^8.0.0, uuid@^8.3.2:
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
uuid@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
version "9.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30"
integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==
v8-to-istanbul@^8.1.0:
version "8.1.0"
@ -7374,6 +7546,15 @@ workerpool@^9.2.0:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-9.2.0.tgz#f74427cbb61234708332ed8ab9cbf56dcb1c4371"
integrity sha512-PKZqBOCo6CYkVOwAxWxQaSF2Fvb5Iv2fCeTP7buyWI2GiynWr46NcXSgK/idoV6e60dgCBfgYc+Un3HMvmqP8w==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@ -7383,6 +7564,15 @@ wrap-ansi@^7.0.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
dependencies:
ansi-styles "^6.1.0"
string-width "^5.0.1"
strip-ansi "^7.0.1"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

4
config/.eslintignore Normal file
View File

@ -0,0 +1,4 @@
node_modules
**/*.min.js
build
coverage

214
config/.eslintrc.js Normal file
View File

@ -0,0 +1,214 @@
// eslint-disable-next-line import/no-commonjs, import/unambiguous
module.exports = {
root: true,
env: {
node: true,
},
parser: '@typescript-eslint/parser',
plugins: ['prettier', '@typescript-eslint', 'type-graphql', 'import', 'n', 'promise'],
extends: [
'standard',
'eslint:recommended',
'plugin:prettier/recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:security/recommended',
'plugin:@eslint-community/eslint-comments/recommended',
],
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
project: ['./tsconfig.json', '**/tsconfig.json'],
},
node: true,
},
// the parser cannot handle the split sodium import
'import/ignore': ['sodium-native'],
},
rules: {
'no-console': 'error',
camelcase: ['error', { allow: ['crypto_*', 'randombytes_random'] }],
'no-debugger': 'error',
'prettier/prettier': [
'error',
{
htmlWhitespaceSensitivity: 'ignore',
},
],
// import
'import/export': 'error',
// 'import/no-deprecated': 'error',
'import/no-empty-named-blocks': 'error',
'import/no-extraneous-dependencies': 'error',
'import/no-mutable-exports': 'error',
'import/no-unused-modules': 'error',
'import/no-named-as-default': 'error',
'import/no-named-as-default-member': 'error',
'import/no-amd': 'error',
'import/no-commonjs': 'error',
'import/no-import-module-exports': 'error',
'import/no-nodejs-modules': 'off',
'import/unambiguous': 'error',
'import/default': 'error',
'import/named': 'error',
'import/namespace': 'error',
'import/no-absolute-path': 'error',
'import/no-cycle': 'error',
'import/no-dynamic-require': 'error',
'import/no-internal-modules': 'off',
'import/no-relative-packages': 'error',
'import/no-relative-parent-imports': [
'error',
{ ignore: ['@/*', 'random-bigint', 'sodium-native'] },
],
'import/no-self-import': 'error',
'import/no-unresolved': 'error',
'import/no-useless-path-segments': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/consistent-type-specifier-style': 'error',
'import/exports-last': 'off',
'import/extensions': 'error',
'import/first': 'error',
'import/group-exports': 'off',
'import/newline-after-import': 'error',
'import/no-anonymous-default-export': 'error',
'import/no-default-export': 'error',
'import/no-duplicates': 'error',
'import/no-named-default': 'error',
'import/no-namespace': 'error',
'import/no-unassigned-import': 'error',
'import/order': [
'error',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
'newlines-between': 'always',
pathGroups: [
{
pattern: '@?*/**',
group: 'external',
position: 'after',
},
{
pattern: '@/**',
group: 'external',
position: 'after',
},
],
alphabetize: {
order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */,
caseInsensitive: true /* ignore case. Options: [true, false] */,
},
distinctGroup: true,
},
],
'import/prefer-default-export': 'off',
// n
'n/handle-callback-err': 'error',
'n/no-callback-literal': 'error',
'n/no-exports-assign': 'error',
'n/no-extraneous-import': 'error',
'n/no-extraneous-require': 'error',
'n/no-hide-core-modules': 'error',
'n/no-missing-import': 'off', // not compatible with typescript
'n/no-missing-require': 'error',
'n/no-new-require': 'error',
'n/no-path-concat': 'error',
'n/no-process-exit': 'error',
'n/no-unpublished-bin': 'error',
'n/no-unpublished-import': 'off', // TODO need to exclude seeds
'n/no-unpublished-require': 'error',
'n/no-unsupported-features': ['error', { ignores: ['modules'] }],
'n/no-unsupported-features/es-builtins': 'error',
'n/no-unsupported-features/es-syntax': 'error',
'n/no-unsupported-features/node-builtins': 'error',
'n/process-exit-as-throw': 'error',
'n/shebang': 'error',
'n/callback-return': 'error',
'n/exports-style': 'error',
'n/file-extension-in-import': 'off',
'n/global-require': 'error',
'n/no-mixed-requires': 'error',
'n/no-process-env': 'error',
'n/no-restricted-import': 'error',
'n/no-restricted-require': 'error',
'n/no-sync': 'error',
'n/prefer-global/buffer': 'error',
'n/prefer-global/console': 'error',
'n/prefer-global/process': 'error',
'n/prefer-global/text-decoder': 'error',
'n/prefer-global/text-encoder': 'error',
'n/prefer-global/url': 'error',
'n/prefer-global/url-search-params': 'error',
'n/prefer-promises/dns': 'error',
'n/prefer-promises/fs': 'error',
// promise
'promise/catch-or-return': 'error',
'promise/no-return-wrap': 'error',
'promise/param-names': 'error',
'promise/always-return': 'error',
'promise/no-native': 'off',
'promise/no-nesting': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-callback-in-promise': 'warn',
'promise/avoid-new': 'warn',
'promise/no-new-statics': 'error',
'promise/no-return-in-finally': 'warn',
'promise/valid-params': 'warn',
'promise/prefer-await-to-callbacks': 'error',
'promise/no-multiple-resolved': 'error',
// eslint comments
'@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
'@eslint-community/eslint-comments/no-restricted-disable': 'error',
'@eslint-community/eslint-comments/no-use': 'off',
'@eslint-community/eslint-comments/require-description': 'off',
},
overrides: [
// only for ts files
{
files: ['*.ts', '*.tsx'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:@typescript-eslint/strict',
'plugin:type-graphql/recommended',
],
rules: {
// allow explicitly defined dangling promises
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
'no-void': ['error', { allowAsStatement: true }],
// ignore prefer-regexp-exec rule to allow string.match(regex)
'@typescript-eslint/prefer-regexp-exec': 'off',
// this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486
'import/unambiguous': 'off',
// this is not compatible with typeorm, due to joined tables can be null, but are not defined as nullable
'@typescript-eslint/no-unnecessary-condition': 'off',
},
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json', '**/tsconfig.json'],
// this is to properly reference the referenced project database without requirement of compiling it
// eslint-disable-next-line camelcase
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
},
},
{
files: ['*.test.ts'],
plugins: ['jest'],
env: {
jest: true,
},
rules: {
'jest/no-disabled-tests': 'error',
'jest/no-focused-tests': 'error',
'jest/no-identical-title': 'error',
'jest/prefer-to-have-length': 'error',
'jest/valid-expect': 'error',
'@typescript-eslint/unbound-method': 'off',
'jest/unbound-method': 'error',
},
},
],
}

14
config/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
node_modules/
build/
.cache/
.yarn/install-state.gz
/.env
/.env.bak
# coverage folder
coverage/
# emacs
*~

1
config/.nvmrc Normal file
View File

@ -0,0 +1 @@
v18.7.0

26
config/package.json Normal file
View File

@ -0,0 +1,26 @@
{
"name": "gradido-config",
"version": "1.0.0",
"description": "Gradido Config for validate config",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"repository": "https://github.com/gradido/gradido/config",
"author": "einhornimmond",
"license": "Apache-2.0",
"private": false,
"scripts": {
"build": "tsc --build",
"clean": "tsc --build --clean",
"test": "node test/index"
},
"devDependencies": {
"@types/joi": "^17.2.3",
"@types/node": "^17.0.21",
"typescript": "^4.3.5",
"mkdirp": "^3.0.1",
"ncp": "^2.0.0"
},
"dependencies": {
"joi": "^17.13.3"
}
}

236
config/src/commonSchema.ts Normal file
View File

@ -0,0 +1,236 @@
import Joi from 'joi'
export const browserUrls = Joi.array()
.items(Joi.string().uri())
.sparse(true)
.custom((value: string[], helpers: Joi.CustomHelpers<string[]>) => {
let protocol: string | undefined
for (const url of value) {
if (url === undefined) {
continue
}
const urlObject = new URL(url)
if(!protocol) {
protocol = urlObject.protocol
} else if(urlObject.protocol !== protocol) {
return helpers.error('any.invalid')
}
}
return value;
})
.required()
.description('All URLs need to have same protocol to prevent mixed block errors')
export const DECAY_START_TIME = Joi.date()
.iso() // ISO 8601 format for date validation
.description('The start time for decay, expected in ISO 8601 format (e.g. 2021-05-13T17:46:31Z)')
.default(new Date('2021-05-13T17:46:31Z')) // default to the specified date if not provided
.required()
export const DB_VERSION = Joi.string()
.pattern(/^\d{4}-[a-z0-9-_]+$/)
.message('DB_VERSION must be in the format: YYYY-description, e.g. "0087-add_index_on_user_roles".')
.description('db version string, last migration file name without ending or last folder in entity')
.required()
export const COMMUNITY_URL = Joi.string()
.uri({ scheme: ['http', 'https'] })
.custom((value: string, helpers: Joi.CustomHelpers<string>) => {
if (value.endsWith('/')) {
return helpers.error('any.invalid', { message: 'URL should not end with a slash (/)' })
}
return value;
})
.description('The base URL of the community, should have the same protocol as frontend, admin and backend api to prevent mixed contend issues.')
.default('http://0.0.0.0')
.required()
export const GRAPHQL_URI = Joi.string()
.uri({ scheme: ['http', 'https'] })
.description(
`
The external URL of the backend service,
accessible from outside the server (e.g., via Nginx or the server's public URL),
should have the same protocol as frontend and admin to prevent mixed contend issues.
`,
)
.default('http://0.0.0.0/graphql')
.required()
export const COMMUNITY_NAME = Joi.string()
.min(3)
.max(40)
.description('The name of the community')
.default('Gradido Entwicklung')
.required()
export const COMMUNITY_DESCRIPTION = Joi.string()
.min(10)
.max(255)
.description('A short description of the community')
.default('Die lokale Entwicklungsumgebung von Gradido.')
.required()
export const COMMUNITY_SUPPORT_MAIL = Joi.string()
.email()
.description('The support email address for the community will be used in frontend and E-Mails')
.default('support@supportmail.com')
.required()
export const COMMUNITY_LOCATION = Joi.string()
.pattern(/^[-+]?[0-9]{1,2}(\.[0-9]+)?,\s?[-+]?[0-9]{1,3}(\.[0-9]+)?$/)
.when('GMS_ACTIVE', {
is: true,
then: Joi.string().required(),
otherwise: Joi.string().optional()
})
.description('Geographical location of the community in "latitude, longitude" format')
.default('49.280377, 9.690151')
export const GRAPHIQL = Joi.boolean()
.description('Flag for enabling GraphQL playground for debugging.')
.default(false)
.when('NODE_ENV', {
is: 'development',
then: Joi.boolean().valid(true, false).required(), // only allow true in development mode
otherwise: Joi.boolean().valid(false).required() // false in any other mode
})
export const GMS_ACTIVE = Joi.boolean()
.description('Flag to indicate if the GMS (Geographic Member Search) service is used.')
.default(false)
.required()
export const GDT_ACTIVE = Joi.boolean()
.description('Flag to indicate if the GMS (Geographic Member Search) service is used.')
.default(false)
.required()
export const GDT_API_URL = Joi.string()
.uri({ scheme: ['http', 'https'] })
.default('https://gdt.gradido.net')
.when('GDT_ACTIVE', { is: true, then: Joi.required() })
.description('The URL for GDT API endpoint')
export const HUMHUB_ACTIVE = Joi.boolean()
.description('Flag to indicate if the HumHub based Community Server is used.')
.default(false)
.required()
export const LOG_LEVEL = Joi.string()
.valid('all', 'mark', 'trace', 'debug', 'info', 'warn', 'error', 'fatal', 'off')
.description('set log level')
.default('info')
.required()
export const LOG4JS_CONFIG = Joi.string()
.pattern(/^[a-zA-Z0-9-_]+\.json$/)
.message('LOG4JS_CONFIG must be a valid filename ending with .json')
.description('config file name for log4js config file')
.default('log4js-config.json')
.required()
export const LOGIN_APP_SECRET = Joi.string()
.pattern(/^[a-fA-F0-9]+$/)
.message('need to be valid hex')
.default('21ffbbc616fe')
.description('App secret for salt component for libsodium crypto_pwhash')
.required()
export const LOGIN_SERVER_KEY = Joi.string()
.pattern(/^[a-fA-F0-9]+$/)
.length(32)
.message('need to be valid hex and 32 character')
.default('a51ef8ac7ef1abf162fb7a65261acd7a')
.description('Server key for password hashing as additional salt for libsodium crypto_shorthash_keygen')
.required()
export const TYPEORM_LOGGING_RELATIVE_PATH = Joi.string()
.pattern(new RegExp('^[a-zA-Z0-9-_\./]+\.log$'))
.message('TYPEORM_LOGGING_RELATIVE_PATH must be a valid filename ending with .log')
.description('log file name for logging typeorm activities')
.default('typeorm.log')
.required()
export const DB_HOST = Joi.string()
.hostname()
.message('must be a valid host with alphanumeric characters, numbers, points and -')
.description("database host like 'localhost' or 'mariadb' in docker setup")
.default('localhost')
.required()
export const DB_PORT = Joi.number()
.integer()
.min(1024)
.max(49151)
.description('database port, default: 3306')
.default(3306)
.required()
export const DB_USER = Joi.string()
.pattern(/^[A-Za-z0-9]([A-Za-z0-9-_\.]*[A-Za-z0-9])?$/) // Validates MariaDB username rules
.min(1) // Minimum length 1
.max(16) // Maximum length 16
.message(
'Valid database username (letters, numbers, hyphens, underscores, dots allowed; no spaces, must not start or end with hyphen, dot, or underscore)'
)
.description('database username for mariadb')
.default('root')
.required()
export const DB_PASSWORD = Joi.string()
.when(Joi.ref('NODE_ENV'), {
is: 'development',
then: Joi.string().allow(''),
otherwise: Joi.string()
.min(8)
.max(32)
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>]).+$/)
.message(
'Password must be between 8 and 32 characters long, and contain at least one uppercase letter, one lowercase letter, one number, and one special character (e.g., !@#$%^&*).'
)
})
.description(
'Password for the database user. In development mode, an empty password is allowed. In other environments, a complex password is required.'
)
.default('')
.required()
export const DB_DATABASE = Joi.string()
.pattern(/^[a-zA-Z][a-zA-Z0-9_-]{1,63}$/)
.description('Database name like gradido_community (must start with a letter, and can only contain letters, numbers, underscores, or dashes)')
.default('gradido_community')
.required()
export const APP_VERSION = Joi.string()
.pattern(/^\d+\.\d+\.\d+$/)
.message('Version must be in the format "major.minor.patch" (e.g., "2.4.1")')
.description('App Version from package.json, alle modules share one version')
.required()
export const BUILD_COMMIT = Joi.string()
.pattern(/^[0-9a-f]{40}$/)
.message('The commit hash must be a 40-character hexadecimal string.')
.description('The full git commit hash.')
.optional()
export const BUILD_COMMIT_SHORT = Joi.string()
.pattern(/^[0-9a-f]{7}$/)
.message('The first 7 hexadecimal character from git commit hash.')
.description('A short version from the git commit hash.')
.required()
export const NODE_ENV = Joi.string()
.valid('production', 'development', 'test')
.default('development')
.description('Specifies the environment in which the application is running.')
export const DEBUG = Joi.boolean()
.description('Indicates whether the application is in debugging mode. Set to true when NODE_ENV is not "production".')
.default(false)
.required()
export const PRODUCTION = Joi.boolean()
.default(false)
.description('Indicates whether the application is running in production mode. Set to true when NODE_ENV is "production".')
.required()

33
config/src/index.ts Normal file
View File

@ -0,0 +1,33 @@
import { ObjectSchema } from 'joi'
export * from './commonSchema'
export function validate(schema: ObjectSchema, data: any) {
const { error } = schema.validate(data)
const schemaJson = schema.describe()
if (error) {
error.details.forEach((err) => {
const details = JSON.stringify(err, null, 2)
if (!err.context) {
throw new Error('missing context in config validation with joi: ' + details)
}
if (!schemaJson) {
throw new Error('invalid schema in config validation with joi: ' + details)
}
const key = err.context.key
if (key === undefined) {
throw new Error('missing key in config validation with joi: ' + details)
}
const value = err.context.value
const description = schemaJson.keys[key]
? schema.describe().keys[key].flags.description
: 'No description available'
if (data[key] === undefined) {
throw new Error(`Environment Variable '${key}' is missing. ${description}, details: ${details}`)
} else {
throw new Error(
`Error on Environment Variable ${key} with value = ${value}: ${err.message}. ${description}`,
)
}
})
}
}

8
config/test/index.js Normal file
View File

@ -0,0 +1,8 @@
const Joi = require('joi')
const commonSchema = require('../dist/commonSchema')
const schema = Joi.object({
commonSchema
})
// console.log(commonSchema.DECAY_START_TIME)

73
config/tsconfig.json Normal file
View File

@ -0,0 +1,73 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./build/outfile.js", /* Concatenate and emit output to single file. */
"outDir": "./build", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
"strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": ".", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [".", "../database"], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
"experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"references": [] /* Any project that is referenced must itself have a `references` array (which may be empty). */
}

70
config/yarn.lock Normal file
View File

@ -0,0 +1,70 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@types/joi@^17.2.3":
version "17.2.3"
resolved "https://registry.yarnpkg.com/@types/joi/-/joi-17.2.3.tgz#b7768ed9d84f1ebd393328b9f97c1cf3d2b94798"
integrity sha512-dGjs/lhrWOa+eO0HwgxCSnDm5eMGCsXuvLglMghJq32F6q5LyyNuXb41DHzrg501CKNOSSAHmfB7FDGeUnDmzw==
dependencies:
joi "*"
"@types/node@^17.0.21":
version "17.0.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
joi@*, joi@^17.13.3:
version "17.13.3"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
dependencies:
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.5"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
mkdirp@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==
ncp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==
typescript@^4.3.5:
version "4.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==

View File

@ -22,7 +22,7 @@
"@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
"@types/faker": "^5.5.9",
"@types/geojson": "^7946.0.13",
"@types/node": "^16.10.3",
"@types/node": "^17.0.21",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
"eslint": "^8.37.0",

View File

@ -0,0 +1,43 @@
import path from 'path'
import fs from 'fs'
// Define the regular expression pattern once
const DB_VERSION_PATTERN = /^(\d{4}-[a-z0-9-_]+)/
// Define the paths to check
const migrationsDir = path.join(__dirname, '..', '..', 'migrations')
const entitiesDir = path.join(__dirname, '..', '..', 'entity')
// Helper function to get the highest version number from the directory
function getLatestDbVersion(dir: string): string {
// Read all files and folders in the directory
const files = fs.readdirSync(dir)
// Filter out files/folders that don't match the pattern for DB_VERSION
const dbVersionFiles = files.filter((file) => file.match(DB_VERSION_PATTERN))
if (dbVersionFiles.length === 0) {
throw new Error(`couldn't found any file in ${dir} matching ${DB_VERSION_PATTERN}`)
}
// Sort files by the version number (extract the version from the filename)
const sortedFiles = dbVersionFiles.sort()
const lastFile = sortedFiles[sortedFiles.length - 1]
const matches = lastFile.match(DB_VERSION_PATTERN)
if (!matches || matches.length < 1) {
throw new Error('invalid match')
}
// Return the latest version file or folder
return matches[1]
}
// Get the latest version from migrations and entities
const latestMigrationVersion = getLatestDbVersion(migrationsDir)
const latestEntityVersion = getLatestDbVersion(entitiesDir)
// Determine which directory has the latest version and return it
export const latestDbVersion =
latestMigrationVersion && (!latestEntityVersion || latestMigrationVersion > latestEntityVersion)
? latestMigrationVersion
: latestEntityVersion

View File

@ -170,10 +170,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.1.tgz#c6b9198178da504dfca1fd0be9b2e1002f1586f0"
integrity sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==
"@types/node@^16.10.3":
version "16.10.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.3.tgz#7a8f2838603ea314d1d22bb3171d899e15c57bd5"
integrity sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ==
"@types/node@^17.0.21":
version "17.0.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
"@types/semver@^7.3.12":
version "7.5.0"

View File

@ -9,7 +9,7 @@ EMAIL=true
EMAIL_USERNAME=peter@lustig.de
EMAIL_SENDER=peter@lustig.de
EMAIL_PASSWORD=1234
EMAIL_SMTP_URL=smtp.lustig.de
EMAIL_SMTP_HOST=smtp.lustig.de
EMAIL_SMTP_PORT=587
# if set to true allow sending gradidos to another communities
@ -55,15 +55,15 @@ WEBHOOK_GITHUB_BRANCH=master
# 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}
COMMUNITY_REDEEM_PATH=/redeem/
COMMUNITY_REDEEM_CONTRIBUTION_PATH=/redeem/CL-
WALLET_LOGIN_PATH=/login
WALLET_AUTH_PATH=/authenticate?token={token}
EMAIL_LINK_VERIFICATION_PATH=/checkEmail/{optin}{code}
EMAIL_LINK_SETPASSWORD_PATH=/reset-password/{optin}
WALLET_AUTH_PATH=/authenticate?token=
EMAIL_LINK_VERIFICATION_PATH=/checkEmail/
EMAIL_LINK_SETPASSWORD_PATH=/reset-password/
EMAIL_LINK_FORGOTPASSWORD_PATH=/forgot-password
EMAIL_LINK_OVERVIEW_PATH=/overview
ADMIN_AUTH_PATH=/admin/authenticate?token={token}
ADMIN_AUTH_PATH=/admin/authenticate?token=
GRAPHQL_PATH=/graphql
# login expire time
@ -82,7 +82,7 @@ FEDERATION_VALIDATE_COMMUNITY_TIMER=60000
FEDERATION_COMMUNITY_APIS=1_0
# externe gradido services (more added in future)
GDT_API_URL=https://gdt.gradido.net
GDT_ACTIVE=false
# DLT-Connector (still in develop)
DLT_CONNECTOR=false
@ -117,7 +117,6 @@ NGINX_SSL_INCLUDE=/etc/letsencrypt/options-ssl-nginx.conf
NGINX_REWRITE_LEGACY_URLS=false
# LEGACY
DEFAULT_PUBLISHER_ID=2896
WEBHOOK_ELOPAGE_SECRET=secret
# GMS

View File

@ -145,6 +145,7 @@ find /tmp -name "yarn--*" -exec rm -r {} \;
# Remove node_modules folders
# we had problems with corrupted node_modules folder
rm -Rf $PROJECT_ROOT/database/node_modules
rm -Rf $PROJECT_ROOT/config/node_modules
rm -Rf $PROJECT_ROOT/backend/node_modules
rm -Rf $PROJECT_ROOT/frontend/node_modules
rm -Rf $PROJECT_ROOT/admin/node_modules
@ -154,6 +155,7 @@ rm -Rf $PROJECT_ROOT/federation/node_modules
# Remove build folders
# we had problems with corrupted incremtal builds
rm -Rf $PROJECT_ROOT/database/build
rm -Rf $PROJECT_ROOT/config/build
rm -Rf $PROJECT_ROOT/backend/build
rm -Rf $PROJECT_ROOT/frontend/build
rm -Rf $PROJECT_ROOT/admin/build
@ -186,6 +188,12 @@ else
yarn up
fi
# Install & build config
echo 'Updating config' >> $UPDATE_HTML
cd $PROJECT_ROOT/config
yarn install
yarn build
# Install & build backend
echo 'Updating backend' >> $UPDATE_HTML
cd $PROJECT_ROOT/backend

View File

@ -47,6 +47,7 @@ RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
RUN mkdir -p /database
RUN mkdir -p /config
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
@ -59,7 +60,7 @@ FROM base as development
# Run command
# (for development we need to execute yarn install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "cd /database && yarn install && yarn build && cd /app && yarn install && yarn run dev"
CMD /bin/sh -c "cd /database && yarn install && yarn build && cd /config && yarn install && cd /app && yarn install && yarn run dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
@ -70,6 +71,11 @@ FROM base as build
COPY ./dht-node/ ./
# Copy everything from database
COPY ./database/ ../database/
# Copy everything from config
COPY ./config/ ../config/
# yarn install and build config
RUN cd ../config && yarn install --production=false --frozen-lockfile --non-interactive && yarn run build
# yarn install dht-node
RUN yarn install --production=false --frozen-lockfile --non-interactive
@ -99,9 +105,11 @@ FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
COPY --from=build ${DOCKER_WORKDIR}/../database/build ../database/build
COPY --from=build ${DOCKER_WORKDIR}/../config/build ../config/build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
COPY --from=build ${DOCKER_WORKDIR}/../database/node_modules ../database/node_modules
COPY --from=build ${DOCKER_WORKDIR}/../config/node_modules ../config/node_modules
# Copy static files
# COPY --from=build ${DOCKER_WORKDIR}/public ./public

View File

@ -31,5 +31,10 @@ module.exports = {
process.env.NODE_ENV === 'development'
? '<rootDir>/../database/src/$1'
: '<rootDir>/../database/build/src/$1',
'@config/(.*)':
// eslint-disable-next-line n/no-process-env
process.env.NODE_ENV === 'development'
? '<rootDir>/../config/src/$1'
: '<rootDir>/../config/build/$1',
},
}

View File

@ -19,7 +19,9 @@
"@hyperswarm/dht": "^6.4.4",
"cross-env": "^7.0.3",
"dotenv": "10.0.0",
"gradido-config": "file:../config",
"gradido-database": "file:../database",
"joi": "^17.13.3",
"log4js": "^6.7.1",
"nodemon": "^2.0.20",
"tsconfig-paths": "^4.1.2",
@ -29,6 +31,7 @@
"@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
"@types/dotenv": "^8.2.0",
"@types/jest": "^27.0.2",
"@types/joi": "^17.2.3",
"@types/node": "^18.11.18",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.57.1",

View File

@ -1,18 +1,17 @@
/* eslint-disable n/no-process-env */
import { validate } from '@config/index'
import { latestDbVersion } from '@dbTools/config/detectLastDBVersion'
import dotenv from 'dotenv'
import { schema } from './schema'
dotenv.config()
const constants = {
DB_VERSION: '0087-add_index_on_user_roles',
DB_VERSION: latestDbVersion,
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v4.2024-01-17',
CURRENT: '',
},
}
const server = {
@ -46,18 +45,6 @@ const federation = {
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
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,
)
) {
throw new Error(
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
)
}
export const CONFIG = {
...constants,
...server,
@ -65,3 +52,4 @@ export const CONFIG = {
...community,
...federation,
}
validate(schema, CONFIG)

View File

@ -0,0 +1,64 @@
import {
COMMUNITY_NAME,
COMMUNITY_DESCRIPTION,
DB_DATABASE,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
LOG4JS_CONFIG,
LOG_LEVEL,
NODE_ENV,
PRODUCTION,
TYPEORM_LOGGING_RELATIVE_PATH,
} from '@config/commonSchema'
import Joi from 'joi'
export const schema = Joi.object({
COMMUNITY_NAME,
COMMUNITY_DESCRIPTION,
DB_DATABASE,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
LOG4JS_CONFIG,
LOG_LEVEL,
NODE_ENV,
PRODUCTION,
TYPEORM_LOGGING_RELATIVE_PATH,
FEDERATION_DHT_TOPIC: Joi.string()
.default('GRADIDO_HUB')
.description('The topic for the DHT (Distributed Hash Table), defaults to GRADIDO_HUB')
.required(),
FEDERATION_DHT_SEED: Joi.string()
.when('NODE_ENV', {
is: 'development',
then: Joi.allow(null), // Allow empty for development
otherwise: Joi.string()
.hex()
.length(64)
.message('need to be valid hex with 64 character')
.required(), // Valid hex and 64 characters for other environments
})
.description(
'Seed for libsodium crypto_sign_seed_keypair. Valid hex with 64 characters in production',
)
.default(''), // Default to empty string
FEDERATION_COMMUNITY_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.default(Joi.ref('COMMUNITY_URL'))
.description('Community URL for federation, defaults to COMMUNITY_URL')
.required(),
FEDERATION_COMMUNITY_APIS: Joi.string()
.valid('1_0', '1_1')
.default('1_0')
.description('Federation community API version, defaults to 1_0')
.required(),
})

View File

@ -53,7 +53,8 @@
"@typeorm/*": ["../backend/src/typeorm/*", "../../backend/src/typeorm/*"],
"@dbTools/*": ["../database/src/*", "../../database/build/src/*"],
"@entity/*": ["../database/entity/*", "../../database/build/entity/*"],
"@logging/*": ["../database/logging/*", "../../database/build/logging/*"]
"@logging/*": ["../database/logging/*", "../../database/build/logging/*"],
"@config/*": ["../config/src/*", "../../config/build/src/*"]
},
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": ["src/dht_node/@types", "node_modules/@types"], /* List of folders to include type definitions from. */
@ -82,6 +83,12 @@
"path": "../database/tsconfig.json",
// add 'prepend' if you want to include the referenced project in your output file
// "prepend": true
},
{
"path": "../config/tsconfig.json",
// add 'prepend' if you want to include the referenced project in your output file
// "prepend": true
}
]
}

View File

@ -345,6 +345,18 @@
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6"
integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@humanwhocodes/config-array@^0.11.10":
version "0.11.10"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
@ -665,6 +677,23 @@
picocolors "^1.0.0"
tslib "^2.5.0"
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sinonjs/commons@^1.7.0":
version "1.8.6"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9"
@ -783,6 +812,13 @@
jest-matcher-utils "^27.0.0"
pretty-format "^27.0.0"
"@types/joi@^17.2.3":
version "17.2.3"
resolved "https://registry.yarnpkg.com/@types/joi/-/joi-17.2.3.tgz#b7768ed9d84f1ebd393328b9f97c1cf3d2b94798"
integrity sha512-dGjs/lhrWOa+eO0HwgxCSnDm5eMGCsXuvLglMghJq32F6q5LyyNuXb41DHzrg501CKNOSSAHmfB7FDGeUnDmzw==
dependencies:
joi "*"
"@types/json-schema@^7.0.9":
version "7.0.11"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
@ -2393,8 +2429,13 @@ graceful-fs@^4.2.4:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
"gradido-config@file:../config":
version "1.0.0"
dependencies:
joi "^17.13.3"
"gradido-database@file:../database":
version "2.2.1"
version "2.4.4"
dependencies:
"@types/uuid" "^8.3.4"
cross-env "^7.0.3"
@ -3226,6 +3267,17 @@ jest@^27.2.4:
import-local "^3.0.2"
jest-cli "^27.5.1"
joi@*, joi@^17.13.3:
version "17.13.3"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
dependencies:
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.5"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

View File

@ -9,7 +9,7 @@ services:
build:
target: development
environment:
- NODE_ENV="development"
- NODE_ENV=development
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
@ -27,7 +27,7 @@ services:
build:
target: development
environment:
- NODE_ENV="development"
- NODE_ENV=development
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
@ -55,9 +55,12 @@ services:
- backend_node_modules:/app/node_modules
- backend_database_node_modules:/database/node_modules
- backend_database_build:/database/build
- backend_config_node_modules:/config/node_modules
- backend_config_build:/config/build
# bind the local folder to the docker to allow live reload
- ./backend:/app
- ./database:/database
- ./config:/config
########################################################
# DHT-NODE #############################################
@ -78,9 +81,12 @@ services:
- dht_node_modules:/app/node_modules
- dht_database_node_modules:/database/node_modules
- dht_database_build:/database/build
- dht_config_node_modules:/config/node_modules
- dht_config_build:/config/build
# bind the local folder to the docker to allow live reload
- ./dht-node:/app
- ./database:/database
- ./config:/config
########################################################
# DLT-CONNECTOR ########################################
@ -122,9 +128,12 @@ services:
- federation_node_modules:/app/node_modules
- federation_database_node_modules:/database/node_modules
- federation_database_build:/database/build
- federation_config_node_modules:/config/node_modules
- federation_config_build:/config/build
# bind the local folder to the docker to allow live reload
- ./federation:/app
- ./database:/database
- ./config:/config
########################################################
# DATABASE ##############################################
@ -216,13 +225,19 @@ volumes:
backend_node_modules:
backend_database_node_modules:
backend_database_build:
backend_config_node_modules:
backend_config_build:
dht_node_modules:
dht_database_node_modules:
dht_database_build:
dht_config_node_modules:
dht_config_build:
dlt_connector_modules:
federation_node_modules:
federation_database_node_modules:
federation_database_build:
federation_config_node_modules:
federation_config_build:
database_node_modules:
database_build:
dlt-database_node_modules:

View File

@ -7,7 +7,7 @@ services:
build:
target: test
environment:
- NODE_ENV="test"
- NODE_ENV=test
########################################################
# ADMIN INTERFACE ######################################
@ -17,7 +17,7 @@ services:
build:
target: test
environment:
- NODE_ENV="test"
- NODE_ENV=test
########################################################
# BACKEND ##############################################
@ -31,7 +31,7 @@ services:
- external-net
- internal-net
environment:
- NODE_ENV="test"
- NODE_ENV=test
- DB_HOST=mariadb
########################################################
@ -46,7 +46,7 @@ services:
- external-net
- internal-net
environment:
- NODE_ENV="test"
- NODE_ENV="test
- DB_HOST=mariadb
########################################################
@ -61,7 +61,7 @@ services:
- external-net
- internal-net
environment:
- NODE_ENV="test"
- NODE_ENV=test
- DB_HOST=mariadb
########################################################
@ -73,7 +73,7 @@ services:
context: ./database
target: test_up
environment:
- NODE_ENV="test"
- NODE_ENV=test
# restart: always # this is very dangerous, but worth a test for the delayed mariadb startup at first run
########################################################
@ -85,7 +85,7 @@ services:
context: ./dlt-database
target: test_up
environment:
- NODE_ENV="test"
- NODE_ENV=test
# restart: always # this is very dangerous, but worth a test for the delayed mariadb startup at first run
#########################################################

View File

@ -12,7 +12,8 @@ services:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: gradido/frontend:local-production
build:
context: ./frontend
context: ./
dockerfile: ./frontend/Dockerfile
target: production
networks:
- external-net
@ -26,7 +27,9 @@ services:
# - BUILD_DATE="1970-01-01T00:00:00.00Z"
# - BUILD_VERSION="0.0.0.0"
# - BUILD_COMMIT="0000000"
- NODE_ENV="production"
- NODE_ENV=production
volumes:
- ./config:/config
# env_file:
# - ./.env
# - ./frontend/.env
@ -38,7 +41,8 @@ services:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: gradido/admin:local-production
build:
context: ./admin
context: ./
dockerfile: ./admin/Dockerfile
target: production
networks:
- external-net
@ -52,7 +56,9 @@ services:
# - BUILD_DATE="1970-01-01T00:00:00.00Z"
# - BUILD_VERSION="0.0.0.0"
# - BUILD_COMMIT="0000000"
- NODE_ENV="production"
- NODE_ENV=production
volumes:
- ./config:/config
# env_file:
# - ./.env
# - ./admin/.env

View File

@ -44,6 +44,7 @@ RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
RUN mkdir -p /database
RUN mkdir -p /config
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
@ -56,7 +57,7 @@ FROM base as development
# Run command
# (for development we need to execute yarn install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "cd /database && yarn install && yarn build && cd /app && yarn install && yarn run dev"
CMD /bin/sh -c "cd /database && yarn install && yarn build && cd /config && yarn install && cd /app && yarn install && yarn run dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
@ -67,6 +68,11 @@ FROM base as build
COPY ./federation/ ./
# Copy everything from database
COPY ./database/ ../database/
# Copy everything from config
COPY ./config/ ../config/
# yarn install and build config
RUN cd ../config && yarn install --production=false --frozen-lockfile --non-interactive && yarn run build
# yarn install federation
RUN yarn install --production=false --frozen-lockfile --non-interactive
@ -96,9 +102,11 @@ FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
COPY --from=build ${DOCKER_WORKDIR}/../database/build ../database/build
COPY --from=build ${DOCKER_WORKDIR}/../config/build ../config/build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
COPY --from=build ${DOCKER_WORKDIR}/../database/node_modules ../database/node_modules
COPY --from=build ${DOCKER_WORKDIR}/../config/node_modules ../config/node_modules
# Copy static files
# COPY --from=build ${DOCKER_WORKDIR}/public ./public

View File

@ -33,5 +33,10 @@ module.exports = {
process.env.NODE_ENV === 'development'
? '<rootDir>/../database/src/$1'
: '<rootDir>/../database/build/src/$1',
'@config/(.*)':
// eslint-disable-next-line n/no-process-env
process.env.NODE_ENV === 'development'
? '<rootDir>/../config/src/$1'
: '<rootDir>/../config/build/$1',
},
}

View File

@ -28,6 +28,7 @@
"graphql": "15.5.1",
"graphql-request": "5.0.0",
"helmet": "^7.1.0",
"joi": "^17.13.3",
"lodash.clonedeep": "^4.5.0",
"log4js": "^6.7.1",
"reflect-metadata": "^0.1.13",
@ -38,6 +39,7 @@
"devDependencies": {
"@types/express": "4.17.12",
"@types/jest": "27.0.2",
"@types/joi": "^17.2.3",
"@types/lodash.clonedeep": "^4.5.6",
"@types/node": "^16.10.3",
"@types/sodium-native": "^2.3.5",
@ -56,6 +58,7 @@
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-security": "^1.7.1",
"eslint-plugin-type-graphql": "^1.0.0",
"gradido-config": "../config",
"graphql-tag": "^2.12.6",
"jest": "^27.2.4",
"nodemon": "^2.0.7",

View File

@ -1,7 +1,12 @@
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
import { Decimal } from 'decimal.js-light'
import { latestDbVersion } from '@dbTools/config/detectLastDBVersion'
import dotenv from 'dotenv'
import { validate } from '@config/index'
import { schema } from './schema'
dotenv.config()
Decimal.set({
@ -10,16 +15,11 @@ Decimal.set({
})
const constants = {
DB_VERSION: '0087-add_index_on_user_roles',
DB_VERSION: latestDbVersion,
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',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v2.2023-08-24',
CURRENT: '',
},
}
const server = {
@ -38,18 +38,6 @@ const database = {
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
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,
)
) {
throw new Error(
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
)
}
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}`
@ -74,4 +62,6 @@ export const CONFIG = {
...federation,
}
validate(schema, CONFIG)
export default CONFIG

View File

@ -0,0 +1,75 @@
import {
DB_DATABASE,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
DECAY_START_TIME,
GRAPHIQL,
LOG4JS_CONFIG,
LOG_LEVEL,
NODE_ENV,
PRODUCTION,
TYPEORM_LOGGING_RELATIVE_PATH,
} from '@config/commonSchema'
import Joi from 'joi'
export const schema = Joi.object({
DB_DATABASE,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
DECAY_START_TIME,
GRAPHIQL,
LOG4JS_CONFIG,
LOG_LEVEL,
NODE_ENV,
PRODUCTION,
TYPEORM_LOGGING_RELATIVE_PATH,
FEDERATION_API: Joi.string()
.valid('1_0', '1_1')
.default('1_0')
.description('Federation API version, defaults to 1_0')
.required(),
FEDERATION_PORT: Joi.number()
.integer()
.min(1024)
.max(49151)
.default(5010)
.description('Port number for the federation service, defaults to 5010')
.required(),
FEDERATION_COMMUNITY_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.default(Joi.ref('COMMUNITY_URL'))
.description('Community URL for federation, defaults to COMMUNITY_URL')
.required(),
FEDERATION_TRADING_LEVEL: Joi.object({
RECEIVER_COMMUNITY_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.default('https://stage3.gradido.net/api/')
.description('URL of the receiver community for trading')
.required(),
SEND_COINS: Joi.boolean()
.default(true)
.description('Indicates if coins can be sent to the receiver community')
.required(),
AMOUNT: Joi.number()
.integer()
.min(1)
.default(100)
.description('Maximum amount of coins allowed for trading')
.required(),
})
.default()
.description('Trading level configuration for federation')
.optional(),
})

View File

@ -61,7 +61,8 @@
"@typeorm/*": ["../backend/src/typeorm/*", "../../backend/src/typeorm/*"],
"@dbTools/*": ["../database/src/*", "../../database/build/src/*"],
"@entity/*": ["../database/entity/*", "../../database/build/entity/*"],
"@logging/*": ["../database/logging/*", "../../database/build/logging/*"]
"@logging/*": ["../database/logging/*", "../../database/build/logging/*"],
"@config/*": ["../config/src/*", "../../config/build/src/*"]
},
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */
@ -90,6 +91,11 @@
"path": "../database/tsconfig.json",
// add 'prepend' if you want to include the referenced project in your output file
// "prepend": true
},
{
"path": "../config/tsconfig.json",
// add 'prepend' if you want to include the referenced project in your output file
// "prepend": true
}
]
}

View File

@ -379,6 +379,18 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@humanwhocodes/config-array@^0.11.10":
version "0.11.10"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
@ -722,6 +734,23 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sinonjs/commons@^1.7.0":
version "1.8.6"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9"
@ -941,6 +970,13 @@
jest-diff "^27.0.0"
pretty-format "^27.0.0"
"@types/joi@^17.2.3":
version "17.2.3"
resolved "https://registry.yarnpkg.com/@types/joi/-/joi-17.2.3.tgz#b7768ed9d84f1ebd393328b9f97c1cf3d2b94798"
integrity sha512-dGjs/lhrWOa+eO0HwgxCSnDm5eMGCsXuvLglMghJq32F6q5LyyNuXb41DHzrg501CKNOSSAHmfB7FDGeUnDmzw==
dependencies:
joi "*"
"@types/json-schema@^7.0.9":
version "7.0.12"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
@ -3027,6 +3063,11 @@ graceful-fs@^4.2.4:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
gradido-config@../config:
version "1.0.0"
dependencies:
joi "^17.13.3"
grapheme-splitter@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
@ -3944,6 +3985,17 @@ jest@^27.2.4:
import-local "^3.0.2"
jest-cli "^27.5.1"
joi@*, joi@^17.13.3:
version "17.13.3"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
dependencies:
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.5"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"

View File

@ -1,9 +1,6 @@
# Environment
DEFAULT_PUBLISHER_ID=2896
# Endpoints
GRAPHQL_PATH=/graphql
ADMIN_AUTH_PATH=/admin/authenticate?token={token}
ADMIN_AUTH_PATH=/admin/authenticate?token=
# Community
COMMUNITY_NAME=Gradido Entwicklung

View File

@ -1,8 +1,5 @@
CONFIG_VERSION=$FRONTEND_CONFIG_VERSION
# Environment
DEFAULT_PUBLISHER_ID=$DEFAULT_PUBLISHER_ID
# Endpoints
GRAPHQL_PATH=$GRAPHQL_PATH
ADMIN_AUTH_PATH=$ADMIN_AUTH_PATH
@ -16,7 +13,7 @@ COMMUNITY_DESCRIPTION=$COMMUNITY_DESCRIPTION
COMMUNITY_SUPPORT_MAIL=$COMMUNITY_SUPPORT_MAIL
# Meta
META_URL=$COMMUNITY_HOST
META_URL=$URL_PROTOCOL://$COMMUNITY_HOST
META_TITLE_DE=$META_TITLE_DE
META_TITLE_EN=$META_TITLE_EN
META_DESCRIPTION_DE=$META_DESCRIPTION_DE

View File

@ -11,7 +11,7 @@ ENV BUILD_DATE="1970-01-01T00:00:00.00Z"
## We cannot do $(npm run version).${BUILD_NUMBER} here so we default to 0.0.0.0
ENV BUILD_VERSION="0.0.0.0"
## We cannot do `$(git rev-parse --short HEAD)` here so we default to 0000000
ENV BUILD_COMMIT="0000000"
ENV BUILD_COMMIT_SHORT="0000000"
## SET NODE_ENV
ENV NODE_ENV="production"
## App relevant Envs
@ -42,6 +42,8 @@ EXPOSE ${PORT}
RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
RUN mkdir -p /config
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
##################################################################################
@ -53,7 +55,7 @@ FROM base as development
# Run command
# (for development we need to execute npm install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "yarn install && yarn run dev"
CMD /bin/sh -c "cd /config && yarn install && yarn build && cd /app && yarn install && yarn run dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
@ -61,9 +63,17 @@ CMD /bin/sh -c "yarn install && yarn run dev"
FROM base as build
# Copy everything
COPY . .
COPY ./frontend ./
# Copy everything from config
COPY ./config/ ../config/
# install and build config
RUN cd ../config && yarn install --production=false --frozen-lockfile --non-interactive && yarn build
# npm install
RUN yarn global add node-gyp && yarn install --production=false --frozen-lockfile --non-interactive
# npm build
RUN yarn run build
@ -85,6 +95,7 @@ FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
COPY --from=build ${DOCKER_WORKDIR}/../config/build ../config/build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
# Copy static files

View File

@ -91,6 +91,8 @@
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-vitest": "^0.5.4",
"eslint-plugin-vue": "8.7.1",
"gradido-config": "../config",
"joi": "^17.13.3",
"jsdom": "^25.0.0",
"mock-apollo-client": "^1.2.1",
"postcss": "^8.4.8",

View File

@ -6,11 +6,6 @@ const pkg = require('../../package')
const constants = {
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v7.2024-08-06',
CURRENT: '',
},
}
const version = {
@ -18,12 +13,13 @@ const version = {
FRONTEND_MODULE_HOST: process.env.FRONTEND_MODULE_HOST ?? '0.0.0.0',
FRONTEND_MODULE_PORT: process.env.FRONTEND_MODULE_PORT ?? '3000',
APP_VERSION: pkg.version,
BUILD_COMMIT: process.env.BUILD_COMMIT ?? null,
BUILD_COMMIT: process.env.BUILD_COMMIT ?? undefined,
// 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),
}
let FRONTEND_MODULE_URL
// in case of hosting the frontend module with a nodejs-instance
if (process.env.FRONTEND_HOSTING === 'nodejs') {
FRONTEND_MODULE_URL =
@ -50,7 +46,6 @@ 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,
}
// const COMMUNITY_HOST = process.env.COMMUNITY_HOST ?? 'localhost'
@ -61,7 +56,7 @@ const endpoints = {
GRAPHQL_URI: process.env.GRAPHQL_URI ?? COMMUNITY_URL + (process.env.GRAPHQL_PATH ?? '/graphql'),
ADMIN_AUTH_URL:
process.env.ADMIN_AUTH_URL ??
COMMUNITY_URL + (process.env.ADMIN_AUTH_PATH ?? '/admin/authenticate?token={token}'),
COMMUNITY_URL + (process.env.ADMIN_AUTH_PATH ?? '/admin/authenticate?token='),
}
const community = {
@ -93,26 +88,15 @@ const meta = {
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
if (
![constants.CONFIG_VERSION.EXPECTED, constants.CONFIG_VERSION.DEFAULT].includes(
constants.CONFIG_VERSION.CURRENT,
)
) {
throw new Error(
`Fatal: Config Version incorrect - expected "${constants.CONFIG_VERSION.EXPECTED}" or "${constants.CONFIG_VERSION.DEFAULT}", but found "${constants.CONFIG_VERSION.CURRENT}"`,
)
}
const CONFIG = {
...constants,
...version,
...features,
...environment,
...endpoints,
...community,
...meta,
...constants,
FRONTEND_MODULE_URL,
}
module.exports = CONFIG

View File

@ -0,0 +1,167 @@
const {
APP_VERSION,
BUILD_COMMIT,
BUILD_COMMIT_SHORT,
COMMUNITY_DESCRIPTION,
COMMUNITY_NAME,
COMMUNITY_SUPPORT_MAIL,
COMMUNITY_LOCATION,
COMMUNITY_URL,
DEBUG,
DECAY_START_TIME,
GMS_ACTIVE,
GRAPHQL_URI,
HUMHUB_ACTIVE,
NODE_ENV,
PRODUCTION,
} = require('gradido-config/build/src/commonSchema.js')
const Joi = require('joi')
// console.log(commonSchema)
module.exports = Joi.object({
APP_VERSION,
BUILD_COMMIT,
BUILD_COMMIT_SHORT,
COMMUNITY_DESCRIPTION,
COMMUNITY_NAME,
COMMUNITY_SUPPORT_MAIL,
COMMUNITY_LOCATION,
COMMUNITY_URL,
DEBUG,
DECAY_START_TIME,
GMS_ACTIVE,
GRAPHQL_URI,
HUMHUB_ACTIVE,
NODE_ENV,
PRODUCTION,
ADMIN_AUTH_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.description('Extern Url for admin-frontend')
.default('http://0.0.0.0/admin/authenticate?token=')
.required(),
COMMUNITY_REGISTER_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.description('URL for Register a new Account in frontend.')
.required(),
FRONTEND_HOSTING: Joi.string()
.valid('nodejs', 'nginx')
.description('set to `nodejs` if frontend is hosted by vite with a own nodejs instance')
.optional(),
FRONTEND_MODULE_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.when('COMMUNITY_URL', {
is: Joi.exist(),
then: Joi.optional(), // not required if COMMUNITY_URL is provided
otherwise: Joi.required(), // required if COMMUNITY_URL is missing
})
.description(
"Base Url for reaching frontend in browser, only needed if COMMUNITY_URL wasn't set",
)
.optional(), // optional in general, but conditionally required
FRONTEND_MODULE_PROTOCOL: Joi.string()
.when('FRONTEND_HOSTING', {
is: Joi.valid('nodejs'),
then: Joi.valid('http').required(),
otherwise: Joi.valid('http', 'https').required(),
})
.description(
`
Protocol for frontend module hosting
- it has to be the same as for backend api url and admin to prevent mixed block errors,
- if frontend is served with nodejs:
is have to be http or setup must be updated to include a ssl certificate
`,
)
.default('http')
.required(),
FRONTEND_MODULE_HOST: Joi.alternatives()
.try(
Joi.string().valid('localhost').messages({ 'any.invalid': 'Must be localhost' }),
Joi.string()
.ip({ version: ['ipv4'] })
.messages({ 'string.ip': 'Must be a valid IPv4 address' }),
Joi.string().domain().messages({ 'string.domain': 'Must be a valid domain' }),
)
.when('FRONTEND_HOSTING', {
is: 'nodejs',
then: Joi.required(),
otherwise: Joi.optional(),
})
.when('COMMUNITY_URL', {
is: null,
then: Joi.required(),
otherwise: Joi.optional(),
})
.description(
'Host (domain, IPv4, or localhost) for the frontend, default is 0.0.0.0 for local hosting during development.',
)
.default('0.0.0.0'),
FRONTEND_MODULE_PORT: Joi.number()
.integer()
.min(1024)
.max(49151)
.description('Port for hosting Frontend with Vite as a Node.js instance, default: 3000')
.default(3000)
.when('FRONTEND_HOSTING', {
is: 'nodejs',
then: Joi.required(),
otherwise: Joi.optional(),
}),
META_URL: Joi.string()
.uri({ scheme: ['http', 'https'] })
.description('The base URL for the meta tags.')
.default('http://localhost')
.required(),
META_TITLE_DE: Joi.string()
.description('Meta title in German.')
.default('Gradido Dein Dankbarkeitskonto')
.required(),
META_TITLE_EN: Joi.string()
.description('Meta title in English.')
.default('Gradido - Your gratitude account')
.required(),
META_DESCRIPTION_DE: Joi.string()
.description('Meta description in German.')
.default(
'Dankbarkeit ist die Währung der neuen Zeit. Immer mehr Menschen entfalten ihr Potenzial und gestalten eine gute Zukunft für alle.',
)
.required(),
META_DESCRIPTION_EN: Joi.string()
.description('Meta description in English.')
.default(
'Gratitude is the currency of the new age. More and more people are unleashing their potential and shaping a good future for all.',
)
.required(),
META_KEYWORDS_DE: Joi.string()
.description('Meta keywords in German.')
.default(
'Grundeinkommen, Währung, Dankbarkeit, Schenk-Ökonomie, Natürliche Ökonomie des Lebens, Ökonomie, Ökologie, Potenzialentfaltung, Schenken und Danken, Kreislauf des Lebens, Geldsystem',
)
.required(),
META_KEYWORDS_EN: Joi.string()
.description('Meta keywords in English.')
.default(
'Basic Income, Currency, Gratitude, Gift Economy, Natural Economy of Life, Economy, Ecology, Potential Development, Giving and Thanking, Cycle of Life, Monetary System',
)
.required(),
META_AUTHOR: Joi.string()
.description('The author for the meta tags.')
.default('Bernd Hückstädt - Gradido-Akademie')
.required(),
})

View File

@ -292,7 +292,7 @@ const getCommunityStatistics = async () => {
}
const admin = () => {
window.location.assign(CONFIG.ADMIN_AUTH_URL.replace('{token}', store.state.token))
window.location.assign(CONFIG.ADMIN_AUTH_URL + store.state.token)
store.dispatch('logout') // logout without redirect
}

View File

@ -7,6 +7,8 @@ import Icons from 'unplugin-icons/vite'
import IconsResolve from 'unplugin-icons/resolver'
import EnvironmentPlugin from 'vite-plugin-environment'
import { createHtmlPlugin } from 'vite-plugin-html'
import schema from './src/config/schema'
import { validate, browserUrls } from 'gradido-config/build/src/index.js'
import { BootstrapVueNextResolver } from 'bootstrap-vue-next'
import dotenv from 'dotenv'
@ -16,100 +18,120 @@ dotenv.config() // load env vars from .env
const CONFIG = require('./src/config')
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: CONFIG.FRONTEND_MODULE_HOST, // '0.0.0.0',
port: CONFIG.FRONTEND_MODULE_PORT, // 3000,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
assets: path.join(__dirname, 'src/assets'),
'@vee-validate/i18n/dist/locale/en.json':
'/node_modules/@vee-validate/i18n/dist/locale/en.json',
'@vee-validate/i18n/dist/locale/de.json':
'/node_modules/@vee-validate/i18n/dist/locale/de.json',
'@vee-validate/i18n/dist/locale/es.json':
'/node_modules/@vee-validate/i18n/dist/locale/es.json',
'@vee-validate/i18n/dist/locale/fr.json':
'/node_modules/@vee-validate/i18n/dist/locale/fr.json',
'@vee-validate/i18n/dist/locale/nl.json':
'/node_modules/@vee-validate/i18n/dist/locale/nl.json',
'@vee-validate/i18n/dist/locale/tr.json':
'/node_modules/@vee-validate/i18n/dist/locale/tr.json',
export default defineConfig(({ command }) => {
if (command === 'serve') {
CONFIG.FRONTEND_HOSTING = 'nodejs'
} else {
CONFIG.FRONTEND_HOSTING = 'nginx'
}
// Check config
validate(schema, CONFIG)
// make sure that all urls used in browser have the same protocol to prevent mixed content errors
validate(browserUrls, [
CONFIG.ADMIN_AUTH_URL,
CONFIG.COMMUNITY_URL,
CONFIG.COMMUNITY_REGISTER_URL,
CONFIG.GRAPHQL_URI,
CONFIG.FRONTEND_MODULE_URL,
])
return {
server: {
host: CONFIG.FRONTEND_MODULE_HOST, // '0.0.0.0',
port: CONFIG.FRONTEND_MODULE_PORT, // 3000,
https: CONFIG.FRONTEND_MODULE_PROTOCOL === 'https',
fs: {
strict: true,
},
esbuild: {
minify: CONFIG.PRODUCTION === true,
},
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
plugins: [
vue(),
createHtmlPlugin({
minify: true,
inject: {
data: {
VITE_META_TITLE_DE: CONFIG.META_TITLE_DE,
VITE_META_TITLE_EN: CONFIG.META_TITLE_EN,
VITE_META_DESCRIPTION_DE: CONFIG.META_DESCRIPTION_DE,
VITE_META_DESCRIPTION_EN: CONFIG.META_DESCRIPTION_EN,
VITE_META_KEYWORDS_DE: CONFIG.META_KEYWORDS_DE,
VITE_META_KEYWORDS_EN: CONFIG.META_KEYWORDS_EN,
VITE_META_AUTHOR: CONFIG.META_AUTHOR,
VITE_META_URL: CONFIG.META_URL,
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
assets: path.join(__dirname, 'src/assets'),
'@vee-validate/i18n/dist/locale/en.json':
'/node_modules/@vee-validate/i18n/dist/locale/en.json',
'@vee-validate/i18n/dist/locale/de.json':
'/node_modules/@vee-validate/i18n/dist/locale/de.json',
'@vee-validate/i18n/dist/locale/es.json':
'/node_modules/@vee-validate/i18n/dist/locale/es.json',
'@vee-validate/i18n/dist/locale/fr.json':
'/node_modules/@vee-validate/i18n/dist/locale/fr.json',
'@vee-validate/i18n/dist/locale/nl.json':
'/node_modules/@vee-validate/i18n/dist/locale/nl.json',
'@vee-validate/i18n/dist/locale/tr.json':
'/node_modules/@vee-validate/i18n/dist/locale/tr.json',
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
plugins: [
vue(),
createHtmlPlugin({
minify: CONFIG.PRODUCTION === true,
inject: {
data: {
VITE_META_TITLE_DE: CONFIG.META_TITLE_DE,
VITE_META_TITLE_EN: CONFIG.META_TITLE_EN,
VITE_META_DESCRIPTION_DE: CONFIG.META_DESCRIPTION_DE,
VITE_META_DESCRIPTION_EN: CONFIG.META_DESCRIPTION_EN,
VITE_META_KEYWORDS_DE: CONFIG.META_KEYWORDS_DE,
VITE_META_KEYWORDS_EN: CONFIG.META_KEYWORDS_EN,
VITE_META_AUTHOR: CONFIG.META_AUTHOR,
VITE_META_URL: CONFIG.META_URL,
},
},
}),
Components({
resolvers: [BootstrapVueNextResolver(), IconsResolve()],
dts: true,
}),
Icons({
compiler: 'vue3',
autoInstall: true,
}),
EnvironmentPlugin({
GMS_ACTIVE: null,
HUMHUB_ACTIVE: null,
DEFAULT_PUBLISHER_ID: null,
PORT: null,
COMMUNITY_HOST: null,
URL_PROTOCOL: null,
COMMUNITY_URL: CONFIG.COMMUNITY_URL,
GRAPHQL_PATH: null,
GRAPHQL_URI: CONFIG.GRAPHQL_URI, // null,
ADMIN_AUTH_PATH: CONFIG.ADMIN_AUTH_PATH ?? null, // it is the only env without exported default
ADMIN_AUTH_URL: CONFIG.ADMIN_AUTH_URL, // null,
COMMUNITY_NAME: null,
COMMUNITY_REGISTER_PATH: null,
COMMUNITY_REGISTER_URL: null,
COMMUNITY_DESCRIPTION: null,
COMMUNITY_SUPPORT_MAIL: null,
META_URL: null,
META_TITLE_DE: null,
META_TITLE_EN: null,
META_DESCRIPTION_DE: null,
META_DESCRIPTION_EN: null,
META_KEYWORDS_DE: null,
META_KEYWORDS_EN: null,
META_AUTHOR: null,
}),
commonjs(),
],
css: {
extract: CONFIG.PRODUCTION === true,
preprocessorOptions: {
scss: {
additionalData: `@use "@/assets/scss/custom/gradido-custom/color" as *;`,
},
},
}),
Components({
resolvers: [BootstrapVueNextResolver(), IconsResolve()],
dts: true,
}),
Icons({
compiler: 'vue3',
autoInstall: true,
}),
EnvironmentPlugin({
BUILD_COMMIT: null,
GMS_ACTIVE: null,
HUMHUB_ACTIVE: null,
NODE_ENV: null,
DEFAULT_PUBLISHER_ID: null,
PORT: null,
COMMUNITY_HOST: null,
URL_PROTOCOL: null,
COMMUNITY_URL: null,
GRAPHQL_PATH: null,
GRAPHQL_URI: CONFIG.GRAPHQL_URI, // null,
ADMIN_AUTH_PATH: CONFIG.ADMIN_AUTH_PATH ?? null, // it is the only env without exported default
ADMIN_AUTH_URL: CONFIG.ADMIN_AUTH_URL, // null,
COMMUNITY_NAME: null,
COMMUNITY_REGISTER_PATH: null,
COMMUNITY_REGISTER_URL: null,
COMMUNITY_DESCRIPTION: null,
COMMUNITY_SUPPORT_MAIL: null,
META_URL: null,
META_TITLE_DE: null,
META_TITLE_EN: null,
META_DESCRIPTION_DE: null,
META_DESCRIPTION_EN: null,
META_KEYWORDS_DE: null,
META_KEYWORDS_EN: null,
META_AUTHOR: null,
CONFIG_VERSION: null,
}),
commonjs(),
],
css: {
extract: true,
preprocessorOptions: {
scss: {
additionalData: `@use "@/assets/scss/custom/gradido-custom/color" as *;`,
},
},
},
build: {
outDir: path.resolve(__dirname, './build'),
chunkSizeWarningLimit: 1600,
},
optimizeDeps: {
include: ['vue', 'vue-router', 'bootstrap'],
exclude: ['@popperjs/core'],
},
build: {
outDir: path.resolve(__dirname, './build'),
chunkSizeWarningLimit: 1600,
minify: 'esbuild',
sourcemap: false,
},
}
})

View File

@ -1073,6 +1073,18 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
version "9.3.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
"@hapi/topo@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@humanwhocodes/config-array@^0.11.14":
version "0.11.14"
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
@ -1522,6 +1534,23 @@
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==
dependencies:
"@hapi/hoek" "^9.0.0"
"@sideway/formula@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sindresorhus/merge-streams@^2.1.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958"
@ -4173,6 +4202,11 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
gradido-config@../config:
version "1.0.0"
dependencies:
joi "^17.13.3"
graphemer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
@ -4739,6 +4773,17 @@ jiti@^2.3.0, jiti@^2.4.0, jiti@^2.4.1:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560"
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
joi@^17.13.3:
version "17.13.3"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec"
integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==
dependencies:
"@hapi/hoek" "^9.3.0"
"@hapi/topo" "^5.1.0"
"@sideway/address" "^4.1.5"
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
js-beautify@^1.14.9:
version "1.15.1"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.15.1.tgz#4695afb508c324e1084ee0b952a102023fc65b64"