diff --git a/config/env/torrents.js b/config/env/torrents.js
index 10344861..84c44640 100644
--- a/config/env/torrents.js
+++ b/config/env/torrents.js
@@ -397,13 +397,19 @@ module.exports = {
* if exceed the expiration time, the invite send qualifications will invalid and user also can not signin(register).
* @expires_str: string desc of @expires
* @banUserInviter: settings whether ban the user`s inviter when a user banned
+ *
+ * @official: settings of official invitations
+ * @presentDays: settings of present official available days list
*/
invite: {
openInvite: true,
scoreExchange: 10000,
expires: 60 * 60 * 1000 * 24,
expires_str: '24h',
- banUserInviter: true
+ banUserInviter: true,
+ official: {
+ presentDays: [1, 10, 30, 90, 180]
+ }
},
/**
@@ -699,6 +705,7 @@ module.exports = {
OperDeleteBackupFiles: {name: 'OperDeleteBackupFiles', enable: true},
userInvitationExchange: {name: 'userInvitationExchange', enable: true},
+ adminPresentInvitations: {name: 'adminPresentInvitations', enable: true},
adminRemoveHnrWarning: {name: 'adminRemoveHnrWarning', enable: true},
userRemoveHnrWarning: {name: 'userRemoveHnrWarning', enable: true},
userSendInvitation: {name: 'userSendInvitation', enable: true},
@@ -1329,7 +1336,8 @@ module.exports = {
* @collectionsListPerPage: movie collections list page settings
* @backupFilesListPerPage: system backup files list page settings
* @torrentPeersListPerPage: torrent detail seeder & leecher users list page settings
- * @invitationsListPerPage: official invitations list page settings
+ * @officialInvitationsListPerPage: official invitations list page settings
+ * @userInvitationsListPerPage: users invitations list page settings
*
* @uploaderUserListPerPage: admin management uploader access list page settings
* @messageBoxListPerPage: message box list page settings
@@ -1364,7 +1372,8 @@ module.exports = {
collectionsListPerPage: 9,
backupFilesListPerPage: 20,
torrentPeersListPerPage: 20,
- invitationsListPerPage: 20,
+ officialInvitationsListPerPage: 20,
+ userInvitationsListPerPage: 10,
uploaderUserListPerPage: 20,
messageBoxListPerPage: 10,
diff --git a/modules/core/client/app/trans-string-en.js b/modules/core/client/app/trans-string-en.js
index 1ffebc95..99f8e51a 100644
--- a/modules/core/client/app/trans-string-en.js
+++ b/modules/core/client/app/trans-string-en.js
@@ -635,6 +635,14 @@
SET_DOWNLOADED_SUCCESSFULLY: 'Add user downloaded successfully',
SET_DOWNLOADED_FAILED: 'Add user downloaded failed',
+ PRESENT_INVITATIONS_TITLE: 'Present invitations',
+ PRESENT_INVITATIONS_NUMBERS: 'Invitation numbers:',
+ PRESENT_INVITATIONS_DAYS: 'Available days:',
+ BTN_PRESENT: 'Present',
+ BTN_PRESENT_INVITATIONS: 'Present invitations',
+ PRESENT_INVITATIONS_SUCCESSFULLY: 'Present invitations successfully',
+ PRESENT_INVITATIONS_FAILED: 'Present invitations failed',
+
ANNOUNCE_EDIT_TIP: 'Upload a torrent file, automatic replacement Announce URL & Comment',
ANNOUNCE_COMMENT: 'Announce Comment',
@@ -1065,12 +1073,16 @@
TITLE_OPERATION: 'Operation',
TITLE_SENDER: 'Sender',
TITLE_TOKEN: 'Token',
+ TITLE_TYPE: 'Type',
TITLE_EMAIL: 'Email',
TITLE_SEND: 'Send an invitation',
TITLE_STATUS: 'Status',
TITLE_STATUS_REGED: 'signed',
TITLE_STATUS_UNREGED: 'unsigned',
- TITLE_STATUS_EXPIRED: 'expired'
+ TITLE_STATUS_EXPIRED: 'expired',
+ TYPE_EXCHANGE: 'exchange',
+ TYPE_PRESENT: 'present',
+ TYPE_OFFICIAL: 'official'
},
GET_INVITATIONS_ERROR: 'Get invitations failed',
BUTTON_INVITE: 'Send',
diff --git a/modules/core/client/app/trans-string-zh-tw.js b/modules/core/client/app/trans-string-zh-tw.js
index 3e44fcb2..57248cd4 100644
--- a/modules/core/client/app/trans-string-zh-tw.js
+++ b/modules/core/client/app/trans-string-zh-tw.js
@@ -635,6 +635,14 @@
SET_DOWNLOADED_SUCCESSFULLY: '新增用戶下載量成功',
SET_DOWNLOADED_FAILED: '新增用戶下載量成功',
+ PRESENT_INVITATIONS_TITLE: '贈送邀請',
+ PRESENT_INVITATIONS_NUMBERS: '邀請數量:',
+ PRESENT_INVITATIONS_DAYS: '有效天數:',
+ BTN_PRESENT: '贈送',
+ BTN_PRESENT_INVITATIONS: '贈送邀請',
+ PRESENT_INVITATIONS_SUCCESSFULLY: '贈送邀請成功',
+ PRESENT_INVITATIONS_FAILED: '贈送邀請失敗',
+
ANNOUNCE_EDIT_TIP: '上傳一個種子檔案, 自動替換 Announce URL 與 Comment',
ANNOUNCE_COMMENT: 'Announce Comment',
@@ -1065,12 +1073,16 @@
TITLE_OPERATION: '操作',
TITLE_SENDER: '傳送人',
TITLE_TOKEN: '邀請碼',
+ TITLE_TYPE: '類型',
TITLE_EMAIL: '郵箱',
TITLE_SEND: '傳送邀請',
TITLE_STATUS: '狀態',
TITLE_STATUS_REGED: '已註冊',
TITLE_STATUS_UNREGED: '未註冊',
- TITLE_STATUS_EXPIRED: '已失效'
+ TITLE_STATUS_EXPIRED: '已失效',
+ TYPE_EXCHANGE: '積分兌換',
+ TYPE_PRESENT: '官方贈送',
+ TYPE_OFFICIAL: '官方邀請'
},
GET_INVITATIONS_ERROR: '獲取邀請列表失敗',
BUTTON_INVITE: '傳送',
diff --git a/modules/core/client/app/trans-string-zh.js b/modules/core/client/app/trans-string-zh.js
index 12f89edd..f1e2c988 100644
--- a/modules/core/client/app/trans-string-zh.js
+++ b/modules/core/client/app/trans-string-zh.js
@@ -635,6 +635,14 @@
SET_DOWNLOADED_SUCCESSFULLY: '添加用户下载量成功',
SET_DOWNLOADED_FAILED: '添加用户下载量成功',
+ PRESENT_INVITATIONS_TITLE: '赠送邀请',
+ PRESENT_INVITATIONS_NUMBERS: '邀请数量:',
+ PRESENT_INVITATIONS_DAYS: '有效天数:',
+ BTN_PRESENT: '赠送',
+ BTN_PRESENT_INVITATIONS: '赠送邀请',
+ PRESENT_INVITATIONS_SUCCESSFULLY: '赠送邀请成功',
+ PRESENT_INVITATIONS_FAILED: '赠送邀请失败',
+
ANNOUNCE_EDIT_TIP: '上传一个种子文件, 自动替换 Announce URL 与 Comment',
ANNOUNCE_COMMENT: 'Announce Comment',
@@ -1065,12 +1073,16 @@
TITLE_OPERATION: '操作',
TITLE_SENDER: '发送人',
TITLE_TOKEN: '邀请码',
+ TITLE_TYPE: '类型',
TITLE_EMAIL: '邮箱',
TITLE_SEND: '发送邀请',
TITLE_STATUS: '状态',
TITLE_STATUS_REGED: '已注册',
TITLE_STATUS_UNREGED: '未注册',
- TITLE_STATUS_EXPIRED: '已失效'
+ TITLE_STATUS_EXPIRED: '已失效',
+ TYPE_EXCHANGE: '积分兑换',
+ TYPE_PRESENT: '官方赠送',
+ TYPE_OFFICIAL: '官方邀请'
},
GET_INVITATIONS_ERROR: '获取邀请列表失败',
BUTTON_INVITE: '发送',
diff --git a/modules/core/client/less/mt.less b/modules/core/client/less/mt.less
index eb4ac733..bfebb6e9 100644
--- a/modules/core/client/less/mt.less
+++ b/modules/core/client/less/mt.less
@@ -14,8 +14,11 @@ body {
background-color: @mt-body-background-color;
}
-.ui-notification{
- width: 400px;
+.ui-notification {
+ width: 300px;
+ .message {
+ word-break: break-all;
+ }
}
.social-list {
@@ -2005,6 +2008,15 @@ body {
}
}
+.set-invitations-popover {
+ max-width: 250px;
+ width: 250px;
+ height: auto;
+ input {
+ max-width: 100px;
+ }
+}
+
.signature-input {
font-size: 0.9em;
background-color: #f5f5f5;
diff --git a/modules/invitations/client/controllers/admin-invitations.client.controller.js b/modules/invitations/client/controllers/admin-invitations.client.controller.js
index ce81abf7..ffa2fa66 100644
--- a/modules/invitations/client/controllers/admin-invitations.client.controller.js
+++ b/modules/invitations/client/controllers/admin-invitations.client.controller.js
@@ -31,7 +31,7 @@
*/
vm.buildPager = function () {
vm.pagedItems = [];
- vm.itemsPerPage = vm.itemsPerPageConfig.invitationsListPerPage;
+ vm.itemsPerPage = vm.itemsPerPageConfig.officialInvitationsListPerPage;
vm.currentPage = 1;
vm.figureOutItemsToDisplay();
};
diff --git a/modules/invitations/client/controllers/invitations.client.controller.js b/modules/invitations/client/controllers/invitations.client.controller.js
index 46e475ed..18fd27d6 100644
--- a/modules/invitations/client/controllers/invitations.client.controller.js
+++ b/modules/invitations/client/controllers/invitations.client.controller.js
@@ -6,16 +6,17 @@
.controller('InviteController', InviteController);
InviteController.$inject = ['$scope', '$state', '$translate', '$timeout', 'Authentication', '$window', 'MeanTorrentConfig', 'NotifycationService',
- 'InvitationsService', '$rootScope', 'moment'];
+ 'InvitationsService', '$rootScope', 'moment', 'DebugConsoleService', '$filter'];
function InviteController($scope, $state, $translate, $timeout, Authentication, $window, MeanTorrentConfig, NotifycationService,
- InvitationsService, $rootScope, moment) {
+ InvitationsService, $rootScope, moment, mtDebug, $filter) {
var vm = this;
vm.inviteConfig = MeanTorrentConfig.meanTorrentConfig.invite;
vm.signConfig = MeanTorrentConfig.meanTorrentConfig.sign;
vm.user = Authentication.user;
vm.announce = MeanTorrentConfig.meanTorrentConfig.announce;
vm.hnrConfig = MeanTorrentConfig.meanTorrentConfig.hitAndRun;
+ vm.itemsPerPageConfig = MeanTorrentConfig.meanTorrentConfig.itemsPerPage;
vm.invitePopover = {
title: 'INVITATION.TITLE_SEND',
@@ -35,17 +36,108 @@
vm.getMyInvitations();
});
+ /**
+ * myBuildPager
+ */
+ vm.myBuildPager = function () {
+ vm.myPagedItems = [];
+ vm.myItemsPerPage = vm.itemsPerPageConfig.userInvitationsListPerPage;
+ vm.myCurrentPage = 1;
+ vm.myFigureOutItemsToDisplay();
+ };
+
+ /**
+ * myFigureOutItemsToDisplay
+ */
+ vm.myFigureOutItemsToDisplay = function (callback) {
+ vm.myFilteredItems = vm.my_invitations;
+ vm.myFilterLength = vm.myFilteredItems.length;
+ var begin = ((vm.myCurrentPage - 1) * vm.myItemsPerPage);
+ var end = begin + vm.myItemsPerPage;
+ vm.myPagedItems = vm.myFilteredItems.slice(begin, end);
+
+ if (callback) callback();
+ };
+
+ /**
+ * myPageChanged
+ */
+ vm.myPageChanged = function () {
+ var element = angular.element('#top_of_my_invitations_list');
+ console.log(element);
+
+ $('.tb-my').fadeTo(100, 0.01, function () {
+ vm.myFigureOutItemsToDisplay(function () {
+ $timeout(function () {
+ $('.tb-my').fadeTo(400, 1, function () {
+ console.log(element[0].offsetTop);
+ //window.scrollTo(0, element[0].offsetTop - 60);
+ $('html,body').animate({scrollTop: element[0].offsetTop - 60}, 200);
+ });
+ }, 100);
+ });
+ });
+ };
+
+ /**
+ * buildPager
+ */
+ vm.buildPager = function () {
+ vm.pagedItems = [];
+ vm.itemsPerPage = vm.itemsPerPageConfig.userInvitationsListPerPage;
+ vm.currentPage = 1;
+ vm.figureOutItemsToDisplay();
+ };
+
+ /**
+ * figureOutItemsToDisplay
+ */
+ vm.figureOutItemsToDisplay = function (callback) {
+ vm.filteredItems = $filter('filter')(vm.used_invitations, {
+ $: vm.search
+ });
+ vm.filterLength = vm.filteredItems.length;
+ var begin = ((vm.currentPage - 1) * vm.itemsPerPage);
+ var end = begin + vm.itemsPerPage;
+ vm.pagedItems = vm.filteredItems.slice(begin, end);
+
+ if (callback) callback();
+ };
+
+ /**
+ * pageChanged
+ */
+ vm.pageChanged = function () {
+ var element = angular.element('#top_of_invitations_list');
+ console.log(element);
+ $('.tb-official').fadeTo(100, 0.01, function () {
+ vm.figureOutItemsToDisplay(function () {
+ $timeout(function () {
+ $('.tb-official').fadeTo(400, 1, function () {
+ //window.scrollTo(0, element[0].offsetTop - 60);
+ console.log(element[0].offsetTop);
+ $('html,body').animate({scrollTop: element[0].offsetTop - 60}, 200);
+ });
+ }, 100);
+ });
+ });
+ };
+
/**
* getMyInvitations
*/
vm.getMyInvitations = function () {
InvitationsService.get({}, function (items) {
+ mtDebug.info(items);
vm.my_invitations = items.my_invitations;
vm.used_invitations = items.used_invitations;
angular.forEach(vm.my_invitations, function (i) {
vm.invitePopover.items.push({isOpen: false});
});
+
+ vm.myBuildPager();
+ vm.buildPager();
}, function (res) {
NotifycationService.showErrorNotify('GET_INVITATIONS_ERROR');
});
diff --git a/modules/invitations/client/views/admin/official.client.view.html b/modules/invitations/client/views/admin/official.client.view.html
index d3184a92..751d50cd 100644
--- a/modules/invitations/client/views/admin/official.client.view.html
+++ b/modules/invitations/client/views/admin/official.client.view.html
@@ -47,7 +47,7 @@
+ ng-change="vm.buildPager()"/>
diff --git a/modules/invitations/client/views/detail.client.view.html b/modules/invitations/client/views/detail.client.view.html
index b3519b0d..39645a48 100644
--- a/modules/invitations/client/views/detail.client.view.html
+++ b/modules/invitations/client/views/detail.client.view.html
@@ -8,7 +8,7 @@
-
+
@@ -25,44 +25,77 @@
{{ 'INVITATION_IS_EMPTY' | translate }}
-
-
-
-
- |
- {{'INVITATION.TITLE_TOKEN' | translate}} |
- {{'INVITATION.TITLE_CREATEDAT' | translate}} |
- {{'INVITATION.TITLE_EXPIRESAT' | translate}} |
- {{'INVITATION.TITLE_OPERATION' | translate}} |
-
-
-
-
- | {{$index+1}}
- | {{r.token}} |
- {{r.createdat | date:'yyyy-MM-dd HH:mm:ss'}} |
- {{r.expiresat | date:'yyyy-MM-dd HH:mm:ss'}} |
-
-
- |
-
-
-
+
+
+
+
+
+
+
+ |
+ {{'INVITATION.TITLE_TOKEN' | translate}} |
+ {{'INVITATION.TITLE_TYPE' | translate}} |
+ {{'INVITATION.TITLE_CREATEDAT' | translate}} |
+ {{'INVITATION.TITLE_EXPIRESAT' | translate}} |
+ {{'INVITATION.TITLE_OPERATION' | translate}} |
+
+
+
+
+ | {{$index+1}}
+
+ | {{r.token}} |
+
+
+ {{'INVITATION.TYPE_'+r.type.toUpperCase() | translate}}
+
+ |
+ {{r.createdat | date:'yyyy-MM-dd HH:mm:ss'}} |
+ {{r.expiresat | date:'yyyy-MM-dd HH:mm:ss'}} |
+
+
+ |
+
+
+
+
+
+
-
+
@@ -79,45 +112,75 @@
{{ 'INVITATION_USED_IS_EMPTY' | translate }}
-
-
-
-
- |
- {{'INVITATION.TITLE_TOKEN' | translate}} |
- {{'INVITATION.TITLE_EMAIL' | translate}} |
- {{'INVITATION.TITLE_INVITEDAT' | translate}} |
- {{'INVITATION.TITLE_SIGNUPAT' | translate}} |
- {{'INVITATION.TITLE_SIGNUPID' | translate}} |
- {{'INVITATION.TITLE_STATUS' | translate}} |
-
-
-
-
- | {{$index+1}} |
- {{r.token}} |
- {{r.to_email}} |
- {{r.invitedat | date:'yyyy-MM-dd HH:mm:ss'}} |
- {{r.registeredat | date:'yyyy-MM-dd HH:mm:ss'}} |
-
-
-
-
-
- |
-
- |
-
- {{vm.getInvitationStatus(r);}}
- |
-
-
-
+
+
+
+
+
+
+
+ |
+ {{'INVITATION.TITLE_TOKEN' | translate}} |
+ {{'INVITATION.TITLE_EMAIL' | translate}} |
+ {{'INVITATION.TITLE_INVITEDAT' | translate}} |
+ {{'INVITATION.TITLE_SIGNUPAT' | translate}} |
+ {{'INVITATION.TITLE_SIGNUPID' | translate}} |
+ {{'INVITATION.TITLE_STATUS' | translate}} |
+
+
+
+
+ | {{$index+1}} |
+ {{r.token}} |
+ {{r.to_email}} |
+ {{r.invitedat | date:'yyyy-MM-dd HH:mm:ss'}} |
+ {{r.registeredat | date:'yyyy-MM-dd HH:mm:ss'}} |
+
+
+
+
+
+ |
+
+ |
+
+ {{vm.getInvitationStatus(r);}}
+ |
+
+
+
+
+
+
diff --git a/modules/invitations/server/controllers/invitations.server.controller.js b/modules/invitations/server/controllers/invitations.server.controller.js
index 7461a9c9..29174520 100644
--- a/modules/invitations/server/controllers/invitations.server.controller.js
+++ b/modules/invitations/server/controllers/invitations.server.controller.js
@@ -131,7 +131,7 @@ exports.list = function (req, res) {
expiresat: {$gt: Date.now()}
})
.sort('createdat')
- .populate('user', '-salt -password')
+ .populate('user', '-salt -password -followers -following -leeched_ip -signed_ip -signature')
.exec(function (err, invitations) {
if (err) {
callback(err, null);
@@ -147,8 +147,8 @@ exports.list = function (req, res) {
status: {$gt: 0}
})
.sort('invitedat')
- .populate('user', '-salt -password')
- .populate('to_user', '-salt -password')
+ .populate('user', '-salt -password -followers -following -leeched_ip -signed_ip -signature')
+ .populate('to_user', '-salt -password -followers -following -leeched_ip -signed_ip -signature')
.exec(function (err, invitations) {
if (err) {
callback(err, null);
@@ -308,6 +308,7 @@ exports.sendOfficial = function (req, res) {
invitation.invitedat = Date.now();
invitation.expiresat = Date.now() + config.meanTorrentConfig.invite.expires;
invitation.isOfficial = true;
+ invitation.type = 'official';
//send invitation mail
var lang = common.getRequestLanguage(req);
diff --git a/modules/invitations/server/models/invitation.server.model.js b/modules/invitations/server/models/invitation.server.model.js
index 3ea9add8..3961725e 100644
--- a/modules/invitations/server/models/invitation.server.model.js
+++ b/modules/invitations/server/models/invitation.server.model.js
@@ -26,6 +26,11 @@ var InvitationSchema = new Schema({
trim: true,
default: ''
},
+ type: {
+ type: String,
+ enum: ['exchange', 'present', 'official'], //'exchange' is from user`s score, 'present' is from official, 'official' is official invitations
+ default: 'exchange'
+ },
status: {
type: Number,
default: 0 //0 is unregistered invitation, 1 already invite friend, 2 is already registered
diff --git a/modules/users/client/controllers/admin/user.client.controller.js b/modules/users/client/controllers/admin/user.client.controller.js
index 1d10975a..c8d6f7bb 100644
--- a/modules/users/client/controllers/admin/user.client.controller.js
+++ b/modules/users/client/controllers/admin/user.client.controller.js
@@ -27,6 +27,7 @@
vm.isContextUserSelf = isContextUserSelf;
vm.scoreLevelData = ScoreLevelService.getScoreLevelJson(vm.user.score);
vm.inputLengthConfig = MeanTorrentConfig.meanTorrentConfig.inputLength;
+ vm.inviteConfig = MeanTorrentConfig.meanTorrentConfig.invite;
vm.searchTags = [];
vm.maker = {};
@@ -49,7 +50,18 @@
isOpen: false
};
+ vm.presentInvitationsPopover = {
+ title: 'PRESENT_INVITATIONS_TITLE',
+ templateUrl: 'present-invitations.html',
+ label_numbers: 'PRESENT_INVITATIONS_NUMBERS',
+ label_days: 'PRESENT_INVITATIONS_DAYS',
+ isOpen: false,
+ numbers: 1,
+ days: 1
+ };
+
mtDebug.info(vm.user);
+
/**
* remove
* @param user
@@ -410,5 +422,36 @@
NotifycationService.showErrorNotify(response.data.message, 'SET_DOWNLOADED_FAILED');
}
};
+
+ /**
+ * presentInvitations
+ */
+ vm.presentInvitations = function () {
+ if (isNaN(vm.presentInvitationsPopover.numbers)) {
+ return false;
+ } else if (vm.presentInvitationsPopover.numbers < 0) {
+ return false;
+ } else {
+ var user = vm.user;
+ AdminService.presentUserInvitations({
+ userId: user._id,
+ numbers: vm.presentInvitationsPopover.numbers,
+ days: vm.presentInvitationsPopover.days
+ })
+ .then(onSuccess)
+ .catch(onError);
+
+ vm.presentInvitationsPopover.isOpen = false;
+ }
+
+ function onSuccess(response) {
+ vm.user = response;
+ NotifycationService.showSuccessNotify('PRESENT_INVITATIONS_SUCCESSFULLY');
+ }
+
+ function onError(response) {
+ NotifycationService.showErrorNotify(response.data.message, 'PRESENT_INVITATIONS_FAILED');
+ }
+ };
}
}());
diff --git a/modules/users/client/less/user.less b/modules/users/client/less/user.less
new file mode 100644
index 00000000..ebe41977
--- /dev/null
+++ b/modules/users/client/less/user.less
@@ -0,0 +1,7 @@
+@import (reference) "../../../core/client/less/mt-var.less";
+
+.user-cmd {
+ margin-bottom: 30px;
+ padding-bottom: 20px;
+ border-bottom: solid 1px #eee;
+}
\ No newline at end of file
diff --git a/modules/users/client/services/users.client.service.js b/modules/users/client/services/users.client.service.js
index d4461708..0f4e6b93 100644
--- a/modules/users/client/services/users.client.service.js
+++ b/modules/users/client/services/users.client.service.js
@@ -318,6 +318,13 @@
method: 'GET',
url: '/api/users/uploaderList',
cache: usersCache
+ },
+ presentInvitations: {
+ method: 'PUT',
+ url: '/api/users/:userId/presentInvitations',
+ params: {
+ userId: '@userId'
+ }
}
});
@@ -351,7 +358,11 @@
},
getUploaderList: function (params) {
return this.uploaderList(params).$promise;
+ },
+ presentUserInvitations: function (params) {
+ return this.presentInvitations(params).$promise;
}
+
});
return Users;
diff --git a/modules/users/client/views/admin/view-user.client.view.html b/modules/users/client/views/admin/view-user.client.view.html
index 29a495f4..f25107ac 100644
--- a/modules/users/client/views/admin/view-user.client.view.html
+++ b/modules/users/client/views/admin/view-user.client.view.html
@@ -19,6 +19,23 @@
+
+
+
+
+
+
+
+
@@ -32,7 +49,9 @@
- ID:
- - {{ vm.user._id }}
+ -
+ {{ vm.user._id }}
+
- {{ 'STATUS_FIELD.USERNAME' | translate}}:
- {{ vm.user.username }}
@@ -340,4 +359,25 @@
+
+
diff --git a/modules/users/server/controllers/admin.server.controller.js b/modules/users/server/controllers/admin.server.controller.js
index 500be8d6..4e5b7497 100644
--- a/modules/users/server/controllers/admin.server.controller.js
+++ b/modules/users/server/controllers/admin.server.controller.js
@@ -12,6 +12,7 @@ var path = require('path'),
Peer = mongoose.model('Peer'),
Torrent = mongoose.model('Torrent'),
Complete = mongoose.model('Complete'),
+ Invitation = mongoose.model('Invitation'),
moment = require('moment'),
async = require('async'),
ScoreLog = mongoose.model('ScoreLog'),
@@ -542,6 +543,44 @@ exports.resetVIPData = function (req, res) {
});
};
+/**
+ * presentInvitations
+ * @param req
+ * @param res
+ */
+exports.presentInvitations = function (req, res) {
+ var user = req.model;
+ var numbers = req.body.numbers;
+ var days = req.body.days;
+ var invitations = [];
+
+ for (var i = 0; i < numbers; i++) {
+ var invitation = new Invitation();
+ invitation.expiresat = Date.now() + (60 * 60 * 1000 * 24 * days);
+ invitation.user = user;
+ invitation.type = 'present';
+ invitation.isOfficial = false;
+ invitation.token = user.randomAsciiString(32);
+
+ invitations.push(invitation);
+ }
+
+ Invitation.insertMany(invitations, function (err, docs) {
+ if (err) {
+ return res.status(422).send({
+ message: errorHandler.getErrorMessage(err)
+ });
+ } else {
+ res.json(user);
+ //create trace log
+ traceLogCreate(req, traceConfig.action.adminPresentInvitations, {
+ user: user._id,
+ invitations: docs
+ });
+ }
+ });
+};
+
/**
* list user seeding torrents
* @param req
diff --git a/modules/users/server/policies/admin.server.policy.js b/modules/users/server/policies/admin.server.policy.js
index 08beb7a4..5d92ebab 100644
--- a/modules/users/server/policies/admin.server.policy.js
+++ b/modules/users/server/policies/admin.server.policy.js
@@ -20,7 +20,8 @@ exports.invokeRolesPolicies = function () {
{resources: '/api/users/uploaderList', permissions: '*'},
{resources: '/api/users/:userId/role', permissions: '*'},
{resources: '/api/users/:userId/VIPMonths/:months', permissions: '*'},
- {resources: '/api/users/:userId/VIPMonths/reset', permissions: '*'}
+ {resources: '/api/users/:userId/VIPMonths/reset', permissions: '*'},
+ {resources: '/api/users/:userId/presentInvitations', permissions: '*'}
]
},
{
diff --git a/modules/users/server/routes/admin.server.routes.js b/modules/users/server/routes/admin.server.routes.js
index 328a7322..9fbbeb7d 100644
--- a/modules/users/server/routes/admin.server.routes.js
+++ b/modules/users/server/routes/admin.server.routes.js
@@ -50,6 +50,8 @@ module.exports = function (app) {
.get(follow.getUserFollowing);
app.route('/api/users/:userId/resetImage').all(adminPolicy.isAllowed)
.put(admin.resetUserProfileImage);
+ app.route('/api/users/:userId/presentInvitations').all(adminPolicy.isAllowed)
+ .put(admin.presentInvitations);
app.route('/api/users/:userId/VIPMonths/reset').all(adminPolicy.isAllowed)
.put(admin.resetVIPData);