This commit is contained in:
Ulf Gebhardt 2023-04-11 13:03:37 +02:00
commit 06fc7a729c
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
156 changed files with 1188 additions and 498 deletions

View File

@ -33,6 +33,7 @@
"bootstrap": "4.3.1", "bootstrap": "4.3.1",
"bootstrap-vue": "^2.21.2", "bootstrap-vue": "^2.21.2",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"date-fns": "^2.29.3",
"dotenv-webpack": "^7.0.3", "dotenv-webpack": "^7.0.3",
"express": "^4.17.1", "express": "^4.17.1",
"graphql": "^15.6.1", "graphql": "^15.6.1",

View File

@ -0,0 +1,183 @@
import { mount } from '@vue/test-utils'
import FederationVisualizeItem from './FederationVisualizeItem.vue'
const localVue = global.localVue
const today = new Date()
const createdDate = new Date()
createdDate.setDate(createdDate.getDate() - 3)
let propsData = {
item: {
id: 7590,
foreign: false,
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
url: 'http://localhost/api/2_0',
lastAnnouncedAt: createdDate,
verifiedAt: today,
lastErrorAt: null,
createdAt: createdDate,
updatedAt: null,
},
}
const mocks = {
$i18n: {
locale: 'en',
},
}
describe('FederationVisualizeItem', () => {
let wrapper
const Wrapper = () => {
return mount(FederationVisualizeItem, { localVue, mocks, propsData })
}
describe('mount', () => {
beforeEach(() => {
wrapper = Wrapper()
})
it('renders the component', () => {
expect(wrapper.find('div.federation-visualize-item').exists()).toBe(true)
})
describe('rendering item properties', () => {
it('has the url', () => {
expect(wrapper.find('.row > div:nth-child(2) > div').text()).toBe(
'http://localhost/api/2_0',
)
})
it('has the public key', () => {
expect(wrapper.find('.row > div:nth-child(2) > small').text()).toContain(
'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7'.substring(0, 26),
)
})
describe('verified item', () => {
it('has the check icon', () => {
expect(wrapper.find('svg.bi-check').exists()).toBe(true)
})
it('has the text variant "success"', () => {
expect(wrapper.find('.text-success').exists()).toBe(true)
})
})
describe('not verified item', () => {
beforeEach(() => {
propsData = {
item: {
id: 7590,
foreign: false,
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
url: 'http://localhost/api/2_0',
lastAnnouncedAt: createdDate,
verifiedAt: null,
lastErrorAt: null,
createdAt: createdDate,
updatedAt: null,
},
}
wrapper = Wrapper()
})
it('has the x-circle icon', () => {
expect(wrapper.find('svg.bi-x-circle').exists()).toBe(true)
})
it('has the text variant "danger"', () => {
expect(wrapper.find('.text-danger').exists()).toBe(true)
})
})
// describe('with different locales (de, en, fr, es, nl)', () => {
describe('lastAnnouncedAt', () => {
it('computes the time string for different locales (de, en, fr, es, nl)', () => {
wrapper.vm.$i18n.locale = 'de'
wrapper = Wrapper()
expect(wrapper.vm.lastAnnouncedAt).toBe('vor 3 Tagen')
wrapper.vm.$i18n.locale = 'fr'
wrapper = Wrapper()
expect(wrapper.vm.lastAnnouncedAt).toBe('il y a 3 jours')
wrapper.vm.$i18n.locale = 'es'
wrapper = Wrapper()
expect(wrapper.vm.lastAnnouncedAt).toBe('hace 3 días')
wrapper.vm.$i18n.locale = 'nl'
wrapper = Wrapper()
expect(wrapper.vm.lastAnnouncedAt).toBe('3 dagen geleden')
})
describe('lastAnnouncedAt == null', () => {
beforeEach(() => {
propsData = {
item: {
id: 7590,
foreign: false,
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
url: 'http://localhost/api/2_0',
lastAnnouncedAt: null,
verifiedAt: null,
lastErrorAt: null,
createdAt: createdDate,
updatedAt: null,
},
}
wrapper = Wrapper()
})
it('computes empty string', async () => {
expect(wrapper.vm.lastAnnouncedAt).toBe('')
})
})
})
describe('createdAt', () => {
it('computes the time string for different locales (de, en, fr, es, nl)', () => {
wrapper.vm.$i18n.locale = 'de'
wrapper = Wrapper()
expect(wrapper.vm.createdAt).toBe('vor 3 Tagen')
wrapper.vm.$i18n.locale = 'fr'
wrapper = Wrapper()
expect(wrapper.vm.createdAt).toBe('il y a 3 jours')
wrapper.vm.$i18n.locale = 'es'
wrapper = Wrapper()
expect(wrapper.vm.createdAt).toBe('hace 3 días')
wrapper.vm.$i18n.locale = 'nl'
wrapper = Wrapper()
expect(wrapper.vm.createdAt).toBe('3 dagen geleden')
})
describe('createdAt == null', () => {
beforeEach(() => {
propsData = {
item: {
id: 7590,
foreign: false,
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
url: 'http://localhost/api/2_0',
lastAnnouncedAt: createdDate,
verifiedAt: null,
lastErrorAt: null,
createdAt: null,
updatedAt: null,
},
}
wrapper = Wrapper()
})
it('computes empty string', async () => {
expect(wrapper.vm.createdAt).toBe('')
})
})
})
})
})
})

View File

@ -0,0 +1,63 @@
<template>
<div class="federation-visualize-item">
<b-row>
<b-col cols="1"><b-icon :icon="icon" :variant="variant" class="mr-4"></b-icon></b-col>
<b-col>
<div>{{ item.url }}</div>
<small>{{ `${item.publicKey.substring(0, 26)}` }}</small>
</b-col>
<b-col cols="2">{{ lastAnnouncedAt }}</b-col>
<b-col cols="2">{{ createdAt }}</b-col>
</b-row>
</div>
</template>
<script>
import { formatDistanceToNow } from 'date-fns'
import { de, en, fr, es, nl } from 'date-fns/locale'
const locales = { en, de, es, fr, nl }
export default {
name: 'FederationVisualizeItem',
props: {
item: { type: Object },
},
data() {
return {
formatDistanceToNow,
locale: this.$i18n.locale,
}
},
computed: {
verified() {
return new Date(this.item.verifiedAt) >= new Date(this.item.lastAnnouncedAt)
},
icon() {
return this.verified ? 'check' : 'x-circle'
},
variant() {
return this.verified ? 'success' : 'danger'
},
lastAnnouncedAt() {
if (this.item.lastAnnouncedAt) {
return formatDistanceToNow(new Date(this.item.lastAnnouncedAt), {
includeSecond: true,
addSuffix: true,
locale: locales[this.locale],
})
}
return ''
},
createdAt() {
if (this.item.createdAt) {
return formatDistanceToNow(new Date(this.item.createdAt), {
includeSecond: true,
addSuffix: true,
locale: locales[this.locale],
})
}
return ''
},
},
}
</script>

View File

