Merge commit '3bebc3ce09e66bbd18203eeaf72a9ab286eceed6' into weekly

This commit is contained in:
NodeBB Misty
2016-06-27 16:00:19 -04:00
51 changed files with 522 additions and 309 deletions

1
app.js
View File

@@ -22,7 +22,6 @@
var nconf = require('nconf');
nconf.argv().env('__');
require('continuation-local-storage');
var url = require('url'),
async = require('async'),

View File

@@ -26,7 +26,6 @@
"connect-mongo": "~1.1.0",
"connect-multiparty": "^2.0.0",
"connect-redis": "~3.0.2",
"continuation-local-storage": "^3.1.6",
"cookie-parser": "^1.3.3",
"cron": "^1.0.5",
"csurf": "^1.6.1",
@@ -48,18 +47,18 @@
"morgan": "^1.3.2",
"mousetrap": "^1.5.3",
"nconf": "~0.8.2",
"nodebb-plugin-composer-default": "4.0.2",
"nodebb-plugin-composer-default": "4.0.5",
"nodebb-plugin-dbsearch": "1.0.2",
"nodebb-plugin-emoji-extended": "1.1.0",
"nodebb-plugin-emoji-one": "1.1.5",
"nodebb-plugin-markdown": "5.1.6",
"nodebb-plugin-markdown": "6.0.0",
"nodebb-plugin-mentions": "1.1.2",
"nodebb-plugin-soundpack-default": "0.1.6",
"nodebb-plugin-spam-be-gone": "0.4.6",
"nodebb-plugin-spam-be-gone": "0.4.8",
"nodebb-rewards-essentials": "0.0.8",
"nodebb-theme-lavender": "3.0.13",
"nodebb-theme-persona": "4.0.148",
"nodebb-theme-vanilla": "5.0.78",
"nodebb-theme-persona": "4.1.3",
"nodebb-theme-vanilla": "5.1.0",
"nodebb-widget-essentials": "2.0.9",
"nodemailer": "2.0.0",
"nodemailer-sendmail-transport": "1.0.0",
@@ -118,4 +117,4 @@
"url": "https://github.com/barisusakli"
}
]
}
}

View File

@@ -23,7 +23,7 @@
"pagination.enter_index": "Enter index",
"header.admin": "Administrace",
"header.categories": "Kategorie",
"header.recent": "Aktuality",
"header.recent": "Nejnovější",
"header.unread": "Nepřečtené",
"header.tags": "Tagy",
"header.popular": "Populární",

View File

@@ -63,7 +63,9 @@
"topics": "Topics",
"posts": "Posts",
"best": "Best",
"upvoters": "Upvoters",
"upvoted": "Upvoted",
"downvoters": "Downvoters",
"downvoted": "Downvoted",
"views": "Views",
"reputation": "Reputation",

View File

@@ -1,5 +1,6 @@
{
"register": "Register",
"cancel_registration": "Cancel Registration",
"help.email": "By default, your email will be hidden from the public.",
"help.username_restrictions": "A unique username between %1 and %2 characters. Others can mention you with @<span id='yourUsername'>username</span>.",
"help.minimum_password_length": "Your password's length must be at least %1 characters.",
@@ -15,5 +16,8 @@
"alternative_registration": "Alternative Registration",
"terms_of_use": "Terms of Use",
"agree_to_terms_of_use": "I agree to the Terms of Use",
"registration-added-to-queue": "Your registration has been added to the approval queue. You will receive an email when it is accepted by an administrator."
"terms_of_use_error": "You must agree to the Terms of Use",
"registration-added-to-queue": "Your registration has been added to the approval queue. You will receive an email when it is accepted by an administrator.",
"interstitial.intro": "We require some additional information before we can create your account.",
"interstitial.errors-found": "We could not complete your registration:"
}

View File

@@ -24,7 +24,7 @@
"digest.day": "روز",
"digest.week": "هفته",
"digest.month": "ماه",
"digest.subject": "Digest for %1",
"digest.subject": "خلاصه برای %1",
"notif.chat.subject": "پیام چتی جدیدی از %1 دریافت شد",
"notif.chat.cta": "برای ادامه‌ی چت اینجا کلیک کنید",
"notif.chat.unsub.info": "این اطلاعیه ی چتیی که برای شما فرستاده شده به علت تنظیمات اشترک شماست.",

View File

@@ -58,9 +58,9 @@
"too-many-tags": "تعداد برچسب ها بیشتر از حد مجاز است. موضوع ها نمی توانند بیشتر از %1 برچسب داشته باشند",
"still-uploading": "خواهشمندیم تا پایان بارگذاری‌ها شکیبا باشید.",
"file-too-big": "حداکثر مجاز حجم فایل %1 کیلوبایت می باشد - لطفا فایلی با حجم کمتر بارگذاری کنید",
"guest-upload-disabled": "Guest uploading has been disabled",
"already-favourited": "You have already bookmarked this post",
"already-unfavourited": "You have already unbookmarked this post",
"guest-upload-disabled": "بارگذاری برای مهمانان غیر فعال شده است",
"already-favourited": "شما در حال حاضر این پست را به علاقمندی های خود اضافه کرده ایید",
"already-unfavourited": "شما در حال حاضر این پست را از لیست علاقمندی خود خارج کردید",
"cant-ban-other-admins": "شما نمی‌توانید دیگر مدیران را محروم کنید!",
"cant-remove-last-admin": "شما تنها مدیر می باشید . شما باید قبل از عزل خود از مدیریت یک کاربر دیگر را مدیر کنید",
"cant-delete-admin": "Remove administrator privileges from this account before attempting to delete it.",
@@ -87,14 +87,14 @@
"about-me-too-long": "با عرض پوزش محتوای 'درباره ی من' نمی تواند طولانی تر از %1 کاراکتر باشد",
"cant-chat-with-yourself": "شما نمی‌توانید با خودتان چت کنید!",
"chat-restricted": "این کاربر پیام های چتی خود را محدود کرده است . آنها بایدشما را دنبال کنند تا اینکه شما بتوانید به آنها پیامی بفرستید",
"chat-disabled": "Chat system disabled",
"chat-disabled": "سیستم گفتمان غیرفعال شده است",
"too-many-messages": "شما پیامهای خیلی زیادی فرستاده اید، لطفا مدتی صبر نمایید",
"invalid-chat-message": "پیام نامعتبر",
"chat-message-too-long": "پیام طولانی تر از حد مجاز است",
"cant-edit-chat-message": "شما اجازه ی ویرایش این پیام را ندارید",
"cant-remove-last-user": "You can't remove the last user",
"cant-delete-chat-message": "You are not allowed to delete this message",
"already-voting-for-this-post": "You have already voted for this post.",
"cant-delete-chat-message": "شما اجازه حذف این پیام را ندارید.",
"already-voting-for-this-post": "شما قبلا به این پست رای داده اید.",
"reputation-system-disabled": "سیستم اعتبار غیر فعال شده است",
"downvoting-disabled": "رأی منفی غیر فعال شده است",
"not-enough-reputation-to-downvote": "شما اعتبار کافی برای دادن رأی منفی به این پست را ندارید.",
@@ -107,7 +107,7 @@
"wrong-login-type-username": "لطفا از نام کاربری خود برای ورود استفاده کنید",
"invite-maximum-met": "You have invited the maximum amount of people (%1 out of %2).",
"no-session-found": "No login session found!",
"not-in-room": "User not in room",
"not-in-room": "هیچ کاربری در این گفتگو نیست",
"no-users-in-room": "هیچ کاربری در این گفتگو نیست",
"cant-kick-self": "You can't kick yourself from the group"
"cant-kick-self": "شما نمی توانید خودتان را از گروه کیک کنید"
}

