mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge remote-tracking branch 'origin/master' into 1798-feature-gradidoid-1-adapt-and-migrate-database-schema
This commit is contained in:
commit
4951a684c6
@ -26,6 +26,7 @@ export enum RIGHTS {
|
||||
LIST_TRANSACTION_LINKS = 'LIST_TRANSACTION_LINKS',
|
||||
GDT_BALANCE = 'GDT_BALANCE',
|
||||
CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION',
|
||||
DELETE_CONTRIBUTION = 'DELETE_CONTRIBUTION',
|
||||
LIST_CONTRIBUTIONS = 'LIST_CONTRIBUTIONS',
|
||||
LIST_ALL_CONTRIBUTIONS = 'LIST_ALL_CONTRIBUTIONS',
|
||||
UPDATE_CONTRIBUTION = 'UPDATE_CONTRIBUTION',
|
||||
|
||||
@ -24,6 +24,7 @@ export const ROLE_USER = new Role('user', [
|
||||
RIGHTS.LIST_TRANSACTION_LINKS,
|
||||
RIGHTS.GDT_BALANCE,
|
||||
RIGHTS.CREATE_CONTRIBUTION,
|
||||
RIGHTS.DELETE_CONTRIBUTION,
|
||||
RIGHTS.LIST_CONTRIBUTIONS,
|
||||
RIGHTS.LIST_ALL_CONTRIBUTIONS,
|
||||
RIGHTS.UPDATE_CONTRIBUTION,
|
||||
|
||||
@ -48,13 +48,13 @@ export class Contribution {
|
||||
@ObjectType()
|
||||
export class ContributionListResult {
|
||||
constructor(count: number, list: Contribution[]) {
|
||||
this.linkCount = count
|
||||
this.linkList = list
|
||||
this.contributionCount = count
|
||||
this.contributionList = list
|
||||
}
|
||||
|
||||
@Field(() => Int)
|
||||
linkCount: number
|
||||
contributionCount: number
|
||||
|
||||
@Field(() => [Contribution])
|
||||
linkList: Contribution[]
|
||||
contributionList: Contribution[]
|
||||
}
|
||||
|
||||
@ -4,7 +4,9 @@
|
||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||
import {
|
||||
adminUpdateContribution,
|
||||
confirmContribution,
|
||||
createContribution,
|
||||
deleteContribution,
|
||||
updateContribution,
|
||||
} from '@/seeds/graphql/mutations'
|
||||
import { listAllContributions, listContributions, login } from '@/seeds/graphql/queries'
|
||||
@ -193,18 +195,21 @@ describe('ContributionResolver', () => {
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
listContributions: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Test env contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
]),
|
||||
listContributions: {
|
||||
contributionCount: 2,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
amount: '1000',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Test env contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
]),
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
@ -226,13 +231,16 @@ describe('ContributionResolver', () => {
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
listContributions: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Test env contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
]),
|
||||
listContributions: {
|
||||
contributionCount: 1,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Test env contribution',
|
||||
amount: '100',
|
||||
}),
|
||||
]),
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
@ -481,6 +489,11 @@ describe('ContributionResolver', () => {
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanDB()
|
||||
resetToken()
|
||||
})
|
||||
|
||||
it('returns allCreation', async () => {
|
||||
await expect(
|
||||
query({
|
||||
@ -496,8 +509,8 @@ describe('ContributionResolver', () => {
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
listAllContributions: {
|
||||
linkCount: 2,
|
||||
linkList: expect.arrayContaining([
|
||||
contributionCount: 2,
|
||||
contributionList: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: expect.any(Number),
|
||||
memo: 'Herzlich Willkommen bei Gradido!',
|
||||
@ -516,4 +529,129 @@ describe('ContributionResolver', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('deleteContribution', () => {
|
||||
describe('unauthenticated', () => {
|
||||
it('returns an error', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: deleteContribution,
|
||||
variables: {
|
||||
id: -1,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('401 Unauthorized')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
beforeAll(async () => {
|
||||
await userFactory(testEnv, bibiBloxberg)
|
||||
await userFactory(testEnv, peterLustig)
|
||||
await query({
|
||||
query: login,
|
||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||
})
|
||||
result = await mutate({
|
||||
mutation: createContribution,
|
||||
variables: {
|
||||
amount: 100.0,
|
||||
memo: 'Test env contribution',
|
||||
creationDate: new Date().toString(),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanDB()
|
||||
resetToken()
|
||||
})
|
||||
|
||||
describe('wrong contribution id', () => {
|
||||
it('returns an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: deleteContribution,
|
||||
variables: {
|
||||
id: -1,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('Contribution not found for given id.')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('other user sends a deleteContribtuion', () => {
|
||||
it('returns an error', async () => {
|
||||
await query({
|
||||
query: login,
|
||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||
})
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: deleteContribution,
|
||||
variables: {
|
||||
id: result.data.createContribution.id,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('Can not delete contribution of another user')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('User deletes own contribution', () => {
|
||||
it('deletes successfully', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: deleteContribution,
|
||||
variables: {
|
||||
id: result.data.createContribution.id,
|
||||
},
|
||||
}),
|
||||
).resolves.toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('User deletes already confirmed contribution', () => {
|
||||
it('throws an error', async () => {
|
||||
await query({
|
||||
query: login,
|
||||
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||
})
|
||||
await mutate({
|
||||
mutation: confirmContribution,
|
||||
variables: {
|
||||
id: result.data.createContribution.id,
|
||||
},
|
||||
})
|
||||
await query({
|
||||
query: login,
|
||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||
})
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: deleteContribution,
|
||||
variables: {
|
||||
id: result.data.createContribution.id,
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
errors: [new GraphQLError('A confirmed contribution can not be deleted')],
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -38,22 +38,43 @@ export class ContributionResolver {
|
||||
return new UnconfirmedContribution(contribution, user, creations)
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.DELETE_CONTRIBUTION])
|
||||
@Mutation(() => Boolean)
|
||||
async deleteContribution(
|
||||
@Arg('id', () => Int) id: number,
|
||||
@Ctx() context: Context,
|
||||
): Promise<boolean> {
|
||||
const user = getUser(context)
|
||||
const contribution = await dbContribution.findOne(id)
|
||||
if (!contribution) {
|
||||
throw new Error('Contribution not found for given id.')
|
||||
}
|
||||
if (contribution.userId !== user.id) {
|
||||
throw new Error('Can not delete contribution of another user')
|
||||
}
|
||||
if (contribution.confirmedAt) {
|
||||
throw new Error('A confirmed contribution can not be deleted')
|
||||
}
|
||||
const res = await contribution.softRemove()
|
||||
return !!res
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.LIST_CONTRIBUTIONS])
|
||||
@Query(() => [Contribution])
|
||||
@Query(() => ContributionListResult)
|
||||
async listContributions(
|
||||
@Args()
|
||||
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
|
||||
@Arg('filterConfirmed', () => Boolean)
|
||||
filterConfirmed: boolean | null,
|
||||
@Ctx() context: Context,
|
||||
): Promise<Contribution[]> {
|
||||
): Promise<ContributionListResult> {
|
||||
const user = getUser(context)
|
||||
const where: {
|
||||
userId: number
|
||||
confirmedBy?: FindOperator<number> | null
|
||||
} = { userId: user.id }
|
||||
if (filterConfirmed) where.confirmedBy = IsNull()
|
||||
const contributions = await dbContribution.find({
|
||||
const [contributions, count] = await dbContribution.findAndCount({
|
||||
where,
|
||||
order: {
|
||||
createdAt: order,
|
||||
@ -62,7 +83,10 @@ export class ContributionResolver {
|
||||
skip: (currentPage - 1) * pageSize,
|
||||
take: pageSize,
|
||||
})
|
||||
return contributions.map((contribution) => new Contribution(contribution, new User(user)))
|
||||
return new ContributionListResult(
|
||||
count,
|
||||
contributions.map((contribution) => new Contribution(contribution, new User(user))),
|
||||
)
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.LIST_ALL_CONTRIBUTIONS])
|
||||
|
||||
@ -255,3 +255,9 @@ export const updateContribution = gql`
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const deleteContribution = gql`
|
||||
mutation ($id: Int!) {
|
||||
deleteContribution(id: $id)
|
||||
}
|
||||
`
|
||||
|
||||
@ -185,9 +185,12 @@ export const listContributions = gql`
|
||||
order: $order
|
||||
filterConfirmed: $filterConfirmed
|
||||
) {
|
||||
id
|
||||
amount
|
||||
memo
|
||||
contributionCount
|
||||
contributionList {
|
||||
id
|
||||
amount
|
||||
memo
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -195,8 +198,8 @@ export const listContributions = gql`
|
||||
export const listAllContributions = `
|
||||
query ($currentPage: Int = 1, $pageSize: Int = 5, $order: Order = DESC) {
|
||||
listAllContributions(currentPage: $currentPage, pageSize: $pageSize, order: $order) {
|
||||
linkCount
|
||||
linkList {
|
||||
contributionCount
|
||||
contributionList {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user