diff --git a/install/package.json b/install/package.json index 2b6221eafd..316b6a965f 100644 --- a/install/package.json +++ b/install/package.json @@ -90,11 +90,11 @@ "nodebb-plugin-spam-be-gone": "0.6.1", "nodebb-rewards-essentials": "0.0.13", "nodebb-theme-lavender": "5.0.9", - "nodebb-theme-persona": "9.1.27", + "nodebb-theme-persona": "9.1.28", "nodebb-theme-slick": "1.2.23", "nodebb-theme-vanilla": "10.1.25", "nodebb-widget-essentials": "4.0.14", - "nodemailer": "^5.0.0", + "nodemailer": "^6.0.0", "passport": "^0.4.0", "passport-local": "1.0.0", "pg": "^7.4.0", @@ -135,10 +135,10 @@ "@commitlint/cli": "7.5.2", "@commitlint/config-angular": "7.5.0", "coveralls": "3.0.3", - "eslint": "5.15.1", + "eslint": "5.15.3", "eslint-config-airbnb-base": "13.1.0", "eslint-plugin-import": "2.16.0", - "grunt": "1.0.3", + "grunt": "1.0.4", "grunt-contrib-watch": "1.1.0", "husky": "1.3.1", "jsdom": "14.0.0", @@ -171,4 +171,4 @@ "url": "https://github.com/barisusakli" } ] -} \ No newline at end of file +} diff --git a/public/language/ar/notifications.json b/public/language/ar/notifications.json index 17faabfd36..982367c5c2 100644 --- a/public/language/ar/notifications.json +++ b/public/language/ar/notifications.json @@ -5,20 +5,20 @@ "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": "You have a new notification", + "new_notification": "لديك تنبيه جديد", "you_have_unread_notifications": "لديك تنبيهات غير مقروءة.", - "all": "All", - "topics": "Topics", - "replies": "Replies", - "chat": "Chats", - "follows": "Follows", - "upvote": "Upvotes", + "all": "الكل", + "topics": "مواضيع", + "replies": "ردود", + "chat": "محادثات", + "follows": "متابعون", + "upvote": "الموافقين", "new-flags": "New Flags", "my-flags": "Flags assigned to me", - "bans": "Bans", + "bans": "الحظر", "new_message_from": "رسالة جديدة من %1", "upvoted_your_post_in": "%1 أضاف صوتًا إيجابيا إلى مشاركتك في %2.", "upvoted_your_post_in_dual": "%1 and %2 have upvoted your post in %3.", @@ -47,10 +47,10 @@ "email-confirm-error-message": "حدث خطأ أثناء التحقق من عنوان بريدك الإلكتروني. ربما رمز التفعيل خاطئ أو انتهت صلاحيته.", "email-confirm-sent": "تم إرسال بريد التفعيل.", "none": "None", - "notification_only": "Notification Only", - "email_only": "Email Only", - "notification_and_email": "Notification & Email", - "notificationType_upvote": "When someone upvotes your post", + "notification_only": "التنبيهات فقط", + "email_only": "البريد الالكتروني فقط", + "notification_and_email": "التنبيهات والبريد اﻻلكتروني", + "notificationType_upvote": "عندما يوافقك احدهم على منشورك", "notificationType_new-topic": "When someone you follow posts a topic", "notificationType_new-reply": "When a new reply is posted in a topic you are watching", "notificationType_follow": "When someone starts following you", diff --git a/public/language/en-GB/admin/manage/users.json b/public/language/en-GB/admin/manage/users.json index 6a17cbf016..05fc3f043f 100644 --- a/public/language/en-GB/admin/manage/users.json +++ b/public/language/en-GB/admin/manage/users.json @@ -6,6 +6,7 @@ "validate-email": "Validate Email", "send-validation-email": "Send Validation Email", "password-reset-email": "Send Password Reset Email", + "force-password-reset": "Force Password Reset & Log User Out", "ban": "Ban User(s)", "temp-ban": "Ban User(s) Temporarily", "unban": "Unban User(s)", @@ -81,7 +82,9 @@ "alerts.confirm-remove-moderator": "Do you really want to remove this moderator?", "alerts.remove-moderator-success": "User is no longer moderator.", "alerts.confirm-validate-email": "Do you want to validate email(s) of these user(s)?", + "alerts.confirm-force-password-reset": "Are you sure you want to force the password reset and log out these user(s)?", "alerts.validate-email-success": "Emails validated", + "alerts.validate-force-password-reset-success": "User(s) passwords have been reset and their existing sessions have been revoked.", "alerts.password-reset-confirm": "Do you want to send password reset email(s) to these user(s)?", "alerts.confirm-delete": "Warning!
Do you really want to delete user(s)?
This action is not reversable! Only the user account will be deleted, their posts and topics will remain.", "alerts.delete-success": "User(s) Deleted!", diff --git a/public/language/ja/admin/manage/privileges.json b/public/language/ja/admin/manage/privileges.json index 5e6d451b67..0db45acc4b 100644 --- a/public/language/ja/admin/manage/privileges.json +++ b/public/language/ja/admin/manage/privileges.json @@ -1,26 +1,26 @@ { - "global": "Global", - "global.no-users": "No user-specific global privileges.", + "global": "グローバル", + "global.no-users": "ユーザー固有のグローバル特権はありません。", - "chat": "Chat", - "upload-images": "Upload Images", - "upload-files": "Upload Files", - "signature": "Signature", + "chat": "チャット", + "upload-images": "画像をアップロード", + "upload-files": "ファイルをアップロード", + "signature": "署名", "ban": "Ban", - "search-content": "Search Content", - "search-users": "Search Users", - "search-tags": "Search Tags", - "view-users": "View Users", - "view-tags": "View Tags", - "view-groups": "View Groups", - "allow-local-login": "Local Login", - "allow-group-creation": "Group Create", + "search-content": "コンテンツを検索", + "search-users": "ユーザー検索", + "search-tags": "タグ検索", + "view-users": "ユーザーを表示", + "view-tags": "タグを表示", + "view-groups": "グループを表示", + "allow-local-login": "ローカルログイン", + "allow-group-creation": "グループを作成", - "find-category": "Find Category", - "access-category": "Access Category", - "access-topics": "Access Topics", - "create-topics": "Create Topics", - "reply-to-topics": "Reply to Topics", + "find-category": "カテゴリを検索", + "access-category": "カテゴリにアクセス", + "access-topics": "トピックスにアクセス", + "create-topics": "トピックスを作成", + "reply-to-topics": "トピックスに返信", "tag-topics": "Tag Topics", "edit-posts": "Edit Posts", "view-edit-history": "View Edit History", diff --git a/public/src/admin/manage/users.js b/public/src/admin/manage/users.js index 9efb1807be..73e33b391b 100644 --- a/public/src/admin/manage/users.js +++ b/public/src/admin/manage/users.js @@ -175,6 +175,19 @@ define('admin/manage/users', ['translator', 'benchpress'], function (translator, }); }); + $('.force-password-reset').on('click', function () { + var uids = getSelectedUids(); + if (!uids.length) { + return; + } + + bootbox.confirm('[[admin/manage/users:alerts.confirm-force-password-reset]]', function (confirm) { + if (confirm) { + socket.emit('admin.user.forcePasswordReset', uids, done('[[admin/manage/users:alerts.validate-force-password-reset-success]]')); + } + }); + }); + $('.delete-user').on('click', function () { var uids = getSelectedUids(); if (!uids.length) { diff --git a/public/src/admin/modules/colorpicker.js b/public/src/admin/modules/colorpicker.js index c219df634f..6000c416d6 100644 --- a/public/src/admin/modules/colorpicker.js +++ b/public/src/admin/modules/colorpicker.js @@ -20,6 +20,10 @@ define('admin/modules/colorpicker', function () { $(colpkr).css('z-index', 1051); }, }); + + $(window).one('action:ajaxify.start', function () { + $this.ColorPickerHide(); + }); }); }; diff --git a/public/src/admin/settings/email.js b/public/src/admin/settings/email.js index 336abf34fa..3e3fdc1280 100644 --- a/public/src/admin/settings/email.js +++ b/public/src/admin/settings/email.js @@ -87,18 +87,20 @@ define('admin/settings/email', ['ace/ace', 'admin/settings'], function (ace) { return app.alertError(err.message); } - now = new Date(now); + var date = new Date(now.timestamp); + var offset = (new Date().getTimezoneOffset() - now.offset) / 60; + date.setHours(date.getHours() + offset); - $('#serverTime').text(now.toString()); + $('#serverTime').text(date.toLocaleTimeString()); - now.setHours(parseInt(hour, 10), 0, 0, 0); + date.setHours(parseInt(hour, 10) - offset, 0, 0, 0); // If adjusted time is in the past, move to next day - if (now.getTime() < Date.now()) { - now.setDate(now.getDate() + 1); + if (date.getTime() < Date.now()) { + date.setDate(date.getDate() + 1); } - $('#nextDigestTime').text(now.toString()); + $('#nextDigestTime').text(date.toLocaleString()); }); } diff --git a/public/src/app.js b/public/src/app.js index 7bf56166b6..f2b6c25ba0 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -134,9 +134,9 @@ app.cacheBuster = null; // Re-render top bar menu var toRender = { + 'slideout-menu': $('.slideout-menu'), menu: $('#header-menu .container'), 'chats-menu': $('#chats-menu'), - 'slideout-menu': $('.slideout-menu'), }; Promise.all(Object.keys(toRender).map(function (tpl) { return Benchpress.render('partials/' + tpl, data.header).then(function (render) { @@ -157,6 +157,8 @@ app.cacheBuster = null; app.handleSearch(); } + handleStatusChange(); + $(window).trigger('action:app.updateHeader'); }); }); diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index 56f7f12287..eda407de46 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -273,13 +273,20 @@ function continueLogin(req, res, next) { if (passwordExpiry && passwordExpiry < Date.now()) { winston.verbose('[auth] Triggering password reset for uid ' + userData.uid + ' due to password policy'); req.session.passwordExpired = true; - user.reset.generate(userData.uid, function (err, code) { + + async.series({ + code: async.apply(user.reset.generate, userData.uid), + buildHeader: async.apply(middleware.buildHeader, req, res), + header: async.apply(middleware.generateHeader, req, res, {}), + }, function (err, payload) { if (err) { return helpers.noScriptErrors(req, res, err.message, 403); } res.status(200).send({ - next: nconf.get('relative_path') + '/reset/' + code, + next: nconf.get('relative_path') + '/reset/' + payload.code, + header: payload.header, + config: res.locals.config, }); }); } else { diff --git a/src/controllers/index.js b/src/controllers/index.js index 494b0e9f02..f4d082067a 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -62,10 +62,10 @@ Controllers.reset = function (req, res, next) { }; if (req.params.code) { - // Save to session and redirect req.session.reset_code = req.params.code; - res.redirect(nconf.get('relative_path') + '/reset'); - } else if (req.session.reset_code) { + } + + if (req.session.reset_code) { // Validate and save to local variable before removing from session user.reset.validate(req.session.reset_code, function (err, valid) { if (err) { diff --git a/src/prestart.js b/src/prestart.js index cb077d1546..49f6336499 100644 --- a/src/prestart.js +++ b/src/prestart.js @@ -69,6 +69,7 @@ function loadConfig(configFile) { nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-persona/templates')); nconf.set('upload_path', path.resolve(nconf.get('base_dir'), nconf.get('upload_path'))); + nconf.set('upload_url', '/assets/uploads'); if (nconf.get('url')) { nconf.set('url_parsed', url.parse(nconf.get('url'))); diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index efd193ede0..02ade56a89 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -126,6 +126,25 @@ User.sendPasswordResetEmail = function (socket, uids, callback) { }, callback); }; +User.forcePasswordReset = function (socket, uids, callback) { + if (!Array.isArray(uids)) { + return callback(new Error('[[error:invalid-data]]')); + } + + uids = uids.filter(uid => parseInt(uid, 10)); + + async.each(uids, function (uid, next) { + async.waterfall([ + function (next) { + user.setUserField(uid, 'passwordExpiry', Date.now(), next); + }, + function (next) { + user.auth.revokeAllSessions(uid, next); + }, + ], next); + }, callback); +}; + User.deleteUsers = function (socket, uids, callback) { deleteUsers(socket, uids, function (uid, next) { user.deleteAccount(uid, next); diff --git a/src/socket.io/meta.js b/src/socket.io/meta.js index 398bf249f5..e9cd3f00e4 100644 --- a/src/socket.io/meta.js +++ b/src/socket.io/meta.js @@ -62,7 +62,12 @@ function leaveCurrentRoom(socket) { SocketMeta.getServerTime = function (socket, data, callback) { // Returns server time in milliseconds - callback(null, Date.now()); + const now = new Date(); + + callback(null, { + timestamp: now.getTime(), + offset: now.getTimezoneOffset(), + }); }; module.exports = SocketMeta; diff --git a/src/start.js b/src/start.js index 53893d44b8..b2b4ceebc9 100644 --- a/src/start.js +++ b/src/start.js @@ -99,7 +99,6 @@ function setupConfigs() { nconf.set('use_port', !!urlObject.port); nconf.set('relative_path', relativePath); nconf.set('port', nconf.get('PORT') || nconf.get('port') || urlObject.port || (nconf.get('PORT_ENV_VAR') ? nconf.get(nconf.get('PORT_ENV_VAR')) : false) || 4567); - nconf.set('upload_url', '/assets/uploads'); } function printStartupInfo() { diff --git a/src/views/admin/extend/plugins.tpl b/src/views/admin/extend/plugins.tpl index cbf44febf8..795c404656 100644 --- a/src/views/admin/extend/plugins.tpl +++ b/src/views/admin/extend/plugins.tpl @@ -20,7 +20,32 @@
-
+
+
+
[[admin/extend/plugins:plugin-search]]
+
+
+
+
+ +
+
[[admin/extend/plugins:reorder-plugins]]
+
+ +
+
+ +
+
[[admin/extend/plugins:dev-interested]]
+
+

+ [[admin/extend/plugins:docs-info]] +

+
+
+
+ +
    @@ -48,32 +73,6 @@
-
-
-
[[admin/extend/plugins:plugin-search]]
-
-
-
-
- -
-
[[admin/extend/plugins:reorder-plugins]]
-
- -
-
- -
-
[[admin/extend/plugins:dev-interested]]
-
-

- [[admin/extend/plugins:docs-info]] -

-
-
-
- -