Skip to content

Commit

Permalink
Fix #734: add mock authentication for testing
Browse files Browse the repository at this point in the history
  • Loading branch information
humphd committed Apr 2, 2020
1 parent 736eb97 commit 1130acc
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 6 deletions.
86 changes: 86 additions & 0 deletions src/backend/web/__mocks__/authentication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* Mock SAML2 SSO Passport.js authentication strategy.
*/
const hash = require('../../data/hash');

let loggedInUser;

/**
* Override init() to provide login for tests
*/
function init(name, email, isAdmin = false) {
if (arguments.length >= 2) {
// Log in
loggedInUser = {
id: hash(email),
name,
email,
isAdmin,
};
} else {
// Log out
loggedInUser = null;
}
}

function samlMetadata() {
return 'metadata';
}

// If user is not authenticated, return an appropriate 400 error type
function forbidden(req, res) {
if (req.accepts('json')) {
res.status(403).json({
message: 'Forbidden',
});
} else {
res.status(403).send('Forbidden');
}
}

function checkUser(requireAdmin, redirect, req, res, next) {
// First, see if the user is authenticated
if (loggedInUser) {
// Next, check to see if we need admin rights to pass
if (requireAdmin) {
// See if this user is an admin
if (loggedInUser.isAdmin) {
next();
}
// Not an admin, so fail this now using best response type
else {
forbidden(req, res);
}
} else {
// We don't need an admin, and this is a regular authenticated user, let it pass
next();
}
} else {
forbidden(req, res);
}
}

// We'll deal with admin via init(), just let this pass
function administration() {
return function(req, res, next) {
next();
};
}

function protect(redirect) {
return function(req, res, next) {
checkUser(false, redirect, req, res, next);
};
}

function protectAdmin(redirect) {
return function(req, res, next) {
checkUser(true, redirect, req, res, next);
};
}

module.exports.init = init;
module.exports.protect = protect;
module.exports.protectAdmin = protectAdmin;
module.exports.administration = administration;
module.exports.samlMetadata = samlMetadata;
1 change: 0 additions & 1 deletion src/backend/web/authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,5 +246,4 @@ module.exports.init = init;
module.exports.protect = protect;
module.exports.protectAdmin = protectAdmin;
module.exports.administration = administration;
module.exports.strategy = strategy;
module.exports.samlMetadata = samlMetadata;
6 changes: 2 additions & 4 deletions src/backend/web/routes/feeds.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const express = require('express');
const Feed = require('../../data/feed');
const { getFeeds } = require('../../utils/storage');
const { logger } = require('../../utils/logger');
// const { protect } = require('../authentication'); https://github.com/Seneca-CDOT/telescope/issues/734
const { protect } = require('../authentication');

const feeds = express.Router();

Expand Down Expand Up @@ -51,9 +51,7 @@ feeds.get('/:id', async (req, res) => {
}
});

// add protect here for development. https://github.com/Seneca-CDOT/telescope/issues/734

feeds.post('/', async (req, res) => {
feeds.post('/', protect(), async (req, res) => {
const feedData = req.body;
try {
if (!(feedData.url && feedData.author)) {
Expand Down
22 changes: 21 additions & 1 deletion test/feeds.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const hash = require('../src/backend/data/hash');

jest.mock('../src/backend/utils/elastic');

// Mock the internal authentication strategy
jest.mock('../src/backend/web/authentication');
// Use our authentication test helper
const { login, logout } = require('./lib/authentication');

describe('test GET /feeds endpoint', () => {
const createdItems = 150;

Expand Down Expand Up @@ -68,8 +73,23 @@ describe('test /feeds/:id responses', () => {
});
});

// https://github.com/Seneca-CDOT/telescope/issues/734 Tests below will need to have authorization to pass.
describe('test POST /feeds endpoint', () => {
beforeEach(() => login());

it('fails if not logged in', async () => {
const feedData = {
author: 'foo',
url: 'http://telescope200.cdot.systems',
user: 'user',
};
logout();
const res = await request(app)
.post('/feeds')
.send(feedData)
.set('Accept', 'application/json');
expect(res.status).toEqual(403);
});

it('responds with json', async () => {
const feedData = {
author: 'foo',
Expand Down
22 changes: 22 additions & 0 deletions test/lib/authentication.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// NOTE: you must mock the authentication provider where you require this:
// jest.mock('../src/backend/web/authentication');

const { init } = require('../../src/backend/web/authentication');

const defaultName = 'user1';
const defaultEmail = 'user1@example.com';

// Login as a regular user
module.exports.login = function(name, email, isAdmin = false) {
init(name || defaultName, email || defaultEmail, isAdmin);
};

// Login as an Admin
module.exports.loginAdmin = function(name, email) {
module.exports.login(name, email, true);
};

// Logout
module.exports.logout = function() {
init();
};

0 comments on commit 1130acc

Please sign in to comment.