Merge branch 'master' into add-nvm-config-files

This commit is contained in:
Moriz Wahl 2022-04-28 16:29:31 +02:00 committed by GitHub
commit 2928a03b81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1181 additions and 109 deletions

View File

@ -528,7 +528,7 @@ jobs:
report_name: Coverage Backend report_name: Coverage Backend
type: lcov type: lcov
result_path: ./backend/coverage/lcov.info result_path: ./backend/coverage/lcov.info
min_coverage: 58 min_coverage: 65
token: ${{ github.token }} token: ${{ github.token }}
########################################################################## ##########################################################################

View File

@ -24,12 +24,6 @@ const mocks = {
}, },
$store: { $store: {
commit: stateCommitMock, commit: stateCommitMock,
state: {
moderator: {
id: 0,
name: 'test moderator',
},
},
}, },
} }
@ -122,7 +116,6 @@ describe('CreationFormular', () => {
creationDate: getCreationDate(2), creationDate: getCreationDate(2),
amount: 90, amount: 90,
memo: 'Test create coins', memo: 'Test create coins',
moderator: 0,
}, },
}), }),
) )
@ -370,14 +363,12 @@ describe('CreationFormular', () => {
creationDate: getCreationDate(1), creationDate: getCreationDate(1),
amount: 200, amount: 200,
memo: 'Test mass create coins', memo: 'Test mass create coins',
moderator: 0,
}, },
{ {
email: 'bibi@bloxberg.de', email: 'bibi@bloxberg.de',
creationDate: getCreationDate(1), creationDate: getCreationDate(1),
amount: 200, amount: 200,
memo: 'Test mass create coins', memo: 'Test mass create coins',
moderator: 0,
}, },
], ],
}, },

View File

@ -154,7 +154,6 @@ export default {
creationDate: this.selected.date, creationDate: this.selected.date,
amount: Number(this.value), amount: Number(this.value),
memo: this.text, memo: this.text,
moderator: Number(this.$store.state.moderator.id),
}) })
}) })
this.$apollo this.$apollo
@ -188,7 +187,6 @@ export default {
creationDate: this.selected.date, creationDate: this.selected.date,
amount: Number(this.value), amount: Number(this.value),
memo: this.text, memo: this.text,
moderator: Number(this.$store.state.moderator.id),
} }
this.$apollo this.$apollo
.mutate({ .mutate({

View File

@ -11,7 +11,6 @@ const apolloMutateMock = jest.fn().mockResolvedValue({
amount: 500, amount: 500,
date: new Date(), date: new Date(),
memo: 'Test Schöpfung 2', memo: 'Test Schöpfung 2',
moderator: 0,
}, },
}, },
}) })
@ -28,12 +27,6 @@ const mocks = {
mutate: apolloMutateMock, mutate: apolloMutateMock,
}, },
$store: { $store: {
state: {
moderator: {
id: 0,
name: 'test moderator',
},
},
commit: stateCommitMock, commit: stateCommitMock,
}, },
} }
@ -104,7 +97,6 @@ describe('EditCreationFormular', () => {
creationDate: getCreationDate(0), creationDate: getCreationDate(0),
amount: 500, amount: 500,
memo: 'Test Schöpfung 2', memo: 'Test Schöpfung 2',
moderator: 0,
}, },
}), }),
) )
@ -129,7 +121,6 @@ describe('EditCreationFormular', () => {
amount: 500, amount: 500,
date: expect.any(Date), date: expect.any(Date),
memo: 'Test Schöpfung 2', memo: 'Test Schöpfung 2',
moderator: 0,
row: expect.any(Object), row: expect.any(Object),
}, },
], ],

View File