@ -62,8 +62,12 @@ describe('NavBar', () => {
) )
}) })
it('has a link to /federation', () => {
expect(wrapper.findAll('.nav-item').at(3).find('a').attributes('href')).toBe('/federation')
})
it('has a link to /statistic', () => { it('has a link to /statistic', () => {
expect(wrapper.findAll('.nav-item').at(3).find('a').attributes('href')).toBe('/statistic') expect(wrapper.findAll('.nav-item').at(4).find('a').attributes('href')).toBe('/statistic')
}) })
}) })
@ -72,7 +76,7 @@ describe('NavBar', () => {
beforeEach(async () => { beforeEach(async () => {
delete window.location delete window.location
window.location = '' window.location = ''
await wrapper.findAll('.nav-item').at(4).find('a').trigger('click') await wrapper.findAll('.nav-item').at(5).find('a').trigger('click')
}) })
afterEach(() => { afterEach(() => {
@ -97,7 +101,7 @@ describe('NavBar', () => {
window.location = { window.location = {
assign: windowLocationMock, assign: windowLocationMock,
} }
await wrapper.findAll('.nav-item').at(5).find('a').trigger('click') await wrapper.findAll('.nav-item').at(6).find('a').trigger('click')
}) })
afterEach(() => { afterEach(() => {

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="component-nabvar"> <div class="component-nabvar">
<b-navbar toggleable="md" type="dark" variant="success"> <b-navbar toggleable="lg" type="dark" class="bg-dark">
<b-navbar-brand class="mb-2" to="/"> <b-navbar-brand class="mb-2" to="/">
<img src="img/brand/gradido_logo_w.png" class="navbar-brand-img pl-2" alt="..." /> <img src="img/brand/gradido_logo_w.png" class="navbar-brand-img pl-2" alt="..." />
</b-navbar-brand> </b-navbar-brand>
@ -19,6 +19,9 @@
<b-nav-item to="/contribution-links"> <b-nav-item to="/contribution-links">
{{ $t('navbar.automaticContributions') }} {{ $t('navbar.automaticContributions') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/federation">
{{ $t('navbar.instances') }}
</b-nav-item>
<b-nav-item to="/statistic">{{ $t('navbar.statistic') }}</b-nav-item> <b-nav-item to="/statistic">{{ $t('navbar.statistic') }}</b-nav-item>
<b-nav-item @click="wallet">{{ $t('navbar.my-account') }}</b-nav-item> <b-nav-item @click="wallet">{{ $t('navbar.my-account') }}</b-nav-item>
<b-nav-item @click="logout">{{ $t('navbar.logout') }}</b-nav-item> <b-nav-item @click="logout">{{ $t('navbar.logout') }}</b-nav-item>

View File

@ -0,0 +1,17 @@
import gql from 'graphql-tag'
export const getCommunities = gql`
query {
getCommunities {
id
foreign
publicKey
url
lastAnnouncedAt
verifiedAt
lastErrorAt
createdAt
updatedAt
}
}
`

View File

@ -68,6 +68,13 @@
"error": "Fehler", "error": "Fehler",
"expired": "abgelaufen", "expired": "abgelaufen",
"e_mail": "E-Mail", "e_mail": "E-Mail",
"federation": {
"createdAt": "Erstellt am",
"gradidoInstances": "Gradido Instanzen",
"lastAnnouncedAt": "letzte Bekanntgabe",
"url": "Url",
"verified": "Verifiziert"
},
"firstname": "Vorname", "firstname": "Vorname",
"footer": { "footer": {
"app_version": "App version {version}", "app_version": "App version {version}",
@ -105,6 +112,7 @@
"name": "Name", "name": "Name",
"navbar": { "navbar": {
"automaticContributions": "Automatische Beiträge", "automaticContributions": "Automatische Beiträge",
"instances": "Instanzen",
"logout": "Abmelden", "logout": "Abmelden",
"my-account": "Mein Konto", "my-account": "Mein Konto",
"statistic": "Statistik", "statistic": "Statistik",

View File

@ -68,6 +68,13 @@
"error": "Error", "error": "Error",
"expired": "expired", "expired": "expired",
"e_mail": "E-mail", "e_mail": "E-mail",
"federation": {
"createdAt": "Created At ",
"gradidoInstances": "Gradido Instances",
"lastAnnouncedAt": "Last Announced",
"url": "Url",
"verified": "Verified"
},
"firstname": "Firstname", "firstname": "Firstname",
"footer": { "footer": {
"app_version": "App version {version}", "app_version": "App version {version}",
@ -105,6 +112,7 @@
"name": "Name", "name": "Name",
"navbar": { "navbar": {
"automaticContributions": "Automatic Contributions", "automaticContributions": "Automatic Contributions",
"instances": "Instances",
"logout": "Logout", "logout": "Logout",
"my-account": "My Account", "my-account": "My Account",
"statistic": "Statistic", "statistic": "Statistic",

View File

@ -39,7 +39,7 @@ const mocks = {
const defaultData = () => { const defaultData = () => {
return { return {
adminListContributions: { adminListContributions: {
contributionCount: 2, contributionCount: 30,
contributionList: [ contributionList: [
{ {
id: 1, id: 1,
@ -407,6 +407,44 @@ describe('CreationConfirm', () => {
statusFilter: ['IN_PROGRESS', 'PENDING', 'CONFIRMED', 'DENIED', 'DELETED'], statusFilter: ['IN_PROGRESS', 'PENDING', 'CONFIRMED', 'DENIED', 'DELETED'],
}) })
}) })
describe('change pagination', () => {
it('has pagination buttons', () => {
expect(wrapper.findComponent({ name: 'BPagination' }).exists()).toBe(true)
})
describe('next page', () => {
beforeEach(() => {
jest.clearAllMocks()
wrapper.findComponent({ name: 'BPagination' }).vm.$emit('input', 2)
})
it('calls the API again', () => {
expect(adminListContributionsMock).toBeCalledWith({
currentPage: 2,
order: 'DESC',
pageSize: 25,
statusFilter: ['IN_PROGRESS', 'PENDING', 'CONFIRMED', 'DENIED', 'DELETED'],
})
})
describe('click tab "open" again', () => {
beforeEach(async () => {
jest.clearAllMocks()
await wrapper.find('a[data-test="open"]').trigger('click')
})
it('refetches contributions with proper filter and current page = 1', () => {
expect(adminListContributionsMock).toBeCalledWith({
currentPage: 1,
order: 'DESC',
pageSize: 25,
statusFilter: ['IN_PROGRESS', 'PENDING'],
})
})
})
})
})
}) })
}) })
}) })

View File

@ -116,6 +116,11 @@ export default {
pageSize: 25, pageSize: 25,
} }
}, },
watch: {
tabIndex() {
this.currentPage = 1
},
},
methods: { methods: {
deleteCreation() { deleteCreation() {
this.$apollo this.$apollo

View File

@ -0,0 +1,125 @@
import { mount } from '@vue/test-utils'
import FederationVisualize from './FederationVisualize'
import VueApollo from 'vue-apollo'
import { createMockClient } from 'mock-apollo-client'
import { getCommunities } from '@/graphql/getCommunities'
import { toastErrorSpy } from '../../test/testSetup'
const mockClient = createMockClient()
const apolloProvider = new VueApollo({
defaultClient: mockClient,
})
const localVue = global.localVue
localVue.use(VueApollo)
const mocks = {
$t: (key) => key,
$d: jest.fn((d) => d),
$i18n: {
locale: 'en',
t: (key) => key,
},
}
const defaultData = () => {
return {
getCommunities: [
{
id: 1776,
foreign: true,
publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527',
url: 'http://localhost/api/2_0',
lastAnnouncedAt: '2023-04-07T12:27:24.037Z',
verifiedAt: null,
lastErrorAt: null,
createdAt: '2023-04-07T11:45:06.254Z',
updatedAt: null,
__typename: 'Community',
},
{
id: 1775,
foreign: true,
publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527',
url: 'http://localhost/api/1_1',
lastAnnouncedAt: '2023-04-07T12:27:24.023Z',
verifiedAt: null,
lastErrorAt: null,
createdAt: '2023-04-07T11:45:06.234Z',
updatedAt: null,
__typename: 'Community',
},
{
id: 1774,
foreign: true,
publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527',
url: 'http://localhost/api/1_0',
lastAnnouncedAt: '2023-04-07T12:27:24.009Z',
verifiedAt: null,
lastErrorAt: null,
createdAt: '2023-04-07T11:45:06.218Z',
updatedAt: null,
__typename: 'Community',
},
],
}
}
describe('FederationVisualize', () => {
let wrapper
const getCommunitiesMock = jest.fn()
mockClient.setRequestHandler(
getCommunities,
getCommunitiesMock
.mockRejectedValueOnce({ message: 'Ouch!' })
.mockResolvedValue({ data: defaultData() }),
)
const Wrapper = () => {
return mount(FederationVisualize, { localVue, mocks, apolloProvider })
}
describe('mount', () => {
beforeEach(() => {
jest.clearAllMocks()
wrapper = Wrapper()
})
describe('server error', () => {
it('toast error', () => {
expect(toastErrorSpy).toBeCalledWith('Ouch!')
})
})
describe('sever success', () => {
it('sends query to Apollo when created', () => {
expect(getCommunitiesMock).toBeCalled()
})
it('has a DIV element with the class "federation-visualize"', () => {
expect(wrapper.find('div.federation-visualize').exists()).toBe(true)
})
it('has a refresh button', () => {
expect(wrapper.find('[data-test="federation-communities-refresh-btn"]').exists()).toBe(true)
})
it('renders 3 community list items', () => {
expect(wrapper.findAll('.list-group-item').length).toBe(3)
})
describe('cklicking the refresh button', () => {
beforeEach(async () => {
jest.clearAllMocks()
await wrapper.find('[data-test="federation-communities-refresh-btn"]').trigger('click')
})
it('calls the API', async () => {
expect(getCommunitiesMock).toBeCalled()
})
})
})
})
})

View File

@ -0,0 +1,69 @@
<template>
<div class="federation-visualize">
<div class="d-flex justify-content-between align-items-center mb-3">
<span class="h2">{{ $t('federation.gradidoInstances') }}</span>
<b-button>
<b-icon
icon="arrow-clockwise"
font-scale="2"
:animation="animation"
@click="$apollo.queries.GetCommunities.refresh()"
data-test="federation-communities-refresh-btn"
></b-icon>
</b-button>
</div>
<b-list-group>
<b-row>
<b-col cols="1" class="ml-1">{{ $t('federation.verified') }}</b-col>
<b-col class="ml-3">{{ $t('federation.url') }}</b-col>
<b-col cols="2">{{ $t('federation.lastAnnouncedAt') }}</b-col>
<b-col cols="2">{{ $t('federation.createdAt') }}</b-col>
</b-row>
<b-list-group-item
v-for="item in communities"
:key="item.id"
:variant="!item.foreign ? 'primary' : 'warning'"
>
<federation-visualize-item :item="item" />
</b-list-group-item>
</b-list-group>
</div>
</template>
<script>
import { getCommunities } from '@/graphql/getCommunities'
import FederationVisualizeItem from '../components/Fedaration/FederationVisualizeItem.vue'
export default {
name: 'FederationVisualize',
components: {
FederationVisualizeItem,
},
data() {
return {
oldPublicKey: '',
communities: [],
icon: '',
}
},
computed: {
animation() {
return this.$apollo.queries.GetCommunities.loading ? 'spin' : ''
},
},
apollo: {
GetCommunities: {
fetchPolicy: 'network-only',
query() {
return getCommunities
},
update({ getCommunities }) {
this.communities = getCommunities
},
error({ message }) {
this.toastError(message)
},
},
},
}
</script>

View File

@ -45,7 +45,7 @@ describe('router', () => {
describe('routes', () => { describe('routes', () => {
it('has nine routes defined', () => { it('has nine routes defined', () => {
expect(routes).toHaveLength(8) expect(routes).toHaveLength(9)
}) })
it('has "/overview" as default', async () => { it('has "/overview" as default', async () => {
@ -88,6 +88,13 @@ describe('router', () => {
}) })
}) })
describe('federation', () => {
it('loads the "FederationVisualize" page', async () => {
const component = await routes.find((r) => r.path === '/federation').component()
expect(component.default.name).toBe('FederationVisualize')
})
})
describe('not found page', () => { describe('not found page', () => {
it('renders the "NotFound" component', async () => { it('renders the "NotFound" component', async () => {
const component = await routes.find((r) => r.path === '*').component() const component = await routes.find((r) => r.path === '*').component()

View File

@ -31,6 +31,10 @@ const routes = [
path: '*', path: '*',
component: () => import('@/components/NotFoundPage.vue'), component: () => import('@/components/NotFoundPage.vue'),
}, },
{
path: '/federation',
component: () => import('@/pages/FederationVisualize.vue'),
},
] ]
export default routes export default routes

View File

@ -5038,6 +5038,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0" whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0" whatwg-url "^8.0.0"
date-fns@^2.29.3:
version "2.29.3"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
de-indent@^1.0.2: de-indent@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"

View File

@ -18,7 +18,9 @@ module.exports = {
'@typescript-eslint/parser': ['.ts', '.tsx'], '@typescript-eslint/parser': ['.ts', '.tsx'],
}, },
'import/resolver': { 'import/resolver': {
typescript: true, typescript: {
project: ['./tsconfig.json', '**/tsconfig.json'],
},
node: true, node: true,
}, },
}, },
@ -55,7 +57,7 @@ module.exports = {
'import/named': 'error', 'import/named': 'error',
'import/namespace': 'error', 'import/namespace': 'error',
'import/no-absolute-path': 'error', 'import/no-absolute-path': 'error',
'import/no-cycle': 'off', 'import/no-cycle': 'error',
'import/no-dynamic-require': 'error', 'import/no-dynamic-require': 'error',
'import/no-internal-modules': 'off', 'import/no-internal-modules': 'off',
'import/no-relative-packages': 'error', 'import/no-relative-packages': 'error',
@ -71,7 +73,7 @@ module.exports = {
'import/group-exports': 'off', 'import/group-exports': 'off',
'import/newline-after-import': 'error', 'import/newline-after-import': 'error',
'import/no-anonymous-default-export': 'error', 'import/no-anonymous-default-export': 'error',
'import/no-default-export': 'off', 'import/no-default-export': 'error',
'import/no-duplicates': 'error', 'import/no-duplicates': 'error',
'import/no-named-default': 'error', 'import/no-named-default': 'error',
'import/no-namespace': 'error', 'import/no-namespace': 'error',
@ -100,7 +102,7 @@ module.exports = {
distinctGroup: true, distinctGroup: true,
}, },
], ],
'import/prefer-default-export': 'off', // TODO 'import/prefer-default-export': 'off',
// n // n
'n/handle-callback-err': 'error', 'n/handle-callback-err': 'error',
'n/no-callback-literal': 'error', 'n/no-callback-literal': 'error',
@ -160,8 +162,8 @@ module.exports = {
'import/unambiguous': 'off', 'import/unambiguous': 'off',
}, },
parserOptions: { parserOptions: {
tsconfigRootDir: './', tsconfigRootDir: __dirname,
project: ['./tsconfig.json'], project: ['./tsconfig.json', '**/tsconfig.json'],
// this is to properly reference the referenced project database without requirement of compiling it // this is to properly reference the referenced project database without requirement of compiling it
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true, EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
}, },

View File

@ -56,17 +56,17 @@
"@types/node": "^16.10.3", "@types/node": "^16.10.3",
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@types/uuid": "^8.3.4", "@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.54.1", "@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.54.1", "@typescript-eslint/parser": "^5.57.1",
"apollo-server-testing": "^2.25.2", "apollo-server-testing": "^2.25.2",
"eslint": "^8.36.0", "eslint": "^8.37.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.8.0",
"eslint-config-standard": "^17.0.0", "eslint-config-standard": "^17.0.0",
"eslint-import-resolver-typescript": "^3.5.3", "eslint-import-resolver-typescript": "^3.5.4",
"eslint-plugin-import": "^2.27.5", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.1", "eslint-plugin-jest": "^27.2.1",
"eslint-plugin-n": "^15.6.1", "eslint-plugin-n": "^15.7.0",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1", "eslint-plugin-promise": "^6.1.1",
"eslint-plugin-type-graphql": "^1.0.0", "eslint-plugin-type-graphql": "^1.0.0",
"faker": "^5.5.3", "faker": "^5.5.3",
@ -74,7 +74,7 @@
"jest": "^27.2.4", "jest": "^27.2.4",
"klicktipp-api": "^1.0.2", "klicktipp-api": "^1.0.2",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"prettier": "^2.3.1", "prettier": "^2.8.7",
"ts-jest": "^27.0.5", "ts-jest": "^27.0.5",
"ts-node": "^10.0.0", "ts-node": "^10.0.0",
"tsconfig-paths": "^3.14.0", "tsconfig-paths": "^3.14.0",

View File

@ -3,7 +3,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-argument */
import axios from 'axios' import axios from 'axios'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@ -4,7 +4,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import CONFIG from '@/config'
import { CONFIG } from '@/config'
// eslint-disable-next-line import/no-relative-parent-imports // eslint-disable-next-line import/no-relative-parent-imports
import KlicktippConnector from 'klicktipp-api' import KlicktippConnector from 'klicktipp-api'

View File

@ -1,7 +1,7 @@
import { verify, sign } from 'jsonwebtoken' import { verify, sign } from 'jsonwebtoken'
import CONFIG from '@/config/' import { CONFIG } from '@/config/'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { CustomJwtPayload } from './CustomJwtPayload' import { CustomJwtPayload } from './CustomJwtPayload'

View File

@ -1,4 +1,4 @@
import CONFIG from './index' import { CONFIG } from './index'
describe('config/index', () => { describe('config/index', () => {
describe('decay start block', () => { describe('decay start block', () => {

View File

@ -121,7 +121,7 @@ const federation = {
Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) || 60000, Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) || 60000,
} }
const CONFIG = { export const CONFIG = {
...constants, ...constants,
...server, ...server,
...database, ...database,
@ -132,5 +132,3 @@ const CONFIG = {
...webhook, ...webhook,
...federation, ...federation,
} }
export default CONFIG

View File

@ -4,7 +4,7 @@ import { createTransport } from 'nodemailer'
import { logger, i18n } from '@test/testSetup' import { logger, i18n } from '@test/testSetup'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { sendEmailTranslated } from './sendEmailTranslated' import { sendEmailTranslated } from './sendEmailTranslated'

View File

@ -6,7 +6,7 @@ import Email from 'email-templates'
import i18n from 'i18n' import i18n from 'i18n'
import { createTransport } from 'nodemailer' import { createTransport } from 'nodemailer'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
export const sendEmailTranslated = async ({ export const sendEmailTranslated = async ({

View File

@ -8,7 +8,7 @@ import { Decimal } from 'decimal.js-light'
import { testEnvironment } from '@test/helpers' import { testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup' import { logger, i18n as localization } from '@test/testSetup'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { sendEmailTranslated } from './sendEmailTranslated' import { sendEmailTranslated } from './sendEmailTranslated'
import { import {

View File

@ -1,6 +1,6 @@
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { decimalSeparatorByLanguage } from '@/util/utilities' import { decimalSeparatorByLanguage } from '@/util/utilities'
import { sendEmailTranslated } from './sendEmailTranslated' import { sendEmailTranslated } from './sendEmailTranslated'

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_CONFIRM = async ( export const EVENT_ADMIN_CONTRIBUTION_CONFIRM = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_CREATE = async ( export const EVENT_ADMIN_CONTRIBUTION_CREATE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_DELETE = async ( export const EVENT_ADMIN_CONTRIBUTION_DELETE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_DENY = async ( export const EVENT_ADMIN_CONTRIBUTION_DENY = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_LINK_CREATE = async ( export const EVENT_ADMIN_CONTRIBUTION_LINK_CREATE = async (
moderator: DbUser, moderator: DbUser,

View File

@ -2,7 +2,8 @@ import { ContributionLink as DbContributionLink } from '@entity/ContributionLink
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_LINK_DELETE = async ( export const EVENT_ADMIN_CONTRIBUTION_LINK_DELETE = async (
moderator: DbUser, moderator: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE = async ( export const EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE = async (
moderator: DbUser, moderator: DbUser,

View File

@ -3,7 +3,8 @@ import { ContributionMessage as DbContributionMessage } from '@entity/Contributi
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE = async ( export const EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async ( export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async (
user: DbUser, user: DbUser,

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_USER_DELETE = async (user: DbUser, moderator: DbUser): Promise<DbEvent> => export const EVENT_ADMIN_USER_DELETE = async (user: DbUser, moderator: DbUser): Promise<DbEvent> =>
Event(EventType.ADMIN_USER_DELETE, user, moderator).save() Event(EventType.ADMIN_USER_DELETE, user, moderator).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_USER_ROLE_SET = async ( export const EVENT_ADMIN_USER_ROLE_SET = async (
user: DbUser, user: DbUser,

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_ADMIN_USER_UNDELETE = async ( export const EVENT_ADMIN_USER_UNDELETE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_CONTRIBUTION_CREATE = async ( export const EVENT_CONTRIBUTION_CREATE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_CONTRIBUTION_DELETE = async ( export const EVENT_CONTRIBUTION_DELETE = async (
user: DbUser, user: DbUser,

View File

@ -5,7 +5,8 @@ import { Transaction as DbTransaction } from '@entity/Transaction'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_CONTRIBUTION_LINK_REDEEM = async ( export const EVENT_CONTRIBUTION_LINK_REDEEM = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { ContributionMessage as DbContributionMessage } from '@entity/Contributi
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_CONTRIBUTION_MESSAGE_CREATE = async ( export const EVENT_CONTRIBUTION_MESSAGE_CREATE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_CONTRIBUTION_UPDATE = async ( export const EVENT_CONTRIBUTION_UPDATE = async (
user: DbUser, user: DbUser,

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION = async (user: DbUser): Promise<DbEvent> => export const EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.EMAIL_ACCOUNT_MULTIREGISTRATION, user, { id: 0 } as DbUser).save() Event(EventType.EMAIL_ACCOUNT_MULTIREGISTRATION, user, { id: 0 } as DbUser).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_EMAIL_ADMIN_CONFIRMATION = async ( export const EVENT_EMAIL_ADMIN_CONFIRMATION = async (
user: DbUser, user: DbUser,

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_EMAIL_CONFIRMATION = async (user: DbUser): Promise<DbEvent> => export const EVENT_EMAIL_CONFIRMATION = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.EMAIL_CONFIRMATION, user, user).save() Event(EventType.EMAIL_CONFIRMATION, user, user).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_EMAIL_FORGOT_PASSWORD = async (user: DbUser): Promise<DbEvent> => export const EVENT_EMAIL_FORGOT_PASSWORD = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.EMAIL_FORGOT_PASSWORD, user, { id: 0 } as DbUser).save() Event(EventType.EMAIL_FORGOT_PASSWORD, user, { id: 0 } as DbUser).save()

View File

@ -3,7 +3,8 @@ import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_TRANSACTION_LINK_CREATE = async ( export const EVENT_TRANSACTION_LINK_CREATE = async (
user: DbUser, user: DbUser,

View File

@ -2,7 +2,8 @@ import { Event as DbEvent } from '@entity/Event'
import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink' import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_TRANSACTION_LINK_DELETE = async ( export const EVENT_TRANSACTION_LINK_DELETE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_TRANSACTION_LINK_REDEEM = async ( export const EVENT_TRANSACTION_LINK_REDEEM = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Transaction as DbTransaction } from '@entity/Transaction'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_TRANSACTION_RECEIVE = async ( export const EVENT_TRANSACTION_RECEIVE = async (
user: DbUser, user: DbUser,

View File

@ -3,7 +3,8 @@ import { Transaction as DbTransaction } from '@entity/Transaction'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_TRANSACTION_SEND = async ( export const EVENT_TRANSACTION_SEND = async (
user: DbUser, user: DbUser,

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_USER_ACTIVATE_ACCOUNT = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_ACTIVATE_ACCOUNT = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_ACTIVATE_ACCOUNT, user, user).save() Event(EventType.USER_ACTIVATE_ACCOUNT, user, user).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_USER_INFO_UPDATE = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_INFO_UPDATE = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_INFO_UPDATE, user, user).save() Event(EventType.USER_INFO_UPDATE, user, user).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_USER_LOGIN = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_LOGIN = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_LOGIN, user, user).save() Event(EventType.USER_LOGIN, user, user).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_USER_LOGOUT = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_LOGOUT = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_LOGOUT, user, user).save() Event(EventType.USER_LOGOUT, user, user).save()

View File

@ -1,7 +1,8 @@
import { Event as DbEvent } from '@entity/Event' import { Event as DbEvent } from '@entity/Event'
import { User as DbUser } from '@entity/User' import { User as DbUser } from '@entity/User'
import { Event, EventType } from './Event' import { Event } from './Event'
import { EventType } from './EventType'
export const EVENT_USER_REGISTER = async (user: DbUser): Promise<DbEvent> => export const EVENT_USER_REGISTER = async (user: DbUser): Promise<DbEvent> =>
Event(EventType.USER_REGISTER, user, user).save() Event(EventType.USER_REGISTER, user, user).save()

View File

@ -34,37 +34,3 @@ export const Event = (
event.amount = amount event.amount = amount
return event return event
} }
export { EventType }
export { EVENT_ADMIN_CONTRIBUTION_CONFIRM } from './EVENT_ADMIN_CONTRIBUTION_CONFIRM'
export { EVENT_ADMIN_CONTRIBUTION_CREATE } from './EVENT_ADMIN_CONTRIBUTION_CREATE'
export { EVENT_ADMIN_CONTRIBUTION_DELETE } from './EVENT_ADMIN_CONTRIBUTION_DELETE'
export { EVENT_ADMIN_CONTRIBUTION_DENY } from './EVENT_ADMIN_CONTRIBUTION_DENY'
export { EVENT_ADMIN_CONTRIBUTION_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_UPDATE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_CREATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_CREATE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_DELETE } from './EVENT_ADMIN_CONTRIBUTION_LINK_DELETE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE'
export { EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE'
export { EVENT_ADMIN_USER_DELETE } from './EVENT_ADMIN_USER_DELETE'
export { EVENT_ADMIN_USER_UNDELETE } from './EVENT_ADMIN_USER_UNDELETE'
export { EVENT_ADMIN_USER_ROLE_SET } from './EVENT_ADMIN_USER_ROLE_SET'
export { EVENT_CONTRIBUTION_CREATE } from './EVENT_CONTRIBUTION_CREATE'
export { EVENT_CONTRIBUTION_DELETE } from './EVENT_CONTRIBUTION_DELETE'
export { EVENT_CONTRIBUTION_UPDATE } from './EVENT_CONTRIBUTION_UPDATE'
export { EVENT_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_CONTRIBUTION_MESSAGE_CREATE'
export { EVENT_CONTRIBUTION_LINK_REDEEM } from './EVENT_CONTRIBUTION_LINK_REDEEM'
export { EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION } from './EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION'
export { EVENT_EMAIL_ADMIN_CONFIRMATION } from './EVENT_EMAIL_ADMIN_CONFIRMATION'
export { EVENT_EMAIL_CONFIRMATION } from './EVENT_EMAIL_CONFIRMATION'
export { EVENT_EMAIL_FORGOT_PASSWORD } from './EVENT_EMAIL_FORGOT_PASSWORD'
export { EVENT_TRANSACTION_SEND } from './EVENT_TRANSACTION_SEND'
export { EVENT_TRANSACTION_RECEIVE } from './EVENT_TRANSACTION_RECEIVE'
export { EVENT_TRANSACTION_LINK_CREATE } from './EVENT_TRANSACTION_LINK_CREATE'
export { EVENT_TRANSACTION_LINK_DELETE } from './EVENT_TRANSACTION_LINK_DELETE'
export { EVENT_TRANSACTION_LINK_REDEEM } from './EVENT_TRANSACTION_LINK_REDEEM'
export { EVENT_USER_ACTIVATE_ACCOUNT } from './EVENT_USER_ACTIVATE_ACCOUNT'
export { EVENT_USER_INFO_UPDATE } from './EVENT_USER_INFO_UPDATE'
export { EVENT_USER_LOGIN } from './EVENT_USER_LOGIN'
export { EVENT_USER_LOGOUT } from './EVENT_USER_LOGOUT'
export { EVENT_USER_REGISTER } from './EVENT_USER_REGISTER'

View File

@ -0,0 +1,33 @@
export { EventType } from './EventType'
export { Event } from './Event'
export { EVENT_ADMIN_CONTRIBUTION_CONFIRM } from './EVENT_ADMIN_CONTRIBUTION_CONFIRM'
export { EVENT_ADMIN_CONTRIBUTION_CREATE } from './EVENT_ADMIN_CONTRIBUTION_CREATE'
export { EVENT_ADMIN_CONTRIBUTION_DELETE } from './EVENT_ADMIN_CONTRIBUTION_DELETE'
export { EVENT_ADMIN_CONTRIBUTION_DENY } from './EVENT_ADMIN_CONTRIBUTION_DENY'
export { EVENT_ADMIN_CONTRIBUTION_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_UPDATE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_CREATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_CREATE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_DELETE } from './EVENT_ADMIN_CONTRIBUTION_LINK_DELETE'
export { EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE'
export { EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE'
export { EVENT_ADMIN_USER_DELETE } from './EVENT_ADMIN_USER_DELETE'
export { EVENT_ADMIN_USER_UNDELETE } from './EVENT_ADMIN_USER_UNDELETE'
export { EVENT_ADMIN_USER_ROLE_SET } from './EVENT_ADMIN_USER_ROLE_SET'
export { EVENT_CONTRIBUTION_CREATE } from './EVENT_CONTRIBUTION_CREATE'
export { EVENT_CONTRIBUTION_DELETE } from './EVENT_CONTRIBUTION_DELETE'
export { EVENT_CONTRIBUTION_UPDATE } from './EVENT_CONTRIBUTION_UPDATE'
export { EVENT_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_CONTRIBUTION_MESSAGE_CREATE'
export { EVENT_CONTRIBUTION_LINK_REDEEM } from './EVENT_CONTRIBUTION_LINK_REDEEM'
export { EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION } from './EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION'
export { EVENT_EMAIL_ADMIN_CONFIRMATION } from './EVENT_EMAIL_ADMIN_CONFIRMATION'
export { EVENT_EMAIL_CONFIRMATION } from './EVENT_EMAIL_CONFIRMATION'
export { EVENT_EMAIL_FORGOT_PASSWORD } from './EVENT_EMAIL_FORGOT_PASSWORD'
export { EVENT_TRANSACTION_SEND } from './EVENT_TRANSACTION_SEND'
export { EVENT_TRANSACTION_RECEIVE } from './EVENT_TRANSACTION_RECEIVE'
export { EVENT_TRANSACTION_LINK_CREATE } from './EVENT_TRANSACTION_LINK_CREATE'
export { EVENT_TRANSACTION_LINK_DELETE } from './EVENT_TRANSACTION_LINK_DELETE'
export { EVENT_TRANSACTION_LINK_REDEEM } from './EVENT_TRANSACTION_LINK_REDEEM'
export { EVENT_USER_ACTIVATE_ACCOUNT } from './EVENT_USER_ACTIVATE_ACCOUNT'
export { EVENT_USER_INFO_UPDATE } from './EVENT_USER_INFO_UPDATE'
export { EVENT_USER_LOGIN } from './EVENT_USER_LOGIN'
export { EVENT_USER_LOGOUT } from './EVENT_USER_LOGOUT'
export { EVENT_USER_REGISTER } from './EVENT_USER_REGISTER'

View File

@ -5,7 +5,7 @@ import { Community as DbCommunity } from '@entity/Community'
import { gql } from 'graphql-request' import { gql } from 'graphql-request'
import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient' import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> { export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {

View File

@ -5,7 +5,7 @@ import { Community as DbCommunity } from '@entity/Community'
import { gql } from 'graphql-request' import { gql } from 'graphql-request'
import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient' import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> { export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {

View File

@ -1,7 +1,7 @@
import { IsNull } from '@dbTools/typeorm' import { IsNull } from '@dbTools/typeorm'
import { Community as DbCommunity } from '@entity/Community' import { Community as DbCommunity } from '@entity/Community'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase

View File

@ -3,7 +3,7 @@ import { ArgsType, Field, InputType } from 'type-graphql'
@InputType() @InputType()
@ArgsType() @ArgsType()
export default class AdminCreateContributionArgs { export class AdminCreateContributionArgs {
@Field(() => String) @Field(() => String)
email: string email: string

View File

@ -2,7 +2,7 @@ import { Decimal } from 'decimal.js-light'
import { ArgsType, Field, Int } from 'type-graphql' import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType() @ArgsType()
export default class AdminUpdateContributionArgs { export class AdminUpdateContributionArgs {
@Field(() => Int) @Field(() => Int)
id: number id: number

View File

@ -3,7 +3,7 @@ import { ArgsType, Field, InputType } from 'type-graphql'
@InputType() @InputType()
@ArgsType() @ArgsType()
export default class ContributionArgs { export class ContributionArgs {
@Field(() => Decimal) @Field(() => Decimal)
amount: Decimal amount: Decimal

View File

@ -2,7 +2,7 @@ import { Decimal } from 'decimal.js-light'
import { ArgsType, Field, Int } from 'type-graphql' import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType() @ArgsType()
export default class ContributionLinkArgs { export class ContributionLinkArgs {
@Field(() => Decimal) @Field(() => Decimal)
amount: Decimal amount: Decimal

View File

@ -2,7 +2,7 @@ import { ArgsType, Field, Int, InputType } from 'type-graphql'
@InputType() @InputType()
@ArgsType() @ArgsType()
export default class ContributionMessageArgs { export class ContributionMessageArgs {
@Field(() => Int) @Field(() => Int)
contributionId: number contributionId: number

View File

@ -1,7 +1,7 @@
import { ArgsType, Field, Int } from 'type-graphql' import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType() @ArgsType()
export default class CreateUserArgs { export class CreateUserArgs {
@Field(() => String) @Field(() => String)
email: string email: string

View File

@ -4,7 +4,7 @@ import { ArgsType, Field, Int } from 'type-graphql'
import { Order } from '@enum/Order' import { Order } from '@enum/Order'
@ArgsType() @ArgsType()
export default class Paginated { export class Paginated {
@Field(() => Int, { nullable: true }) @Field(() => Int, { nullable: true })
currentPage?: number currentPage?: number

View File

@ -1,9 +1,9 @@
import { ArgsType, Field, Int } from 'type-graphql' import { ArgsType, Field, Int } from 'type-graphql'
import SearchUsersFilters from '@arg/SearchUsersFilters' import { SearchUsersFilters } from '@arg/SearchUsersFilters'
@ArgsType() @ArgsType()
export default class SearchUsersArgs { export class SearchUsersArgs {
@Field(() => String) @Field(() => String)
searchText: string searchText: string

View File

@ -1,7 +1,7 @@
import { Field, InputType } from 'type-graphql' import { Field, InputType } from 'type-graphql'
@InputType() @InputType()
export default class SearchUsersFilters { export class SearchUsersFilters {
@Field(() => Boolean, { nullable: true, defaultValue: null }) @Field(() => Boolean, { nullable: true, defaultValue: null })
byActivated?: boolean | null byActivated?: boolean | null

View File

@ -2,7 +2,7 @@ import { Decimal } from 'decimal.js-light'
import { ArgsType, Field } from 'type-graphql' import { ArgsType, Field } from 'type-graphql'
@ArgsType() @ArgsType()
export default class TransactionLinkArgs { export class TransactionLinkArgs {
@Field(() => Decimal) @Field(() => Decimal)
amount: Decimal amount: Decimal

View File

@ -2,7 +2,7 @@
import { Field, InputType } from 'type-graphql' import { Field, InputType } from 'type-graphql'
@InputType() @InputType()
export default class TransactionLinkFilters { export class TransactionLinkFilters {
@Field(() => Boolean, { nullable: true }) @Field(() => Boolean, { nullable: true })
withDeleted?: boolean withDeleted?: boolean

View File

@ -2,7 +2,7 @@ import { Decimal } from 'decimal.js-light'
import { ArgsType, Field } from 'type-graphql' import { ArgsType, Field } from 'type-graphql'
@ArgsType() @ArgsType()
export default class TransactionSendArgs { export class TransactionSendArgs {
@Field(() => String) @Field(() => String)
identifier: string identifier: string

View File

@ -1,7 +1,7 @@
import { ArgsType, Field, Int } from 'type-graphql' import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType() @ArgsType()
export default class UnsecureLoginArgs { export class UnsecureLoginArgs {
@Field(() => String) @Field(() => String)
email: string email: string

View File

@ -1,7 +1,7 @@
import { ArgsType, Field, Int } from 'type-graphql' import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType() @ArgsType()
export default class UpdateUserInfosArgs { export class UpdateUserInfosArgs {
@Field({ nullable: true }) @Field({ nullable: true })
firstName?: string firstName?: string

View File

@ -10,9 +10,9 @@ import { INALIENABLE_RIGHTS } from '@/auth/INALIENABLE_RIGHTS'
import { decode, encode } from '@/auth/JWT' import { decode, encode } from '@/auth/JWT'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
import { ROLE_UNAUTHORIZED, ROLE_USER, ROLE_ADMIN } from '@/auth/ROLES' import { ROLE_UNAUTHORIZED, ROLE_USER, ROLE_ADMIN } from '@/auth/ROLES'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
const isAuthorized: AuthChecker<any> = async ({ context }, rights) => { export const isAuthorized: AuthChecker<any> = async ({ context }, rights) => {
context.role = ROLE_UNAUTHORIZED // unauthorized user context.role = ROLE_UNAUTHORIZED // unauthorized user
// is rights an inalienable right? // is rights an inalienable right?
@ -56,5 +56,3 @@ const isAuthorized: AuthChecker<any> = async ({ context }, rights) => {
context.setHeaders.push({ key: 'token', value: encode(decoded.gradidoID) }) context.setHeaders.push({ key: 'token', value: encode(decoded.gradidoID) })
return true return true
} }
export default isAuthorized

View File

@ -8,9 +8,7 @@ export class Community {
this.foreign = dbCom.foreign this.foreign = dbCom.foreign
this.publicKey = dbCom.publicKey.toString() this.publicKey = dbCom.publicKey.toString()
this.url = this.url =
(dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/') + (dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/') + dbCom.apiVersion
'api/' +
dbCom.apiVersion
this.lastAnnouncedAt = dbCom.lastAnnouncedAt this.lastAnnouncedAt = dbCom.lastAnnouncedAt
this.verifiedAt = dbCom.verifiedAt this.verifiedAt = dbCom.verifiedAt
this.lastErrorAt = dbCom.lastErrorAt this.lastErrorAt = dbCom.lastErrorAt

View File

@ -2,7 +2,7 @@ import { ContributionLink as dbContributionLink } from '@entity/ContributionLink
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql' import { ObjectType, Field, Int } from 'type-graphql'
import CONFIG from '@/config' import { CONFIG } from '@/config'
@ObjectType() @ObjectType()
export class ContributionLink { export class ContributionLink {

View File

@ -47,6 +47,10 @@ export class Transaction {
this.linkId = transaction.contribution this.linkId = transaction.contribution
? transaction.contribution.contributionLinkId ? transaction.contribution.contributionLinkId
: transaction.transactionLinkId || null : transaction.transactionLinkId || null
this.previousBalance =
(transaction.previousTransaction &&
transaction.previousTransaction.balance.toDecimalPlaces(2, Decimal.ROUND_DOWN)) ||
new Decimal(0)
} }
@Field(() => Int) @Field(() => Int)
@ -70,6 +74,9 @@ export class Transaction {
@Field(() => Date) @Field(() => Date)
balanceDate: Date balanceDate: Date
@Field(() => Decimal)
previousBalance: Decimal
@Field(() => Decay) @Field(() => Decay)
decay: Decay decay: Decay

View File

@ -2,7 +2,7 @@ import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { ObjectType, Field, Int } from 'type-graphql' import { ObjectType, Field, Int } from 'type-graphql'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { User } from './User' import { User } from './User'

View File

@ -36,6 +36,7 @@ describe('CommunityResolver', () => {
let foreignCom1: DbCommunity let foreignCom1: DbCommunity
let foreignCom2: DbCommunity let foreignCom2: DbCommunity
let foreignCom3: DbCommunity let foreignCom3: DbCommunity
describe('with empty list', () => { describe('with empty list', () => {
it('returns no community entry', async () => { it('returns no community entry', async () => {
// const result: Community[] = await query({ query: getCommunities }) // const result: Community[] = await query({ query: getCommunities })
@ -56,7 +57,7 @@ describe('CommunityResolver', () => {
homeCom1.foreign = false homeCom1.foreign = false
homeCom1.publicKey = Buffer.from('publicKey-HomeCommunity') homeCom1.publicKey = Buffer.from('publicKey-HomeCommunity')
homeCom1.apiVersion = '1_0' homeCom1.apiVersion = '1_0'
homeCom1.endPoint = 'http://localhost' homeCom1.endPoint = 'http://localhost/api'
homeCom1.createdAt = new Date() homeCom1.createdAt = new Date()
await DbCommunity.insert(homeCom1) await DbCommunity.insert(homeCom1)
@ -64,7 +65,7 @@ describe('CommunityResolver', () => {
homeCom2.foreign = false homeCom2.foreign = false
homeCom2.publicKey = Buffer.from('publicKey-HomeCommunity') homeCom2.publicKey = Buffer.from('publicKey-HomeCommunity')
homeCom2.apiVersion = '1_1' homeCom2.apiVersion = '1_1'
homeCom2.endPoint = 'http://localhost' homeCom2.endPoint = 'http://localhost/api'
homeCom2.createdAt = new Date() homeCom2.createdAt = new Date()
await DbCommunity.insert(homeCom2) await DbCommunity.insert(homeCom2)
@ -72,24 +73,24 @@ describe('CommunityResolver', () => {
homeCom3.foreign = false homeCom3.foreign = false
homeCom3.publicKey = Buffer.from('publicKey-HomeCommunity') homeCom3.publicKey = Buffer.from('publicKey-HomeCommunity')
homeCom3.apiVersion = '2_0' homeCom3.apiVersion = '2_0'
homeCom3.endPoint = 'http://localhost' homeCom3.endPoint = 'http://localhost/api'
homeCom3.createdAt = new Date() homeCom3.createdAt = new Date()
await DbCommunity.insert(homeCom3) await DbCommunity.insert(homeCom3)
}) })
it('returns three home-community entries', async () => { it('returns 3 home-community entries', async () => {
await expect(query({ query: getCommunities })).resolves.toMatchObject({ await expect(query({ query: getCommunities })).resolves.toMatchObject({
data: { data: {
getCommunities: [ getCommunities: [
{ {
id: 1, id: 3,
foreign: homeCom1.foreign, foreign: homeCom3.foreign,
publicKey: expect.stringMatching('publicKey-HomeCommunity'), publicKey: expect.stringMatching('publicKey-HomeCommunity'),
url: expect.stringMatching('http://localhost/api/1_0'), url: expect.stringMatching('http://localhost/api/2_0'),
lastAnnouncedAt: null, lastAnnouncedAt: null,
verifiedAt: null, verifiedAt: null,
lastErrorAt: null, lastErrorAt: null,
createdAt: homeCom1.createdAt.toISOString(), createdAt: homeCom3.createdAt.toISOString(),
updatedAt: null, updatedAt: null,
}, },
{ {
@ -104,14 +105,14 @@ describe('CommunityResolver', () => {
updatedAt: null, updatedAt: null,
}, },
{ {
id: 3, id: 1,
foreign: homeCom3.foreign, foreign: homeCom1.foreign,
publicKey: expect.stringMatching('publicKey-HomeCommunity'), publicKey: expect.stringMatching('publicKey-HomeCommunity'),
url: expect.stringMatching('http://localhost/api/2_0'), url: expect.stringMatching('http://localhost/api/1_0'),
lastAnnouncedAt: null, lastAnnouncedAt: null,
verifiedAt: null, verifiedAt: null,
lastErrorAt: null, lastErrorAt: null,
createdAt: homeCom3.createdAt.toISOString(), createdAt: homeCom1.createdAt.toISOString(),
updatedAt: null, updatedAt: null,
}, },
], ],
@ -128,7 +129,7 @@ describe('CommunityResolver', () => {
foreignCom1.foreign = true foreignCom1.foreign = true
foreignCom1.publicKey = Buffer.from('publicKey-ForeignCommunity') foreignCom1.publicKey = Buffer.from('publicKey-ForeignCommunity')
foreignCom1.apiVersion = '1_0' foreignCom1.apiVersion = '1_0'
foreignCom1.endPoint = 'http://remotehost' foreignCom1.endPoint = 'http://remotehost/api'
foreignCom1.createdAt = new Date() foreignCom1.createdAt = new Date()
await DbCommunity.insert(foreignCom1) await DbCommunity.insert(foreignCom1)
@ -136,7 +137,7 @@ describe('CommunityResolver', () => {
foreignCom2.foreign = true foreignCom2.foreign = true
foreignCom2.publicKey = Buffer.from('publicKey-ForeignCommunity') foreignCom2.publicKey = Buffer.from('publicKey-ForeignCommunity')
foreignCom2.apiVersion = '1_1' foreignCom2.apiVersion = '1_1'
foreignCom2.endPoint = 'http://remotehost' foreignCom2.endPoint = 'http://remotehost/api'
foreignCom2.createdAt = new Date() foreignCom2.createdAt = new Date()
await DbCommunity.insert(foreignCom2) await DbCommunity.insert(foreignCom2)
@ -144,24 +145,24 @@ describe('CommunityResolver', () => {
foreignCom3.foreign = true foreignCom3.foreign = true
foreignCom3.publicKey = Buffer.from('publicKey-ForeignCommunity') foreignCom3.publicKey = Buffer.from('publicKey-ForeignCommunity')
foreignCom3.apiVersion = '1_2' foreignCom3.apiVersion = '1_2'
foreignCom3.endPoint = 'http://remotehost' foreignCom3.endPoint = 'http://remotehost/api'
foreignCom3.createdAt = new Date() foreignCom3.createdAt = new Date()
await DbCommunity.insert(foreignCom3) await DbCommunity.insert(foreignCom3)
}) })
it('returns 3x home and 3x foreign-community entries', async () => { it('returns 3 home community and 3 foreign community entries', async () => {
await expect(query({ query: getCommunities })).resolves.toMatchObject({ await expect(query({ query: getCommunities })).resolves.toMatchObject({
data: { data: {
getCommunities: [ getCommunities: [
{ {
id: 1, id: 3,
foreign: homeCom1.foreign, foreign: homeCom3.foreign,
publicKey: expect.stringMatching('publicKey-HomeCommunity'), publicKey: expect.stringMatching('publicKey-HomeCommunity'),
url: expect.stringMatching('http://localhost/api/1_0'), url: expect.stringMatching('http://localhost/api/2_0'),
lastAnnouncedAt: null, lastAnnouncedAt: null,
verifiedAt: null, verifiedAt: null,
lastErrorAt: null, lastErrorAt: null,
createdAt: homeCom1.createdAt.toISOString(), createdAt: homeCom3.createdAt.toISOString(),
updatedAt: null, updatedAt: null,
}, },
{ {
@ -176,25 +177,25 @@ describe('CommunityResolver', () => {
updatedAt: null, updatedAt: null,
}, },
{ {
id: 3, id: 1,
foreign: homeCom3.foreign, foreign: homeCom1.foreign,
publicKey: expect.stringMatching('publicKey-HomeCommunity'), publicKey: expect.stringMatching('publicKey-HomeCommunity'),
url: expect.stringMatching('http://localhost/api/2_0'), url: expect.stringMatching('http://localhost/api/1_0'),
lastAnnouncedAt: null, lastAnnouncedAt: null,
verifiedAt: null, verifiedAt: null,
lastErrorAt: null, lastErrorAt: null,
createdAt: homeCom3.createdAt.toISOString(), createdAt: homeCom1.createdAt.toISOString(),
updatedAt: null, updatedAt: null,
}, },
{ {
id: 4, id: 6,
foreign: foreignCom1.foreign, foreign: foreignCom3.foreign,
publicKey: expect.stringMatching('publicKey-ForeignCommunity'), publicKey: expect.stringMatching('publicKey-ForeignCommunity'),
url: expect.stringMatching('http://remotehost/api/1_0'), url: expect.stringMatching('http://remotehost/api/1_2'),
lastAnnouncedAt: null, lastAnnouncedAt: null,
verifiedAt: null, verifiedAt: null,
lastErrorAt: null, lastErrorAt: null,
createdAt: foreignCom1.createdAt.toISOString(), createdAt: foreignCom3.createdAt.toISOString(),
updatedAt: null, updatedAt: null,
}, },
{ {
@ -209,14 +210,14 @@ describe('CommunityResolver', () => {
updatedAt: null, updatedAt: null,
}, },
{ {
id: 6, id: 4,
foreign: foreignCom3.foreign, foreign: foreignCom1.foreign,
publicKey: expect.stringMatching('publicKey-ForeignCommunity'), publicKey: expect.stringMatching('publicKey-ForeignCommunity'),
url: expect.stringMatching('http://remotehost/api/1_2'), url: expect.stringMatching('http://remotehost/api/1_0'),
lastAnnouncedAt: null, lastAnnouncedAt: null,
verifiedAt: null, verifiedAt: null,
lastErrorAt: null, lastErrorAt: null,
createdAt: foreignCom3.createdAt.toISOString(), createdAt: foreignCom1.createdAt.toISOString(),
updatedAt: null, updatedAt: null,
}, },
], ],

View File

@ -11,7 +11,11 @@ export class CommunityResolver {
@Query(() => [Community]) @Query(() => [Community])
async getCommunities(): Promise<Community[]> { async getCommunities(): Promise<Community[]> {
const dbCommunities: DbCommunity[] = await DbCommunity.find({ const dbCommunities: DbCommunity[] = await DbCommunity.find({
order: { foreign: 'ASC', publicKey: 'ASC', apiVersion: 'ASC' }, order: {
foreign: 'ASC',
createdAt: 'DESC',
lastAnnouncedAt: 'DESC',
},
}) })
return dbCommunities.map((dbCom: DbCommunity) => new Community(dbCom)) return dbCommunities.map((dbCom: DbCommunity) => new Community(dbCom))
} }

View File

@ -13,7 +13,7 @@ import { GraphQLError } from 'graphql'
import { cleanDB, testEnvironment, resetToken } from '@test/helpers' import { cleanDB, testEnvironment, resetToken } from '@test/helpers'
import { logger } from '@test/testSetup' import { logger } from '@test/testSetup'
import { EventType } from '@/event/Event' import { EventType } from '@/event/Events'
import { userFactory } from '@/seeds/factory/user' import { userFactory } from '@/seeds/factory/user'
import { import {
login, login,

View File

@ -3,9 +3,8 @@ import { ContributionLink as DbContributionLink } from '@entity/ContributionLink
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Resolver, Args, Arg, Authorized, Mutation, Query, Int, Ctx } from 'type-graphql' import { Resolver, Args, Arg, Authorized, Mutation, Query, Int, Ctx } from 'type-graphql'
// TODO: this is a strange construct import { ContributionLinkArgs } from '@arg/ContributionLinkArgs'
import ContributionLinkArgs from '@arg/ContributionLinkArgs' import { Paginated } from '@arg/Paginated'
import Paginated from '@arg/Paginated'
import { Order } from '@enum/Order' import { Order } from '@enum/Order'
import { ContributionLink } from '@model/ContributionLink' import { ContributionLink } from '@model/ContributionLink'
import { ContributionLinkList } from '@model/ContributionLinkList' import { ContributionLinkList } from '@model/ContributionLinkList'
@ -15,9 +14,9 @@ import {
EVENT_ADMIN_CONTRIBUTION_LINK_CREATE, EVENT_ADMIN_CONTRIBUTION_LINK_CREATE,
EVENT_ADMIN_CONTRIBUTION_LINK_DELETE, EVENT_ADMIN_CONTRIBUTION_LINK_DELETE,
EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE, EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE,
} from '@/event/Event' } from '@/event/Events'
import { Context, getUser } from '@/server/context' import { Context, getUser } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { import {
CONTRIBUTIONLINK_NAME_MAX_CHARS, CONTRIBUTIONLINK_NAME_MAX_CHARS,

View File

@ -13,7 +13,7 @@ import { cleanDB, resetToken, testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup' import { logger, i18n as localization } from '@test/testSetup'
import { sendAddedContributionMessageEmail } from '@/emails/sendEmailVariants' import { sendAddedContributionMessageEmail } from '@/emails/sendEmailVariants'
import { EventType } from '@/event/Event' import { EventType } from '@/event/Events'
import { userFactory } from '@/seeds/factory/user' import { userFactory } from '@/seeds/factory/user'
import { import {
adminCreateContributionMessage, adminCreateContributionMessage,

View File

@ -6,8 +6,8 @@ import { User as DbUser } from '@entity/User'
import { UserContact as DbUserContact } from '@entity/UserContact' import { UserContact as DbUserContact } from '@entity/UserContact'
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
import ContributionMessageArgs from '@arg/ContributionMessageArgs' import { ContributionMessageArgs } from '@arg/ContributionMessageArgs'
import Paginated from '@arg/Paginated' import { Paginated } from '@arg/Paginated'
import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionStatus } from '@enum/ContributionStatus'
import { ContributionMessageType } from '@enum/MessageType' import { ContributionMessageType } from '@enum/MessageType'
import { Order } from '@enum/Order' import { Order } from '@enum/Order'
@ -18,9 +18,9 @@ import { sendAddedContributionMessageEmail } from '@/emails/sendEmailVariants'
import { import {
EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE, EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE,
EVENT_CONTRIBUTION_MESSAGE_CREATE, EVENT_CONTRIBUTION_MESSAGE_CREATE,
} from '@/event/Event' } from '@/event/Events'
import { Context, getUser } from '@/server/context' import { Context, getUser } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
@Resolver() @Resolver()
export class ContributionMessageResolver { export class ContributionMessageResolver {

View File

@ -32,7 +32,7 @@ import {
sendContributionDeletedEmail, sendContributionDeletedEmail,
sendContributionDeniedEmail, sendContributionDeniedEmail,
} from '@/emails/sendEmailVariants' } from '@/emails/sendEmailVariants'
import { EventType } from '@/event/Event' import { EventType } from '@/event/Events'
import { creations } from '@/seeds/creation/index' import { creations } from '@/seeds/creation/index'
import { creationFactory } from '@/seeds/factory/creation' import { creationFactory } from '@/seeds/factory/creation'
import { userFactory } from '@/seeds/factory/user' import { userFactory } from '@/seeds/factory/user'

View File

@ -8,10 +8,10 @@ import { UserContact } from '@entity/UserContact'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql'
import AdminCreateContributionArgs from '@arg/AdminCreateContributionArgs' import { AdminCreateContributionArgs } from '@arg/AdminCreateContributionArgs'
import AdminUpdateContributionArgs from '@arg/AdminUpdateContributionArgs' import { AdminUpdateContributionArgs } from '@arg/AdminUpdateContributionArgs'
import ContributionArgs from '@arg/ContributionArgs' import { ContributionArgs } from '@arg/ContributionArgs'
import Paginated from '@arg/Paginated' import { Paginated } from '@arg/Paginated'
import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionStatus } from '@enum/ContributionStatus'
import { ContributionType } from '@enum/ContributionType' import { ContributionType } from '@enum/ContributionType'
import { ContributionMessageType } from '@enum/MessageType' import { ContributionMessageType } from '@enum/MessageType'
@ -38,9 +38,9 @@ import {
EVENT_ADMIN_CONTRIBUTION_DELETE, EVENT_ADMIN_CONTRIBUTION_DELETE,
EVENT_ADMIN_CONTRIBUTION_CONFIRM, EVENT_ADMIN_CONTRIBUTION_CONFIRM,
EVENT_ADMIN_CONTRIBUTION_DENY, EVENT_ADMIN_CONTRIBUTION_DENY,
} from '@/event/Event' } from '@/event/Events'
import { Context, getUser, getClientTimezoneOffset } from '@/server/context' import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
import { calculateDecay } from '@/util/decay' import { calculateDecay } from '@/util/decay'
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'

View File

@ -9,7 +9,7 @@ import { GraphQLError } from 'graphql'
import { testEnvironment, cleanDB } from '@test/helpers' import { testEnvironment, cleanDB } from '@test/helpers'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { createUser, setPassword, forgotPassword } from '@/seeds/graphql/mutations' import { createUser, setPassword, forgotPassword } from '@/seeds/graphql/mutations'
import { queryOptIn } from '@/seeds/graphql/queries' import { queryOptIn } from '@/seeds/graphql/queries'

View File

@ -4,15 +4,15 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-argument */
import { Resolver, Query, Args, Ctx, Authorized, Arg, Int, Float } from 'type-graphql' import { Resolver, Query, Args, Ctx, Authorized, Arg, Int, Float } from 'type-graphql'
import Paginated from '@arg/Paginated' import { Paginated } from '@arg/Paginated'
import { Order } from '@enum/Order' import { Order } from '@enum/Order'
import { GdtEntryList } from '@model/GdtEntryList' import { GdtEntryList } from '@model/GdtEntryList'
import { apiGet, apiPost } from '@/apis/HttpRequest' import { apiGet, apiPost } from '@/apis/HttpRequest'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { Context, getUser } from '@/server/context' import { Context, getUser } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
@Resolver() @Resolver()
export class GdtResolver { export class GdtResolver {

View File

@ -18,7 +18,7 @@ import { UnconfirmedContribution } from '@model/UnconfirmedContribution'
import { cleanDB, testEnvironment, resetToken, resetEntity } from '@test/helpers' import { cleanDB, testEnvironment, resetToken, resetEntity } from '@test/helpers'
import { logger } from '@test/testSetup' import { logger } from '@test/testSetup'
import { EventType } from '@/event/Event' import { EventType } from '@/event/Events'
import { creations } from '@/seeds/creation/index' import { creations } from '@/seeds/creation/index'
import { creationFactory } from '@/seeds/factory/creation' import { creationFactory } from '@/seeds/factory/creation'
import { transactionLinkFactory } from '@/seeds/factory/transactionLink' import { transactionLinkFactory } from '@/seeds/factory/transactionLink'

View File

@ -9,9 +9,9 @@ import { User as DbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Resolver, Args, Arg, Authorized, Ctx, Mutation, Query, Int } from 'type-graphql' import { Resolver, Args, Arg, Authorized, Ctx, Mutation, Query, Int } from 'type-graphql'
import Paginated from '@arg/Paginated' import { Paginated } from '@arg/Paginated'
import TransactionLinkArgs from '@arg/TransactionLinkArgs' import { TransactionLinkArgs } from '@arg/TransactionLinkArgs'
import TransactionLinkFilters from '@arg/TransactionLinkFilters' import { TransactionLinkFilters } from '@arg/TransactionLinkFilters'
import { ContributionCycleType } from '@enum/ContributionCycleType' import { ContributionCycleType } from '@enum/ContributionCycleType'
import { ContributionStatus } from '@enum/ContributionStatus' import { ContributionStatus } from '@enum/ContributionStatus'
import { ContributionType } from '@enum/ContributionType' import { ContributionType } from '@enum/ContributionType'
@ -20,7 +20,7 @@ import { ContributionLink } from '@model/ContributionLink'
import { Decay } from '@model/Decay' import { Decay } from '@model/Decay'
import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink' import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink'
import { User } from '@model/User' import { User } from '@model/User'
import QueryLinkResult from '@union/QueryLinkResult' import { QueryLinkResult } from '@union/QueryLinkResult'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
import { import {
@ -28,9 +28,9 @@ import {
EVENT_TRANSACTION_LINK_CREATE, EVENT_TRANSACTION_LINK_CREATE,
EVENT_TRANSACTION_LINK_DELETE, EVENT_TRANSACTION_LINK_DELETE,
EVENT_TRANSACTION_LINK_REDEEM, EVENT_TRANSACTION_LINK_REDEEM,
} from '@/event/Event' } from '@/event/Events'
import { Context, getUser, getClientTimezoneOffset } from '@/server/context' import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
import { calculateDecay } from '@/util/decay' import { calculateDecay } from '@/util/decay'
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
@ -39,7 +39,7 @@ import { calculateBalance } from '@/util/validate'
import { executeTransaction } from './TransactionResolver' import { executeTransaction } from './TransactionResolver'
import { getUserCreation, validateContribution } from './util/creations' import { getUserCreation, validateContribution } from './util/creations'
import { getLastTransaction } from './util/getLastTransaction' import { getLastTransaction } from './util/getLastTransaction'
import transactionLinkList from './util/transactionLinkList' import { transactionLinkList } from './util/transactionLinkList'
// TODO: do not export, test it inside the resolver // TODO: do not export, test it inside the resolver
export const transactionLinkCode = (date: Date): string => { export const transactionLinkCode = (date: Date): string => {

View File

@ -14,7 +14,7 @@ import { GraphQLError } from 'graphql'
import { cleanDB, testEnvironment } from '@test/helpers' import { cleanDB, testEnvironment } from '@test/helpers'
import { logger } from '@test/testSetup' import { logger } from '@test/testSetup'
import { EventType } from '@/event/Event' import { EventType } from '@/event/Events'
import { userFactory } from '@/seeds/factory/user' import { userFactory } from '@/seeds/factory/user'
import { import {
confirmContribution, confirmContribution,

View File

@ -9,14 +9,13 @@ import { User as dbUser } from '@entity/User'
import { Decimal } from 'decimal.js-light' import { Decimal } from 'decimal.js-light'
import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql' import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql'
import Paginated from '@arg/Paginated' import { Paginated } from '@arg/Paginated'
import TransactionSendArgs from '@arg/TransactionSendArgs' import { TransactionSendArgs } from '@arg/TransactionSendArgs'
import { Order } from '@enum/Order' import { Order } from '@enum/Order'
import { TransactionTypeId } from '@enum/TransactionTypeId' import { TransactionTypeId } from '@enum/TransactionTypeId'
import { Transaction } from '@model/Transaction' import { Transaction } from '@model/Transaction'
import { TransactionList } from '@model/TransactionList' import { TransactionList } from '@model/TransactionList'
import { User } from '@model/User' import { User } from '@model/User'
import { TransactionRepository } from '@repository/Transaction'
import { TransactionLinkRepository } from '@repository/TransactionLink' import { TransactionLinkRepository } from '@repository/TransactionLink'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
@ -24,9 +23,9 @@ import {
sendTransactionLinkRedeemedEmail, sendTransactionLinkRedeemedEmail,
sendTransactionReceivedEmail, sendTransactionReceivedEmail,
} from '@/emails/sendEmailVariants' } from '@/emails/sendEmailVariants'
import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Event' import { EVENT_TRANSACTION_RECEIVE, EVENT_TRANSACTION_SEND } from '@/event/Events'
import { Context, getUser } from '@/server/context' import { Context, getUser } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
import { communityUser } from '@/util/communityUser' import { communityUser } from '@/util/communityUser'
import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK' import { TRANSACTIONS_LOCK } from '@/util/TRANSACTIONS_LOCK'
@ -37,6 +36,7 @@ import { BalanceResolver } from './BalanceResolver'
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const' import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
import { findUserByIdentifier } from './util/findUserByIdentifier' import { findUserByIdentifier } from './util/findUserByIdentifier'
import { getLastTransaction } from './util/getLastTransaction' import { getLastTransaction } from './util/getLastTransaction'
import { getTransactionList } from './util/getTransactionList'
export const executeTransaction = async ( export const executeTransaction = async (
amount: Decimal, amount: Decimal,
@ -209,8 +209,7 @@ export class TransactionResolver {
// find transactions // find transactions
// first page can contain 26 due to virtual decay transaction // first page can contain 26 due to virtual decay transaction
const offset = (currentPage - 1) * pageSize const offset = (currentPage - 1) * pageSize
const transactionRepository = getCustomRepository(TransactionRepository) const [userTransactions, userTransactionsCount] = await getTransactionList(
const [userTransactions, userTransactionsCount] = await transactionRepository.findByUserPaged(
user.id, user.id,
pageSize, pageSize,
offset, offset,
@ -275,6 +274,7 @@ export class TransactionResolver {
firstDate || now, firstDate || now,
lastDate || now, lastDate || now,
self, self,
(userTransactions.length && userTransactions[0].balance) || new Decimal(0),
), ),
) )
logger.debug(`transactions=${transactions}`) logger.debug(`transactions=${transactions}`)
@ -282,7 +282,7 @@ export class TransactionResolver {
} }
// transactions // transactions
userTransactions.forEach((userTransaction) => { userTransactions.forEach((userTransaction: dbTransaction) => {
const linkedUser = const linkedUser =
userTransaction.typeId === TransactionTypeId.CREATION userTransaction.typeId === TransactionTypeId.CREATION
? communityUser ? communityUser
@ -291,6 +291,15 @@ export class TransactionResolver {
}) })
logger.debug(`TransactionTypeId.CREATION: transactions=${transactions}`) logger.debug(`TransactionTypeId.CREATION: transactions=${transactions}`)
transactions.forEach((transaction: Transaction) => {
if (transaction.typeId !== TransactionTypeId.DECAY) {
const { balance, previousBalance, amount } = transaction
transaction.decay.decay = new Decimal(
Number(balance) - Number(amount) - Number(previousBalance),
).toDecimalPlaces(2, Decimal.ROUND_HALF_UP)
}
})
// Construct Result // Construct Result
return new TransactionList(await balanceResolver.balance(context), transactions) return new TransactionList(await balanceResolver.balance(context), transactions)
} }

View File

@ -20,13 +20,13 @@ import { ContributionLink } from '@model/ContributionLink'
import { testEnvironment, headerPushMock, resetToken, cleanDB } from '@test/helpers' import { testEnvironment, headerPushMock, resetToken, cleanDB } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup' import { logger, i18n as localization } from '@test/testSetup'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { import {
sendAccountActivationEmail, sendAccountActivationEmail,
sendAccountMultiRegistrationEmail, sendAccountMultiRegistrationEmail,
sendResetPasswordEmail, sendResetPasswordEmail,
} from '@/emails/sendEmailVariants' } from '@/emails/sendEmailVariants'
import { EventType } from '@/event/Event' import { EventType } from '@/event/Events'
import { SecretKeyCryptographyCreateKey } from '@/password/EncryptorUtils' import { SecretKeyCryptographyCreateKey } from '@/password/EncryptorUtils'
import { encryptPassword } from '@/password/PasswordEncryptor' import { encryptPassword } from '@/password/PasswordEncryptor'
import { contributionLinkFactory } from '@/seeds/factory/contributionLink' import { contributionLinkFactory } from '@/seeds/factory/contributionLink'

View File

@ -21,11 +21,11 @@ import {
} from 'type-graphql' } from 'type-graphql'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import CreateUserArgs from '@arg/CreateUserArgs' import { CreateUserArgs } from '@arg/CreateUserArgs'
import Paginated from '@arg/Paginated' import { Paginated } from '@arg/Paginated'
import SearchUsersArgs from '@arg/SearchUsersArgs' import { SearchUsersArgs } from '@arg/SearchUsersArgs'
import UnsecureLoginArgs from '@arg/UnsecureLoginArgs' import { UnsecureLoginArgs } from '@arg/UnsecureLoginArgs'
import UpdateUserInfosArgs from '@arg/UpdateUserInfosArgs' import { UpdateUserInfosArgs } from '@arg/UpdateUserInfosArgs'
import { OptInType } from '@enum/OptInType' import { OptInType } from '@enum/OptInType'
import { Order } from '@enum/Order' import { Order } from '@enum/Order'
import { PasswordEncryptionType } from '@enum/PasswordEncryptionType' import { PasswordEncryptionType } from '@enum/PasswordEncryptionType'
@ -38,7 +38,7 @@ import { UserRepository } from '@repository/User'
import { klicktippSignIn } from '@/apis/KlicktippController' import { klicktippSignIn } from '@/apis/KlicktippController'
import { encode } from '@/auth/JWT' import { encode } from '@/auth/JWT'
import { RIGHTS } from '@/auth/RIGHTS' import { RIGHTS } from '@/auth/RIGHTS'
import CONFIG from '@/config' import { CONFIG } from '@/config'
import { import {
sendAccountActivationEmail, sendAccountActivationEmail,
sendAccountMultiRegistrationEmail, sendAccountMultiRegistrationEmail,
@ -59,12 +59,12 @@ import {
EVENT_ADMIN_USER_ROLE_SET, EVENT_ADMIN_USER_ROLE_SET,
EVENT_ADMIN_USER_DELETE, EVENT_ADMIN_USER_DELETE,
EVENT_ADMIN_USER_UNDELETE, EVENT_ADMIN_USER_UNDELETE,
} from '@/event/Event' } from '@/event/Events'
import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddleware' import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddleware'
import { isValidPassword } from '@/password/EncryptorUtils' import { isValidPassword } from '@/password/EncryptorUtils'
import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor' import { encryptPassword, verifyPassword } from '@/password/PasswordEncryptor'
import { Context, getUser, getClientTimezoneOffset } from '@/server/context' import { Context, getUser, getClientTimezoneOffset } from '@/server/context'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
import { communityDbUser } from '@/util/communityUser' import { communityDbUser } from '@/util/communityUser'
import { hasElopageBuys } from '@/util/hasElopageBuys' import { hasElopageBuys } from '@/util/hasElopageBuys'

View File

@ -8,7 +8,7 @@ import { Decimal } from 'decimal.js-light'
import { OpenCreation } from '@model/OpenCreation' import { OpenCreation } from '@model/OpenCreation'
import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '@/graphql/resolver/const/const' import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '@/graphql/resolver/const/const'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
interface CreationMap { interface CreationMap {

View File

@ -2,7 +2,7 @@ import { User as DbUser } from '@entity/User'
import { UserContact as DbUserContact } from '@entity/UserContact' import { UserContact as DbUserContact } from '@entity/UserContact'
import { validate, version } from 'uuid' import { validate, version } from 'uuid'
import LogError from '@/server/LogError' import { LogError } from '@/server/LogError'
export const findUserByIdentifier = async (identifier: string): Promise<DbUser> => { export const findUserByIdentifier = async (identifier: string): Promise<DbUser> => {
let user: DbUser | undefined let user: DbUser | undefined

View File

@ -0,0 +1,20 @@
import { Transaction as DbTransaction } from '@entity/Transaction'
import { Order } from '@enum/Order'
export const getTransactionList = async (
userId: number,
limit: number,
offset: number,
order: Order,
): Promise<[DbTransaction[], number]> => {
return DbTransaction.findAndCount({
where: {
userId,
},
order: { balanceDate: order, id: order },
relations: ['previousTransaction'],
skip: offset,
take: limit,
})
}

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