Merge branch 'feature/57-token-refresh' into 'develop'
Fixed #57: now refresh jwt token on page refresh Closes #57 See merge request funkwhale/funkwhale!36
This commit is contained in:
commit
a8a37603be
|
@ -46,9 +46,8 @@ v1_patterns += [
|
||||||
include(
|
include(
|
||||||
('funkwhale_api.users.api_urls', 'users'),
|
('funkwhale_api.users.api_urls', 'users'),
|
||||||
namespace='users')),
|
namespace='users')),
|
||||||
url(r'^token/',
|
url(r'^token/$', jwt_views.obtain_jwt_token, name='token'),
|
||||||
jwt_views.obtain_jwt_token),
|
url(r'^token/refresh/$', jwt_views.refresh_jwt_token, name='token_refresh'),
|
||||||
url(r'^token/refresh/', jwt_views.refresh_jwt_token),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -62,3 +62,38 @@ def test_can_fetch_data_from_api(client, factories):
|
||||||
assert payload['name'] == user.name
|
assert payload['name'] == user.name
|
||||||
assert payload['permissions']['import.launch']['status']
|
assert payload['permissions']['import.launch']['status']
|
||||||
assert payload['permissions']['settings.change']['status']
|
assert payload['permissions']['settings.change']['status']
|
||||||
|
|
||||||
|
|
||||||
|
def test_can_get_token_via_api(client, factories):
|
||||||
|
user = factories['users.User']()
|
||||||
|
url = reverse('api:v1:token')
|
||||||
|
payload = {
|
||||||
|
'username': user.username,
|
||||||
|
'password': 'test'
|
||||||
|
}
|
||||||
|
|
||||||
|
response = client.post(url, payload)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert '"token":' in response.content.decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def test_can_refresh_token_via_api(client, factories):
|
||||||
|
# first, we get a token
|
||||||
|
user = factories['users.User']()
|
||||||
|
url = reverse('api:v1:token')
|
||||||
|
payload = {
|
||||||
|
'username': user.username,
|
||||||
|
'password': 'test'
|
||||||
|
}
|
||||||
|
|
||||||
|
response = client.post(url, payload)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
token = json.loads(response.content.decode('utf-8'))['token']
|
||||||
|
url = reverse('api:v1:token_refresh')
|
||||||
|
response = client.post(url,{'token': token})
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert '"token":' in response.content.decode('utf-8')
|
||||||
|
# a different token should be returned
|
||||||
|
assert token in response.content.decode('utf-8')
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dateformat": "^2.0.0",
|
"dateformat": "^2.0.0",
|
||||||
"js-logger": "^1.3.0",
|
"js-logger": "^1.3.0",
|
||||||
|
"jwt-decode": "^2.2.0",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"semantic-ui-css": "^2.2.10",
|
"semantic-ui-css": "^2.2.10",
|
||||||
"vue": "^2.3.3",
|
"vue": "^2.3.3",
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import jwtDecode from 'jwt-decode'
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import logger from '@/logging'
|
import logger from '@/logging'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
|
||||||
const LOGIN_URL = config.API_URL + 'token/'
|
const LOGIN_URL = config.API_URL + 'token/'
|
||||||
|
const REFRESH_TOKEN_URL = config.API_URL + 'token/refresh/'
|
||||||
const USER_PROFILE_URL = config.API_URL + 'users/users/me/'
|
const USER_PROFILE_URL = config.API_URL + 'users/users/me/'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -13,7 +15,8 @@ export default {
|
||||||
username: '',
|
username: '',
|
||||||
availablePermissions: {},
|
availablePermissions: {},
|
||||||
profile: null,
|
profile: null,
|
||||||
token: ''
|
token: '',
|
||||||
|
tokenData: {}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
header: state => {
|
header: state => {
|
||||||
|
@ -32,6 +35,7 @@ export default {
|
||||||
},
|
},
|
||||||
token: (state, value) => {
|
token: (state, value) => {
|
||||||
state.token = value
|
state.token = value
|
||||||
|
state.tokenData = jwtDecode(value)
|
||||||
},
|
},
|
||||||
permission: (state, {key, status}) => {
|
permission: (state, {key, status}) => {
|
||||||
state.availablePermissions[key] = status
|
state.availablePermissions[key] = status
|
||||||
|
@ -70,6 +74,7 @@ export default {
|
||||||
commit('token', jwt)
|
commit('token', jwt)
|
||||||
logger.default.info('Logged back in as ' + username)
|
logger.default.info('Logged back in as ' + username)
|
||||||
dispatch('fetchProfile')
|
dispatch('fetchProfile')
|
||||||
|
dispatch('refreshToken')
|
||||||
} else {
|
} else {
|
||||||
logger.default.info('Anonymous user')
|
logger.default.info('Anonymous user')
|
||||||
commit('authenticated', false)
|
commit('authenticated', false)
|
||||||
|
@ -90,6 +95,15 @@ export default {
|
||||||
}, (response) => {
|
}, (response) => {
|
||||||
logger.default.info('Error while fetching user profile')
|
logger.default.info('Error while fetching user profile')
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
refreshToken ({commit, dispatch, state}) {
|
||||||
|
let resource = Vue.resource(REFRESH_TOKEN_URL)
|
||||||
|
return resource.save({}, {token: state.token}).then(response => {
|
||||||
|
logger.default.info('Refreshed auth token')
|
||||||
|
commit('token', response.data.token)
|
||||||
|
}, response => {
|
||||||
|
logger.default.error('Error while refreshing token', response.data)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue