mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch '2473-feature-emails-further-design-of-html-emails' of https://github.com/gradido/gradido into 2473-feature-emails-further-design-of-html-emails
This commit is contained in:
commit
e77385e27d
@ -7,7 +7,7 @@ module.exports = {
|
||||
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 86,
|
||||
lines: 89,
|
||||
},
|
||||
},
|
||||
setupFiles: ['<rootDir>/test/testSetup.ts'],
|
||||
|
||||
@ -19,6 +19,7 @@ import {
|
||||
createContribution,
|
||||
login,
|
||||
sendCoins,
|
||||
updateUserInfos,
|
||||
} from '@/seeds/graphql/mutations'
|
||||
import { transactionsQuery } from '@/seeds/graphql/queries'
|
||||
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
|
||||
@ -52,10 +53,13 @@ let bobData: any
|
||||
let peterData: any
|
||||
let user: User[]
|
||||
|
||||
let bob: User
|
||||
let peter: User
|
||||
|
||||
describe('send coins', () => {
|
||||
beforeAll(async () => {
|
||||
await userFactory(testEnv, peterLustig)
|
||||
await userFactory(testEnv, bobBaumeister)
|
||||
peter = await userFactory(testEnv, peterLustig)
|
||||
bob = await userFactory(testEnv, bobBaumeister)
|
||||
await userFactory(testEnv, stephenHawking)
|
||||
await userFactory(testEnv, garrickOllivander)
|
||||
|
||||
@ -376,6 +380,114 @@ describe('send coins', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('send coins via gradido ID', () => {
|
||||
it('sends the coins', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
identifier: peter?.gradidoID,
|
||||
amount: 10,
|
||||
memo: 'send via gradido ID',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
sendCoins: true,
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('send coins via alias', () => {
|
||||
beforeAll(async () => {
|
||||
await mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
alias: 'bob',
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
mutation: login,
|
||||
variables: peterData,
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await mutate({
|
||||
mutation: login,
|
||||
variables: bobData,
|
||||
})
|
||||
})
|
||||
|
||||
it('sends the coins', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: sendCoins,
|
||||
variables: {
|
||||
identifier: 'bob',
|
||||
amount: 6.66,
|
||||
memo: 'send via alias',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
sendCoins: true,
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
describe("peter's transactions", () => {
|
||||
it('has all expected transactions', async () => {
|
||||
await expect(query({ query: transactionsQuery })).resolves.toMatchObject({
|
||||
data: {
|
||||
transactionList: {
|
||||
balance: expect.any(Object),
|
||||
transactions: [
|
||||
expect.objectContaining({
|
||||
typeId: 'DECAY',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(-6.66),
|
||||
linkedUser: {
|
||||
firstName: 'Bob',
|
||||
gradidoID: bob?.gradidoID,
|
||||
lastName: 'der Baumeister',
|
||||
},
|
||||
memo: 'send via alias',
|
||||
typeId: 'SEND',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(10),
|
||||
linkedUser: {
|
||||
firstName: 'Bob',
|
||||
gradidoID: bob?.gradidoID,
|
||||
lastName: 'der Baumeister',
|
||||
},
|
||||
memo: 'send via gradido ID',
|
||||
typeId: 'RECEIVE',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
amount: expect.decimalEqual(50),
|
||||
linkedUser: {
|
||||
firstName: 'Bob',
|
||||
gradidoID: bob?.gradidoID,
|
||||
lastName: 'der Baumeister',
|
||||
},
|
||||
memo: 'unrepeatable memo',
|
||||
typeId: 'RECEIVE',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('more transactions to test semaphore', () => {
|
||||
it('sends the coins four times in a row', async () => {
|
||||
await expect(
|
||||
|
||||
@ -323,6 +323,7 @@ export class TransactionResolver {
|
||||
}
|
||||
|
||||
// TODO this is subject to replay attacks
|
||||
// --- WHY?
|
||||
const senderUser = getUser(context)
|
||||
|
||||
// validate recipient user
|
||||
|
||||
@ -2358,15 +2358,21 @@ describe('UserResolver', () => {
|
||||
mutation: login,
|
||||
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||
})
|
||||
await mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
alias: 'bibi',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is no gradido ID and no email', () => {
|
||||
describe('identifier is no gradido ID, no email and no alias', () => {
|
||||
it('throws and logs "Unknown identifier type" error', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'identifier',
|
||||
identifier: 'identifier_is_no_valid_alias!',
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
@ -2374,7 +2380,10 @@ describe('UserResolver', () => {
|
||||
errors: [new GraphQLError('Unknown identifier type')],
|
||||
}),
|
||||
)
|
||||
expect(logger.error).toBeCalledWith('Unknown identifier type', 'identifier')
|
||||
expect(logger.error).toBeCalledWith(
|
||||
'Unknown identifier type',
|
||||
'identifier_is_no_valid_alias!',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -2441,6 +2450,29 @@ describe('UserResolver', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('identifier is found via alias', () => {
|
||||
it('returns user', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: userQuery,
|
||||
variables: {
|
||||
identifier: 'bibi',
|
||||
},
|
||||
}),
|
||||
).resolves.toEqual(
|
||||
expect.objectContaining({
|
||||
data: {
|
||||
user: {
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ import { validate, version } from 'uuid'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { VALID_ALIAS_REGEX } from './validateAlias'
|
||||
|
||||
export const findUserByIdentifier = async (identifier: string): Promise<DbUser> => {
|
||||
let user: DbUser | undefined
|
||||
if (validate(identifier) && version(identifier) === 4) {
|
||||
@ -27,8 +29,12 @@ export const findUserByIdentifier = async (identifier: string): Promise<DbUser>
|
||||
}
|
||||
user = userContact.user
|
||||
user.emailContact = userContact
|
||||
} else if (VALID_ALIAS_REGEX.exec(identifier)) {
|
||||
user = await DbUser.findOne({ where: { alias: identifier }, relations: ['emailContact'] })
|
||||
if (!user) {
|
||||
throw new LogError('No user found to given identifier', identifier)
|
||||
}
|
||||
} else {
|
||||
// last is alias when implemented
|
||||
throw new LogError('Unknown identifier type', identifier)
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,10 @@ import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
const reservedAlias = [
|
||||
// eslint-disable-next-line security/detect-unsafe-regex
|
||||
export const VALID_ALIAS_REGEX = /^(?=.{3,20}$)[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/
|
||||
|
||||
const RESERVED_ALIAS = [
|
||||
'admin',
|
||||
'email',
|
||||
'gast',
|
||||
@ -24,10 +27,9 @@ const reservedAlias = [
|
||||
export const validateAlias = async (alias: string): Promise<boolean> => {
|
||||
if (alias.length < 3) throw new LogError('Given alias is too short', alias)
|
||||
if (alias.length > 20) throw new LogError('Given alias is too long', alias)
|
||||
/* eslint-disable-next-line security/detect-unsafe-regex */
|
||||
if (!alias.match(/^[0-9A-Za-z]([_-]?[A-Za-z0-9])+$/))
|
||||
throw new LogError('Invalid characters in alias', alias)
|
||||
if (reservedAlias.includes(alias.toLowerCase())) throw new LogError('Alias is not allowed', alias)
|
||||
if (!alias.match(VALID_ALIAS_REGEX)) throw new LogError('Invalid characters in alias', alias)
|
||||
if (RESERVED_ALIAS.includes(alias.toLowerCase()))
|
||||
throw new LogError('Alias is not allowed', alias)
|
||||
const aliasInUse = await DbUser.find({
|
||||
where: { alias: Raw((a) => `LOWER(${a}) = "${alias.toLowerCase()}"`) },
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user