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,
424 type: DataTypes.ENUM('yes', 'no'),
429 type: DataTypes.ENUM('yes', 'no'),
434 type: DataTypes.ENUM('yes', 'no', 'never'),
438 type: DataTypes.ENUM('yes', 'no'),
442 type: DataTypes.ENUM('yes', 'no'),
446 type: DataTypes.INTEGER(11),
450 type: DataTypes.STRING,
454 type: DataTypes.STRING,
456 defaultValue: '"" <>'
459 type: DataTypes.STRING,
463 type: DataTypes.ENUM('yes', 'no'),
468 type: DataTypes.INTEGER(11),
472 type: DataTypes.ENUM('yes', 'no'),
476 type: DataTypes.ENUM('yes', 'no'),
480 type: DataTypes.ENUM('yes', 'no'),
484 type: DataTypes.ENUM('yes', 'no'),
488 type: DataTypes.STRING,
492 type: DataTypes.STRING,
496 type: DataTypes.ENUM('yes', 'no', 'always'),
501 type: DataTypes.INTEGER(11),
505 type: DataTypes.ENUM('yes', 'no'),
509 type: DataTypes.STRING,
513 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
517 type: DataTypes.INTEGER(11),
521 type: DataTypes.INTEGER(11),
525 type: DataTypes.ENUM('uac', 'uas'),
529 t38pt_usertpsource: {
530 type: DataTypes.STRING,
534 type: DataTypes.STRING,
538 type: DataTypes.STRING,
542 type: DataTypes.STRING,
546 type: DataTypes.ENUM('yes', 'no'),
551 type: DataTypes.INTEGER(11),
555 type: DataTypes.STRING,
559 type: DataTypes.STRING,
562 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
563 type: DataTypes.INTEGER(11),
566 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
567 type: DataTypes.INTEGER(11),
570 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
571 type: DataTypes.INTEGER(11),
575 type: DataTypes.ENUM('yes', 'no'),
580 type: DataTypes.STRING,
584 type: DataTypes.STRING,
588 type: DataTypes.INTEGER(11),
592 type: DataTypes.INTEGER(11),
596 type: DataTypes.INTEGER(11),
600 type: DataTypes.STRING,
604 type: DataTypes.STRING,
608 type: DataTypes.STRING,
611 unsolicited_mailbox: {
612 type: DataTypes.STRING,
616 type: DataTypes.STRING,
620 type: DataTypes.INTEGER(11),
624 type: DataTypes.ENUM('yes', 'no'),
629 type: DataTypes.ENUM('yes', 'no'),
633 type: DataTypes.ENUM('yes', 'no'),
637 type: DataTypes.ENUM('yes', 'no'),
641 type: DataTypes.ENUM('yes', 'no'),
645 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
649 type: DataTypes.INTEGER(11),
653 type: DataTypes.STRING,
657 type: DataTypes.STRING,
661 type: DataTypes.STRING,
665 type: DataTypes.STRING,
669 type: DataTypes.STRING,
673 type: DataTypes.ENUM('active', 'passive', 'actpass'),
677 type: DataTypes.STRING,
680 usereqphone: { //This provider requires ";user=phone" on URI
681 type: DataTypes.ENUM('yes', 'no'),
685 recordonfeature: { //Feature to use when INFO with Record: on is received.
686 type: DataTypes.STRING,
689 recordofffeature: { //Feature to use when INFO with Record: off is received.
690 type: DataTypes.STRING,
694 type: DataTypes.INTEGER(11),
698 registertrying: { //Send a 100 Trying when the device registers.
699 type: DataTypes.ENUM('yes', 'no'),
702 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
703 type: DataTypes.ENUM('yes', 'no'),
706 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
707 type: DataTypes.STRING,
710 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
711 type: DataTypes.STRING,
714 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
715 type: DataTypes.STRING,
719 type: DataTypes.STRING,
723 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
728 type: DataTypes.BOOLEAN,
731 resetPasswordToken: {
732 type: DataTypes.STRING
734 resetPasswordExpires: {
737 phoneBarEnableRecording: {
738 type: DataTypes.BOOLEAN,
742 type: DataTypes.BOOLEAN,
745 phoneBarShowOmniDesktop: {
746 type: DataTypes.BOOLEAN,
750 type: DataTypes.BOOLEAN,
754 type: DataTypes.BOOLEAN,
757 phoneBarUnansweredCallBadge: {
758 type: DataTypes.BOOLEAN,
761 phonebarEnableDtmfTone: {
762 type: DataTypes.BOOLEAN,
765 phonebarAutoAnswerDelay: {
766 type: DataTypes.INTEGER,
775 * Authenticate - check if the passwords are the same
777 * @param {String} plainText
778 * {function} callBack
781 authenticate: function(plainText) {
782 return this.encryptPassword(plainText) === this.password;
790 makeSalt: function() {
791 return crypto.randomBytes(16).toString('base64');
796 * @param {String} password
800 encryptPassword: function(password) {
801 if (!password || !this.salt) return '';
802 var salt = new Buffer(this.salt, 'base64');
803 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
809 * @param {String} password
813 md5Password: function(password) {
814 if (!password) return '';
815 return md5(password);
818 associate: function(models) {
820 User.hasMany(models.ChatMessage);
821 User.hasMany(models.MailMessage);
822 User.hasMany(models.Contact);
823 User.hasMany(models.Action);
824 User.belongsToMany(models.Module, {
825 through: models.UserHasModule,
828 User.belongsToMany(models.MailRoom, {
829 through: models.UserHasMailRoom,
831 User.belongsToMany(models.Channel, {
832 through: 'user_has_channels'
834 User.belongsToMany(models.SmsRoom, {
835 through: 'user_has_sms_rooms'
837 User.belongsToMany(models.OpenchannelRoom, {
838 through: 'user_has_openchannel_rooms'
840 User.belongsToMany(models.FaxRoom, {
841 through: 'user_has_fax_rooms'
843 User.belongsToMany(models.Team, {
844 through: models.UserHasTeam
846 User.belongsToMany(models.VoiceQueue, {
847 through: models.UserHasVoiceQueue,
850 User.belongsToMany(models.VoiceQueue, {
851 through: models.UserHasVoiceQueuePermit,
854 User.belongsToMany(models.MailQueue, {
855 through: models.UserHasMailQueue,
858 User.belongsToMany(models.SmsQueue, {
859 through: models.UserHasSmsQueue,
862 User.belongsToMany(models.SmsQueue, {
863 through: models.UserHasSmsQueuePermit,
866 User.belongsToMany(models.OpenchannelQueue, {
867 through: models.UserHasOpenchannelQueue,
870 User.belongsToMany(models.OpenchannelQueue, {
871 through: models.UserHasOpenchannelQueuePermit,
872 as: 'POpenchannelQueues'
874 User.belongsToMany(models.MailQueue, {
875 through: models.UserHasMailQueuePermit,
878 User.belongsToMany(models.FaxQueue, {
879 through: models.UserHasFaxQueue,
882 User.belongsToMany(models.FaxQueue, {
883 through: models.UserHasFaxQueuePermit,
886 User.belongsToMany(models.ChatQueue, {
887 through: models.UserHasChatQueue,
890 User.belongsToMany(models.ChatQueue, {
891 through: models.UserHasChatQueuePermit,
894 User.belongsToMany(models.ChatRoom, {
895 through: models.UserHasChatRoom
897 User.belongsToMany(models.List, {
898 through: models.UserHasList
900 User.hasMany(models.VoiceExtension, {
901 foreignKey: 'UserId',
902 as: 'UserExtensions',
908 User.addScope('all', {
936 User.addScope('user', {
939 $in: ['admin', 'user']
966 User.addScope('agent', {
987 'openchannelCapacity',
990 'phoneBarAutoAnswer',
991 'phoneBarEnableSettings',
992 'phoneBarUnconditional',
995 'phoneBarUnconditionalNumber',
996 'phoneBarNoReplyNumber',
997 'phoneBarBusyNumber',
998 'phoneBarListenPort',
1000 'phoneBarRemoteControl',
1001 'phoneBarRemoteControlPort',
1002 'phoneBarEnableRecording',
1027 'phoneBarShowOmniDesktop',
1028 'phoneBarRingInUse',
1030 'phoneBarUnansweredCallBadge',
1033 'phonebarEnableDtmfTone',
1034 'phonebarAutoAnswerDelay'
1037 User.addScope('telephone', {
1042 User.addScope('queues', {
1044 model: models.VoiceQueue,
1047 model: models.ChatQueue,
1050 model: models.MailQueue,
1053 model: models.FaxQueue,
1056 model: models.SmsQueue,
1059 model: models.OpenchannelQueue,
1064 User.addScope('checkPauseStatus', function(query) {
1068 if (query.voicePause) {
1069 scope.where.voicePause = (query.voicePause === 'true') ?
1071 delete query.voicePause;
1072 } else if (query.faxPause) {
1073 scope.where.faxPause = (query.faxPause === 'true') ? true :
1075 delete query.faxPause;
1076 } else if (query.chatPause) {
1077 scope.where.chatPause = (query.chatPause === 'true') ?
1079 delete query.chatPause;
1080 } else if (query.mailPause) {
1081 scope.where.mailPause = (query.mailPause === 'true') ?
1083 delete query.mailPause;
1084 } else if (query.smsPause) {
1085 scope.where.smsPause = (query.smsPause === 'true') ?
1087 delete query.smsPause;
1088 } else if (query.openchannelPause) {
1089 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1091 delete query.openchannelPause;
1095 User.addScope('checkOnlineStatus', function(query) {
1100 scope.where.online = (query.online === 'true') ? true :
1102 delete query.online;
1106 User.addScope('checkSipStatus', function(query) {
1111 scope.where.status = query.status;
1112 delete query.status;
1116 User.addScope('checkQueueStatus', function(query) { //to be executed before checkOnlineStatus
1120 if (query.queueStatus) {
1121 if (query.queueStatus === 'paused') {
1122 scope.where.voicePause = true;
1124 scope.where.queueStatus = query.queueStatus;
1125 scope.where.voicePause = false;
1126 query.online = 'true';
1128 delete query.queueStatus;
1133 User.addScope('me', function(userId) {
1138 attributes: ['id', 'fullname', 'name', 'email', 'role', 'userpic', 'lastLoginAt', 'voicePause',
1146 'phoneBarRemoteControl',
1147 'phoneBarRemoteControlPort',
1150 'phonebarEnableDtmfTone',
1151 'phonebarAutoAnswerDelay'
1154 model: models.Module,
1155 attributes: ['id', 'path'],
1157 model: models.Module,
1158 attributes: ['id', 'path'],
1162 model: models.Module,
1163 attributes: ['id', 'path'],