@ -120,7 +120,6 @@ export default {
creationDate: this.selected.date, creationDate: this.selected.date,
amount: Number(this.value), amount: Number(this.value),
memo: this.text, memo: this.text,
moderator: Number(this.$store.state.moderator.id),
}, },
}) })
.then((result) => { .then((result) => {
@ -129,7 +128,6 @@ export default {
amount: Number(result.data.updatePendingCreation.amount), amount: Number(result.data.updatePendingCreation.amount),
date: result.data.updatePendingCreation.date, date: result.data.updatePendingCreation.date,
memo: result.data.updatePendingCreation.memo, memo: result.data.updatePendingCreation.memo,
moderator: Number(result.data.updatePendingCreation.moderator),
row: this.row, row: this.row,
}) })
this.toastSuccess( this.toastSuccess(

View File

@ -1,19 +1,7 @@
import gql from 'graphql-tag' import gql from 'graphql-tag'
export const createPendingCreation = gql` export const createPendingCreation = gql`
mutation ( mutation ($email: String!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
$email: String! createPendingCreation(email: $email, amount: $amount, memo: $memo, creationDate: $creationDate)
$amount: Decimal!
$memo: String!
$creationDate: String!
$moderator: Int!
) {
createPendingCreation(
email: $email
amount: $amount
memo: $memo
creationDate: $creationDate
moderator: $moderator
)
} }
` `

View File

@ -1,27 +1,18 @@
import gql from 'graphql-tag' import gql from 'graphql-tag'
export const updatePendingCreation = gql` export const updatePendingCreation = gql`
mutation ( mutation ($id: Int!, $email: String!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
$id: Int!
$email: String!
$amount: Decimal!
$memo: String!
$creationDate: String!
$moderator: Int!
) {
updatePendingCreation( updatePendingCreation(
id: $id id: $id
email: $email email: $email
amount: $amount amount: $amount
memo: $memo memo: $memo
creationDate: $creationDate creationDate: $creationDate
moderator: $moderator
) { ) {
amount amount
date date
memo memo
creation creation
moderator
} }
} }
` `

View File

@ -1,4 +1,4 @@
import { ArgsType, Field, InputType, Int } from 'type-graphql' import { ArgsType, Field, InputType } from 'type-graphql'
import Decimal from 'decimal.js-light' import Decimal from 'decimal.js-light'
@InputType() @InputType()
@ -15,7 +15,4 @@ export default class CreatePendingCreationArgs {
@Field(() => String) @Field(() => String)
creationDate: string creationDate: string
@Field(() => Int)
moderator: number
} }

View File

@ -17,7 +17,4 @@ export default class UpdatePendingCreationArgs {
@Field(() => String) @Field(() => String)
creationDate: string creationDate: string
@Field(() => Int)
moderator: number
} }

View File

@ -12,9 +12,6 @@ export class UpdatePendingCreation {
@Field(() => Decimal) @Field(() => Decimal)
amount: Decimal amount: Decimal
@Field(() => Number)
moderator: number
@Field(() => [Decimal]) @Field(() => [Decimal])
creation: Decimal[] creation: Decimal[]
} }

File diff suppressed because it is too large Load Diff

View File