View File

@@ -49,7 +49,7 @@
"users": "کاربران",
"topics": "موضوع ها",
"posts": "دیدگاه‌ها",
"best": "Best",
"best": "بهترین",
"upvoted": "Upvoted",
"downvoted": "Downvoted",
"views": "بازدیدها",
@@ -65,7 +65,7 @@
"posted_in_ago_by": "ارسال شده در %1 %2 توسط %3",
"user_posted_ago": "%1 در %2 ارسال کرده است",
"guest_posted_ago": "مهمان در %1 ارسال کرده است",
"last_edited_by": "last edited by %1",
"last_edited_by": "آخرین ویرایش توسط %1 انجام شده",
"norecentposts": "هیچ دیدگاه تازه‌ای نیست",
"norecenttopics": "هیچ جستار تازه‌ای نیست",
"recentposts": "دیدگاه‌های تازه",
@@ -85,10 +85,10 @@
"unfollow": "دنبال نکن",
"delete_all": "حذف همه",
"map": "نقشه",
"sessions": "Login Sessions",
"ip_address": "IP Address",
"enter_page_number": "Enter page number",
"upload_file": "Upload file",
"upload": "Upload",
"allowed-file-types": "Allowed file types are %1"
"sessions": "Session های ورود",
"ip_address": "آدرس آی پی",
"enter_page_number": "شماره صفحه را وارد کنید",
"upload_file": "بارگذاری فایل",
"upload": "بارگذاری",
"allowed-file-types": "فایل قابل قبول اینها هستند %1"
}

View File

@@ -41,7 +41,7 @@
"details.hidden": "پنهان",
"details.hidden_help": "اگر فعال باشد، این گروه در فهرست گروه‌ها پیدا نمی‌شود و کاربران باید دستی فراخوانده شوند",
"details.delete_group": "حذف گروه",
"details.private_system_help": "Private groups is disabled at system level, this option does not do anything",
"details.private_system_help": "گروه های خصوصی در این سطح سیستم غیر فعال هستند، این گزینه هیچ کاری انجام نمی دهد",
"event.updated": "جزییات گروه با موفقیت به روز شد",
"event.deleted": "گروه \"%1\" حدف شد",
"membership.accept-invitation": "دعوت را قبول میکنم",

View File

@@ -5,7 +5,7 @@
"remember_me": "مرا به یاد بسپار؟",
"forgot_password": "گذرواژه را فراموش کرده‌اید؟",
"alternative_logins": "روش‌های درون آمدن جایگزین",
"failed_login_attempt": "Login Unsuccessful",
"failed_login_attempt": "ورود ناموفق",
"login_successful": "شما با موفقیت به درون آمده‌اید!",
"dont_have_account": "حساب کاربری ندارید؟"
}

View File

@@ -6,7 +6,7 @@
"chat.user_typing": "%1 در حال نوشتن است...",
"chat.user_has_messaged_you": "%1 به شما پیام داده است.",
"chat.see_all": "دیدن همه ی چت ها",
"chat.mark_all_read": "Mark all chats read",
"chat.mark_all_read": "علامت گذاری شده به عنوان تمام چت ها را خوانده",
"chat.no-messages": "مشخص کنید تاریخچه چتهایتان با چه کاربری را می‌خواهید ببینید",
"chat.no-users-in-room": "هیچ کاربری در این گفتگو نیست",
"chat.recent-chats": "چتهای اخیر",
@@ -18,8 +18,8 @@
"chat.thirty_days": "30 روز",
"chat.three_months": "3 ماه",
"chat.delete_message_confirm": "آیا مطمئن هستید که می خواهید این پیام را حذف کنید؟",
"chat.roomname": "Chat Room %1",
"chat.add-users-to-room": "Add users to room",
"chat.roomname": "اتاق گفتگو %1",
"chat.add-users-to-room": "اضافه کردن کاربر به این گفتگو",
"composer.compose": "ارسال",
"composer.show_preview": "نمایش پیش‌نمایش",
"composer.hide_preview": "مخفی کردن پیش‌نمایش",
@@ -29,14 +29,14 @@
"composer.submit_and_lock": "ارسال و قفل",
"composer.toggle_dropdown": "باز و بسته کردن کرکره",
"composer.uploading": "در حال بارگذاری %1",
"composer.formatting.bold": "Bold",
"composer.formatting.italic": "Italic",
"composer.formatting.list": "List",
"composer.formatting.strikethrough": "Strikethrough",
"composer.formatting.link": "Link",
"composer.formatting.picture": "Picture",
"composer.upload-picture": "Upload Image",
"composer.upload-file": "Upload File",
"composer.formatting.bold": "توپر",
"composer.formatting.italic": "کج",
"composer.formatting.list": "فهرست",
"composer.formatting.strikethrough": "خط خورده",
"composer.formatting.link": "پیوند",
"composer.formatting.picture": "عکس",
"composer.upload-picture": "بارگذاری عکس",
"composer.upload-file": "بارگذاری فایل",
"bootbox.ok": "باشه",
"bootbox.cancel": "لغو",
"bootbox.confirm": "تایید",

View File

@@ -5,7 +5,7 @@
"mark_all_read": "همه اطلاعیه ها را خوانده شده علامت بزن",
"back_to_home": "بازگشت به %1",
"outgoing_link": "پیوند برون‌رو",
"outgoing_link_message": "You are now leaving %1",
"outgoing_link_message": "شما در حال ترک %1 هستید",
"continue_to": "ادامه به %1",
"return_to": "بازگشت به %1",
"new_notification": "آکاه‌سازی تازه",

