v1.18.x
Barış Soner Uşaklı 7 years ago
parent 19491b5210
commit a7267df404

@ -11,7 +11,6 @@
"maximumTagsPerTopic": 5,
"minimumTagLength": 3,
"maximumTagLength": 15,
"allowGuestSearching": 0,
"allowTopicsThumbnail": 0,
"registrationType": "normal",
"allowLocalLogin": 1,

@ -75,9 +75,9 @@
"nodebb-plugin-spam-be-gone": "0.5.3",
"nodebb-rewards-essentials": "0.0.11",
"nodebb-theme-lavender": "5.0.4",
"nodebb-theme-persona": "9.0.6",
"nodebb-theme-slick": "1.2.1",
"nodebb-theme-vanilla": "10.0.6",
"nodebb-theme-persona": "9.0.7",
"nodebb-theme-slick": "1.2.2",
"nodebb-theme-vanilla": "10.0.7",
"nodebb-widget-essentials": "4.0.4",
"nodemailer": "4.6.4",
"passport": "^0.4.0",

@ -1,8 +1,5 @@
{
"handles": "Guest Handles",
"handles.enabled": "Allow guest handles",
"handles.enabled-help": "This option exposes a new field that allows guests to pick a name to associate with each post they make. If disabled, they will simply be called \"Guest\"",
"privileges": "Guest Privileges",
"privileges.can-search": "Allow guests to search without logging in",
"privileges.can-search-users": "Allow guests to search users without logging in"
"handles.enabled-help": "This option exposes a new field that allows guests to pick a name to associate with each post they make. If disabled, they will simply be called \"Guest\""
}

