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: 'alaw;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,
754 * Authenticate - check if the passwords are the same
756 * @param {String} plainText
757 * {function} callBack
760 authenticate: function(plainText) {
761 return this.encryptPassword(plainText) === this.password;
769 makeSalt: function() {
770 return crypto.randomBytes(16).toString('base64');
775 * @param {String} password
779 encryptPassword: function(password) {
780 if (!password || !this.salt) return '';
781 var salt = new Buffer(this.salt, 'base64');
782 return crypto.pbkdf2Sync(password, salt, 10000, 64).toString(
788 * @param {String} password
792 md5Password: function(password) {
793 if (!password) return '';
794 return md5(password);
797 associate: function(models) {
799 User.hasMany(models.ChatMessage);
800 User.hasMany(models.MailMessage);
801 User.hasMany(models.Contact);
802 User.hasMany(models.Action);
803 User.belongsToMany(models.Module, {
804 through: models.UserHasModule,
807 User.belongsToMany(models.Channel, {
808 through: 'user_has_channels'
810 User.belongsToMany(models.MailRoom, {
811 through: 'user_has_mail_rooms'
813 User.belongsToMany(models.SmsRoom, {
814 through: 'user_has_sms_rooms'
816 User.belongsToMany(models.OpenchannelRoom, {
817 through: 'user_has_openchannel_rooms'
819 User.belongsToMany(models.FaxRoom, {
820 through: 'user_has_fax_rooms'
822 User.belongsToMany(models.Team, {
823 through: models.UserHasTeam
825 User.belongsToMany(models.VoiceQueue, {
826 through: models.UserHasVoiceQueue,
829 User.belongsToMany(models.VoiceQueue, {
830 through: models.UserHasVoiceQueuePermit,
833 User.belongsToMany(models.MailQueue, {
834 through: models.UserHasMailQueue,
837 User.belongsToMany(models.SmsQueue, {
838 through: models.UserHasSmsQueue,
841 User.belongsToMany(models.SmsQueue, {
842 through: models.UserHasSmsQueuePermit,
845 User.belongsToMany(models.OpenchannelQueue, {
846 through: models.UserHasOpenchannelQueue,
849 User.belongsToMany(models.OpenchannelQueue, {
850 through: models.UserHasOpenchannelQueuePermit,
851 as: 'POpenchannelQueues'
853 User.belongsToMany(models.MailQueue, {
854 through: models.UserHasMailQueuePermit,
857 User.belongsToMany(models.FaxQueue, {
858 through: models.UserHasFaxQueue,
861 User.belongsToMany(models.FaxQueue, {
862 through: models.UserHasFaxQueuePermit,
865 User.belongsToMany(models.ChatQueue, {
866 through: models.UserHasChatQueue,
869 User.belongsToMany(models.ChatQueue, {
870 through: models.UserHasChatQueuePermit,
873 User.belongsToMany(models.ChatRoom, {
874 through: models.UserHasChatRoom
876 User.belongsToMany(models.List, {
877 through: models.UserHasList
879 User.hasMany(models.VoiceExtension, {
880 foreignKey: 'UserId',
881 as: 'UserExtensions',
887 User.addScope('all', {
915 User.addScope('user', {
918 $in: ['admin', 'user']
945 User.addScope('agent', {
966 'openchannelCapacity',
969 'phoneBarAutoAnswer',
970 'phoneBarEnableSettings',
971 'phoneBarUnconditional',
974 'phoneBarUnconditionalNumber',
975 'phoneBarNoReplyNumber',
976 'phoneBarBusyNumber',
977 'phoneBarListenPort',
979 'phoneBarRemoteControl',
980 'phoneBarRemoteControlPort',
981 'phoneBarEnableRecording',
1006 'phoneBarShowOmniDesktop'
1009 User.addScope('telephone', {
1014 User.addScope('queues', {
1016 model: models.VoiceQueue,
1019 model: models.ChatQueue,
1022 model: models.MailQueue,
1025 model: models.FaxQueue,
1028 model: models.SmsQueue,
1031 model: models.OpenchannelQueue,
1036 User.addScope('checkPauseStatus', function(query) {
1040 if (query.voicePause) {
1041 scope.where.voicePause = (query.voicePause === 'true') ?
1043 delete query.voicePause;
1044 } else if (query.faxPause) {
1045 scope.where.faxPause = (query.faxPause === 'true') ? true :
1047 delete query.faxPause;
1048 } else if (query.chatPause) {
1049 scope.where.chatPause = (query.chatPause === 'true') ?
1051 delete query.chatPause;
1052 } else if (query.mailPause) {
1053 scope.where.mailPause = (query.mailPause === 'true') ?
1055 delete query.mailPause;
1056 } else if (query.smsPause) {
1057 scope.where.smsPause = (query.smsPause === 'true') ?
1059 delete query.smsPause;
1060 } else if (query.openchannelPause) {
1061 scope.where.openchannelPause = (query.openchannelPause === 'true') ?
1063 delete query.openchannelPause;
1067 User.addScope('checkOnlineStatus', function(query) {
1072 scope.where.online = (query.online === 'true') ? true :
1074 delete query.online;
1078 User.addScope('checkSipStatus', function(query) {
1083 scope.where.status = query.status;
1084 delete query.status;
1088 User.addScope('checkQueueStatus', function(query) {
1092 if (query.queueStatus) {
1093 scope.where.queueStatus = query.queueStatus;
1094 delete query.queueStatus;
1099 User.addScope('me', function(userId) {
1104 attributes: ['id', 'fullname', 'name', 'email', 'role', 'userpic', 'lastLoginAt', 'voicePause',
1112 'phoneBarRemoteControl',
1113 'phoneBarRemoteControlPort',
1118 model: models.Module,
1120 model: models.Module,
1128 model: models.VoiceQueue,
1131 model: models.ChatQueue,
1134 model: models.MailQueue,
1137 model: models.FaxQueue,
1140 model: models.SmsQueue,