Merge branch 'master' into fix-store-problems

This commit is contained in:
mahula 2023-05-08 15:36:32 +02:00 committed by GitHub
commit eb570ada63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 121 additions and 193 deletions

View File

@ -1,3 +1,3 @@
node_modules/
dist/
build/
coverage/

2
admin/.gitignore vendored
View File

@ -1,5 +1,5 @@
node_modules/
dist/
build/
.cache/
/.env

View File

@ -84,7 +84,7 @@ CMD /bin/sh -c "yarn run dev"
FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/dist ./dist
COPY --from=build ${DOCKER_WORKDIR}/build ./build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
# Copy static files

View File

@ -11,7 +11,7 @@
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"dev": "yarn run serve",
"analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json",
"analyse-bundle": "yarn build && webpack-bundle-analyzer build/webpack.stats.json",
"lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
"test": "cross-env TZ=UTC jest",

View File

@ -9,10 +9,10 @@ const port = process.env.PORT || 8080
// Express Server
const app = express()
// Serve files
app.use(express.static(path.join(__dirname, '../dist')))
app.use(express.static(path.join(__dirname, '../build')))
// Default to index.html
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../dist/index.html'))
res.sendFile(path.join(__dirname, '../build/index.html'))
})
app.listen(port, hostname, () => {

View File

@ -49,5 +49,5 @@ module.exports = {
// Enable CSS source maps.
sourceMap: CONFIG.NODE_ENV !== 'production',
},
outputDir: path.resolve(__dirname, './dist'),
outputDir: path.resolve(__dirname, './build'),
}

View File

@ -2,7 +2,6 @@ import { User as dbUser } from '@entity/User'
import { ObjectType, Field, Int } from 'type-graphql'
import { KlickTipp } from './KlickTipp'
import { UserContact } from './UserContact'
@ObjectType()
export class User {
@ -10,10 +9,7 @@ export class User {
this.id = user.id
this.gradidoID = user.gradidoID
this.alias = user.alias
this.emailId = user.emailId
if (user.emailContact) {
this.email = user.emailContact.email
this.emailContact = new UserContact(user.emailContact)
this.emailChecked = user.emailContact.emailChecked
}
this.firstName = user.firstName
@ -38,16 +34,6 @@ export class User {
@Field(() => String, { nullable: true })
alias: string | null
@Field(() => Int, { nullable: true })
emailId: number | null
// TODO privacy issue here
@Field(() => String, { nullable: true })
email: string | null
@Field(() => UserContact)
emailContact: UserContact
@Field(() => String, { nullable: true })
firstName: string | null

View File

@ -20,12 +20,15 @@ import {
login,
sendCoins,
} from '@/seeds/graphql/mutations'
import { transactionsQuery } from '@/seeds/graphql/queries'
import { bobBaumeister } from '@/seeds/users/bob-baumeister'
import { garrickOllivander } from '@/seeds/users/garrick-ollivander'
import { peterLustig } from '@/seeds/users/peter-lustig'
import { stephenHawking } from '@/seeds/users/stephen-hawking'
let mutate: ApolloServerTestClient['mutate'], con: Connection
let query: ApolloServerTestClient['query']
let testEnv: {
mutate: ApolloServerTestClient['mutate']
query: ApolloServerTestClient['query']
@ -35,6 +38,7 @@ let testEnv: {
beforeAll(async () => {
testEnv = await testEnvironment(logger)
mutate = testEnv.mutate
query = testEnv.query
con = testEnv.con
await cleanDB()
})
@ -442,3 +446,42 @@ describe('send coins', () => {
})
})
})
describe('transactionList', () => {
describe('unauthenticated', () => {
it('throws an error', async () => {
await expect(query({ query: transactionsQuery })).resolves.toMatchObject({
errors: [new GraphQLError('401 Unauthorized')],
})
})
})
describe('authenticated', () => {
describe('no transactions', () => {
beforeAll(async () => {
await userFactory(testEnv, bobBaumeister)
await mutate({
mutation: login,
variables: {
email: 'bob@baumeister.de',
password: 'Aa12345_',
},
})
})
it('has no transactions and balance 0', async () => {
await expect(query({ query: transactionsQuery })).resolves.toMatchObject({
data: {
transactionList: {
balance: expect.objectContaining({
balance: expect.decimalEqual(0),
}),
transactions: [],
},
},
errors: undefined,
})
})
})
})
})

View File

@ -680,7 +680,6 @@ describe('UserResolver', () => {
expect.objectContaining({
data: {
login: {
email: 'bibi@bloxberg.de',
firstName: 'Bibi',
hasElopage: false,
id: expect.any(Number),
@ -953,7 +952,6 @@ describe('UserResolver', () => {
expect.objectContaining({
data: {
verifyLogin: {
email: 'bibi@bloxberg.de',
firstName: 'Bibi',
lastName: 'Bloxberg',
language: 'de',
@ -1310,7 +1308,7 @@ describe('UserResolver', () => {
expect.objectContaining({
data: {
login: expect.objectContaining({
email: 'bibi@bloxberg.de',
firstName: 'Benjamin',
}),
},
}),
@ -1457,7 +1455,6 @@ describe('UserResolver', () => {
expect.objectContaining({
data: {
login: {
email: 'bibi@bloxberg.de',
firstName: 'Bibi',
hasElopage: false,
id: expect.any(Number),

View File

@ -130,7 +130,7 @@ export class UserResolver {
// Elopage Status & Stored PublisherId
user.hasElopage = await this.hasElopage(context)
logger.debug(`verifyLogin... successful: ${user.firstName}.${user.lastName}, ${user.email}`)
logger.debug(`verifyLogin... successful: ${user.firstName}.${user.lastName}`)
return user
}
@ -238,7 +238,6 @@ export class UserResolver {
const user = new User(communityDbUser)
user.id = sodium.randombytes_random() % (2048 * 16) // TODO: for a better faking derive id from email so that it will be always the same id when the same email comes in?
user.gradidoID = uuidv4()
user.email = email
user.firstName = firstName
user.lastName = lastName
user.language = language

View File

@ -305,7 +305,6 @@ export const login = gql`
mutation ($email: String!, $password: String!, $publisherId: Int) {
login(email: $email, password: $password, publisherId: $publisherId) {
id
email
firstName
lastName
language

View File

@ -3,7 +3,6 @@ import { gql } from 'graphql-tag'
export const verifyLogin = gql`
query {
verifyLogin {
email
firstName
lastName
language
@ -24,31 +23,26 @@ export const queryOptIn = gql`
`
export const transactionsQuery = gql`
query (
$currentPage: Int = 1
$pageSize: Int = 25
$order: Order = DESC
$onlyCreations: Boolean = false
) {
transactionList(
currentPage: $currentPage
pageSize: $pageSize
order: $order
onlyCreations: $onlyCreations
) {
balanceGDT
count
balance
query ($currentPage: Int = 1, $pageSize: Int = 25, $order: Order = DESC) {
transactionList(currentPage: $currentPage, pageSize: $pageSize, order: $order) {
balance {
balance
balanceGDT
count
linkCount
}
transactions {
id
typeId
amount
balance
previousBalance
balanceDate
memo
linkedUser {
firstName
lastName
gradidoID
}
decay {
decay
@ -56,6 +50,7 @@ export const transactionsQuery = gql`
end
duration
}
linkId
}
}
}

View File

@ -117,7 +117,7 @@ server {
# TODO this could be a performance optimization
#location /vue {
# alias /var/www/html/gradido/frontend/dist;
# alias /var/www/html/gradido/frontend/build;
# index index.html;
#
# location ~* \.(png)$ {

View File

@ -103,7 +103,7 @@ server {
# TODO this could be a performance optimization
#location /vue {
# alias /var/www/html/gradido/frontend/dist;
# alias /var/www/html/gradido/frontend/build;
# index index.html;
#
# location ~* \.(png)$ {

View File

@ -15,6 +15,6 @@ export NVM_DIR="/root/.nvm"
$NPM_BIN install
$NPM_BIN run build
# prezip for faster deliver throw nginx
cd dist
cd build
find . -type f -name "*.css" -exec gzip -9 -k {} \;
find . -type f -name "*.js" -exec gzip -9 -k {} \;

View File

@ -130,6 +130,15 @@ rm -Rf $PROJECT_ROOT/admin/node_modules
rm -Rf $PROJECT_ROOT/dht-node/node_modules
rm -Rf $PROJECT_ROOT/federation/node_modules
# Remove build folders
# we had problems with corrupted incremtal builds
rm -Rf $PROJECT_ROOT/database/build
rm -Rf $PROJECT_ROOT/backend/build
rm -Rf $PROJECT_ROOT/frontend/build
rm -Rf $PROJECT_ROOT/admin/build
rm -Rf $PROJECT_ROOT/dht-node/build
rm -Rf $PROJECT_ROOT/federation/build
# Regenerate .env files
cp -f $PROJECT_ROOT/database/.env $PROJECT_ROOT/database/.env.bak
cp -f $PROJECT_ROOT/backend/.env $PROJECT_ROOT/backend/.env.bak

View File

@ -58,7 +58,7 @@ export default defineConfig({
mailserverURL: 'http://localhost:1080',
loginQuery: `mutation ($email: String!, $password: String!, $publisherId: Int) {
login(email: $email, password: $password, publisherId: $publisherId) {
email
id
firstName
lastName
language

View File

@ -1,3 +1,3 @@
node_modules/
dist/
build/
coverage/

2
frontend/.gitignore vendored
View File

@ -1,6 +1,6 @@
.DS_Store
node_modules/
dist/
build/
.cache/
npm-debug.log*
yarn-debug.log*

View File

@ -84,7 +84,7 @@ CMD /bin/sh -c "yarn run dev"
FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/dist ./dist
COPY --from=build ${DOCKER_WORKDIR}/build ./build
# We also copy the node_modules express and serve-static for the run script
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
# Copy static files

View File

@ -7,7 +7,7 @@
"serve": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"dev": "yarn run serve",
"analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json",
"analyse-bundle": "yarn build && webpack-bundle-analyzer build/webpack.stats.json",
"lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
"test": "cross-env TZ=UTC jest",

View File

@ -9,10 +9,10 @@ const port = process.env.PORT || 3000
// Express Server
const app = express()
// Serve files
app.use(express.static(path.join(__dirname, '../dist')))
app.use(express.static(path.join(__dirname, '../build')))
// Default to index.html
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../dist/index.html'))
res.sendFile(path.join(__dirname, '../build/index.html'))
})
app.listen(port, hostname, () => {

View File

@ -15,7 +15,7 @@ describe('LanguageSwitch', () => {
let wrapper
const state = {
email: 'he@ho.he',
gradidoID: 'current-user-id',
language: null,
}

View File

@ -31,7 +31,7 @@ export default {
async saveLocale(locale) {
// if (this.$i18n.locale === locale) return
this.setLocale(locale)
if (this.$store.state.email) {
if (this.$store.state.gradidoID) {
this.$apollo
.mutate({
mutation: updateUserInfos,

View File

@ -15,7 +15,7 @@ describe('LanguageSwitch', () => {
let wrapper
const state = {
email: 'he@ho.he',
gradidoID: 'current-user-id',
language: null,
}

View File

@ -59,7 +59,7 @@ export default {
async saveLocale(locale) {
if (this.$i18n.locale === locale) return
this.setLocale(locale)
if (this.$store.state.email) {
if (this.$store.state.gradidoID) {
this.$apollo
.mutate({
mutation: updateUserInfos,

View File

@ -20,7 +20,7 @@ const mocks = {
state: {
firstName: 'Testy',
lastName: 'User',
email: 'testy.user@example.com',
gradidoID: 'current-user-id',
},
},
}
@ -64,8 +64,8 @@ describe('AuthNavbar', () => {
)
})
it('has the email address', () => {
// expect(wrapper.find('div.small:nth-child(2)').text()).toBe(wrapper.vm.$store.state.email)
// I think this should be username
it.skip('has the email address', () => {
expect(wrapper.find('div[data-test="navbar-item-email"]').text()).toBe(
wrapper.vm.$store.state.email,
)

View File

@ -39,37 +39,5 @@ describe('AmountAndNameRow', () => {
expect(wrapper.find('div.gdd-transaction-list-item-name').find('a').exists()).toBe(false)
})
})
describe('with linked user', () => {
beforeEach(async () => {
await wrapper.setProps({
linkedUser: { firstName: 'Bibi', lastName: 'Bloxberg', email: 'bibi@bloxberg.de' },
})
})
it('has a link with first and last name', () => {
expect(wrapper.find('div.gdd-transaction-list-item-name').text()).toBe('Bibi Bloxberg')
})
it('has a link', () => {
expect(wrapper.find('div.gdd-transaction-list-item-name').find('a').exists()).toBe(true)
})
describe('click link', () => {
beforeEach(async () => {
await wrapper.find('div.gdd-transaction-list-item-name').find('a').trigger('click')
})
it('emits set tunneled email', () => {
expect(wrapper.emitted('set-tunneled-email')).toEqual([['bibi@bloxberg.de']])
})
it('pushes the route with query for email', () => {
expect(mocks.$router.push).toBeCalledWith({
path: '/send',
})
})
})
})
})
})

View File

@ -10,21 +10,7 @@
</b-col>
<b-col cols="7">
<div class="gdd-transaction-list-item-name">
<span v-if="linkedUser && linkedUser.email">
<b-link @click.stop="tunnelEmail">
{{ itemText }}
</b-link>
</span>
<span v-else>{{ itemText }}</span>
<span v-if="linkId">
{{ $t('via_link') }}
<b-icon
icon="link45deg"
variant="muted"
class="m-mb-1"
:title="$t('gdd_per_link.redeemed-title')"
/>
</span>
<span>{{ text }}</span>
</div>
</b-col>
</b-row>
@ -38,31 +24,9 @@ export default {
type: String,
required: true,
},
linkedUser: {
type: Object,
required: false,
},
text: {
type: String,
required: false,
},
linkId: {
type: Number,
required: false,
default: null,
},
},
methods: {
tunnelEmail() {
this.$emit('set-tunneled-email', this.linkedUser.email)
this.$router.push({ path: '/send' })
},
},
computed: {
itemText() {
return this.linkedUser
? this.linkedUser.firstName + ' ' + this.linkedUser.lastName
: this.text
required: true,
},
},
}

View File

@ -18,7 +18,6 @@ describe('UserCard_Newsletter', () => {
$store: {
state: {
language: 'de',
email: 'peter@lustig.de',
newsletterState: true,
},
commit: storeCommitMock,

View File

@ -145,7 +145,6 @@ export const login = gql`
mutation($email: String!, $password: String!, $publisherId: Int) {
login(email: $email, password: $password, publisherId: $publisherId) {
gradidoID
email
firstName
lastName
language

View File

@ -3,7 +3,7 @@ import gql from 'graphql-tag'
export const verifyLogin = gql`
query {
verifyLogin {
email
gradidoID
firstName
lastName
language
@ -40,7 +40,6 @@ export const transactionsQuery = gql`
firstName
lastName
gradidoID
email
}
decay {
decay
@ -102,9 +101,9 @@ export const queryTransactionLink = gql`
redeemedAt
deletedAt
user {
gradidoID
firstName
publisherId
email
}
}
... on ContributionLink {

View File

@ -43,7 +43,6 @@ const mocks = {
$store: {
dispatch: storeDispatchMock,
state: {
email: 'user@example.org',
publisherId: 123,
firstName: 'User',
lastName: 'Example',
@ -260,34 +259,6 @@ describe('DashboardLayout', () => {
})
})
describe.skip('elopage URI', () => {
describe('user has no publisher ID and no elopage', () => {
beforeEach(() => {
mocks.$store.state.publisherId = null
mocks.$store.state.hasElopage = false
wrapper = Wrapper()
})
it('links to basic-de', () => {
expect(wrapper.vm.elopageUri).toBe(
'https://elopage.com/s/gradido/basic-de/payment?locale=en&prid=111&pid=2896&firstName=User&lastName=Example&email=user@example.org',
)
})
})
describe('user has elopage', () => {
beforeEach(() => {
mocks.$store.state.publisherId = '123'
mocks.$store.state.hasElopage = true
wrapper = Wrapper()
})
it('links to sign in for elopage', () => {
expect(wrapper.vm.elopageUri).toBe('https://elopage.com/s/gradido/sign_in?locale=en')
})
})
})
describe.skip('admin method', () => {
const windowLocationMock = jest.fn()
beforeEach(() => {

View File

@ -32,7 +32,7 @@ apolloQueryMock.mockResolvedValue({
validUntil: transactionLinkValidExpireDate(),
redeemedAt: '2022-03-18T10:08:43.000Z',
deletedAt: null,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})
@ -44,7 +44,7 @@ const mocks = {
state: {
token: null,
tokenTime: null,
email: 'bibi@bloxberg.de',
gradidoID: 'current-user-id',
},
},
$apollo: {
@ -101,7 +101,7 @@ describe('TransactionLink', () => {
validUntil: transactionLinkValidExpireDate(),
redeemedAt: '2022-03-18T10:08:43.000Z',
deletedAt: now,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})
@ -132,7 +132,7 @@ describe('TransactionLink', () => {
validUntil: '2020-03-18T10:08:43.000Z',
redeemedAt: '2022-03-18T10:08:43.000Z',
deletedAt: null,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})
@ -163,7 +163,7 @@ describe('TransactionLink', () => {
validUntil: transactionLinkValidExpireDate(),
redeemedAt: '2022-03-18T10:08:43.000Z',
deletedAt: null,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})
@ -195,7 +195,7 @@ describe('TransactionLink', () => {
validUntil: transactionLinkValidExpireDate(),
redeemedAt: null,
deletedAt: null,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})
@ -239,7 +239,7 @@ describe('TransactionLink', () => {
validUntil: transactionLinkValidExpireDate(),
redeemedAt: null,
deletedAt: null,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'current-user-id' },
},
},
})
@ -275,7 +275,7 @@ describe('TransactionLink', () => {
validUntil: transactionLinkValidExpireDate(),
redeemedAt: null,
deletedAt: null,
user: { firstName: 'Peter', publisherId: 0, email: 'peter@listig.de' },
user: { firstName: 'Peter', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})
@ -351,7 +351,7 @@ describe('TransactionLink', () => {
validUntil: transactionLinkValidExpireDate(),
redeemedAt: null,
deletedAt: null,
user: { firstName: 'Bibi', publisherId: 0, email: 'bibi@bloxberg.de' },
user: { firstName: 'Bibi', publisherId: 0, gradidoID: 'other-user-id' },
},
},
})

View File

@ -139,7 +139,7 @@ export default {
if (this.tokenExpiresInSeconds < 5) return `LOGGED_OUT`
// logged in, nicht berechtigt einzulösen, eigener link
if (this.linkData.user && this.$store.state.email === this.linkData.user.email) {
if (this.linkData.user && this.$store.state.gradidoID === this.linkData.user.gradidoID) {
return `SELF_CREATOR`
}

View File

@ -13,8 +13,8 @@ export const mutations = {
localeChanged(language)
state.language = language
},
email: (state, email) => {
state.email = email
gradidoID: (state, gradidoID) => {
state.gradidoID = gradidoID
},
// username: (state, username) => {
// state.username = username
@ -57,7 +57,7 @@ export const mutations = {
export const actions = {
login: ({ dispatch, commit }, data) => {
commit('email', data.email)
commit('gradidoID', data.gradidoID)
commit('language', data.language)
// commit('username', data.username)
commit('firstName', data.firstName)
@ -71,8 +71,8 @@ export const actions = {
},
logout: ({ commit, state }) => {
commit('token', null)
commit('email', null)
// commit('username', '')
commit('gradidoID', null)
commit('firstName', '')
commit('lastName', '')
commit('newsletterState', null)
@ -96,8 +96,8 @@ try {
}),
],
state: {
email: '',
language: null,
gradidoID: null,
firstName: '',
lastName: '',
// username: '',

View File

@ -22,7 +22,7 @@ i18n.locale = 'blubb'
const {
language,
email,
gradidoID,
token,
firstName,
lastName,
@ -53,11 +53,11 @@ describe('Vuex store', () => {
})
})
describe('email', () => {
it('sets the state of email', () => {
const state = { email: 'nobody@knows.tv' }
email(state, 'someone@there.is')
expect(state.email).toEqual('someone@there.is')
describe('gradidoID', () => {
it('sets the state of gradidoID', () => {
const state = { gradidoID: 'old-id' }
gradidoID(state, 'new-id')
expect(state.gradidoID).toEqual('new-id')
})
})
@ -164,7 +164,7 @@ describe('Vuex store', () => {
const commit = jest.fn()
const state = {}
const commitedData = {
email: 'user@example.org',
gradidoID: 'my-gradido-id',
language: 'de',
firstName: 'Peter',
lastName: 'Lustig',
@ -183,9 +183,9 @@ describe('Vuex store', () => {
expect(commit).toHaveBeenCalledTimes(10)
})
it('commits email', () => {
it('commits gradidoID', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(1, 'email', 'user@example.org')
expect(commit).toHaveBeenNthCalledWith(1, 'gradidoID', 'my-gradido-id')
})
it('commits language', () => {
@ -248,9 +248,9 @@ describe('Vuex store', () => {
expect(commit).toHaveBeenNthCalledWith(1, 'token', null)
})
it('commits email', () => {
it('commits gradidoID', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(2, 'email', null)
expect(commit).toHaveBeenNthCalledWith(2, 'gradidoID', null)
})
it('commits firstName', () => {

View File

@ -64,5 +64,5 @@ module.exports = {
// Enable CSS source maps.
sourceMap: CONFIG.NODE_ENV !== 'production',
},
outputDir: path.resolve(__dirname, './dist'),
outputDir: path.resolve(__dirname, './build'),
}

View File

@ -71,7 +71,7 @@ server {
# TODO this could be a performance optimization
#location /vue {
# alias /var/www/html/gradido/frontend/dist;
# alias /var/www/html/gradido/frontend/build;
# index index.html;
#
# location ~* \.(png)$ {