mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into 2274-feature-concept-manuel-user-registration-for-admins
This commit is contained in:
commit
a78f6ab8b6
@ -4,8 +4,16 @@ 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).
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||||
|
|
||||||
|
#### [1.13.1](https://github.com/gradido/gradido/compare/1.13.0...1.13.1)
|
||||||
|
|
||||||
|
- Fix: correctly evaluate to EMAIL_TEST_MODE to false [`#2273`](https://github.com/gradido/gradido/pull/2273)
|
||||||
|
- Refactor: Contribution resolver logs and events [`#2231`](https://github.com/gradido/gradido/pull/2231)
|
||||||
|
|
||||||
#### [1.13.0](https://github.com/gradido/gradido/compare/1.12.1...1.13.0)
|
#### [1.13.0](https://github.com/gradido/gradido/compare/1.12.1...1.13.0)
|
||||||
|
|
||||||
|
> 18 October 2022
|
||||||
|
|
||||||
|
- release: Version 1.13.0 [`#2269`](https://github.com/gradido/gradido/pull/2269)
|
||||||
- fix: Linked User Email in Transaction List [`#2268`](https://github.com/gradido/gradido/pull/2268)
|
- fix: Linked User Email in Transaction List [`#2268`](https://github.com/gradido/gradido/pull/2268)
|
||||||
- concept capturing alias [`#2148`](https://github.com/gradido/gradido/pull/2148)
|
- concept capturing alias [`#2148`](https://github.com/gradido/gradido/pull/2148)
|
||||||
- fix: 🍰 Daily Redeem Of Contribution Link [`#2265`](https://github.com/gradido/gradido/pull/2265)
|
- fix: 🍰 Daily Redeem Of Contribution Link [`#2265`](https://github.com/gradido/gradido/pull/2265)
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"description": "Administraion Interface for Gradido",
|
"description": "Administraion Interface for Gradido",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "Moriz Wahl",
|
"author": "Moriz Wahl",
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gradido-backend",
|
"name": "gradido-backend",
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"description": "Gradido unified backend providing an API-Service for Gradido Transactions",
|
"description": "Gradido unified backend providing an API-Service for Gradido Transactions",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": "https://github.com/gradido/gradido/backend",
|
"repository": "https://github.com/gradido/gradido/backend",
|
||||||
|
|||||||
@ -10,7 +10,7 @@ Decimal.set({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const constants = {
|
const constants = {
|
||||||
DB_VERSION: '0050-add_messageId_to_event_protocol',
|
DB_VERSION: '0051-add_delete_by_to_contributions',
|
||||||
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
|
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
|
||||||
LOG4JS_CONFIG: 'log4js-config.json',
|
LOG4JS_CONFIG: 'log4js-config.json',
|
||||||
// default log level on production should be info
|
// default log level on production should be info
|
||||||
@ -67,7 +67,7 @@ const loginServer = {
|
|||||||
|
|
||||||
const email = {
|
const email = {
|
||||||
EMAIL: process.env.EMAIL === 'true' || false,
|
EMAIL: process.env.EMAIL === 'true' || false,
|
||||||
EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || 'false',
|
EMAIL_TEST_MODUS: process.env.EMAIL_TEST_MODUS === 'true' || false,
|
||||||
EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER || 'stage1@gradido.net',
|
EMAIL_TEST_RECEIVER: process.env.EMAIL_TEST_RECEIVER || 'stage1@gradido.net',
|
||||||
EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'gradido_email',
|
EMAIL_USERNAME: process.env.EMAIL_USERNAME || 'gradido_email',
|
||||||
EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net',
|
EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net',
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import {
|
|||||||
setUserRole,
|
setUserRole,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
unDeleteUser,
|
unDeleteUser,
|
||||||
|
createContribution,
|
||||||
adminCreateContribution,
|
adminCreateContribution,
|
||||||
adminCreateContributions,
|
adminCreateContributions,
|
||||||
adminUpdateContribution,
|
adminUpdateContribution,
|
||||||
@ -77,6 +78,7 @@ afterAll(async () => {
|
|||||||
let admin: User
|
let admin: User
|
||||||
let user: User
|
let user: User
|
||||||
let creation: Contribution | void
|
let creation: Contribution | void
|
||||||
|
let result: any
|
||||||
|
|
||||||
describe('AdminResolver', () => {
|
describe('AdminResolver', () => {
|
||||||
describe('set user role', () => {
|
describe('set user role', () => {
|
||||||
@ -1365,6 +1367,38 @@ describe('AdminResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('admin deletes own user contribution', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await query({
|
||||||
|
query: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
result = await mutate({
|
||||||
|
mutation: createContribution,
|
||||||
|
variables: {
|
||||||
|
amount: 100.0,
|
||||||
|
memo: 'Test env contribution',
|
||||||
|
creationDate: new Date().toString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: adminDeleteContribution,
|
||||||
|
variables: {
|
||||||
|
id: result.data.createContribution.id,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('Own contribution can not be deleted as admin')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('creation id does exist', () => {
|
describe('creation id does exist', () => {
|
||||||
it('returns true', async () => {
|
it('returns true', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
|
|||||||
@ -400,13 +400,24 @@ export class AdminResolver {
|
|||||||
|
|
||||||
@Authorized([RIGHTS.ADMIN_DELETE_CONTRIBUTION])
|
@Authorized([RIGHTS.ADMIN_DELETE_CONTRIBUTION])
|
||||||
@Mutation(() => Boolean)
|
@Mutation(() => Boolean)
|
||||||
async adminDeleteContribution(@Arg('id', () => Int) id: number): Promise<boolean> {
|
async adminDeleteContribution(
|
||||||
|
@Arg('id', () => Int) id: number,
|
||||||
|
@Ctx() context: Context,
|
||||||
|
): Promise<boolean> {
|
||||||
const contribution = await DbContribution.findOne(id)
|
const contribution = await DbContribution.findOne(id)
|
||||||
if (!contribution) {
|
if (!contribution) {
|
||||||
logger.error(`Contribution not found for given id: ${id}`)
|
logger.error(`Contribution not found for given id: ${id}`)
|
||||||
throw new Error('Contribution not found for given id.')
|
throw new Error('Contribution not found for given id.')
|
||||||
}
|
}
|
||||||
|
const moderator = getUser(context)
|
||||||
|
if (
|
||||||
|
contribution.contributionType === ContributionType.USER &&
|
||||||
|
contribution.userId === moderator.id
|
||||||
|
) {
|
||||||
|
throw new Error('Own contribution can not be deleted as admin')
|
||||||
|
}
|
||||||
contribution.contributionStatus = ContributionStatus.DELETED
|
contribution.contributionStatus = ContributionStatus.DELETED
|
||||||
|
contribution.deletedBy = moderator.id
|
||||||
await contribution.save()
|
await contribution.save()
|
||||||
const res = await contribution.softRemove()
|
const res = await contribution.softRemove()
|
||||||
return !!res
|
return !!res
|
||||||
|
|||||||
@ -91,6 +91,7 @@ export class ContributionResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contribution.contributionStatus = ContributionStatus.DELETED
|
contribution.contributionStatus = ContributionStatus.DELETED
|
||||||
|
contribution.deletedBy = user.id
|
||||||
contribution.deletedAt = new Date()
|
contribution.deletedAt = new Date()
|
||||||
await contribution.save()
|
await contribution.save()
|
||||||
|
|
||||||
@ -127,6 +128,7 @@ export class ContributionResolver {
|
|||||||
.from(dbContribution, 'c')
|
.from(dbContribution, 'c')
|
||||||
.leftJoinAndSelect('c.messages', 'm')
|
.leftJoinAndSelect('c.messages', 'm')
|
||||||
.where(where)
|
.where(where)
|
||||||
|
.withDeleted()
|
||||||
.orderBy('c.createdAt', order)
|
.orderBy('c.createdAt', order)
|
||||||
.limit(pageSize)
|
.limit(pageSize)
|
||||||
.offset((currentPage - 1) * pageSize)
|
.offset((currentPage - 1) * pageSize)
|
||||||
|
|||||||
@ -26,7 +26,7 @@ describe('sendAddedContributionMessageEmail', () => {
|
|||||||
it('calls sendEMail', () => {
|
it('calls sendEMail', () => {
|
||||||
expect(sendEMail).toBeCalledWith({
|
expect(sendEMail).toBeCalledWith({
|
||||||
to: `Bibi Bloxberg <bibi@bloxberg.de>`,
|
to: `Bibi Bloxberg <bibi@bloxberg.de>`,
|
||||||
subject: 'Gradido Frage zur Schöpfung',
|
subject: 'Rückfrage zu Deinem Gemeinwohl-Beitrag',
|
||||||
text:
|
text:
|
||||||
expect.stringContaining('Hallo Bibi Bloxberg') &&
|
expect.stringContaining('Hallo Bibi Bloxberg') &&
|
||||||
expect.stringContaining('Peter Lustig') &&
|
expect.stringContaining('Peter Lustig') &&
|
||||||
|
|||||||
@ -29,6 +29,7 @@ describe('sendEMail', () => {
|
|||||||
let result: boolean
|
let result: boolean
|
||||||
describe('config email is false', () => {
|
describe('config email is false', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
result = await sendEMail({
|
result = await sendEMail({
|
||||||
to: 'receiver@mail.org',
|
to: 'receiver@mail.org',
|
||||||
cc: 'support@gradido.net',
|
cc: 'support@gradido.net',
|
||||||
@ -48,6 +49,7 @@ describe('sendEMail', () => {
|
|||||||
|
|
||||||
describe('config email is true', () => {
|
describe('config email is true', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
CONFIG.EMAIL = true
|
CONFIG.EMAIL = true
|
||||||
result = await sendEMail({
|
result = await sendEMail({
|
||||||
to: 'receiver@mail.org',
|
to: 'receiver@mail.org',
|
||||||
@ -73,7 +75,7 @@ describe('sendEMail', () => {
|
|||||||
it('calls sendMail of transporter', () => {
|
it('calls sendMail of transporter', () => {
|
||||||
expect((createTransport as jest.Mock).mock.results[0].value.sendMail).toBeCalledWith({
|
expect((createTransport as jest.Mock).mock.results[0].value.sendMail).toBeCalledWith({
|
||||||
from: `Gradido (nicht antworten) <${CONFIG.EMAIL_SENDER}>`,
|
from: `Gradido (nicht antworten) <${CONFIG.EMAIL_SENDER}>`,
|
||||||
to: `${CONFIG.EMAIL_TEST_RECEIVER}`,
|
to: 'receiver@mail.org',
|
||||||
cc: 'support@gradido.net',
|
cc: 'support@gradido.net',
|
||||||
subject: 'Subject',
|
subject: 'Subject',
|
||||||
text: 'Text text text',
|
text: 'Text text text',
|
||||||
@ -84,4 +86,28 @@ describe('sendEMail', () => {
|
|||||||
expect(result).toBeTruthy()
|
expect(result).toBeTruthy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('with email EMAIL_TEST_MODUS true', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
CONFIG.EMAIL = true
|
||||||
|
CONFIG.EMAIL_TEST_MODUS = true
|
||||||
|
result = await sendEMail({
|
||||||
|
to: 'receiver@mail.org',
|
||||||
|
cc: 'support@gradido.net',
|
||||||
|
subject: 'Subject',
|
||||||
|
text: 'Text text text',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls sendMail of transporter with faked to', () => {
|
||||||
|
expect((createTransport as jest.Mock).mock.results[0].value.sendMail).toBeCalledWith({
|
||||||
|
from: `Gradido (nicht antworten) <${CONFIG.EMAIL_SENDER}>`,
|
||||||
|
to: CONFIG.EMAIL_TEST_RECEIVER,
|
||||||
|
cc: 'support@gradido.net',
|
||||||
|
subject: 'Subject',
|
||||||
|
text: 'Text text text',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export const contributionMessageReceived = {
|
export const contributionMessageReceived = {
|
||||||
de: {
|
de: {
|
||||||
subject: 'Gradido Frage zur Schöpfung',
|
subject: 'Rückfrage zu Deinem Gemeinwohl-Beitrag',
|
||||||
text: (data: {
|
text: (data: {
|
||||||
senderFirstName: string
|
senderFirstName: string
|
||||||
senderLastName: string
|
senderLastName: string
|
||||||
|
|||||||
@ -0,0 +1,92 @@
|
|||||||
|
import Decimal from 'decimal.js-light'
|
||||||
|
import {
|
||||||
|
BaseEntity,
|
||||||
|
Column,
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
DeleteDateColumn,
|
||||||
|
JoinColumn,
|
||||||
|
ManyToOne,
|
||||||
|
OneToMany,
|
||||||
|
} from 'typeorm'
|
||||||
|
import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer'
|
||||||
|
import { User } from '../User'
|
||||||
|
import { ContributionMessage } from '../ContributionMessage'
|
||||||
|
|
||||||
|
@Entity('contributions')
|
||||||
|
export class Contribution extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: false, name: 'user_id' })
|
||||||
|
userId: number
|
||||||
|
|
||||||
|
@ManyToOne(() => User, (user) => user.contributions)
|
||||||
|
@JoinColumn({ name: 'user_id' })
|
||||||
|
user: User
|
||||||
|
|
||||||
|
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP', name: 'created_at' })
|
||||||
|
createdAt: Date
|
||||||
|
|
||||||
|
@Column({ type: 'datetime', nullable: false, name: 'contribution_date' })
|
||||||
|
contributionDate: Date
|
||||||
|
|
||||||
|
@Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' })
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'decimal',
|
||||||
|
precision: 40,
|
||||||
|
scale: 20,
|
||||||
|
nullable: false,
|
||||||
|
transformer: DecimalTransformer,
|
||||||
|
})
|
||||||
|
amount: Decimal
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: true, name: 'moderator_id' })
|
||||||
|
moderatorId: number
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: true, name: 'contribution_link_id' })
|
||||||
|
contributionLinkId: number
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: true, name: 'confirmed_by' })
|
||||||
|
confirmedBy: number
|
||||||
|
|
||||||
|
@Column({ nullable: true, name: 'confirmed_at' })
|
||||||
|
confirmedAt: Date
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: true, name: 'denied_by' })
|
||||||
|
deniedBy: number
|
||||||
|
|
||||||
|
@Column({ nullable: true, name: 'denied_at' })
|
||||||
|
deniedAt: Date
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
name: 'contribution_type',
|
||||||
|
length: 12,
|
||||||
|
nullable: false,
|
||||||
|
collation: 'utf8mb4_unicode_ci',
|
||||||
|
})
|
||||||
|
contributionType: string
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
name: 'contribution_status',
|
||||||
|
length: 12,
|
||||||
|
nullable: false,
|
||||||
|
collation: 'utf8mb4_unicode_ci',
|
||||||
|
})
|
||||||
|
contributionStatus: string
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: true, name: 'transaction_id' })
|
||||||
|
transactionId: number
|
||||||
|
|
||||||
|
@DeleteDateColumn({ name: 'deleted_at' })
|
||||||
|
deletedAt: Date | null
|
||||||
|
|
||||||
|
@DeleteDateColumn({ unsigned: true, nullable: true, name: 'deleted_by' })
|
||||||
|
deletedBy: number
|
||||||
|
|
||||||
|
@OneToMany(() => ContributionMessage, (message) => message.contribution)
|
||||||
|
@JoinColumn({ name: 'contribution_id' })
|
||||||
|
messages?: ContributionMessage[]
|
||||||
|
}
|
||||||
@ -1 +1 @@
|
|||||||
export { Contribution } from './0047-messages_tables/Contribution'
|
export { Contribution } from './0051-add_delete_by_to_contributions/Contribution'
|
||||||
|
|||||||
12
database/migrations/0051-add_delete_by_to_contributions.ts
Normal file
12
database/migrations/0051-add_delete_by_to_contributions.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* 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<Array<any>>) {
|
||||||
|
await queryFn(
|
||||||
|
`ALTER TABLE \`contributions\` ADD COLUMN \`deleted_by\` int(10) unsigned DEFAULT NULL;`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`ALTER TABLE \`contributions\` DROP COLUMN \`deleted_by\`;`)
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gradido-database",
|
"name": "gradido-database",
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"description": "Gradido Database Tool to execute database migrations",
|
"description": "Gradido Database Tool to execute database migrations",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": "https://github.com/gradido/gradido/database",
|
"repository": "https://github.com/gradido/gradido/database",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bootstrap-vue-gradido-wallet",
|
"name": "bootstrap-vue-gradido-wallet",
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node run/server.js",
|
"start": "node run/server.js",
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
"contribution": {
|
"contribution": {
|
||||||
"activity": "Tätigkeit",
|
"activity": "Tätigkeit",
|
||||||
"alert": {
|
"alert": {
|
||||||
"answerQuestion": "Bitte beantworte die Nachfrage",
|
"answerQuestion": "Bitte beantworte die Rückfrage!",
|
||||||
"communityNoteList": "Hier findest du alle eingereichten und bestätigten Beiträge von allen Mitgliedern aus dieser Gemeinschaft.",
|
"communityNoteList": "Hier findest du alle eingereichten und bestätigten Beiträge von allen Mitgliedern aus dieser Gemeinschaft.",
|
||||||
"confirm": "bestätigt",
|
"confirm": "bestätigt",
|
||||||
"in_progress": "Es gibt eine Rückfrage der Moderatoren.",
|
"in_progress": "Es gibt eine Rückfrage der Moderatoren.",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gradido",
|
"name": "gradido",
|
||||||
"version": "1.13.0",
|
"version": "1.13.1",
|
||||||
"description": "Gradido",
|
"description": "Gradido",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": "git@github.com:gradido/gradido.git",
|
"repository": "git@github.com:gradido/gradido.git",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user