3 var crypto = require('crypto');
4 var md5 = require('md5');
5 var _ = require('lodash');
6 var moment = require('moment');
8 module.exports = function(sequelize, DataTypes) {
9 var User = sequelize.define('User', {
11 type: DataTypes.STRING,
15 is: /^[A-Za-z0-9\.\_]+$/i
18 this.setDataValue('name', name);
19 this.setDataValue('defaultuser', name);
23 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 + ':asterisk:' + password));
54 type: DataTypes.STRING,
58 type: DataTypes.INTEGER(11),
60 set: function(internal) {
61 this.setDataValue('internal', internal);
62 this.setDataValue('accountcode', internal);
66 type: DataTypes.STRING
69 type: DataTypes.STRING
72 type: DataTypes.STRING
75 type: DataTypes.STRING
78 type: DataTypes.STRING
81 type: DataTypes.STRING
84 type: DataTypes.STRING
87 type: DataTypes.STRING
90 type: DataTypes.BOOLEAN,
97 type: DataTypes.STRING,
98 defaultValue: 'UNKNOWN'
104 type: DataTypes.STRING,
105 defaultValue: 'complete'
111 type: DataTypes.STRING
114 type: DataTypes.BOOLEAN,
116 // set: function(voicePause) {
117 // this.setDataValue('voicePause', voicePause);
119 // this.setDataValue('queueStatus', 'paused');
120 // this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
122 // this.setDataValue('queueStatus', 'complete');
123 // this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
128 type: DataTypes.BOOLEAN,
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 openchannelCapacity: {
171 type: DataTypes.INTEGER,
174 phoneBarAutoAnswer: {
175 type: DataTypes.BOOLEAN,
178 phoneBarEnableSettings: {
179 type: DataTypes.BOOLEAN,
182 phoneBarUnconditionalNumber: {
183 type: DataTypes.STRING,
185 if (this.getDataValue('phoneBarUnconditional')) {
186 return this.getDataValue('phoneBarUnconditionalNumber');
191 phoneBarNoReplyNumber: {
192 type: DataTypes.STRING,
194 if (this.getDataValue('phoneBarNoReply')) {
195 return this.getDataValue('phoneBarNoReplyNumber');
200 phoneBarBusyNumber: {
201 type: DataTypes.STRING,
203 if (this.getDataValue('phoneBarBusy')) {
204 return this.getDataValue('phoneBarBusyNumber');
209 phoneBarUnconditional: {
210 type: DataTypes.BOOLEAN,
214 type: DataTypes.BOOLEAN,
218 type: DataTypes.BOOLEAN,
221 phoneBarListenPort: {
222 type: DataTypes.INTEGER(5),
226 type: DataTypes.INTEGER(5),
230 type: DataTypes.INTEGER(5),
233 phoneBarNameServer: {
234 type: DataTypes.STRING,
237 phoneBarStunServer: {
238 type: DataTypes.STRING,
241 phoneBarVADEnabled: {
242 type: DataTypes.BOOLEAN,
246 type: DataTypes.BOOLEAN,
250 type: DataTypes.BOOLEAN,
254 type: DataTypes.INTEGER(5),
257 phoneBarPublishEnabled: {
258 type: DataTypes.BOOLEAN,
261 phoneBarRemoteControl: {
262 type: DataTypes.BOOLEAN,
265 phoneBarRemoteControlPort: {
266 type: DataTypes.INTEGER,
270 type: DataTypes.BOOLEAN,
274 type: DataTypes.STRING,
278 type: DataTypes.STRING,
280 defaultValue: 'dynamic'
282 ipaddr: { //REALTIME ASTERISK
283 type: DataTypes.STRING,
286 port: { //REALTIME ASTERISK
287 type: DataTypes.INTEGER(5),
290 regseconds: { //REALTIME ASTERISK
291 type: DataTypes.INTEGER(11),
294 fullcontact: { //REALTIME ASTERISK
295 type: DataTypes.STRING,
298 regserver: { //REALTIME ASTERISK
299 type: DataTypes.STRING,
302 useragent: { //REALTIME ASTERISK
303 type: DataTypes.STRING,
306 lastms: { //REALTIME ASTERISK
307 type: DataTypes.INTEGER(11),
311 type: DataTypes.ENUM('friend', 'user', 'peer'),
313 defaultValue: 'friend'
316 type: DataTypes.STRING,
318 defaultValue: 'from-sip'
321 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
322 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
323 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
324 'PROHIB_FAILED_SCREEN', 'PROHIB'),
328 type: DataTypes.STRING,
332 type: DataTypes.STRING,
336 type: DataTypes.STRING,
340 type: DataTypes.STRING,
344 type: DataTypes.STRING,
348 type: DataTypes.STRING,
353 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
356 defaultValue: 'rfc2833'
359 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
364 type: DataTypes.ENUM('yes', 'no'),
369 type: DataTypes.STRING,
373 type: DataTypes.STRING,
377 type: DataTypes.STRING,
379 defaultValue: 'force_rport,comedia'
382 type: DataTypes.STRING,
385 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
386 type: DataTypes.STRING,
390 type: DataTypes.STRING,
393 namedpickupgroup: { //We can do call pick-p for named call group sales
394 type: DataTypes.STRING,
398 type: DataTypes.STRING,
403 type: DataTypes.STRING,
407 type: DataTypes.STRING,
412 type: DataTypes.STRING,
414 defaultValue: 'alaw;ulaw;gsm'
417 type: DataTypes.ENUM('yes', 'no'),
421 type: DataTypes.STRING,
423 defaultValue: 'port,invite'
426 type: DataTypes.ENUM('yes', 'no'),
431 type: DataTypes.ENUM('yes', 'no'),
436 type: DataTypes.ENUM('yes', 'no', 'never'),
440 type: DataTypes.ENUM('yes', 'no'),
444 type: DataTypes.ENUM('yes', 'no'),
448 type: DataTypes.INTEGER(11),
452 type: DataTypes.STRING,
456 type: DataTypes.STRING,
458 defaultValue: '"" <>'
461 type: DataTypes.STRING,
465 type: DataTypes.ENUM('yes', 'no'),
470 type: DataTypes.INTEGER(11),
474 type: DataTypes.ENUM('yes', 'no'),
478 type: DataTypes.ENUM('yes', 'no'),
482 type: DataTypes.ENUM('yes', 'no'),
486 type: DataTypes.ENUM('yes', 'no'),
490 type: DataTypes.STRING,
494 type: DataTypes.STRING,
498 type: DataTypes.ENUM('yes', 'no', 'always'),
503 type: DataTypes.INTEGER(11),
507 type: DataTypes.ENUM('yes', 'no'),
511 type: DataTypes.STRING,
515 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
519 type: DataTypes.INTEGER(11),
523 type: DataTypes.INTEGER(11),
527 type: DataTypes.ENUM('uac', 'uas'),
531 t38pt_usertpsource: {
532 type: DataTypes.STRING,
536 type: DataTypes.STRING,
540 type: DataTypes.STRING,
544 type: DataTypes.STRING,
548 type: DataTypes.ENUM('yes', 'no'),
553 type: DataTypes.INTEGER(11),
557 type: DataTypes.STRING,
561 type: DataTypes.STRING,
564 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
565 type: DataTypes.INTEGER(11),
568 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
569 type: DataTypes.INTEGER(11),
572 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
573 type: DataTypes.INTEGER(11),
577 type: DataTypes.ENUM('yes', 'no'),
582 type: DataTypes.STRING,
586 type: DataTypes.STRING,
590 type: DataTypes.INTEGER(11),
594 type: DataTypes.INTEGER(11),
598 type: DataTypes.INTEGER(11),
602 type: DataTypes.STRING,
606 type: DataTypes.STRING,
610 type: DataTypes.STRING,
613 unsolicited_mailbox: {
614 type: DataTypes.STRING,
618 type: DataTypes.STRING,
622 type: DataTypes.INTEGER(11),
626 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'),
647 type: DataTypes.ENUM('yes', 'no', 'fingerprint', 'certificate'),
651 type: DataTypes.INTEGER(11),
655 type: DataTypes.STRING,
659 type: DataTypes.STRING,
663 type: DataTypes.STRING,
667 type: DataTypes.STRING,
671 type: DataTypes.STRING,
675 type: DataTypes.ENUM('active', 'passive', 'actpass'),
679 type: DataTypes.STRING,
682 usereqphone: { //This provider requires ";user=phone" on URI
683 type: DataTypes.ENUM('yes', 'no'),
687 recordonfeature: { //Feature to use when INFO with Record: on is received.
688 type: DataTypes.STRING,
691 recordofffeature: { //Feature to use when INFO with Record: off is received.
692 type: DataTypes.STRING,
696 type: DataTypes.INTEGER(11),
700 registertrying: { //Send a 100 Trying when the device registers.
701 type: DataTypes.ENUM('yes', 'no'),
704 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
705 type: DataTypes.ENUM('yes', 'no'),
708 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
709 type: DataTypes.STRING,
712 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
713 type: DataTypes.STRING,
716 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
717 type: DataTypes.STRING,
721 type: DataTypes.STRING,
725 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
730 type: DataTypes.BOOLEAN,
733 resetPasswordToken: {
734 type: DataTypes.STRING
736 resetPasswordExpires: {
739 phoneBarEnableRecording: {
740 type: DataTypes.BOOLEAN,
747 * Authenticate - check if the passwords are the same
749 * @param {String} plainText
750 * {function} callBack
753 authenticate: function(plainText) {
754 return this.encryptPassword(plainText) === this.password;
762 makeSalt: function() {
763 return crypto.randomBytes(16).toString('base64');
768 * @param {String} password
772 encryptPassword: function(password) {
773 if (!password || !this.salt) return '';
774 var salt = new Buffer(this.salt, 'base64');
775 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
781 * @param {String} password
785 md5Password: function(password) {
786 if (!password) return '';
787 return md5(password);
790 associate: function(models) {
792 User.hasMany(models.ChatMessage);
793 User.hasMany(models.MailMessage);
794 User.hasMany(models.Contact);
795 User.hasMany(models.Action);
796 User.belongsToMany(models.Module, {
797 through: models.UserHasModule,
800 User.belongsToMany(models.Channel, {
801 through: 'user_has_channels'
803 User.belongsToMany(models.MailRoom, {
804 through: 'user_has_mail_rooms'
806 User.belongsToMany(models.SmsRoom, {
807 through: 'user_has_sms_rooms'
809 User.belongsToMany(models.OpenchannelRoom, {
810 through: 'user_has_openchannel_rooms'
812 User.belongsToMany(models.FaxRoom, {
813 through: 'user_has_fax_rooms'
815 User.belongsToMany(models.Team, {
816 through: models.UserHasTeam
818 User.belongsToMany(models.VoiceQueue, {
819 through: models.UserHasVoiceQueue,
822 User.belongsToMany(models.VoiceQueue, {
823 through: models.UserHasVoiceQueuePermit,
826 User.belongsToMany(models.MailQueue, {
827 through: models.UserHasMailQueue,
830 User.belongsToMany(models.SmsQueue, {
831 through: models.UserHasSmsQueue,
834 User.belongsToMany(models.SmsQueue, {
835 through: models.UserHasSmsQueuePermit,
838 User.belongsToMany(models.OpenchannelQueue, {
839 through: models.UserHasOpenchannelQueue,
842 User.belongsToMany(models.OpenchannelQueue, {
843 through: models.UserHasOpenchannelQueuePermit,
844 as: 'POpenchannelQueues'
846 User.belongsToMany(models.MailQueue, {
847 through: models.UserHasMailQueuePermit,
850 User.belongsToMany(models.FaxQueue, {
851 through: models.UserHasFaxQueue,
854 User.belongsToMany(models.FaxQueue, {
855 through: models.UserHasFaxQueuePermit,
858 User.belongsToMany(models.ChatQueue, {
859 through: models.UserHasChatQueue,
862 User.belongsToMany(models.ChatQueue, {
863 through: models.UserHasChatQueuePermit,
866 User.belongsToMany(models.ChatRoom, {
867 through: models.UserHasChatRoom
869 User.belongsToMany(models.List, {
870 through: models.UserHasList
872 User.hasMany(models.VoiceExtension, {
873 foreignKey: 'UserId',
874 as: 'UserExtensions',
880 User.addScope('all', {
906 User.addScope('user', {
909 $in: ['admin', 'user']
934 User.addScope('agent', {
955 'openchannelCapacity',
958 'phoneBarAutoAnswer',
959 'phoneBarEnableSettings',
960 'phoneBarUnconditional',
963 'phoneBarUnconditionalNumber',
964 'phoneBarNoReplyNumber',
965 'phoneBarBusyNumber',
966 'phoneBarListenPort',
968 'phoneBarRemoteControl',
969 'phoneBarRemoteControlPort',
970 'phoneBarEnableRecording',
994 User.addScope('telephone', {
999 User.addScope('queues', {
1001 model: models.VoiceQueue,
1004 model: models.ChatQueue,
1007 model: models.MailQueue,
1010 model: models.FaxQueue,
1013 model: models.SmsQueue,
1016 model: models.OpenchannelQueue,
1021 User.addScope('checkPauseStatus', function(query) {
1025 if (query.voicePause) {
1026 scope.where.voicePause = (query.voicePause === 'true') ?
1028 delete query.voicePause;
1029 } else if (query.faxPause) {
1030 scope.where.faxPause = (query.faxPause === 'true') ? true :
1032 delete query.faxPause;
1033 } else if (query.chatPause) {
1034 scope.where.chatPause = (query.chatPause === 'true') ?
1036 delete query.chatPause;
1037 } else if (query.mailPause) {
1038 scope.where.mailPause = (query.mailPause === 'true') ?
1040 delete query.mailPause;
1041 } else if (query.smsPause) {
1042 scope.where.smsPause = (query.smsPause === 'true') ?
1044 delete query.smsPause;
1045 } else if (query.openchannelPause) {
1046 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1048 delete query.openchannelPause;
1052 User.addScope('checkOnlineStatus', function(query) {
1057 scope.where.online = (query.online === 'true') ? true :
1059 delete query.online;
1063 User.addScope('checkSipStatus', function(query) {
1068 scope.where.status = query.status;
1069 delete query.status;
1073 User.addScope('checkQueueStatus', function(query) {
1077 if (query.queueStatus) {
1078 scope.where.queueStatus = query.queueStatus;
1079 delete query.queueStatus;
1084 User.addScope('me', function(userId) {
1089 attributes: ['id', 'fullname', 'name', 'email', 'role', 'userpic', 'lastLoginAt', 'voicePause',
1097 'phoneBarRemoteControl',
1098 'phoneBarRemoteControlPort',
1102 model: models.Module,
1104 model: models.Module,
1112 model: models.VoiceQueue,
1115 model: models.ChatQueue,
1118 model: models.MailQueue,
1121 model: models.FaxQueue,
1124 model: models.SmsQueue,