From 41d6e8215cd836fbe61b94479732b177b9b31451 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 15 May 2024 13:20:51 +0200 Subject: [PATCH 001/166] beta releae --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ admin/package.json | 2 +- backend/package.json | 2 +- database/package.json | 2 +- dht-node/package.json | 2 +- dlt-connector/package.json | 2 +- federation/package.json | 2 +- frontend/package.json | 2 +- package.json | 2 +- 9 files changed, 38 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b05bd3e70..72f37afd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,39 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [2.3.0](https://github.com/gradido/gradido/compare/2.2.1...2.3.0) + +- feat(frontend): conditional services menu entries [`#3314`](https://github.com/gradido/gradido/pull/3314) +- feat(frontend): update news [`#3313`](https://github.com/gradido/gradido/pull/3313) +- feat(frontend): auto-login link for humhub [`#3311`](https://github.com/gradido/gradido/pull/3311) +- feat(frontend): remove gdt menu entry [`#3312`](https://github.com/gradido/gradido/pull/3312) +- feat(backend): sync user change with humhub [`#3310`](https://github.com/gradido/gradido/pull/3310) +- feat(backend): humhub export user function [`#3308`](https://github.com/gradido/gradido/pull/3308) +- feat(frontend): add humhub switch and name format [`#3309`](https://github.com/gradido/gradido/pull/3309) +- feat(frontend): gms - new menu item userplayground [`#3307`](https://github.com/gradido/gradido/pull/3307) +- feat(backend): gms user-search - backend authentication-handshake [`#3306`](https://github.com/gradido/gradido/pull/3306) + #### [2.2.1](https://github.com/gradido/gradido/compare/2.2.0...2.2.1) +> 2 April 2024 + +- fix(other): v2.2.1 merge with master [`#3296`](https://github.com/gradido/gradido/pull/3296) +- feat(backend): 3287 feature gms user update after change user settings [`#3291`](https://github.com/gradido/gradido/pull/3291) +- docs(backend): 3302 docu usecase - user search [`#3303`](https://github.com/gradido/gradido/pull/3303) +- fix(backend): prevent updating alias backend-side [`#3300`](https://github.com/gradido/gradido/pull/3300) +- fix(other): add GMS_ACTIVE and GMS_URL to deploy .env.dist [`#3301`](https://github.com/gradido/gradido/pull/3301) +- feat(frontend): update gms user settings [`#3297`](https://github.com/gradido/gradido/pull/3297) +- feat(admin): admin update community list [`#3271`](https://github.com/gradido/gradido/pull/3271) +- refactor(backend): refactor community and add to dlt-connector [`#3289`](https://github.com/gradido/gradido/pull/3289) +- feat(frontend): serve frontend and admin static [`#3278`](https://github.com/gradido/gradido/pull/3278) +- build(other): add config for nvm [`#3292`](https://github.com/gradido/gradido/pull/3292) +- feat(dlt): transmit to iota [`#3275`](https://github.com/gradido/gradido/pull/3275) - fix(other): deployment bugfixes [`#3290`](https://github.com/gradido/gradido/pull/3290) +- fix(backend): prevent running validate communities continuous [`#3288`](https://github.com/gradido/gradido/pull/3288) +- feat(workflow): add videos to deployment readme [`#3286`](https://github.com/gradido/gradido/pull/3286) +- feat(backend): 3263 feature gms publish user backend update user settings [`#3281`](https://github.com/gradido/gradido/pull/3281) +- feat(backend): gms publish user backend gradido communities dialog [`#3265`](https://github.com/gradido/gradido/pull/3265) +- feat(backend): 3237 feature connect gms api with a new rest client [`#3256`](https://github.com/gradido/gradido/pull/3256) #### [2.2.0](https://github.com/gradido/gradido/compare/2.1.1...2.2.0) diff --git a/admin/package.json b/admin/package.json index 97d4f6fda..db87f59e9 100644 --- a/admin/package.json +++ b/admin/package.json @@ -3,7 +3,7 @@ "description": "Administraion Interface for Gradido", "main": "index.js", "author": "Moriz Wahl", - "version": "2.2.1", + "version": "2.3.0", "license": "Apache-2.0", "private": false, "scripts": { diff --git a/backend/package.json b/backend/package.json index 7e70b7b8c..bef3fd560 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "gradido-backend", - "version": "2.2.1", + "version": "2.3.0", "description": "Gradido unified backend providing an API-Service for Gradido Transactions", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/backend", diff --git a/database/package.json b/database/package.json index c0f7496f0..e445fe15b 100644 --- a/database/package.json +++ b/database/package.json @@ -1,6 +1,6 @@ { "name": "gradido-database", - "version": "2.2.1", + "version": "2.3.0", "description": "Gradido Database Tool to execute database migrations", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/database", diff --git a/dht-node/package.json b/dht-node/package.json index a4859e394..620a77ee9 100644 --- a/dht-node/package.json +++ b/dht-node/package.json @@ -1,6 +1,6 @@ { "name": "gradido-dht-node", - "version": "2.2.1", + "version": "2.3.0", "description": "Gradido dht-node module", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/", diff --git a/dlt-connector/package.json b/dlt-connector/package.json index 30cd4b33b..4923d6408 100644 --- a/dlt-connector/package.json +++ b/dlt-connector/package.json @@ -1,6 +1,6 @@ { "name": "gradido-dlt-connector", - "version": "2.2.1", + "version": "2.3.0", "description": "Gradido DLT-Connector", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/", diff --git a/federation/package.json b/federation/package.json index 9a74201ab..5a945f963 100644 --- a/federation/package.json +++ b/federation/package.json @@ -1,6 +1,6 @@ { "name": "gradido-federation", - "version": "2.2.1", + "version": "2.3.0", "description": "Gradido federation module providing Gradido-Hub-Federation and versioned API for inter community communication", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/federation", diff --git a/frontend/package.json b/frontend/package.json index 4dd840261..e803a004a 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "bootstrap-vue-gradido-wallet", - "version": "2.2.1", + "version": "2.3.0", "private": true, "scripts": { "start": "node run/server.js", diff --git a/package.json b/package.json index 8ed31de63..de62f441d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gradido", - "version": "2.2.1", + "version": "2.3.0", "description": "Gradido", "main": "index.js", "repository": "git@github.com:gradido/gradido.git", From 04a536205141e2460001f1ee9f55301de5012d13 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Thu, 30 May 2024 15:23:44 +0200 Subject: [PATCH 002/166] remove automatically logged out message --- frontend/src/components/SessionLogoutTimeout.vue | 2 -- frontend/src/locales/de.json | 1 - frontend/src/locales/en.json | 1 - 3 files changed, 4 deletions(-) diff --git a/frontend/src/components/SessionLogoutTimeout.vue b/frontend/src/components/SessionLogoutTimeout.vue index 7a11d1d83..1ebff752a 100644 --- a/frontend/src/components/SessionLogoutTimeout.vue +++ b/frontend/src/components/SessionLogoutTimeout.vue @@ -67,7 +67,6 @@ export default { } if (this.tokenExpiresInSeconds === 0) { this.$timer.stop('tokenExpires') - this.toastInfoNoHide(this.$t('session.automaticallyLoggedOut')) this.$emit('logout') } }, @@ -85,7 +84,6 @@ export default { }) .catch(() => { this.$timer.stop('tokenExpires') - this.toastInfoNoHide(this.$t('session.automaticallyLoggedOut')) this.$emit('logout') }) }, diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 661a4f8e4..5e5ca3225 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -299,7 +299,6 @@ "send_gdd": "GDD versenden", "send_per_link": "GDD versenden per Link", "session": { - "automaticallyLoggedOut": "Du wurdest automatisch abgemeldet", "extend": "Angemeldet bleiben", "lightText": "Wenn du länger als 10 Minuten keine Aktion getätigt hast, wirst du aus Sicherheitsgründen abgemeldet.", "logoutIn": "Abmelden in ", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 527ec3ddf..6a43b8fec 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -299,7 +299,6 @@ "send_gdd": "Send GDD", "send_per_link": "Send GDD via Link", "session": { - "automaticallyLoggedOut": "You have been automatically logged out.", "extend": "Stay logged in", "lightText": "If you have not performed any action for more than 10 minutes, you will be logged out for security reasons.", "logoutIn": "Log out in ", From af24b0ef057b0316754e4e8a35a6654b9f0fd883 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Thu, 30 May 2024 16:47:58 +0200 Subject: [PATCH 003/166] gradido_address link always gradido_id, static auto login humhub link --- backend/src/apis/humhub/HumHubClient.ts | 2 +- backend/src/apis/humhub/model/Profile.ts | 6 +----- backend/src/graphql/resolver/UserResolver.ts | 9 +++++++-- frontend/src/pages/Circles.vue | 10 +++++++--- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/backend/src/apis/humhub/HumHubClient.ts b/backend/src/apis/humhub/HumHubClient.ts index 42fe598c2..d2ccf8ec5 100644 --- a/backend/src/apis/humhub/HumHubClient.ts +++ b/backend/src/apis/humhub/HumHubClient.ts @@ -65,7 +65,7 @@ export class HumHubClient { const token = await new SignJWT({ username }) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() - .setExpirationTime('2m') + .setExpirationTime(CONFIG.JWT_EXPIRES_IN) .sign(secret) return `${CONFIG.HUMHUB_API_URL}user/auth/external?authclient=jwt&jwt=${token}` diff --git a/backend/src/apis/humhub/model/Profile.ts b/backend/src/apis/humhub/model/Profile.ts index 424c48026..336e8cb80 100644 --- a/backend/src/apis/humhub/model/Profile.ts +++ b/backend/src/apis/humhub/model/Profile.ts @@ -10,11 +10,7 @@ export class Profile { const publishNameLogic = new PublishNameLogic(user) this.firstname = publishNameLogic.getFirstName(user.humhubPublishName as PublishNameType) this.lastname = publishNameLogic.getLastName(user.humhubPublishName as PublishNameType) - if (user.alias && user.alias.length > 2) { - this.gradido_address = CONFIG.COMMUNITY_NAME + '/' + user.alias - } else { - this.gradido_address = CONFIG.COMMUNITY_NAME + '/' + user.gradidoID - } + this.gradido_address = CONFIG.COMMUNITY_NAME + '/' + user.gradidoID } firstname: string diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 352f7ffc9..3abb745e8 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -203,8 +203,13 @@ export class UserResolver { await EVENT_USER_LOGIN(dbUser) // load humhub state if (humhubUserPromise) { - const result = await humhubUserPromise - user.humhubAllowed = result?.result?.account.status === 1 + try { + const result = await humhubUserPromise + user.humhubAllowed = result?.result?.account.status === 1 + } catch (e) { + logger.error("couldn't reach out to humhub, disable for now", e) + user.humhubAllowed = false + } } user.klickTipp = await klicktippStatePromise logger.info(`successful Login: ${JSON.stringify(user, null, 2)}`) diff --git a/frontend/src/pages/Circles.vue b/frontend/src/pages/Circles.vue index ab91b9fe2..e0502ff9a 100644 --- a/frontend/src/pages/Circles.vue +++ b/frontend/src/pages/Circles.vue @@ -12,10 +12,10 @@
{{ $t('circles.button') }} @@ -37,7 +37,8 @@ export default { name: 'Circles', data() { return { - enableButton: true, + enableButton: false, + humhubUri: '', } }, computed: { @@ -55,7 +56,7 @@ export default { fetchPolicy: 'network-only', }) .then(async (result) => { - window.open(result.data.authenticateHumhubAutoLogin, '_blank') + this.humhubUri = result.data.authenticateHumhubAutoLogin this.enableButton = true }) .catch(() => { @@ -67,5 +68,8 @@ export default { }) }, }, + created() { + this.authenticateHumhubAutoLogin() + }, } From f36eb85411dfdbad86693085dbc9324fc17abc16 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 31 May 2024 16:50:14 +0200 Subject: [PATCH 004/166] add test for circles --- frontend/src/pages/Circles.spec.js | 84 ++++++++++++++++++++++++++++++ frontend/src/pages/Circles.vue | 3 +- 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 frontend/src/pages/Circles.spec.js diff --git a/frontend/src/pages/Circles.spec.js b/frontend/src/pages/Circles.spec.js new file mode 100644 index 000000000..39a4e0f02 --- /dev/null +++ b/frontend/src/pages/Circles.spec.js @@ -0,0 +1,84 @@ +import { mount } from '@vue/test-utils' +import Circles from './Circles' +import { authenticateHumhubAutoLogin } from '@/graphql/queries' + +const localVue = global.localVue + +const TEST_URL_WITH_JWT_TOKEN = + 'https://community.gradido.net/user/auth/external?authclient=jwt&jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTY4NTI0NjQxMn0.V2h4Rf3LfdOYDsx2clVCx-jbhKoY5F4Ks5-YJGVtHRk' + +const apolloQueryMock = jest.fn().mockResolvedValue({ + data: { + authenticateHumhubAutoLogin: TEST_URL_WITH_JWT_TOKEN, + }, +}) + +describe('Circles', () => { + let wrapper + + const mocks = { + $t: jest.fn((t) => t), + $n: jest.fn(), + $i18n: { + locale: 'en', + }, + $apollo: { + query: apolloQueryMock, + }, + $store: { + state: { + humhubAllowed: true, + }, + commit: jest.fn(), + }, + } + + const Wrapper = () => { + return mount(Circles, { + localVue, + mocks, + }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders the circles page', () => { + expect(wrapper.find('div.circles').exists()).toBeTruthy() + }) + + it('calls authenticateHumhubAutoLogin', () => { + expect(apolloQueryMock).toBeCalledWith( + expect.objectContaining({ + query: authenticateHumhubAutoLogin, + fetchPolicy: 'network-only', + }), + ) + }) + + it('sets humhubUri and enables button on success', async () => { + await wrapper.vm.$nextTick() + expect(wrapper.vm.humhubUri).toBe(TEST_URL_WITH_JWT_TOKEN) + expect(wrapper.vm.enableButton).toBe(true) + }) + + describe('error apolloQueryMock', () => { + beforeEach(async () => { + jest.clearAllMocks() + apolloQueryMock.mockRejectedValue({ + message: 'uups', + }) + wrapper = Wrapper() + await wrapper.vm.$nextTick() + }) + + it('toasts an error message and disables humhub', () => { + expect(wrapper.vm.enableButton).toBe(true) + expect(wrapper.vm.humhubUri).toBe('') + expect(mocks.$store.commit).toBeCalledWith('humhubAllowed', false) + }) + }) + }) +}) diff --git a/frontend/src/pages/Circles.vue b/frontend/src/pages/Circles.vue index e0502ff9a..77e556bd7 100644 --- a/frontend/src/pages/Circles.vue +++ b/frontend/src/pages/Circles.vue @@ -60,11 +60,10 @@ export default { this.enableButton = true }) .catch(() => { - // this.toastError('authenticateHumhubAutoLogin failed!') this.enableButton = true + this.humhubUri = '' // something went wrong with login link so we disable humhub this.$store.commit('humhubAllowed', false) - this.$router.push('/settings/extern') }) }, }, From baca224a2aec890bd1e41febc9a207efec95148c Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Fri, 31 May 2024 18:49:41 +0200 Subject: [PATCH 005/166] fix test which will only fail at 31. of month, or 30.05 --- .../resolver/ContributionResolver.test.ts | 7 ++- .../graphql/resolver/util/creations.test.ts | 47 ++++++++++++++++++- .../src/graphql/resolver/util/creations.ts | 5 +- backend/src/util/utilities.ts | 19 ++++++++ 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index a188c5d2c..9317b76e7 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -56,6 +56,7 @@ import { garrickOllivander } from '@/seeds/users/garrick-ollivander' import { peterLustig } from '@/seeds/users/peter-lustig' import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz' import { stephenHawking } from '@/seeds/users/stephen-hawking' +import { getFirstDayOfPreviousNMonth } from '@/util/utilities' jest.mock('@/emails/sendEmailVariants') @@ -290,8 +291,7 @@ describe('ContributionResolver', () => { it('throws error when creationDate 3 month behind', async () => { jest.clearAllMocks() - const date = new Date() - date.setMonth(date.getMonth() - 3) + const date = getFirstDayOfPreviousNMonth(new Date(), 3) const { errors: errorObjects } = await mutate({ mutation: createContribution, variables: { @@ -584,8 +584,7 @@ describe('ContributionResolver', () => { describe('update creation to a date that is older than 3 months', () => { it('throws an error', async () => { jest.clearAllMocks() - const date = new Date() - date.setMonth(date.getMonth() - 3) + const date = getFirstDayOfPreviousNMonth(new Date(), 3) const { errors: errorObjects } = await mutate({ mutation: updateContribution, variables: { diff --git a/backend/src/graphql/resolver/util/creations.test.ts b/backend/src/graphql/resolver/util/creations.test.ts index 25d8a45c2..83d787dd9 100644 --- a/backend/src/graphql/resolver/util/creations.test.ts +++ b/backend/src/graphql/resolver/util/creations.test.ts @@ -10,7 +10,7 @@ import { login, createContribution, adminCreateContribution } from '@/seeds/grap import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' import { peterLustig } from '@/seeds/users/peter-lustig' -import { getUserCreation } from './creations' +import { getOpenCreations, getUserCreation } from './creations' let mutate: ApolloServerTestClient['mutate'], con: Connection let testEnv: { @@ -270,4 +270,49 @@ describe('util/creation', () => { }) }) }) + describe('getOpenCreations', () => { + beforeAll(() => { + // enable Fake timers + jest.useFakeTimers() + // jest.setSystemTime(new Date('2022-01-01T00:00:00Z')) + }) + + afterAll(() => { + // disable Fake timers and set time back to system time + jest.useRealTimers() + }) + it('test default case', async () => { + jest.setSystemTime(new Date('2022-01-10T00:00:00Z')) + const creationDates = await getOpenCreations(user.id, 0) + expect(creationDates).toEqual( + expect.arrayContaining([ + expect.objectContaining({ month: 10 }), + expect.objectContaining({ month: 11 }), + expect.objectContaining({ month: 0 }), + ]), + ) + }) + it('test edge case with february', async () => { + jest.setSystemTime(new Date('2022-05-31T00:00:00Z')) + const creationDates = await getOpenCreations(user.id, 0) + expect(creationDates).toEqual( + expect.arrayContaining([ + expect.objectContaining({ month: 2 }), + expect.objectContaining({ month: 3 }), + expect.objectContaining({ month: 4 }), + ]), + ) + }) + it('test edge case with july', async () => { + jest.setSystemTime(new Date('2022-07-31T00:00:00Z')) + const creationDates = await getOpenCreations(user.id, 0) + expect(creationDates).toEqual( + expect.arrayContaining([ + expect.objectContaining({ month: 4 }), + expect.objectContaining({ month: 5 }), + expect.objectContaining({ month: 6 }), + ]), + ) + }) + }) }) diff --git a/backend/src/graphql/resolver/util/creations.ts b/backend/src/graphql/resolver/util/creations.ts index d6f0e9af4..6bb7214b1 100644 --- a/backend/src/graphql/resolver/util/creations.ts +++ b/backend/src/graphql/resolver/util/creations.ts @@ -10,6 +10,7 @@ import { OpenCreation } from '@model/OpenCreation' import { FULL_CREATION_AVAILABLE, MAX_CREATION_AMOUNT } from '@/graphql/resolver/const/const' import { LogError } from '@/server/LogError' import { backendLogger as logger } from '@/server/logger' +import { getFirstDayOfPreviousNMonth } from '@/util/utilities' interface CreationMap { id: number @@ -115,8 +116,8 @@ const getCreationDates = (timezoneOffset: number): Date[] => { `getCreationMonths -- offset: ${timezoneOffset} -- clientNow: ${clientNow.toISOString()}`, ) return [ - new Date(clientNow.getFullYear(), clientNow.getMonth() - 2, 1), - new Date(clientNow.getFullYear(), clientNow.getMonth() - 1, 1), + getFirstDayOfPreviousNMonth(clientNow, 2), + getFirstDayOfPreviousNMonth(clientNow, 1), clientNow, ] } diff --git a/backend/src/util/utilities.ts b/backend/src/util/utilities.ts index bc2c2198a..905cce686 100644 --- a/backend/src/util/utilities.ts +++ b/backend/src/util/utilities.ts @@ -33,3 +33,22 @@ export function resetInterface>(obj: T): T { export const ensureUrlEndsWithSlash = (url: string): string => { return url.endsWith('/') ? url : url.concat('/') } +/** + * Calculates the date representing the first day of the month, a specified number of months prior to a given date. + * + * This function was created to address an issue with using `Date.prototype.setMonth`. + * When calculating previous months, `setMonth` can produce incorrect results at the end of months. + * For example, subtracting 3 months from May 31st using `setMonth` would result in March instead of February. + * This function ensures the correct month is calculated by setting the day to the 1st before performing the month subtraction. + * + * @param {Date} startDate - The starting date from which to calculate the previous months. + * @param {number} monthsAgo - The number of months to go back from the startDate. + * @returns {Date} A new Date object set to the first day of the month, `monthsAgo` months before the `startDate`. + * + * @example + * // Calculate the date for the first day of the month, 3 months prior to March 15, 2024 + * const date = getFirstDayOfPreviousNMonth(new Date(2024, 4, 31), 3); + * console.log(date); // Output: Fri Feb 01 2024 00:00:00 GMT+0000 (Coordinated Universal Time) + */ +export const getFirstDayOfPreviousNMonth = (startDate: Date, monthsAgo: number): Date => + new Date(startDate.getFullYear(), startDate.getMonth() - monthsAgo, 1) From fc137c09b3c8e4a435cd358c24fa19bb085fde36 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 4 Jun 2024 13:25:18 +0200 Subject: [PATCH 006/166] add additional tests for edge cases --- backend/src/util/utilities.test.ts | 59 ++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 backend/src/util/utilities.test.ts diff --git a/backend/src/util/utilities.test.ts b/backend/src/util/utilities.test.ts new file mode 100644 index 000000000..5c193d5a8 --- /dev/null +++ b/backend/src/util/utilities.test.ts @@ -0,0 +1,59 @@ +import { getFirstDayOfPreviousNMonth } from './utilities' // Adjust the path as necessary + +describe('getFirstDayOfPreviousNMonth', () => { + test('should calculate 3 months prior to March 31, 2024', () => { + const startDate = new Date(2024, 2, 31) // March 31, 2024 (month is 0-indexed) + const monthsAgo = 3 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2023, 11, 1)) // December 1, 2023 + }) + + test('should handle end of month correctly, January 31, 2024', () => { + const startDate = new Date(2024, 0, 31) // January 31, 2024 + const monthsAgo = 1 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2023, 11, 1)) // December 1, 2023 + }) + + test('should handle leap year, March 1, 2024', () => { + const startDate = new Date(2024, 2, 1) // March 1, 2024 + const monthsAgo = 1 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2024, 1, 1)) // February 1, 2024 + }) + + test('should handle leap year, February 29, 2024', () => { + const startDate = new Date(2024, 1, 29) // February 29, 2024 (leap year) + const monthsAgo = 12 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2023, 1, 1)) // February 1, 2023 + }) + + test('should handle end of year transition, January 1, 2024', () => { + const startDate = new Date(2024, 0, 1) // January 1, 2024 + const monthsAgo = 1 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2023, 11, 1)) // December 1, 2023 + }) + + test('should handle a large number of months ago, December 15, 2024', () => { + const startDate = new Date(2024, 11, 15) // December 15, 2024 + const monthsAgo = 24 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2022, 11, 1)) // December 1, 2022 + }) + + test('should handle start of month correctly, February 1, 2024', () => { + const startDate = new Date(2024, 1, 1) // February 1, 2024 + const monthsAgo = 1 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2024, 0, 1)) // January 1, 2024 + }) + + test('should handle middle of month correctly, February 14, 2024', () => { + const startDate = new Date(2024, 1, 14) // February 14, 2024 + const monthsAgo = 3 + const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) + expect(result).toEqual(new Date(2023, 10, 1)) // November 1, 2024 + }) +}) From 44dd0f28ea3f8cc1ed96657ed6a91c5ebc63c88a Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 4 Jun 2024 13:27:40 +0200 Subject: [PATCH 007/166] correct comment --- backend/src/util/utilities.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/util/utilities.test.ts b/backend/src/util/utilities.test.ts index 5c193d5a8..abd7604a8 100644 --- a/backend/src/util/utilities.test.ts +++ b/backend/src/util/utilities.test.ts @@ -54,6 +54,6 @@ describe('getFirstDayOfPreviousNMonth', () => { const startDate = new Date(2024, 1, 14) // February 14, 2024 const monthsAgo = 3 const result = getFirstDayOfPreviousNMonth(startDate, monthsAgo) - expect(result).toEqual(new Date(2023, 10, 1)) // November 1, 2024 + expect(result).toEqual(new Date(2023, 10, 1)) // November 1, 2023 }) }) From dbea2888be4456919c02a01055832d3b21828fb9 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 10 Jun 2024 18:45:10 +0200 Subject: [PATCH 008/166] release --- CHANGELOG.md | 9 +++++++++ admin/package.json | 2 +- backend/package.json | 2 +- database/package.json | 2 +- dht-node/package.json | 2 +- dlt-connector/package.json | 2 +- federation/package.json | 2 +- frontend/package.json | 2 +- package.json | 2 +- 9 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72f37afd3..a84f8909c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,17 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [2.3.1](https://github.com/gradido/gradido/compare/2.3.0...2.3.1) + +- feat(frontend): more compatible humhub auto-login link [`#3319`](https://github.com/gradido/gradido/pull/3319) +- fix(backend): fix test which will only fail at 31. of month, or 30.05 [`#3320`](https://github.com/gradido/gradido/pull/3320) +- feat(frontend): remove automatically logged out message [`#3318`](https://github.com/gradido/gradido/pull/3318) + #### [2.3.0](https://github.com/gradido/gradido/compare/2.2.1...2.3.0) +> 20 May 2024 + +- chore(release): v2.3.0 beta [`#3316`](https://github.com/gradido/gradido/pull/3316) - feat(frontend): conditional services menu entries [`#3314`](https://github.com/gradido/gradido/pull/3314) - feat(frontend): update news [`#3313`](https://github.com/gradido/gradido/pull/3313) - feat(frontend): auto-login link for humhub [`#3311`](https://github.com/gradido/gradido/pull/3311) diff --git a/admin/package.json b/admin/package.json index db87f59e9..96015e1c0 100644 --- a/admin/package.json +++ b/admin/package.json @@ -3,7 +3,7 @@ "description": "Administraion Interface for Gradido", "main": "index.js", "author": "Moriz Wahl", - "version": "2.3.0", + "version": "2.3.1", "license": "Apache-2.0", "private": false, "scripts": { diff --git a/backend/package.json b/backend/package.json index bef3fd560..7fcd21000 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "gradido-backend", - "version": "2.3.0", + "version": "2.3.1", "description": "Gradido unified backend providing an API-Service for Gradido Transactions", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/backend", diff --git a/database/package.json b/database/package.json index e445fe15b..50a489934 100644 --- a/database/package.json +++ b/database/package.json @@ -1,6 +1,6 @@ { "name": "gradido-database", - "version": "2.3.0", + "version": "2.3.1", "description": "Gradido Database Tool to execute database migrations", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/database", diff --git a/dht-node/package.json b/dht-node/package.json index 620a77ee9..67c24dd9e 100644 --- a/dht-node/package.json +++ b/dht-node/package.json @@ -1,6 +1,6 @@ { "name": "gradido-dht-node", - "version": "2.3.0", + "version": "2.3.1", "description": "Gradido dht-node module", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/", diff --git a/dlt-connector/package.json b/dlt-connector/package.json index 4923d6408..3e576b48d 100644 --- a/dlt-connector/package.json +++ b/dlt-connector/package.json @@ -1,6 +1,6 @@ { "name": "gradido-dlt-connector", - "version": "2.3.0", + "version": "2.3.1", "description": "Gradido DLT-Connector", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/", diff --git a/federation/package.json b/federation/package.json index 5a945f963..151777054 100644 --- a/federation/package.json +++ b/federation/package.json @@ -1,6 +1,6 @@ { "name": "gradido-federation", - "version": "2.3.0", + "version": "2.3.1", "description": "Gradido federation module providing Gradido-Hub-Federation and versioned API for inter community communication", "main": "src/index.ts", "repository": "https://github.com/gradido/gradido/federation", diff --git a/frontend/package.json b/frontend/package.json index e803a004a..879171697 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "bootstrap-vue-gradido-wallet", - "version": "2.3.0", + "version": "2.3.1", "private": true, "scripts": { "start": "node run/server.js", diff --git a/package.json b/package.json index de62f441d..28f981637 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gradido", - "version": "2.3.0", + "version": "2.3.1", "description": "Gradido", "main": "index.js", "repository": "git@github.com:gradido/gradido.git", From 337be6e00b085b19232331d22ea5b531576d643f Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 17 Jun 2024 11:47:14 +0200 Subject: [PATCH 009/166] fix link forwarding after using send with url parameters --- frontend/src/pages/Send.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/Send.vue b/frontend/src/pages/Send.vue index 334d1062d..550c30bf3 100644 --- a/frontend/src/pages/Send.vue +++ b/frontend/src/pages/Send.vue @@ -172,7 +172,7 @@ export default { throw new Error(`undefined transactionData.selected : ${this.transactionData.selected}`) } this.loading = false - this.$router.push('send') + this.$router.push({ path: '/send' }) }, onBack() { this.currentTransactionStep = TRANSACTION_STEPS.transactionForm From 5008a60225410f3ab04eb5a53d964b7a4f4f6d4d Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 17 Jun 2024 11:53:58 +0200 Subject: [PATCH 010/166] fix test --- frontend/src/pages/Send.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/Send.spec.js b/frontend/src/pages/Send.spec.js index 43bda6f3d..8a4c4cc79 100644 --- a/frontend/src/pages/Send.spec.js +++ b/frontend/src/pages/Send.spec.js @@ -229,7 +229,7 @@ describe('Send', () => { }) it('resets the gradido ID query in route', () => { - expect(routerPushMock).toBeCalledWith('send') + expect(routerPushMock).toBeCalledWith({ path: '/send' }) }) }) }) From b3fab60970148e7e0ce27b913b87712d1aa1f558 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 18 Jun 2024 17:05:59 +0200 Subject: [PATCH 011/166] implement coordinates for community --- .../ContributionLink/ContributionLinkForm.vue | 2 +- .../Federation/CommunityVisualizeItem.vue | 46 +++++++--- admin/src/components/Federation/GMSApiKey.vue | 33 +++++++ admin/src/components/input/Coordinates.vue | 90 +++++++++++++++++++ admin/src/components/input/EditableGroup.vue | 61 +++++++++++++ admin/src/graphql/allCommunities.js | 1 + admin/src/graphql/updateHomeCommunity.js | 4 +- admin/src/locales/de.json | 13 ++- admin/src/locales/en.json | 13 ++- backend/package.json | 3 + backend/src/config/index.ts | 2 +- .../src/graphql/input/EditCommunityInput.ts | 7 ++ .../src/graphql/model/AdminCommunityView.ts | 5 ++ backend/src/graphql/model/Point.ts | 10 +++ .../src/graphql/resolver/CommunityResolver.ts | 7 +- backend/src/graphql/scalar/Point.ts | 16 ++-- backend/src/graphql/schema.ts | 3 + backend/src/graphql/validator/Point.ts | 29 ++++++ backend/yarn.lock | 12 ++- .../0085-add_community_location/Community.ts | 89 ++++++++++++++++++ database/entity/Community.ts | 2 +- .../migrations/0085-add_community_location.ts | 13 +++ dht-node/src/config/index.ts | 2 +- dht-node/yarn.lock | 16 +++- dlt-database/migrations/0004-fix_spelling.ts | 4 +- federation/src/config/index.ts | 2 +- 26 files changed, 452 insertions(+), 33 deletions(-) create mode 100644 admin/src/components/Federation/GMSApiKey.vue create mode 100644 admin/src/components/input/Coordinates.vue create mode 100644 admin/src/components/input/EditableGroup.vue create mode 100644 backend/src/graphql/model/Point.ts create mode 100644 backend/src/graphql/validator/Point.ts create mode 100644 database/entity/0085-add_community_location/Community.ts create mode 100644 database/migrations/0085-add_community_location.ts diff --git a/admin/src/components/ContributionLink/ContributionLinkForm.vue b/admin/src/components/ContributionLink/ContributionLinkForm.vue index 2afd8e1c5..f8e3d0f1f 100644 --- a/admin/src/components/ContributionLink/ContributionLinkForm.vue +++ b/admin/src/components/ContributionLink/ContributionLinkForm.vue @@ -113,7 +113,7 @@ {{ $t('contributionLink.clear') }} - {{ $t('contributionLink.close') }} + {{ $t('close') }}
diff --git a/admin/src/components/Federation/CommunityVisualizeItem.vue b/admin/src/components/Federation/CommunityVisualizeItem.vue index 24e6b3712..edabc3a70 100644 --- a/admin/src/components/Federation/CommunityVisualizeItem.vue +++ b/admin/src/components/Federation/CommunityVisualizeItem.vue @@ -25,12 +25,24 @@ {{ $t('federation.publicKey') }} {{ item.publicKey }} - {{ $t('federation.gmsApiKey') }}  - + @save="handleUpdateHomeCommunity" + @reset="resetHomeCommunityEditable" + > + + + @@ -59,17 +71,21 @@ diff --git a/admin/src/components/Federation/GMSApiKey.vue b/admin/src/components/Federation/GMSApiKey.vue new file mode 100644 index 000000000..468bd7c28 --- /dev/null +++ b/admin/src/components/Federation/GMSApiKey.vue @@ -0,0 +1,33 @@ + + + diff --git a/admin/src/components/input/Coordinates.vue b/admin/src/components/input/Coordinates.vue new file mode 100644 index 000000000..dbbe4c7e5 --- /dev/null +++ b/admin/src/components/input/Coordinates.vue @@ -0,0 +1,90 @@ + + + diff --git a/admin/src/components/input/EditableGroup.vue b/admin/src/components/input/EditableGroup.vue new file mode 100644 index 000000000..9653430bc --- /dev/null +++ b/admin/src/components/input/EditableGroup.vue @@ -0,0 +1,61 @@ + + + diff --git a/admin/src/graphql/allCommunities.js b/admin/src/graphql/allCommunities.js index 6379086c7..c2ccdd15e 100644 --- a/admin/src/graphql/allCommunities.js +++ b/admin/src/graphql/allCommunities.js @@ -11,6 +11,7 @@ export const allCommunities = gql` name description gmsApiKey + location creationDate createdAt updatedAt diff --git a/admin/src/graphql/updateHomeCommunity.js b/admin/src/graphql/updateHomeCommunity.js index a43d6edd2..a33e7164c 100644 --- a/admin/src/graphql/updateHomeCommunity.js +++ b/admin/src/graphql/updateHomeCommunity.js @@ -1,8 +1,8 @@ import gql from 'graphql-tag' export const updateHomeCommunity = gql` - mutation ($uuid: String!, $gmsApiKey: String!) { - updateHomeCommunity(uuid: $uuid, gmsApiKey: $gmsApiKey) { + mutation ($uuid: String!, $gmsApiKey: String!, $location: Point!) { + updateHomeCommunity(uuid: $uuid, gmsApiKey: $gmsApiKey, location: $location) { id } } diff --git a/admin/src/locales/de.json b/admin/src/locales/de.json index 9f808f70c..aa8f51983 100644 --- a/admin/src/locales/de.json +++ b/admin/src/locales/de.json @@ -1,14 +1,15 @@ { "GDD": "GDD", "all_emails": "Alle Nutzer", + "edit": "bearbeiten", "back": "zurück", "change_user_role": "Nutzerrolle ändern", "chat": "Chat", + "close": "Schließen", "contributionLink": { "amount": "Betrag", "changeSaved": "Änderungen gespeichert", "clear": "Löschen", - "close": "Schließen", "contributionLinks": "Beitragslinks", "create": "Anlegen", "cycle": "Zyklus", @@ -76,6 +77,7 @@ "apiVersion": "API Version", "authenticatedAt": "Verifiziert am:", "communityUuid": "Community UUID:", + "coordinates": "Koordinaten:", "createdAt": "Erstellt am", "gmsApiKey": "GMS API Key:", "toast_gmsApiKeyUpdated": "Der GMS Api Key wurde erfolgreich aktualisiert!", @@ -100,6 +102,13 @@ "form": { "cancel": "Abbrechen" }, + "geo-coordinates": { + "both-or-none": "Bitte beide oder keine eingeben!", + "label": "Geo-Koordinaten", + "latitude": { + "describe": "Teilt Koordinaten im Format 'Längengrad, Breitengrad' automatisch in separate Eingabefelder auf. Fügen sie hier einfach z.B. ihre Koordinaten von Google Maps, zum Beispiel: 49.28187664243721, 9.740672183943639, ein." + } + }, "help": { "help": "Hilfe", "transactionlist": { @@ -113,6 +122,8 @@ "hide_resubmission": "Wiedervorlage verbergen", "hide_resubmission_tooltip": "Verbirgt alle Schöpfungen für die ein Moderator ein Erinnerungsdatum festgelegt hat.", "lastname": "Nachname", + "latitude": "Breitengrad:", + "longitude": "Längengrad:", "math": { "equals": "=", "pipe": "|", diff --git a/admin/src/locales/en.json b/admin/src/locales/en.json index b1f020921..258abe891 100644 --- a/admin/src/locales/en.json +++ b/admin/src/locales/en.json @@ -1,14 +1,15 @@ { "GDD": "GDD", "all_emails": "All users", + "edit": "edit", "back": "back", "change_user_role": "Change user role", "chat": "Chat", + "close": "Close", "contributionLink": { "amount": "Amount", "changeSaved": "Changes saved", "clear": "Clear", - "close": "Close", "contributionLinks": "Contribution Links", "create": "Create", "cycle": "Cycle", @@ -76,6 +77,7 @@ "apiVersion": "API Version", "authenticatedAt": "verified at:", "communityUuid": "Community UUID:", + "coordinates": "Coordinates:", "createdAt": "Created At ", "gmsApiKey": "GMS API Key:", "toast_gmsApiKeyUpdated": "The GMS Api Key has been successfully updated!", @@ -100,6 +102,13 @@ "form": { "cancel": "Cancel" }, + "geo-coordinates": { + "both-or-none": "Please enter both or none!", + "label": "geo-coordinates", + "latitude": { + "describe": "Automatically splits coordinates in the format 'longitude, latitude' into separate input fields. Simply enter your coordinates from Google Maps here, for example: 49.28187664243721, 9.740672183943639." + } + }, "help": { "help": "Help", "transactionlist": { @@ -113,6 +122,8 @@ "hide_resubmission": "Hide resubmission", "hide_resubmission_tooltip": "Hides all creations for which a moderator has set a reminder date.", "lastname": "Lastname", + "latitude": "Breitengrad:", + "longitude": "Längengrad:", "math": { "equals": "=", "pipe": "|", diff --git a/backend/package.json b/backend/package.json index 7fcd21000..7c6128a81 100644 --- a/backend/package.json +++ b/backend/package.json @@ -33,9 +33,11 @@ "email-templates": "^10.0.1", "express": "^4.17.1", "express-slow-down": "^2.0.1", + "geojson": "^0.5.0", "gradido-database": "file:../database", "graphql": "^15.5.1", "graphql-request": "5.0.0", + "graphql-type-json": "0.3.2", "helmet": "^5.1.1", "i18n": "^0.15.1", "jose": "^4.14.4", @@ -56,6 +58,7 @@ "@types/email-templates": "^10.0.1", "@types/express": "^4.17.12", "@types/faker": "^5.5.9", + "@types/geojson": "^7946.0.13", "@types/i18n": "^0.13.4", "@types/jest": "^27.0.2", "@types/lodash.clonedeep": "^4.5.6", diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 82308a52b..d75730c8e 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -12,7 +12,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0084-introduce_humhub_registration', + DB_VERSION: '0085-add_community_location', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info diff --git a/backend/src/graphql/input/EditCommunityInput.ts b/backend/src/graphql/input/EditCommunityInput.ts index 8c74f874b..b1bfc20fb 100644 --- a/backend/src/graphql/input/EditCommunityInput.ts +++ b/backend/src/graphql/input/EditCommunityInput.ts @@ -1,6 +1,9 @@ import { IsString, IsUUID } from 'class-validator' import { ArgsType, Field, InputType } from 'type-graphql' +import { Point } from '@/graphql/model/Point' +import { isValidPoint } from '@/graphql/validator/Point' + @ArgsType() @InputType() export class EditCommunityInput { @@ -11,4 +14,8 @@ export class EditCommunityInput { @Field(() => String) @IsString() gmsApiKey: string + + @Field(() => Point) + @isValidPoint() + location: Point } diff --git a/backend/src/graphql/model/AdminCommunityView.ts b/backend/src/graphql/model/AdminCommunityView.ts index 95af54bc5..c92a41b90 100644 --- a/backend/src/graphql/model/AdminCommunityView.ts +++ b/backend/src/graphql/model/AdminCommunityView.ts @@ -3,6 +3,7 @@ import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCom import { ObjectType, Field } from 'type-graphql' import { FederatedCommunity } from './FederatedCommunity' +import { Point } from './Point' @ObjectType() export class AdminCommunityView { @@ -36,6 +37,7 @@ export class AdminCommunityView { this.uuid = dbCom.communityUuid this.authenticatedAt = dbCom.authenticatedAt this.gmsApiKey = dbCom.gmsApiKey + this.location = dbCom.location ? dbCom.location as Point : new Point() } @Field(() => Boolean) @@ -62,6 +64,9 @@ export class AdminCommunityView { @Field(() => String, { nullable: true }) gmsApiKey: string | null + @Field(() => Point) + location: Point + @Field(() => Date, { nullable: true }) creationDate: Date | null diff --git a/backend/src/graphql/model/Point.ts b/backend/src/graphql/model/Point.ts new file mode 100644 index 000000000..bddb50598 --- /dev/null +++ b/backend/src/graphql/model/Point.ts @@ -0,0 +1,10 @@ +import { Position, Point as geojsonPoint } from 'geojson' + +export class Point implements geojsonPoint { + constructor() { + this.coordinates = [] + this.type = 'Point' + } + type: 'Point' + coordinates: Position +} diff --git a/backend/src/graphql/resolver/CommunityResolver.ts b/backend/src/graphql/resolver/CommunityResolver.ts index 2d2323865..0dc844b5c 100644 --- a/backend/src/graphql/resolver/CommunityResolver.ts +++ b/backend/src/graphql/resolver/CommunityResolver.ts @@ -78,7 +78,9 @@ export class CommunityResolver { @Authorized([RIGHTS.COMMUNITY_UPDATE]) @Mutation(() => Community) - async updateHomeCommunity(@Args() { uuid, gmsApiKey }: EditCommunityInput): Promise { + async updateHomeCommunity( + @Args() { uuid, gmsApiKey, location }: EditCommunityInput, + ): Promise { const homeCom = await getCommunityByUuid(uuid) if (!homeCom) { throw new LogError('HomeCommunity with uuid not found: ', uuid) @@ -86,8 +88,9 @@ export class CommunityResolver { if (homeCom.foreign) { throw new LogError('Error: Only the HomeCommunity could be modified!') } - if (homeCom.gmsApiKey !== gmsApiKey) { + if (homeCom.gmsApiKey !== gmsApiKey || homeCom.location !== location) { homeCom.gmsApiKey = gmsApiKey + homeCom.location = location await DbCommunity.save(homeCom) } return new Community(homeCom) diff --git a/backend/src/graphql/scalar/Point.ts b/backend/src/graphql/scalar/Point.ts index 06af56bfc..015704a15 100644 --- a/backend/src/graphql/scalar/Point.ts +++ b/backend/src/graphql/scalar/Point.ts @@ -1,23 +1,25 @@ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { Point as DbPoint } from '@dbTools/typeorm' import { GraphQLScalarType, Kind } from 'graphql' +import { Point } from '@/graphql/model/Point' export const PointScalar = new GraphQLScalarType({ name: 'Point', description: 'The `Point` scalar type to represent longitude and latitude values of a geo location', - serialize(value: DbPoint) { + serialize(value: Point) { // Check type of value if (value.type !== 'Point') { - throw new Error(`PointScalar can only serialize Geometry type 'Point' values`) + throw new Error(`PointScalar can only serialize Geometry type 'Point' values`, ) } return value }, - parseValue(value): DbPoint { - const point = JSON.parse(value) as DbPoint - return point + parseValue(value): Point { + if (value.type !== 'Point') { + throw new Error(`PointScalar can only deserialize Geometry type 'Point' values`, ) + } + return value as Point }, parseLiteral(ast) { @@ -25,7 +27,7 @@ export const PointScalar = new GraphQLScalarType({ throw new TypeError(`${String(ast)} is not a valid Geometry value.`) } - const point = JSON.parse(ast.value) as DbPoint + const point = JSON.parse(ast.value) as Point return point }, }) diff --git a/backend/src/graphql/schema.ts b/backend/src/graphql/schema.ts index bcb8081a6..4aa5ae2e1 100644 --- a/backend/src/graphql/schema.ts +++ b/backend/src/graphql/schema.ts @@ -7,8 +7,10 @@ import { buildSchema } from 'type-graphql' import { Location } from '@model/Location' import { isAuthorized } from './directive/isAuthorized' +import { Point } from './model/Point' import { DecimalScalar } from './scalar/Decimal' import { LocationScalar } from './scalar/Location' +import { PointScalar } from './scalar/Point' export const schema = async (): Promise => { return buildSchema({ @@ -17,6 +19,7 @@ export const schema = async (): Promise => { scalarsMap: [ { type: Decimal, scalar: DecimalScalar }, { type: Location, scalar: LocationScalar }, + { type: Point, scalar: PointScalar }, ], validate: { validationError: { target: false }, diff --git a/backend/src/graphql/validator/Point.ts b/backend/src/graphql/validator/Point.ts new file mode 100644 index 000000000..e82836e67 --- /dev/null +++ b/backend/src/graphql/validator/Point.ts @@ -0,0 +1,29 @@ +import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator' +import { Point } from '@/graphql/model/Point' + +export function isValidPoint(validationOptions?: ValidationOptions) { + // eslint-disable-next-line @typescript-eslint/ban-types + return function (object: Object, propertyName: string) { + registerDecorator({ + name: 'isValidPoint', + target: object.constructor, + propertyName, + options: validationOptions, + validator: { + validate(value: Point) { + if (value.type === 'Point') { + if (value.coordinates.length === 2) { + return value.coordinates.every((coord) => typeof coord === 'number') + } else if(value.coordinates.length === 0) { + return true + } + } + return false + }, + defaultMessage(args: ValidationArguments) { + return `${propertyName} must be a valid Point in geoJSON Format, ${args.property}` + }, + }, + }) + } +} diff --git a/backend/yarn.lock b/backend/yarn.lock index 26f861772..caddf50a0 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -994,6 +994,11 @@ dependencies: "@types/node" "*" +"@types/geojson@^7946.0.13": + version "7946.0.14" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" + integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== + "@types/glob@^7.1.3": version "7.1.4" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" @@ -3696,7 +3701,7 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0: integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== "gradido-database@file:../database": - version "2.2.1" + version "2.3.1" dependencies: "@types/uuid" "^8.3.4" cross-env "^7.0.3" @@ -3774,6 +3779,11 @@ graphql-tools@^4.0.8: iterall "^1.1.3" uuid "^3.1.0" +graphql-type-json@0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/graphql-type-json/-/graphql-type-json-0.3.2.tgz#f53a851dbfe07bd1c8157d24150064baab41e115" + integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg== + graphql@^15.5.1: version "15.6.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.1.tgz#9125bdf057553525da251e19e96dab3d3855ddfc" diff --git a/database/entity/0085-add_community_location/Community.ts b/database/entity/0085-add_community_location/Community.ts new file mode 100644 index 000000000..60410c8ce --- /dev/null +++ b/database/entity/0085-add_community_location/Community.ts @@ -0,0 +1,89 @@ +import { + BaseEntity, + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + OneToMany, + JoinColumn, + Geometry, +} from 'typeorm' +import { FederatedCommunity } from '../FederatedCommunity' +import { GeometryTransformer } from '../../src/typeorm/GeometryTransformer' +import { User } from '../User' + +@Entity('communities') +export class Community extends BaseEntity { + @PrimaryGeneratedColumn('increment', { unsigned: true }) + id: number + + @Column({ name: 'foreign', type: 'bool', nullable: false, default: true }) + foreign: boolean + + @Column({ name: 'url', length: 255, nullable: false }) + url: string + + @Column({ name: 'public_key', type: 'binary', length: 32, nullable: false }) + publicKey: Buffer + + @Column({ name: 'private_key', type: 'binary', length: 64, nullable: true }) + privateKey: Buffer | null + + @Column({ + name: 'community_uuid', + type: 'char', + length: 36, + nullable: true, + collation: 'utf8mb4_unicode_ci', + }) + communityUuid: string | null + + @Column({ name: 'authenticated_at', type: 'datetime', nullable: true }) + authenticatedAt: Date | null + + @Column({ name: 'name', type: 'varchar', length: 40, nullable: true }) + name: string | null + + @Column({ name: 'description', type: 'varchar', length: 255, nullable: true }) + description: string | null + + @CreateDateColumn({ name: 'creation_date', type: 'datetime', nullable: true }) + creationDate: Date | null + + @Column({ name: 'gms_api_key', type: 'varchar', length: 512, nullable: true, default: null }) + gmsApiKey: string | null + + @Column({ + name: 'location', + type: 'geometry', + default: null, + nullable: true, + transformer: GeometryTransformer, + }) + location: Geometry | null + + @CreateDateColumn({ + name: 'created_at', + type: 'datetime', + default: () => 'CURRENT_TIMESTAMP(3)', + nullable: false, + }) + createdAt: Date + + @UpdateDateColumn({ + name: 'updated_at', + type: 'datetime', + onUpdate: 'CURRENT_TIMESTAMP(3)', + nullable: true, + }) + updatedAt: Date | null + + @OneToMany(() => User, (user) => user.community) + @JoinColumn({ name: 'community_uuid', referencedColumnName: 'communityUuid' }) + users: User[] + + @OneToMany(() => FederatedCommunity, (federatedCommunity) => federatedCommunity.community) + @JoinColumn({ name: 'public_key', referencedColumnName: 'publicKey' }) + federatedCommunities?: FederatedCommunity[] +} diff --git a/database/entity/Community.ts b/database/entity/Community.ts index ccc752cd8..750a2e842 100644 --- a/database/entity/Community.ts +++ b/database/entity/Community.ts @@ -1 +1 @@ -export { Community } from './0083-join_community_federated_communities/Community' +export { Community } from './0085-add_community_location/Community' diff --git a/database/migrations/0085-add_community_location.ts b/database/migrations/0085-add_community_location.ts new file mode 100644 index 000000000..b6f0ea917 --- /dev/null +++ b/database/migrations/0085-add_community_location.ts @@ -0,0 +1,13 @@ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'ALTER TABLE `communities` ADD COLUMN IF NOT EXISTS `location` geometry DEFAULT NULL NULL AFTER `gms_api_key`;', + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('ALTER TABLE `communities` DROP COLUMN IF EXISTS `location`;') +} diff --git a/dht-node/src/config/index.ts b/dht-node/src/config/index.ts index f557eee83..08d5a7053 100644 --- a/dht-node/src/config/index.ts +++ b/dht-node/src/config/index.ts @@ -4,7 +4,7 @@ import dotenv from 'dotenv' dotenv.config() const constants = { - DB_VERSION: '0084-introduce_humhub_registration', + DB_VERSION: '0085-add_community_location', LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info LOG_LEVEL: process.env.LOG_LEVEL ?? 'info', diff --git a/dht-node/yarn.lock b/dht-node/yarn.lock index 5f42f71a7..4bf9fa916 100644 --- a/dht-node/yarn.lock +++ b/dht-node/yarn.lock @@ -2260,6 +2260,11 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +geojson@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/geojson/-/geojson-0.5.0.tgz#3cd6c96399be65b56ee55596116fe9191ce701c0" + integrity sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ== + get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2389,18 +2394,20 @@ graceful-fs@^4.2.4: integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== "gradido-database@file:../database": - version "1.22.3" + version "2.2.1" dependencies: "@types/uuid" "^8.3.4" cross-env "^7.0.3" crypto "^1.0.1" decimal.js-light "^2.5.1" dotenv "^10.0.0" + geojson "^0.5.0" mysql2 "^2.3.0" reflect-metadata "^0.1.13" ts-mysql-migrate "^1.0.2" typeorm "^0.3.16" uuid "^8.3.2" + wkx "^0.5.0" grapheme-splitter@^1.0.4: version "1.0.4" @@ -4888,6 +4895,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wkx@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c" + integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg== + dependencies: + "@types/node" "*" + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" diff --git a/dlt-database/migrations/0004-fix_spelling.ts b/dlt-database/migrations/0004-fix_spelling.ts index 3b2153a7d..1507ab590 100644 --- a/dlt-database/migrations/0004-fix_spelling.ts +++ b/dlt-database/migrations/0004-fix_spelling.ts @@ -1,7 +1,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn(` ALTER TABLE \`transactions\` - RENAME COLUMN \`paring_transaction_id\` TO \`pairing_transaction_id\`, + RENAME COLUMN \`paring_transaction_id\` TO \`pairing_transaction_id\` ; `) } @@ -9,7 +9,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { await queryFn(` ALTER TABLE \`transactions\` - RENAME COLUMN \`pairing_transaction_id\` TO \`paring_transaction_id\`, + RENAME COLUMN \`pairing_transaction_id\` TO \`paring_transaction_id\` ; `) } diff --git a/federation/src/config/index.ts b/federation/src/config/index.ts index 26b727841..793d9957e 100644 --- a/federation/src/config/index.ts +++ b/federation/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0084-introduce_humhub_registration', + DB_VERSION: '0085-add_community_location', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info From 43b0ac45113adbcbcaf59a9d2eb83f1d03b8e3a2 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 11:05:45 +0200 Subject: [PATCH 012/166] move timing log messages from debug to info --- backend/src/graphql/resolver/BalanceResolver.ts | 17 +++++++++++++++++ .../src/graphql/resolver/TransactionResolver.ts | 16 +++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 87de0e0f7..a702cc08f 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -29,12 +29,19 @@ export class BalanceResolver { const gdtResolver = new GdtResolver() const balanceGDT = await gdtResolver.gdtBalance(context) + + logger.info(`time for load gdt balance: ${new Date().getTime() - now.getTime()} ms`) + let profilingTime = new Date() + logger.debug(`balanceGDT=${balanceGDT}`) const lastTransaction = context.lastTransaction ? context.lastTransaction : await getLastTransaction(user.id) + logger.info(`time for load lastTransaction from db (if not already done): ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() + logger.debug(`lastTransaction=${lastTransaction}`) // No balance found @@ -52,8 +59,12 @@ export class BalanceResolver { context.transactionCount || context.transactionCount === 0 ? context.transactionCount : await dbTransaction.count({ where: { userId: user.id } }) + logger.debug(`transactionCount=${count}`) + logger.info(`time for count transaction in db: ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() + const linkCount = await dbTransactionLink.count({ where: { userId: user.id, @@ -63,6 +74,9 @@ export class BalanceResolver { }) logger.debug(`linkCount=${linkCount}`) + logger.info(`time for count transaction links in db: ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() + // The decay is always calculated on the last booked transaction const calculatedDecay = calculateDecay( lastTransaction.balance, @@ -81,6 +95,9 @@ export class BalanceResolver { ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } : await transactionLinkSummary(user.id, now) + logger.info(`time for load transactionLinkSummary from db (if not already done): ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() + logger.debug(`context.sumHoldAvailableAmount=${context.sumHoldAvailableAmount}`) logger.debug(`sumHoldAvailableAmount=${sumHoldAvailableAmount}`) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 56c928995..c1d3e6bad 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -233,6 +233,8 @@ export class TransactionResolver { const lastTransaction = await getLastTransaction(user.id, ['contribution']) logger.debug(`lastTransaction=${lastTransaction}`) + logger.info(`time for get last transaction: ${new Date().getTime() - now.getTime()} ms`) + const balanceResolver = new BalanceResolver() context.lastTransaction = lastTransaction @@ -251,6 +253,8 @@ export class TransactionResolver { order, ) context.transactionCount = userTransactionsCount + let profilingTime = new Date() + logger.info(`time for getTransactionList: ${profilingTime.getTime() - now.getTime()} ms`) // find involved users; I am involved const involvedUserIds: number[] = [user.id] @@ -305,6 +309,9 @@ export class TransactionResolver { logger.debug(`involvedUserIds=`, involvedUserIds) logger.debug(`involvedRemoteUsers=`, involvedRemoteUsers) + logger.info(`time for collect involved user and load remote user: ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() + // We need to show the name for deleted users for old transactions const involvedDbUsers = await dbUser.find({ where: { id: In(involvedUserIds) }, @@ -313,12 +320,18 @@ export class TransactionResolver { }) const involvedUsers = involvedDbUsers.map((u) => new User(u)) logger.debug(`involvedUsers=`, involvedUsers) + logger.info(`time for load involved user from db: ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() const self = new User(user) const transactions: Transaction[] = [] const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, transactionLinkcount } = await transactionLinkSummary(user.id, now) + + logger.debug(`time for load transactionLinkSummary db: ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() + context.linkCount = transactionLinkcount logger.debug(`transactionLinkcount=${transactionLinkcount}`) context.sumHoldAvailableAmount = sumHoldAvailableAmount @@ -413,7 +426,8 @@ export class TransactionResolver { ).toDecimalPlaces(2, Decimal.ROUND_HALF_UP) } }) - + logger.info(`time for process transaction list and fill in decay db: ${new Date().getTime() - profilingTime.getTime()} ms`) + profilingTime = new Date() // Construct Result return new TransactionList(await balanceResolver.balance(context), transactions) } From 91435656e03b43374006ff48aec3f10b1319aea6 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 11:16:56 +0200 Subject: [PATCH 013/166] add decayLoggingView use in balanceResolver.balance to compress log output --- .../src/graphql/resolver/BalanceResolver.ts | 9 +++++---- backend/src/logging/DecayLogging.view.ts | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 backend/src/logging/DecayLogging.view.ts diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index a702cc08f..8103e0cff 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -15,6 +15,7 @@ import { calculateDecay } from '@/util/decay' import { GdtResolver } from './GdtResolver' import { getLastTransaction } from './util/getLastTransaction' import { transactionLinkSummary } from './util/transactionLinkSummary' +import { DecayLoggingView } from '@/logging/DecayLogging.view' @Resolver() export class BalanceResolver { @@ -85,9 +86,9 @@ export class BalanceResolver { ) logger.info( 'calculatedDecay', - lastTransaction.balance, - lastTransaction.balanceDate, - calculatedDecay, + lastTransaction.balance.toString(), + lastTransaction.balanceDate.toISOString(), + new DecayLoggingView(calculatedDecay), ) // The final balance is reduced by the link amount withheld @@ -115,7 +116,7 @@ export class BalanceResolver { count, linkCount, }) - logger.info('new Balance', balance, balanceGDT, count, linkCount, newBalance) + logger.info('new Balance', balance.toString(), balanceGDT?.toString(), count, linkCount, newBalance.toString()) return newBalance } diff --git a/backend/src/logging/DecayLogging.view.ts b/backend/src/logging/DecayLogging.view.ts new file mode 100644 index 000000000..aef7c6da6 --- /dev/null +++ b/backend/src/logging/DecayLogging.view.ts @@ -0,0 +1,20 @@ +import { Decay } from '@/graphql/model/Decay' +import { AbstractLoggingView } from '@logging/AbstractLogging.view' + +export class DecayLoggingView extends AbstractLoggingView { + public constructor(private self: Decay) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + balance: this.decimalToString(this.self.balance), + decay: this.decimalToString(this.self.decay), + roundedDecay: this.decimalToString(this.self.roundedDecay), + start: this.dateToString(this.self.start), + end: this.dateToString(this.self.end), + duration: this.self.duration + } + } +} From 4f480faf7558f6f4495408234794e9c924f1a4e3 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 11:27:46 +0200 Subject: [PATCH 014/166] lint, add and use BalanceLoggingView in BalanceResolver.balance --- .../src/graphql/resolver/BalanceResolver.ts | 38 +++++++++++++++---- .../graphql/resolver/TransactionResolver.ts | 22 +++++++++-- backend/src/logging/BalanceLogging.view.ts | 18 +++++++++ backend/src/logging/DecayLogging.view.ts | 5 ++- 4 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 backend/src/logging/BalanceLogging.view.ts diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 8103e0cff..e101a36d7 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -8,6 +8,7 @@ import { Resolver, Query, Ctx, Authorized } from 'type-graphql' import { Balance } from '@model/Balance' import { RIGHTS } from '@/auth/RIGHTS' +import { DecayLoggingView } from '@/logging/DecayLogging.view' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { calculateDecay } from '@/util/decay' @@ -15,7 +16,7 @@ import { calculateDecay } from '@/util/decay' import { GdtResolver } from './GdtResolver' import { getLastTransaction } from './util/getLastTransaction' import { transactionLinkSummary } from './util/transactionLinkSummary' -import { DecayLoggingView } from '@/logging/DecayLogging.view' +import { BalanceLoggingView } from '@/logging/BalanceLogging.view' @Resolver() export class BalanceResolver { @@ -40,7 +41,11 @@ export class BalanceResolver { ? context.lastTransaction : await getLastTransaction(user.id) - logger.info(`time for load lastTransaction from db (if not already done): ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.info( + `time for load lastTransaction from db (if not already done): ${ + new Date().getTime() - profilingTime.getTime() + } ms`, + ) profilingTime = new Date() logger.debug(`lastTransaction=${lastTransaction}`) @@ -60,11 +65,13 @@ export class BalanceResolver { context.transactionCount || context.transactionCount === 0 ? context.transactionCount : await dbTransaction.count({ where: { userId: user.id } }) - + logger.debug(`transactionCount=${count}`) - logger.info(`time for count transaction in db: ${new Date().getTime() - profilingTime.getTime()} ms`) - profilingTime = new Date() + logger.info( + `time for count transaction in db: ${new Date().getTime() - profilingTime.getTime()} ms`, + ) + profilingTime = new Date() const linkCount = await dbTransactionLink.count({ where: { @@ -75,7 +82,11 @@ export class BalanceResolver { }) logger.debug(`linkCount=${linkCount}`) - logger.info(`time for count transaction links in db: ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.info( + `time for count transaction links in db: ${ + new Date().getTime() - profilingTime.getTime() + } ms`, + ) profilingTime = new Date() // The decay is always calculated on the last booked transaction @@ -96,7 +107,11 @@ export class BalanceResolver { ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } : await transactionLinkSummary(user.id, now) - logger.info(`time for load transactionLinkSummary from db (if not already done): ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.info( + `time for load transactionLinkSummary from db (if not already done): ${ + new Date().getTime() - profilingTime.getTime() + } ms`, + ) profilingTime = new Date() logger.debug(`context.sumHoldAvailableAmount=${context.sumHoldAvailableAmount}`) @@ -116,7 +131,14 @@ export class BalanceResolver { count, linkCount, }) - logger.info('new Balance', balance.toString(), balanceGDT?.toString(), count, linkCount, newBalance.toString()) + logger.info( + 'new Balance', + balance.toString(), + balanceGDT?.toString(), + count, + linkCount, + new BalanceLoggingView(newBalance), + ) return newBalance } diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index c1d3e6bad..4a4843382 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -309,7 +309,11 @@ export class TransactionResolver { logger.debug(`involvedUserIds=`, involvedUserIds) logger.debug(`involvedRemoteUsers=`, involvedRemoteUsers) - logger.info(`time for collect involved user and load remote user: ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.info( + `time for collect involved user and load remote user: ${ + new Date().getTime() - profilingTime.getTime() + } ms`, + ) profilingTime = new Date() // We need to show the name for deleted users for old transactions @@ -320,7 +324,9 @@ export class TransactionResolver { }) const involvedUsers = involvedDbUsers.map((u) => new User(u)) logger.debug(`involvedUsers=`, involvedUsers) - logger.info(`time for load involved user from db: ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.info( + `time for load involved user from db: ${new Date().getTime() - profilingTime.getTime()} ms`, + ) profilingTime = new Date() const self = new User(user) @@ -329,7 +335,11 @@ export class TransactionResolver { const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, transactionLinkcount } = await transactionLinkSummary(user.id, now) - logger.debug(`time for load transactionLinkSummary db: ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.debug( + `time for load transactionLinkSummary db: ${ + new Date().getTime() - profilingTime.getTime() + } ms`, + ) profilingTime = new Date() context.linkCount = transactionLinkcount @@ -426,7 +436,11 @@ export class TransactionResolver { ).toDecimalPlaces(2, Decimal.ROUND_HALF_UP) } }) - logger.info(`time for process transaction list and fill in decay db: ${new Date().getTime() - profilingTime.getTime()} ms`) + logger.info( + `time for process transaction list and fill in decay db: ${ + new Date().getTime() - profilingTime.getTime() + } ms`, + ) profilingTime = new Date() // Construct Result return new TransactionList(await balanceResolver.balance(context), transactions) diff --git a/backend/src/logging/BalanceLogging.view.ts b/backend/src/logging/BalanceLogging.view.ts new file mode 100644 index 000000000..5d20745d9 --- /dev/null +++ b/backend/src/logging/BalanceLogging.view.ts @@ -0,0 +1,18 @@ +import { Balance } from '@/graphql/model/Balance' +import { AbstractLoggingView } from '@logging/AbstractLogging.view' + +export class BalanceLoggingView extends AbstractLoggingView { + public constructor(private self: Balance) { + super() + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public toJSON(): any { + return { + balance: this.decimalToString(this.self.balance), + balanceGDT: this.self.balanceGDT, + count: this.self.count, + linkCount: this.self.linkCount, + } + } +} diff --git a/backend/src/logging/DecayLogging.view.ts b/backend/src/logging/DecayLogging.view.ts index aef7c6da6..44fd392f9 100644 --- a/backend/src/logging/DecayLogging.view.ts +++ b/backend/src/logging/DecayLogging.view.ts @@ -1,6 +1,7 @@ -import { Decay } from '@/graphql/model/Decay' import { AbstractLoggingView } from '@logging/AbstractLogging.view' +import { Decay } from '@/graphql/model/Decay' + export class DecayLoggingView extends AbstractLoggingView { public constructor(private self: Decay) { super() @@ -14,7 +15,7 @@ export class DecayLoggingView extends AbstractLoggingView { roundedDecay: this.decimalToString(this.self.roundedDecay), start: this.dateToString(this.self.start), end: this.dateToString(this.self.end), - duration: this.self.duration + duration: this.self.duration, } } } From 7f97ff6cf8c39fe54866cc1e4a8ce7d5737f3e28 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 11:39:37 +0200 Subject: [PATCH 015/166] remove unnecessary join which slow down getLastTransaction call --- backend/src/graphql/resolver/TransactionResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 4a4843382..8c1bbf787 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -230,7 +230,7 @@ export class TransactionResolver { logger.info(`transactionList(user=${user.firstName}.${user.lastName}, ${user.emailId})`) // find current balance - const lastTransaction = await getLastTransaction(user.id, ['contribution']) + const lastTransaction = await getLastTransaction(user.id) logger.debug(`lastTransaction=${lastTransaction}`) logger.info(`time for get last transaction: ${new Date().getTime() - now.getTime()} ms`) From d64ceedd04fa8c8c01c2e1a5b35ddf62249b9b3c Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 11:46:22 +0200 Subject: [PATCH 016/166] let fetching gdt sum running parallel --- backend/src/graphql/resolver/BalanceResolver.ts | 10 ++++++---- backend/src/graphql/resolver/TransactionResolver.ts | 7 +++++++ backend/src/server/context.ts | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index e101a36d7..6f303ea2f 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -29,13 +29,15 @@ export class BalanceResolver { logger.addContext('user', user.id) logger.info(`balance(userId=${user.id})...`) - const gdtResolver = new GdtResolver() - const balanceGDT = await gdtResolver.gdtBalance(context) + if(!context.balanceGDT) { + const gdtResolver = new GdtResolver() + context.balanceGDT = await gdtResolver.gdtBalance(context) + } logger.info(`time for load gdt balance: ${new Date().getTime() - now.getTime()} ms`) let profilingTime = new Date() - logger.debug(`balanceGDT=${balanceGDT}`) + logger.debug(`balanceGDT=${context.balanceGDT}`) const lastTransaction = context.lastTransaction ? context.lastTransaction @@ -55,7 +57,7 @@ export class BalanceResolver { logger.info(`no balance found, return Default-Balance!`) return new Balance({ balance: new Decimal(0), - balanceGDT, + balanceGDT: context.balanceGDT, count: 0, linkCount: 0, }) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 8c1bbf787..eba5102e2 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -49,6 +49,7 @@ import { import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { storeForeignUser } from './util/storeForeignUser' import { transactionLinkSummary } from './util/transactionLinkSummary' +import { GdtResolver } from './GdtResolver' export const executeTransaction = async ( amount: Decimal, @@ -229,6 +230,9 @@ export class TransactionResolver { logger.addContext('user', user.id) logger.info(`transactionList(user=${user.firstName}.${user.lastName}, ${user.emailId})`) + const gdtResolver = new GdtResolver() + const balanceGDTPromise = gdtResolver.gdtBalance(context) + // find current balance const lastTransaction = await getLastTransaction(user.id) logger.debug(`lastTransaction=${lastTransaction}`) @@ -442,6 +446,9 @@ export class TransactionResolver { } ms`, ) profilingTime = new Date() + const balanceGDT = await balanceGDTPromise + context.balanceGDT = balanceGDT + // Construct Result return new TransactionList(await balanceResolver.balance(context), transactions) } diff --git a/backend/src/server/context.ts b/backend/src/server/context.ts index 45f0a6c1f..a6038271c 100644 --- a/backend/src/server/context.ts +++ b/backend/src/server/context.ts @@ -16,6 +16,7 @@ export interface Context { gradidoID?: string // hack to use less DB calls for Balance Resolver lastTransaction?: dbTransaction | null + balanceGDT?: number | null transactionCount?: number linkCount?: number sumHoldAvailableAmount?: Decimal From 1df250620bcd6e6722cbbd6a0ed434dd6e0f39dc Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 12:13:18 +0200 Subject: [PATCH 017/166] lint, fix --- backend/src/graphql/resolver/BalanceResolver.ts | 11 +++++++---- backend/src/graphql/resolver/TransactionResolver.ts | 4 ++-- backend/src/logging/BalanceLogging.view.ts | 3 ++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 6f303ea2f..5ee47f7d1 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -8,6 +8,7 @@ import { Resolver, Query, Ctx, Authorized } from 'type-graphql' import { Balance } from '@model/Balance' import { RIGHTS } from '@/auth/RIGHTS' +import { BalanceLoggingView } from '@/logging/BalanceLogging.view' import { DecayLoggingView } from '@/logging/DecayLogging.view' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' @@ -16,7 +17,6 @@ import { calculateDecay } from '@/util/decay' import { GdtResolver } from './GdtResolver' import { getLastTransaction } from './util/getLastTransaction' import { transactionLinkSummary } from './util/transactionLinkSummary' -import { BalanceLoggingView } from '@/logging/BalanceLogging.view' @Resolver() export class BalanceResolver { @@ -29,9 +29,12 @@ export class BalanceResolver { logger.addContext('user', user.id) logger.info(`balance(userId=${user.id})...`) - if(!context.balanceGDT) { + let balanceGDT + if (!context.balanceGDT) { const gdtResolver = new GdtResolver() - context.balanceGDT = await gdtResolver.gdtBalance(context) + balanceGDT = await gdtResolver.gdtBalance(context) + } else { + balanceGDT = context.balanceGDT } logger.info(`time for load gdt balance: ${new Date().getTime() - now.getTime()} ms`) @@ -57,7 +60,7 @@ export class BalanceResolver { logger.info(`no balance found, return Default-Balance!`) return new Balance({ balance: new Decimal(0), - balanceGDT: context.balanceGDT, + balanceGDT, count: 0, linkCount: 0, }) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index eba5102e2..0bbe0b331 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -38,6 +38,7 @@ import { calculateBalance } from '@/util/validate' import { virtualLinkTransaction, virtualDecayTransaction } from '@/util/virtualTransactions' import { BalanceResolver } from './BalanceResolver' +import { GdtResolver } from './GdtResolver' import { getCommunityByIdentifier, getCommunityName, isHomeCommunity } from './util/communities' import { findUserByIdentifier } from './util/findUserByIdentifier' import { getLastTransaction } from './util/getLastTransaction' @@ -49,7 +50,6 @@ import { import { sendTransactionsToDltConnector } from './util/sendTransactionsToDltConnector' import { storeForeignUser } from './util/storeForeignUser' import { transactionLinkSummary } from './util/transactionLinkSummary' -import { GdtResolver } from './GdtResolver' export const executeTransaction = async ( amount: Decimal, @@ -448,7 +448,7 @@ export class TransactionResolver { profilingTime = new Date() const balanceGDT = await balanceGDTPromise context.balanceGDT = balanceGDT - + // Construct Result return new TransactionList(await balanceResolver.balance(context), transactions) } diff --git a/backend/src/logging/BalanceLogging.view.ts b/backend/src/logging/BalanceLogging.view.ts index 5d20745d9..0fa73baf1 100644 --- a/backend/src/logging/BalanceLogging.view.ts +++ b/backend/src/logging/BalanceLogging.view.ts @@ -1,6 +1,7 @@ -import { Balance } from '@/graphql/model/Balance' import { AbstractLoggingView } from '@logging/AbstractLogging.view' +import { Balance } from '@/graphql/model/Balance' + export class BalanceLoggingView extends AbstractLoggingView { public constructor(private self: Balance) { super() From 14300dc9b6cb92e6d68dae4a06a8207ba21f7cf4 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 12:36:16 +0200 Subject: [PATCH 018/166] remove profiling logger messages --- .../src/graphql/resolver/BalanceResolver.ts | 29 ----------------- .../graphql/resolver/TransactionResolver.ts | 32 ++----------------- 2 files changed, 2 insertions(+), 59 deletions(-) diff --git a/backend/src/graphql/resolver/BalanceResolver.ts b/backend/src/graphql/resolver/BalanceResolver.ts index 5ee47f7d1..c023e3510 100644 --- a/backend/src/graphql/resolver/BalanceResolver.ts +++ b/backend/src/graphql/resolver/BalanceResolver.ts @@ -37,22 +37,12 @@ export class BalanceResolver { balanceGDT = context.balanceGDT } - logger.info(`time for load gdt balance: ${new Date().getTime() - now.getTime()} ms`) - let profilingTime = new Date() - logger.debug(`balanceGDT=${context.balanceGDT}`) const lastTransaction = context.lastTransaction ? context.lastTransaction : await getLastTransaction(user.id) - logger.info( - `time for load lastTransaction from db (if not already done): ${ - new Date().getTime() - profilingTime.getTime() - } ms`, - ) - profilingTime = new Date() - logger.debug(`lastTransaction=${lastTransaction}`) // No balance found @@ -73,11 +63,6 @@ export class BalanceResolver { logger.debug(`transactionCount=${count}`) - logger.info( - `time for count transaction in db: ${new Date().getTime() - profilingTime.getTime()} ms`, - ) - profilingTime = new Date() - const linkCount = await dbTransactionLink.count({ where: { userId: user.id, @@ -87,13 +72,6 @@ export class BalanceResolver { }) logger.debug(`linkCount=${linkCount}`) - logger.info( - `time for count transaction links in db: ${ - new Date().getTime() - profilingTime.getTime() - } ms`, - ) - profilingTime = new Date() - // The decay is always calculated on the last booked transaction const calculatedDecay = calculateDecay( lastTransaction.balance, @@ -112,13 +90,6 @@ export class BalanceResolver { ? { sumHoldAvailableAmount: context.sumHoldAvailableAmount } : await transactionLinkSummary(user.id, now) - logger.info( - `time for load transactionLinkSummary from db (if not already done): ${ - new Date().getTime() - profilingTime.getTime() - } ms`, - ) - profilingTime = new Date() - logger.debug(`context.sumHoldAvailableAmount=${context.sumHoldAvailableAmount}`) logger.debug(`sumHoldAvailableAmount=${sumHoldAvailableAmount}`) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 0bbe0b331..11888444c 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -237,8 +237,6 @@ export class TransactionResolver { const lastTransaction = await getLastTransaction(user.id) logger.debug(`lastTransaction=${lastTransaction}`) - logger.info(`time for get last transaction: ${new Date().getTime() - now.getTime()} ms`) - const balanceResolver = new BalanceResolver() context.lastTransaction = lastTransaction @@ -257,8 +255,6 @@ export class TransactionResolver { order, ) context.transactionCount = userTransactionsCount - let profilingTime = new Date() - logger.info(`time for getTransactionList: ${profilingTime.getTime() - now.getTime()} ms`) // find involved users; I am involved const involvedUserIds: number[] = [user.id] @@ -311,14 +307,7 @@ export class TransactionResolver { } } logger.debug(`involvedUserIds=`, involvedUserIds) - logger.debug(`involvedRemoteUsers=`, involvedRemoteUsers) - - logger.info( - `time for collect involved user and load remote user: ${ - new Date().getTime() - profilingTime.getTime() - } ms`, - ) - profilingTime = new Date() + logger.debug(`involvedRemoteUsers=`, involvedRemoteUsers) // We need to show the name for deleted users for old transactions const involvedDbUsers = await dbUser.find({ @@ -328,24 +317,13 @@ export class TransactionResolver { }) const involvedUsers = involvedDbUsers.map((u) => new User(u)) logger.debug(`involvedUsers=`, involvedUsers) - logger.info( - `time for load involved user from db: ${new Date().getTime() - profilingTime.getTime()} ms`, - ) - profilingTime = new Date() - + const self = new User(user) const transactions: Transaction[] = [] const { sumHoldAvailableAmount, sumAmount, lastDate, firstDate, transactionLinkcount } = await transactionLinkSummary(user.id, now) - logger.debug( - `time for load transactionLinkSummary db: ${ - new Date().getTime() - profilingTime.getTime() - } ms`, - ) - profilingTime = new Date() - context.linkCount = transactionLinkcount logger.debug(`transactionLinkcount=${transactionLinkcount}`) context.sumHoldAvailableAmount = sumHoldAvailableAmount @@ -440,12 +418,6 @@ export class TransactionResolver { ).toDecimalPlaces(2, Decimal.ROUND_HALF_UP) } }) - logger.info( - `time for process transaction list and fill in decay db: ${ - new Date().getTime() - profilingTime.getTime() - } ms`, - ) - profilingTime = new Date() const balanceGDT = await balanceGDTPromise context.balanceGDT = balanceGDT From 1cefe2df8e94f71dd8e3280b18dfb432b2faa9da Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 12:41:20 +0200 Subject: [PATCH 019/166] add migration for transactions.user_id index --- backend/src/config/index.ts | 2 +- database/migrations/0082-introduce_gms_registration.ts | 2 +- .../migrations/0085-add_index_transactions_user_id.ts | 10 ++++++++++ dht-node/src/config/index.ts | 2 +- federation/src/config/index.ts | 2 +- 5 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 database/migrations/0085-add_index_transactions_user_id.ts diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 82308a52b..37818d4bd 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -12,7 +12,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0084-introduce_humhub_registration', + DB_VERSION: '0085-add_index_transactions_user_id', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info diff --git a/database/migrations/0082-introduce_gms_registration.ts b/database/migrations/0082-introduce_gms_registration.ts index e02801a4f..b24be2bb5 100644 --- a/database/migrations/0082-introduce_gms_registration.ts +++ b/database/migrations/0082-introduce_gms_registration.ts @@ -50,5 +50,5 @@ export async function downgrade(queryFn: (query: string, values?: any[]) => Prom await queryFn('ALTER TABLE `user_contacts` DROP COLUMN IF EXISTS `gms_publish_email`;') await queryFn('ALTER TABLE `user_contacts` DROP COLUMN IF EXISTS `country_code`;') await queryFn('ALTER TABLE `user_contacts` DROP COLUMN IF EXISTS `gms_publish_phone`;') - await queryFn('ALTER TABLE `communities` DROP COLUMN IF EXISTS `gms_api_key`;') + await queryFn('ALTER TABLE `communities` DROP COLUMN IF EXISTS `gms_api_key`;') } diff --git a/database/migrations/0085-add_index_transactions_user_id.ts b/database/migrations/0085-add_index_transactions_user_id.ts new file mode 100644 index 000000000..c4cb02431 --- /dev/null +++ b/database/migrations/0085-add_index_transactions_user_id.ts @@ -0,0 +1,10 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('CREATE INDEX user_id ON transactions (user_id);') +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('DROP INDEX user_id ON transactions;') +} diff --git a/dht-node/src/config/index.ts b/dht-node/src/config/index.ts index f557eee83..5c6910d45 100644 --- a/dht-node/src/config/index.ts +++ b/dht-node/src/config/index.ts @@ -4,7 +4,7 @@ import dotenv from 'dotenv' dotenv.config() const constants = { - DB_VERSION: '0084-introduce_humhub_registration', + DB_VERSION: '0085-add_index_transactions_user_id', LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info LOG_LEVEL: process.env.LOG_LEVEL ?? 'info', diff --git a/federation/src/config/index.ts b/federation/src/config/index.ts index 26b727841..b66ed3974 100644 --- a/federation/src/config/index.ts +++ b/federation/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0084-introduce_humhub_registration', + DB_VERSION: '0085-add_index_transactions_user_id', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info From 2e26ca4cd72c2875dc40e45e35c14dc9a9fbb599 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Wed, 19 Jun 2024 13:18:00 +0200 Subject: [PATCH 020/166] lint --- backend/src/graphql/resolver/TransactionResolver.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/graphql/resolver/TransactionResolver.ts b/backend/src/graphql/resolver/TransactionResolver.ts index 11888444c..1889e3be0 100644 --- a/backend/src/graphql/resolver/TransactionResolver.ts +++ b/backend/src/graphql/resolver/TransactionResolver.ts @@ -307,7 +307,7 @@ export class TransactionResolver { } } logger.debug(`involvedUserIds=`, involvedUserIds) - logger.debug(`involvedRemoteUsers=`, involvedRemoteUsers) + logger.debug(`involvedRemoteUsers=`, involvedRemoteUsers) // We need to show the name for deleted users for old transactions const involvedDbUsers = await dbUser.find({ @@ -317,7 +317,7 @@ export class TransactionResolver { }) const involvedUsers = involvedDbUsers.map((u) => new User(u)) logger.debug(`involvedUsers=`, involvedUsers) - + const self = new User(user) const transactions: Transaction[] = [] From d6f58ef7d9a7e0ef5fef3cf865e6de39767bb2b7 Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Mon, 24 Jun 2024 09:01:08 +0200 Subject: [PATCH 021/166] refactor a bit to remove strange behavior --- .../Federation/CommunityVisualizeItem.vue | 2 +- admin/src/components/Federation/GMSApiKey.vue | 12 +++- admin/src/components/input/Coordinates.vue | 56 +++++++++++++------ admin/src/components/input/EditableGroup.vue | 1 + admin/src/locales/de.json | 5 +- admin/src/locales/en.json | 9 +-- 6 files changed, 58 insertions(+), 27 deletions(-) diff --git a/admin/src/components/Federation/CommunityVisualizeItem.vue b/admin/src/components/Federation/CommunityVisualizeItem.vue index edabc3a70..9ec303c34 100644 --- a/admin/src/components/Federation/CommunityVisualizeItem.vue +++ b/admin/src/components/Federation/CommunityVisualizeItem.vue @@ -31,7 +31,7 @@ @reset="resetHomeCommunityEditable" > From 968c7ceac34df8fdc5de0fd361f85b682a5238a3 Mon Sep 17 00:00:00 2001 From: Kamila Date: Fri, 19 Jul 2024 14:31:08 +0200 Subject: [PATCH 053/166] navbar adjustments --- admin/src/components/NavBar.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/src/components/NavBar.vue b/admin/src/components/NavBar.vue index bad81f79a..6d6450989 100644 --- a/admin/src/components/NavBar.vue +++ b/admin/src/components/NavBar.vue @@ -12,7 +12,7 @@ {{ $t('navbar.user_search') }} {{ $t('creation') }} - + {{ openCreations.value }} @@ -44,6 +44,7 @@ import { BNavbarBrand, BBadge, BNavbarToggle, + vBColorMode, } from 'bootstrap-vue-next' const store = useStore() From ff86af18b2168af669dc60c09dd4027a3ae1a065 Mon Sep 17 00:00:00 2001 From: Kamila Date: Mon, 22 Jul 2024 09:44:05 +0200 Subject: [PATCH 054/166] add depenedencies --- admin/package.json | 1 + admin/yarn.lock | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/admin/package.json b/admin/package.json index dcfab16ac..93c64c286 100644 --- a/admin/package.json +++ b/admin/package.json @@ -50,6 +50,7 @@ "portal-vue": "3.0.0", "qrcanvas-vue": "3.0.0", "regenerator-runtime": "^0.13.9", + "sass": "^1.77.8", "vite": "3.2.10", "vite-plugin-commonjs": "^0.10.1", "vue": "3.4.31", diff --git a/admin/yarn.lock b/admin/yarn.lock index 33fa8e107..798fa4f3c 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -3824,7 +3824,7 @@ char-regex@^2.0.0: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e" integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw== -chokidar@^3.6.0: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -5832,6 +5832,11 @@ ignore@^5.1.1, ignore@^5.1.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +immutable@^4.0.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447" + integrity sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -8924,6 +8929,15 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sass@^1.77.8: + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + saxes@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" @@ -9147,16 +9161,16 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" From 61bd9f3aa88f335ff4b2703aba65cad803b06e1f Mon Sep 17 00:00:00 2001 From: Kamila Date: Mon, 22 Jul 2024 09:44:40 +0200 Subject: [PATCH 055/166] style adjustment in footer --- admin/src/components/ContentFooter.vue | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/admin/src/components/ContentFooter.vue b/admin/src/components/ContentFooter.vue index a9afe90d7..d1591e242 100644 --- a/admin/src/components/ContentFooter.vue +++ b/admin/src/components/ContentFooter.vue @@ -32,17 +32,16 @@ import CONFIG from '../config' import { BTr } from 'bootstrap-vue-next' - const year = new Date().getFullYear() const version = CONFIG.APP_VERSION const hash = CONFIG.BUILD_COMMIT const shortHash = CONFIG.BUILD_COMMIT_SHORT - From baaf06ca974359510343e244c09f62f24fc8c689 Mon Sep 17 00:00:00 2001 From: Kamila Date: Mon, 22 Jul 2024 09:57:23 +0200 Subject: [PATCH 056/166] composable adjustments --- admin/src/composables/useCreationMonths.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/admin/src/composables/useCreationMonths.js b/admin/src/composables/useCreationMonths.js index f0eeaea19..7e87a7a07 100644 --- a/admin/src/composables/useCreationMonths.js +++ b/admin/src/composables/useCreationMonths.js @@ -1,8 +1,11 @@ import { ref, computed, watch } from 'vue' import { adminOpenCreations } from '../graphql/adminOpenCreations' import { useQuery } from '@vue/apollo-composable' +import { useI18n } from 'vue-i18n' export default () => { + const { d } = useI18n() + const creation = ref([1000, 1000, 1000]) const userId = ref(0) @@ -19,10 +22,10 @@ export default () => { const result = [] creationDates.value.forEach((date) => { result.push({ - short: $d(date, 'month'), - long: $d(date, 'short'), - year: $d(date, 'year'), - date: $d(date, 'short', 'en'), + short: d(date, 'month'), + long: d(date, 'long'), + year: d(date, 'year'), + date: d(date, 'short', 'en'), }) }) return result @@ -38,7 +41,7 @@ export default () => { } const creationLabel = () => { - return creationDates.value.map((date) => $d(date, 'monthShort')).join('|') + return creationDates.value.map((date) => d(date, 'monthShort')).join(' | ') } const { result, error } = useQuery(adminOpenCreations, { userId }, { fetchPolicy: 'no-cache' }) From d2f07ee0c4af4a80cf3421c4e3b62bb82836def7 Mon Sep 17 00:00:00 2001 From: Kamila Date: Mon, 22 Jul 2024 12:51:57 +0200 Subject: [PATCH 057/166] update node version --- admin/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/Dockerfile b/admin/Dockerfile index 029339f10..0658c2053 100644 --- a/admin/Dockerfile +++ b/admin/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # BASE ########################################################################### ################################################################################## -FROM node:14.17.0-alpine3.10 as base +FROM node:16-alpine3.14 as base # ENVs (available in production aswell, can be overwritten by commandline or env file) ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame From a35ce52cc91d939ce28186888134073d10b77edc Mon Sep 17 00:00:00 2001 From: Kamila Date: Mon, 22 Jul 2024 14:57:50 +0200 Subject: [PATCH 058/166] rework search and pagination --- admin/src/components/UserQuery.vue | 25 +++++++++++++-------- admin/src/pages/UserSearch.vue | 35 +++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/admin/src/components/UserQuery.vue b/admin/src/components/UserQuery.vue index f6677fa1a..045ad1ff9 100644 --- a/admin/src/components/UserQuery.vue +++ b/admin/src/components/UserQuery.vue @@ -7,7 +7,7 @@ v-model="currentValue" :placeholder="placeholderText" /> -
+
@@ -22,25 +22,32 @@ import { useI18n } from 'vue-i18n' import { BInputGroupText, BFormInput } from 'bootstrap-vue-next' const props = defineProps({ - value: { type: String, default: '' }, + modelValue: { type: String, default: '' }, placeholder: { type: String, default: '' }, }) -const emit = defineEmits(['input']) +const emit = defineEmits(['update:modelValue']) const { t } = useI18n() -const currentValue = ref(props.value) - const placeholderText = computed(() => props.placeholder || t('user_search')) -const clearValue = () => { +const onClear = () => { currentValue.value = '' } +const currentValue = ref(props.modelValue) + watch(currentValue, (newValue) => { - if (props.value !== newValue) { - emit('input', newValue) - } + emit('update:modelValue', newValue) }) + +watch( + () => props.modelValue, + (newValue) => { + if (newValue !== currentValue.value) { + currentValue.value = newValue + } + }, +) diff --git a/admin/src/pages/UserSearch.vue b/admin/src/pages/UserSearch.vue index 8aa84c086..a47fef58e 100644 --- a/admin/src/pages/UserSearch.vue +++ b/admin/src/pages/UserSearch.vue @@ -32,13 +32,13 @@ @updateDeletedAt="updateDeletedAt" />
@@ -65,7 +65,7 @@ const currentPage = ref(1) const perPage = ref(25) const response = ref() -const { creationDates, creationLabel } = useCreationMonths() +const { creationLabel } = useCreationMonths() const { result, refetch } = useQuery(searchUsers, { query: criteria.value, @@ -91,7 +91,6 @@ const updateRoles = (userId, roles) => { const updateDeletedAt = (userId, deletedAt) => { searchResult.value.find((obj) => obj.userId === userId).deletedAt = deletedAt // toastSuccess(deletedAt ? $t('user_deleted') : $t('user_recovered')) - refetch() } const unconfirmedRegisterMails = () => { @@ -122,8 +121,32 @@ const fields = computed(() => [ { key: 'status', label: t('status') }, ]) -watch(currentPage, refetch) -watch(criteria, refetch) +watch( + () => currentPage.value, + async (newValue, oldValue) => { + if (newValue !== oldValue) { + await refetch({ + query: criteria.value, + filters: filters, + currentPage: newValue, + pageSize: perPage.value, + order: 'DESC', + fetchPolicy: 'no-cache', + }) + } + }, +) + +watch( + () => criteria.value, + async (newValue, oldValue) => { + if (newValue !== oldValue) { + await refetch({ + query: newValue, + }) + } + }, +) diff --git a/admin/src/components/ContributionLink/ContributionLink.vue b/admin/src/components/ContributionLink/ContributionLink.vue index 027eb35d7..3b8f5f74f 100644 --- a/admin/src/components/ContributionLink/ContributionLink.vue +++ b/admin/src/components/ContributionLink/ContributionLink.vue @@ -10,21 +10,21 @@ > {{ $t('math.plus') }} {{ $t('contributionLink.newContributionLink') }} - +

{{ $t('contributionLink.contributionLinks') }}

@@ -33,9 +33,9 @@
{{ $t('contributionLink.noContributionLinks') }}
@@ -62,6 +62,7 @@ export default { required: true, }, }, + emits: ['get-contribution-links'], data: function () { return { visible: false, diff --git a/admin/src/components/ContributionLink/ContributionLinkForm.vue b/admin/src/components/ContributionLink/ContributionLinkForm.vue index f8e3d0f1f..239d77c83 100644 --- a/admin/src/components/ContributionLink/ContributionLinkForm.vue +++ b/admin/src/components/ContributionLink/ContributionLinkForm.vue @@ -1,13 +1,13 @@