View File

@@ -11,7 +11,7 @@
"users/latest": "آخرین کاربران",
"users/sort-posts": "کاربران با بیش‌ترین پست",
"users/sort-reputation": "کاربران دارای بیشترین اعتبار",
"users/banned": "Banned Users",
"users/banned": "کاربران اخراج شده",
"users/search": "جستجوی کاربر",
"notifications": "آگاه‌سازی‌ها",
"tags": "برچسب‌ها",
@@ -39,7 +39,7 @@
"account/upvoted": "Posts upvoted by %1",
"account/downvoted": "Posts downvoted by %1",
"account/best": "Best posts made by %1",
"confirm": "Email Confirmed",
"confirm": "ایمیل تایید شد",
"maintenance.text": "%1 در حال حاضر تحت تعمیر و نگهدارییست. لطفا زمان دیگری مراجعه کنید.",
"maintenance.messageIntro": "علاوه بر این، مدیر این پیام را گذاشته است:",
"throttled.text": "%1 به دلیل بارگذاری بیش از حد ، قابل دسترس نمی باشد. لطفا در زمان دیگری دوباره امتحان کنید"

View File

@@ -13,7 +13,7 @@
"notify_me": "از پاسخ‌های تازه در موضوع آگاه شوید",
"quote": "نقل قول",
"reply": "پاسخ",
"reply-as-topic": "Reply as topic",
"reply-as-topic": "پاسخ به موضوع",
"guest-login-reply": "وارد شوید تا پست بفرستید",
"edit": "ویرایش",
"delete": "حذف",
@@ -58,7 +58,7 @@
"thread_tools.move_all": "جابجایی همه",
"thread_tools.fork": "شاخه ساختن از موضوع",
"thread_tools.delete": "پاک کردن موضوع",
"thread_tools.delete-posts": "Delete Posts",
"thread_tools.delete-posts": "حذف پست ها",
"thread_tools.delete_confirm": "آیا مطمئنید می خواهید این موضوع را حذف کنید؟",
"thread_tools.restore": "برگرداندن موضوع",
"thread_tools.restore_confirm": "آیا مطمئنید که می خواهید این موضوع را بازگردانی کنید؟",
@@ -73,7 +73,7 @@
"confirm_move": "جابه‌جا کردن",
"confirm_fork": "شاخه ساختن",
"favourite": "Bookmark",
"favourites": "Bookmarks",
"favourites": "علاقمندی ها",
"favourites.has_no_favourites": "You haven't bookmarked any posts yet.",
"loading_more_posts": "بارگذاری پست‌های بیش‌تر",
"move_topic": "جابه‌جایی موضوع",
@@ -112,7 +112,7 @@
"stale.warning": "موضوعی که شما در حال پاسخگویی به آن هستید قدیمی می باشد. آیا میلید به جای آن یک موضوع جدید ایجاد کنید و در آن به این موضوع ارجاع دهید؟",
"stale.create": "ایجاد یک موضوع جدید",
"stale.reply_anyway": "در هر صورت می خواهم به این موضوع پاسخ دهم",
"link_back": "Re: [%1](%2)",
"link_back": "پاسخ: [%1](%2)",
"spam": "اسپم",
"offensive": "توهین آمیز",
"custom-flag-reason": "وارد کردن دلیل پرچمگذاری"

View File

@@ -7,7 +7,7 @@
"all": "همه",
"all_categories": "تمام دسته ها",
"topics_marked_as_read.success": "همه موضوع ها خوانده شدند",
"all-topics": "All Topics",
"new-topics": "New Topics",
"watched-topics": "Watched Topics"
"all-topics": "همه موضوع ها",
"new-topics": "موضوع های جدید",
"watched-topics": "موضوع های پیگیری شده"
}

View File

@@ -1,6 +1,6 @@
{
"uploading-file": "Uploading the file...",
"select-file-to-upload": "Select a file to upload!",
"upload-success": "File uploaded successfully!",
"maximum-file-size": "Maximum %1 kb"
"uploading-file": "در حال بارگذاری فایل...",
"select-file-to-upload": "فایل مورد نظر را برای بارگذاری انتخاب کنید!",
"upload-success": "فایل با موفقیت بارگذاری شد!",
"maximum-file-size": "حداکثر %1 کیلوبایت"
}

View File

@@ -22,7 +22,7 @@
"profile": "پروفایل",
"profile_views": "بازدیدهای نمایه",
"reputation": "اعتبار",
"favourites": "Bookmarks",
"favourites": "علاقمندی ها",
"watched": "پیگیری شده",
"followers": "دنبال‌کننده‌ها",
"following": "دنبال‌شونده‌ها",
@@ -39,7 +39,7 @@
"change_username": "تغییر نام کاربری",
"change_email": "تغییر ایمیل",
"edit": "ویرایش",
"edit-profile": "Edit Profile",
"edit-profile": "ویرایش پروفایل",
"default_picture": "آیکون پیش فرض",
"uploaded_picture": "تصویر بارشده",
"upload_new_picture": "بارگذاری تصویر تازه",
@@ -56,11 +56,11 @@
"password": "گذرواژه",
"username_taken_workaround": "نام کاربری درخواستی شما در حال حاضر گرفته شده است، بنابراین ما آن را کمی تغییر داده‌ایم. شما هم‌اکنون با نام <strong>%1</strong شناخته می‌شوید.",
"password_same_as_username": "کلمه ی عبور شما با نام کاربری شما یکسان می باشند ، لطفا کلمه ی عبور دیگری را انتخاب کنید",
"password_same_as_email": "Your password is the same as your email, please select another password.",
"password_same_as_email": "کلمه ی عبور شما با ایمیل شما یکسان است، لطفا کلمه عبور دیگری را انتخاب کنید.",
"upload_picture": "بارگذاری تصویر",
"upload_a_picture": "یک تصویر بارگذاری کنید",
"remove_uploaded_picture": "پاک کردن عکس بارگذاری شده",
"upload_cover_picture": "Upload cover picture",
"upload_cover_picture": "بارگذاری عکس کاور",
"settings": "تنظیمات",
"show_email": "نمایش ایمیل‌ام",
"show_fullname": "نام کامل من را نشان بده",
@@ -79,9 +79,9 @@
"has_no_posts": "این کاربر تا به حال هیچ چیزی ارسال نکرده است.",
"has_no_topics": "این کاربر تا به حال هیچ موضوعی ارسال نکرده است",
"has_no_watched_topics": "این کاربر تا به حال هیچ موضوعی را پیگیری نکرده است",
"has_no_upvoted_posts": "This user hasn't upvoted any posts yet.",
"has_no_upvoted_posts": "این کاربر به هیچ پستی امتیاز نداده است.",
"has_no_downvoted_posts": "This user hasn't downvoted any posts yet.",
"has_no_voted_posts": "This user has no voted posts",
"has_no_voted_posts": "این کاربر به پست رای نداده است",
"email_hidden": "ایمیل پنهان شده",
"hidden": "پنهان",
"paginate_description": "صفحه بندی و نمایش موضوع ها و پست‌ها به جای نمایش بر اساس اسکرول موس",
@@ -92,12 +92,12 @@
"open_links_in_new_tab": "پیوندهای به بیرون را در برگ جدید باز کن",
"enable_topic_searching": "فعال کردن جستجوی داخل-موضوع",
"topic_search_help": "If enabled, in-topic searching will override the browser's default page search behaviour and allow you to search through the entire topic, instead of what is only shown on screen",
"delay_image_loading": "Delay Image Loading",
"delay_image_loading": "تاخیر در حال بارگذاری عکس",
"image_load_delay_help": "If enabled, images in topics will not load until they are scrolled into view",
"scroll_to_my_post": "After posting a reply, show the new post",
"scroll_to_my_post": "پس از ارسال پست، اولین پست جدید نشان بده",
"follow_topics_you_reply_to": "تاپیک هایی که پاسخ داده ای را دنبال کن",
"follow_topics_you_create": "موضوع هایی که ایجاد کرده ای را دنبال کن",
"grouptitle": "Group Title",
"grouptitle": "عنوان گروه",
"no-group-title": "عنوان گروهی نیست",
"select-skin": "Select a Skin",
"select-homepage": "Select a Homepage",

