mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
✨ Added success indicator for members magic links
- Add a query param that indicates whether signin/up succeeded or failed - Add unit tests for all 3 possible cases for the createSessionFromMagicLink middleware - Added an acceptance test to show the behaviour works in principle
This commit is contained in:
parent
11f7834800
commit
998eb62e22
3 changed files with 109 additions and 4 deletions
|
@ -108,16 +108,18 @@ const createSessionFromMagicLink = async function (req, res, next) {
|
||||||
|
|
||||||
// We need to include the subdirectory,
|
// We need to include the subdirectory,
|
||||||
// members is already removed from the path by express because it's a mount path
|
// members is already removed from the path by express because it's a mount path
|
||||||
const redirectPath = `${urlUtils.getSubdir()}${req.path}?${searchParams.toString()}`;
|
let redirectPath = `${urlUtils.getSubdir()}${req.path}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await membersService.ssr.exchangeTokenForSession(req, res);
|
await membersService.ssr.exchangeTokenForSession(req, res);
|
||||||
|
|
||||||
// Do a standard 302 redirect
|
// Do a standard 302 redirect, with success=true
|
||||||
return res.redirect(redirectPath);
|
searchParams.set('success', true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logging.warn(err.message);
|
logging.warn(err.message);
|
||||||
return res.redirect(redirectPath);
|
searchParams.set('success', false);
|
||||||
|
} finally {
|
||||||
|
res.redirect(`${redirectPath}?${searchParams.toString()}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,18 @@ describe('Basic Members Routes', function () {
|
||||||
return request.put('/members/api/subscriptions/123')
|
return request.put('/members/api/subscriptions/123')
|
||||||
.expect(400);
|
.expect(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should serve theme 404 on members endpoint', function () {
|
||||||
|
return request.get('/members/')
|
||||||
|
.expect(404)
|
||||||
|
.expect('Content-Type', 'text/html; charset=utf-8');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should redirect invalid token on members endpoint', function () {
|
||||||
|
return request.get('/members/?token=abc&action=signup')
|
||||||
|
.expect(302)
|
||||||
|
.expect('Location', '/?action=signup&success=false');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -161,6 +173,16 @@ describe('Basic Members Routes', function () {
|
||||||
return request.put('/members/api/subscriptions/123')
|
return request.put('/members/api/subscriptions/123')
|
||||||
.expect(404);
|
.expect(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should serve 404 on members endpoint', function () {
|
||||||
|
return request.get('/members/')
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not redirect members endpoint with token', function () {
|
||||||
|
return request.get('/members/?token=abc&action=signup')
|
||||||
|
.expect(404);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
81
test/unit/services/members/middleware_spec.js
Normal file
81
test/unit/services/members/middleware_spec.js
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
const should = require('should');
|
||||||
|
const sinon = require('sinon');
|
||||||
|
|
||||||
|
const urlUtils = require('../../../../core/server/lib/url-utils');
|
||||||
|
const membersService = require('../../../../core/server/services/members');
|
||||||
|
const membersMiddleware = require('../../../../core/server/services/members/middleware');
|
||||||
|
|
||||||
|
describe('Members Service Middleware', function () {
|
||||||
|
describe('createSessionFromMagicLink', function () {
|
||||||
|
let req;
|
||||||
|
let res;
|
||||||
|
let next;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
req = {};
|
||||||
|
res = {};
|
||||||
|
next = sinon.stub();
|
||||||
|
|
||||||
|
res.redirect = sinon.stub().returns('');
|
||||||
|
|
||||||
|
// Stub the members Service, handle this in separate tests
|
||||||
|
membersService.ssr.exchangeTokenForSession = sinon.stub();
|
||||||
|
|
||||||
|
sinon.stub(urlUtils, 'getSubdir').returns('/blah');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
sinon.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls next if url does not include a token', async function () {
|
||||||
|
// This recreates what express does, note: members is mounted so path will be /
|
||||||
|
req.url = '/members';
|
||||||
|
req.path = '/';
|
||||||
|
req.query = {};
|
||||||
|
|
||||||
|
// Call the middleware
|
||||||
|
await membersMiddleware.createSessionFromMagicLink(req, res, next);
|
||||||
|
|
||||||
|
// Check behaviour
|
||||||
|
next.calledOnce.should.be.true();
|
||||||
|
next.firstCall.args.should.be.an.Array().with.lengthOf(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects correctly on success', async function () {
|
||||||
|
// This recreates what express does, note: members is mounted so path will be /
|
||||||
|
req.url = '/members?token=test&action=signup';
|
||||||
|
req.path = '/';
|
||||||
|
req.query = {token: 'test', action: 'signup'};
|
||||||
|
|
||||||
|
// Fake token handling success
|
||||||
|
membersService.ssr.exchangeTokenForSession.resolves();
|
||||||
|
|
||||||
|
// Call the middleware
|
||||||
|
await membersMiddleware.createSessionFromMagicLink(req, res, next);
|
||||||
|
|
||||||
|
// Check behaviour
|
||||||
|
next.calledOnce.should.be.false();
|
||||||
|
res.redirect.calledOnce.should.be.true();
|
||||||
|
res.redirect.firstCall.args[0].should.eql('/blah/?action=signup&success=true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('redirects correctly on failure', async function () {
|
||||||
|
// This recreates what express does, note: members is mounted so path will be /
|
||||||
|
req.url = '/members?token=test&action=signup';
|
||||||
|
req.path = '/';
|
||||||
|
req.query = {token: 'test', action: 'signup'};
|
||||||
|
|
||||||
|
// Fake token handling failure
|
||||||
|
membersService.ssr.exchangeTokenForSession.rejects();
|
||||||
|
|
||||||
|
// Call the middleware
|
||||||
|
await membersMiddleware.createSessionFromMagicLink(req, res, next);
|
||||||
|
|
||||||
|
// Check behaviour
|
||||||
|
next.calledOnce.should.be.false();
|
||||||
|
res.redirect.calledOnce.should.be.true();
|
||||||
|
res.redirect.firstCall.args[0].should.eql('/blah/?action=signup&success=false');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue