feat: Add tests for authentication helper

This commit is contained in:
Faruk AYDIN
2024-01-15 15:21:04 +01:00
parent 1e3ab75bb7
commit 782fa67320
2 changed files with 108 additions and 23 deletions

View File

@@ -3,7 +3,7 @@ import jwt from 'jsonwebtoken';
import appConfig from '../config/app.js'; import appConfig from '../config/app.js';
import User from '../models/user.js'; import User from '../models/user.js';
const isAuthenticated = rule()(async (_parent, _args, req) => { export const isAuthenticated = async (_parent, _args, req) => {
const token = req.headers['authorization']; const token = req.headers['authorization'];
if (token == null) return false; if (token == null) return false;
@@ -26,29 +26,32 @@ const isAuthenticated = rule()(async (_parent, _args, req) => {
} catch (error) { } catch (error) {
return false; return false;
} }
}); };
const authentication = shield( const isAuthenticatedRule = rule()(isAuthenticated);
{
Query: { export const authenticationRules = {
'*': isAuthenticated, Query: {
getAutomatischInfo: allow, '*': isAuthenticatedRule,
getConfig: allow, getAutomatischInfo: allow,
getNotifications: allow, getConfig: allow,
healthcheck: allow, getNotifications: allow,
listSamlAuthProviders: allow, healthcheck: allow,
}, listSamlAuthProviders: allow,
Mutation: {
'*': isAuthenticated,
forgotPassword: allow,
login: allow,
registerUser: allow,
resetPassword: allow,
},
}, },
{ Mutation: {
allowExternalErrors: true, '*': isAuthenticatedRule,
} forgotPassword: allow,
); login: allow,
registerUser: allow,
resetPassword: allow,
},
};
export const authenticationOptions = {
allowExternalErrors: true,
};
const authentication = shield(authenticationRules, authenticationOptions);
export default authentication; export default authentication;

View File

@@ -0,0 +1,82 @@
import { describe, it, expect, vi } from 'vitest';
import { allow } from 'graphql-shield';
import jwt from 'jsonwebtoken';
import User from '../models/user.js';
import {
isAuthenticated,
isAuthenticatedRule,
authenticationRules,
} from './authentication.js';
vi.mock('jsonwebtoken');
vi.mock('../models/user.js');
describe('isAuthenticated', () => {
it('should return false if no token is provided', async () => {
const req = { headers: {} };
expect(await isAuthenticated(null, null, req)).toBe(false);
});
it('should return false if token is invalid', async () => {
jwt.verify.mockImplementation(() => {
throw new Error('invalid token');
});
const req = { headers: { authorization: 'invalidToken' } };
expect(await isAuthenticated(null, null, req)).toBe(false);
});
it('should return true if token is valid', async () => {
jwt.verify.mockReturnValue({ userId: '123' });
User.query.mockReturnValue({
findById: vi.fn().mockReturnValue({
leftJoinRelated: vi.fn().mockReturnThis(),
withGraphFetched: vi
.fn()
.mockResolvedValue({ id: '123', role: {}, permissions: {} }),
}),
});
const req = { headers: { authorization: 'validToken' } };
expect(await isAuthenticated(null, null, req)).toBe(true);
});
});
describe('authentication rules', () => {
const getQueryAndMutationNames = (rules) => {
const queries = Object.keys(rules.Query || {});
const mutations = Object.keys(rules.Mutation || {});
return { queries, mutations };
};
const { queries, mutations } = getQueryAndMutationNames(authenticationRules);
describe('for queries', () => {
queries.forEach((query) => {
it(`should apply correct rule for query: ${query}`, () => {
const ruleApplied = authenticationRules.Query[query];
if (query === '*') {
expect(ruleApplied.func).toBe(isAuthenticated);
} else {
expect(ruleApplied).toEqual(allow);
}
});
});
});
describe('for mutations', () => {
mutations.forEach((mutation) => {
it(`should apply correct rule for mutation: ${mutation}`, () => {
const ruleApplied = authenticationRules.Mutation[mutation];
if (mutation === '*') {
expect(ruleApplied.func).toBe(isAuthenticated);
} else {
expect(ruleApplied).toBe(allow);
}
});
});
});
});