Merge branch 'master' into 2274-feature-concept-manuel-user-registration-for-admins

This commit is contained in:
clauspeterhuebner 2022-10-21 14:00:03 +02:00 committed by GitHub
commit a78f6ab8b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 198 additions and 13 deletions

View File

@ -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).
#### [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)
> 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)
- 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)

View File

@ -3,7 +3,7 @@
"description": "Administraion Interface for Gradido",
"main": "index.js",
"author": "Moriz Wahl",
"version": "1.13.0",
"version": "1.13.1",
"license": "Apache-2.0",
"private": false,
"scripts": {

View File

@ -1,6 +1,6 @@
{
"name": "gradido-backend",
"version": "1.13.0",
"version": "1.13.1",
"description": "Gradido unified backend providing an API-Service for Gradido Transactions",
"main": "src/index.ts",
"repository": "https://github.com/gradido/gradido/backend",

View File

@ -10,7 +10,7 @@ Decimal.set({
})
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
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info
@ -67,7 +67,7 @@ const loginServer = {
const email = {
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_USERNAME: process.env.EMAIL_USERNAME || 'gradido_email',
EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net',

View File

@ -17,6 +17,7 @@ import {
setUserRole,
deleteUser,
unDeleteUser,
createContribution,
adminCreateContribution,
adminCreateContributions,
adminUpdateContribution,
@ -77,6 +78,7 @@ afterAll(async () => {
let admin: User
let user: User
let creation: Contribution | void
let result: any
describe('AdminResolver', () => {
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', () => {
it('returns true', async () => {
await expect(

View File

@ -400,13 +400,24 @@ export class AdminResolver {
@Authorized([RIGHTS.ADMIN_DELETE_CONTRIBUTION])
@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)
if (!contribution) {
logger.error(`Contribution not found for given id: ${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.deletedBy = moderator.id
await contribution.save()
const res = await contribution.softRemove()
return !!res

View File

@ -91,6 +91,7 @@ export class ContributionResolver {
}
contribution.contributionStatus = ContributionStatus.DELETED
contribution.deletedBy = user.id
contribution.deletedAt = new Date()
await contribution.save()
@ -127,6 +128,7 @@ export class ContributionResolver {
.from(dbContribution, 'c')
.leftJoinAndSelect('c.messages', 'm')
.where(where)
.withDeleted()
.orderBy('c.createdAt', order)
.limit(pageSize)
.offset((currentPage - 1) * pageSize)

View File

@ -26,7 +26,7 @@ describe('sendAddedContributionMessageEmail', () => {
it('calls sendEMail', () => {
expect(sendEMail).toBeCalledWith({
to: `Bibi Bloxberg <bibi@bloxberg.de>`,
subject: 'Gradido Frage zur Schöpfung',
subject: 'Rückfrage zu Deinem Gemeinwohl-Beitrag',
text:
expect.stringContaining('Hallo Bibi Bloxberg') &&
expect.stringContaining('Peter Lustig') &&

View File

@ -29,6 +29,7 @@ describe('sendEMail', () => {
let result: boolean
describe('config email is false', () => {
beforeEach(async () => {
jest.clearAllMocks()
result = await sendEMail({
to: 'receiver@mail.org',
cc: 'support@gradido.net',
@ -48,6 +49,7 @@ describe('sendEMail', () => {
describe('config email is true', () => {
beforeEach(async () => {
jest.clearAllMocks()
CONFIG.EMAIL = true
result = await sendEMail({
to: 'receiver@mail.org',
@ -73,7 +75,7 @@ describe('sendEMail', () => {
it('calls sendMail of transporter', () => {
expect((createTransport as jest.Mock).mock.results[0].value.sendMail).toBeCalledWith({
from: `Gradido (nicht antworten) <${CONFIG.EMAIL_SENDER}>`,
to: `${CONFIG.EMAIL_TEST_RECEIVER}`,
to: 'receiver@mail.org',
cc: 'support@gradido.net',
subject: 'Subject',
text: 'Text text text',
@ -84,4 +86,28 @@ describe('sendEMail', () => {
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',
})
})
})
})

View File

@ -1,6 +1,6 @@
export const contributionMessageReceived = {
de: {
subject: 'Gradido Frage zur Schöpfung',
subject: 'Rückfrage zu Deinem Gemeinwohl-Beitrag',
text: (data: {
senderFirstName: string
senderLastName: string

View File

@ -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[]
}

View File

@ -1 +1 @@
export { Contribution } from './0047-messages_tables/Contribution'
export { Contribution } from './0051-add_delete_by_to_contributions/Contribution'

View 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\`;`)
}

View File

@ -1,6 +1,6 @@
{
"name": "gradido-database",
"version": "1.13.0",
"version": "1.13.1",
"description": "Gradido Database Tool to execute database migrations",
"main": "src/index.ts",
"repository": "https://github.com/gradido/gradido/database",

View File

@ -1,6 +1,6 @@
{
"name": "bootstrap-vue-gradido-wallet",
"version": "1.13.0",
"version": "1.13.1",
"private": true,
"scripts": {
"start": "node run/server.js",

View File

@ -34,7 +34,7 @@
"contribution": {
"activity": "Tätigkeit",
"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.",
"confirm": "bestätigt",
"in_progress": "Es gibt eine Rückfrage der Moderatoren.",

View File

@ -1,6 +1,6 @@
{
"name": "gradido",
"version": "1.13.0",
"version": "1.13.1",
"description": "Gradido",
"main": "index.js",
"repository": "git@github.com:gradido/gradido.git",