@ -157,11 +157,12 @@ export class AdminResolver {
@Mutation(() => Date, { nullable: true }) @Mutation(() => Date, { nullable: true })
async unDeleteUser(@Arg('userId', () => Int) userId: number): Promise<Date | null> { async unDeleteUser(@Arg('userId', () => Int) userId: number): Promise<Date | null> {
const user = await dbUser.findOne({ id: userId }, { withDeleted: true }) const user = await dbUser.findOne({ id: userId }, { withDeleted: true })
// user exists ?
if (!user) { if (!user) {
throw new Error(`Could not find user with userId: ${userId}`) throw new Error(`Could not find user with userId: ${userId}`)
} }
// recover user account if (!user.deletedAt) {
throw new Error('User is not deleted')
}
await user.recover() await user.recover()
return null return null
} }
@ -169,7 +170,8 @@ export class AdminResolver {
@Authorized([RIGHTS.CREATE_PENDING_CREATION]) @Authorized([RIGHTS.CREATE_PENDING_CREATION])
@Mutation(() => [Number]) @Mutation(() => [Number])
async createPendingCreation( async createPendingCreation(
@Args() { email, amount, memo, creationDate, moderator }: CreatePendingCreationArgs, @Args() { email, amount, memo, creationDate }: CreatePendingCreationArgs,
@Ctx() context: Context,
): Promise<Decimal[]> { ): Promise<Decimal[]> {
const user = await dbUser.findOne({ email }, { withDeleted: true }) const user = await dbUser.findOne({ email }, { withDeleted: true })
if (!user) { if (!user) {
@ -181,6 +183,7 @@ export class AdminResolver {
if (!user.emailChecked) { if (!user.emailChecked) {
throw new Error('Creation could not be saved, Email is not activated') throw new Error('Creation could not be saved, Email is not activated')
} }
const moderator = getUser(context)
const creations = await getUserCreation(user.id) const creations = await getUserCreation(user.id)
const creationDateObj = new Date(creationDate) const creationDateObj = new Date(creationDate)
if (isCreationValid(creations, amount, creationDateObj)) { if (isCreationValid(creations, amount, creationDateObj)) {
@ -190,7 +193,7 @@ export class AdminResolver {
adminPendingCreation.created = new Date() adminPendingCreation.created = new Date()
adminPendingCreation.date = creationDateObj adminPendingCreation.date = creationDateObj
adminPendingCreation.memo = memo adminPendingCreation.memo = memo
adminPendingCreation.moderator = moderator adminPendingCreation.moderator = moderator.id
await AdminPendingCreation.save(adminPendingCreation) await AdminPendingCreation.save(adminPendingCreation)
} }
@ -202,12 +205,13 @@ export class AdminResolver {
async createPendingCreations( async createPendingCreations(
@Arg('pendingCreations', () => [CreatePendingCreationArgs]) @Arg('pendingCreations', () => [CreatePendingCreationArgs])
pendingCreations: CreatePendingCreationArgs[], pendingCreations: CreatePendingCreationArgs[],
@Ctx() context: Context,
): Promise<CreatePendingCreations> { ): Promise<CreatePendingCreations> {
let success = false let success = false
const successfulCreation: string[] = [] const successfulCreation: string[] = []
const failedCreation: string[] = [] const failedCreation: string[] = []
for (const pendingCreation of pendingCreations) { for (const pendingCreation of pendingCreations) {
await this.createPendingCreation(pendingCreation) await this.createPendingCreation(pendingCreation, context)
.then(() => { .then(() => {
successfulCreation.push(pendingCreation.email) successfulCreation.push(pendingCreation.email)
success = true success = true
@ -226,7 +230,8 @@ export class AdminResolver {
@Authorized([RIGHTS.UPDATE_PENDING_CREATION]) @Authorized([RIGHTS.UPDATE_PENDING_CREATION])
@Mutation(() => UpdatePendingCreation) @Mutation(() => UpdatePendingCreation)
async updatePendingCreation( async updatePendingCreation(
@Args() { id, email, amount, memo, creationDate, moderator }: UpdatePendingCreationArgs, @Args() { id, email, amount, memo, creationDate }: UpdatePendingCreationArgs,
@Ctx() context: Context,
): Promise<UpdatePendingCreation> { ): Promise<UpdatePendingCreation> {
const user = await dbUser.findOne({ email }, { withDeleted: true }) const user = await dbUser.findOne({ email }, { withDeleted: true })
if (!user) { if (!user) {
@ -236,7 +241,13 @@ export class AdminResolver {
throw new Error(`User was deleted (${email})`) throw new Error(`User was deleted (${email})`)
} }
const pendingCreationToUpdate = await AdminPendingCreation.findOneOrFail({ id }) const moderator = getUser(context)
const pendingCreationToUpdate = await AdminPendingCreation.findOne({ id })
if (!pendingCreationToUpdate) {
throw new Error('No creation found to given id.')
}
if (pendingCreationToUpdate.userId !== user.id) { if (pendingCreationToUpdate.userId !== user.id) {
throw new Error('user of the pending creation and send user does not correspond') throw new Error('user of the pending creation and send user does not correspond')
@ -248,20 +259,18 @@ export class AdminResolver {
creations = updateCreations(creations, pendingCreationToUpdate) creations = updateCreations(creations, pendingCreationToUpdate)
} }
if (!isCreationValid(creations, amount, creationDateObj)) { // all possible cases not to be true are thrown in this function
throw new Error('Creation is not valid') isCreationValid(creations, amount, creationDateObj)
}
pendingCreationToUpdate.amount = amount pendingCreationToUpdate.amount = amount
pendingCreationToUpdate.memo = memo pendingCreationToUpdate.memo = memo
pendingCreationToUpdate.date = new Date(creationDate) pendingCreationToUpdate.date = new Date(creationDate)
pendingCreationToUpdate.moderator = moderator pendingCreationToUpdate.moderator = moderator.id
await AdminPendingCreation.save(pendingCreationToUpdate) await AdminPendingCreation.save(pendingCreationToUpdate)
const result = new UpdatePendingCreation() const result = new UpdatePendingCreation()
result.amount = amount result.amount = amount
result.memo = pendingCreationToUpdate.memo result.memo = pendingCreationToUpdate.memo
result.date = pendingCreationToUpdate.date result.date = pendingCreationToUpdate.date
result.moderator = pendingCreationToUpdate.moderator
result.creation = await getUserCreation(user.id) result.creation = await getUserCreation(user.id)
@ -298,8 +307,11 @@ export class AdminResolver {
@Authorized([RIGHTS.DELETE_PENDING_CREATION]) @Authorized([RIGHTS.DELETE_PENDING_CREATION])
@Mutation(() => Boolean) @Mutation(() => Boolean)
async deletePendingCreation(@Arg('id', () => Int) id: number): Promise<boolean> { async deletePendingCreation(@Arg('id', () => Int) id: number): Promise<boolean> {
const entity = await AdminPendingCreation.findOneOrFail(id) const pendingCreation = await AdminPendingCreation.findOne(id)
const res = await AdminPendingCreation.delete(entity) if (!pendingCreation) {
throw new Error('Creation not found for given id.')
}
const res = await AdminPendingCreation.delete(pendingCreation)
return !!res return !!res
} }
@ -309,7 +321,10 @@ export class AdminResolver {
@Arg('id', () => Int) id: number, @Arg('id', () => Int) id: number,
@Ctx() context: Context, @Ctx() context: Context,
): Promise<boolean> { ): Promise<boolean> {
const pendingCreation = await AdminPendingCreation.findOneOrFail(id) const pendingCreation = await AdminPendingCreation.findOne(id)
if (!pendingCreation) {
throw new Error('Creation not found to given id.')
}
const moderatorUser = getUser(context) const moderatorUser = getUser(context)
if (moderatorUser.id === pendingCreation.userId) if (moderatorUser.id === pendingCreation.userId)
throw new Error('Moderator can not confirm own pending creation') throw new Error('Moderator can not confirm own pending creation')
@ -340,8 +355,7 @@ export class AdminResolver {
transaction.memo = pendingCreation.memo transaction.memo = pendingCreation.memo
transaction.userId = pendingCreation.userId transaction.userId = pendingCreation.userId
transaction.previous = lastTransaction ? lastTransaction.id : null transaction.previous = lastTransaction ? lastTransaction.id : null
// TODO pending creations decimal transaction.amount = pendingCreation.amount
transaction.amount = new Decimal(Number(pendingCreation.amount))
transaction.creationDate = pendingCreation.date transaction.creationDate = pendingCreation.date
transaction.balance = newBalance transaction.balance = newBalance
transaction.balanceDate = receivedCallDate transaction.balanceDate = receivedCallDate
@ -504,7 +518,7 @@ function updateCreations(creations: Decimal[], pendingCreation: AdminPendingCrea
if (index < 0) { if (index < 0) {
throw new Error('You cannot create GDD for a month older than the last three months.') throw new Error('You cannot create GDD for a month older than the last three months.')
} }
creations[index] = creations[index].plus(pendingCreation.amount) creations[index] = creations[index].plus(pendingCreation.amount.toString())
return creations return creations
} }
@ -512,12 +526,12 @@ function isCreationValid(creations: Decimal[], amount: Decimal, creationDate: Da
const index = getCreationIndex(creationDate.getMonth()) const index = getCreationIndex(creationDate.getMonth())
if (index < 0) { if (index < 0) {
throw new Error(`No Creation found!`) throw new Error('No information for available creations for the given date')
} }
if (amount.greaterThan(creations[index].toString())) { if (amount.greaterThan(creations[index].toString())) {
throw new Error( throw new Error(
`The amount (${amount} GDD) to be created exceeds the available amount (${creations[index]} GDD) for this month.`, `The amount (${amount} GDD) to be created exceeds the amount (${creations[index]} GDD) still available for this month.`,
) )
} }

View File

@ -17,27 +17,22 @@ export const nMonthsBefore = (date: Date, months = 1): string => {
export const creationFactory = async ( export const creationFactory = async (
client: ApolloServerTestClient, client: ApolloServerTestClient,
creation: CreationInterface, creation: CreationInterface,
): Promise<void> => { ): Promise<AdminPendingCreation | void> => {
const { mutate, query } = client const { mutate, query } = client
// login as Peter Lustig (admin) and get his user ID await query({ query: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } })
const {
data: {
login: { id },
},
} = await query({ query: login, variables: { email: 'peter@lustig.de', password: 'Aa12345_' } })
await mutate({ mutation: createPendingCreation, variables: { ...creation, moderator: id } }) // TODO it would be nice to have this mutation return the id
await mutate({ mutation: createPendingCreation, variables: { ...creation } })
// get User
const user = await User.findOneOrFail({ where: { email: creation.email } }) const user = await User.findOneOrFail({ where: { email: creation.email } })
if (creation.confirmed) { const pendingCreation = await AdminPendingCreation.findOneOrFail({
const pendingCreation = await AdminPendingCreation.findOneOrFail({ where: { userId: user.id, amount: creation.amount },
where: { userId: user.id }, order: { created: 'DESC' },
order: { created: 'DESC' }, })
})
if (creation.confirmed) {
await mutate({ mutation: confirmPendingCreation, variables: { id: pendingCreation.id } }) await mutate({ mutation: confirmPendingCreation, variables: { id: pendingCreation.id } })
if (creation.moveCreationDate) { if (creation.moveCreationDate) {
@ -55,5 +50,7 @@ export const creationFactory = async (
await transaction.save() await transaction.save()
} }
} }
} else {
return pendingCreation
} }
} }

View File

@ -7,7 +7,7 @@ import { ApolloServerTestClient } from 'apollo-server-testing'
export const userFactory = async ( export const userFactory = async (
client: ApolloServerTestClient, client: ApolloServerTestClient,
user: UserInterface, user: UserInterface,
): Promise<void> => { ): Promise<User> => {
const { mutate } = client const { mutate } = client
const { const {
@ -24,13 +24,15 @@ export const userFactory = async (
}) })
} }
if (user.createdAt || user.deletedAt || user.isAdmin) { // get user from database
// get user from database const dbUser = await User.findOneOrFail({ id })
const dbUser = await User.findOneOrFail({ id })
if (user.createdAt || user.deletedAt || user.isAdmin) {
if (user.createdAt) dbUser.createdAt = user.createdAt if (user.createdAt) dbUser.createdAt = user.createdAt
if (user.deletedAt) dbUser.deletedAt = user.deletedAt if (user.deletedAt) dbUser.deletedAt = user.deletedAt
if (user.isAdmin) dbUser.isAdmin = new Date() if (user.isAdmin) dbUser.isAdmin = new Date()
await dbUser.save() await dbUser.save()
} }
return dbUser
} }

View File

@ -84,20 +84,8 @@ export const createTransactionLink = gql`
// from admin interface // from admin interface
export const createPendingCreation = gql` export const createPendingCreation = gql`
mutation ( mutation ($email: String!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
$email: String! createPendingCreation(email: $email, amount: $amount, memo: $memo, creationDate: $creationDate)
$amount: Decimal!
$memo: String!
$creationDate: String!
$moderator: Int!
) {
createPendingCreation(
email: $email
amount: $amount
memo: $memo
creationDate: $creationDate
moderator: $moderator
)
} }
` `
@ -106,3 +94,48 @@ export const confirmPendingCreation = gql`
confirmPendingCreation(id: $id) confirmPendingCreation(id: $id)
} }
` `
export const deleteUser = gql`
mutation ($userId: Int!) {
deleteUser(userId: $userId)
}
`
export const unDeleteUser = gql`
mutation ($userId: Int!) {
unDeleteUser(userId: $userId)
}
`
export const createPendingCreations = gql`
mutation ($pendingCreations: [CreatePendingCreationArgs!]!) {
createPendingCreations(pendingCreations: $pendingCreations) {
success
successfulCreation
failedCreation
}
}
`
export const updatePendingCreation = gql`
mutation ($id: Int!, $email: String!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
updatePendingCreation(
id: $id
email: $email
amount: $amount
memo: $memo
creationDate: $creationDate
) {
amount
date
memo
creation
}
}
`
export const deletePendingCreation = gql`
mutation ($id: Int!) {
deletePendingCreation(id: $id)
}
`

View File

@ -148,3 +148,21 @@ export const queryTransactionLink = gql`
} }
} }
` `
// from admin interface
export const getPendingCreations = gql`
query {
getPendingCreations {
id
firstName
lastName
email
amount
memo
date
moderator
creation
}
}
`