diff --git a/config/env/torrents.js b/config/env/torrents.js index d8d9dbe3..bf386ec7 100644 --- a/config/env/torrents.js +++ b/config/env/torrents.js @@ -165,6 +165,19 @@ module.exports = { showDemoSignMessage: true }, + /** + * @password + * + * password setting + * + * @resetTokenExpires: reset password token expires time, default 1 hour + * @resetTimeInterval: reset password time interval, default 24 hours, means only can do once in 24 hours. + */ + password: { + resetTokenExpires: 60 * 60 * 1000 * 1, + resetTimeInterval: 60 * 60 * 1000 * 24 + }, + /** * @invite * diff --git a/modules/core/client/app/trans-string-en.js b/modules/core/client/app/trans-string-en.js index 55a68694..5a076934 100644 --- a/modules/core/client/app/trans-string-en.js +++ b/modules/core/client/app/trans-string-en.js @@ -1034,6 +1034,16 @@ } }, + //status pages + STATUS_PAGE: { + BAD_REQUEST: 'Bad Request', + FORBIDDEN: 'Forbidden', + MADE_BAD_REQUEST: 'You made a bad request', + NOT_AUTHORIZED_THIS: 'You are not authorized to access this resource', + NOT_FOUND: 'Not Found', + PAGE_NOT_FOUND: 'Page Or Resources Not Found' + }, + /////////////////////////resources tag fields/////////////////////////////////// RESOURCESTAGS: { TYPE: { @@ -1198,7 +1208,8 @@ SENDING_RESET_MAIL_SUCCESSFULLY: 'An email has been sent to the provided email with further instructions. please check it then reset your password', SENDING_RESET_MAIL_FAILED: 'The password reset mail send failed', PASSWORDS_DO_NOT_MATCH: 'twice passwords do not match', - RESET_TOKEN_INVALID: 'Password reset token is invalid or has expired.' + RESET_TOKEN_INVALID: 'Password reset token is invalid or has expired.', + RESET_PASSWORD_TO_FREQUENT: 'Reset password operation is too frequent, you can do once only in {{hours}} hours, next time is: {{nextTime}}' } }; diff --git a/modules/core/client/app/trans-string-zh.js b/modules/core/client/app/trans-string-zh.js index c08ac162..93f4d62f 100644 --- a/modules/core/client/app/trans-string-zh.js +++ b/modules/core/client/app/trans-string-zh.js @@ -1034,6 +1034,16 @@ } }, + //status pages + STATUS_PAGE: { + BAD_REQUEST: '请求错误', + FORBIDDEN: '请求禁止', + MADE_BAD_REQUEST: '您发起了一个无效的请求', + NOT_AUTHORIZED_THIS: '您无权访问此资源', + NOT_FOUND: '无法访问', + PAGE_NOT_FOUND: '没有找到页面或资源' + }, + /////////////////////////resources tag fields/////////////////////////////////// RESOURCESTAGS: { TYPE: { @@ -1198,7 +1208,8 @@ SENDING_RESET_MAIL_SUCCESSFULLY: '系统已向您帐户的注册邮箱发送了一封验证邮件, 请检查邮件并跟据邮件提示进一步重置您的帐户密码', SENDING_RESET_MAIL_FAILED: '密码重置邮件发送失败', PASSWORDS_DO_NOT_MATCH: '两次密码不匹配', - RESET_TOKEN_INVALID: '密码重置请求无效或已过期' + RESET_TOKEN_INVALID: '密码重置请求无效或已过期', + RESET_PASSWORD_TO_FREQUENT: '密码重置操作过于频繁, 您在 {{hours}} 小时内只能操作一次, 下次可操作时间为: {{nextTime}}' } }; diff --git a/modules/core/client/config/core.client.routes.js b/modules/core/client/config/core.client.routes.js index c471c8fd..59e7b219 100644 --- a/modules/core/client/config/core.client.routes.js +++ b/modules/core/client/config/core.client.routes.js @@ -44,6 +44,9 @@ params: { message: function ($stateParams) { return $stateParams.message; + }, + params: function ($stateParams) { + return $stateParams.params; } }, data: { @@ -58,6 +61,9 @@ params: { message: function ($stateParams) { return $stateParams.message; + }, + params: function ($stateParams) { + return $stateParams.params; } }, data: { diff --git a/modules/core/client/controllers/error.client.controller.js b/modules/core/client/controllers/error.client.controller.js index 5968f343..978aec48 100644 --- a/modules/core/client/controllers/error.client.controller.js +++ b/modules/core/client/controllers/error.client.controller.js @@ -10,9 +10,11 @@ function ErrorController($stateParams) { var vm = this; vm.errorMessage = null; + vm.errorParams = null; // Display custom message if it was set if ($stateParams.message) vm.errorMessage = $stateParams.message; + if ($stateParams.params) vm.errorParams = $stateParams.params; } }()); diff --git a/modules/core/client/services/interceptors/auth-interceptor.client.service.js b/modules/core/client/services/interceptors/auth-interceptor.client.service.js index 89bae6f0..da1373cf 100644 --- a/modules/core/client/services/interceptors/auth-interceptor.client.service.js +++ b/modules/core/client/services/interceptors/auth-interceptor.client.service.js @@ -5,9 +5,9 @@ .module('core') .factory('authInterceptor', authInterceptor); - authInterceptor.$inject = ['$q', '$injector', 'Authentication']; + authInterceptor.$inject = ['$q', '$injector', 'Authentication', '$translate']; - function authInterceptor($q, $injector, Authentication) { + function authInterceptor($q, $injector, Authentication, $translate) { var service = { responseError: responseError }; @@ -18,7 +18,7 @@ if (!rejection.config.ignoreAuthModule) { switch (rejection.status) { case 400: - $injector.get('$state').go('bad-request', { message: rejection.data.message }); + $injector.get('$state').go('bad-request', {message: rejection.data.message, params: rejection.data.params}); break; case 401: // Deauthenticate the global user @@ -29,11 +29,15 @@ $injector.get('$state').transitionTo('forbidden'); break; case 404: - $injector.get('$state').go('not-found', { message: rejection.data.message }); + $injector.get('$state').go('not-found', {message: rejection.data.message, params: rejection.data.params}); break; case -1: // Handle error if no response from server(Network Lost or Server not responding) var Notification = $injector.get('Notification'); - Notification.error({ message: 'No response received from server. Please try again later.', title: 'Error processing request!', delay: 5000 }); + Notification.error({ + message: 'No response received from server. Please try again later.', + title: 'Error processing request!', + delay: 5000 + }); break; } } diff --git a/modules/users/client/controllers/password.client.controller.js b/modules/users/client/controllers/password.client.controller.js index 0697ea30..c52872e0 100644 --- a/modules/users/client/controllers/password.client.controller.js +++ b/modules/users/client/controllers/password.client.controller.js @@ -5,9 +5,9 @@ .module('users') .controller('PasswordController', PasswordController); - PasswordController.$inject = ['$scope', '$stateParams', 'UsersService', '$location', 'Authentication', 'PasswordValidator', 'NotifycationService']; + PasswordController.$inject = ['$scope', '$stateParams', 'UsersService', '$location', 'Authentication', 'PasswordValidator', 'NotifycationService', '$translate']; - function PasswordController($scope, $stateParams, UsersService, $location, Authentication, PasswordValidator, NotifycationService) { + function PasswordController($scope, $stateParams, UsersService, $location, Authentication, PasswordValidator, NotifycationService, $translate) { var vm = this; vm.resetUserPassword = resetUserPassword; @@ -64,6 +64,10 @@ // Show user error message and clear form vm.credentials = null; vm.isSendingMail = false; + + if (response.data.params) { + response.data.message = $translate.instant(response.data.message, response.data.params); + } NotifycationService.showErrorNotify(response.data.message, 'SIGN.REST_MAIL_SEND_FAILED'); } diff --git a/modules/users/server/controllers/users/users.password.server.controller.js b/modules/users/server/controllers/users/users.password.server.controller.js index d19c5d51..8bcef9ff 100644 --- a/modules/users/server/controllers/users/users.password.server.controller.js +++ b/modules/users/server/controllers/users/users.password.server.controller.js @@ -12,10 +12,12 @@ var path = require('path'), nodemailer = require('nodemailer'), async = require('async'), crypto = require('crypto'), + moment = require('moment'), traceLogCreate = require(path.resolve('./config/lib/tracelog')).create; var smtpTransport = nodemailer.createTransport(config.mailer.options); var traceConfig = config.meanTorrentConfig.trace; +var passwordConfig = config.meanTorrentConfig.password; /** * Forgot for reset password (forgot POST) @@ -49,9 +51,18 @@ exports.forgot = function (req, res, next) { return res.status(400).send({ message: 'It seems like you signed up using your ' + user.provider + ' account, please sign in using that provider.' }); + } else if (user.nextResetPasswordTime > Date.now()) { + return res.status(400).send({ + message: 'SERVER.RESET_PASSWORD_TO_FREQUENT', + params: { + hours: passwordConfig.resetTimeInterval / (60 * 60 * 1000), + nextTime: moment(user.nextResetPasswordTime).format('YYYY-MM-DD HH:mm:ss') + } + }); } else { user.resetPasswordToken = token; - user.resetPasswordExpires = Date.now() + 3600000; // 1 hour + user.resetPasswordExpires = Date.now() + passwordConfig.resetTokenExpires; + user.nextResetPasswordTime = Date.now() + passwordConfig.resetTimeInterval; user.save(function (err) { done(err, token, user); diff --git a/modules/users/server/models/user.server.model.js b/modules/users/server/models/user.server.model.js index 2d2a8976..b21e822d 100644 --- a/modules/users/server/models/user.server.model.js +++ b/modules/users/server/models/user.server.model.js @@ -233,6 +233,9 @@ var UserSchema = new Schema({ }, resetPasswordExpires: { type: Date + }, + nextResetPasswordTime: { + type: Date } });