3 var crypto = require('crypto');
4 var md5 = require('md5');
5 var _ = require('lodash');
6 var moment = require('moment');
8 module.exports = function(sequelize, DataTypes) {
9 var User = sequelize.define('User', {
11 type: DataTypes.STRING,
15 is: /^[A-Za-z0-9\.\_]+$/i
18 this.setDataValue('name', name);
19 this.setDataValue('defaultuser', name);
23 type: DataTypes.STRING,
27 type: DataTypes.STRING,
30 set: function(email) {
32 this.setDataValue('email', email.toLowerCase());
38 type: DataTypes.ENUM('admin', 'user', 'agent', 'telephone')
41 type: DataTypes.STRING,
46 set: function(password) {
47 this.salt = this.makeSalt();
48 this.setDataValue('password', this.encryptPassword(password));
49 this.setDataValue('md5secret', this.md5Password(this.name + ':asterisk:' + password));
53 type: DataTypes.STRING,
57 type: DataTypes.INTEGER(11),
59 set: function(internal) {
60 this.setDataValue('internal', internal);
61 this.setDataValue('accountcode', internal);
65 type: DataTypes.STRING
68 type: DataTypes.STRING
71 type: DataTypes.STRING
74 type: DataTypes.STRING
77 type: DataTypes.STRING
80 type: DataTypes.STRING
83 type: DataTypes.STRING
86 type: DataTypes.STRING
89 type: DataTypes.BOOLEAN,
96 type: DataTypes.STRING,
97 defaultValue: 'UNKNOWN'
103 type: DataTypes.STRING,
104 defaultValue: 'complete'
110 type: DataTypes.STRING
113 type: DataTypes.BOOLEAN,
115 // set: function(voicePause) {
116 // this.setDataValue('voicePause', voicePause);
118 // this.setDataValue('queueStatus', 'paused');
119 // this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
121 // this.setDataValue('queueStatus', 'complete');
122 // this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
127 type: DataTypes.BOOLEAN,
131 type: DataTypes.BOOLEAN,
135 type: DataTypes.BOOLEAN,
139 type: DataTypes.BOOLEAN,
143 type: DataTypes.BOOLEAN,
147 type: DataTypes.STRING,
148 defaultValue: 'Default Pause'
154 type: DataTypes.INTEGER,
158 type: DataTypes.INTEGER,
162 type: DataTypes.INTEGER,
166 type: DataTypes.INTEGER,
169 openchannelCapacity: {
170 type: DataTypes.INTEGER,
173 phoneBarAutoAnswer: {
174 type: DataTypes.BOOLEAN,
177 phoneBarEnableSettings: {
178 type: DataTypes.BOOLEAN,
181 phoneBarUnconditionalNumber: {
182 type: DataTypes.STRING,
184 if (this.getDataValue('phoneBarUnconditional')) {
185 return this.getDataValue('phoneBarUnconditionalNumber');
190 phoneBarNoReplyNumber: {
191 type: DataTypes.STRING,
193 if (this.getDataValue('phoneBarNoReply')) {
194 return this.getDataValue('phoneBarNoReplyNumber');
199 phoneBarBusyNumber: {
200 type: DataTypes.STRING,
202 if (this.getDataValue('phoneBarBusy')) {
203 return this.getDataValue('phoneBarBusyNumber');
208 phoneBarUnconditional: {
209 type: DataTypes.BOOLEAN,
213 type: DataTypes.BOOLEAN,
217 type: DataTypes.BOOLEAN,
220 phoneBarListenPort: {
221 type: DataTypes.INTEGER(5),
225 type: DataTypes.INTEGER(5),
229 type: DataTypes.INTEGER(5),
232 phoneBarNameServer: {
233 type: DataTypes.STRING,
236 phoneBarStunServer: {
237 type: DataTypes.STRING,
240 phoneBarVADEnabled: {
241 type: DataTypes.BOOLEAN,
245 type: DataTypes.BOOLEAN,
249 type: DataTypes.BOOLEAN,
253 type: DataTypes.INTEGER(5),
256 phoneBarPublishEnabled: {
257 type: DataTypes.BOOLEAN,
260 phoneBarRemoteControl: {
261 type: DataTypes.BOOLEAN,
264 phoneBarRemoteControlPort: {
265 type: DataTypes.INTEGER,
269 type: DataTypes.BOOLEAN,
273 type: DataTypes.STRING,
277 type: DataTypes.STRING,
279 defaultValue: 'dynamic'
281 ipaddr: { //REALTIME ASTERISK
282 type: DataTypes.STRING,
285 port: { //REALTIME ASTERISK
286 type: DataTypes.INTEGER(5),
289 regseconds: { //REALTIME ASTERISK
290 type: DataTypes.INTEGER(11),
293 fullcontact: { //REALTIME ASTERISK
294 type: DataTypes.STRING,
297 regserver: { //REALTIME ASTERISK
298 type: DataTypes.STRING,
301 useragent: { //REALTIME ASTERISK
302 type: DataTypes.STRING,
305 lastms: { //REALTIME ASTERISK
306 type: DataTypes.INTEGER(11),
310 type: DataTypes.ENUM('friend', 'user', 'peer'),
312 defaultValue: 'friend'
315 type: DataTypes.STRING,
317 defaultValue: 'from-sip'
320 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
321 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
322 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
323 'PROHIB_FAILED_SCREEN', 'PROHIB'),
327 type: DataTypes.STRING,
331 type: DataTypes.STRING,
335 type: DataTypes.STRING,
339 type: DataTypes.STRING,
343 type: DataTypes.STRING,
347 type: DataTypes.STRING,
352 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
355 defaultValue: 'rfc2833'
358 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
363 type: DataTypes.ENUM('yes', 'no'),
368 type: DataTypes.STRING,
372 type: DataTypes.STRING,
376 type: DataTypes.STRING,
378 defaultValue: 'force_rport,comedia'
381 type: DataTypes.STRING,
384 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
385 type: DataTypes.STRING,
389 type: DataTypes.STRING,
392 namedpickupgroup: { //We can do call pick-p for named call group sales
393 type: DataTypes.STRING,
397 type: DataTypes.STRING,
402 type: DataTypes.STRING,
406 type: DataTypes.STRING,
411 type: DataTypes.STRING,
413 defaultValue: 'ulaw;gsm'
416 type: DataTypes.ENUM('yes', 'no'),
420 type: DataTypes.STRING,
422 defaultValue: 'port,invite'
425 type: DataTypes.ENUM('yes', 'no'),
430 type: DataTypes.ENUM('yes', 'no'),
435 type: DataTypes.ENUM('yes', 'no', 'never'),
439 type: DataTypes.ENUM('yes', 'no'),
443 type: DataTypes.ENUM('yes', 'no'),
447 type: DataTypes.INTEGER(11),
451 type: DataTypes.STRING,
455 type: DataTypes.STRING,
457 defaultValue: '"" <>'
460 type: DataTypes.STRING,
464 type: DataTypes.ENUM('yes', 'no'),
469 type: DataTypes.INTEGER(11),
473 type: DataTypes.ENUM('yes', 'no'),
477 type: DataTypes.ENUM('yes', 'no'),
481 type: DataTypes.ENUM('yes', 'no'),
485 type: DataTypes.ENUM('yes', 'no'),
489 type: DataTypes.STRING,
493 type: DataTypes.STRING,
497 type: DataTypes.ENUM('yes', 'no', 'always'),
502 type: DataTypes.INTEGER(11),
506 type: DataTypes.ENUM('yes', 'no'),
510 type: DataTypes.STRING,
514 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
518 type: DataTypes.INTEGER(11),
522 type: DataTypes.INTEGER(11),
526 type: DataTypes.ENUM('uac', 'uas'),
530 t38pt_usertpsource: {
531 type: DataTypes.STRING,
535 type: DataTypes.STRING,
539 type: DataTypes.STRING,
543 type: DataTypes.STRING,
547 type: DataTypes.ENUM('yes', 'no'),
552 type: DataTypes.INTEGER(11),
556 type: DataTypes.STRING,
560 type: DataTypes.STRING,
563 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
564 type: DataTypes.INTEGER(11),
567 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
568 type: DataTypes.INTEGER(11),
571 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
572 type: DataTypes.INTEGER(11),
576 type: DataTypes.ENUM('yes', 'no'),
581 type: DataTypes.STRING,
585 type: DataTypes.STRING,
589 type: DataTypes.INTEGER(11),
593 type: DataTypes.INTEGER(11),
597 type: DataTypes.INTEGER(11),
601 type: DataTypes.STRING,
605 type: DataTypes.STRING,
609 type: DataTypes.STRING,
612 unsolicited_mailbox: {
613 type: DataTypes.STRING,
617 type: DataTypes.STRING,
621 type: DataTypes.INTEGER(11),
625 type: DataTypes.ENUM('yes', 'no'),
630 type: DataTypes.ENUM('yes', 'no'),
634 type: DataTypes.ENUM('yes', 'no'),
638 type: DataTypes.ENUM('yes', 'no'),
642 type: DataTypes.ENUM('yes', 'no'),
646 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
650 type: DataTypes.INTEGER(11),
654 type: DataTypes.STRING,
658 type: DataTypes.STRING,
662 type: DataTypes.STRING,
666 type: DataTypes.STRING,
670 type: DataTypes.STRING,
674 type: DataTypes.ENUM('active', 'passive', 'actpass'),
678 type: DataTypes.STRING,
681 usereqphone: { //This provider requires ";user=phone" on URI
682 type: DataTypes.ENUM('yes', 'no'),
686 recordonfeature: { //Feature to use when INFO with Record: on is received.
687 type: DataTypes.STRING,
690 recordofffeature: { //Feature to use when INFO with Record: off is received.
691 type: DataTypes.STRING,
695 type: DataTypes.INTEGER(11),
699 registertrying: { //Send a 100 Trying when the device registers.
700 type: DataTypes.ENUM('yes', 'no'),
703 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
704 type: DataTypes.ENUM('yes', 'no'),
707 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
708 type: DataTypes.STRING,
711 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
712 type: DataTypes.STRING,
715 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
716 type: DataTypes.STRING,
720 type: DataTypes.STRING,
724 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
729 type: DataTypes.BOOLEAN,
732 resetPasswordToken: {
733 type: DataTypes.STRING
735 resetPasswordExpires: {
738 phoneBarEnableRecording: {
739 type: DataTypes.BOOLEAN,
743 type: DataTypes.BOOLEAN,
746 phoneBarShowOmniDesktop: {
747 type: DataTypes.BOOLEAN,
751 type: DataTypes.BOOLEAN,
755 type: DataTypes.BOOLEAN,
758 phoneBarUnansweredCallBadge: {
759 type: DataTypes.BOOLEAN,
762 phonebarEnableDtmfTone: {
763 type: DataTypes.BOOLEAN,
766 phonebarAutoAnswerDelay: {
767 type: DataTypes.INTEGER,
776 * Authenticate - check if the passwords are the same
778 * @param {String} plainText
779 * {function} callBack
782 authenticate: function(plainText) {
783 return this.encryptPassword(plainText) === this.password;
791 makeSalt: function() {
792 return crypto.randomBytes(16).toString('base64');
797 * @param {String} password
801 encryptPassword: function(password) {
802 if (!password || !this.salt) return '';
803 var salt = new Buffer(this.salt, 'base64');
804 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
810 * @param {String} password
814 md5Password: function(password) {
815 if (!password) return '';
816 return md5(password);
819 associate: function(models) {
821 User.hasMany(models.ChatMessage);
822 User.hasMany(models.MailMessage);
823 User.hasMany(models.Contact);
824 User.hasMany(models.Action);
825 User.belongsToMany(models.Module, {
826 through: models.UserHasModule,
829 User.belongsToMany(models.MailRoom, {
830 through: models.UserHasMailRoom,
832 User.belongsToMany(models.Channel, {
833 through: 'user_has_channels'
835 User.belongsToMany(models.SmsRoom, {
836 through: 'user_has_sms_rooms'
838 User.belongsToMany(models.OpenchannelRoom, {
839 through: 'user_has_openchannel_rooms'
841 User.belongsToMany(models.FaxRoom, {
842 through: 'user_has_fax_rooms'
844 User.belongsToMany(models.Team, {
845 through: models.UserHasTeam
847 User.belongsToMany(models.VoiceQueue, {
848 through: models.UserHasVoiceQueue,
851 User.belongsToMany(models.VoiceQueue, {
852 through: models.UserHasVoiceQueuePermit,
855 User.belongsToMany(models.MailQueue, {
856 through: models.UserHasMailQueue,
859 User.belongsToMany(models.SmsQueue, {
860 through: models.UserHasSmsQueue,
863 User.belongsToMany(models.SmsQueue, {
864 through: models.UserHasSmsQueuePermit,
867 User.belongsToMany(models.OpenchannelQueue, {
868 through: models.UserHasOpenchannelQueue,
871 User.belongsToMany(models.OpenchannelQueue, {
872 through: models.UserHasOpenchannelQueuePermit,
873 as: 'POpenchannelQueues'
875 User.belongsToMany(models.MailQueue, {
876 through: models.UserHasMailQueuePermit,
879 User.belongsToMany(models.FaxQueue, {
880 through: models.UserHasFaxQueue,
883 User.belongsToMany(models.FaxQueue, {
884 through: models.UserHasFaxQueuePermit,
887 User.belongsToMany(models.ChatQueue, {
888 through: models.UserHasChatQueue,
891 User.belongsToMany(models.ChatQueue, {
892 through: models.UserHasChatQueuePermit,
895 User.belongsToMany(models.ChatRoom, {
896 through: models.UserHasChatRoom
898 User.belongsToMany(models.List, {
899 through: models.UserHasList
901 User.hasMany(models.VoiceExtension, {
902 foreignKey: 'UserId',
903 as: 'UserExtensions',
909 User.addScope('all', {
937 User.addScope('user', {
940 $in: ['admin', 'user']
967 User.addScope('agent', {
988 'openchannelCapacity',
991 'phoneBarAutoAnswer',
992 'phoneBarEnableSettings',
993 'phoneBarUnconditional',
996 'phoneBarUnconditionalNumber',
997 'phoneBarNoReplyNumber',
998 'phoneBarBusyNumber',
999 'phoneBarListenPort',
1001 'phoneBarRemoteControl',
1002 'phoneBarRemoteControlPort',
1003 'phoneBarEnableRecording',
1028 'phoneBarShowOmniDesktop',
1029 'phoneBarRingInUse',
1031 'phoneBarUnansweredCallBadge',
1034 'phonebarEnableDtmfTone',
1035 'phonebarAutoAnswerDelay'
1038 User.addScope('telephone', {
1043 User.addScope('queues', {
1045 model: models.VoiceQueue,
1048 model: models.ChatQueue,
1051 model: models.MailQueue,
1054 model: models.FaxQueue,
1057 model: models.SmsQueue,
1060 model: models.OpenchannelQueue,
1065 User.addScope('checkPauseStatus', function(query) {
1069 if (query.voicePause) {
1070 scope.where.voicePause = (query.voicePause === 'true') ?
1072 delete query.voicePause;
1073 } else if (query.faxPause) {
1074 scope.where.faxPause = (query.faxPause === 'true') ? true :
1076 delete query.faxPause;
1077 } else if (query.chatPause) {
1078 scope.where.chatPause = (query.chatPause === 'true') ?
1080 delete query.chatPause;
1081 } else if (query.mailPause) {
1082 scope.where.mailPause = (query.mailPause === 'true') ?
1084 delete query.mailPause;
1085 } else if (query.smsPause) {
1086 scope.where.smsPause = (query.smsPause === 'true') ?
1088 delete query.smsPause;
1089 } else if (query.openchannelPause) {
1090 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1092 delete query.openchannelPause;
1096 User.addScope('checkOnlineStatus', function(query) {
1101 scope.where.online = (query.online === 'true') ? true :
1103 delete query.online;
1107 User.addScope('checkSipStatus', function(query) {
1112 scope.where.status = query.status;
1113 delete query.status;
1117 User.addScope('checkQueueStatus', function(query) { //to be executed before checkOnlineStatus
1121 if (query.queueStatus) {
1122 if (query.queueStatus === 'paused') {
1123 scope.where.voicePause = true;
1125 scope.where.queueStatus = query.queueStatus;
1126 scope.where.voicePause = false;
1127 query.online = 'true';
1129 delete query.queueStatus;
1134 User.addScope('me', function(userId) {
1139 attributes: ['id', 'fullname', 'name', 'email', 'role', 'userpic', 'lastLoginAt', 'voicePause',
1147 'phoneBarRemoteControl',
1148 'phoneBarRemoteControlPort',
1151 'phonebarEnableDtmfTone',
1152 'phonebarAutoAnswerDelay'
1155 model: models.Module,
1157 model: models.Module,
1165 model: models.VoiceQueue,
1168 model: models.ChatQueue,
1171 model: models.MailQueue,
1174 model: models.FaxQueue,
1177 model: models.SmsQueue,