Merge branch 'master' into yarn_workspaces_turbo

This commit is contained in:
einhornimmond 2025-04-30 11:17:56 +02:00
commit 9efdf80498
429 changed files with 2231 additions and 7418 deletions

12
.vscode/settings.json vendored
View File

@ -1,5 +1,17 @@
{
"git.ignoreLimitWarning": true,
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit"
}
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit"
}
},
"sqltools.connections": [
{
"mysqlOptions": {

View File

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

View File

@ -1,213 +0,0 @@
// 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: ['FederationClient_*', '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/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',
},
},
],
}

View File

@ -1,14 +0,0 @@
module.exports = {
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
quoteProps: "as-needed",
jsxSingleQuote: true,
trailingComma: "all",
bracketSpacing: true,
bracketSameLine: false,
arrowParens: "always",
endOfLine: "auto",
};

View File

@ -57,6 +57,20 @@
"fileNameSep" : "_",
"numBackups" : 30
},
"gms":
{
"type": "dateFile",
"filename": "../logs/backend/gms.log",
"pattern": "yyyy-MM-dd",
"layout":
{
"type": "pattern", "pattern": "%d{ISO8601} %p %c [%X{user}] [%f : %l] - %m"
},
"compress": true,
"keepFileExt" : true,
"fileNameSep" : "_",
"numBackups" : 30
},
"errorFile":
{
"type": "dateFile",
@ -137,6 +151,16 @@
"level": "debug",
"enableCallStack": true
},
"gms":
{
"appenders":
[
"gms",
"errors"
],
"level": "debug",
"enableCallStack": true
},
"http":
{
"appenders":

View File

@ -12,7 +12,8 @@
"clean": "tsc --build --clean",
"start": "cross-env TZ=UTC TS_NODE_BASEURL=./build node -r tsconfig-paths/register build/src/index.js",
"dev": "cross-env TZ=UTC nodemon -w src --ext ts,pug,json,css --exec ts-node -r tsconfig-paths/register src/index.ts",
"lint": "eslint --max-warnings=0 .",
"lint": "biome check --error-on-warnings .",
"lint:fix": "biome check --error-on-warnings . --write",
"test": "cross-env TZ=UTC NODE_ENV=development DB_DATABASE=gradido_test_backend jest --runInBand --forceExit --detectOpenHandles",
"seed": "cross-env TZ=UTC NODE_ENV=development ts-node -r tsconfig-paths/register src/seeds/index.ts",
"klicktipp": "cross-env TZ=UTC NODE_ENV=development ts-node -r tsconfig-paths/register src/util/executeKlicktipp.ts",
@ -59,10 +60,9 @@
"xregexp": "^5.1.1"
},
"devDependencies": {
"@anatine/esbuild-decorators": "^0.2.19",
"@eslint-community/eslint-plugin-eslint-comments": "^3.2.1",
"@types/email-templates": "^10.0.4",
"@types/express": "^4.17.21",
"@biomejs/biome": "1.9.4",
"@types/faker": "^5.5.9",
"@types/i18n": "^0.13.4",
"@types/jest": "27.0.2",
@ -71,20 +71,7 @@
"@types/nodemailer": "^6.4.4",
"@types/sodium-native": "^2.3.5",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"apollo-server-testing": "^2.25.2",
"eslint": "^8.57.1",
"eslint-config-prettier": "^10.1.1",
"eslint-config-standard": "^17.0.0",
"eslint-import-resolver-typescript": "^4.2.2",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "27.2.1",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-security": "^1.7.1",
"eslint-plugin-type-graphql": "^1.0.0",
"faker": "^5.5.3",
"graphql-tag": "^2.12.6",
"jest": "27.2.4",

View File

@ -1,7 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import axios from 'axios'
import { LogError } from '@/server/LogError'

View File

@ -1,13 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { CONFIG } from '@/config'
import { backendLogger as logger } from '@/server/logger'
// eslint-disable-next-line import/no-relative-parent-imports
import KlicktippConnector from 'klicktipp-api'
const klicktippConnector = new KlicktippConnector()
@ -18,7 +11,9 @@ export const subscribe = async (
firstName?: string,
lastName?: string,
): Promise<boolean> => {
if (!CONFIG.KLICKTIPP) return true
if (!CONFIG.KLICKTIPP) {
return true
}
const fields = {
fieldFirstName: firstName,
fieldLastName: lastName,
@ -29,7 +24,9 @@ export const subscribe = async (
}
export const unsubscribe = async (email: string): Promise<boolean> => {
if (!CONFIG.KLICKTIPP) return true
if (!CONFIG.KLICKTIPP) {
return true
}
const isLogin = await loginKlicktippUser()
if (isLogin) {
return await klicktippConnector.unsubscribe(email)
@ -38,12 +35,14 @@ export const unsubscribe = async (email: string): Promise<boolean> => {
}
export const getKlickTippUser = async (email: string): Promise<any> => {
if (!CONFIG.KLICKTIPP) return true
if (!CONFIG.KLICKTIPP) {
return true
}
const isLogin = await loginKlicktippUser()
if (isLogin) {
try {
return klicktippConnector.subscriberGet(await klicktippConnector.subscriberSearch(email))
} catch (e) {
} catch (_e) {
logger.error('Could not find subscriber', email)
return false
}
@ -52,7 +51,9 @@ export const getKlickTippUser = async (email: string): Promise<any> => {
}
export const loginKlicktippUser = async (): Promise<boolean> => {
if (!CONFIG.KLICKTIPP) return true
if (!CONFIG.KLICKTIPP) {
return true
}
return await klicktippConnector.login(CONFIG.KLICKTIPP_USER, CONFIG.KLICKTIPP_PASSWORD)
}
@ -62,7 +63,9 @@ export const addFieldsToSubscriber = async (
newemail = '',
newsmsnumber = '',
) => {
if (!CONFIG.KLICKTIPP) return true
if (!CONFIG.KLICKTIPP) {
return true
}
const isLogin = await loginKlicktippUser()
if (isLogin) {
try {

View File

@ -1,8 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable security/detect-object-injection */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { Transaction as DbTransaction } from 'database'
import { Decimal } from 'decimal.js-light'
import { Connection } from 'typeorm'
@ -116,7 +111,7 @@ describe('transmitTransaction', () => {
await DltConnectorClient.getInstance()?.transmitTransaction(localTransaction)
} catch (e) {
expect(e).toMatchObject(
new LogError('invalid transaction type id: ' + localTransaction.typeId.toString()),
new LogError(`invalid transaction type id: ${localTransaction.typeId.toString()}`),
)
}
})

View File

@ -1,5 +1,5 @@
import { Transaction as DbTransaction } from 'database'
import { gql, GraphQLClient } from 'graphql-request'
import { GraphQLClient, gql } from 'graphql-request'
import { CONFIG } from '@/config'
import { TransactionTypeId } from '@/graphql/enum/TransactionTypeId'
@ -34,16 +34,15 @@ function getTransactionTypeString(id: TransactionTypeId): string {
* A Singleton class defines the `getInstance` method that lets clients access
* the unique singleton instance.
*/
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class DltConnectorClient {
// eslint-disable-next-line no-use-before-define
private static instance: DltConnectorClient
client: GraphQLClient
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
/**

View File

@ -1,9 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import { User as DbUser } from 'database'
// import { createTestClient } from 'apollo-server-testing'
@ -12,30 +6,29 @@ import { User as DbUser } from 'database'
import { CONFIG } from '@/config'
import { getHomeCommunity } from '@/graphql/resolver/util/communities'
import { sendUserToGms } from '@/graphql/resolver/util/sendUserToGms'
import { createServer } from '@/server/createServer'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { checkDBVersion } from '@/typeorm/DBVersion'
import { Connection } from '@/typeorm/connection'
CONFIG.EMAIL = false
// use force to copy over all user even if gmsRegistered is set to true
const forceMode = process.argv.includes('--force')
const context = {
token: '',
setHeaders: {
push: (value: { key: string; value: string }): void => {
context.token = value.value
},
// eslint-disable-next-line @typescript-eslint/no-empty-function
forEach: (): void => {},
},
clientTimezoneOffset: 0,
}
async function main() {
// open mysql connection
const con = await Connection.getInstance()
if (!con?.isConnected) {
logger.fatal(`Couldn't open connection to database!`)
throw new Error(`Fatal: Couldn't open connection to database`)
}
const run = async () => {
const server = await createServer(context)
// const seedClient = createTestClient(server.apollo)
const { con } = server
// check for correct database version
const dbVersion = await checkDBVersion(CONFIG.DB_VERSION)
if (!dbVersion) {
logger.fatal('Fatal: Database Version incorrect')
throw new Error('Fatal: Database Version incorrect')
}
const homeCom = await getHomeCommunity()
if (homeCom.gmsApiKey === null) {
@ -63,7 +56,7 @@ const run = async () => {
/*
const gmsUser = new GmsUser(user)
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
if (await createGmsUser(homeCom.gmsApiKey, gmsUser)) {
logger.debug('GMS user published successfully:', gmsUser)
user.gmsRegistered = true
@ -84,7 +77,11 @@ const run = async () => {
}
logger.info('##gms## publishing all local users successful...')
await con.close()
await con.destroy()
}
void run()
main().catch((e) => {
// biome-ignore lint/suspicious/noConsole: logger isn't used here
console.error(e)
process.exit(1)
})

View File

@ -1,7 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import axios from 'axios'
import { httpAgent, httpsAgent } from '@/apis/ConnectionAgents'
@ -33,10 +29,10 @@ export async function communityList(): Promise<GmsCommunity[] | string | undefin
throw new LogError('HTTP Status Error in community/list:', result.status, result.statusText)
}
logger.debug('responseData:', result.data.responseData.data)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// const gmsCom = JSON.parse(result.data.responseData.data)
// logger.debug('gmsCom:', gmsCom)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return result.data.responseData.data
} catch (error: any) {
logger.error('Error in Get community/list:', error)
@ -69,10 +65,10 @@ export async function userList(): Promise<GmsUser[] | string | undefined> {
)
}
logger.debug('responseData:', result.data.responseData.data)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// const gmsUser = JSON.parse(result.data.responseData.data)
// logger.debug('gmsUser:', gmsUser)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return result.data.responseData.data
} catch (error: any) {
logger.error('Error in Get community-user/list:', error)
@ -105,10 +101,10 @@ export async function userByUuid(uuid: string): Promise<GmsUser[] | string | und
)
}
logger.debug('responseData:', result.data.responseData.data)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// const gmsUser = JSON.parse(result.data.responseData.data)
// logger.debug('gmsUser:', gmsUser)
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return result.data.responseData.data
} catch (error: any) {
logger.error('Error in Get community-user/list:', error)
@ -139,13 +135,16 @@ export async function createGmsUser(apiKey: string, user: GmsUser): Promise<bool
throw new LogError('HTTP Status Error in community-user:', result.status, result.statusText)
}
logger.debug('responseData:', result.data.responseData)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// const gmsUser = JSON.parse(result.data.responseData)
// logger.debug('gmsUser:', gmsUser)
return true
} catch (error: any) {
} catch (error: unknown) {
logger.error('Error in post community-user:', error)
throw new LogError(error.message)
if (error instanceof Error) {
throw new LogError(error.message)
}
throw new LogError('Unknown error in post community-user')
}
} else {
logger.info('GMS-Communication disabled per ConfigKey GMS_ACTIVE=false!')
@ -174,13 +173,16 @@ export async function updateGmsUser(apiKey: string, user: GmsUser): Promise<bool
throw new LogError('HTTP Status Error in community-user:', result.status, result.statusText)
}
logger.debug('responseData:', result.data.responseData)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
// const gmsUser = JSON.parse(result.data.responseData)
// logger.debug('gmsUser:', gmsUser)
return true
} catch (error: any) {
} catch (error: unknown) {
logger.error('Error in patch community-user:', error)
throw new LogError(error.message)
if (error instanceof Error) {
throw new LogError(error.message)
}
throw new LogError('Unknown error in patch community-user')
}
} else {
logger.info('GMS-Communication disabled per ConfigKey GMS_ACTIVE=false!')
@ -194,6 +196,7 @@ export async function verifyAuthToken(
token: string,
): Promise<string> {
const baseUrl = ensureUrlEndsWithSlash(CONFIG.GMS_API_URL)
// TODO: NEVER pass user JWT token to another server - serious security risk! 😱⚠️
const service = 'verify-auth-token?token='.concat(token).concat('&uuid=').concat(communityUuid)
const config = {
headers: {
@ -216,12 +219,15 @@ export async function verifyAuthToken(
)
}
logger.debug('responseData:', result.data.responseData)
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const token: string = result.data.responseData.token
logger.debug('verifyAuthToken=', token)
return token
} catch (error: any) {
} catch (error: unknown) {
logger.error('Error in verifyAuthToken:', error)
throw new LogError(error.message)
if (error instanceof Error) {
throw new LogError(error.message)
}
throw new LogError('Unknown error in verifyAuthToken')
}
}

View File

@ -10,7 +10,7 @@ export class GmsCommunityProfile {
communityId: number
radius: number
description: string
// eslint-disable-next-line camelcase
api_key: string
communityAuthUrl: unknown
profileImage: unknown

View File

@ -11,7 +11,7 @@ export class GmsUserAccount {
address: string
radius: number
description: string
// eslint-disable-next-line camelcase
api_key: string
profileImage: unknown
}

View File

@ -4,8 +4,8 @@ import { IsNull, Not } from 'typeorm'
import { CONFIG } from '@/config'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { Connection } from '@/typeorm/connection'
import { checkDBVersion } from '@/typeorm/DBVersion'
import { Connection } from '@/typeorm/connection'
import { HumHubClient } from './HumHubClient'
import { GetUser } from './model/GetUser'
@ -39,14 +39,14 @@ async function loadUsersFromHumHub(client: HumHubClient): Promise<Map<string, Ge
if (!usersPage) {
throw new LogError('error requesting next users page from humhub')
}
usersPage.results.forEach((user) => {
for (const user of usersPage.results) {
// deleted users have empty emails
if (user.account.email) {
humhubUsers.set(user.account.username, user)
} else {
skippedUsersCount++
}
})
}
page++
process.stdout.write(
`load users from humhub: ${humhubUsers.size}/${usersPage.total}, skipped: ${skippedUsersCount}\r`,
@ -97,11 +97,13 @@ async function main() {
userCount = users.length
page++
const promises: Promise<ExecutedHumhubAction>[] = []
users.forEach((user: User) => promises.push(syncUser(user, humhubUsers)))
for (const user of users) {
promises.push(syncUser(user, humhubUsers))
}
const executedActions = await Promise.all(promises)
executedActions.forEach((executedAction: ExecutedHumhubAction) => {
for (const executedAction of executedActions) {
executedHumhubActionsCount[executedAction as number]++
})
}
// using process.stdout.write here so that carriage-return is working analog to c
// printf("\rchecked user: %d/%d", dbUserCount, totalUsers);
process.stdout.write(`checked user: ${dbUserCount}/${totalUsers}\r`)
@ -126,8 +128,7 @@ async function main() {
}
main().catch((e) => {
// eslint-disable-next-line no-console
console.error(JSON.stringify(e, null, 2))
// eslint-disable-next-line n/no-process-exit
// biome-ignore lint/suspicious/noConsole: logger isn't used here
console.error(e)
process.exit(1)
})

View File

@ -17,11 +17,9 @@ import { UsersResponse } from './model/UsersResponse'
* HumHubClient as singleton class
*/
export class HumHubClient {
// eslint-disable-next-line no-use-before-define
private static instance: HumHubClient
private restClient: RestClient
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {
this.restClient = new RestClient('gradido-backend', CONFIG.HUMHUB_API_URL, undefined, {
keepAlive: true,

View File

@ -9,10 +9,8 @@ import { UsersResponse } from '@/apis/humhub/model/UsersResponse'
* HumHubClient as singleton class
*/
export class HumHubClient {
// eslint-disable-next-line no-use-before-define
private static instance: HumHubClient
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
public static getInstance(): HumHubClient {

View File

@ -1,5 +1,3 @@
/* eslint-disable prettier/prettier */
// eslint-disable-next-line import/no-unassigned-import
import 'reflect-metadata'
import { PublishNameType } from '@/graphql/enum/PublishNameType'
import { communityDbUser } from '@/util/communityUser'
@ -10,73 +8,73 @@ import { GetUser } from './model/GetUser'
const defaultUser = communityDbUser
describe('isHumhubUserIdenticalToDbUser', () => {
beforeEach(() => {
defaultUser.firstName = 'first name'
defaultUser.lastName = 'last name'
defaultUser.alias = 'alias'
defaultUser.emailContact.email = 'email@gmail.com'
defaultUser.language = 'en'
defaultUser.gradidoID = 'gradidoID'
})
beforeEach(() => {
defaultUser.firstName = 'first name'
defaultUser.lastName = 'last name'
defaultUser.alias = 'alias'
defaultUser.emailContact.email = 'email@gmail.com'
defaultUser.language = 'en'
defaultUser.gradidoID = 'gradidoID'
})
it('Should return true because humhubUser was created from entity user', () => {
const humhubUser = new GetUser(defaultUser, 1)
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(true)
})
it('Should return true because humhubUser was created from entity user', () => {
const humhubUser = new GetUser(defaultUser, 1)
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(true)
})
it('Should return false, because last name differ because of publish name type', () => {
const humhubUser = new GetUser(defaultUser, 1)
defaultUser.humhubPublishName = PublishNameType.PUBLISH_NAME_FIRST
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false, because last name differ because of publish name type', () => {
const humhubUser = new GetUser(defaultUser, 1)
defaultUser.humhubPublishName = PublishNameType.PUBLISH_NAME_FIRST
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return true, even if alias is empty', () => {
defaultUser.alias = ''
const humhubUser = new GetUser(defaultUser, 1)
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(true)
})
it('Should return true, even if alias is empty', () => {
defaultUser.alias = ''
const humhubUser = new GetUser(defaultUser, 1)
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(true)
})
it('Should return false because first name differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.profile.firstname = 'changed first name'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because last name differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.profile.lastname = 'changed last name'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because username differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.account.username = 'changed username'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because first name differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.profile.firstname = 'changed first name'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because last name differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.profile.lastname = 'changed last name'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because username differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.account.username = 'changed username'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because email differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.account.email = 'new@gmail.com'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because email differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.account.email = 'new@gmail.com'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because language differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.account.language = 'de'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because language differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.account.language = 'de'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because gradido_address differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
// eslint-disable-next-line camelcase
humhubUser.profile.gradido_address = 'changed gradido address'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
it('Should return false because gradido_address differ', () => {
const humhubUser = new GetUser(defaultUser, 1)
humhubUser.profile.gradido_address = 'changed gradido address'
const result = isHumhubUserIdenticalToDbUser(humhubUser, defaultUser)
expect(result).toBe(false)
})
})

View File

@ -6,18 +6,32 @@ import { Profile } from './model/Profile'
function profileIsTheSame(profile: Profile, user: User): boolean {
const gradidoUserProfile = new Profile(user)
if (profile.firstname !== gradidoUserProfile.firstname) return false
if (profile.lastname !== gradidoUserProfile.lastname) return false
if (profile.gradido_address !== gradidoUserProfile.gradido_address) return false
if (profile.firstname !== gradidoUserProfile.firstname) {
return false
}
if (profile.lastname !== gradidoUserProfile.lastname) {
return false
}
if (profile.gradido_address !== gradidoUserProfile.gradido_address) {
return false
}
return true
}
function accountIsTheSame(account: Account, user: User): boolean {
const gradidoUserAccount = new Account(user)
if (account.username !== gradidoUserAccount.username) return false
if (account.email !== gradidoUserAccount.email) return false
if (account.language !== gradidoUserAccount.language) return false
if (account.status !== gradidoUserAccount.status) return false
if (account.username !== gradidoUserAccount.username) {
return false
}
if (account.email !== gradidoUserAccount.email) {
return false
}
if (account.language !== gradidoUserAccount.language) {
return false
}
if (account.status !== gradidoUserAccount.status) {
return false
}
return true
}

View File

@ -12,7 +12,7 @@ export class ProfileLoggingView extends AbstractLoggingView {
return {
firstname: this.self.firstname.substring(0, 3) + '...',
lastname: this.self.lastname.substring(0, 3) + '...',
// eslint-disable-next-line camelcase
gradido_address:
gradidoAddressParts[0] + '/' + gradidoAddressParts[1].substring(0, 3) + '...',
}

View File

@ -10,6 +10,6 @@ export class GetUser extends AbstractUser {
id: number
guid: string
// eslint-disable-next-line camelcase
display_name: string
}

View File

@ -1,4 +1,3 @@
/* eslint-disable camelcase */
import { User } from 'database'
import { CONFIG } from '@/config'

View File

@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { User, UserContact } from 'database'
import { GetUser } from './model/GetUser'
import { syncUser, ExecutedHumhubAction } from './syncUser'
import { ExecutedHumhubAction, syncUser } from './syncUser'
jest.mock('@/apis/humhub/HumHubClient')

View File

@ -3,8 +3,8 @@ import { User } from 'database'
import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger'
import { isHumhubUserIdenticalToDbUser } from './compareHumhubUserDbUser'
import { HumHubClient } from './HumHubClient'
import { isHumhubUserIdenticalToDbUser } from './compareHumhubUserDbUser'
import { GetUser } from './model/GetUser'
import { PostUser } from './model/PostUser'

View File

@ -1,4 +1,3 @@
/* eslint-disable camelcase */
import { OpenaiThreads, User } from 'database'
import { OpenAI } from 'openai'
import { Message } from 'openai/resources/beta/threads/messages'
@ -17,7 +16,7 @@ export class OpenaiClient {
/**
* The singleton instance of the `OpenaiClient`.
*/
// eslint-disable-next-line no-use-before-define
private static instance: OpenaiClient
/**

View File

@ -6,7 +6,9 @@ import { LogError } from '@/server/LogError'
import { CustomJwtPayload } from './CustomJwtPayload'
export const decode = async (token: string): Promise<CustomJwtPayload | null> => {
if (!token) throw new LogError('401 Unauthorized')
if (!token) {
throw new LogError('401 Unauthorized')
}
try {
const secret = new TextEncoder().encode(CONFIG.JWT_SECRET)
@ -15,7 +17,7 @@ export const decode = async (token: string): Promise<CustomJwtPayload | null> =>
audience: 'urn:gradido:audience',
})
return payload as CustomJwtPayload
} catch (err) {
} catch (_err) {
return null
}
}

View File

@ -1,5 +1,4 @@
// 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-schema'
@ -89,8 +88,8 @@ const email = {
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD ?? '',
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_TLS: process.env.EMAIL_TLS !== 'false',
EMAIL_LINK_VERIFICATION:
COMMUNITY_URL + (process.env.EMAIL_LINK_VERIFICATION_PATH ?? '/checkEmail/'),
EMAIL_LINK_SETPASSWORD:

View File

@ -1,19 +1,17 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
// eslint-disable-next-line import/no-unresolved
import {
COMMUNITY_NAME,
COMMUNITY_URL,
COMMUNITY_DESCRIPTION,
COMMUNITY_NAME,
COMMUNITY_SUPPORT_MAIL,
COMMUNITY_URL,
DB_DATABASE,
DB_HOST,
DB_PASSWORD,
DB_PORT,
DB_USER,
DB_VERSION,
DB_DATABASE,
DECAY_START_TIME,
GDT_API_URL,
GDT_ACTIVE,
GDT_API_URL,
GMS_ACTIVE,
GRAPHIQL,
HUMHUB_ACTIVE,
@ -61,7 +59,6 @@ export const schema = Joi.object({
.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 })
}
@ -72,7 +69,6 @@ export const schema = Joi.object({
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 })
}
@ -168,7 +164,6 @@ export const schema = Joi.object({
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 })
}
@ -180,7 +175,6 @@ export const schema = Joi.object({
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 })
}
@ -192,7 +186,6 @@ export const schema = Joi.object({
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 })
}
@ -204,7 +197,6 @@ export const schema = Joi.object({
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 })
}

View File

@ -2,7 +2,6 @@ import { Contribution, ContributionMessage, User } from 'database'
import { ContributionMessageType } from '@/graphql/enum/ContributionMessageType'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class ContributionMessageBuilder {
private contributionMessage: ContributionMessage

View File

@ -18,7 +18,6 @@ export class PublishNameLogic {
// remove character which are invalid for humhub username
private filterOutInvalidChar(name: string) {
// eslint-disable-next-line import/no-named-as-default-member
return XRegExp.match(name, this.usernameRegex, 'all').join('')
}

View File

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTransport } from 'nodemailer'
import { logger, i18n } from '@test/testSetup'
import { i18n, logger } from '@test/testSetup'
import { CONFIG } from '@/config'
@ -103,12 +102,10 @@ describe('sendEmailTranslated', () => {
})
})
// eslint-disable-next-line jest/no-disabled-tests
it.skip('calls "i18n.setLocale" with "en"', () => {
expect(i18n.setLocale).toBeCalledWith('en')
})
// eslint-disable-next-line jest/no-disabled-tests
it.skip('calls "i18n.__" for translation', () => {
expect(i18n.__).toBeCalled()
})

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import path from 'path'
import Email from 'email-templates'

View File

@ -1,29 +1,24 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { ApolloServerTestClient } from 'apollo-server-testing'
import { Decimal } from 'decimal.js-light'
import { Connection } from 'typeorm'
import { testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
import { i18n as localization, logger } from '@test/testSetup'
import { CONFIG } from '@/config'
// eslint-disable-next-line import/no-namespace
import * as sendEmailTranslatedApi from './sendEmailTranslated'
import {
sendAddedContributionMessageEmail,
sendAccountActivationEmail,
sendAccountMultiRegistrationEmail,
sendAddedContributionMessageEmail,
sendContributionChangedByModeratorEmail,
sendContributionConfirmedEmail,
sendContributionDeniedEmail,
sendContributionDeletedEmail,
sendContributionDeniedEmail,
sendResetPasswordEmail,
sendTransactionLinkRedeemedEmail,
sendTransactionReceivedEmail,
sendContributionChangedByModeratorEmail,
} from './sendEmailVariants'
const testMailServerHost = 'localhost'
@ -69,7 +64,6 @@ afterAll(async () => {
const sendEmailTranslatedSpy = jest.spyOn(sendEmailTranslatedApi, 'sendEmailTranslated')
describe('sendEmailVariants', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let result: any
describe('sendAddedContributionMessageEmail', () => {

View File

@ -2,7 +2,7 @@ import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity }
import { validate as validateUUID, version as versionUUID } from 'uuid'
import { CONFIG } from '@/config'
// eslint-disable-next-line camelcase
import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient'
import { backendLogger as logger } from '@/server/logger'
import { ensureUrlEndsWithSlash } from '@/util/utilities'
@ -34,7 +34,7 @@ export async function startCommunityAuthentication(
) {
try {
const client = AuthenticationClientFactory.getInstance(foreignFedCom)
// eslint-disable-next-line camelcase
if (client instanceof V1_0_AuthenticationClient) {
const args = new OpenConnectionArgs()
args.publicKey = homeCom.publicKey.toString('hex')

View File

@ -132,7 +132,7 @@ export class SendCoinsClient {
{ args },
)
logger.debug(`X-Com: SendCoinsClient: after revertSettledSendCoins: data=`, data)
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (!data?.revertSettledSendCoins) {
logger.warn(
'X-Com: SendCoinsClient: revertSettledSendCoins without response data from endpoint',

View File

@ -7,7 +7,6 @@ export class PublicCommunityInfoLoggingView extends AbstractLoggingView {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
name: this.self.name,

View File

@ -7,7 +7,6 @@ export class SendCoinsArgsLoggingView extends AbstractLoggingView {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
recipientCommunityUuid: this.self.recipientCommunityUuid,

View File

@ -7,7 +7,6 @@ export class SendCoinsResultLoggingView extends AbstractLoggingView {
super()
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public toJSON(): any {
return {
vote: this.self.vote,

View File

@ -1,8 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Field, ObjectType } from 'type-graphql'
@ObjectType()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export class GetPublicKeyResult {
constructor(pubKey: string) {
this.publicKey = pubKey

View File

@ -1,5 +1,3 @@
// eslint-disable-next-line camelcase
import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient'
// eslint-disable-next-line camelcase
export class AuthenticationClient extends V1_0_AuthenticationClient {}

View File

@ -1,5 +1,3 @@
// eslint-disable-next-line camelcase
import { FederationClient as V1_0_FederationClient } from '@/federation/client/1_0/FederationClient'
// eslint-disable-next-line camelcase
export class FederationClient extends V1_0_FederationClient {}

View File

@ -1,5 +1,3 @@
// eslint-disable-next-line camelcase
import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient'
// eslint-disable-next-line camelcase
export class SendCoinsClient extends V1_0_SendCoinsClient {}

View File

@ -1,21 +1,18 @@
import { FederatedCommunity as DbFederatedCommunity } from 'database'
// eslint-disable-next-line camelcase
import { AuthenticationClient as V1_0_AuthenticationClient } from '@/federation/client/1_0/AuthenticationClient'
// eslint-disable-next-line camelcase
import { AuthenticationClient as V1_1_AuthenticationClient } from '@/federation/client/1_1/AuthenticationClient'
import { ApiVersionType } from '@/federation/enum/apiVersionType'
// eslint-disable-next-line camelcase
type AuthenticationClient = V1_0_AuthenticationClient | V1_1_AuthenticationClient
interface AuthenticationClientInstance {
id: number
// eslint-disable-next-line no-use-before-define
client: AuthenticationClient
}
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class AuthenticationClientFactory {
private static instanceArray: AuthenticationClientInstance[] = []
@ -23,7 +20,7 @@ export class AuthenticationClientFactory {
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
private static createAuthenticationClient = (dbCom: DbFederatedCommunity) => {

View File

@ -1,22 +1,19 @@
import { FederatedCommunity as DbFederatedCommunity } from 'database'
// eslint-disable-next-line camelcase
import { FederationClient as V1_0_FederationClient } from '@/federation/client/1_0/FederationClient'
// eslint-disable-next-line camelcase
import { FederationClient as V1_1_FederationClient } from '@/federation/client/1_1/FederationClient'
import { ApiVersionType } from '@/federation/enum/apiVersionType'
import { ensureUrlEndsWithSlash } from '@/util/utilities'
// eslint-disable-next-line camelcase
type FederationClient = V1_0_FederationClient | V1_1_FederationClient
interface FederationClientInstance {
id: number
// eslint-disable-next-line no-use-before-define
client: FederationClient
}
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class FederationClientFactory {
private static instanceArray: FederationClientInstance[] = []
@ -24,7 +21,7 @@ export class FederationClientFactory {
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
private static createFederationClient = (dbCom: DbFederatedCommunity) => {

View File

@ -1,21 +1,18 @@
import { FederatedCommunity as DbFederatedCommunity } from 'database'
// eslint-disable-next-line camelcase
import { SendCoinsClient as V1_0_SendCoinsClient } from '@/federation/client/1_0/SendCoinsClient'
// eslint-disable-next-line camelcase
import { SendCoinsClient as V1_1_SendCoinsClient } from '@/federation/client/1_1/SendCoinsClient'
import { ApiVersionType } from '@/federation/enum/apiVersionType'
// eslint-disable-next-line camelcase
type SendCoinsClient = V1_0_SendCoinsClient | V1_1_SendCoinsClient
interface SendCoinsClientInstance {
id: number
// eslint-disable-next-line no-use-before-define
client: SendCoinsClient
}
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class SendCoinsClientFactory {
private static instanceArray: SendCoinsClientInstance[] = []
@ -23,7 +20,7 @@ export class SendCoinsClientFactory {
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
private static createSendCoinsClient = (dbCom: DbFederatedCommunity) => {

View File

@ -1,17 +1,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { ApolloServerTestClient } from 'apollo-server-testing'
import { FederatedCommunity as DbFederatedCommunity } from 'database'
import { GraphQLClient } from 'graphql-request'
import { Response } from 'graphql-request/dist/types'
import { Connection } from 'typeorm'
import { testEnvironment, cleanDB } from '@test/helpers'
import { cleanDB, testEnvironment } from '@test/helpers'
import { logger } from '@test/testSetup'
import { validateCommunities } from './validateCommunities'
@ -62,9 +55,8 @@ describe('validate Communities', () => {
describe('with one Community of api 1_0 but missing pubKey response', () => {
beforeEach(async () => {
jest.clearAllMocks()
// eslint-disable-next-line @typescript-eslint/require-await
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return { data: {} } as Response<unknown>
})
const variables1 = {
@ -78,7 +70,6 @@ describe('validate Communities', () => {
.into(DbFederatedCommunity)
.values(variables1)
.orUpdate({
// eslint-disable-next-line camelcase
conflict_target: ['id', 'publicKey', 'apiVersion'],
overwrite: ['end_point', 'last_announced_at'],
})
@ -101,9 +92,8 @@ describe('validate Communities', () => {
describe('with one Community of api 1_0 and not matching pubKey', () => {
beforeEach(async () => {
jest.clearAllMocks()
// eslint-disable-next-line @typescript-eslint/require-await
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
data: {
getPublicKey: {
@ -123,15 +113,14 @@ describe('validate Communities', () => {
.into(DbFederatedCommunity)
.values(variables1)
.orUpdate({
// eslint-disable-next-line camelcase
conflict_target: ['id', 'publicKey', 'apiVersion'],
overwrite: ['end_point', 'last_announced_at'],
})
.execute()
/*
// eslint-disable-next-line @typescript-eslint/require-await
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
data: {
getPublicCommunityInfo: {
@ -183,9 +172,8 @@ describe('validate Communities', () => {
describe('with one Community of api 1_0 and matching pubKey', () => {
beforeEach(async () => {
jest.clearAllMocks()
// eslint-disable-next-line @typescript-eslint/require-await
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
data: {
getPublicKey: {
@ -205,7 +193,6 @@ describe('validate Communities', () => {
.into(DbFederatedCommunity)
.values(variables1)
.orUpdate({
// eslint-disable-next-line camelcase
conflict_target: ['id', 'publicKey', 'apiVersion'],
overwrite: ['end_point', 'last_announced_at'],
})
@ -251,9 +238,8 @@ describe('validate Communities', () => {
describe('with two Communities of api 1_0 and 1_1', () => {
beforeEach(async () => {
jest.clearAllMocks()
// eslint-disable-next-line @typescript-eslint/require-await
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
data: {
getPublicKey: {
@ -273,7 +259,6 @@ describe('validate Communities', () => {
.into(DbFederatedCommunity)
.values(variables2)
.orUpdate({
// eslint-disable-next-line camelcase
conflict_target: ['id', 'publicKey', 'apiVersion'],
overwrite: ['end_point', 'last_announced_at'],
})
@ -303,9 +288,8 @@ describe('validate Communities', () => {
let dbCom: DbFederatedCommunity
beforeEach(async () => {
jest.clearAllMocks()
// eslint-disable-next-line @typescript-eslint/require-await
jest.spyOn(GraphQLClient.prototype, 'rawRequest').mockImplementation(async () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return {
data: {
getPublicKey: {
@ -325,7 +309,6 @@ describe('validate Communities', () => {
.into(DbFederatedCommunity)
.values(variables3)
.orUpdate({
// eslint-disable-next-line camelcase
conflict_target: ['id', 'publicKey', 'apiVersion'],
overwrite: ['end_point', 'last_announced_at'],
})

View File

@ -1,5 +1,3 @@
/** eslint-disable @typescript-eslint/no-unsafe-assignment */
/** eslint-disable @typescript-eslint/no-unsafe-call */
import {
Community as DbCommunity,
FederatedCommunity as DbFederatedCommunity,
@ -29,8 +27,8 @@ export async function startValidateCommunities(timerInterval: number): Promise<v
// TODO: replace the timer-loop by an event-based communication to verify announced foreign communities
// better to use setTimeout twice than setInterval once -> see https://javascript.info/settimeout-setinterval
setTimeout(function run() {
void validateCommunities()
setTimeout(async function run() {
await validateCommunities()
setTimeout(run, timerInterval)
}, timerInterval)
}
@ -57,7 +55,7 @@ export async function validateCommunities(): Promise<void> {
}
try {
const client = FederationClientFactory.getInstance(dbCom)
// eslint-disable-next-line camelcase
if (client instanceof V1_0_FederationClient) {
const pubKey = await client.getPublicKey()
if (pubKey && pubKey === dbCom.publicKey.toString('hex')) {

View File

@ -3,10 +3,10 @@ import { Decimal } from 'decimal.js-light'
import { ArgsType, Field, Int } from 'type-graphql'
import {
CONTRIBUTIONLINK_NAME_MAX_CHARS,
CONTRIBUTIONLINK_NAME_MIN_CHARS,
MEMO_MAX_CHARS,
MEMO_MIN_CHARS,
CONTRIBUTIONLINK_NAME_MIN_CHARS,
CONTRIBUTIONLINK_NAME_MAX_CHARS,
} from '@/graphql/resolver/const/const'
import { isValidDateString } from '@/graphql/validator/DateString'
import { IsPositiveDecimal } from '@/graphql/validator/Decimal'

View File

@ -1,5 +1,5 @@
import { IsInt, IsString, IsEnum } from 'class-validator'
import { ArgsType, Field, Int, InputType } from 'type-graphql'
import { IsEnum, IsInt, IsString } from 'class-validator'
import { ArgsType, Field, InputType, Int } from 'type-graphql'
import { ContributionMessageType } from '@enum/ContributionMessageType'

View File

@ -1,6 +1,5 @@
/* eslint-disable type-graphql/invalid-nullable-input-type */
import { IsPositive, IsEnum } from 'class-validator'
import { ArgsType, Field, Int, InputType } from 'type-graphql'
import { IsEnum, IsPositive } from 'class-validator'
import { ArgsType, Field, InputType, Int } from 'type-graphql'
import { Order } from '@enum/Order'

View File

@ -1,5 +1,5 @@
import { IsBoolean, IsPositive, IsString } from 'class-validator'
import { Field, ArgsType, Int, InputType } from 'type-graphql'
import { ArgsType, Field, InputType, Int } from 'type-graphql'
import { ContributionStatus } from '@enum/ContributionStatus'

View File

@ -1,5 +1,5 @@
import { IsPositive, IsEnum } from 'class-validator'
import { ArgsType, Field, Int, InputType } from 'type-graphql'
import { IsEnum, IsPositive } from 'class-validator'
import { ArgsType, Field, InputType, Int } from 'type-graphql'
import { RoleNames } from '@enum/RoleNames'

View File

@ -1,4 +1,3 @@
/* eslint-disable type-graphql/invalid-nullable-input-type */
import { IsBoolean } from 'class-validator'
import { Field, InputType } from 'type-graphql'

View File

@ -1,4 +1,4 @@
import { MaxLength, MinLength, IsString } from 'class-validator'
import { IsString, MaxLength, MinLength } from 'class-validator'
import { Decimal } from 'decimal.js-light'
import { ArgsType, Field } from 'type-graphql'

View File

@ -7,22 +7,25 @@ import { INALIENABLE_RIGHTS } from '@/auth/INALIENABLE_RIGHTS'
import { decode, encode } from '@/auth/JWT'
import { RIGHTS } from '@/auth/RIGHTS'
import {
ROLE_UNAUTHORIZED,
ROLE_USER,
ROLE_ADMIN,
ROLE_DLT_CONNECTOR,
ROLE_MODERATOR,
ROLE_MODERATOR_AI,
ROLE_DLT_CONNECTOR,
ROLE_UNAUTHORIZED,
ROLE_USER,
} from '@/auth/ROLES'
import { Context } from '@/server/context'
import { LogError } from '@/server/LogError'
import { Context } from '@/server/context'
export const isAuthorized: AuthChecker<Context> = async ({ context }, rights) => {
context.role = ROLE_UNAUTHORIZED // unauthorized user
// is rights an inalienable right?
if ((rights as RIGHTS[]).reduce((acc, right) => acc && INALIENABLE_RIGHTS.includes(right), true))
if (
(rights as RIGHTS[]).reduce((acc, right) => acc && INALIENABLE_RIGHTS.includes(right), true)
) {
return true
}
// Do we have a token?
if (!context.token) {

View File

@ -1,5 +1,5 @@
import { IsString, IsOptional, MaxLength, IsNumber, IsBoolean, IsUrl } from 'class-validator'
import { InputType, Field, Int } from 'type-graphql'
import { IsBoolean, IsNumber, IsOptional, IsString, IsUrl, MaxLength } from 'class-validator'
import { Field, InputType, Int } from 'type-graphql'
@InputType()
export class ProjectBrandingInput {

View File

@ -1,5 +1,5 @@
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity } from 'database'
import { ObjectType, Field } from 'type-graphql'
import { Field, ObjectType } from 'type-graphql'
import { Point } from 'typeorm'
import { Point2Location } from '@/graphql/resolver/util/Location2Point'

View File

@ -1,5 +1,5 @@
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field } from 'type-graphql'
import { Field, ObjectType } from 'type-graphql'
@ObjectType()
export class AdminUpdateContribution {

View File

@ -1,5 +1,5 @@
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int, Float } from 'type-graphql'
import { Field, Float, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class Balance {

View File

@ -1,4 +1,4 @@
import { ObjectType, Field } from 'type-graphql'
import { Field, ObjectType } from 'type-graphql'
import { Message } from '@/apis/openai/model/Message'

View File

@ -1,5 +1,5 @@
import { Community as DbCommunity } from 'database'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class Community {

View File

@ -1,5 +1,5 @@
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class DynamicStatisticsFields {

View File

@ -1,6 +1,6 @@
import { Contribution as dbContribution, User as DbUser } from 'database'
import { User as DbUser, Contribution as dbContribution } from 'database'
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { User } from './User'

View File

@ -1,6 +1,6 @@
import { ContributionLink as dbContributionLink } from 'database'
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { CONFIG } from '@/config'

View File

@ -1,4 +1,4 @@
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { ContributionLink } from '@model/ContributionLink'

View File

@ -1,5 +1,5 @@
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
interface DecayInterface {
balance: Decimal

View File

@ -1,5 +1,5 @@
import { FederatedCommunity as DbFederatedCommunity } from 'database'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { ensureUrlEndsWithSlash } from '@/util/utilities'

View File

@ -1,6 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ObjectType, Field, Float, Int } from 'type-graphql'
import { Field, Float, Int, ObjectType } from 'type-graphql'
import { GdtEntryType } from '@enum/GdtEntryType'
@ -12,9 +10,9 @@ export class GdtEntry {
date,
email,
comment,
// eslint-disable-next-line camelcase
coupon_code,
// eslint-disable-next-line camelcase
gdt_entry_type_id,
factor,
amount2,
@ -26,9 +24,9 @@ export class GdtEntry {
this.date = date
this.email = email
this.comment = comment
// eslint-disable-next-line camelcase
this.couponCode = coupon_code
// eslint-disable-next-line camelcase
this.gdtEntryType = gdt_entry_type_id
this.factor = factor
this.amount2 = amount2

View File

@ -1,4 +1,4 @@
import { ObjectType, Field, Int, Float } from 'type-graphql'
import { Field, Float, Int, ObjectType } from 'type-graphql'
import { GdtEntry } from './GdtEntry'

View File

@ -1,4 +1,4 @@
import { ObjectType, Field } from 'type-graphql'
import { Field, ObjectType } from 'type-graphql'
@ObjectType()
export class KlickTipp {

View File

@ -1,5 +1,5 @@
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class OpenCreation {

View File

@ -1,4 +1,4 @@
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class Pagination {

View File

@ -1,5 +1,5 @@
import { ProjectBranding as dbProjectBranding } from 'database'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class ProjectBranding {

View File

@ -1,4 +1,4 @@
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { Space as HumhubSpace } from '@/apis/humhub/model/Space'

View File

@ -1,4 +1,4 @@
import { ObjectType, Field } from 'type-graphql'
import { Field, ObjectType } from 'type-graphql'
import { SpacesResponse } from '@/apis/humhub/model/SpacesResponse'

View File

@ -1,6 +1,6 @@
import { Transaction as dbTransaction } from 'database'
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { TransactionTypeId } from '@enum/TransactionTypeId'

View File

@ -1,6 +1,6 @@
import { TransactionLink as dbTransactionLink } from 'database'
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { CONFIG } from '@/config'

View File

@ -1,4 +1,4 @@
import { ObjectType, Field } from 'type-graphql'
import { Field, ObjectType } from 'type-graphql'
import { Balance } from './Balance'
import { Transaction } from './Transaction'

View File

@ -1,6 +1,6 @@
import { Contribution, User } from 'database'
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class UnconfirmedContribution {

View File

@ -1,5 +1,5 @@
import { User as dbUser } from 'database'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
import { Point } from 'typeorm'
import { GmsPublishLocationType } from '@enum/GmsPublishLocationType'

View File

@ -1,6 +1,6 @@
import { User } from 'database'
import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class UserAdmin {

View File

@ -1,5 +1,5 @@
import { UserContact as DbUserContact } from 'database'
import { ObjectType, Field, Int } from 'type-graphql'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
export class UserContact {

View File

@ -1,10 +1,10 @@
import { Resolver, Mutation, Authorized, Ctx, Arg, Query } from 'type-graphql'
import { Arg, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql'
import { OpenaiMessage } from '@input/OpenaiMessage'
import { ChatGptMessage } from '@model/ChatGptMessage'
import { Message } from '@/apis/openai/model/Message'
import { OpenaiClient } from '@/apis/openai/OpenaiClient'
import { Message } from '@/apis/openai/model/Message'
import { RIGHTS } from '@/auth/RIGHTS'
import { Context } from '@/server/context'

View File

@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { Transaction as dbTransaction, TransactionLink as dbTransactionLink } from 'database'
import { Decimal } from 'decimal.js-light'
import { Resolver, Query, Ctx, Authorized } from 'type-graphql'
import { Authorized, Ctx, Query, Resolver } from 'type-graphql'
import { IsNull } from 'typeorm'
import { Balance } from '@model/Balance'

View File

@ -1,10 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { ApolloServerTestClient } from 'apollo-server-testing'
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity } from 'database'
import { GraphQLError } from 'graphql/error/GraphQLError'
@ -12,16 +5,16 @@ import { Connection } from 'typeorm'
import { v4 as uuidv4 } from 'uuid'
import { cleanDB, testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
import { i18n as localization, logger } from '@test/testSetup'
import { userFactory } from '@/seeds/factory/user'
import { login, updateHomeCommunityQuery } from '@/seeds/graphql/mutations'
import {
allCommunities,
getCommunities,
communitiesQuery,
getHomeCommunityQuery,
getCommunities,
getCommunityByIdentifierQuery,
getHomeCommunityQuery,
} from '@/seeds/graphql/queries'
import { peterLustig } from '@/seeds/users/peter-lustig'
@ -30,9 +23,9 @@ import { getCommunityByUuid } from './util/communities'
jest.mock('@/password/EncryptorUtils')
// to do: We need a setup for the tests that closes the connection
let mutate: ApolloServerTestClient['mutate'],
query: ApolloServerTestClient['query'],
con: Connection
let mutate: ApolloServerTestClient['mutate']
let query: ApolloServerTestClient['query']
let con: Connection
let testEnv: {
mutate: ApolloServerTestClient['mutate']

View File

@ -1,5 +1,5 @@
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity } from 'database'
import { Resolver, Query, Authorized, Mutation, Args, Arg } from 'type-graphql'
import { Arg, Args, Authorized, Mutation, Query, Resolver } from 'type-graphql'
import { IsNull, Not } from 'typeorm'
import { Paginated } from '@arg/Paginated'
@ -11,13 +11,13 @@ import { FederatedCommunity } from '@model/FederatedCommunity'
import { RIGHTS } from '@/auth/RIGHTS'
import { LogError } from '@/server/LogError'
import { Location2Point } from './util/Location2Point'
import {
getAllCommunities,
getCommunityByIdentifier,
getCommunityByUuid,
getHomeCommunity,
} from './util/communities'
import { Location2Point } from './util/Location2Point'
@Resolver()
export class CommunityResolver {

View File

@ -1,20 +1,18 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { ApolloServerTestClient } from 'apollo-server-testing'
import { ContributionLink as DbContributionLink, Event as DbEvent } from 'database'
import { Decimal } from 'decimal.js-light'
import { GraphQLError } from 'graphql'
import { Connection } from 'typeorm'
import { cleanDB, testEnvironment, resetToken } from '@test/helpers'
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
import { logger } from '@test/testSetup'
import { EventType } from '@/event/Events'
import { userFactory } from '@/seeds/factory/user'
import {
login,
createContributionLink,
deleteContributionLink,
login,
updateContributionLink,
} from '@/seeds/graphql/mutations'
import { listContributionLinks } from '@/seeds/graphql/queries'
@ -23,9 +21,9 @@ import { peterLustig } from '@/seeds/users/peter-lustig'
jest.mock('@/password/EncryptorUtils')
let mutate: ApolloServerTestClient['mutate'],
query: ApolloServerTestClient['query'],
con: Connection
let mutate: ApolloServerTestClient['mutate']
let query: ApolloServerTestClient['query']
let con: Connection
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']

View File

@ -1,6 +1,6 @@
import { ContributionLink as DbContributionLink } from 'database'
import { Resolver, Args, Arg, Authorized, Mutation, Query, Int, Ctx } from 'type-graphql'
import { MoreThan, IsNull } from 'typeorm'
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
import { IsNull, MoreThan } from 'typeorm'
import { ContributionLinkArgs } from '@arg/ContributionLinkArgs'
import { Paginated } from '@arg/Paginated'
@ -14,8 +14,8 @@ import {
EVENT_ADMIN_CONTRIBUTION_LINK_DELETE,
EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE,
} from '@/event/Events'
import { Context, getUser } from '@/server/context'
import { LogError } from '@/server/LogError'
import { Context, getUser } from '@/server/context'
import { transactionLinkCode as contributionLinkCode } from './TransactionLinkResolver'
import { isStartEndDateValid } from './util/creations'
@ -47,8 +47,12 @@ export class ContributionLinkResolver {
dbContributionLink.createdAt = new Date()
dbContributionLink.code = contributionLinkCode(dbContributionLink.createdAt)
dbContributionLink.cycle = cycle
if (validFrom) dbContributionLink.validFrom = new Date(validFrom)
if (validTo) dbContributionLink.validTo = new Date(validTo)
if (validFrom) {
dbContributionLink.validFrom = new Date(validFrom)
}
if (validTo) {
dbContributionLink.validTo = new Date(validTo)
}
dbContributionLink.maxAmountPerMonth = maxAmountPerMonth
dbContributionLink.maxPerCycle = maxPerCycle
await dbContributionLink.save()
@ -116,8 +120,12 @@ export class ContributionLinkResolver {
dbContributionLink.name = name
dbContributionLink.memo = memo
dbContributionLink.cycle = cycle
if (validFrom) dbContributionLink.validFrom = new Date(validFrom)
if (validTo) dbContributionLink.validTo = new Date(validTo)
if (validFrom) {
dbContributionLink.validFrom = new Date(validFrom)
}
if (validTo) {
dbContributionLink.validTo = new Date(validTo)
}
dbContributionLink.maxAmountPerMonth = maxAmountPerMonth
dbContributionLink.maxPerCycle = maxPerCycle
await dbContributionLink.save()

View File

@ -1,8 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ApolloServerTestClient } from 'apollo-server-testing'
import { Contribution as DbContribution, Event as DbEvent } from 'database'
import { GraphQLError } from 'graphql'
@ -10,7 +5,7 @@ import { Connection } from 'typeorm'
import { ContributionStatus } from '@enum/ContributionStatus'
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
import { i18n as localization, logger } from '@test/testSetup'
import { sendAddedContributionMessageEmail } from '@/emails/sendEmailVariants'
import { EventType } from '@/event/Events'
@ -21,7 +16,7 @@ import {
createContributionMessage,
login,
} from '@/seeds/graphql/mutations'
import { listContributionMessages, adminListContributionMessages } from '@/seeds/graphql/queries'
import { adminListContributionMessages, listContributionMessages } from '@/seeds/graphql/queries'
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
import { peterLustig } from '@/seeds/users/peter-lustig'
@ -38,7 +33,8 @@ jest.mock('@/emails/sendEmailVariants', () => {
}
})
let mutate: ApolloServerTestClient['mutate'], con: Connection
let mutate: ApolloServerTestClient['mutate']
let con: Connection
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']

View File

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import {
Contribution as DbContribution,
ContributionMessage as DbContributionMessage,
@ -20,8 +19,8 @@ import {
EVENT_CONTRIBUTION_MESSAGE_CREATE,
} from '@/event/Events'
import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUnconfirmedContribution/UpdateUnconfirmedContribution.context'
import { Context, getUser } from '@/server/context'
import { LogError } from '@/server/LogError'
import { Context, getUser } from '@/server/context'
import { backendLogger as logger } from '@/server/logger'
import { findContributionMessages } from './util/findContributionMessages'
@ -177,9 +176,10 @@ export class ContributionMessageResolver {
throw new LogError('ContributionMessage was not sent successfully')
}
const moderator = getUser(context)
if (messageType === ContributionMessageType.DIALOG) {
// send email (never for moderator messages)
void sendAddedContributionMessageEmail({
await sendAddedContributionMessageEmail({
firstName: finalContribution.user.firstName,
lastName: finalContribution.user.lastName,
email: finalContribution.user.emailContact.email,

View File

@ -1,6 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { UserInputError } from 'apollo-server-express'
import { ApolloServerTestClient } from 'apollo-server-testing'
import { Contribution, Event as DbEvent, Transaction as DbTransaction, User } from 'database'
@ -13,12 +10,12 @@ import { ContributionStatus } from '@enum/ContributionStatus'
import { Order } from '@enum/Order'
import {
cleanDB,
resetToken,
testEnvironment,
contributionDateFormatter,
resetEntity,
resetToken,
testEnvironment,
} from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
import { i18n as localization, logger } from '@test/testSetup'
import {
sendContributionConfirmedEmail,
@ -30,22 +27,22 @@ import { creations } from '@/seeds/creation/index'
import { creationFactory } from '@/seeds/factory/creation'
import { userFactory } from '@/seeds/factory/user'
import {
adminCreateContribution,
adminCreateContributionMessage,
adminDeleteContribution,
adminUpdateContribution,
confirmContribution,
createContribution,
updateContribution,
deleteContribution,
denyContribution,
confirmContribution,
adminCreateContribution,
adminUpdateContribution,
adminDeleteContribution,
login,
logout,
adminCreateContributionMessage,
updateContribution,
} from '@/seeds/graphql/mutations'
import {
adminListContributions,
listAllContributions,
listContributions,
adminListContributions,
} from '@/seeds/graphql/queries'
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
@ -58,9 +55,9 @@ import { getFirstDayOfPreviousNMonth } from '@/util/utilities'
jest.mock('@/emails/sendEmailVariants')
jest.mock('@/password/EncryptorUtils')
let mutate: ApolloServerTestClient['mutate'],
query: ApolloServerTestClient['query'],
con: Connection
let mutate: ApolloServerTestClient['mutate']
let query: ApolloServerTestClient['query']
let con: Connection
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']
@ -96,7 +93,7 @@ describe('ContributionResolver', () => {
admin = await userFactory(testEnv, peterLustig)
await userFactory(testEnv, raeuberHotzenplotz)
const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de')
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
bibiCreatedContribution = await creationFactory(testEnv, bibisCreation!)
await mutate({
mutation: login,
@ -2278,7 +2275,6 @@ describe('ContributionResolver', () => {
})
})
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('creation update is successful changing month', () => {
// skipped as changing the month is currently disable
it('returns update creation object', async () => {

View File

@ -45,25 +45,25 @@ import {
sendContributionDeniedEmail,
} from '@/emails/sendEmailVariants'
import {
EVENT_ADMIN_CONTRIBUTION_CONFIRM,
EVENT_ADMIN_CONTRIBUTION_CREATE,
EVENT_ADMIN_CONTRIBUTION_DELETE,
EVENT_ADMIN_CONTRIBUTION_DENY,
EVENT_ADMIN_CONTRIBUTION_UPDATE,
EVENT_CONTRIBUTION_CREATE,
EVENT_CONTRIBUTION_DELETE,
EVENT_CONTRIBUTION_UPDATE,
EVENT_ADMIN_CONTRIBUTION_CREATE,
EVENT_ADMIN_CONTRIBUTION_UPDATE,
EVENT_ADMIN_CONTRIBUTION_DELETE,
EVENT_ADMIN_CONTRIBUTION_CONFIRM,
EVENT_ADMIN_CONTRIBUTION_DENY,
} from '@/event/Events'
import { UpdateUnconfirmedContributionContext } from '@/interactions/updateUnconfirmedContribution/UpdateUnconfirmedContribution.context'
import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
import { LogError } from '@/server/LogError'
import { Context, getClientTimezoneOffset, getUser } from '@/server/context'
import { backendLogger as logger } from '@/server/logger'
import { calculateDecay } from '@/util/decay'
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
import { calculateDecay } from '@/util/decay'
import { fullName } from '@/util/utilities'
import { findContribution } from './util/contributions'
import { getUserCreation, validateContribution, getOpenCreations } from './util/creations'
import { getOpenCreations, getUserCreation, validateContribution } from './util/creations'
import { extractGraphQLFields, extractGraphQLFieldsForSelect } from './util/extractGraphQLFields'
import { findContributions } from './util/findContributions'
import { getLastTransaction } from './util/getLastTransaction'
@ -320,7 +320,7 @@ export class ContributionResolver {
relations: ['emailContact'],
})
void sendContributionChangedByModeratorEmail({
await sendContributionChangedByModeratorEmail({
firstName: user.firstName,
lastName: user.lastName,
email: user.emailContact.email,
@ -410,7 +410,7 @@ export class ContributionResolver {
contribution,
contribution.amount,
)
void sendContributionDeletedEmail({
await sendContributionDeletedEmail({
firstName: user.firstName,
lastName: user.lastName,
email: user.emailContact.email,
@ -513,10 +513,10 @@ export class ContributionResolver {
await queryRunner.commitTransaction()
// trigger to send transaction via dlt-connector
void sendTransactionsToDltConnector()
await sendTransactionsToDltConnector()
logger.info('creation commited successfuly.')
void sendContributionConfirmedEmail({
await sendContributionConfirmedEmail({
firstName: user.firstName,
lastName: user.lastName,
email: user.emailContact.email,
@ -600,7 +600,7 @@ export class ContributionResolver {
contributionToUpdate.amount,
)
void sendContributionDeniedEmail({
await sendContributionDeniedEmail({
firstName: user.firstName,
lastName: user.lastName,
email: user.emailContact.email,

View File

@ -1,20 +1,18 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { ApolloServerTestClient } from 'apollo-server-testing'
import { User as DbUser } from 'database'
import { GraphQLError } from 'graphql'
import { Connection } from 'typeorm'
import { testEnvironment, cleanDB } from '@test/helpers'
import { cleanDB, testEnvironment } from '@test/helpers'
import { CONFIG } from '@/config'
import { writeHomeCommunityEntry } from '@/seeds/community'
import { createUser, setPassword, forgotPassword } from '@/seeds/graphql/mutations'
import { createUser, forgotPassword, setPassword } from '@/seeds/graphql/mutations'
import { queryOptIn } from '@/seeds/graphql/queries'
let mutate: ApolloServerTestClient['mutate'],
query: ApolloServerTestClient['query'],
con: Connection
let mutate: ApolloServerTestClient['mutate']
let query: ApolloServerTestClient['query']
let con: Connection
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']

View File

@ -1,8 +1,4 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { Resolver, Query, Args, Ctx, Authorized, Arg, Int, Float } from 'type-graphql'
import { Arg, Args, Authorized, Ctx, Float, Int, Query, Resolver } from 'type-graphql'
import { Paginated } from '@arg/Paginated'
import { Order } from '@enum/Order'
@ -12,8 +8,10 @@ import { GdtEntryList } from '@model/GdtEntryList'
import { apiGet, apiPost } from '@/apis/HttpRequest'
import { RIGHTS } from '@/auth/RIGHTS'
import { CONFIG } from '@/config'
import { Context, getUser } from '@/server/context'
import { LogError } from '@/server/LogError'
import { Context, getUser } from '@/server/context'
import { backendLogger as logger } from '@/server/logger'
@Resolver()
export class GdtResolver {
@ -25,20 +23,12 @@ export class GdtResolver {
@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,
)
return new GdtEntryList('disabled', 0, [], 0, 0)
}
const userEntity = getUser(context)
try {
const resultGDT = await apiGet(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`${CONFIG.GDT_API_URL}/GdtEntries/listPerEmailApi/${userEntity.emailContact.email}/${currentPage}/${pageSize}/${order}`,
)
if (!resultGDT.success) {
@ -48,12 +38,12 @@ export class GdtResolver {
return new GdtEntryList(
state,
count,
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
gdtEntries ? gdtEntries.map((data: any) => new GdtEntry(data)) : [],
gdtSum,
timeUsed,
)
} catch (err) {
logger.error('GDT Server is not reachable', err)
throw new LogError('GDT Server is not reachable')
}
}
@ -74,15 +64,13 @@ export class GdtResolver {
}
return Number(resultGDTSum.data.sum) || 0
} catch (err) {
// eslint-disable-next-line no-console
console.log('Could not query GDT Server')
logger.error('Could not query GDT Server', err)
return null
}
}
@Authorized([RIGHTS.EXIST_PID])
@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

View File

@ -1,13 +1,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Event as DbEvent, UserContact } from 'database'
import { GraphQLError } from 'graphql'
import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
import { i18n as localization, logger } from '@test/testSetup'
import { EventType } from '@/event/Events'
import { userFactory } from '@/seeds/factory/user'
@ -16,7 +11,9 @@ import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
jest.mock('@/password/EncryptorUtils')
let testEnv: any, mutate: any, con: any
let testEnv: any
let mutate: any
let con: any
beforeAll(async () => {
testEnv = await testEnvironment(logger, localization)

View File

@ -1,6 +1,6 @@
import { Resolver, Authorized, Mutation, Ctx } from 'type-graphql'
import { Authorized, Ctx, Mutation, Resolver } from 'type-graphql'
import { unsubscribe, subscribe } from '@/apis/KlicktippController'
import { subscribe, unsubscribe } from '@/apis/KlicktippController'
import { RIGHTS } from '@/auth/RIGHTS'
import { EVENT_NEWSLETTER_SUBSCRIBE, EVENT_NEWSLETTER_UNSUBSCRIBE } from '@/event/Events'
import { Context, getUser } from '@/server/context'

View File

@ -1,5 +1,5 @@
import { ProjectBranding as DbProjectBranding } from 'database'
import { Resolver, Query, Mutation, Arg, Int, Authorized, ID } from 'type-graphql'
import { Arg, Authorized, ID, Int, Mutation, Query, Resolver } from 'type-graphql'
import { ProjectBrandingInput } from '@input/ProjectBrandingInput'
import { ProjectBranding } from '@model/ProjectBranding'

View File

@ -1,9 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { Transaction as DbTransaction, User as DbUser } from 'database'
import { Decimal } from 'decimal.js-light'
import { Resolver, Query, Authorized, FieldResolver } from 'type-graphql'
import { Authorized, FieldResolver, Query, Resolver } from 'type-graphql'
import { getConnection } from 'typeorm'
import { CommunityStatistics, DynamicStatisticsFields } from '@model/CommunityStatistics'
@ -11,8 +8,7 @@ import { CommunityStatistics, DynamicStatisticsFields } from '@model/CommunitySt
import { RIGHTS } from '@/auth/RIGHTS'
import { calculateDecay } from '@/util/decay'
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
@Resolver((of) => CommunityStatistics)
@Resolver(() => CommunityStatistics)
export class StatisticsResolver {
@Authorized([RIGHTS.COMMUNITY_STATISTICS])
@Query(() => CommunityStatistics)

View File

@ -1,6 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { ApolloServerTestClient } from 'apollo-server-testing'
import {
ContributionLink as DbContributionLink,
@ -14,7 +11,7 @@ import { GraphQLError } from 'graphql'
import { Connection } from 'typeorm'
import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
import { cleanDB, testEnvironment, resetToken, resetEntity } from '@test/helpers'
import { cleanDB, resetEntity, resetToken, testEnvironment } from '@test/helpers'
import { logger } from '@test/testSetup'
import { EventType } from '@/event/Events'
@ -23,14 +20,14 @@ import { creationFactory } from '@/seeds/factory/creation'
import { transactionLinkFactory } from '@/seeds/factory/transactionLink'
import { userFactory } from '@/seeds/factory/user'
import {
login,
createContributionLink,
redeemTransactionLink,
confirmContribution,
createContribution,
updateContribution,
createContributionLink,
createTransactionLink,
deleteTransactionLink,
confirmContribution,
login,
redeemTransactionLink,
updateContribution,
} from '@/seeds/graphql/mutations'
import { listTransactionLinksAdmin } from '@/seeds/graphql/queries'
import { transactionLinks } from '@/seeds/transactionLink/index'
@ -46,9 +43,9 @@ jest.mock('@/password/EncryptorUtils')
jest.mock('@/util/TRANSACTIONS_LOCK')
TRANSACTIONS_LOCK.acquire = jest.fn().mockResolvedValue(jest.fn())
let mutate: ApolloServerTestClient['mutate'],
query: ApolloServerTestClient['query'],
con: Connection
let mutate: ApolloServerTestClient['mutate']
let query: ApolloServerTestClient['query']
let con: Connection
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']
@ -892,7 +889,7 @@ describe('TransactionLinkResolver', () => {
variables.pageSize = 25
// bibi needs GDDs
const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de')
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await creationFactory(testEnv, bibisCreation!)
// bibis transaktion links
const bibisTransaktionLinks = transactionLinks.filter(
@ -1068,7 +1065,7 @@ describe('TransactionLinkResolver', () => {
})
// TODO: works not as expected, because 'redeemedAt' and 'redeemedBy' have to be added to the transaktion link factory
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('filter by redeemed', () => {
it('finds 6 open transaction links, 1 deleted, and no redeemed', async () => {
await expect(
@ -1121,7 +1118,6 @@ describe('TransactionLinkResolver', () => {
})
it('returns a string that ends with the hex value of date', () => {
// eslint-disable-next-line security/detect-non-literal-regexp
const regexp = new RegExp(date.getTime().toString(16) + '$')
expect(transactionLinkCode(date)).toEqual(expect.stringMatching(regexp))
})

View File

@ -8,7 +8,7 @@ import {
User as DbUser,
} from 'database'
import { Decimal } from 'decimal.js-light'
import { Resolver, Args, Arg, Authorized, Ctx, Mutation, Query, Int } from 'type-graphql'
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
import { getConnection } from 'typeorm'
import { Paginated } from '@arg/Paginated'
@ -31,12 +31,12 @@ import {
EVENT_TRANSACTION_LINK_DELETE,
EVENT_TRANSACTION_LINK_REDEEM,
} from '@/event/Events'
import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
import { LogError } from '@/server/LogError'
import { Context, getClientTimezoneOffset, getUser } from '@/server/context'
import { backendLogger as logger } from '@/server/logger'
import { calculateDecay } from '@/util/decay'
import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK'
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
import { TRANSACTION_LINK_LOCK } from '@/util/TRANSACTION_LINK_LOCK'
import { calculateDecay } from '@/util/decay'
import { fullName } from '@/util/utilities'
import { calculateBalance } from '@/util/validate'
@ -313,7 +313,7 @@ export class TransactionLinkResolver {
releaseLock()
}
// trigger to send transaction via dlt-connector
void sendTransactionsToDltConnector()
await sendTransactionsToDltConnector()
return true
} else {
const now = new Date()
@ -389,9 +389,8 @@ export class TransactionLinkResolver {
async listTransactionLinksAdmin(
@Args()
paginated: Paginated,
// eslint-disable-next-line type-graphql/wrong-decorator-signature
@Arg('filters', () => TransactionLinkFilters, { nullable: true })
filters: TransactionLinkFilters | null, // eslint-disable-line type-graphql/invalid-nullable-input-type
filters: TransactionLinkFilters,
@Arg('userId', () => Int)
userId: number,
): Promise<TransactionLinkResult> {

Some files were not shown because too many files have changed in this diff Show More