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,
27 type: DataTypes.STRING,
30 set: function(email) {
32 this.setDataValue('email', email.toLowerCase());
38 type: DataTypes.ENUM('admin', 'user', 'agent', 'telephone')
41 type: DataTypes.STRING,
46 set: function(password) {
47 this.salt = this.makeSalt();
48 this.setDataValue('password', this.encryptPassword(password));
49 this.setDataValue('md5secret', this.md5Password(this.name + ':asterisk:' + password));
53 type: DataTypes.STRING,
57 type: DataTypes.INTEGER(11),
59 set: function(internal) {
60 this.setDataValue('internal', internal);
61 this.setDataValue('accountcode', internal);
65 type: DataTypes.STRING
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.BOOLEAN,
96 type: DataTypes.STRING,
97 defaultValue: 'UNKNOWN'
103 type: DataTypes.STRING,
104 defaultValue: 'complete'
110 type: DataTypes.STRING
113 type: DataTypes.BOOLEAN,
115 // set: function(voicePause) {
116 // this.setDataValue('voicePause', voicePause);
118 // this.setDataValue('queueStatus', 'paused');
119 // this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
121 // this.setDataValue('queueStatus', 'complete');
122 // this.setDataValue('queueStatusAt', moment().format("YYYY-MM-DD HH:mm:ss"));
127 type: DataTypes.BOOLEAN,
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 openchannelCapacity: {
170 type: DataTypes.INTEGER,
173 phoneBarAutoAnswer: {
174 type: DataTypes.BOOLEAN,
177 phoneBarEnableSettings: {
178 type: DataTypes.BOOLEAN,
181 phoneBarUnconditionalNumber: {
182 type: DataTypes.STRING,
184 if (this.getDataValue('phoneBarUnconditional')) {
185 return this.getDataValue('phoneBarUnconditionalNumber');
190 phoneBarNoReplyNumber: {
191 type: DataTypes.STRING,
193 if (this.getDataValue('phoneBarNoReply')) {
194 return this.getDataValue('phoneBarNoReplyNumber');
199 phoneBarBusyNumber: {
200 type: DataTypes.STRING,
202 if (this.getDataValue('phoneBarBusy')) {
203 return this.getDataValue('phoneBarBusyNumber');
208 phoneBarUnconditional: {
209 type: DataTypes.BOOLEAN,
213 type: DataTypes.BOOLEAN,
217 type: DataTypes.BOOLEAN,
220 phoneBarListenPort: {
221 type: DataTypes.INTEGER(5),
225 type: DataTypes.INTEGER(5),
229 type: DataTypes.INTEGER(5),
232 phoneBarNameServer: {
233 type: DataTypes.STRING,
236 phoneBarStunServer: {
237 type: DataTypes.STRING,
240 phoneBarVADEnabled: {
241 type: DataTypes.BOOLEAN,
245 type: DataTypes.BOOLEAN,
249 type: DataTypes.BOOLEAN,
253 type: DataTypes.INTEGER(5),
256 phoneBarPublishEnabled: {
257 type: DataTypes.BOOLEAN,
260 phoneBarRemoteControl: {
261 type: DataTypes.BOOLEAN,
264 phoneBarRemoteControlPort: {
265 type: DataTypes.INTEGER,
269 type: DataTypes.BOOLEAN,
273 type: DataTypes.STRING,
277 type: DataTypes.STRING,
279 defaultValue: 'dynamic'
281 ipaddr: { //REALTIME ASTERISK
282 type: DataTypes.STRING,
285 port: { //REALTIME ASTERISK
286 type: DataTypes.INTEGER(5),
289 regseconds: { //REALTIME ASTERISK
290 type: DataTypes.INTEGER(11),
293 fullcontact: { //REALTIME ASTERISK
294 type: DataTypes.STRING,
297 regserver: { //REALTIME ASTERISK
298 type: DataTypes.STRING,
301 useragent: { //REALTIME ASTERISK
302 type: DataTypes.STRING,
305 lastms: { //REALTIME ASTERISK
306 type: DataTypes.INTEGER(11),
310 type: DataTypes.ENUM('friend', 'user', 'peer'),
312 defaultValue: 'friend'
315 type: DataTypes.STRING,
317 defaultValue: 'from-sip'
320 type: DataTypes.ENUM('ALLOWED_NOT_SCREENED',
321 'ALLOWED_PASSED_SCREEN', 'ALLOWED_FAILED_SCREEN', 'ALLOWED',
322 'PROHIB_NOT_SCREENED', 'PROHIB_PASSED_SCREEN',
323 'PROHIB_FAILED_SCREEN', 'PROHIB'),
327 type: DataTypes.STRING,
331 type: DataTypes.STRING,
335 type: DataTypes.STRING,
339 type: DataTypes.STRING,
343 type: DataTypes.STRING,
347 type: DataTypes.STRING,
352 type: DataTypes.ENUM('rfc2833', 'info', 'shortinfo', 'inband',
355 defaultValue: 'rfc2833'
358 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'outgoing'),
363 type: DataTypes.ENUM('yes', 'no'),
368 type: DataTypes.STRING,
372 type: DataTypes.STRING,
376 type: DataTypes.STRING,
378 defaultValue: 'force_rport,comedia'
381 type: DataTypes.STRING,
384 namedcallgroup: { //We are in named call groups engineering,sales,netgroup,protgroup
385 type: DataTypes.STRING,
389 type: DataTypes.STRING,
392 namedpickupgroup: { //We can do call pick-p for named call group sales
393 type: DataTypes.STRING,
397 type: DataTypes.STRING,
402 type: DataTypes.STRING,
406 type: DataTypes.STRING,
411 type: DataTypes.STRING,
413 defaultValue: 'ulaw;gsm'
416 type: DataTypes.ENUM('yes', 'no'),
420 type: DataTypes.STRING,
422 defaultValue: 'port,invite'
425 type: DataTypes.ENUM('yes', 'no'),
430 type: DataTypes.ENUM('yes', 'no'),
435 type: DataTypes.ENUM('yes', 'no', 'never'),
439 type: DataTypes.ENUM('yes', 'no'),
443 type: DataTypes.ENUM('yes', 'no'),
447 type: DataTypes.INTEGER(11),
451 type: DataTypes.STRING,
455 type: DataTypes.STRING,
457 defaultValue: '"" <>'
460 type: DataTypes.STRING,
464 type: DataTypes.ENUM('yes', 'no'),
469 type: DataTypes.INTEGER(11),
473 type: DataTypes.ENUM('yes', 'no'),
477 type: DataTypes.ENUM('yes', 'no'),
481 type: DataTypes.ENUM('yes', 'no'),
485 type: DataTypes.ENUM('yes', 'no'),
489 type: DataTypes.STRING,
493 type: DataTypes.STRING,
497 type: DataTypes.ENUM('yes', 'no', 'always'),
502 type: DataTypes.INTEGER(11),
506 type: DataTypes.ENUM('yes', 'no'),
510 type: DataTypes.STRING,
514 type: DataTypes.ENUM('accept', 'refuse', 'originate'),
518 type: DataTypes.INTEGER(11),
522 type: DataTypes.INTEGER(11),
526 type: DataTypes.ENUM('uac', 'uas'),
530 t38pt_usertpsource: {
531 type: DataTypes.STRING,
535 type: DataTypes.STRING,
539 type: DataTypes.STRING,
543 type: DataTypes.STRING,
547 type: DataTypes.ENUM('yes', 'no'),
552 type: DataTypes.INTEGER(11),
556 type: DataTypes.STRING,
560 type: DataTypes.STRING,
563 rtptimeout: { // Terminate call if 60 seconds of no RTP or RTCP activity on the audio channel when we're not on hold.
564 type: DataTypes.INTEGER(11),
567 rtpholdtimeout: { // Terminate call if 300 seconds of no RTP or RTCP activity on the audio channel when we're on hold (must be > rtptimeout)
568 type: DataTypes.INTEGER(11),
571 rtpkeepalive: { // Send keepalives in the RTP stream to keep NAT open (default is off - zero)
572 type: DataTypes.INTEGER(11),
576 type: DataTypes.ENUM('yes', 'no'),
581 type: DataTypes.STRING,
585 type: DataTypes.STRING,
589 type: DataTypes.INTEGER(11),
593 type: DataTypes.INTEGER(11),
597 type: DataTypes.INTEGER(11),
601 type: DataTypes.STRING,
605 type: DataTypes.STRING,
609 type: DataTypes.STRING,
612 unsolicited_mailbox: {
613 type: DataTypes.STRING,
617 type: DataTypes.STRING,
621 type: DataTypes.INTEGER(11),
625 type: DataTypes.ENUM('yes', 'no'),
630 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', 'fingerprint', 'certificate'),
650 type: DataTypes.INTEGER(11),
654 type: DataTypes.STRING,
658 type: DataTypes.STRING,
662 type: DataTypes.STRING,
666 type: DataTypes.STRING,
670 type: DataTypes.STRING,
674 type: DataTypes.ENUM('active', 'passive', 'actpass'),
678 type: DataTypes.STRING,
681 usereqphone: { //This provider requires ";user=phone" on URI
682 type: DataTypes.ENUM('yes', 'no'),
686 recordonfeature: { //Feature to use when INFO with Record: on is received.
687 type: DataTypes.STRING,
690 recordofffeature: { //Feature to use when INFO with Record: off is received.
691 type: DataTypes.STRING,
695 type: DataTypes.INTEGER(11),
699 registertrying: { //Send a 100 Trying when the device registers.
700 type: DataTypes.ENUM('yes', 'no'),
703 subscribemwi: { //Only send notifications if this phone subscribes for mailbox notification
704 type: DataTypes.ENUM('yes', 'no'),
707 vmexten: { // dialplan extension to reach mailbox. defaults to global vmexten which defaults to "asterisk"
708 type: DataTypes.STRING,
711 mohinterpret: { // This option specifies a preference for which music on hold class this channel should listen to when put on hold
712 type: DataTypes.STRING,
715 mohsuggest: { // This option specifies which music on hold class to suggest to the peer channel when this channel places the peer on hold.
716 type: DataTypes.STRING,
720 type: DataTypes.STRING,
724 type: DataTypes.ENUM('yes', 'no', 'nonat', 'update', 'update,nonat'),
729 type: DataTypes.BOOLEAN,
732 resetPasswordToken: {
733 type: DataTypes.STRING
735 resetPasswordExpires: {
738 phoneBarEnableRecording: {
739 type: DataTypes.BOOLEAN,
743 type: DataTypes.BOOLEAN,
746 phoneBarShowOmniDesktop: {
747 type: DataTypes.BOOLEAN,
751 type: DataTypes.BOOLEAN,
755 type: DataTypes.BOOLEAN,
758 phoneBarUnansweredCallBadge: {
759 type: DataTypes.BOOLEAN,
766 * Authenticate - check if the passwords are the same
768 * @param {String} plainText
769 * {function} callBack
772 authenticate: function(plainText) {
773 return this.encryptPassword(plainText) === this.password;
781 makeSalt: function() {
782 return crypto.randomBytes(16).toString('base64');
787 * @param {String} password
791 encryptPassword: function(password) {
792 if (!password || !this.salt) return '';
793 var salt = new Buffer(this.salt, 'base64');
794 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
800 * @param {String} password
804 md5Password: function(password) {
805 if (!password) return '';
806 return md5(password);
809 associate: function(models) {
811 User.hasMany(models.ChatMessage);
812 User.hasMany(models.MailMessage);
813 User.hasMany(models.Contact);
814 User.hasMany(models.Action);
815 User.belongsToMany(models.Module, {
816 through: models.UserHasModule,
819 User.belongsToMany(models.MailRoom, {
820 through: models.UserHasMailRoom,
822 User.belongsToMany(models.Channel, {
823 through: 'user_has_channels'
825 User.belongsToMany(models.SmsRoom, {
826 through: 'user_has_sms_rooms'
828 User.belongsToMany(models.OpenchannelRoom, {
829 through: 'user_has_openchannel_rooms'
831 User.belongsToMany(models.FaxRoom, {
832 through: 'user_has_fax_rooms'
834 User.belongsToMany(models.Team, {
835 through: models.UserHasTeam
837 User.belongsToMany(models.VoiceQueue, {
838 through: models.UserHasVoiceQueue,
841 User.belongsToMany(models.VoiceQueue, {
842 through: models.UserHasVoiceQueuePermit,
845 User.belongsToMany(models.MailQueue, {
846 through: models.UserHasMailQueue,
849 User.belongsToMany(models.SmsQueue, {
850 through: models.UserHasSmsQueue,
853 User.belongsToMany(models.SmsQueue, {
854 through: models.UserHasSmsQueuePermit,
857 User.belongsToMany(models.OpenchannelQueue, {
858 through: models.UserHasOpenchannelQueue,
861 User.belongsToMany(models.OpenchannelQueue, {
862 through: models.UserHasOpenchannelQueuePermit,
863 as: 'POpenchannelQueues'
865 User.belongsToMany(models.MailQueue, {
866 through: models.UserHasMailQueuePermit,
869 User.belongsToMany(models.FaxQueue, {
870 through: models.UserHasFaxQueue,
873 User.belongsToMany(models.FaxQueue, {
874 through: models.UserHasFaxQueuePermit,
877 User.belongsToMany(models.ChatQueue, {
878 through: models.UserHasChatQueue,
881 User.belongsToMany(models.ChatQueue, {
882 through: models.UserHasChatQueuePermit,
885 User.belongsToMany(models.ChatRoom, {
886 through: models.UserHasChatRoom
888 User.belongsToMany(models.List, {
889 through: models.UserHasList
891 User.hasMany(models.VoiceExtension, {
892 foreignKey: 'UserId',
893 as: 'UserExtensions',
899 User.addScope('all', {
927 User.addScope('user', {
930 $in: ['admin', 'user']
957 User.addScope('agent', {
978 'openchannelCapacity',
981 'phoneBarAutoAnswer',
982 'phoneBarEnableSettings',
983 'phoneBarUnconditional',
986 'phoneBarUnconditionalNumber',
987 'phoneBarNoReplyNumber',
988 'phoneBarBusyNumber',
989 'phoneBarListenPort',
991 'phoneBarRemoteControl',
992 'phoneBarRemoteControlPort',
993 'phoneBarEnableRecording',
1018 'phoneBarShowOmniDesktop',
1019 'phoneBarRingInUse',
1021 'phoneBarUnansweredCallBadge',
1026 User.addScope('telephone', {
1031 User.addScope('queues', {
1033 model: models.VoiceQueue,
1036 model: models.ChatQueue,
1039 model: models.MailQueue,
1042 model: models.FaxQueue,
1045 model: models.SmsQueue,
1048 model: models.OpenchannelQueue,
1053 User.addScope('checkPauseStatus', function(query) {
1057 if (query.voicePause) {
1058 scope.where.voicePause = (query.voicePause === 'true') ?
1060 delete query.voicePause;
1061 } else if (query.faxPause) {
1062 scope.where.faxPause = (query.faxPause === 'true') ? true :
1064 delete query.faxPause;
1065 } else if (query.chatPause) {
1066 scope.where.chatPause = (query.chatPause === 'true') ?
1068 delete query.chatPause;
1069 } else if (query.mailPause) {
1070 scope.where.mailPause = (query.mailPause === 'true') ?
1072 delete query.mailPause;
1073 } else if (query.smsPause) {
1074 scope.where.smsPause = (query.smsPause === 'true') ?
1076 delete query.smsPause;
1077 } else if (query.openchannelPause) {
1078 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1080 delete query.openchannelPause;
1084 User.addScope('checkOnlineStatus', function(query) {
1089 scope.where.online = (query.online === 'true') ? true :
1091 delete query.online;
1095 User.addScope('checkSipStatus', function(query) {
1100 scope.where.status = query.status;
1101 delete query.status;
1105 User.addScope('checkQueueStatus', function(query) { //to be executed before checkOnlineStatus
1109 if (query.queueStatus) {
1110 if (query.queueStatus === 'paused') {
1111 scope.where.voicePause = true;
1113 scope.where.queueStatus = query.queueStatus;
1114 scope.where.voicePause = false;
1115 query.online = 'true';
1117 delete query.queueStatus;
1122 User.addScope('me', function(userId) {
1127 attributes: ['id', 'fullname', 'name', 'email', 'role', 'userpic', 'lastLoginAt', 'voicePause',
1135 'phoneBarRemoteControl',
1136 'phoneBarRemoteControlPort',
1141 model: models.Module,
1143 model: models.Module,
1151 model: models.VoiceQueue,
1154 model: models.ChatQueue,
1157 model: models.MailQueue,
1160 model: models.FaxQueue,
1163 model: models.SmsQueue,