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,
28 type: DataTypes.STRING,
31 set: function(email) {
33 this.setDataValue('email', email.toLowerCase());
39 type: DataTypes.ENUM('admin', 'user', 'agent', 'telephone')
42 type: DataTypes.STRING,
47 set: function(password) {
48 this.salt = this.makeSalt();
49 this.setDataValue('password', this.encryptPassword(password));
50 this.setDataValue('md5secret', this.md5Password(this.name +
51 ':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.STRING,
148 defaultValue: 'Default Pause'
154 type: DataTypes.INTEGER,
158 type: DataTypes.INTEGER,
162 type: DataTypes.INTEGER,
166 type: DataTypes.INTEGER,
169 phoneBarAutoAnswer: {
170 type: DataTypes.BOOLEAN,
173 phoneBarEnableSettings: {
174 type: DataTypes.BOOLEAN,
177 phoneBarUnconditionalNumber: {
178 type: DataTypes.STRING,
180 if (this.getDataValue('phoneBarUnconditional')) {
181 return this.getDataValue('phoneBarUnconditionalNumber');
186 phoneBarNoReplyNumber: {
187 type: DataTypes.STRING,
189 if (this.getDataValue('phoneBarNoReply')) {
190 return this.getDataValue('phoneBarNoReplyNumber');
195 phoneBarBusyNumber: {
196 type: DataTypes.STRING,
198 if (this.getDataValue('phoneBarBusy')) {
199 return this.getDataValue('phoneBarBusyNumber');
204 phoneBarUnconditional: {
205 type: DataTypes.BOOLEAN,
209 type: DataTypes.BOOLEAN,
213 type: DataTypes.BOOLEAN,
216 phoneBarListenPort: {
217 type: DataTypes.INTEGER(5),
221 type: DataTypes.INTEGER(5),
225 type: DataTypes.INTEGER(5),
228 phoneBarNameServer: {
229 type: DataTypes.STRING,
232 phoneBarStunServer: {
233 type: DataTypes.STRING,
236 phoneBarVADEnabled: {
237 type: DataTypes.BOOLEAN,
241 type: DataTypes.BOOLEAN,
245 type: DataTypes.BOOLEAN,
249 type: DataTypes.INTEGER(5),
252 phoneBarPublishEnabled: {
253 type: DataTypes.BOOLEAN,
257 type: DataTypes.BOOLEAN,
261 type: DataTypes.STRING,
264 ipaddr: { //REALTIME ASTERISK
265 type: DataTypes.STRING,
268 port: { //REALTIME ASTERISK
269 type: DataTypes.INTEGER(5),
272 regseconds: { //REALTIME ASTERISK
273 type: DataTypes.INTEGER(11),
276 fullcontact: { //REALTIME ASTERISK
277 type: DataTypes.STRING,
280 regserver: { //REALTIME ASTERISK
281 type: DataTypes.STRING,
284 useragent: { //REALTIME ASTERISK
285 type: DataTypes.STRING,
288 lastms: { //REALTIME ASTERISK
289 type: DataTypes.INTEGER(11),
293 type: DataTypes.ENUM('friend', 'user', 'peer'),
295 defaultValue: 'friend'
298 type: DataTypes.STRING,
300 defaultValue: 'from-sip'
303 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
304 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
305 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
306 'PROHIB_FAILED_SCREEN', 'PROHIB'),
310 type: DataTypes.STRING,
314 type: DataTypes.STRING,
318 type: DataTypes.STRING,
322 type: DataTypes.STRING,
326 type: DataTypes.STRING,
330 type: DataTypes.STRING,
335 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
338 defaultValue: 'rfc2833'
341 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
346 type: DataTypes.ENUM('yes', 'no'),
351 type: DataTypes.STRING,
355 type: DataTypes.STRING,
359 type: DataTypes.STRING,
361 defaultValue: 'force_rport,comedia'
364 type: DataTypes.STRING,
367 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
368 type: DataTypes.STRING,
372 type: DataTypes.STRING,
375 namedpickupgroup: { //We can do call pick-p for named call group sales
376 type: DataTypes.STRING,
380 type: DataTypes.STRING,
385 type: DataTypes.STRING,
389 type: DataTypes.STRING,
391 defaultValue: 'alaw;ulaw;gsm'
394 type: DataTypes.STRING,
399 type: DataTypes.ENUM('yes', 'no'),
403 type: DataTypes.STRING,
405 defaultValue: 'port,invite'
408 type: DataTypes.ENUM('yes', 'no'),
413 type: DataTypes.ENUM('yes', 'no'),
418 type: DataTypes.ENUM('yes', 'no', 'never'),
422 type: DataTypes.ENUM('yes', 'no'),
426 type: DataTypes.ENUM('yes', 'no'),
430 type: DataTypes.INTEGER(11),
434 type: DataTypes.STRING,
438 type: DataTypes.STRING,
440 defaultValue: '"" <>'
443 type: DataTypes.STRING,
447 type: DataTypes.ENUM('yes', 'no'),
452 type: DataTypes.INTEGER(11),
456 type: DataTypes.ENUM('yes', 'no'),
460 type: DataTypes.ENUM('yes', 'no'),
464 type: DataTypes.ENUM('yes', 'no'),
468 type: DataTypes.ENUM('yes', 'no'),
472 type: DataTypes.STRING,
476 type: DataTypes.STRING,
480 type: DataTypes.ENUM('yes', 'no', 'always'),
485 type: DataTypes.INTEGER(11),
489 type: DataTypes.ENUM('yes', 'no'),
493 type: DataTypes.STRING,
497 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
501 type: DataTypes.INTEGER(11),
505 type: DataTypes.INTEGER(11),
509 type: DataTypes.ENUM('uac', 'uas'),
513 t38pt_usertpsource: {
514 type: DataTypes.STRING,
518 type: DataTypes.STRING,
522 type: DataTypes.STRING,
526 type: DataTypes.STRING,
530 type: DataTypes.STRING,
532 defaultValue: 'dynamic'
535 type: DataTypes.ENUM('yes', 'no'),
540 type: DataTypes.INTEGER(11),
544 type: DataTypes.STRING,
548 type: DataTypes.STRING,
551 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
552 type: DataTypes.INTEGER(11),
555 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
556 type: DataTypes.INTEGER(11),
559 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
560 type: DataTypes.INTEGER(11),
564 type: DataTypes.ENUM('yes', 'no'),
569 type: DataTypes.STRING,
573 type: DataTypes.STRING,
577 type: DataTypes.INTEGER(11),
581 type: DataTypes.INTEGER(11),
585 type: DataTypes.INTEGER(11),
589 type: DataTypes.STRING,
593 type: DataTypes.STRING,
597 type: DataTypes.STRING,
600 unsolicited_mailbox: {
601 type: DataTypes.STRING,
605 type: DataTypes.STRING,
609 type: DataTypes.INTEGER(11),
613 type: DataTypes.ENUM('yes', 'no'),
618 type: DataTypes.ENUM('yes', 'no'),
622 type: DataTypes.ENUM('yes', 'no'),
626 type: DataTypes.ENUM('yes', 'no'),
630 type: DataTypes.ENUM('yes', 'no'),
634 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
638 type: DataTypes.INTEGER(11),
642 type: DataTypes.STRING,
646 type: DataTypes.STRING,
650 type: DataTypes.STRING,
654 type: DataTypes.STRING,
658 type: DataTypes.STRING,
662 type: DataTypes.ENUM('active', 'passive', 'actpass'),
666 type: DataTypes.STRING,
669 usereqphone: { //This provider requires ";user=phone" on URI
670 type: DataTypes.ENUM('yes', 'no'),
674 recordonfeature: { //Feature to use when INFO with Record: on is received.
675 type: DataTypes.STRING,
678 recordofffeature: { //Feature to use when INFO with Record: off is received.
679 type: DataTypes.STRING,
683 type: DataTypes.INTEGER(11),
687 registertrying: { //Send a 100 Trying when the device registers.
688 type: DataTypes.ENUM('yes', 'no'),
691 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
692 type: DataTypes.ENUM('yes', 'no'),
695 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
696 type: DataTypes.STRING,
699 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
700 type: DataTypes.STRING,
703 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
704 type: DataTypes.STRING,
708 type: DataTypes.STRING,
712 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
720 * Authenticate - check if the passwords are the same
722 * @param {String} plainText
723 * {function} callBack
726 authenticate: function(plainText) {
727 return this.encryptPassword(plainText) === this.password;
735 makeSalt: function() {
736 return crypto.randomBytes(16).toString('base64');
741 * @param {String} password
745 encryptPassword: function(password) {
746 if (!password || !this.salt) return '';
747 var salt = new Buffer(this.salt, 'base64');
748 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
754 * @param {String} password
758 md5Password: function(password) {
759 if (!password) return '';
760 return md5(password);
763 associate: function(models) {
765 User.hasMany(models.ChatMessage);
766 User.hasMany(models.MailMessage);
767 User.hasMany(models.Contact);
768 User.hasMany(models.Action);
769 User.belongsToMany(models.Module, {
770 through: models.UserHasModule,
773 User.belongsToMany(models.Channel, {
774 through: 'user_has_channels'
776 User.belongsToMany(models.MailRoom, {
777 through: 'user_has_mail_rooms'
779 User.belongsToMany(models.SmsRoom, {
780 through: 'user_has_sms_rooms'
782 User.belongsToMany(models.Team, {
783 through: models.UserHasTeam
785 User.belongsToMany(models.VoiceQueue, {
786 through: models.UserHasVoiceQueue,
789 User.belongsToMany(models.VoiceQueue, {
790 through: models.UserHasVoiceQueuePermit,
793 User.belongsToMany(models.MailQueue, {
794 through: models.UserHasMailQueue,
797 User.belongsToMany(models.SmsQueue, {
798 through: models.UserHasSmsQueue,
801 User.belongsToMany(models.SmsQueue, {
802 through: models.UserHasSmsQueuePermit,
806 User.belongsToMany(models.MailQueue, {
807 through: models.UserHasMailQueuePermit,
810 User.belongsToMany(models.FaxQueue, {
811 through: models.UserHasFaxQueue,
814 User.belongsToMany(models.FaxQueue, {
815 through: models.UserHasFaxQueuePermit,
818 User.belongsToMany(models.ChatQueue, {
819 through: models.UserHasChatQueue,
822 User.belongsToMany(models.ChatQueue, {
823 through: models.UserHasChatQueuePermit,
826 User.belongsToMany(models.ChatRoom, {
827 through: models.UserHasChatRoom
829 User.belongsToMany(models.List, {
830 through: models.UserHasList
832 User.hasMany(models.VoiceExtension, {
833 foreignKey: 'UserId',
834 as: 'UserExtensions',
840 User.addScope('all', {
866 User.addScope('user', {
869 $in: ['admin', 'user']
894 User.addScope('agent', {
917 'phoneBarAutoAnswer',
918 'phoneBarEnableSettings',
919 'phoneBarUnconditional',
922 'phoneBarUnconditionalNumber',
923 'phoneBarNoReplyNumber',
924 'phoneBarBusyNumber',
925 'phoneBarListenPort',
947 User.addScope('telephone', {
952 User.addScope('queues', {
953 include: [models.VoiceQueue, models.ChatQueue, models.MailQueue,
954 models.FaxQueue, models.SmsQueue
958 User.addScope('checkPauseStatus', function(query) {
962 if (query.voicePause) {
963 scope.where.voicePause = (query.voicePause === 'true') ?
965 delete query.voicePause;
966 } else if (query.faxPause) {
967 scope.where.faxPause = (query.faxPause === 'true') ? true :
969 delete query.faxPause;
970 } else if (query.chatPause) {
971 scope.where.chatPause = (query.chatPause === 'true') ?
973 delete query.chatPause;
974 } else if (query.mailPause) {
975 scope.where.mailPause = (query.mailPause === 'true') ?
977 delete query.mailPause;
978 } else if (query.smsPause) {
979 scope.where.smsPause = (query.smsPause === 'true') ?
981 delete query.smsPause;
985 User.addScope('checkOnlineStatus', function(query) {
990 scope.where.online = (query.online === 'true') ? true :
996 User.addScope('checkSipStatus', function(query) {
1001 scope.where.status = query.status;
1002 delete query.status;
1006 User.addScope('checkQueueStatus', function(query) {
1010 if (query.queueStatus) {
1011 scope.where.queueStatus = query.queueStatus;
1012 delete query.queueStatus;