@ -521,7 +521,7 @@ app.cacheBuster = null;
}
searchButton.on('click', function (e) {
if (!config.loggedIn && !config.allowGuestSearching) {
if (!config.loggedIn && !app.user.privileges['search:content']) {
app.alert({
message: '[[error:search-requires-login]]',
timeout: 3000,

@ -20,7 +20,6 @@
generateCategoryBackground: generateCategoryBackground,
generateChildrenCategories: generateChildrenCategories,
generateTopicClass: generateTopicClass,
displayUserSearch: displayUserSearch,
membershipBtn: membershipBtn,
spawnPrivilegeStates: spawnPrivilegeStates,
localeToHTML: localeToHTML,
@ -159,10 +158,6 @@
return style.join(' ');
}
function displayUserSearch(data, allowGuestUserSearching) {
return data.loggedIn || allowGuestUserSearching === 'true';
}
// Groups helpers
function membershipBtn(groupObj) {
if (groupObj.isMember && groupObj.name !== 'administrators') {

@ -32,8 +32,6 @@ apiController.loadConfig = function (req, callback) {
config.minimumTagLength = meta.config.minimumTagLength || 3;
config.maximumTagLength = meta.config.maximumTagLength || 15;
config.useOutgoingLinksPage = parseInt(meta.config.useOutgoingLinksPage, 10) === 1;
config.allowGuestSearching = parseInt(meta.config.allowGuestSearching, 10) === 1;
config.allowGuestUserSearching = parseInt(meta.config.allowGuestUserSearching, 10) === 1;
config.allowGuestHandles = parseInt(meta.config.allowGuestHandles, 10) === 1;
config.allowFileUploads = parseInt(meta.config.allowFileUploads, 10) === 1;
config.allowTopicsThumbnail = parseInt(meta.config.allowTopicsThumbnail, 10) === 1;

@ -9,6 +9,7 @@ var plugins = require('../plugins');
var search = require('../search');
var categories = require('../categories');
var pagination = require('../pagination');
var privileges = require('../privileges');
var helpers = require('./helpers');
var searchController = module.exports;
@ -17,64 +18,68 @@ searchController.search = function (req, res, next) {
if (!plugins.hasListeners('filter:search.query')) {
return next();
}
if (!req.loggedIn && parseInt(meta.config.allowGuestSearching, 10) !== 1) {
return helpers.notAllowed(req, res);
}
var page = Math.max(1, parseInt(req.query.page, 10)) || 1;
if (req.query.categories && !Array.isArray(req.query.categories)) {
req.query.categories = [req.query.categories];
}
var data = {
query: req.query.term,
searchIn: req.query.in || 'posts',
matchWords: req.query.matchWords || 'all',
postedBy: req.query.by,
categories: req.query.categories,
searchChildren: req.query.searchChildren,
hasTags: req.query.hasTags,
replies: req.query.replies,
repliesFilter: req.query.repliesFilter,
timeRange: req.query.timeRange,
timeFilter: req.query.timeFilter,
sortBy: req.query.sortBy || meta.config.searchDefaultSortBy || '',
sortDirection: req.query.sortDirection,
page: page,
uid: req.uid,
qs: req.query,
};
async.waterfall([
function (next) {
privileges.global.can('search:content', req.uid, next);
},
function (allowed, next) {
if (!allowed) {
return helpers.notAllowed(req, res);
}
if (req.query.categories && !Array.isArray(req.query.categories)) {
req.query.categories = [req.query.categories];
}
async.parallel({
categories: async.apply(categories.buildForSelect, req.uid, 'read'),
search: async.apply(search.search, data),
}, function (err, results) {
if (err) {
return next(err);
}
var data = {
query: req.query.term,
searchIn: req.query.in || 'posts',
matchWords: req.query.matchWords || 'all',
postedBy: req.query.by,
categories: req.query.categories,
searchChildren: req.query.searchChildren,
hasTags: req.query.hasTags,
replies: req.query.replies,
repliesFilter: req.query.repliesFilter,
timeRange: req.query.timeRange,
timeFilter: req.query.timeFilter,
sortBy: req.query.sortBy || meta.config.searchDefaultSortBy || '',
sortDirection: req.query.sortDirection,
page: page,
uid: req.uid,
qs: req.query,
};
results.categories = results.categories.filter(function (category) {
return category && !category.link;
});
async.parallel({
categories: async.apply(categories.buildForSelect, req.uid, 'read'),
search: async.apply(search.search, data),
}, next);
},
function (results) {
results.categories = results.categories.filter(function (category) {
return category && !category.link;
});
var categoriesData = [
{ value: 'all', text: '[[unread:all_categories]]' },
{ value: 'watched', text: '[[category:watched-categories]]' },
].concat(results.categories);
var categoriesData = [
{ value: 'all', text: '[[unread:all_categories]]' },
{ value: 'watched', text: '[[category:watched-categories]]' },
].concat(results.categories);
var searchData = results.search;
searchData.categories = categoriesData;
searchData.categoriesCount = Math.max(10, Math.min(20, categoriesData.length));
searchData.pagination = pagination.create(page, searchData.pageCount, req.query);
searchData.showAsPosts = !req.query.showAs || req.query.showAs === 'posts';
searchData.showAsTopics = req.query.showAs === 'topics';
searchData.title = '[[global:header.search]]';
searchData.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[global:search]]' }]);
searchData.expandSearch = !req.query.term;
searchData.searchDefaultSortBy = meta.config.searchDefaultSortBy || '';
searchData.search_query = validator.escape(String(req.query.term || ''));
searchData.term = req.query.term;
res.render('search', searchData);
});
var searchData = results.search;
searchData.categories = categoriesData;
searchData.categoriesCount = Math.max(10, Math.min(20, categoriesData.length));
searchData.pagination = pagination.create(page, searchData.pageCount, req.query);
searchData.showAsPosts = !req.query.showAs || req.query.showAs === 'posts';
searchData.showAsTopics = req.query.showAs === 'topics';
searchData.title = '[[global:header.search]]';
searchData.breadcrumbs = helpers.buildBreadcrumbs([{ text: '[[global:search]]' }]);
searchData.expandSearch = !req.query.term;
searchData.searchDefaultSortBy = meta.config.searchDefaultSortBy || '';
searchData.search_query = validator.escape(String(req.query.term || ''));
searchData.term = req.query.term;
res.render('search', searchData);
},
], next);
};

@ -5,6 +5,7 @@ var validator = require('validator');
var user = require('../user');
var topics = require('../topics');
var privileges = require('../privileges');
var pagination = require('../pagination');
var helpers = require('./helpers');
@ -71,12 +72,20 @@ tagsController.getTag = function (req, res, next) {
tagsController.getTags = function (req, res, next) {
async.waterfall([
function (next) {
topics.getTags(0, 99, next);
async.parallel({
canSearch: function (next) {
privileges.global.can('search:tags', req.uid, next);
},
tags: function (next) {
topics.getTags(0, 99, next);
},
}, next);
},
function (tags) {
tags = tags.filter(Boolean);
function (results) {
results.tags = results.tags.filter(Boolean);
var data = {
tags: tags,
tags: results.tags,
displayTagSearch: results.canSearch,
nextStart: 100,
breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[tags:tags]]' }]),
title: '[[pages:tags]]',

@ -4,8 +4,9 @@ var async = require('async');
var user = require('../user');
var meta = require('../meta');
var pagination = require('../pagination');
var db = require('../database');
var pagination = require('../pagination');
var privileges = require('../privileges');
var helpers = require('./helpers');
var usersController = module.exports;
@ -33,6 +34,12 @@ usersController.index = function (req, res, next) {
usersController.search = function (req, res, next) {
async.waterfall([
function (next) {
privileges.global.can('search:users', req.uid, next);
},
function (allowed, next) {
if (!allowed) {
return next(new Error('[[error:no-privileges]]'));
}
async.parallel({
search: function (next) {
user.search({
@ -56,6 +63,7 @@ usersController.search = function (req, res, next) {
results.search.isAdminOrGlobalMod = results.isAdminOrGlobalMod;
results.search.pagination = pagination.create(req.query.page, results.search.pageCount, req.query);
results.search['section_' + section] = true;
results.displayUserSearch = true;
render(req, res, results.search, next);
},
], next);
@ -171,6 +179,9 @@ usersController.getUsers = function (set, uid, query, callback) {
isAdminOrGlobalMod: function (next) {
user.isAdminOrGlobalMod(uid, next);
},
canSearch: function (next) {
privileges.global.can('search:users', uid, next);
},
usersData: function (next) {
usersController.getUsersAndCount(set, uid, start, stop, next);
},
@ -185,6 +196,7 @@ usersController.getUsers = function (set, uid, query, callback) {
title: setToData[set].title || '[[pages:users/latest]]',
breadcrumbs: helpers.buildBreadcrumbs(breadcrumbs),
isAdminOrGlobalMod: results.isAdminOrGlobalMod,
displayUserSearch: results.canSearch,
};
userData['section_' + (query.section || 'joindate')] = true;
next(null, userData);

@ -380,7 +380,8 @@ function createGlobalModeratorsGroup(next) {
function giveGlobalPrivileges(next) {
var privileges = require('./privileges');
privileges.global.give(['chat', 'upload:post:image', 'signature'], 'registered-users', next);
var defaultPrivileges = ['chat', 'upload:post:image', 'signature', 'search:content', 'search:users', 'search:tags'];
privileges.global.give(defaultPrivileges, 'registered-users', next);
}
function createCategories(next) {

@ -18,6 +18,9 @@ module.exports = function (privileges) {
{ name: 'Upload Files' },
{ name: 'Signature' },
{ name: 'Ban' },
{ name: 'Search Content' },
{ name: 'Search Users' },
{ name: 'Search Tags' },
];
privileges.global.userPrivilegeList = [
@ -26,6 +29,9 @@ module.exports = function (privileges) {
'upload:post:file',
'signature',
'ban',
'search:content',
'search:users',
'search:tags',
];
privileges.global.groupPrivilegeList = privileges.global.userPrivilegeList.map(function (privilege) {
@ -81,6 +87,9 @@ module.exports = function (privileges) {
chat: privData.chat || isAdminOrMod,
'upload:post:image': privData['upload:post:image'] || isAdminOrMod,
'upload:post:file': privData['upload:post:file'] || isAdminOrMod,
'search:content': privData['search:content'] || isAdminOrMod,
'search:users': privData['search:users'] || isAdminOrMod,
'search:tags': privData['search:tags'] || isAdminOrMod,
}, next);
},
], callback);

@ -3,6 +3,7 @@
var async = require('async');
var db = require('../../database');
var topics = require('../../topics');
var privileges = require('../../privileges');
var utils = require('../../utils');
module.exports = function (SocketTopics) {
@ -25,13 +26,27 @@ module.exports = function (SocketTopics) {
};
SocketTopics.searchTags = function (socket, data, callback) {
topics.searchTags(data, callback);
searchTags(socket.uid, topics.searchTags, data, callback);
};
SocketTopics.searchAndLoadTags = function (socket, data, callback) {
topics.searchAndLoadTags(data, callback);
searchTags(socket.uid, topics.searchAndLoadTags, data, callback);
};
function searchTags(uid, method, data, callback) {
async.waterfall([
function (next) {
privileges.global.can('search:tags', uid, next);
},
function (allowed, next) {
if (!allowed) {
return next(new Error('[[error:no-privileges]]'));
}
method(data, next);
},
], callback);
}
SocketTopics.loadMoreTags = function (socket, data, callback) {
if (!data || !utils.isNumber(data.after)) {
return callback(new Error('[[error:invalid-data]]'));

@ -3,8 +3,8 @@
var async = require('async');
var user = require('../../user');
var meta = require('../../meta');
var pagination = require('../../pagination');
var privileges = require('../../privileges');
module.exports = function (SocketUser) {
SocketUser.search = function (socket, data, callback) {
@ -12,12 +12,14 @@ module.exports = function (SocketUser) {
return callback(new Error('[[error:invalid-data]]'));
}
if (!socket.uid && parseInt(meta.config.allowGuestUserSearching, 10) !== 1) {
return callback(new Error('[[error:not-logged-in]]'));
}
async.waterfall([
function (next) {
privileges.global.can('search:users', socket.uid, next);
},
function (allowed, next) {
if (!allowed) {
return next(new Error('[[error:no-privileges]]'));
}
user.search({
query: data.query,
page: data.page,

@ -0,0 +1,30 @@
'use strict';
var async = require('async');
module.exports = {
name: 'Give global search privileges',
timestamp: Date.UTC(2018, 4, 28),
method: function (callback) {
var meta = require('../../meta');
var privileges = require('../../privileges');
var allowGuestSearching = parseInt(meta.config.allowGuestSearching, 10) === 1;
var allowGuestUserSearching = parseInt(meta.config.allowGuestUserSearching, 10) === 1;
async.waterfall([
function (next) {
privileges.global.give(['search:content', 'search:users', 'search:tags'], 'registered-users', next);
},
function (next) {
var guestPrivs = [];
if (allowGuestSearching) {
guestPrivs.push('search:content');
}
if (allowGuestUserSearching) {
guestPrivs.push('search:users');
}
guestPrivs.push('search:tags');
privileges.global.give(guestPrivs, 'guests', next);
},
], callback);
},
};

@ -17,26 +17,4 @@
</div>
</div>
<div class="row">
<div class="col-sm-2 col-xs-12 settings-header">[[admin/settings/guest:privileges]]</div>
<div class="col-sm-10 col-xs-12">
<form role="form">
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" data-field="allowGuestSearching">
<span class="mdl-switch__label"><strong>[[admin/settings/guest:privileges.can-search]]</strong></span>
</label>
</div>
<div class="checkbox">
<label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
<input class="mdl-switch__input" type="checkbox" data-field="allowGuestUserSearching">
<span class="mdl-switch__label"><strong>[[admin/settings/guest:privileges.can-search-users]]</strong></span>
</label>
</div>
</form>
</div>
</div>
<!-- IMPORT admin/partials/settings/footer.tpl -->

@ -667,6 +667,9 @@ describe('Categories', function () {
assert.deepEqual(data, {
ban: false,
chat: false,
'search:content': false,
'search:users': false,
'search:tags': false,
'upload:post:image': false,
'upload:post:file': false,
signature: false,
@ -705,6 +708,9 @@ describe('Categories', function () {
assert.deepEqual(data, {
'groups:ban': false,
'groups:chat': true,
'groups:search:content': true,
'groups:search:users': true,
'groups:search:tags': true,
'groups:upload:post:image': true,
'groups:upload:post:file': false,
'groups:signature': true,

@ -630,15 +630,28 @@ describe('Controllers', function () {
});
});
it('should load users search page', function (done) {
request(nconf.get('url') + '/users?term=bar&section=sort-posts', function (err, res, body) {
it('should error if guests do not have search privilege', function (done) {
request(nconf.get('url') + '/api/users?term=bar&section=sort-posts', { json: true }, function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert.equal(res.statusCode, 500);
assert(body);
assert.equal(body.error, '[[error:no-privileges]]');
done();
});
});
it('should load users search page', function (done) {
privileges.global.give(['search:users'], 'guests', function (err) {
assert.ifError(err);
request(nconf.get('url') + '/users?term=bar&section=sort-posts', function (err, res, body) {
assert.ifError(err);
assert.equal(res.statusCode, 200);
assert(body);
privileges.global.rescind(['search:users'], 'guests', done);
});
});
});
it('should load groups page', function (done) {
request(nconf.get('url') + '/groups', function (err, res, body) {
assert.ifError(err);

@ -205,7 +205,7 @@ function setupDefaultConfigs(meta, next) {
function giveDefaultGlobalPrivileges(next) {
var privileges = require('../../src/privileges');
privileges.global.give(['chat', 'upload:post:image', 'signature'], 'registered-users', next);
privileges.global.give(['chat', 'upload:post:image', 'signature', 'search:content', 'search:users', 'search:tags'], 'registered-users', next);
}
function enableDefaultPlugins(callback) {

@ -11,6 +11,7 @@ var topics = require('../src/topics');
var categories = require('../src/categories');
var user = require('../src/user');
var search = require('../src/search');
var privileges = require('../src/privileges');
describe('Search', function () {
var phoebeUid;
@ -96,21 +97,22 @@ describe('Search', function () {
it('should search term in titles and posts', function (done) {
var meta = require('../src/meta');
meta.config.allowGuestSearching = 1;
var qs = '/api/search?term=cucumber&in=titlesposts&categories[]=' + cid1 + '&by=phoebe&replies=1&repliesFilter=atleast&sortBy=timestamp&sortDirection=desc&showAs=posts';
request({
url: nconf.get('url') + qs,
json: true,
}, function (err, response, body) {
privileges.global.give(['search:content'], 'guests', function (err) {
assert.ifError(err);
assert(body);
assert.equal(body.matchCount, 1);
assert.equal(body.posts.length, 1);
assert.equal(body.posts[0].pid, post1Data.pid);
assert.equal(body.posts[0].uid, phoebeUid);
done();
request({
url: nconf.get('url') + qs,
json: true,
}, function (err, response, body) {
assert.ifError(err);
assert(body);
assert.equal(body.matchCount, 1);
assert.equal(body.posts.length, 1);
assert.equal(body.posts[0].pid, post1Data.pid);
assert.equal(body.posts[0].uid, phoebeUid);
privileges.global.rescind(['search:content'], 'guests', done);
});
});
});

@ -293,10 +293,8 @@ describe('User', function () {
});
it('should error for guest', function (done) {
meta.config.allowGuestUserSearching = 0;
socketUser.search({ uid: 0 }, { query: 'john' }, function (err) {
assert.equal(err.message, '[[error:not-logged-in]]');
meta.config.allowGuestUserSearching = 1;
assert.equal(err.message, '[[error:no-privileges]]');
done();
});
});

Loading…
Cancel
Save