mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 03:26:04 +01:00
Merge branch 'master' into styleguide
This commit is contained in:
@@ -39,8 +39,8 @@
|
|||||||
"markAsUnreadForAll.success": "すべてのスレッドを未読にしました。",
|
"markAsUnreadForAll.success": "すべてのスレッドを未読にしました。",
|
||||||
"mark_unread": "未読としてマーク",
|
"mark_unread": "未読としてマーク",
|
||||||
"mark_unread.success": "スレッドは未読にマークされました。",
|
"mark_unread.success": "スレッドは未読にマークされました。",
|
||||||
"watch": "ウオッチ",
|
"watch": "ウォッチ",
|
||||||
"unwatch": "ウオッチ解除",
|
"unwatch": "ウォッチ解除",
|
||||||
"watch.title": "新しい投稿の通知を受ける",
|
"watch.title": "新しい投稿の通知を受ける",
|
||||||
"unwatch.title": "このスレッドの通知を停止します",
|
"unwatch.title": "このスレッドの通知を停止します",
|
||||||
"share_this_post": "投稿を共有",
|
"share_this_post": "投稿を共有",
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
"more_guests": "ゲストさんが%1人",
|
"more_guests": "ゲストさんが%1人",
|
||||||
"users_and_others": "%1と他は%2",
|
"users_and_others": "%1と他は%2",
|
||||||
"sort_by": "並び替え",
|
"sort_by": "並び替え",
|
||||||
"oldest_to_newest": "古い\bものから新しい順",
|
"oldest_to_newest": "古いものから新しい順",
|
||||||
"newest_to_oldest": "新しいものから古い順",
|
"newest_to_oldest": "新しいものから古い順",
|
||||||
"most_votes": "最も投票された順",
|
"most_votes": "最も投票された順",
|
||||||
"most_posts": "最も投稿された順",
|
"most_posts": "最も投稿された順",
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
"change_password": "パスワードを変更",
|
"change_password": "パスワードを変更",
|
||||||
"change_password_error": "無効のパスワード!",
|
"change_password_error": "無効のパスワード!",
|
||||||
"change_password_error_wrong_current": "現在のパスワードは正しくありません!",
|
"change_password_error_wrong_current": "現在のパスワードは正しくありません!",
|
||||||
"change_password_error_length": "パスワードは短い過ぎです!",
|
"change_password_error_length": "パスワードが短過ぎです!",
|
||||||
"change_password_error_match": "パスワードは一致しません!",
|
"change_password_error_match": "パスワードは一致しません!",
|
||||||
"change_password_error_privileges": "パスワードを更新する権限はありません。",
|
"change_password_error_privileges": "パスワードを更新する権限はありません。",
|
||||||
"change_password_success": "パスワードを更新しました!",
|
"change_password_success": "パスワードを更新しました!",
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"digest_monthly": "マンスリー",
|
"digest_monthly": "マンスリー",
|
||||||
"send_chat_notifications": "オンラインではない時に新しいチャットメッセージを受信した場合、通知メールを送信する。",
|
"send_chat_notifications": "オンラインではない時に新しいチャットメッセージを受信した場合、通知メールを送信する。",
|
||||||
"send_post_notifications": "購読中のスレッドに返信があった場合、メールで通知する。",
|
"send_post_notifications": "購読中のスレッドに返信があった場合、メールで通知する。",
|
||||||
"settings-require-reload": "変化がありましてブラウザを更新する必要があります。ここを押して、ページ更新します。",
|
"settings-require-reload": "設定を変更するにはページを更新する必要があります。ここを押して、ページを更新します。",
|
||||||
"has_no_follower": "フォロワーはまだいません :(",
|
"has_no_follower": "フォロワーはまだいません :(",
|
||||||
"follows_no_one": "フォロー中のユーザーはまだいません :(",
|
"follows_no_one": "フォロー中のユーザーはまだいません :(",
|
||||||
"has_no_posts": "このユーザーはまだ一つも投稿していません",
|
"has_no_posts": "このユーザーはまだ一つも投稿していません",
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
"delay_image_loading": "画像読み込みを遅延させる",
|
"delay_image_loading": "画像読み込みを遅延させる",
|
||||||
"image_load_delay_help": "有効の場合、スレッド内の画像はスクロールされるまで読み込みません",
|
"image_load_delay_help": "有効の場合、スレッド内の画像はスクロールされるまで読み込みません",
|
||||||
"scroll_to_my_post": "返信を投稿した後、新しい投稿を表示する",
|
"scroll_to_my_post": "返信を投稿した後、新しい投稿を表示する",
|
||||||
"follow_topics_you_reply_to": "あなたが返信するスレッドをウォッチ",
|
"follow_topics_you_reply_to": "あなたが返信したスレッドをウォッチする",
|
||||||
"follow_topics_you_create": "あなたが作成したスレッドをウォッチする",
|
"follow_topics_you_create": "あなたが作成したスレッドをウォッチする",
|
||||||
"grouptitle": "グループ題名",
|
"grouptitle": "グループ題名",
|
||||||
"no-group-title": "グループ名がありません",
|
"no-group-title": "グループ名がありません",
|
||||||
|
|||||||
@@ -3,29 +3,29 @@
|
|||||||
"title": "Site Başlığı",
|
"title": "Site Başlığı",
|
||||||
"title.name": "Topluluk İsmi",
|
"title.name": "Topluluk İsmi",
|
||||||
"title.show-in-header": "Show Site Title in Header",
|
"title.show-in-header": "Show Site Title in Header",
|
||||||
"browser-title": "Browser Title",
|
"browser-title": "Tarayıcı Başlığı",
|
||||||
"browser-title-help": "If no browser title is specified, the site title will be used",
|
"browser-title-help": "If no browser title is specified, the site title will be used",
|
||||||
"title-layout": "Title Layout",
|
"title-layout": "Title Layout",
|
||||||
"title-layout-help": "Define how the browser title will be structured ie. {pageTitle} | {browserTitle}",
|
"title-layout-help": "Define how the browser title will be structured ie. {pageTitle} | {browserTitle}",
|
||||||
"description.placeholder": "A short description about your community",
|
"description.placeholder": "A short description about your community",
|
||||||
"description": "Site Açıklaması",
|
"description": "Site Açıklaması",
|
||||||
"keywords": "Site Keywords",
|
"keywords": "Site Anahtar Kelimeler",
|
||||||
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
"keywords-placeholder": "Keywords describing your community, comma-separated",
|
||||||
"logo": "Site Logo",
|
"logo": "Site Logo",
|
||||||
"logo.image": "Image",
|
"logo.image": "Görsel",
|
||||||
"logo.image-placeholder": "Path to a logo to display on forum header",
|
"logo.image-placeholder": "Path to a logo to display on forum header",
|
||||||
"logo.upload": "Yükle",
|
"logo.upload": "Yükle",
|
||||||
"logo.url": "URL",
|
"logo.url": "URL",
|
||||||
"logo.url-placeholder": "The URL of the site logo",
|
"logo.url-placeholder": "The URL of the site logo",
|
||||||
"logo.url-help": "When the logo is clicked, send users to this address. If left blank, user will be sent to the forum index.",
|
"logo.url-help": "When the logo is clicked, send users to this address. If left blank, user will be sent to the forum index.",
|
||||||
"logo.alt-text": "Alt Text",
|
"logo.alt-text": "Alt Yazı",
|
||||||
"log.alt-text-placeholder": "Alternative text for accessibility",
|
"log.alt-text-placeholder": "Alternative text for accessibility",
|
||||||
"favicon": "Favicon",
|
"favicon": "Favicon",
|
||||||
"favicon.upload": "Yükle",
|
"favicon.upload": "Yükle",
|
||||||
"touch-icon": "Homescreen/Touch Icon",
|
"touch-icon": "Homescreen/Touch Icon",
|
||||||
"touch-icon.upload": "Yükle",
|
"touch-icon.upload": "Yükle",
|
||||||
"touch-icon.help": "Recommended size and format: 192x192, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.",
|
"touch-icon.help": "Recommended size and format: 192x192, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.",
|
||||||
"outgoing-links": "Outgoing Links",
|
"outgoing-links": "Harici Bağlantılar",
|
||||||
"outgoing-links.warning-page": "Use Outgoing Links Warning Page",
|
"outgoing-links.warning-page": "Use Outgoing Links Warning Page",
|
||||||
"search-default-sort-by": "Search default sort by"
|
"search-default-sort-by": "Aramada varsayılan sıralama"
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,6 @@ app.cacheBuster = null;
|
|||||||
require(['taskbar', 'helpers', 'forum/pagination'], function (taskbar, helpers, pagination) {
|
require(['taskbar', 'helpers', 'forum/pagination'], function (taskbar, helpers, pagination) {
|
||||||
taskbar.init();
|
taskbar.init();
|
||||||
|
|
||||||
// templates.js helpers
|
|
||||||
helpers.register();
|
helpers.register();
|
||||||
|
|
||||||
pagination.init();
|
pagination.init();
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
(function (exports) {
|
(function (exports) {
|
||||||
var helpers = {};
|
'use strict';
|
||||||
|
|
||||||
|
/* globals define, utils, config */
|
||||||
|
|
||||||
|
// export the class if we are in a Node-like system.
|
||||||
|
if (typeof module === 'object' && module.exports === exports) {
|
||||||
|
exports = module.exports/* = SemVer*/;
|
||||||
|
}
|
||||||
|
|
||||||
|
var helpers = exports;
|
||||||
|
|
||||||
helpers.displayMenuItem = function (data, index) {
|
helpers.displayMenuItem = function (data, index) {
|
||||||
var item = data.navigation[index];
|
var item = data.navigation[index];
|
||||||
|
|||||||
@@ -32,17 +32,18 @@ groupsController.getGroupsFromSet = function (uid, sort, start, stop, callback)
|
|||||||
set = 'groups:visible:createtime';
|
set = 'groups:visible:createtime';
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.getGroupsFromSet(set, uid, start, stop, function (err, groups) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
groups.getGroupsFromSet(set, uid, start, stop, next);
|
||||||
}
|
},
|
||||||
|
function (groupsData, next) {
|
||||||
callback(null, {
|
next(null, {
|
||||||
groups: groups,
|
groups: groupsData,
|
||||||
allowGroupCreation: parseInt(meta.config.allowGroupCreation, 10) === 1,
|
allowGroupCreation: parseInt(meta.config.allowGroupCreation, 10) === 1,
|
||||||
nextStart: stop + 1,
|
nextStart: stop + 1,
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
groupsController.details = function (req, res, callback) {
|
groupsController.details = function (req, res, callback) {
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ topicsController.teaser = function (req, res, next) {
|
|||||||
var tid = req.params.topic_id;
|
var tid = req.params.topic_id;
|
||||||
|
|
||||||
if (!utils.isNumber(tid)) {
|
if (!utils.isNumber(tid)) {
|
||||||
return next(new Error('[[error:invalid-tid]]'));
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ uploadsController.upload = function (req, res, filesIterator) {
|
|||||||
deleteTempFiles(files);
|
deleteTempFiles(files);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return res.status(500).send(err.message);
|
return res.status(500).json({ path: req.path, error: err.message });
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(200).send(images);
|
res.status(200).send(images);
|
||||||
@@ -136,26 +136,24 @@ uploadsController.uploadThumb = function (req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uploadsController.upload(req, res, function (uploadedFile, next) {
|
uploadsController.upload(req, res, function (uploadedFile, next) {
|
||||||
file.isFileTypeAllowed(uploadedFile.path, function (err) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return next(err);
|
if (!uploadedFile.type.match(/image./)) {
|
||||||
}
|
return next(new Error('[[error:invalid-file]]'));
|
||||||
|
|
||||||
if (!uploadedFile.type.match(/image./)) {
|
|
||||||
return next(new Error('[[error:invalid-file]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
var size = parseInt(meta.config.topicThumbSize, 10) || 120;
|
|
||||||
image.resizeImage({
|
|
||||||
path: uploadedFile.path,
|
|
||||||
extension: path.extname(uploadedFile.name),
|
|
||||||
width: size,
|
|
||||||
height: size,
|
|
||||||
}, function (err) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file.isFileTypeAllowed(uploadedFile.path, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
var size = parseInt(meta.config.topicThumbSize, 10) || 120;
|
||||||
|
image.resizeImage({
|
||||||
|
path: uploadedFile.path,
|
||||||
|
extension: path.extname(uploadedFile.name),
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
if (plugins.hasListeners('filter:uploadImage')) {
|
if (plugins.hasListeners('filter:uploadImage')) {
|
||||||
return plugins.fireHook('filter:uploadImage', {
|
return plugins.fireHook('filter:uploadImage', {
|
||||||
image: uploadedFile,
|
image: uploadedFile,
|
||||||
@@ -164,8 +162,8 @@ uploadsController.uploadThumb = function (req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uploadFile(req.uid, uploadedFile, next);
|
uploadFile(req.uid, uploadedFile, next);
|
||||||
});
|
},
|
||||||
});
|
], next);
|
||||||
}, next);
|
}, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -184,12 +182,14 @@ uploadsController.uploadGroupCover = function (uid, uploadedFile, callback) {
|
|||||||
}, callback);
|
}, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
file.isFileTypeAllowed(uploadedFile.path, function (err) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
file.isFileTypeAllowed(uploadedFile.path, next);
|
||||||
}
|
},
|
||||||
saveFileToLocal(uploadedFile, callback);
|
function (next) {
|
||||||
});
|
saveFileToLocal(uploadedFile, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
function uploadFile(uid, uploadedFile, callback) {
|
function uploadFile(uid, uploadedFile, callback) {
|
||||||
@@ -228,17 +228,18 @@ function saveFileToLocal(uploadedFile, callback) {
|
|||||||
|
|
||||||
filename = Date.now() + '-' + validator.escape(filename.replace(path.extname(uploadedFile.name) || '', '')).substr(0, 255) + extension;
|
filename = Date.now() + '-' + validator.escape(filename.replace(path.extname(uploadedFile.name) || '', '')).substr(0, 255) + extension;
|
||||||
|
|
||||||
file.saveFileToLocal(filename, 'files', uploadedFile.path, function (err, upload) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
file.saveFileToLocal(filename, 'files', uploadedFile.path, next);
|
||||||
}
|
},
|
||||||
|
function (upload, next) {
|
||||||
callback(null, {
|
next(null, {
|
||||||
url: nconf.get('relative_path') + upload.url,
|
url: nconf.get('relative_path') + upload.url,
|
||||||
path: upload.path,
|
path: upload.path,
|
||||||
name: uploadedFile.name,
|
name: uploadedFile.name,
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
|
], callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteTempFiles(files) {
|
function deleteTempFiles(files) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var winston = require('winston');
|
var winston = require('winston');
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
|
|
||||||
@@ -137,7 +137,6 @@ module.exports = function (Groups) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Groups.acceptMembership = function (groupName, uid, callback) {
|
Groups.acceptMembership = function (groupName, uid, callback) {
|
||||||
// Note: For simplicity, this method intentially doesn't check the caller uid for ownership!
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
async.apply(db.setRemove, 'group:' + groupName + ':pending', uid),
|
async.apply(db.setRemove, 'group:' + groupName + ':pending', uid),
|
||||||
async.apply(db.setRemove, 'group:' + groupName + ':invited', uid),
|
async.apply(db.setRemove, 'group:' + groupName + ':invited', uid),
|
||||||
@@ -146,7 +145,6 @@ module.exports = function (Groups) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Groups.rejectMembership = function (groupName, uid, callback) {
|
Groups.rejectMembership = function (groupName, uid, callback) {
|
||||||
// Note: For simplicity, this method intentially doesn't check the caller uid for ownership!
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
async.apply(db.setRemove, 'group:' + groupName + ':pending', uid),
|
async.apply(db.setRemove, 'group:' + groupName + ':pending', uid),
|
||||||
async.apply(db.setRemove, 'group:' + groupName + ':invited', uid),
|
async.apply(db.setRemove, 'group:' + groupName + ':invited', uid),
|
||||||
|
|||||||
@@ -62,13 +62,14 @@ module.exports = function (privileges) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
privileges.topics.can = function (privilege, tid, uid, callback) {
|
privileges.topics.can = function (privilege, tid, uid, callback) {
|
||||||
topics.getTopicField(tid, 'cid', function (err, cid) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
topics.getTopicField(tid, 'cid', next);
|
||||||
|
},
|
||||||
|
function (cid, next) {
|
||||||
|
privileges.categories.can(privilege, cid, uid, next);
|
||||||
}
|
}
|
||||||
|
], callback);
|
||||||
privileges.categories.can(privilege, cid, uid, callback);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
privileges.topics.filterTids = function (privilege, tids, uid, callback) {
|
privileges.topics.filterTids = function (privilege, tids, uid, callback) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
|
||||||
var groups = require('../groups');
|
var groups = require('../groups');
|
||||||
var meta = require('../meta');
|
var meta = require('../meta');
|
||||||
@@ -77,7 +77,7 @@ function isOwner(next) {
|
|||||||
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
||||||
isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName),
|
isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName),
|
||||||
}, function (err, results) {
|
}, function (err, results) {
|
||||||
if (err || (!isOwner && !results.isAdmin)) {
|
if (err || (!results.isOwner && !results.isAdmin)) {
|
||||||
return callback(err || new Error('[[error:no-privileges]]'));
|
return callback(err || new Error('[[error:no-privileges]]'));
|
||||||
}
|
}
|
||||||
next(socket, data, callback);
|
next(socket, data, callback);
|
||||||
@@ -141,22 +141,25 @@ SocketGroups.issueMassInvite = isOwner(function (socket, data, callback) {
|
|||||||
if (!data || !data.usernames || !data.groupName) {
|
if (!data || !data.usernames || !data.groupName) {
|
||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
var usernames = data.usernames.split(',');
|
var usernames = String(data.usernames).split(',');
|
||||||
usernames = usernames.map(function (username) {
|
usernames = usernames.map(function (username) {
|
||||||
return username && username.trim();
|
return username && username.trim();
|
||||||
});
|
});
|
||||||
user.getUidsByUsernames(usernames, function (err, uids) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
uids = uids.filter(function (uid) {
|
|
||||||
return !!uid && parseInt(uid, 10);
|
|
||||||
});
|
|
||||||
|
|
||||||
async.eachSeries(uids, function (uid, next) {
|
async.waterfall([
|
||||||
groups.invite(data.groupName, uid, next);
|
function (next) {
|
||||||
}, callback);
|
user.getUidsByUsernames(usernames, next);
|
||||||
});
|
},
|
||||||
|
function (uids, next) {
|
||||||
|
uids = uids.filter(function (uid) {
|
||||||
|
return !!uid && parseInt(uid, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
async.eachSeries(uids, function (uid, next) {
|
||||||
|
groups.invite(data.groupName, uid, next);
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
SocketGroups.rescindInvite = isOwner(function (socket, data, callback) {
|
SocketGroups.rescindInvite = isOwner(function (socket, data, callback) {
|
||||||
@@ -181,12 +184,14 @@ SocketGroups.kick = isOwner(function (socket, data, callback) {
|
|||||||
return callback(new Error('[[error:cant-kick-self]]'));
|
return callback(new Error('[[error:cant-kick-self]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.ownership.isOwner(data.uid, data.groupName, function (err, isOwner) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
groups.ownership.isOwner(data.uid, data.groupName, next);
|
||||||
}
|
},
|
||||||
groups.kick(data.uid, data.groupName, isOwner, callback);
|
function (isOwner, next) {
|
||||||
});
|
groups.kick(data.uid, data.groupName, isOwner, next);
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
SocketGroups.create = function (socket, data, callback) {
|
SocketGroups.create = function (socket, data, callback) {
|
||||||
@@ -198,32 +203,19 @@ SocketGroups.create = function (socket, data, callback) {
|
|||||||
return callback(new Error('[[error:invalid-group-name]]'));
|
return callback(new Error('[[error:invalid-group-name]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data.ownerUid = socket.uid;
|
data.ownerUid = socket.uid;
|
||||||
groups.create(data, callback);
|
groups.create(data, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketGroups.delete = function (socket, data, callback) {
|
SocketGroups.delete = isOwner(function (socket, data, callback) {
|
||||||
if (data.groupName === 'administrators' ||
|
if (data.groupName === 'administrators' ||
|
||||||
data.groupName === 'registered-users' ||
|
data.groupName === 'registered-users' ||
|
||||||
data.groupName === 'Global Moderators') {
|
data.groupName === 'Global Moderators') {
|
||||||
return callback(new Error('[[error:not-allowed]]'));
|
return callback(new Error('[[error:not-allowed]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async.parallel({
|
groups.destroy(data.groupName, callback);
|
||||||
isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName),
|
});
|
||||||
isAdmin: async.apply(user.isAdministrator, socket.uid),
|
|
||||||
}, function (err, checks) {
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
if (!checks.isOwner && !checks.isAdmin) {
|
|
||||||
return callback(new Error('[[error:no-privileges]]'));
|
|
||||||
}
|
|
||||||
|
|
||||||
groups.destroy(data.groupName, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
SocketGroups.search = function (socket, data, callback) {
|
SocketGroups.search = function (socket, data, callback) {
|
||||||
data.options = data.options || {};
|
data.options = data.options || {};
|
||||||
@@ -241,7 +233,7 @@ SocketGroups.search = function (socket, data, callback) {
|
|||||||
|
|
||||||
SocketGroups.loadMore = function (socket, data, callback) {
|
SocketGroups.loadMore = function (socket, data, callback) {
|
||||||
if (!data.sort || !utils.isNumber(data.after) || parseInt(data.after, 10) < 0) {
|
if (!data.sort || !utils.isNumber(data.after) || parseInt(data.after, 10) < 0) {
|
||||||
return callback();
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var groupsPerPage = 9;
|
var groupsPerPage = 9;
|
||||||
@@ -260,13 +252,17 @@ SocketGroups.loadMoreMembers = function (socket, data, callback) {
|
|||||||
return callback(new Error('[[error:invalid-data]]'));
|
return callback(new Error('[[error:invalid-data]]'));
|
||||||
}
|
}
|
||||||
data.after = parseInt(data.after, 10);
|
data.after = parseInt(data.after, 10);
|
||||||
user.getUsersFromSet('group:' + data.groupName + ':members', socket.uid, data.after, data.after + 9, function (err, users) {
|
async.waterfall([
|
||||||
if (err) {
|
function (next) {
|
||||||
return callback(err);
|
user.getUsersFromSet('group:' + data.groupName + ':members', socket.uid, data.after, data.after + 9, next);
|
||||||
}
|
},
|
||||||
|
function (users, next) {
|
||||||
callback(null, { users: users, nextStart: data.after + 10 });
|
next(null, {
|
||||||
});
|
users: users,
|
||||||
|
nextStart: data.after + 10,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
], callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
SocketGroups.cover = {};
|
SocketGroups.cover = {};
|
||||||
|
|||||||
317
test/groups.js
317
test/groups.js
@@ -432,7 +432,6 @@ describe('Groups', function () {
|
|||||||
var socketGroups = require('../src/socket.io/groups');
|
var socketGroups = require('../src/socket.io/groups');
|
||||||
var meta = require('../src/meta');
|
var meta = require('../src/meta');
|
||||||
|
|
||||||
|
|
||||||
it('should error if data is null', function (done) {
|
it('should error if data is null', function (done) {
|
||||||
socketGroups.before({ uid: 0 }, 'groups.join', null, function (err) {
|
socketGroups.before({ uid: 0 }, 'groups.join', null, function (err) {
|
||||||
assert.equal(err.message, '[[error:invalid-data]]');
|
assert.equal(err.message, '[[error:invalid-data]]');
|
||||||
@@ -535,17 +534,186 @@ describe('Groups', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should accept membership of user', function (done) {
|
it('should reject membership of user', function (done) {
|
||||||
socketGroups.accept({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: testUid }, function (err) {
|
socketGroups.reject({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: testUid }, function (err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
Groups.isMember(testUid, 'PrivateCanJoin', function (err, isMember) {
|
Groups.isInvited(testUid, 'PrivateCanJoin', function (err, invited) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert(isMember);
|
assert.equal(invited, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should error if not owner or admin', function (done) {
|
||||||
|
socketGroups.accept({ uid: 0 }, { groupName: 'PrivateCanJoin', toUid: testUid }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:no-privileges]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept membership of user', function (done) {
|
||||||
|
socketGroups.join({ uid: testUid }, { groupName: 'PrivateCanJoin' }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.accept({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: testUid }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.isMember(testUid, 'PrivateCanJoin', function (err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject/accept all memberships requests', function (done) {
|
||||||
|
function requestMembership(uids, callback) {
|
||||||
|
async.series([
|
||||||
|
function (next) {
|
||||||
|
socketGroups.join({ uid: uids.uid1 }, { groupName: 'PrivateCanJoin' }, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
socketGroups.join({ uid: uids.uid2 }, { groupName: 'PrivateCanJoin' }, next);
|
||||||
|
},
|
||||||
|
], function (err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var uids;
|
||||||
|
async.waterfall([
|
||||||
|
function (next) {
|
||||||
|
async.parallel({
|
||||||
|
uid1: function (next) {
|
||||||
|
User.create({ username: 'groupuser1' }, next);
|
||||||
|
},
|
||||||
|
uid2: function (next) {
|
||||||
|
User.create({ username: 'groupuser2' }, next);
|
||||||
|
},
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
function (results, next) {
|
||||||
|
uids = results;
|
||||||
|
requestMembership(results, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
socketGroups.rejectAll({ uid: adminUid }, { groupName: 'PrivateCanJoin' }, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
Groups.getPending('PrivateCanJoin', next);
|
||||||
|
},
|
||||||
|
function (pending, next) {
|
||||||
|
assert.equal(pending.length, 0);
|
||||||
|
requestMembership(uids, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
socketGroups.acceptAll({ uid: adminUid }, { groupName: 'PrivateCanJoin' }, next);
|
||||||
|
},
|
||||||
|
function (next) {
|
||||||
|
Groups.isMembers([uids.uid1, uids.uid2], 'PrivateCanJoin', next);
|
||||||
|
},
|
||||||
|
function (isMembers, next) {
|
||||||
|
assert(isMembers[0]);
|
||||||
|
assert(isMembers[1]);
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
], function (err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should issue invite to user', function (done) {
|
||||||
|
User.create({ username: 'invite1' }, function (err, uid) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.issueInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: uid }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.isInvited(uid, 'PrivateCanJoin', function (err, isInvited) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isInvited);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail with invalid data', function (done) {
|
||||||
|
socketGroups.issueMassInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', usernames: null }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:invalid-data]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should issue mass invite to users', function (done) {
|
||||||
|
User.create({ username: 'invite2' }, function (err, uid) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.issueMassInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', usernames: 'invite1, invite2' }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.isInvited(uid, 'PrivateCanJoin', function (err, isInvited) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isInvited);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should rescind invite', function (done) {
|
||||||
|
User.create({ username: 'invite3' }, function (err, uid) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.issueInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: uid }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.rescindInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: uid }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.isInvited(uid, 'PrivateCanJoin', function (err, isInvited) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(!isInvited);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error if user is not invited', function (done) {
|
||||||
|
socketGroups.acceptInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:not-invited]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept invite', function (done) {
|
||||||
|
User.create({ username: 'invite4' }, function (err, uid) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.issueInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: uid }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.acceptInvite({ uid: uid }, { groupName: 'PrivateCanJoin' }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.isMember(uid, 'PrivateCanJoin', function (err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should reject invite', function (done) {
|
||||||
|
User.create({ username: 'invite5' }, function (err, uid) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.issueInvite({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: uid }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
socketGroups.rejectInvite({ uid: uid }, { groupName: 'PrivateCanJoin' }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.isInvited(uid, 'PrivateCanJoin', function (err, isInvited) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(!isInvited);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should grant ownership to user', function (done) {
|
it('should grant ownership to user', function (done) {
|
||||||
socketGroups.grant({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: testUid }, function (err) {
|
socketGroups.grant({ uid: adminUid }, { groupName: 'PrivateCanJoin', toUid: testUid }, function (err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
@@ -568,6 +736,13 @@ describe('Groups', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail to kick user with invalid data', function (done) {
|
||||||
|
socketGroups.kick({ uid: adminUid }, { groupName: 'PrivateCanJoin', uid: adminUid }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:cant-kick-self]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should kick user from group', function (done) {
|
it('should kick user from group', function (done) {
|
||||||
socketGroups.kick({ uid: adminUid }, { groupName: 'PrivateCanJoin', uid: testUid }, function (err) {
|
socketGroups.kick({ uid: adminUid }, { groupName: 'PrivateCanJoin', uid: testUid }, function (err) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
@@ -578,6 +753,131 @@ describe('Groups', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail to create group with invalid data', function (done) {
|
||||||
|
socketGroups.create({ uid: 0 }, {}, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:no-privileges]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to create group if group creation is disabled', function (done) {
|
||||||
|
var oldValue = meta.config.allowGroupCreation;
|
||||||
|
meta.config.allowGroupCreation = 0;
|
||||||
|
socketGroups.create({ uid: 1 }, {}, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:group-creation-disabled]]');
|
||||||
|
meta.config.allowGroupCreation = oldValue;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to create group if name is privilege group', function (done) {
|
||||||
|
var oldValue = meta.config.allowGroupCreation;
|
||||||
|
meta.config.allowGroupCreation = 1;
|
||||||
|
socketGroups.create({ uid: 1 }, { name: 'cid:1:privileges:groups:find' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:invalid-group-name]]');
|
||||||
|
meta.config.allowGroupCreation = oldValue;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should create/update group', function (done) {
|
||||||
|
var oldValue = meta.config.allowGroupCreation;
|
||||||
|
meta.config.allowGroupCreation = 1;
|
||||||
|
socketGroups.create({ uid: adminUid }, { name: 'createupdategroup' }, function (err, groupData) {
|
||||||
|
meta.config.allowGroupCreation = oldValue;
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(groupData);
|
||||||
|
var data = {
|
||||||
|
groupName: 'createupdategroup',
|
||||||
|
values: {
|
||||||
|
name: 'renamedupdategroup',
|
||||||
|
description: 'cat group',
|
||||||
|
userTitle: 'cats',
|
||||||
|
userTitleEnabled: 1,
|
||||||
|
disableJoinRequests: 1,
|
||||||
|
hidden: 1,
|
||||||
|
private: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
socketGroups.update({ uid: adminUid }, data, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.get('renamedupdategroup', {}, function (err, groupData) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(groupData.name, 'renamedupdategroup');
|
||||||
|
assert.equal(groupData.userTitle, 'cats');
|
||||||
|
assert.equal(groupData.description, 'cat group');
|
||||||
|
assert.equal(groupData.hidden, true);
|
||||||
|
assert.equal(groupData.disableJoinRequests, true);
|
||||||
|
assert.equal(groupData.private, false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete group', function (done) {
|
||||||
|
socketGroups.delete({ uid: adminUid }, { groupName: 'renamedupdategroup' }, function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
Groups.exists('renamedupdategroup', function (err, exists) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(!exists);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to delete group if name is special', function (done) {
|
||||||
|
socketGroups.delete({ uid: adminUid }, { groupName: 'administrators' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:not-allowed]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to delete group if name is special', function (done) {
|
||||||
|
socketGroups.delete({ uid: adminUid }, { groupName: 'registered-users' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:not-allowed]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to delete group if name is special', function (done) {
|
||||||
|
socketGroups.delete({ uid: adminUid }, { groupName: 'Global Moderators' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:not-allowed]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to load more groups with invalid data', function (done) {
|
||||||
|
socketGroups.loadMore({ uid: adminUid }, {}, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:invalid-data]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load more groups', function (done) {
|
||||||
|
socketGroups.loadMore({ uid: adminUid }, { after: 0, sort: 'count' }, function (err, data) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(Array.isArray(data.groups));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail to load more members with invalid data', function (done) {
|
||||||
|
socketGroups.loadMoreMembers({ uid: adminUid }, {}, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:invalid-data]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load more members', function (done) {
|
||||||
|
socketGroups.loadMoreMembers({ uid: adminUid }, { after: 0, groupName: 'PrivateCanJoin' }, function (err, data) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(Array.isArray(data.users));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('admin socket methods', function () {
|
describe('admin socket methods', function () {
|
||||||
@@ -815,6 +1115,13 @@ describe('Groups', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail to remove cover if not logged in', function (done) {
|
||||||
|
socketGroups.cover.remove({ uid: 0 }, { groupName: 'Test' }, function (err) {
|
||||||
|
assert.equal(err.message, '[[error:no-privileges]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should fail to remove cover if not owner', function (done) {
|
it('should fail to remove cover if not owner', function (done) {
|
||||||
socketGroups.cover.remove({ uid: regularUid }, { groupName: 'Test' }, function (err) {
|
socketGroups.cover.remove({ uid: regularUid }, { groupName: 'Test' }, function (err) {
|
||||||
assert.equal(err.message, '[[error:no-privileges]]');
|
assert.equal(err.message, '[[error:no-privileges]]');
|
||||||
|
|||||||
55
test/template-helpers.js
Normal file
55
test/template-helpers.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var async = require('async');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var db = require('./mocks/databasemock');
|
||||||
|
var helpers = require('../public/src/modules/helpers');
|
||||||
|
|
||||||
|
describe('helpers', function () {
|
||||||
|
|
||||||
|
|
||||||
|
it('should return false if item doesn\'t exist', function (done) {
|
||||||
|
var flag = helpers.displayMenuItem({navigation: []}, 0);
|
||||||
|
assert(!flag);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should return false if route is /users and privateUserInfo is on and user is not logged in', function (done) {
|
||||||
|
var flag = helpers.displayMenuItem({
|
||||||
|
navigation: [{route: '/users'}],
|
||||||
|
privateUserInfo: true,
|
||||||
|
config: {
|
||||||
|
loggedIn: false
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
assert(!flag);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if route is /tags and privateTagListing is on and user is not logged in', function (done) {
|
||||||
|
var flag = helpers.displayMenuItem({
|
||||||
|
navigation: [{route: '/tags'}],
|
||||||
|
privateTagListing: true,
|
||||||
|
config: {
|
||||||
|
loggedIn: false
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
assert(!flag);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should stringify object', function (done) {
|
||||||
|
var str = helpers.stringify({a: 'herp < derp > and & quote "'});
|
||||||
|
assert.equal(str, '{"a":"herp < derp > and & quote \\""}');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should escape html', function (done) {
|
||||||
|
var str = helpers.escape('gdkfhgk < some > and &');
|
||||||
|
assert.equal(str, 'gdkfhgk < some > and &');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
177
test/topics.js
177
test/topics.js
@@ -10,6 +10,7 @@ var topics = require('../src/topics');
|
|||||||
var categories = require('../src/categories');
|
var categories = require('../src/categories');
|
||||||
var User = require('../src/user');
|
var User = require('../src/user');
|
||||||
var groups = require('../src/groups');
|
var groups = require('../src/groups');
|
||||||
|
var helpers = require('./helpers');
|
||||||
var socketPosts = require('../src/socket.io/posts');
|
var socketPosts = require('../src/socket.io/posts');
|
||||||
|
|
||||||
describe('Topic\'s', function () {
|
describe('Topic\'s', function () {
|
||||||
@@ -19,7 +20,7 @@ describe('Topic\'s', function () {
|
|||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
groups.resetCache();
|
groups.resetCache();
|
||||||
User.create({ username: 'admin' }, function (err, uid) {
|
User.create({ username: 'admin', password: '123456' }, function (err, uid) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
@@ -669,26 +670,176 @@ describe('Topic\'s', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load topic', function (done) {
|
describe('controller', function () {
|
||||||
topics.post({
|
var request = require('request');
|
||||||
uid: topic.userId,
|
var topicData;
|
||||||
title: 'topic for controller test',
|
|
||||||
content: 'topic content',
|
before(function (done) {
|
||||||
cid: topic.categoryId,
|
topics.post({
|
||||||
thumb: 'http://i.imgur.com/64iBdBD.jpg',
|
uid: topic.userId,
|
||||||
}, function (err, result) {
|
title: 'topic for controller test',
|
||||||
assert.ifError(err);
|
content: 'topic content',
|
||||||
assert.ok(result);
|
cid: topic.categoryId,
|
||||||
var request = require('request');
|
thumb: 'http://i.imgur.com/64iBdBD.jpg',
|
||||||
request(nconf.get('url') + '/topic/' + result.topicData.slug, function (err, response, body) {
|
}, function (err, result) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.ok(result);
|
||||||
|
topicData = result.topicData;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load topic', function (done) {
|
||||||
|
request(nconf.get('url') + '/topic/' + topicData.slug, function (err, response, body) {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.equal(response.statusCode, 200);
|
assert.equal(response.statusCode, 200);
|
||||||
assert(body);
|
assert(body);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should 404 if post index is invalid', function (done) {
|
||||||
|
request(nconf.get('url') + '/topic/' + topicData.slug + '/derp', function (err, response) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 404);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should 404 if topic does not exist', function (done) {
|
||||||
|
request(nconf.get('url') + '/topic/123123/does-not-exist', function (err, response) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 404);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should 401 if not allowed to read as guest', function (done) {
|
||||||
|
var privileges = require('../src/privileges');
|
||||||
|
privileges.categories.rescind(['read'], topicData.cid, 'guests', function (err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
request(nconf.get('url') + '/api/topic/' + topicData.slug, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 401);
|
||||||
|
assert(body);
|
||||||
|
privileges.categories.give(['read'], topicData.cid, 'guests', done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should redirect to correct topic if slug is missing', function (done) {
|
||||||
|
request(nconf.get('url') + '/topic/' + topicData.tid + '/herpderp/1?page=2', function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 200);
|
||||||
|
assert(body);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should redirect if post index is out of range', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/' + topicData.slug + '/-1', function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 308);
|
||||||
|
assert.equal(body, '"/topic/13/topic-for-controller-test"');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should 404 if page is out of bounds', function (done) {
|
||||||
|
var meta = require('../src/meta');
|
||||||
|
meta.config.usePagination = 1;
|
||||||
|
request(nconf.get('url') + '/topic/' + topicData.slug + '?page=100', function (err, response) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 404);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mark topic read', function (done) {
|
||||||
|
helpers.loginUser('admin', '123456', function (err, jar) {
|
||||||
|
assert.ifError(err);
|
||||||
|
request(nconf.get('url') + '/topic/' + topicData.slug, {
|
||||||
|
jar: jar,
|
||||||
|
}, function (err, res) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(res.statusCode, 200);
|
||||||
|
topics.hasReadTopics([topicData.tid], adminUid, function (err, hasRead) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(hasRead[0], true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should 404 if tid is not a number', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/teaser/nan', { json: true }, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 404);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should 403 if cant read', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/teaser/' + 123123, { json: true }, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 403);
|
||||||
|
assert.equal(body, '[[error:no-privileges]]');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load topic teaser', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/teaser/' + topicData.tid, { json: true }, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 200);
|
||||||
|
assert(body);
|
||||||
|
assert.equal(body.tid, topicData.tid);
|
||||||
|
assert.equal(body.content, 'topic content');
|
||||||
|
assert(body.user);
|
||||||
|
assert(body.topic);
|
||||||
|
assert(body.category);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should 404 if tid is not a number', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/pagination/nan', { json: true }, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 404);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should 404 if tid does not exist', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/pagination/1231231', { json: true }, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 404);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load pagination', function (done) {
|
||||||
|
request(nconf.get('url') + '/api/topic/pagination/' + topicData.tid, { json: true }, function (err, response, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(response.statusCode, 200);
|
||||||
|
assert(body);
|
||||||
|
assert.deepEqual(body, {
|
||||||
|
prev: { page: 1, active: false },
|
||||||
|
next: { page: 1, active: false },
|
||||||
|
rel: [],
|
||||||
|
pages: [],
|
||||||
|
currentPage: 1,
|
||||||
|
pageCount: 1,
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('infinitescroll', function () {
|
describe('infinitescroll', function () {
|
||||||
var socketTopics = require('../src/socket.io/topics');
|
var socketTopics = require('../src/socket.io/topics');
|
||||||
var tid;
|
var tid;
|
||||||
|
|||||||
@@ -87,6 +87,20 @@ describe('Upload Controllers', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should resize and upload an image to a post', function (done) {
|
||||||
|
var oldValue = meta.config.maximumImageWidth;
|
||||||
|
meta.config.maximumImageWidth = 10;
|
||||||
|
helpers.uploadFile(nconf.get('url') + '/api/post/upload', path.join(__dirname, '../test/files/test.png'), { cid: cid }, jar, csrf_token, function (err, res, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(res.statusCode, 200);
|
||||||
|
assert(Array.isArray(body));
|
||||||
|
assert(body[0].path);
|
||||||
|
assert(body[0].url);
|
||||||
|
meta.config.maximumImageWidth = oldValue;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should upload a file to a post', function (done) {
|
it('should upload a file to a post', function (done) {
|
||||||
meta.config.allowFileUploads = 1;
|
meta.config.allowFileUploads = 1;
|
||||||
@@ -99,6 +113,37 @@ describe('Upload Controllers', function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fail if topic thumbs are disabled', function (done) {
|
||||||
|
helpers.uploadFile(nconf.get('url') + '/api/topic/thumb/upload', path.join(__dirname, '../test/files/test.png'), {}, jar, csrf_token, function (err, res, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(res.statusCode, 500);
|
||||||
|
assert.equal(body.error, '[[error:topic-thumbnails-are-disabled]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail if file is not image', function (done) {
|
||||||
|
meta.config.allowTopicsThumbnail = 1;
|
||||||
|
helpers.uploadFile(nconf.get('url') + '/api/topic/thumb/upload', path.join(__dirname, '../test/files/503.html'), {}, jar, csrf_token, function (err, res, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(res.statusCode, 500);
|
||||||
|
assert.equal(body.error, '[[error:invalid-file]]');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should upload topic thumb', function (done) {
|
||||||
|
meta.config.allowTopicsThumbnail = 1;
|
||||||
|
helpers.uploadFile(nconf.get('url') + '/api/topic/thumb/upload', path.join(__dirname, '../test/files/test.png'), {}, jar, csrf_token, function (err, res, body) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(res.statusCode, 200);
|
||||||
|
assert(Array.isArray(body));
|
||||||
|
assert(body[0].path);
|
||||||
|
assert(body[0].url);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user