mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-27 17:11:14 +01:00
fix: check if user has read priv before flagging
This commit is contained in:
17
src/flags.js
17
src/flags.js
@@ -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);
|
||||||
|
|||||||
@@ -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 () {
|
||||||
|
|||||||
Reference in New Issue
Block a user