View File

@@ -1,5 +1,5 @@
{
"name": "אנגלית (הממלכה המאוחדת/קנדה)",
"name": "עברית (ישראל)",
"code": "he",
"dir": "rtl"
}

View File

@@ -173,7 +173,15 @@ define('admin/manage/group', [
if (err) {
return app.alertError(err.message);
}
app.alertSuccess('Changes saved!');
var newName = $('#change-group-name').val();
// If the group name changed, change url
if (groupName === newName) {
app.alertSuccess('Changes saved!');
} else {
ajaxify.go('admin/manage/groups/' + encodeURIComponent(newName), undefined, true);
}
});
return false;
});

View File

@@ -13,8 +13,7 @@ define('forum/register', ['csrf', 'translator'], function(csrf, translator) {
username = $('#username'),
password = $('#password'),
password_confirm = $('#password-confirm'),
register = $('#register'),
agreeTerms = $('#agree-terms');
register = $('#register');
handleLanguageOverride();
@@ -111,18 +110,6 @@ define('forum/register', ['csrf', 'translator'], function(csrf, translator) {
});
});
});
if (agreeTerms.length) {
agreeTerms.on('click', function() {
if ($(this).prop('checked')) {
register.removeAttr('disabled');
} else {
register.attr('disabled', 'disabled');
}
});
register.attr('disabled', 'disabled');
}
};
function validateEmail(email, callback) {

View File

@@ -242,37 +242,40 @@ define('forum/topic', [
Topic.navigatorCallback = function(index, elementCount, threshold) {
var path = ajaxify.removeRelativePath(window.location.pathname.slice(1));
if (!path.startsWith('topic')) {
return 1;
return;
}
if (!navigator.scrollActive) {
var parts = ajaxify.removeRelativePath(window.location.pathname.slice(1)).split('/');
var topicId = parts[1],
slug = parts[2];
var newUrl = 'topic/' + topicId + '/' + (slug ? slug : '');
if (index > 1) {
newUrl += '/' + index;
if (navigator.scrollActive) {
return;
}
posts.loadImages(threshold);
var newUrl = 'topic/' + ajaxify.data.slug + (index > 1 ? ('/' + index) : '');
if (newUrl !== currentUrl) {
if (Topic.replaceURLTimeout) {
clearTimeout(Topic.replaceURLTimeout);
}
posts.loadImages(threshold);
Topic.replaceURLTimeout = setTimeout(function() {
if (newUrl !== currentUrl) {
if (Topic.replaceURLTimeout) {
clearTimeout(Topic.replaceURLTimeout);
if (index >= elementCount && app.user.uid) {
socket.emit('topics.markAsRead', [ajaxify.data.tid]);
}
Topic.replaceURLTimeout = setTimeout(function() {
updateUserBookmark(index);
Topic.replaceURLTimeout = 0;
if (history.replaceState) {
var search = (window.location.search ? window.location.search : '');
history.replaceState({
url: newUrl + search
}, null, window.location.protocol + '//' + window.location.host + RELATIVE_PATH + '/' + newUrl + search);
}
currentUrl = newUrl;
}, 500);
}
updateUserBookmark(index);
Topic.replaceURLTimeout = 0;
if (history.replaceState) {
var search = (window.location.search ? window.location.search : '');
history.replaceState({
url: newUrl + search
}, null, window.location.protocol + '//' + window.location.host + RELATIVE_PATH + '/' + newUrl + search);
}
currentUrl = newUrl;
}, 500);
}
};

View File

@@ -226,41 +226,39 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
}
function onReplyClicked(button, tid) {
showStaleWarning(function(proceed) {
if (!proceed) {
var selectedText = getSelectedText(button);
showStaleWarning(function() {
var selectedText = getSelectedText(button);
var username = getUserName(button);
if (getData(button, 'data-uid') === '0' || !getData(button, 'data-userslug')) {
username = '';
}
var username = getUserName(button);
if (getData(button, 'data-uid') === '0' || !getData(button, 'data-userslug')) {
username = '';
}
var toPid = button.is('[component="post/reply"]') ? getData(button, 'data-pid') : null;
var toPid = button.is('[component="post/reply"]') ? getData(button, 'data-pid') : null;
if (selectedText) {
$(window).trigger('action:composer.addQuote', {
tid: tid,
slug: ajaxify.data.slug,
index: getData(button, 'data-index'),
pid: toPid,
topicName: ajaxify.data.titleRaw,
username: username,
text: selectedText
});
} else {
$(window).trigger('action:composer.post.new', {
tid: tid,
pid: toPid,
topicName: ajaxify.data.titleRaw,
text: username ? username + ' ' : ''
});
}
if (selectedText) {
$(window).trigger('action:composer.addQuote', {
tid: tid,
slug: ajaxify.data.slug,
index: getData(button, 'data-index'),
pid: toPid,
topicName: ajaxify.data.titleRaw,
username: username,
text: selectedText
});
} else {
$(window).trigger('action:composer.post.new', {
tid: tid,
pid: toPid,
topicName: ajaxify.data.titleRaw,
text: username ? username + ' ' : ''
});
}
});
}
function onQuoteClicked(button, tid) {
showStaleWarning(function(proceed) {
showStaleWarning(function() {
function quote(text) {
$(window).trigger('action:composer.addQuote', {
@@ -274,21 +272,19 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
});
}
if (!proceed) {
var username = getUserName(button);
var pid = getData(button, 'data-pid');
var selectedText = getSelectedText(button);
if (selectedText) {
return quote(selectedText);
}
socket.emit('posts.getRawPost', pid, function(err, post) {
if (err) {
return app.alertError(err.message);
}
quote(post);
});
var username = getUserName(button);
var pid = getData(button, 'data-pid');
var selectedText = getSelectedText(button);
if (selectedText) {
return quote(selectedText);
}
socket.emit('posts.getRawPost', pid, function(err, post) {
if (err) {
return app.alertError(err.message);
}
quote(post);
});
});
}
@@ -498,39 +494,39 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator
}
function showStaleWarning(callback) {
if (ajaxify.data.lastposttime < (Date.now() - (1000 * 60 * 60 * 24 * ajaxify.data.topicStaleDays))) {
translator.translate('[[topic:stale.warning]]', function(translated) {
var warning = bootbox.dialog({
title: '[[topic:stale.title]]',
message: translated,
buttons: {
reply: {
label: '[[topic:stale.reply_anyway]]',
className: 'btn-link',
callback: function() {
callback(false);
}
},
create: {
label: '[[topic:stale.create]]',
className: 'btn-primary',
callback: function() {
translator.translate('[[topic:link_back, ' + ajaxify.data.title + ', ' + config.relative_path + '/topic/' + ajaxify.data.slug + ']]', function(body) {
$(window).trigger('action:composer.topic.new', {
cid: ajaxify.data.cid,
body: body
});
if (ajaxify.data.lastposttime >= (Date.now() - (1000 * 60 * 60 * 24 * ajaxify.data.topicStaleDays))) {
return callback();
}
translator.translate('[[topic:stale.warning]]', function(translated) {
var warning = bootbox.dialog({
title: '[[topic:stale.title]]',
message: translated,
buttons: {
reply: {
label: '[[topic:stale.reply_anyway]]',
className: 'btn-link',
callback: function() {
callback();
}
},
create: {
label: '[[topic:stale.create]]',
className: 'btn-primary',
callback: function() {
translator.translate('[[topic:link_back, ' + ajaxify.data.title + ', ' + config.relative_path + '/topic/' + ajaxify.data.slug + ']]', function(body) {
$(window).trigger('action:composer.topic.new', {
cid: ajaxify.data.cid,
body: body
});
}
});
}
}
});
}
});
warning.modal();
});
} else {
callback(false);
}
warning.modal();
});
}
return PostTools;

View File

@@ -225,9 +225,6 @@ define('forum/topic/posts', [
if (data && data.posts && data.posts.length) {
createNewPosts(data, replies, direction, done);
} else {
if (app.user.uid) {
socket.emit('topics.markAsRead', [tid]);
}
navigator.update();
done();
}

View File

@@ -45,6 +45,7 @@ define('forum/unread', ['forum/recent', 'topicSelect', 'forum/infinitescroll', '
app.alertSuccess('[[unread:topics_marked_as_read.success]]');
$('[component="category"]').empty();
$('[component="pagination"]').addClass('hidden');
$('#category-no-topics').removeClass('hidden');
$('.markread').addClass('hidden');
});

View File

@@ -17,8 +17,15 @@ define('navigator', ['forum/pagination', 'components'], function(pagination, com
navigator.callback = callback;
toTop = toTop || function() {};
toBottom = toBottom || function() {};
var navigatorUpdateTimeoutId = 0;
$(window).off('scroll', navigator.update).on('scroll', navigator.update);
$(window).off('scroll', navigator.update).on('scroll', function() {
if (navigatorUpdateTimeoutId) {
clearTimeout(navigatorUpdateTimeoutId);
navigatorUpdateTimeoutId = 0;
}
navigatorUpdateTimeoutId = setTimeout(navigator.update, 100);
});
$('.pagination-block .dropdown-menu').off('click').on('click', function(e) {
e.stopPropagation();

View File

@@ -0,0 +1,20 @@
// Azerbaijani shortened
jQuery.timeago.settings.strings = {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "",
suffixFromNow: "",
seconds: '1 dəq',
minute: '1 dəq',
minutes: '%d dəq',
hour: '1 saat',
hours: '%d saat',
day: '1 gün',
days: '%d gün',
month: '1 ay',
months: '%d ay',
year: '1 il',
years: '%d il',
wordSeparator: '',
numbers: []
};

View File

@@ -0,0 +1,20 @@
// Azerbaijani
jQuery.timeago.settings.strings = {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: 'əvvəl',
suffixFromNow: 'sonra',
seconds: 'saniyələr',
minute: '1 dəqiqə',
minutes: '%d dəqiqə',
hour: '1 saat',
hours: '%d saat',
day: '1 gün',
days: '%d gün',
month: '1 ay',
months: '%d ay',
year: '1 il',
years: '%d il',
wordSeparator: '',
numbers: []
};

View File

@@ -4,17 +4,17 @@ jQuery.timeago.settings.strings = {
prefixFromNow: null,
suffixAgo: "",
suffixFromNow: "",
seconds: "sec",
minute: "1min",
minutes: "%dmin",
seconds: "s",
minute: "1m",
minutes: "%dm",
hour: "1h",
hours: "%dh",
day: "1d",
days: "%dd",
month: "1Mon",
months: "%dMon",
year: "1Jhr",
years: "%dJhr",
day: "1T.",
days: "%dT.",
month: "1Mt.",
months: "%dMt.",
year: "1J.",
years: "%dJ.",
wordSeparator: " ",
numbers: []
};

View File

@@ -11,8 +11,8 @@ jQuery.timeago.settings.strings = {
hours: "約 %d 時間",
day: "約 1 日",
days: "約 %d 日",
month: "約 1 月",
months: "約 %d 月",
month: "約 1 月",
months: "約 %d 月",
year: "約 1 年",
years: "約 %d 年",
wordSeparator: ""

View File

@@ -0,0 +1,20 @@
//Latvian
jQuery.timeago.settings.strings = {
prefixAgo: "pirms",
prefixFromNow: null,
suffixAgo: null,
suffixFromNow: "no šī brīža",
seconds: "%d sek.",
minute: "min.",
minutes: "%d min.",
hour: "st.",
hours: "%d st.",
day: "1 d.",
days: "%d d.",
month: "mēnesis.",
months: "%d mēnesis.",
year: "gads",
years: "%d gads",
wordSeparator: " ",
numbers: []
};

View File

@@ -28,7 +28,7 @@
},
month: "en mesec",
months: function (value) {
return numpf(value, ["%d mescov", "%d mesec", "%d mesca", "%d mesce"]);
return numpf(value, ["%d mesecev", "%d mesec", "%d meseca", "%d mesece"]);
},
year: "eno leto",
years: function (value) {

View File

@@ -0,0 +1,49 @@
// Serbian
(function () {
var numpf;
numpf = function (n, f, s, t) {
var n10;
n10 = n % 10;
if (n10 === 1 && (n === 1 || n > 20)) {
return f;
} else if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) {
return s;
} else {
return t;
}
};
jQuery.timeago.settings.strings = {
prefixAgo: "пре",
prefixFromNow: "за",
suffixAgo: null,
suffixFromNow: null,
second: "секунд",
seconds: function (value) {
return numpf(value, "%d секунд", "%d секунде", "%d секунди");
},
minute: "један минут",
minutes: function (value) {
return numpf(value, "%d минут", "%d минута", "%d минута");
},
hour: "један сат",
hours: function (value) {
return numpf(value, "%d сат", "%d сата", "%d сати");
},
day: "један дан",
days: function (value) {
return numpf(value, "%d дан", "%d дана", "%d дана");
},
month: "месец дана",
months: function (value) {
return numpf(value, "%d месец", "%d месеца", "%d месеци");
},
year: "годину дана",
years: function (value) {
return numpf(value, "%d годину", "%d године", "%d година");
},
wordSeparator: " "
};
}).call(this);

View File

@@ -0,0 +1,20 @@
// Turkish shortened
jQuery.timeago.settings.strings = {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "",
suffixFromNow: "",
seconds: "1sn",
minute: "1d",
minutes: "%dd",
hour: "1s",
hours: "%ds",
day: "1g",
days: "%dg",
month: "1ay",
months: "%day",
year: "1y",
years: "%dy",
wordSeparator: " ",
numbers: []
};

View File

@@ -81,6 +81,27 @@ authenticationController.register = function(req, res, next) {
function registerAndLoginUser(req, res, userData, callback) {
var uid;
async.waterfall([
function(next) {
plugins.fireHook('filter:register.interstitial', {
userData: userData,
interstitials: []
}, function(err, data) {
// If interstitials are found, save registration attempt into session and abort
var deferRegistration = data.interstitials.length;
if (!deferRegistration) {
return next();
} else {
userData.register = true;
req.session.registration = userData;
if (res.locals.isAPI) {
return res.json({ referrer: nconf.get('relative_path') + '/register/complete' });
} else {
return res.redirect(nconf.get('relative_path') + '/register/complete');
}
}
});
},
function(next) {
user.create(userData, next);
},
@@ -111,6 +132,54 @@ function addToApprovalQueue(req, userData, callback) {
], callback);
}
authenticationController.registerComplete = function(req, res, next) {
// For the interstitials that respond, execute the callback with the form body
plugins.fireHook('filter:register.interstitial', {
userData: req.session.registration,
interstitials: []
}, function(err, data) {
var callbacks = data.interstitials.reduce(function(memo, cur) {
if (cur.hasOwnProperty('callback') && typeof cur.callback === 'function') {
memo.push(async.apply(cur.callback, req.session.registration, req.body));
}
return memo;
}, []);
var done = function() {
delete req.session.registration;
if (req.session.returnTo) {
res.redirect(req.session.returnTo);
} else {
res.redirect(nconf.get('relative_path') + '/');
}
}
async.parallel(callbacks, function(err) {
if (err) {
req.flash('error', err.message);
return res.redirect(nconf.get('relative_path') + '/register/complete');
}
if (req.session.registration.register === true) {
res.locals.processLogin = true;
registerAndLoginUser(req, res, req.session.registration, done);
} else {
// Clear registration data in session
done();
}
});
});
};
authenticationController.registerAbort = function(req, res, next) {
// End the session and redirect to home
req.session.destroy(function() {
res.redirect(nconf.get('relative_path') + '/');
});
};
authenticationController.login = function(req, res, next) {
// Handle returnTo data
if (req.body.hasOwnProperty('returnTo') && !req.session.returnTo) {
@@ -307,6 +376,7 @@ authenticationController.logout = function(req, res, next) {
return next(err);
}
req.logout();
req.session.destroy();
user.setUserField(uid, 'lastonline', Date.now() - 300000);

View File

@@ -12,29 +12,35 @@ var meta = require('../meta');
var helpers = {};
helpers.notAllowed = function(req, res, error) {
if (req.uid) {
if (res.locals.isAPI) {
res.status(403).json({
path: req.path.replace(/^\/api/, ''),
loggedIn: !!req.uid, error: error,
title: '[[global:403.title]]'
});
plugins.fireHook('filter:helpers.notAllowed', {
req: req,
res: res,
error: error
}, function(err, data) {
if (req.uid) {
if (res.locals.isAPI) {
res.status(403).json({
path: req.path.replace(/^\/api/, ''),
loggedIn: !!req.uid, error: error,
title: '[[global:403.title]]'
});
} else {
res.status(403).render('403', {
path: req.path,
loggedIn: !!req.uid, error: error,
title: '[[global:403.title]]'
});
}
} else {
res.status(403).render('403', {
path: req.path,
loggedIn: !!req.uid, error: error,
title: '[[global:403.title]]'
});
if (res.locals.isAPI) {
req.session.returnTo = nconf.get('relative_path') + req.url.replace(/^\/api/, '');
res.status(401).json('not-authorized');
} else {
req.session.returnTo = nconf.get('relative_path') + req.url;
res.redirect(nconf.get('relative_path') + '/login');
}
}
} else {
if (res.locals.isAPI) {
req.session.returnTo = nconf.get('relative_path') + req.url.replace(/^\/api/, '');
res.status(401).json('not-authorized');
} else {
req.session.returnTo = nconf.get('relative_path') + req.url;
res.redirect(nconf.get('relative_path') + '/login');
}
}
});
};
helpers.redirect = function(res, url) {

View File

@@ -185,6 +185,33 @@ Controllers.register = function(req, res, next) {
});
};
Controllers.registerInterstitial = function(req, res, next) {
if (!req.session.hasOwnProperty('registration')) {
return res.redirect(nconf.get('relative_path') + '/register');
}
plugins.fireHook('filter:register.interstitial', {
userData: req.session.registration,
interstitials: []
}, function(err, data) {
if (!data.interstitials.length) {
return next();
}
var renders = data.interstitials.map(function(interstitial) {
return async.apply(req.app.render.bind(req.app), interstitial.template, interstitial.data || {});
});
var errors = req.flash('error');
async.parallel(renders, function(err, sections) {
res.render('registerComplete', {
errors: errors,
sections: sections
});
});
});
};
Controllers.compose = function(req, res, next) {
plugins.fireHook('filter:composer.build', {
req: req,
@@ -383,12 +410,14 @@ Controllers.handle404 = function(req, res) {
meta.errors.log404(req.path.replace(/^\/api/, '') || '');
res.status(404);
var path = String(req.path || '');
if (res.locals.isAPI) {
return res.json({path: validator.escape(req.path.replace(/^\/api/, '') || ''), title: '[[global:404.title]]'});
return res.json({path: validator.escape(path.replace(/^\/api/, '')), title: '[[global:404.title]]'});
}
req.app.locals.middleware.buildHeader(req, res, function() {
res.render('404', {path: validator.escape(req.path || ''), title: '[[global:404.title]]'});
res.render('404', {path: validator.escape(path), title: '[[global:404.title]]'});
});
} else {
res.status(404).type('txt').send('Not found');
@@ -412,11 +441,12 @@ Controllers.handleErrors = function(err, req, res, next) {
res.status(err.status || 500);
var path = String(req.path || '');
if (res.locals.isAPI) {
res.json({path: validator.escape(req.path || ''), error: err.message});
res.json({path: validator.escape(path), error: err.message});
} else {
req.app.locals.middleware.buildHeader(req, res, function() {
res.render('500', {path: validator.escape(String(req.path || '')), error: validator.escape(err.message)});
res.render('500', {path: validator.escape(path), error: validator.escape(String(err.message))});
});
}
};

View File

@@ -168,7 +168,7 @@ module.exports = function(Groups) {
return callback(err);
}
if (parseInt(group.system, 10) === 1 || parseInt(group.hidden, 10) === 1) {
if (parseInt(group.system, 10) === 1) {
return callback();
}

View File

@@ -1,38 +0,0 @@
var path = require('path');
var sockets = require('path');
var websockets = require('../socket.io/');
var continuationLocalStorage = require('continuation-local-storage');
var APP_NAMESPACE = require(path.join(__dirname, '../../package.json')).name;
var namespace = continuationLocalStorage.createNamespace(APP_NAMESPACE);
(function(cls) {
cls.http = function (req, res, next) {
namespace.run(function() {
namespace.set('request', req);
next && next();
});
};
cls.socket = function (socket, payload, event, next) {
namespace.run(function() {
namespace.set('request', websockets.reqFromSocket(socket, payload, event));
next && next();
});
};
cls.get = function (key) {
return namespace.get(key);
};
cls.set = function (key, value) {
return namespace.set(key, value);
};
cls.setItem = cls.set;
cls.getItem = cls.get;
cls.namespace = namespace;
cls.continuationLocalStorage = continuationLocalStorage;
})(exports);

View File

@@ -14,7 +14,6 @@ var meta = require('../meta'),
compression = require('compression'),
favicon = require('serve-favicon'),
session = require('express-session'),
cls = require('./cls'),
useragent = require('express-useragent');
@@ -62,7 +61,7 @@ module.exports = function(app) {
if (nconf.get('secure')) {
cookie.secure = true;
}
if (relativePath !== '') {
cookie.path = relativePath;
}
@@ -78,7 +77,6 @@ module.exports = function(app) {
app.use(middleware.addHeaders);
app.use(middleware.processRender);
app.use(cls.http);
auth.initialize(app, middleware);
return middleware;

View File

@@ -350,6 +350,19 @@ middleware.processTimeagoLocales = function(req, res, next) {
}
};
middleware.registrationComplete = function(req, res, next) {
// If the user's session contains registration data, redirect the user to complete registration
if (!req.session.hasOwnProperty('registration')) {
return next();
} else {
if (!req.path.endsWith('/register/complete')) {
controllers.helpers.redirect(res, '/register/complete');
} else {
return next();
}
}
};
module.exports = function(webserver) {
app = webserver;
middleware.admin = require('./admin')(webserver);

View File

@@ -7,29 +7,6 @@ module.exports = function(Plugins) {
Plugins.deprecatedHooks = {
'filter:user.custom_fields': null // remove in v1.1.0
};
Plugins.deprecatedHooksParams = {
'action:homepage.get': '{req, res}',
'filter:register.check': '{req, res}',
'action:user.loggedOut': '{req, res}',
'static:user.loggedOut': '{req, res}',
'filter:categories.build': '{req, res}',
'filter:category.build': '{req, res}',
'filter:group.build': '{req, res}',
'filter:register.build': '{req, res}',
'filter:composer.build': '{req, res}',
'filter:popular.build': '{req, res}',
'filter:recent.build': '{req, res}',
'filter:topic.build': '{req, res}',
'filter:users.build': '{req, res}',
'filter:admin.category.get': '{req, res}',
'filter:middleware.renderHeader': '{req, res}',
'filter:widget.render': '{req, res}',
'filter:middleware.buildHeader': '{req, locals}',
'action:middleware.pageView': '{req}',
'action:meta.override404': '{req}'
};
/*
`data` is an object consisting of (* is required):
`data.hook`*, the name of the NodeBB hook
@@ -62,12 +39,6 @@ module.exports = function(Plugins) {
parts.pop();
}
var hook = parts.join(':');
if (Plugins.deprecatedHooksParams[hook]) {
winston.warn('[plugins/' + id + '] Hook `' + hook + '` parameters: `' + Plugins.deprecatedHooksParams[hook] + '`, are being deprecated, '
+ 'all plugins should now use the `middleware/cls` module instead of hook\'s arguments to get a reference to the `http-request` or the `socket-request` object(s) (from which you can get the current `uid` if you need to.) '
+ '- for more info, visit https://docs.nodebb.org/en/latest/plugins/create.html#getting-a-reference-to-each-request-from-within-any-plugin-hook\n');
delete Plugins.deprecatedHooksParams[hook];
}
}
if (data.hook && data.method) {

View File

@@ -64,6 +64,8 @@
});
router.post('/register', Auth.middleware.applyCSRF, Auth.middleware.applyBlacklist, controllers.authentication.register);
router.post('/register/complete', Auth.middleware.applyCSRF, Auth.middleware.applyBlacklist, controllers.authentication.registerComplete);
router.get('/register/abort', controllers.authentication.registerAbort);
router.post('/login', Auth.middleware.applyCSRF, Auth.middleware.applyBlacklist, controllers.authentication.login);
router.post('/logout', Auth.middleware.applyCSRF, controllers.authentication.logout);

View File

@@ -3,7 +3,7 @@
var helpers = {};
helpers.setupPageRoute = function(router, name, middleware, middlewares, controller) {
middlewares = middlewares.concat([middleware.pageView, middleware.pluginHooks]);
middlewares = middlewares.concat([middleware.registrationComplete, middleware.pageView, middleware.pluginHooks]);
router.get(name, middleware.busyCheck, middleware.buildHeader, middlewares, controller);
router.get('/api' + name, middlewares, controller);

View File

@@ -6,6 +6,7 @@ var async = require('async');
var winston = require('winston');
var controllers = require('../controllers');
var plugins = require('../plugins');
var user = require('../user');
var express = require('express');
var validator = require('validator');
@@ -28,6 +29,7 @@ function mainRoutes(app, middleware, controllers) {
setupPageRoute(app, '/login', middleware, loginRegisterMiddleware, controllers.login);
setupPageRoute(app, '/register', middleware, loginRegisterMiddleware, controllers.register);
setupPageRoute(app, '/register/complete', middleware, [], controllers.registerInterstitial);
setupPageRoute(app, '/compose', middleware, [], controllers.compose);
setupPageRoute(app, '/confirm/:code', middleware, [], controllers.confirmEmail);
setupPageRoute(app, '/outgoing', middleware, [], controllers.outgoing);
@@ -155,6 +157,7 @@ module.exports = function(app, middleware, hotswapIds) {
// Add plugin routes
async.series([
async.apply(plugins.reloadRoutes),
async.apply(authRoutes.reloadRoutes)
async.apply(authRoutes.reloadRoutes),
async.apply(user.addInterstitials)
]);
};

View File

@@ -5,8 +5,10 @@ var groups = require('../../groups'),
Groups = {};
Groups.create = function(socket, data, callback) {
if(!data) {
if (!data) {
return callback(new Error('[[error:invalid-data]]'));
} else if (groups.isPrivilegeGroup(data.name)) {
return callback(new Error('[[error:invalid-group-name]]'));
}
groups.create({

View File

@@ -170,6 +170,8 @@ SocketGroups.create = function(socket, data, callback) {
return callback(new Error('[[error:no-privileges]]'));
} else if (parseInt(meta.config.allowGroupCreation, 10) !== 1) {
return callback(new Error('[[error:group-creation-disabled]]'));
} else if (groups.isPrivilegeGroup(data.name)) {
return callback(new Error('[[error:invalid-group-name]]'));
}

View File

@@ -11,7 +11,6 @@ var url = require('url');
var db = require('../database');
var logger = require('../logger');
var ratelimit = require('../middleware/ratelimit');
var cls = require('../middleware/cls');
(function(Sockets) {
var Namespaces = {};
@@ -30,7 +29,6 @@ var cls = require('../middleware/cls');
io.use(authorize);
io.on('connection', onConnection);
io.on('disconnect', onDisconnect);
io.listen(server, {
transports: nconf.get('socket.io:transports')
@@ -44,14 +42,10 @@ var cls = require('../middleware/cls');
logger.io_one(socket, socket.uid);
cls.socket(socket, null, 'connection', function () {
onConnect(socket);
});
onConnect(socket);
socket.on('*', function (payload) {
cls.socket(socket, payload, null, function () {
onMessage(socket, payload);
});
onMessage(socket, payload);
});
}
@@ -64,12 +58,6 @@ var cls = require('../middleware/cls');
}
}
function onDisconnect(socket) {
cls.socket(socket, null, 'disconnect', function () {
});
}
function onMessage(socket, payload) {
if (!payload.data.length) {
return winston.warn('[socket.io] Empty payload');
@@ -235,4 +223,4 @@ var cls = require('../middleware/cls');
};
};
})(exports);
})(exports);

View File

@@ -255,7 +255,7 @@ module.exports = function(Topics) {
async.parallel({
markRead: async.apply(db.sortedSetAdd, 'uid:' + uid + ':tids_read', scores, tids),
markUnread: async.apply(db.sortedSetRemove, 'uid:' + uid + ':tids_unread', tids),
topicData: async.apply( Topics.getTopicsFields, tids, ['cid'])
topicData: async.apply(Topics.getTopicsFields, tids, ['cid'])
}, next);
},
function (results, next) {

View File

@@ -6,6 +6,7 @@ var plugins = require('./plugins');
var db = require('./database');
var topics = require('./topics');
var privileges = require('./privileges');
var meta = require('./meta');
var utils = require('../public/src/utils');
(function(User) {
@@ -255,5 +256,32 @@ var utils = require('../public/src/utils');
});
};
User.addInterstitials = function(callback) {
plugins.registerHook('core', {
hook: 'filter:register.interstitial',
method: function(data, callback) {
if (meta.config.termsOfUse && !data.userData.acceptTos) {
data.interstitials.push({
template: 'partials/acceptTos',
data: {
termsOfUse: meta.config.termsOfUse
},
callback: function(userData, formData, next) {
if (formData['agree-terms'] === 'on') {
userData.acceptTos = true;
}
next(userData.acceptTos ? null : new Error('[[register:terms_of_use_error]]'));
}
});
}
callback(null, data);
}
});
callback();
};
}(exports));

View File

@@ -8,11 +8,9 @@ var plugins = require('../plugins');
var groups = require('../groups');
var meta = require('../meta');
module.exports = function(User) {
User.create = function(data, callback) {
data.username = data.username.trim();
data.userslug = utils.slugify(data.username);
if (data.email !== undefined) {

View File

@@ -136,13 +136,21 @@ widgets.reset = function(callback) {
{ name: 'Draft Zone', template: 'global', location: 'sidebar' }
];
plugins.fireHook('filter:widgets.getAreas', defaultAreas, function(err, areas) {
async.parallel({
areas: function(next) {
plugins.fireHook('filter:widgets.getAreas', defaultAreas, next);
},
drafts: function(next) {
widgets.getArea('global', 'drafts', next);
}
}, function(err, results) {
if (err) {
return callback(err);
}
var drafts = [];
async.each(areas, function(area, next) {
var drafts = results.drafts || [];
async.each(results.areas, function(area, next) {
widgets.getArea(area.template, area.location, function(err, areaData) {
if (err) {
return next(err);