Detect 402 in frontend, allow me query

This commit is contained in:
Christian Cueni 2020-02-17 16:08:47 +01:00
parent c9c42e2296
commit 36c43bf4e1
5 changed files with 30 additions and 6 deletions

View File

@ -7,7 +7,7 @@ import fetch from 'unfetch'
import {typeDefs} from '@/graphql/typedefs';
import {resolvers} from '@/graphql/resolvers';
export default function (uri) {
export default function (uri, networkErrorCallback) {
const httpLink = createHttpLink({
// uri: process.env.NODE_ENV !== 'production' ? 'http://localhost:8000/api/graphql/' : '/api/graphql/',
uri,
@ -42,6 +42,12 @@ export default function (uri) {
});
const errorLink = onError(({response, operation, networkError, graphQLErrors}) => {
if (networkError && networkErrorCallback) {
networkErrorCallback(networkError.statusCode);
return Observable.of();
}
if (graphQLErrors) {
graphQLErrors.forEach(({message, locations, path}) =>
console.log(

View File

@ -64,8 +64,8 @@ if (process.env.GOOGLE_ANALYTICS_ID) {
Vue.directive('click-outside', clickOutside);
Vue.directive('auto-grow', autoGrow);
const publicApolloClient = apolloClientFactory('/api/graphql-public/');
const privateApolloClient = apolloClientFactory('/api/graphql/');
const publicApolloClient = apolloClientFactory('/api/graphql-public/', null);
const privateApolloClient = apolloClientFactory('/api/graphql/', networkErrorCallback);
const apolloProvider = new VueApollo({
clients: {
@ -140,7 +140,14 @@ function redirectStudentsWithoutClass() {
}).then(({data}) => data.me.schoolClasses.edges.length === 0 && data.me.permissions.length === 0);
}
function networkErrorCallback(statusCode) {
if (statusCode === 402) {
router.push({name: 'licenseActivation'}, 0);
}
}
router.beforeEach(async (to, from, next) => {
// handle logout
if (to.path === '/logout') {
privateApolloClient.resetStore();
@ -154,7 +161,7 @@ router.beforeEach(async (to, from, next) => {
return
}
if (to.name !== 'noClass' && loginRequired(to) && await redirectStudentsWithoutClass()) {
if ((to.name !== 'noClass' || to.name !== 'licenseActivation') && loginRequired(to) && await redirectStudentsWithoutClass()) {
next({name: 'noClass'})
return
}

View File

@ -1,3 +1,4 @@
import json
import re
from django.conf import settings
@ -104,6 +105,6 @@ class UserHasLicenseeMiddleWare(MiddlewareMixin):
def process_response(self, request, response):
if request.path == '/api/graphql/':
if not is_private_api_call_allowed(request.user, request.body):
return HttpResponse('License required', status=402)
return HttpResponse(json.dumps({'errors': ['no active license']}), status=402)
return response

View File

@ -46,3 +46,13 @@ class MiddlewareTestCase(TestCase):
body = b'"{mutation { logout {"'
self.assertTrue(is_private_api_call_allowed(user, body))
def test_me_query_is_allowed_without_valid_license(self):
yesterday = timezone.now() - timedelta(1)
user = UserFactory(username='aschiman@ch.ch')
user.license_expiry_date = yesterday
body = b'"{query { me {"'
self.assertTrue(is_private_api_call_allowed(user, body))

View File

@ -28,7 +28,7 @@ def is_private_api_call_allowed(user, body):
body_unicode = body.decode('utf-8')
if re.search(r"mutation\s*.*\s*logout\s*{", body_unicode):
if re.search(r"mutation\s*.*\s*logout\s*{", body_unicode) or re.search(r"query\s*.*\s*me\s*{", body_unicode):
return True
license_expiry = user.license_expiry_date