fix: check if user has read priv before flagging

This commit is contained in:
Barış Soner Uşaklı
2020-01-22 12:14:50 -05:00
parent 1f13ab8a19
commit 51236df4ed
2 changed files with 45 additions and 14 deletions

View File

@@ -251,18 +251,21 @@ Flags.create = async function (type, id, uid, reason, timestamp) {
timestamp = Date.now(); timestamp = Date.now();
doHistoryAppend = true; doHistoryAppend = true;
} }
const [exists, targetExists, targetUid, targetCid] = await Promise.all([ const [flagExists, targetExists, canFlag, targetUid, targetCid] = await Promise.all([
// Sanity checks // Sanity checks
Flags.exists(type, id, uid), Flags.exists(type, id, uid),
Flags.targetExists(type, id), Flags.targetExists(type, id),
Flags.canFlag(type, id, uid),
// Extra data for zset insertion // Extra data for zset insertion
Flags.getTargetUid(type, id), Flags.getTargetUid(type, id),
Flags.getTargetCid(type, id), Flags.getTargetCid(type, id),
]); ]);
if (exists) { if (flagExists) {
throw new Error('[[error:already-flagged]]'); throw new Error('[[error:already-flagged]]');
} else if (!targetExists) { } else if (!targetExists) {
throw new Error('[[error:invalid-data]]'); throw new Error('[[error:invalid-data]]');
} else if (!canFlag) {
throw new Error('[[error:no-privileges]]');
} }
const flagId = await db.incrObjectField('global', 'nextFlagId'); const flagId = await db.incrObjectField('global', 'nextFlagId');
@@ -307,6 +310,16 @@ Flags.exists = async function (type, id, uid) {
return await db.isSortedSetMember('flags:hash', [type, id, uid].join(':')); return await db.isSortedSetMember('flags:hash', [type, id, uid].join(':'));
}; };
Flags.canFlag = async function (type, id, uid) {
if (type === 'user') {
return true;
}
if (type === 'post') {
return await privileges.posts.can('topics:read', id, uid);
}
throw new Error('[[error:invalid-data]]');
};
Flags.getTarget = async function (type, id, uid) { Flags.getTarget = async function (type, id, uid) {
if (type === 'user') { if (type === 'user') {
const userData = await user.getUserData(id); const userData = await user.getUserData(id);

View File

@@ -11,18 +11,19 @@ var Posts = require('../src/posts');
var User = require('../src/user'); var User = require('../src/user');
var Groups = require('../src/groups'); var Groups = require('../src/groups');
var Meta = require('../src/meta'); var Meta = require('../src/meta');
var Privileges = require('../src/privileges');
describe('Flags', function () { describe('Flags', function () {
let uid1; let uid1;
let uid2; let adminUid;
let uid3; let uid3;
let category; let category;
before(async () => { before(async () => {
// Create some stuff to flag // Create some stuff to flag
uid1 = await User.create({ username: 'testUser', password: 'abcdef', email: 'b@c.com' }); uid1 = await User.create({ username: 'testUser', password: 'abcdef', email: 'b@c.com' });
uid2 = await User.create({ username: 'testUser2', password: 'abcdef', email: 'c@d.com' }); adminUid = await User.create({ username: 'testUser2', password: 'abcdef', email: 'c@d.com' });
await Groups.join('administrators', uid2); await Groups.join('administrators', adminUid);
category = await Categories.create({ category = await Categories.create({
name: 'test category', name: 'test category',
@@ -264,9 +265,9 @@ describe('Flags', function () {
describe('.update()', function () { describe('.update()', function () {
it('should alter a flag\'s various attributes and persist them to the database', function (done) { it('should alter a flag\'s various attributes and persist them to the database', function (done) {
Flags.update(1, uid2, { Flags.update(1, adminUid, {
state: 'wip', state: 'wip',
assignee: uid2, assignee: adminUid,
}, function (err) { }, function (err) {
assert.ifError(err); assert.ifError(err);
db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) { db.getObjectFields('flag:1', ['state', 'assignee'], function (err, data) {
@@ -276,7 +277,7 @@ describe('Flags', function () {
assert.strictEqual('wip', data.state); assert.strictEqual('wip', data.state);
assert.ok(!isNaN(parseInt(data.assignee, 10))); assert.ok(!isNaN(parseInt(data.assignee, 10)));
assert.strictEqual(uid2, parseInt(data.assignee, 10)); assert.strictEqual(adminUid, parseInt(data.assignee, 10));
done(); done();
}); });
}); });
@@ -305,17 +306,17 @@ describe('Flags', function () {
}); });
it('should allow assignment if user is an admin and do nothing otherwise', async () => { it('should allow assignment if user is an admin and do nothing otherwise', async () => {
await Flags.update(1, uid2, { await Flags.update(1, adminUid, {
assignee: uid2, assignee: adminUid,
}); });
let assignee = await db.getObjectField('flag:1', 'assignee'); let assignee = await db.getObjectField('flag:1', 'assignee');
assert.strictEqual(uid2, parseInt(assignee, 10)); assert.strictEqual(adminUid, parseInt(assignee, 10));
await Flags.update(1, uid2, { await Flags.update(1, adminUid, {
assignee: uid3, assignee: uid3,
}); });
assignee = await db.getObjectField('flag:1', 'assignee'); assignee = await db.getObjectField('flag:1', 'assignee');
assert.strictEqual(uid2, parseInt(assignee, 10)); assert.strictEqual(adminUid, parseInt(assignee, 10));
}); });
it('should allow assignment if user is a global mod and do nothing otherwise', async () => { it('should allow assignment if user is a global mod and do nothing otherwise', async () => {
@@ -355,7 +356,7 @@ describe('Flags', function () {
}); });
it('should do nothing when you attempt to set a bogus state', async () => { it('should do nothing when you attempt to set a bogus state', async () => {
await Flags.update(1, uid2, { await Flags.update(1, adminUid, {
state: 'hocus pocus', state: 'hocus pocus',
}); });
@@ -630,6 +631,23 @@ describe('Flags', function () {
}); });
}); });
}); });
it('should not allow flagging post in private category', async function () {
const category = await Categories.create({ name: 'private category' });
await Privileges.categories.rescind(['topics:read'], category.cid, 'registered-users');
const result = await Topics.post({
cid: category.cid,
uid: adminUid,
title: 'private topic',
content: 'private post',
});
try {
await SocketFlags.create({ uid: uid3 }, { type: 'post', id: result.postData.pid, reason: 'foobar' });
} catch (err) {
assert.equal(err.message, '[[error:no-privileges]]');
}
});
}); });
describe('.update()', function () { describe('.update()', function () {