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 name = name.toLowerCase();
20 this.setDataValue('name', name);
21 this.setDataValue('defaultuser', name);
25 type: DataTypes.STRING,
30 type: DataTypes.STRING,
33 set: function(email) {
35 this.setDataValue('email', email.toLowerCase());
41 type: DataTypes.ENUM('admin', 'user', 'agent', 'telephone')
44 type: DataTypes.STRING,
49 set: function(password) {
50 this.salt = this.makeSalt();
51 this.setDataValue('password', this.encryptPassword(password));
52 this.setDataValue('md5secret', this.md5Password(this.name + ':asterisk:' + password));
56 type: DataTypes.STRING,
60 type: DataTypes.INTEGER(11),
62 set: function(internal) {
63 this.setDataValue('internal', internal);
64 this.setDataValue('accountcode', internal);
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.STRING
92 type: DataTypes.BOOLEAN,
99 type: DataTypes.STRING,
100 defaultValue: 'UNKNOWN'
106 type: DataTypes.STRING,
107 defaultValue: 'complete'
113 type: DataTypes.STRING
116 type: DataTypes.BOOLEAN,
118 set: function(voicePause) {
119 this.setDataValue('voicePause', voicePause);
121 this.setDataValue('queueStatus', 'paused');
122 this.setDataValue('queueStatusAt', moment().format(
123 "YYYY-MM-DD HH:mm:ss"));
125 this.setDataValue('queueStatus', 'complete');
126 this.setDataValue('queueStatusAt', moment().format(
127 "YYYY-MM-DD HH:mm:ss"));
132 type: DataTypes.BOOLEAN,
136 type: DataTypes.BOOLEAN,
140 type: DataTypes.BOOLEAN,
144 type: DataTypes.BOOLEAN,
148 type: DataTypes.STRING,
149 defaultValue: 'Default Pause'
155 type: DataTypes.INTEGER,
159 type: DataTypes.INTEGER,
163 type: DataTypes.INTEGER,
167 type: DataTypes.INTEGER,
170 phoneBarAutoAnswer: {
171 type: DataTypes.BOOLEAN,
174 phoneBarEnableSettings: {
175 type: DataTypes.BOOLEAN,
178 phoneBarUnconditionalNumber: {
179 type: DataTypes.STRING,
181 if (this.getDataValue('phoneBarUnconditional')) {
182 return this.getDataValue('phoneBarUnconditionalNumber');
187 phoneBarNoReplyNumber: {
188 type: DataTypes.STRING,
190 if (this.getDataValue('phoneBarNoReply')) {
191 return this.getDataValue('phoneBarNoReplyNumber');
196 phoneBarBusyNumber: {
197 type: DataTypes.STRING,
199 if (this.getDataValue('phoneBarBusy')) {
200 return this.getDataValue('phoneBarBusyNumber');
205 phoneBarUnconditional: {
206 type: DataTypes.BOOLEAN,
210 type: DataTypes.BOOLEAN,
214 type: DataTypes.BOOLEAN,
217 phoneBarListenPort: {
218 type: DataTypes.INTEGER(5),
222 type: DataTypes.INTEGER(5),
226 type: DataTypes.INTEGER(5),
229 phoneBarNameServer: {
230 type: DataTypes.STRING,
233 phoneBarStunServer: {
234 type: DataTypes.STRING,
237 phoneBarVADEnabled: {
238 type: DataTypes.BOOLEAN,
242 type: DataTypes.BOOLEAN,
246 type: DataTypes.BOOLEAN,
250 type: DataTypes.INTEGER(5),
253 phoneBarPublishEnabled: {
254 type: DataTypes.BOOLEAN,
257 phoneBarRemoteControl: {
258 type: DataTypes.BOOLEAN,
261 phoneBarRemoteControlPort: {
262 type: DataTypes.INTEGER,
266 type: DataTypes.BOOLEAN,
270 type: DataTypes.STRING,
273 ipaddr: { //REALTIME ASTERISK
274 type: DataTypes.STRING,
277 port: { //REALTIME ASTERISK
278 type: DataTypes.INTEGER(5),
281 regseconds: { //REALTIME ASTERISK
282 type: DataTypes.INTEGER(11),
285 fullcontact: { //REALTIME ASTERISK
286 type: DataTypes.STRING,
289 regserver: { //REALTIME ASTERISK
290 type: DataTypes.STRING,
293 useragent: { //REALTIME ASTERISK
294 type: DataTypes.STRING,
297 lastms: { //REALTIME ASTERISK
298 type: DataTypes.INTEGER(11),
302 type: DataTypes.ENUM('friend', 'user', 'peer'),
304 defaultValue: 'friend'
307 type: DataTypes.STRING,
309 defaultValue: 'from-sip'
312 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
313 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
314 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
315 'PROHIB_FAILED_SCREEN', 'PROHIB'),
319 type: DataTypes.STRING,
323 type: DataTypes.STRING,
327 type: DataTypes.STRING,
331 type: DataTypes.STRING,
335 type: DataTypes.STRING,
339 type: DataTypes.STRING,
344 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
347 defaultValue: 'rfc2833'
350 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
355 type: DataTypes.ENUM('yes', 'no'),
360 type: DataTypes.STRING,
364 type: DataTypes.STRING,
368 type: DataTypes.STRING,
370 defaultValue: 'force_rport,comedia'
373 type: DataTypes.STRING,
376 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
377 type: DataTypes.STRING,
381 type: DataTypes.STRING,
384 namedpickupgroup: { //We can do call pick-p for named call group sales
385 type: DataTypes.STRING,
389 type: DataTypes.STRING,
394 type: DataTypes.STRING,
398 type: DataTypes.STRING,
400 defaultValue: 'alaw;ulaw;gsm'
403 type: DataTypes.STRING,
408 type: DataTypes.ENUM('yes', 'no'),
412 type: DataTypes.STRING,
414 defaultValue: 'port,invite'
417 type: DataTypes.ENUM('yes', 'no'),
422 type: DataTypes.ENUM('yes', 'no'),
427 type: DataTypes.ENUM('yes', 'no', 'never'),
431 type: DataTypes.ENUM('yes', 'no'),
435 type: DataTypes.ENUM('yes', 'no'),
439 type: DataTypes.INTEGER(11),
443 type: DataTypes.STRING,
447 type: DataTypes.STRING,
449 defaultValue: '"" <>'
452 type: DataTypes.STRING,
456 type: DataTypes.ENUM('yes', 'no'),
461 type: DataTypes.INTEGER(11),
465 type: DataTypes.ENUM('yes', 'no'),
469 type: DataTypes.ENUM('yes', 'no'),
473 type: DataTypes.ENUM('yes', 'no'),
477 type: DataTypes.ENUM('yes', 'no'),
481 type: DataTypes.STRING,
485 type: DataTypes.STRING,
489 type: DataTypes.ENUM('yes', 'no', 'always'),
494 type: DataTypes.INTEGER(11),
498 type: DataTypes.ENUM('yes', 'no'),
502 type: DataTypes.STRING,
506 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
510 type: DataTypes.INTEGER(11),
514 type: DataTypes.INTEGER(11),
518 type: DataTypes.ENUM('uac', 'uas'),
522 t38pt_usertpsource: {
523 type: DataTypes.STRING,
527 type: DataTypes.STRING,
531 type: DataTypes.STRING,
535 type: DataTypes.STRING,
539 type: DataTypes.STRING,
541 defaultValue: 'dynamic'
544 type: DataTypes.ENUM('yes', 'no'),
549 type: DataTypes.INTEGER(11),
553 type: DataTypes.STRING,
557 type: DataTypes.STRING,
560 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
561 type: DataTypes.INTEGER(11),
564 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
565 type: DataTypes.INTEGER(11),
568 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
569 type: DataTypes.INTEGER(11),
573 type: DataTypes.ENUM('yes', 'no'),
578 type: DataTypes.STRING,
582 type: DataTypes.STRING,
586 type: DataTypes.INTEGER(11),
590 type: DataTypes.INTEGER(11),
594 type: DataTypes.INTEGER(11),
598 type: DataTypes.STRING,
602 type: DataTypes.STRING,
606 type: DataTypes.STRING,
609 unsolicited_mailbox: {
610 type: DataTypes.STRING,
614 type: DataTypes.STRING,
618 type: DataTypes.INTEGER(11),
622 type: DataTypes.ENUM('yes', 'no'),
627 type: DataTypes.ENUM('yes', 'no'),
631 type: DataTypes.ENUM('yes', 'no'),
635 type: DataTypes.ENUM('yes', 'no'),
639 type: DataTypes.ENUM('yes', 'no'),
643 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
647 type: DataTypes.INTEGER(11),
651 type: DataTypes.STRING,
655 type: DataTypes.STRING,
659 type: DataTypes.STRING,
663 type: DataTypes.STRING,
667 type: DataTypes.STRING,
671 type: DataTypes.ENUM('active', 'passive', 'actpass'),
675 type: DataTypes.STRING,
678 usereqphone: { //This provider requires ";user=phone" on URI
679 type: DataTypes.ENUM('yes', 'no'),
683 recordonfeature: { //Feature to use when INFO with Record: on is received.
684 type: DataTypes.STRING,
687 recordofffeature: { //Feature to use when INFO with Record: off is received.
688 type: DataTypes.STRING,
692 type: DataTypes.INTEGER(11),
696 registertrying: { //Send a 100 Trying when the device registers.
697 type: DataTypes.ENUM('yes', 'no'),
700 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
701 type: DataTypes.ENUM('yes', 'no'),
704 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
705 type: DataTypes.STRING,
708 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
709 type: DataTypes.STRING,
712 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
713 type: DataTypes.STRING,
717 type: DataTypes.STRING,
721 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
729 * Authenticate - check if the passwords are the same
731 * @param {String} plainText
732 * {function} callBack
735 authenticate: function(plainText) {
736 return this.encryptPassword(plainText) === this.password;
744 makeSalt: function() {
745 return crypto.randomBytes(16).toString('base64');
750 * @param {String} password
754 encryptPassword: function(password) {
755 if (!password || !this.salt) return '';
756 var salt = new Buffer(this.salt, 'base64');
757 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
763 * @param {String} password
767 md5Password: function(password) {
768 if (!password) return '';
769 return md5(password);
772 associate: function(models) {
774 User.hasMany(models.ChatMessage);
775 User.hasMany(models.MailMessage);
776 User.hasMany(models.Contact);
777 User.hasMany(models.Action);
778 User.belongsToMany(models.Module, {
779 through: models.UserHasModule,
782 User.belongsToMany(models.Channel, {
783 through: 'user_has_channels'
785 User.belongsToMany(models.MailRoom, {
786 through: 'user_has_mail_rooms'
788 User.belongsToMany(models.SmsRoom, {
789 through: 'user_has_sms_rooms'
791 User.belongsToMany(models.FaxRoom, {
792 through: 'user_has_fax_rooms'
794 User.belongsToMany(models.Team, {
795 through: models.UserHasTeam
797 User.belongsToMany(models.VoiceQueue, {
798 through: models.UserHasVoiceQueue,
801 User.belongsToMany(models.VoiceQueue, {
802 through: models.UserHasVoiceQueuePermit,
805 User.belongsToMany(models.MailQueue, {
806 through: models.UserHasMailQueue,
809 User.belongsToMany(models.SmsQueue, {
810 through: models.UserHasSmsQueue,
813 User.belongsToMany(models.SmsQueue, {
814 through: models.UserHasSmsQueuePermit,
818 User.belongsToMany(models.MailQueue, {
819 through: models.UserHasMailQueuePermit,
822 User.belongsToMany(models.FaxQueue, {
823 through: models.UserHasFaxQueue,
826 User.belongsToMany(models.FaxQueue, {
827 through: models.UserHasFaxQueuePermit,
830 User.belongsToMany(models.ChatQueue, {
831 through: models.UserHasChatQueue,
834 User.belongsToMany(models.ChatQueue, {
835 through: models.UserHasChatQueuePermit,
838 User.belongsToMany(models.ChatRoom, {
839 through: models.UserHasChatRoom
841 User.belongsToMany(models.List, {
842 through: models.UserHasList
844 User.hasMany(models.VoiceExtension, {
845 foreignKey: 'UserId',
846 as: 'UserExtensions',
852 User.addScope('all', {
878 User.addScope('user', {
881 $in: ['admin', 'user']
906 User.addScope('agent', {
929 'phoneBarAutoAnswer',
930 'phoneBarEnableSettings',
931 'phoneBarUnconditional',
934 'phoneBarUnconditionalNumber',
935 'phoneBarNoReplyNumber',
936 'phoneBarBusyNumber',
937 'phoneBarListenPort',
939 'phoneBarRemoteControl',
940 'phoneBarRemoteControlPort',
962 User.addScope('telephone', {
967 User.addScope('queues', {
968 include: [models.VoiceQueue, models.ChatQueue, models.MailQueue,
969 models.FaxQueue, models.SmsQueue
973 User.addScope('checkPauseStatus', function(query) {
977 if (query.voicePause) {
978 scope.where.voicePause = (query.voicePause === 'true') ?
980 delete query.voicePause;
981 } else if (query.faxPause) {
982 scope.where.faxPause = (query.faxPause === 'true') ? true :
984 delete query.faxPause;
985 } else if (query.chatPause) {
986 scope.where.chatPause = (query.chatPause === 'true') ?
988 delete query.chatPause;
989 } else if (query.mailPause) {
990 scope.where.mailPause = (query.mailPause === 'true') ?
992 delete query.mailPause;
993 } else if (query.smsPause) {
994 scope.where.smsPause = (query.smsPause === 'true') ?
996 delete query.smsPause;
1000 User.addScope('checkOnlineStatus', function(query) {
1005 scope.where.online = (query.online === 'true') ? true :
1007 delete query.online;
1011 User.addScope('checkSipStatus', function(query) {
1016 scope.where.status = query.status;
1017 delete query.status;
1021 User.addScope('checkQueueStatus', function(query) {
1025 if (query.queueStatus) {
1026 scope.where.queueStatus = query.queueStatus;
1027 delete query.queueStatus;