Merge pull request #777 from gradido/jwt-setup

feat: JSON Web Token for Authentification
This commit is contained in:
Moriz Wahl 2021-09-01 14:50:07 +02:00 committed by GitHub
commit 8c729c1723
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 215 additions and 197 deletions

21
backend/src/auth/auth.ts Normal file
View File

@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AuthChecker } from 'type-graphql'
import decode from '../jwt/decode'
import { apiGet } from '../apis/loginAPI'
import CONFIG from '../config'
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
export const isAuthorized: AuthChecker<any> = async ({ root, args, context, info }, roles) => {
if (context.token) {
const decoded = decode(context.token)
if (decoded.sessionId && decoded.sessionId !== 0) {
const result = await apiGet(
`${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`,
)
context.sessionId = decoded.sessionId
return result.success
}
}
return false
}

View File

@ -17,9 +17,6 @@ export class GdtTransactionInput {
@ArgsType()
export class GdtTransactionSessionIdInput {
@Field(() => Number)
sessionId: number
@Field(() => Int, { nullable: true })
currentPage?: number

View File

@ -38,9 +38,6 @@ export class ChangePasswordArgs {
@ArgsType()
export class UpdateUserInfosArgs {
@Field(() => Number)
sessionId!: number
@Field(() => String)
email!: string

View File

@ -2,9 +2,6 @@ import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType()
export class TransactionListInput {
@Field(() => Number)
sessionId: number
@Field(() => Int)
firstPage: number
@ -17,9 +14,6 @@ export class TransactionListInput {
@ArgsType()
export class TransactionSendArgs {
@Field(() => Number)
sessionId: number
@Field(() => String)
email: string

View File

@ -1,20 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { ObjectType, Field } from 'type-graphql'
import { User } from './User'
// temporaray solution until we have JWT implemented
@ObjectType()
export class LoginResponse {
constructor(json: any) {
this.sessionId = json.session_id
this.user = new User(json.user)
}
@Field(() => Number)
sessionId: number
@Field(() => User)
user: User
}

View File

@ -1,13 +1,17 @@
import { Resolver, Query, /* Mutation, */ Arg } from 'type-graphql'
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Resolver, Query, Ctx, Authorized } from 'type-graphql'
import CONFIG from '../../config'
import { Balance } from '../models/Balance'
import { apiGet } from '../../apis/loginAPI'
@Resolver()
export class BalanceResolver {
@Authorized()
@Query(() => Balance)
async balance(@Arg('sessionId') sessionId: number): Promise<Balance> {
const result = await apiGet(CONFIG.COMMUNITY_API_URL + 'getBalance/' + sessionId)
async balance(@Ctx() context: any): Promise<Balance> {
const result = await apiGet(CONFIG.COMMUNITY_API_URL + 'getBalance/' + context.sessionId)
if (!result.success) throw new Error(result.data)
return new Balance(result.data)
}

View File

@ -1,5 +1,7 @@
// import jwt from 'jsonwebtoken'
import { Resolver, Query, /* Mutation, */ Args } from 'type-graphql'
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Resolver, Query, Args, Ctx, Authorized } from 'type-graphql'
import CONFIG from '../../config'
import { GdtEntryList } from '../models/GdtEntryList'
import { GdtTransactionSessionIdInput } from '../inputs/GdtInputs'
@ -7,14 +9,16 @@ import { apiGet } from '../../apis/loginAPI'
@Resolver()
export class GdtResolver {
@Authorized()
@Query(() => GdtEntryList)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async listGDTEntries(
@Args()
{ currentPage = 1, pageSize = 5, order = 'DESC', sessionId }: GdtTransactionSessionIdInput,
{ currentPage = 1, pageSize = 5, order = 'DESC' }: GdtTransactionSessionIdInput,
@Ctx() context: any,
): Promise<GdtEntryList> {
const result = await apiGet(
`${CONFIG.COMMUNITY_API_URL}listGDTTransactions/${currentPage}/${pageSize}/${order}/${sessionId}`,
`${CONFIG.COMMUNITY_API_URL}listGDTTransactions/${currentPage}/${pageSize}/${order}/${context.sessionId}`,
)
if (!result.success) {
throw new Error(result.data)

View File

@ -1,4 +1,7 @@
import { Resolver, Query, Args } from 'type-graphql'
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Resolver, Query, Args, Authorized, Ctx } from 'type-graphql'
import CONFIG from '../../config'
import { TransactionList } from '../models/Transaction'
import { TransactionListInput, TransactionSendArgs } from '../inputs/TransactionInput'
@ -6,23 +9,27 @@ import { apiGet, apiPost } from '../../apis/loginAPI'
@Resolver()
export class TransactionResolver {
@Authorized()
@Query(() => TransactionList)
async transactionList(
@Args() { sessionId, firstPage = 1, items = 25, order = 'DESC' }: TransactionListInput,
@Args() { firstPage = 1, items = 25, order = 'DESC' }: TransactionListInput,
@Ctx() context: any,
): Promise<TransactionList> {
const result = await apiGet(
`${CONFIG.COMMUNITY_API_URL}listTransactions/${firstPage}/${items}/${order}/${sessionId}`,
`${CONFIG.COMMUNITY_API_URL}listTransactions/${firstPage}/${items}/${order}/${context.sessionId}`,
)
if (!result.success) throw new Error(result.data)
return new TransactionList(result.data)
}
@Authorized()
@Query(() => String)
async sendCoins(
@Args() { sessionId, email, amount, memo }: TransactionSendArgs,
@Args() { email, amount, memo }: TransactionSendArgs,
@Ctx() context: any,
): Promise<string> {
const payload = {
session_id: sessionId,
session_id: context.sessionId,
target_email: email,
amount: amount * 10000,
memo,

View File

@ -1,8 +1,10 @@
// import jwt from 'jsonwebtoken'
import { Resolver, Query, Args, Arg } from 'type-graphql'
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Resolver, Query, Args, Arg, Authorized, Ctx } from 'type-graphql'
import CONFIG from '../../config'
import { CheckUsernameResponse } from '../models/CheckUsernameResponse'
import { LoginResponse } from '../models/LoginResponse'
import { User } from '../models/User'
import { LoginViaVerificationCode } from '../models/LoginViaVerificationCode'
import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse'
import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse'
@ -14,11 +16,12 @@ import {
UpdateUserInfosArgs,
} from '../inputs/LoginUserInput'
import { apiPost, apiGet } from '../../apis/loginAPI'
import encode from '../../jwt/encode'
@Resolver()
export class UserResolver {
@Query(() => LoginResponse)
async login(@Args() { email, password }: UnsecureLoginArgs): Promise<LoginResponse> {
@Query(() => String)
async login(@Args() { email, password }: UnsecureLoginArgs): Promise<string> {
email = email.trim().toLowerCase()
const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
@ -27,21 +30,10 @@ export class UserResolver {
throw new Error(result.data)
}
// temporary solution until we have JWT implemented
return new LoginResponse(result.data)
// create and return the json web token
// The expire doesn't help us here. The client needs to track when the token expires on its own,
// since every action prolongs the time the session is valid.
/*
return jwt.sign(
{ result, role: 'todo' },
CONFIG.JWT_SECRET, // * , { expiresIn: CONFIG.JWT_EXPIRES_IN } ,
)
*/
// return (await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', login)).result.data
// const loginResult: LoginResult = await loginAPI.login(data)
// return loginResult.user ? loginResult.user : new User()
const data = result.data
const sessionId = data.session_id
delete data.session_id
return encode({ sessionId, user: new User(data.user) })
}
@Query(() => LoginViaVerificationCode)
@ -59,9 +51,10 @@ export class UserResolver {
return new LoginViaVerificationCode(result.data)
}
@Authorized()
@Query(() => String)
async logout(@Arg('sessionId') sessionId: number): Promise<string> {
const payload = { session_id: sessionId }
async logout(@Ctx() context: any): Promise<string> {
const payload = { session_id: context.sessionId }
const result = await apiPost(CONFIG.LOGIN_API_URL + 'logout', payload)
if (!result.success) {
throw new Error(result.data)
@ -115,11 +108,11 @@ export class UserResolver {
return 'sucess'
}
@Authorized()
@Query(() => UpdateUserInfosResponse)
async updateUserInfos(
@Args()
{
sessionId,
email,
firstName,
lastName,
@ -129,9 +122,10 @@ export class UserResolver {
password,
passwordNew,
}: UpdateUserInfosArgs,
@Ctx() context: any,
): Promise<UpdateUserInfosResponse> {
const payload = {
session_id: sessionId,
session_id: context.sessionId,
email,
update: {
'User.first_name': firstName || undefined,

View File

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import 'reflect-metadata'
import express from 'express'
import { buildSchema } from 'type-graphql'
@ -8,17 +10,30 @@ import connection from './database/connection'
import CONFIG from './config'
// TODO move to extern
// import { BookResolver } from './graphql/resolvers/BookResolver'
import { UserResolver } from './graphql/resolvers/UserResolver'
import { BalanceResolver } from './graphql/resolvers/BalanceResolver'
import { GdtResolver } from './graphql/resolvers/GdtResolver'
import { TransactionResolver } from './graphql/resolvers/TransactionResolver'
import { isAuthorized } from './auth/auth'
// TODO implement
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
const DB_VERSION = '0001-init_db'
const context = (req: any) => {
const authorization = req.req.headers.authorization
let token = null
if (authorization) {
token = req.req.headers.authorization.replace(/^Bearer /, '')
}
const context = {
token,
}
return context
}
async function main() {
// check for correct database version
const con = await connection()
@ -34,6 +49,7 @@ async function main() {
// const connection = await createConnection()
const schema = await buildSchema({
resolvers: [UserResolver, BalanceResolver, TransactionResolver, GdtResolver],
authChecker: isAuthorized,
})
// Graphiql interface
@ -46,7 +62,7 @@ async function main() {
const server = express()
// Apollo Server
const apollo = new ApolloServer({ schema, playground })
const apollo = new ApolloServer({ schema, playground, context })
apollo.applyMiddleware({ app: server })
// Start Server

23
backend/src/jwt/decode.ts Normal file
View File

@ -0,0 +1,23 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import jwt from 'jsonwebtoken'
import CONFIG from '../config/'
export default (token: string): any => {
if (!token) return null
let sessionId = null
const email = null
try {
const decoded = jwt.verify(token, CONFIG.JWT_SECRET)
sessionId = decoded.sub
// email = decoded.email
return {
token,
sessionId,
email,
}
} catch (err) {
return null
}
}

18
backend/src/jwt/encode.ts Normal file
View File

@ -0,0 +1,18 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import jwt from 'jsonwebtoken'
import CONFIG from '../config/'
// Generate an Access Token
export default function encode(data: any): string {
const { user, sessionId } = data
const { email, language, firstName, lastName } = user
const token = jwt.sign({ email, language, firstName, lastName, sessionId }, CONFIG.JWT_SECRET, {
expiresIn: CONFIG.JWT_EXPIRES_IN,
// issuer: CONFIG.GRAPHQL_URI,
// audience: CONFIG.CLIENT_URI,
subject: sessionId.toString(),
})
return token
}

View File

@ -72,6 +72,7 @@
"vue-good-table": "^2.21.3",
"vue-i18n": "^8.22.4",
"vue-jest": "^3.0.7",
"vue-jwt-decode": "^0.1.0",
"vue-loading-overlay": "^3.4.2",
"vue-moment": "^4.1.0",
"vue-qrcode": "^0.3.5",

View File

@ -15,7 +15,6 @@ describe('LanguageSwitch', () => {
let wrapper
const state = {
sessionId: 1234,
email: 'he@ho.he',
language: null,
}
@ -123,7 +122,6 @@ describe('LanguageSwitch', () => {
expect(updateUserInfosQueryMock).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1234,
email: 'he@ho.he',
locale: 'en',
},
@ -136,7 +134,6 @@ describe('LanguageSwitch', () => {
expect(updateUserInfosQueryMock).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1234,
email: 'he@ho.he',
locale: 'de',
},

View File

@ -32,13 +32,13 @@ export default {
localeChanged(locale)
},
async saveLocale(locale) {
// if (this.$i18n.locale === locale) return
this.setLocale(locale)
if (this.$store.state.sessionId && this.$store.state.email) {
if (this.$store.state.email) {
this.$apollo
.query({
query: updateUserInfos,
variables: {
sessionId: this.$store.state.sessionId,
email: this.$store.state.email,
locale: locale,
},

View File

@ -2,23 +2,13 @@ import gql from 'graphql-tag'
export const login = gql`
query($email: String!, $password: String!) {
login(email: $email, password: $password) {
sessionId
user {
email
firstName
lastName
language
username
description
}
}
login(email: $email, password: $password)
}
`
export const logout = gql`
query($sessionId: Float!) {
logout(sessionId: $sessionId)
query {
logout
}
`
@ -39,7 +29,6 @@ export const loginViaEmailVerificationCode = gql`
export const updateUserInfos = gql`
query(
$sessionId: Float!
$email: String!
$firstName: String
$lastName: String
@ -50,7 +39,6 @@ export const updateUserInfos = gql`
$locale: String
) {
updateUserInfos(
sessionId: $sessionId
email: $email
firstName: $firstName
lastName: $lastName
@ -66,8 +54,8 @@ export const updateUserInfos = gql`
`
export const transactionsQuery = gql`
query($sessionId: Float!, $firstPage: Int = 1, $items: Int = 25, $order: String = "DESC") {
transactionList(sessionId: $sessionId, firstPage: $firstPage, items: $items, order: $order) {
query($firstPage: Int = 1, $items: Int = 25, $order: String = "DESC") {
transactionList(firstPage: $firstPage, items: $items, order: $order) {
gdtSum
count
balance
@ -103,8 +91,8 @@ export const resgisterUserQuery = gql`
`
export const sendCoins = gql`
query($sessionId: Float!, $email: String!, $amount: Float!, $memo: String!) {
sendCoins(sessionId: $sessionId, email: $email, amount: $amount, memo: $memo)
query($email: String!, $amount: Float!, $memo: String!) {
sendCoins(email: $email, amount: $amount, memo: $memo)
}
`
@ -125,8 +113,8 @@ export const checkUsername = gql`
`
export const listGDTEntriesQuery = gql`
query($currentPage: Int!, $pageSize: Int!, $sessionId: Float!) {
listGDTEntries(currentPage: $currentPage, pageSize: $pageSize, sessionId: $sessionId) {
query($currentPage: Int!, $pageSize: Int!) {
listGDTEntries(currentPage: $currentPage, pageSize: $pageSize) {
count
gdtEntries {
id

View File

@ -3,7 +3,7 @@ import DashboardPlugin from './plugins/dashboard-plugin'
import App from './App.vue'
import i18n from './i18n.js'
import { loadAllRules } from './validation-rules'
import ApolloClient from 'apollo-boost'
import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost'
import VueApollo from 'vue-apollo'
import CONFIG from './config'
@ -11,7 +11,21 @@ import { store } from './store/store'
import router from './routes/router'
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
const authLink = new ApolloLink((operation, forward) => {
const token = store.state.token
operation.setContext({
headers: {
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
},
})
return forward(operation)
})
const apolloClient = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
uri: CONFIG.GRAPHQL_URI,
})
@ -26,7 +40,7 @@ Vue.config.productionTip = false
loadAllRules(i18n)
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.state.sessionId) {
if (to.meta.requiresAuth && !store.state.token) {
next({ path: '/login' })
} else {
next()

View File

@ -1,6 +1,8 @@
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import VueJwtDecode from 'vue-jwt-decode'
Vue.use(Vuex)
export const mutations = {
@ -10,9 +12,6 @@ export const mutations = {
email: (state, email) => {
state.email = email
},
sessionId: (state, sessionId) => {
state.sessionId = sessionId
},
username: (state, username) => {
state.username = username
},
@ -25,43 +24,47 @@ export const mutations = {
description: (state, description) => {
state.description = description
},
token: (state, token) => {
state.token = token
},
}
export const actions = {
login: ({ dispatch, commit }, data) => {
commit('sessionId', data.sessionId)
commit('email', data.user.email)
commit('language', data.user.language)
commit('username', data.user.username)
commit('firstName', data.user.firstName)
commit('lastName', data.user.lastName)
commit('description', data.user.description)
login: ({ dispatch, commit }, token) => {
const decoded = VueJwtDecode.decode(token)
commit('token', token)
commit('email', decoded.email)
commit('language', decoded.language)
commit('username', decoded.username)
commit('firstName', decoded.firstName)
commit('lastName', decoded.lastName)
commit('description', decoded.description)
},
logout: ({ commit, state }) => {
commit('sessionId', null)
commit('token', null)
commit('email', null)
commit('username', '')
commit('firstName', '')
commit('lastName', '')
commit('description', '')
sessionStorage.clear()
localStorage.clear()
},
}
export const store = new Vuex.Store({
plugins: [
createPersistedState({
storage: window.sessionStorage,
storage: window.localStorage,
}),
],
state: {
sessionId: null,
email: '',
language: null,
firstName: '',
lastName: '',
username: '',
description: '',
token: null,
},
getters: {},
// Syncronous mutation of the state

View File

@ -1,6 +1,17 @@
import { mutations, actions } from './store'
import VueJwtDecode from 'vue-jwt-decode'
const { language, email, sessionId, username, firstName, lastName, description } = mutations
jest.mock('vue-jwt-decode')
VueJwtDecode.decode.mockReturnValue({
email: 'user@example.org',
language: 'de',
username: 'peter',
firstName: 'Peter',
lastName: 'Lustig',
description: 'Nickelbrille',
})
const { language, email, token, username, firstName, lastName, description } = mutations
const { login, logout } = actions
describe('Vuex store', () => {
@ -21,11 +32,11 @@ describe('Vuex store', () => {
})
})
describe('sessionId', () => {
it('sets the state of sessionId', () => {
const state = { sessionId: null }
sessionId(state, '1234')
expect(state.sessionId).toEqual('1234')
describe('token', () => {
it('sets the state of token', () => {
const state = { token: null }
token(state, '1234')
expect(state.token).toEqual('1234')
})
})
@ -66,41 +77,31 @@ describe('Vuex store', () => {
describe('login', () => {
const commit = jest.fn()
const state = {}
const commitedData = {
sessionId: 1234,
user: {
email: 'someone@there.is',
language: 'en',
username: 'user',
firstName: 'Peter',
lastName: 'Lustig',
description: 'Nickelbrille',
},
}
const commitedData = 'token'
it('calls seven commits', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenCalledTimes(7)
})
it('commits sessionId', () => {
it('commits token', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(1, 'sessionId', 1234)
expect(commit).toHaveBeenNthCalledWith(1, 'token', 'token')
})
it('commits email', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(2, 'email', 'someone@there.is')
expect(commit).toHaveBeenNthCalledWith(2, 'email', 'user@example.org')
})
it('commits language', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(3, 'language', 'en')
expect(commit).toHaveBeenNthCalledWith(3, 'language', 'de')
})
it('commits username', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(4, 'username', 'user')
expect(commit).toHaveBeenNthCalledWith(4, 'username', 'peter')
})
it('commits firstName', () => {
@ -128,9 +129,9 @@ describe('Vuex store', () => {
expect(commit).toHaveBeenCalledTimes(6)
})
it('commits sessionId', () => {
it('commits token', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(1, 'sessionId', null)
expect(commit).toHaveBeenNthCalledWith(1, 'token', null)
})
it('commits email', () => {
@ -159,7 +160,7 @@ describe('Vuex store', () => {
})
// how to get this working?
it.skip('calls sessionStorage.clear()', () => {
it.skip('calls localStorage.clear()', () => {
const clearStorageMock = jest.fn()
global.sessionStorage = jest.fn(() => {
return {

View File

@ -41,7 +41,6 @@ describe('DashboardLayoutGdd', () => {
},
$store: {
state: {
sessionId: 1,
email: 'user@example.org',
},
dispatch: storeDispatchMock,
@ -133,11 +132,7 @@ describe('DashboardLayoutGdd', () => {
})
it('calls the API', async () => {
expect(apolloMock).toBeCalledWith(
expect.objectContaining({
variables: { sessionId: 1 },
}),
)
expect(apolloMock).toBeCalled()
})
it('dispatches logout to store', () => {
@ -196,7 +191,6 @@ describe('DashboardLayoutGdd', () => {
expect(apolloMock).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
firstPage: 2,
items: 5,
},

View File

@ -92,7 +92,6 @@ export default {
this.$apollo
.query({
query: logout,
variables: { sessionId: this.$store.state.sessionId },
})
.then(() => {
this.$sidebar.displaySidebar(false)
@ -111,7 +110,6 @@ export default {
.query({
query: transactionsQuery,
variables: {
sessionId: this.$store.state.sessionId,
firstPage: pagination.firstPage,
items: pagination.items,
},

View File

@ -16,12 +16,12 @@ describe('AccountOverview', () => {
const mocks = {
$t: jest.fn((t) => t),
$n: jest.fn((n) => String(n)),
$store: {
state: {
sessionId: 1,
email: 'sender@example.org',
},
},
$n: jest.fn((n) => String(n)),
$apollo: {
query: sendMock,
},
@ -93,7 +93,6 @@ describe('AccountOverview', () => {
expect(sendMock).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
email: 'user@example.org',
amount: 23.45,
memo: 'Make the best of it!',

View File

@ -107,10 +107,7 @@ export default {
this.$apollo
.query({
query: sendCoins,
variables: {
sessionId: this.$store.state.sessionId,
...this.transactionData,
},
variables: this.transactionData,
})
.then(() => {
this.error = false

View File

@ -8,11 +8,6 @@ describe('GddSend', () => {
const mocks = {
$t: jest.fn((t) => t),
$store: {
state: {
sessionId: 1234,
},
},
$i18n: {
locale: jest.fn(() => 'en'),
},

View File

@ -57,11 +57,6 @@ describe('GdtTransactionList', () => {
$t: jest.fn((t) => t),
$n: jest.fn((n) => n),
$d: jest.fn((d) => d),
$store: {
state: {
sessionId: 1,
},
},
$toasted: {
error: toastErrorMock,
},
@ -89,7 +84,6 @@ describe('GdtTransactionList', () => {
expect(apolloMock).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
currentPage: 1,
pageSize: 25,
},

View File

@ -208,7 +208,6 @@ export default {
.query({
query: listGDTEntriesQuery,
variables: {
sessionId: this.$store.state.sessionId,
currentPage: this.currentPage,
pageSize: this.pageSize,
},

View File

@ -6,12 +6,7 @@ const localVue = global.localVue
const loginQueryMock = jest.fn().mockResolvedValue({
data: {
login: {
sessionId: 1,
user: {
name: 'Peter Lustig',
},
},
login: 'token',
},
})
@ -159,10 +154,7 @@ describe('Login', () => {
describe('login success', () => {
it('dispatches server response to store', () => {
expect(mockStoreDispach).toBeCalledWith('login', {
sessionId: 1,
user: { name: 'Peter Lustig' },
})
expect(mockStoreDispach).toBeCalledWith('login', 'token')
})
it('redirects to overview page', () => {

View File

@ -17,7 +17,6 @@ describe('UserCard_FormUserData', () => {
$t: jest.fn((t) => t),
$store: {
state: {
sessionId: 1,
email: 'user@example.org',
firstName: 'Peter',
lastName: 'Lustig',
@ -118,7 +117,6 @@ describe('UserCard_FormUserData', () => {
expect(mockAPIcall).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
email: 'user@example.org',
firstName: 'Petra',
lastName: 'Lustiger',
@ -167,7 +165,6 @@ describe('UserCard_FormUserData', () => {
expect(mockAPIcall).toBeCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
email: 'user@example.org',
firstName: 'Petra',
lastName: 'Lustiger',

View File

@ -85,7 +85,6 @@ export default {
data() {
return {
showUserData: true,
sessionId: this.$store.state.sessionId,
form: {
firstName: this.$store.state.firstName,
lastName: this.$store.state.lastName,
@ -118,7 +117,6 @@ export default {
.query({
query: updateUserInfos,
variables: {
sessionId: this.$store.state.sessionId,
email: this.$store.state.email,
firstName: this.form.firstName,
lastName: this.form.lastName,

View File

@ -14,7 +14,6 @@ describe('UserCard_FormUserMail', () => {
$t: jest.fn((t) => t),
$store: {
state: {
sessionId: 1,
email: 'user@example.org',
firstName: 'Peter',
lastName: 'Lustig',
@ -76,7 +75,6 @@ describe('UserCard_FormUserMail', () => {
expect(mockAPIcall).toHaveBeenCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
email: 'user@example.org',
newEmail: 'test@example.org',
},
@ -106,7 +104,6 @@ describe('UserCard_FormUserMail', () => {
expect(mockAPIcall).toHaveBeenCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
email: 'user@example.org',
newEmail: 'test@example.org',
},

View File

@ -48,7 +48,6 @@ export default {
.query({
query: updateUserInfos,
variables: {
sessionId: this.$store.state.sessionId,
email: this.$store.state.email,
newEmail: this.newEmail,
},

View File

@ -17,7 +17,6 @@ describe('UserCard_FormUserPasswort', () => {
$t: jest.fn((t) => t),
$store: {
state: {
sessionId: 1,
email: 'user@example.org',
},
},
@ -175,7 +174,6 @@ describe('UserCard_FormUserPasswort', () => {
expect(changePasswordProfileMock).toHaveBeenCalledWith(
expect.objectContaining({
variables: {
sessionId: 1,
email: 'user@example.org',
password: '1234',
passwordNew: 'Aa123456',

View File

@ -81,7 +81,6 @@ export default {
.query({
query: updateUserInfos,
variables: {
sessionId: this.$store.state.sessionId,
email: this.$store.state.email,
password: this.form.password,
passwordNew: this.form.newPassword.password,

View File

@ -25,7 +25,6 @@ describe('UserCard_FormUsername', () => {
$t: jest.fn((t) => t),
$store: {
state: {
sessionId: 1,
email: 'user@example.org',
username: '',
},
@ -111,7 +110,6 @@ describe('UserCard_FormUsername', () => {
expect.objectContaining({
variables: {
email: 'user@example.org',
sessionId: 1,
username: 'username',
},
}),
@ -151,7 +149,6 @@ describe('UserCard_FormUsername', () => {
expect.objectContaining({
variables: {
email: 'user@example.org',
sessionId: 1,
username: 'username',
},
}),

View File

@ -90,7 +90,6 @@ export default {
.query({
query: updateUserInfos,
variables: {
sessionId: this.$store.state.sessionId,
email: this.$store.state.email,
username: this.form.username,
},

View File

@ -13,11 +13,6 @@ describe('UserProfileTransactionList', () => {
$i18n: {
locale: jest.fn(() => 'en'),
},
$store: {
state: {
sessionId: 1,
},
},
}
const stubs = {

View File

@ -13576,6 +13576,13 @@ vue-jest@^3.0.5, vue-jest@^3.0.7:
tsconfig "^7.0.0"
vue-template-es2015-compiler "^1.6.0"
vue-jwt-decode@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/vue-jwt-decode/-/vue-jwt-decode-0.1.0.tgz#f9caf7b9030d5459cc567b1c3117d9d1f291458f"
integrity sha512-4iP0NzYHkAF7G13tYPc/nudk4oNpB8GCVZupc7lekxXok1XKEgefNaGTpDT14g7RKe5H9GaMphPduDj4UVfZwQ==
dependencies:
vue "^2.3.3"
vue-loader@^15.7.0:
version "15.9.6"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.9.6.tgz#f4bb9ae20c3a8370af3ecf09b8126d38ffdb6b8b"
@ -13655,6 +13662,11 @@ vue@^2.2.6, vue@^2.5.17, vue@^2.6.11:
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==
vue@^2.3.3:
version "2.6.14"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
integrity sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==
vuex-persistedstate@^4.0.0-beta.3:
version "4.0.0-beta.3"
resolved "https://registry.yarnpkg.com/vuex-persistedstate/-/vuex-persistedstate-4.0.0-beta.3.tgz#89dd712de72d28e85cc95467d066002c1405f277"