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(
122 "YYYY-MM-DD HH:mm:ss"));
124 this.setDataValue('queueStatus', 'complete');
125 this.setDataValue('queueStatusAt', moment().format(
126 "YYYY-MM-DD HH:mm:ss"));
131 type: DataTypes.BOOLEAN,
135 type: DataTypes.BOOLEAN,
139 type: DataTypes.BOOLEAN,
143 type: DataTypes.BOOLEAN,
147 type: DataTypes.BOOLEAN,
151 type: DataTypes.STRING,
152 defaultValue: 'Default Pause'
158 type: DataTypes.INTEGER,
162 type: DataTypes.INTEGER,
166 type: DataTypes.INTEGER,
170 type: DataTypes.INTEGER,
173 openchannelCapacity: {
174 type: DataTypes.INTEGER,
177 phoneBarAutoAnswer: {
178 type: DataTypes.BOOLEAN,
181 phoneBarEnableSettings: {
182 type: DataTypes.BOOLEAN,
185 phoneBarUnconditionalNumber: {
186 type: DataTypes.STRING,
188 if (this.getDataValue('phoneBarUnconditional')) {
189 return this.getDataValue('phoneBarUnconditionalNumber');
194 phoneBarNoReplyNumber: {
195 type: DataTypes.STRING,
197 if (this.getDataValue('phoneBarNoReply')) {
198 return this.getDataValue('phoneBarNoReplyNumber');
203 phoneBarBusyNumber: {
204 type: DataTypes.STRING,
206 if (this.getDataValue('phoneBarBusy')) {
207 return this.getDataValue('phoneBarBusyNumber');
212 phoneBarUnconditional: {
213 type: DataTypes.BOOLEAN,
217 type: DataTypes.BOOLEAN,
221 type: DataTypes.BOOLEAN,
224 phoneBarListenPort: {
225 type: DataTypes.INTEGER(5),
229 type: DataTypes.INTEGER(5),
233 type: DataTypes.INTEGER(5),
236 phoneBarNameServer: {
237 type: DataTypes.STRING,
240 phoneBarStunServer: {
241 type: DataTypes.STRING,
244 phoneBarVADEnabled: {
245 type: DataTypes.BOOLEAN,
249 type: DataTypes.BOOLEAN,
253 type: DataTypes.BOOLEAN,
257 type: DataTypes.INTEGER(5),
260 phoneBarPublishEnabled: {
261 type: DataTypes.BOOLEAN,
264 phoneBarRemoteControl: {
265 type: DataTypes.BOOLEAN,
268 phoneBarRemoteControlPort: {
269 type: DataTypes.INTEGER,
273 type: DataTypes.BOOLEAN,
277 type: DataTypes.STRING,
280 ipaddr: { //REALTIME ASTERISK
281 type: DataTypes.STRING,
284 port: { //REALTIME ASTERISK
285 type: DataTypes.INTEGER(5),
288 regseconds: { //REALTIME ASTERISK
289 type: DataTypes.INTEGER(11),
292 fullcontact: { //REALTIME ASTERISK
293 type: DataTypes.STRING,
296 regserver: { //REALTIME ASTERISK
297 type: DataTypes.STRING,
300 useragent: { //REALTIME ASTERISK
301 type: DataTypes.STRING,
304 lastms: { //REALTIME ASTERISK
305 type: DataTypes.INTEGER(11),
309 type: DataTypes.ENUM('friend', 'user', 'peer'),
311 defaultValue: 'friend'
314 type: DataTypes.STRING,
316 defaultValue: 'from-sip'
319 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
320 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
321 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
322 'PROHIB_FAILED_SCREEN', 'PROHIB'),
326 type: DataTypes.STRING,
330 type: DataTypes.STRING,
334 type: DataTypes.STRING,
338 type: DataTypes.STRING,
342 type: DataTypes.STRING,
346 type: DataTypes.STRING,
351 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
354 defaultValue: 'rfc2833'
357 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
362 type: DataTypes.ENUM('yes', 'no'),
367 type: DataTypes.STRING,
371 type: DataTypes.STRING,
375 type: DataTypes.STRING,
377 defaultValue: 'force_rport,comedia'
380 type: DataTypes.STRING,
383 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
384 type: DataTypes.STRING,
388 type: DataTypes.STRING,
391 namedpickupgroup: { //We can do call pick-p for named call group sales
392 type: DataTypes.STRING,
396 type: DataTypes.STRING,
401 type: DataTypes.STRING,
405 type: DataTypes.STRING,
407 defaultValue: 'alaw;ulaw;gsm'
410 type: DataTypes.STRING,
415 type: DataTypes.ENUM('yes', 'no'),
419 type: DataTypes.STRING,
421 defaultValue: 'port,invite'
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.STRING,
548 defaultValue: 'dynamic'
551 type: DataTypes.ENUM('yes', 'no'),
556 type: DataTypes.INTEGER(11),
560 type: DataTypes.STRING,
564 type: DataTypes.STRING,
567 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
568 type: DataTypes.INTEGER(11),
571 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
572 type: DataTypes.INTEGER(11),
575 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
576 type: DataTypes.INTEGER(11),
580 type: DataTypes.ENUM('yes', 'no'),
585 type: DataTypes.STRING,
589 type: DataTypes.STRING,
593 type: DataTypes.INTEGER(11),
597 type: DataTypes.INTEGER(11),
601 type: DataTypes.INTEGER(11),
605 type: DataTypes.STRING,
609 type: DataTypes.STRING,
613 type: DataTypes.STRING,
616 unsolicited_mailbox: {
617 type: DataTypes.STRING,
621 type: DataTypes.STRING,
625 type: DataTypes.INTEGER(11),
629 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'),
650 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
654 type: DataTypes.INTEGER(11),
658 type: DataTypes.STRING,
662 type: DataTypes.STRING,
666 type: DataTypes.STRING,
670 type: DataTypes.STRING,
674 type: DataTypes.STRING,
678 type: DataTypes.ENUM('active', 'passive', 'actpass'),
682 type: DataTypes.STRING,
685 usereqphone: { //This provider requires ";user=phone" on URI
686 type: DataTypes.ENUM('yes', 'no'),
690 recordonfeature: { //Feature to use when INFO with Record: on is received.
691 type: DataTypes.STRING,
694 recordofffeature: { //Feature to use when INFO with Record: off is received.
695 type: DataTypes.STRING,
699 type: DataTypes.INTEGER(11),
703 registertrying: { //Send a 100 Trying when the device registers.
704 type: DataTypes.ENUM('yes', 'no'),
707 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
708 type: DataTypes.ENUM('yes', 'no'),
711 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
712 type: DataTypes.STRING,
715 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
716 type: DataTypes.STRING,
719 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
720 type: DataTypes.STRING,
724 type: DataTypes.STRING,
728 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
736 * Authenticate - check if the passwords are the same
738 * @param {String} plainText
739 * {function} callBack
742 authenticate: function(plainText) {
743 return this.encryptPassword(plainText) === this.password;
751 makeSalt: function() {
752 return crypto.randomBytes(16).toString('base64');
757 * @param {String} password
761 encryptPassword: function(password) {
762 if (!password || !this.salt) return '';
763 var salt = new Buffer(this.salt, 'base64');
764 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
770 * @param {String} password
774 md5Password: function(password) {
775 if (!password) return '';
776 return md5(password);
779 associate: function(models) {
781 User.hasMany(models.ChatMessage);
782 User.hasMany(models.MailMessage);
783 User.hasMany(models.Contact);
784 User.hasMany(models.Action);
785 User.belongsToMany(models.Module, {
786 through: models.UserHasModule,
789 User.belongsToMany(models.Channel, {
790 through: 'user_has_channels'
792 User.belongsToMany(models.MailRoom, {
793 through: 'user_has_mail_rooms'
795 User.belongsToMany(models.SmsRoom, {
796 through: 'user_has_sms_rooms'
798 User.belongsToMany(models.OpenchannelRoom, {
799 through: 'user_has_openchannel_rooms'
801 User.belongsToMany(models.FaxRoom, {
802 through: 'user_has_fax_rooms'
804 User.belongsToMany(models.Team, {
805 through: models.UserHasTeam
807 User.belongsToMany(models.VoiceQueue, {
808 through: models.UserHasVoiceQueue,
811 User.belongsToMany(models.VoiceQueue, {
812 through: models.UserHasVoiceQueuePermit,
815 User.belongsToMany(models.MailQueue, {
816 through: models.UserHasMailQueue,
819 User.belongsToMany(models.SmsQueue, {
820 through: models.UserHasSmsQueue,
823 User.belongsToMany(models.SmsQueue, {
824 through: models.UserHasSmsQueuePermit,
827 User.belongsToMany(models.OpenchannelQueue, {
828 through: models.UserHasOpenchannelQueue,
831 User.belongsToMany(models.OpenchannelQueue, {
832 through: models.UserHasOpenchannelQueuePermit,
833 as: 'POpenchannelQueues'
835 User.belongsToMany(models.MailQueue, {
836 through: models.UserHasMailQueuePermit,
839 User.belongsToMany(models.FaxQueue, {
840 through: models.UserHasFaxQueue,
843 User.belongsToMany(models.FaxQueue, {
844 through: models.UserHasFaxQueuePermit,
847 User.belongsToMany(models.ChatQueue, {
848 through: models.UserHasChatQueue,
851 User.belongsToMany(models.ChatQueue, {
852 through: models.UserHasChatQueuePermit,
855 User.belongsToMany(models.ChatRoom, {
856 through: models.UserHasChatRoom
858 User.belongsToMany(models.List, {
859 through: models.UserHasList
861 User.hasMany(models.VoiceExtension, {
862 foreignKey: 'UserId',
863 as: 'UserExtensions',
869 User.addScope('all', {
895 User.addScope('user', {
898 $in: ['admin', 'user']
923 User.addScope('agent', {
944 'openchannelCapacity',
947 'phoneBarAutoAnswer',
948 'phoneBarEnableSettings',
949 'phoneBarUnconditional',
952 'phoneBarUnconditionalNumber',
953 'phoneBarNoReplyNumber',
954 'phoneBarBusyNumber',
955 'phoneBarListenPort',
957 'phoneBarRemoteControl',
958 'phoneBarRemoteControlPort',
981 User.addScope('telephone', {
986 User.addScope('queues', {
987 include: [models.VoiceQueue, models.ChatQueue, models.MailQueue,
988 models.FaxQueue, models.SmsQueue, models.OpenchannelQueue
992 User.addScope('checkPauseStatus', function(query) {
996 if (query.voicePause) {
997 scope.where.voicePause = (query.voicePause === 'true') ?
999 delete query.voicePause;
1000 } else if (query.faxPause) {
1001 scope.where.faxPause = (query.faxPause === 'true') ? true :
1003 delete query.faxPause;
1004 } else if (query.chatPause) {
1005 scope.where.chatPause = (query.chatPause === 'true') ?
1007 delete query.chatPause;
1008 } else if (query.mailPause) {
1009 scope.where.mailPause = (query.mailPause === 'true') ?
1011 delete query.mailPause;
1012 } else if (query.smsPause) {
1013 scope.where.smsPause = (query.smsPause === 'true') ?
1015 delete query.smsPause;
1016 } else if (query.openchannelPause) {
1017 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1019 delete query.openchannelPause;
1023 User.addScope('checkOnlineStatus', function(query) {
1028 scope.where.online = (query.online === 'true') ? true :
1030 delete query.online;
1034 User.addScope('checkSipStatus', function(query) {
1039 scope.where.status = query.status;
1040 delete query.status;
1044 User.addScope('checkQueueStatus', function(query) {
1048 if (query.queueStatus) {
1049 scope.where.queueStatus = query.queueStatus;
1050 delete query.queueStatus;