Get rid of JWT_SECRET once and for all

* refactor store/auth.js not to use `delete Object`
* refactor store/auth.js to have less redundancy
* implement fetchCurrentUser without knowing the id beforehand
* test fetchCurrentUser and init
This commit is contained in:
Robert Schäfer 2019-02-26 15:43:03 +01:00
parent 165b296499
commit 71ab2f3828
4 changed files with 141 additions and 58 deletions

View File

@ -1,2 +1 @@
JWT_SECRET="b/&&7b78BF&fv/Vd"
MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.KZ8KK9l70omjXbEkkbHGsQ"

View File

@ -14,7 +14,6 @@ services:
environment:
- HOST=0.0.0.0
- BACKEND_URL=http://backend:4000
- JWT_SECRET=b/&&7b78BF&fv/Vd
- MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.bZ8KK9l70omjXbEkkbHGsQ"
networks:

View File

@ -57,56 +57,44 @@ export const actions = {
if (!token) {
return
}
const payload = await jwt.verify(token, process.env.JWT_SECRET)
if (!payload.id) {
return
}
commit('SET_TOKEN', token)
commit('SET_USER', {
id: payload.id
})
await dispatch('fetchCurrentUser')
},
async check({ commit, dispatch, getters }) {
if (!this.app.$apolloHelpers.getToken()) {
await dispatch('logout')
}
return getters.isLoggedIn
},
async fetchCurrentUser({ commit, getters }) {
await this.app.apolloProvider.defaultClient
.query({
query: gql(`
query User($id: ID!) {
User(id: $id) {
id
name
slug
email
avatar
role
locationName
about
}
async fetchCurrentUser({ commit }) {
const client = this.app.apolloProvider.defaultClient
const {
data: { currentUser }
} = await client.query({
query: gql(`{
currentUser {
id
name
slug
email
avatar
role
}
`),
variables: { id: getters.user.id }
})
.then(({ data }) => {
const user = data.User.pop()
if (user.id && user.email) {
commit('SET_USER', user)
}
})
return getters.user
}`)
})
const { token, ...user } = currentUser
commit('SET_USER', user)
return user
},
async login({ commit }, { email, password }) {
commit('SET_PENDING', true)
try {
const res = await this.app.apolloProvider.defaultClient
.mutate({
mutation: gql(`
const client = this.app.apolloProvider.defaultClient
const {
data: { login }
} = await client.mutate({
mutation: gql(`
mutation($email: String!, $password: String!) {
login(email: $email, password: $password) {
id
@ -121,15 +109,13 @@ export const actions = {
}
}
`),
variables: { email, password }
})
.then(({ data }) => data && data.login)
variables: { email, password }
})
const { token, ...user } = login
await this.app.$apolloHelpers.onLogin(res.token)
commit('SET_TOKEN', res.token)
const userData = Object.assign({}, res)
delete userData.token
commit('SET_USER', userData)
await this.app.$apolloHelpers.onLogin(token)
commit('SET_TOKEN', token)
commit('SET_USER', user)
} catch (err) {
throw new Error(err)
} finally {

View File

@ -2,23 +2,35 @@ import { getters, mutations, actions } from './auth.js'
let state
let commit
let dispatch
const token =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InUzIiwic2x1ZyI6Implbm55LXJvc3RvY2siLCJuYW1lIjoiSmVubnkgUm9zdG9jayIsImF2YXRhciI6Imh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS91aWZhY2VzL2ZhY2VzL3R3aXR0ZXIvbXV0dV9rcmlzaC8xMjguanBnIiwiZW1haWwiOiJ1c2VyQGV4YW1wbGUub3JnIiwicm9sZSI6InVzZXIiLCJpYXQiOjE1NDUxNDQ2ODgsImV4cCI6MTYzMTU0NDY4OCwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo0MDAwIiwic3ViIjoidTMifQ.s5_JeQN9TaUPfymAXPOpbMAwhmTIg9cnOvNEcj4z75k'
const currentUser = {
id: 'u3',
name: 'Jenny Rostock',
slug: 'jenny-rostock',
email: 'user@example.org',
avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/mutu_krish/128.jpg',
role: 'user'
}
const successfulLoginResponse = {
data: {
login: {
id: 'u3',
name: 'Jenny Rostock',
slug: 'jenny-rostock',
email: 'user@example.org',
avatar:
'https://s3.amazonaws.com/uifaces/faces/twitter/mutu_krish/128.jpg',
role: 'user',
...currentUser,
token
}
}
}
const successfulCurrentUserResponse = {
data: {
currentUser: {
...currentUser,
token
}
}
}
const incorrectPasswordResponse = {
data: {
login: null
@ -39,6 +51,7 @@ const incorrectPasswordResponse = {
beforeEach(() => {
commit = jest.fn()
dispatch = jest.fn(() => Promise.resolve())
})
describe('getters', () => {
@ -55,16 +68,102 @@ describe('getters', () => {
describe('actions', () => {
let action
describe('init', () => {
const theAction = () => {
const module = {
app: {
$apolloHelpers: {
getToken: () => token
}
}
}
action = actions.init.bind(module)
return action({ commit, dispatch })
}
describe('client-side', () => {
beforeEach(() => {
process.server = false
})
it('returns', async () => {
await theAction()
expect(dispatch.mock.calls).toEqual([])
expect(commit.mock.calls).toEqual([])
})
})
describe('server-side', () => {
beforeEach(() => {
process.server = true
})
it('fetches the current user', async () => {
await theAction()
expect(dispatch.mock.calls).toEqual([['fetchCurrentUser']])
})
it('saves the JWT Bearer token', async () => {
await theAction()
expect(commit.mock.calls).toEqual(
expect.arrayContaining([['SET_TOKEN', token]])
)
})
})
})
describe('fetchCurrentUser', () => {
describe('given a successful response', () => {
beforeEach(async () => {
const module = {
app: {
apolloProvider: {
defaultClient: {
query: jest.fn(() =>
Promise.resolve(successfulCurrentUserResponse)
)
}
}
}
}
action = actions.fetchCurrentUser.bind(module)
await action({ commit })
})
it('saves user data without token', () => {
expect(commit.mock.calls).toEqual(
expect.arrayContaining([
[
'SET_USER',
{
id: 'u3',
name: 'Jenny Rostock',
slug: 'jenny-rostock',
email: 'user@example.org',
avatar:
'https://s3.amazonaws.com/uifaces/faces/twitter/mutu_krish/128.jpg',
role: 'user'
}
]
])
)
})
})
})
describe('login', () => {
describe('given valid credentials and a successful response', () => {
beforeEach(async () => {
const response = Object.assign({}, successfulLoginResponse)
const mutate = jest.fn(() => Promise.resolve(response))
const onLogin = jest.fn(() => Promise.resolve())
const module = {
app: {
apolloProvider: { defaultClient: { mutate } },
$apolloHelpers: { onLogin }
apolloProvider: {
defaultClient: {
mutate: jest.fn(() => Promise.resolve(successfulLoginResponse))
}
},
$apolloHelpers: {
onLogin: jest.fn(() => Promise.resolve())
}
}
}
action = actions.login.bind(module)