3 var crypto = require('crypto');
4 var md5 = require('md5');
5 var _ = require('lodash');
6 var moment = require('moment');
7 var VoiceQueue = require('.').VoiceQueue;
9 module.exports = function(sequelize, DataTypes) {
10 var User = sequelize.define('User', {
12 type: DataTypes.STRING,
16 is: /^[A-Za-z0-9\.\_]+$/i
19 this.setDataValue('name', name);
20 this.setDataValue('defaultuser', name);
24 type: DataTypes.STRING,
29 type: DataTypes.STRING,
32 set: function(email) {
34 this.setDataValue('email', email.toLowerCase());
40 type: DataTypes.ENUM('admin', 'user', 'agent', 'telephone')
43 type: DataTypes.STRING,
48 set: function(password) {
49 this.salt = this.makeSalt();
50 this.setDataValue('password', this.encryptPassword(password));
51 this.setDataValue('md5secret', this.md5Password(this.name + ':asterisk:' + password));
55 type: DataTypes.STRING,
59 type: DataTypes.INTEGER(11),
61 set: function(internal) {
62 this.setDataValue('internal', internal);
63 this.setDataValue('accountcode', internal);
67 type: DataTypes.STRING
70 type: DataTypes.STRING
73 type: DataTypes.STRING
76 type: DataTypes.STRING
79 type: DataTypes.STRING
82 type: DataTypes.STRING
85 type: DataTypes.STRING
88 type: DataTypes.STRING
91 type: DataTypes.BOOLEAN,
98 type: DataTypes.STRING,
99 defaultValue: 'UNKNOWN'
105 type: DataTypes.STRING,
106 defaultValue: 'complete'
112 type: DataTypes.STRING
115 type: DataTypes.BOOLEAN,
117 set: function(voicePause) {
118 this.setDataValue('voicePause', voicePause);
120 this.setDataValue('queueStatus', 'paused');
121 this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
123 this.setDataValue('queueStatus', 'complete');
124 this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
129 type: DataTypes.BOOLEAN,
133 type: DataTypes.BOOLEAN,
137 type: DataTypes.BOOLEAN,
141 type: DataTypes.BOOLEAN,
145 type: DataTypes.BOOLEAN,
149 type: DataTypes.STRING,
150 defaultValue: 'Default Pause'
156 type: DataTypes.INTEGER,
160 type: DataTypes.INTEGER,
164 type: DataTypes.INTEGER,
168 type: DataTypes.INTEGER,
171 openchannelCapacity: {
172 type: DataTypes.INTEGER,
175 phoneBarAutoAnswer: {
176 type: DataTypes.BOOLEAN,
179 phoneBarEnableSettings: {
180 type: DataTypes.BOOLEAN,
183 phoneBarUnconditionalNumber: {
184 type: DataTypes.STRING,
186 if (this.getDataValue('phoneBarUnconditional')) {
187 return this.getDataValue('phoneBarUnconditionalNumber');
192 phoneBarNoReplyNumber: {
193 type: DataTypes.STRING,
195 if (this.getDataValue('phoneBarNoReply')) {
196 return this.getDataValue('phoneBarNoReplyNumber');
201 phoneBarBusyNumber: {
202 type: DataTypes.STRING,
204 if (this.getDataValue('phoneBarBusy')) {
205 return this.getDataValue('phoneBarBusyNumber');
210 phoneBarUnconditional: {
211 type: DataTypes.BOOLEAN,
215 type: DataTypes.BOOLEAN,
219 type: DataTypes.BOOLEAN,
222 phoneBarListenPort: {
223 type: DataTypes.INTEGER(5),
227 type: DataTypes.INTEGER(5),
231 type: DataTypes.INTEGER(5),
234 phoneBarNameServer: {
235 type: DataTypes.STRING,
238 phoneBarStunServer: {
239 type: DataTypes.STRING,
242 phoneBarVADEnabled: {
243 type: DataTypes.BOOLEAN,
247 type: DataTypes.BOOLEAN,
251 type: DataTypes.BOOLEAN,
255 type: DataTypes.INTEGER(5),
258 phoneBarPublishEnabled: {
259 type: DataTypes.BOOLEAN,
262 phoneBarRemoteControl: {
263 type: DataTypes.BOOLEAN,
266 phoneBarRemoteControlPort: {
267 type: DataTypes.INTEGER,
271 type: DataTypes.BOOLEAN,
275 type: DataTypes.STRING,
278 ipaddr: { //REALTIME ASTERISK
279 type: DataTypes.STRING,
282 port: { //REALTIME ASTERISK
283 type: DataTypes.INTEGER(5),
286 regseconds: { //REALTIME ASTERISK
287 type: DataTypes.INTEGER(11),
290 fullcontact: { //REALTIME ASTERISK
291 type: DataTypes.STRING,
294 regserver: { //REALTIME ASTERISK
295 type: DataTypes.STRING,
298 useragent: { //REALTIME ASTERISK
299 type: DataTypes.STRING,
302 lastms: { //REALTIME ASTERISK
303 type: DataTypes.INTEGER(11),
307 type: DataTypes.ENUM('friend', 'user', 'peer'),
309 defaultValue: 'friend'
312 type: DataTypes.STRING,
314 defaultValue: 'from-sip'
317 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
318 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
319 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
320 'PROHIB_FAILED_SCREEN', 'PROHIB'),
324 type: DataTypes.STRING,
328 type: DataTypes.STRING,
332 type: DataTypes.STRING,
336 type: DataTypes.STRING,
340 type: DataTypes.STRING,
344 type: DataTypes.STRING,
349 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
352 defaultValue: 'rfc2833'
355 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
360 type: DataTypes.ENUM('yes', 'no'),
365 type: DataTypes.STRING,
369 type: DataTypes.STRING,
373 type: DataTypes.STRING,
375 defaultValue: 'force_rport,comedia'
378 type: DataTypes.STRING,
381 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
382 type: DataTypes.STRING,
386 type: DataTypes.STRING,
389 namedpickupgroup: { //We can do call pick-p for named call group sales
390 type: DataTypes.STRING,
394 type: DataTypes.STRING,
399 type: DataTypes.STRING,
403 type: DataTypes.STRING,
405 defaultValue: 'alaw;ulaw;gsm'
408 type: DataTypes.STRING,
413 type: DataTypes.ENUM('yes', 'no'),
417 type: DataTypes.STRING,
419 defaultValue: 'port,invite'
422 type: DataTypes.ENUM('yes', 'no'),
427 type: DataTypes.ENUM('yes', 'no'),
432 type: DataTypes.ENUM('yes', 'no', 'never'),
436 type: DataTypes.ENUM('yes', 'no'),
440 type: DataTypes.ENUM('yes', 'no'),
444 type: DataTypes.INTEGER(11),
448 type: DataTypes.STRING,
452 type: DataTypes.STRING,
454 defaultValue: '"" <>'
457 type: DataTypes.STRING,
461 type: DataTypes.ENUM('yes', 'no'),
466 type: DataTypes.INTEGER(11),
470 type: DataTypes.ENUM('yes', 'no'),
474 type: DataTypes.ENUM('yes', 'no'),
478 type: DataTypes.ENUM('yes', 'no'),
482 type: DataTypes.ENUM('yes', 'no'),
486 type: DataTypes.STRING,
490 type: DataTypes.STRING,
494 type: DataTypes.ENUM('yes', 'no', 'always'),
499 type: DataTypes.INTEGER(11),
503 type: DataTypes.ENUM('yes', 'no'),
507 type: DataTypes.STRING,
511 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
515 type: DataTypes.INTEGER(11),
519 type: DataTypes.INTEGER(11),
523 type: DataTypes.ENUM('uac', 'uas'),
527 t38pt_usertpsource: {
528 type: DataTypes.STRING,
532 type: DataTypes.STRING,
536 type: DataTypes.STRING,
540 type: DataTypes.STRING,
544 type: DataTypes.STRING,
546 defaultValue: 'dynamic'
549 type: DataTypes.ENUM('yes', 'no'),
554 type: DataTypes.INTEGER(11),
558 type: DataTypes.STRING,
562 type: DataTypes.STRING,
565 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
566 type: DataTypes.INTEGER(11),
569 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
570 type: DataTypes.INTEGER(11),
573 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
574 type: DataTypes.INTEGER(11),
578 type: DataTypes.ENUM('yes', 'no'),
583 type: DataTypes.STRING,
587 type: DataTypes.STRING,
591 type: DataTypes.INTEGER(11),
595 type: DataTypes.INTEGER(11),
599 type: DataTypes.INTEGER(11),
603 type: DataTypes.STRING,
607 type: DataTypes.STRING,
611 type: DataTypes.STRING,
614 unsolicited_mailbox: {
615 type: DataTypes.STRING,
619 type: DataTypes.STRING,
623 type: DataTypes.INTEGER(11),
627 type: DataTypes.ENUM('yes', 'no'),
632 type: DataTypes.ENUM('yes', 'no'),
636 type: DataTypes.ENUM('yes', 'no'),
640 type: DataTypes.ENUM('yes', 'no'),
644 type: DataTypes.ENUM('yes', 'no'),
648 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
652 type: DataTypes.INTEGER(11),
656 type: DataTypes.STRING,
660 type: DataTypes.STRING,
664 type: DataTypes.STRING,
668 type: DataTypes.STRING,
672 type: DataTypes.STRING,
676 type: DataTypes.ENUM('active', 'passive', 'actpass'),
680 type: DataTypes.STRING,
683 usereqphone: { //This provider requires ";user=phone" on URI
684 type: DataTypes.ENUM('yes', 'no'),
688 recordonfeature: { //Feature to use when INFO with Record: on is received.
689 type: DataTypes.STRING,
692 recordofffeature: { //Feature to use when INFO with Record: off is received.
693 type: DataTypes.STRING,
697 type: DataTypes.INTEGER(11),
701 registertrying: { //Send a 100 Trying when the device registers.
702 type: DataTypes.ENUM('yes', 'no'),
705 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
706 type: DataTypes.ENUM('yes', 'no'),
709 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
710 type: DataTypes.STRING,
713 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
714 type: DataTypes.STRING,
717 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
718 type: DataTypes.STRING,
722 type: DataTypes.STRING,
726 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
731 type: DataTypes.BOOLEAN,
734 resetPasswordToken: {
735 type: DataTypes.STRING
737 resetPasswordExpires: {
740 phoneBarEnableRecording: {
741 type: DataTypes.BOOLEAN,
748 * Authenticate - check if the passwords are the same
750 * @param {String} plainText
751 * {function} callBack
754 authenticate: function(plainText) {
755 return this.encryptPassword(plainText) === this.password;
763 makeSalt: function() {
764 return crypto.randomBytes(16).toString('base64');
769 * @param {String} password
773 encryptPassword: function(password) {
774 if (!password || !this.salt) return '';
775 var salt = new Buffer(this.salt, 'base64');
776 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
782 * @param {String} password
786 md5Password: function(password) {
787 if (!password) return '';
788 return md5(password);
791 associate: function(models) {
793 User.hasMany(models.ChatMessage);
794 User.hasMany(models.MailMessage);
795 User.hasMany(models.Contact);
796 User.hasMany(models.Action);
797 User.belongsToMany(models.Module, {
798 through: models.UserHasModule,
801 User.belongsToMany(models.Channel, {
802 through: 'user_has_channels'
804 User.belongsToMany(models.MailRoom, {
805 through: 'user_has_mail_rooms'
807 User.belongsToMany(models.SmsRoom, {
808 through: 'user_has_sms_rooms'
810 User.belongsToMany(models.OpenchannelRoom, {
811 through: 'user_has_openchannel_rooms'
813 User.belongsToMany(models.FaxRoom, {
814 through: 'user_has_fax_rooms'
816 User.belongsToMany(models.Team, {
817 through: models.UserHasTeam
819 User.belongsToMany(models.VoiceQueue, {
820 through: models.UserHasVoiceQueue,
823 User.belongsToMany(models.VoiceQueue, {
824 through: models.UserHasVoiceQueuePermit,
827 User.belongsToMany(models.MailQueue, {
828 through: models.UserHasMailQueue,
831 User.belongsToMany(models.SmsQueue, {
832 through: models.UserHasSmsQueue,
835 User.belongsToMany(models.SmsQueue, {
836 through: models.UserHasSmsQueuePermit,
839 User.belongsToMany(models.OpenchannelQueue, {
840 through: models.UserHasOpenchannelQueue,
843 User.belongsToMany(models.OpenchannelQueue, {
844 through: models.UserHasOpenchannelQueuePermit,
845 as: 'POpenchannelQueues'
847 User.belongsToMany(models.MailQueue, {
848 through: models.UserHasMailQueuePermit,
851 User.belongsToMany(models.FaxQueue, {
852 through: models.UserHasFaxQueue,
855 User.belongsToMany(models.FaxQueue, {
856 through: models.UserHasFaxQueuePermit,
859 User.belongsToMany(models.ChatQueue, {
860 through: models.UserHasChatQueue,
863 User.belongsToMany(models.ChatQueue, {
864 through: models.UserHasChatQueuePermit,
867 User.belongsToMany(models.ChatRoom, {
868 through: models.UserHasChatRoom
870 User.belongsToMany(models.List, {
871 through: models.UserHasList
873 User.hasMany(models.VoiceExtension, {
874 foreignKey: 'UserId',
875 as: 'UserExtensions',
881 User.addScope('all', {
907 User.addScope('user', {
910 $in: ['admin', 'user']
935 User.addScope('agent', {
956 'openchannelCapacity',
959 'phoneBarAutoAnswer',
960 'phoneBarEnableSettings',
961 'phoneBarUnconditional',
964 'phoneBarUnconditionalNumber',
965 'phoneBarNoReplyNumber',
966 'phoneBarBusyNumber',
967 'phoneBarListenPort',
969 'phoneBarRemoteControl',
970 'phoneBarRemoteControlPort',
971 'phoneBarEnableRecording',
995 User.addScope('telephone', {
1000 User.addScope('queues', {
1001 include: [models.VoiceQueue, models.ChatQueue, models.MailQueue,
1002 models.FaxQueue, models.SmsQueue, models.OpenchannelQueue
1006 User.addScope('checkPauseStatus', function(query) {
1010 if (query.voicePause) {
1011 scope.where.voicePause = (query.voicePause === 'true') ?
1013 delete query.voicePause;
1014 } else if (query.faxPause) {
1015 scope.where.faxPause = (query.faxPause === 'true') ? true :
1017 delete query.faxPause;
1018 } else if (query.chatPause) {
1019 scope.where.chatPause = (query.chatPause === 'true') ?
1021 delete query.chatPause;
1022 } else if (query.mailPause) {
1023 scope.where.mailPause = (query.mailPause === 'true') ?
1025 delete query.mailPause;
1026 } else if (query.smsPause) {
1027 scope.where.smsPause = (query.smsPause === 'true') ?
1029 delete query.smsPause;
1030 } else if (query.openchannelPause) {
1031 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1033 delete query.openchannelPause;
1037 User.addScope('checkOnlineStatus', function(query) {
1042 scope.where.online = (query.online === 'true') ? true :
1044 delete query.online;
1048 User.addScope('checkSipStatus', function(query) {
1053 scope.where.status = query.status;
1054 delete query.status;
1058 User.addScope('checkQueueStatus', function(query) {
1062 if (query.queueStatus) {
1063 scope.where.queueStatus = query.queueStatus;
1064 delete query.queueStatus;