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: {
744 * Authenticate - check if the passwords are the same
746 * @param {String} plainText
747 * {function} callBack
750 authenticate: function(plainText) {
751 return this.encryptPassword(plainText) === this.password;
759 makeSalt: function() {
760 return crypto.randomBytes(16).toString('base64');
765 * @param {String} password
769 encryptPassword: function(password) {
770 if (!password || !this.salt) return '';
771 var salt = new Buffer(this.salt, 'base64');
772 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
778 * @param {String} password
782 md5Password: function(password) {
783 if (!password) return '';
784 return md5(password);
787 associate: function(models) {
789 User.hasMany(models.ChatMessage);
790 User.hasMany(models.MailMessage);
791 User.hasMany(models.Contact);
792 User.hasMany(models.Action);
793 User.belongsToMany(models.Module, {
794 through: models.UserHasModule,
797 User.belongsToMany(models.Channel, {
798 through: 'user_has_channels'
800 User.belongsToMany(models.MailRoom, {
801 through: 'user_has_mail_rooms'
803 User.belongsToMany(models.SmsRoom, {
804 through: 'user_has_sms_rooms'
806 User.belongsToMany(models.OpenchannelRoom, {
807 through: 'user_has_openchannel_rooms'
809 User.belongsToMany(models.FaxRoom, {
810 through: 'user_has_fax_rooms'
812 User.belongsToMany(models.Team, {
813 through: models.UserHasTeam
815 User.belongsToMany(models.VoiceQueue, {
816 through: models.UserHasVoiceQueue,
819 User.belongsToMany(models.VoiceQueue, {
820 through: models.UserHasVoiceQueuePermit,
823 User.belongsToMany(models.MailQueue, {
824 through: models.UserHasMailQueue,
827 User.belongsToMany(models.SmsQueue, {
828 through: models.UserHasSmsQueue,
831 User.belongsToMany(models.SmsQueue, {
832 through: models.UserHasSmsQueuePermit,
835 User.belongsToMany(models.OpenchannelQueue, {
836 through: models.UserHasOpenchannelQueue,
839 User.belongsToMany(models.OpenchannelQueue, {
840 through: models.UserHasOpenchannelQueuePermit,
841 as: 'POpenchannelQueues'
843 User.belongsToMany(models.MailQueue, {
844 through: models.UserHasMailQueuePermit,
847 User.belongsToMany(models.FaxQueue, {
848 through: models.UserHasFaxQueue,
851 User.belongsToMany(models.FaxQueue, {
852 through: models.UserHasFaxQueuePermit,
855 User.belongsToMany(models.ChatQueue, {
856 through: models.UserHasChatQueue,
859 User.belongsToMany(models.ChatQueue, {
860 through: models.UserHasChatQueuePermit,
863 User.belongsToMany(models.ChatRoom, {
864 through: models.UserHasChatRoom
866 User.belongsToMany(models.List, {
867 through: models.UserHasList
869 User.hasMany(models.VoiceExtension, {
870 foreignKey: 'UserId',
871 as: 'UserExtensions',
877 User.addScope('all', {
903 User.addScope('user', {
906 $in: ['admin', 'user']
931 User.addScope('agent', {
952 'openchannelCapacity',
955 'phoneBarAutoAnswer',
956 'phoneBarEnableSettings',
957 'phoneBarUnconditional',
960 'phoneBarUnconditionalNumber',
961 'phoneBarNoReplyNumber',
962 'phoneBarBusyNumber',
963 'phoneBarListenPort',
965 'phoneBarRemoteControl',
966 'phoneBarRemoteControlPort',
990 User.addScope('telephone', {
995 User.addScope('queues', {
996 include: [models.VoiceQueue, models.ChatQueue, models.MailQueue,
997 models.FaxQueue, models.SmsQueue, models.OpenchannelQueue
1001 User.addScope('checkPauseStatus', function(query) {
1005 if (query.voicePause) {
1006 scope.where.voicePause = (query.voicePause === 'true') ?
1008 delete query.voicePause;
1009 } else if (query.faxPause) {
1010 scope.where.faxPause = (query.faxPause === 'true') ? true :
1012 delete query.faxPause;
1013 } else if (query.chatPause) {
1014 scope.where.chatPause = (query.chatPause === 'true') ?
1016 delete query.chatPause;
1017 } else if (query.mailPause) {
1018 scope.where.mailPause = (query.mailPause === 'true') ?
1020 delete query.mailPause;
1021 } else if (query.smsPause) {
1022 scope.where.smsPause = (query.smsPause === 'true') ?
1024 delete query.smsPause;
1025 } else if (query.openchannelPause) {
1026 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1028 delete query.openchannelPause;
1032 User.addScope('checkOnlineStatus', function(query) {
1037 scope.where.online = (query.online === 'true') ? true :
1039 delete query.online;
1043 User.addScope('checkSipStatus', function(query) {
1048 scope.where.status = query.status;
1049 delete query.status;
1053 User.addScope('checkQueueStatus', function(query) {
1057 if (query.queueStatus) {
1058 scope.where.queueStatus = query.queueStatus;
1059 delete query.queueStatus;