diff --git a/src/middleware/user.js b/src/middleware/user.js index 63caafaf1e..b8ebb06d15 100644 --- a/src/middleware/user.js +++ b/src/middleware/user.js @@ -289,17 +289,20 @@ module.exports = function (middleware) { } let cid; + let privilege; if (req.params.hasOwnProperty('category_id')) { cid = req.params.category_id; + privilege = 'read'; } else if (req.params.hasOwnProperty('topic_id')) { cid = await topics.getTopicField(req.params.topic_id, 'cid'); + privilege = 'topics:read'; } else { return false; // not a category or topic url, no check required } const [registeredAllowed, verifiedAllowed] = await Promise.all([ - privilegeHelpers.isAllowedTo(['read'], 'registered-users', cid), - privilegeHelpers.isAllowedTo(['read'], 'verified-users', cid), + privilegeHelpers.isAllowedTo([privilege], 'registered-users', cid), + privilegeHelpers.isAllowedTo([privilege], 'verified-users', cid), ]); return !registeredAllowed.pop() && verifiedAllowed.pop(); diff --git a/test/controllers.js b/test/controllers.js index 87e7a460d7..fbe1901191 100644 --- a/test/controllers.js +++ b/test/controllers.js @@ -21,6 +21,7 @@ const translator = require('../src/translator'); const privileges = require('../src/privileges'); const plugins = require('../src/plugins'); const utils = require('../src/utils'); +const slugify = require('../src/slugify'); const helpers = require('./helpers'); const sleep = util.promisify(setTimeout); @@ -571,15 +572,27 @@ describe('Controllers', () => { describe('blocking access for unconfirmed emails', () => { let jar; let token; + const username = utils.generateUUID().slice(0, 10); before(async () => { jar = await helpers.registerUser({ - username: utils.generateUUID().slice(0, 10), + username, password: utils.generateUUID(), }); token = await helpers.getCsrfToken(jar); }); + async function abortInterstitial() { + await requestAsync(`${nconf.get('url')}/register/abort`, { + method: 'post', + jar, + simple: false, + headers: { + 'x-csrf-token': token, + }, + }); + } + it('should not apply if requireEmailAddress is not enabled', async () => { meta.config.requireEmailAddress = 0; @@ -600,11 +613,12 @@ describe('Controllers', () => { }, }); + console.log(res.headers.location); assert.strictEqual(res.headers.location, `${nconf.get('relative_path')}/`); meta.config.requireEmailAddress = 1; }); - it('should continue to redirect back to interstitial after an email is entered, as it is not confirmed', async () => { + it('should allow access to regular resources after an email is entered, even if unconfirmed', async () => { const res = await requestAsync(`${nconf.get('url')}/recent`, { jar, json: true, @@ -613,8 +627,56 @@ describe('Controllers', () => { simple: false, }); + assert.strictEqual(res.statusCode, 200); + }); + + it('should redirect back to interstitial for categories requiring validated email', async () => { + const name = utils.generateUUID(); + const { cid } = await categories.create({ name }); + await privileges.categories.rescind(['groups:read'], cid, ['registered-users']); + await privileges.categories.give(['groups:read'], cid, ['verified-users']); + const res = await requestAsync(`${nconf.get('url')}/category/${cid}/${slugify(name)}`, { + jar, + json: true, + resolveWithFullResponse: true, + followRedirect: false, + simple: false, + }); + assert.strictEqual(res.statusCode, 307); assert.strictEqual(res.headers.location, `${nconf.get('relative_path')}/register/complete`); + await abortInterstitial(); + }); + + it('should redirect back to interstitial for topics requiring validated email', async () => { + const name = utils.generateUUID(); + const { cid } = await categories.create({ name }); + await privileges.categories.rescind(['groups:topics:read'], cid, 'registered-users'); + await privileges.categories.give(['groups:topics:read'], cid, 'verified-users'); + const res = await requestAsync(`${nconf.get('url')}/category/${cid}/${slugify(name)}`, { + jar, + json: true, + resolveWithFullResponse: true, + followRedirect: false, + simple: false, + }); + + assert.strictEqual(res.statusCode, 200); + + const title = utils.generateUUID(); + const uid = await user.getUidByUsername(username); + const { topicData } = await topics.post({ uid, cid, title, content: utils.generateUUID() }); + const res2 = await requestAsync(`${nconf.get('url')}/topic/${topicData.tid}/${slugify(title)}`, { + jar, + json: true, + resolveWithFullResponse: true, + followRedirect: false, + simple: false, + }); + assert.strictEqual(res2.statusCode, 307); + assert.strictEqual(res2.headers.location, `${nconf.get('relative_path')}/register/complete`); + await abortInterstitial(); + await topics.purge(topicData.tid, uid); }); }); });