feat: Add tests for authentication helper
This commit is contained in:
@@ -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;
|
||||||
|
82
packages/backend/src/helpers/authentication.test.js
Normal file
82
packages/backend/src/helpers/authentication.test.js
Normal 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user