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,
772 * Authenticate - check if the passwords are the same
774 * @param {String} plainText
775 * {function} callBack
778 authenticate: function(plainText) {
779 return this.encryptPassword(plainText) === this.password;
787 makeSalt: function() {
788 return crypto.randomBytes(16).toString('base64');
793 * @param {String} password
797 encryptPassword: function(password) {
798 if (!password || !this.salt) return '';
799 var salt = new Buffer(this.salt, 'base64');
800 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
806 * @param {String} password
810 md5Password: function(password) {
811 if (!password) return '';
812 return md5(password);
815 associate: function(models) {
817 User.hasMany(models.ChatMessage);
818 User.hasMany(models.MailMessage);
819 User.hasMany(models.Contact);
820 User.hasMany(models.Action);
821 User.belongsToMany(models.Module, {
822 through: models.UserHasModule,
825 User.belongsToMany(models.MailRoom, {
826 through: models.UserHasMailRoom,
828 User.belongsToMany(models.Channel, {
829 through: 'user_has_channels'
831 User.belongsToMany(models.SmsRoom, {
832 through: 'user_has_sms_rooms'
834 User.belongsToMany(models.OpenchannelRoom, {
835 through: 'user_has_openchannel_rooms'
837 User.belongsToMany(models.FaxRoom, {
838 through: 'user_has_fax_rooms'
840 User.belongsToMany(models.Team, {
841 through: models.UserHasTeam
843 User.belongsToMany(models.VoiceQueue, {
844 through: models.UserHasVoiceQueue,
847 User.belongsToMany(models.VoiceQueue, {
848 through: models.UserHasVoiceQueuePermit,
851 User.belongsToMany(models.MailQueue, {
852 through: models.UserHasMailQueue,
855 User.belongsToMany(models.SmsQueue, {
856 through: models.UserHasSmsQueue,
859 User.belongsToMany(models.SmsQueue, {
860 through: models.UserHasSmsQueuePermit,
863 User.belongsToMany(models.OpenchannelQueue, {
864 through: models.UserHasOpenchannelQueue,
867 User.belongsToMany(models.OpenchannelQueue, {
868 through: models.UserHasOpenchannelQueuePermit,
869 as: 'POpenchannelQueues'
871 User.belongsToMany(models.MailQueue, {
872 through: models.UserHasMailQueuePermit,
875 User.belongsToMany(models.FaxQueue, {
876 through: models.UserHasFaxQueue,
879 User.belongsToMany(models.FaxQueue, {
880 through: models.UserHasFaxQueuePermit,
883 User.belongsToMany(models.ChatQueue, {
884 through: models.UserHasChatQueue,
887 User.belongsToMany(models.ChatQueue, {
888 through: models.UserHasChatQueuePermit,
891 User.belongsToMany(models.ChatRoom, {
892 through: models.UserHasChatRoom
894 User.belongsToMany(models.List, {
895 through: models.UserHasList
897 User.hasMany(models.VoiceExtension, {
898 foreignKey: 'UserId',
899 as: 'UserExtensions',
905 User.addScope('all', {
933 User.addScope('user', {
936 $in: ['admin', 'user']
963 User.addScope('agent', {
984 'openchannelCapacity',
987 'phoneBarAutoAnswer',
988 'phoneBarEnableSettings',
989 'phoneBarUnconditional',
992 'phoneBarUnconditionalNumber',
993 'phoneBarNoReplyNumber',
994 'phoneBarBusyNumber',
995 'phoneBarListenPort',
997 'phoneBarRemoteControl',
998 'phoneBarRemoteControlPort',
999 'phoneBarEnableRecording',
1024 'phoneBarShowOmniDesktop',
1025 'phoneBarRingInUse',
1027 'phoneBarUnansweredCallBadge',
1030 'phonebarEnableDtmfTone'
1033 User.addScope('telephone', {
1038 User.addScope('queues', {
1040 model: models.VoiceQueue,
1043 model: models.ChatQueue,
1046 model: models.MailQueue,
1049 model: models.FaxQueue,
1052 model: models.SmsQueue,
1055 model: models.OpenchannelQueue,
1060 User.addScope('checkPauseStatus', function(query) {
1064 if (query.voicePause) {
1065 scope.where.voicePause = (query.voicePause === 'true') ?
1067 delete query.voicePause;
1068 } else if (query.faxPause) {
1069 scope.where.faxPause = (query.faxPause === 'true') ? true :
1071 delete query.faxPause;
1072 } else if (query.chatPause) {
1073 scope.where.chatPause = (query.chatPause === 'true') ?
1075 delete query.chatPause;
1076 } else if (query.mailPause) {
1077 scope.where.mailPause = (query.mailPause === 'true') ?
1079 delete query.mailPause;
1080 } else if (query.smsPause) {
1081 scope.where.smsPause = (query.smsPause === 'true') ?
1083 delete query.smsPause;
1084 } else if (query.openchannelPause) {
1085 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1087 delete query.openchannelPause;
1091 User.addScope('checkOnlineStatus', function(query) {
1096 scope.where.online = (query.online === 'true') ? true :
1098 delete query.online;
1102 User.addScope('checkSipStatus', function(query) {
1107 scope.where.status = query.status;
1108 delete query.status;
1112 User.addScope('checkQueueStatus', function(query) { //to be executed before checkOnlineStatus
1116 if (query.queueStatus) {
1117 if (query.queueStatus === 'paused') {
1118 scope.where.voicePause = true;
1120 scope.where.queueStatus = query.queueStatus;
1121 scope.where.voicePause = false;
1122 query.online = 'true';
1124 delete query.queueStatus;
1129 User.addScope('me', function(userId) {
1134 attributes: ['id', 'fullname', 'name', 'email', 'role', 'userpic', 'lastLoginAt', 'voicePause',
1142 'phoneBarRemoteControl',
1143 'phoneBarRemoteControlPort',
1146 'phonebarEnableDtmfTone'
1149 model: models.Module,
1151 model: models.Module,
1159 model: models.VoiceQueue,
1162 model: models.ChatQueue,
1165 model: models.MailQueue,
1168 model: models.FaxQueue,
1171 model: models.SmsQueue,