From ae394408e62eb5817679998a4b7a249b9d627901 Mon Sep 17 00:00:00 2001 From: isymchych Date: Fri, 18 Dec 2015 15:58:40 +0200 Subject: [PATCH 1/3] remove old nick when adding new one --- JitsiConference.js | 3 +++ lib-jitsi-meet.js | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/JitsiConference.js b/JitsiConference.js index 4cdd5cda3..c57d404ab 100644 --- a/JitsiConference.js +++ b/JitsiConference.js @@ -211,6 +211,9 @@ JitsiConference.prototype.removeCommand = function (name) { */ JitsiConference.prototype.setDisplayName = function(name) { if(this.room){ + // remove previously set nickname + this.room.removeFromPresence("nick"); + this.room.addToPresence("nick", {attributes: {xmlns: 'http://jabber.org/protocol/nick'}, value: name}); this.room.sendPresence(); } diff --git a/lib-jitsi-meet.js b/lib-jitsi-meet.js index 74c16fd7a..79038348f 100644 --- a/lib-jitsi-meet.js +++ b/lib-jitsi-meet.js @@ -213,6 +213,9 @@ JitsiConference.prototype.removeCommand = function (name) { */ JitsiConference.prototype.setDisplayName = function(name) { if(this.room){ + // remove previously set nickname + this.room.removeFromPresence("nick"); + this.room.addToPresence("nick", {attributes: {xmlns: 'http://jabber.org/protocol/nick'}, value: name}); this.room.sendPresence(); } @@ -959,9 +962,18 @@ var LibJitsiMeet = { return tracks; }); }, + /** + * Checks if its possible to enumerate available cameras/micropones. + * @returns {boolean} true if available, false otherwise. + */ isDeviceListAvailable: function () { return RTC.isDeviceListAvailable(); }, + /** + * Returns true if changing the camera / microphone device is supported and + * false if not. + * @returns {boolean} true if available, false otherwise. + */ isDeviceChangeAvailable: function () { return RTC.isDeviceChangeAvailable(); }, From c5c0326b5576e50abc661c38761e1b14ddb398c5 Mon Sep 17 00:00:00 2001 From: isymchych Date: Fri, 18 Dec 2015 19:52:33 +0200 Subject: [PATCH 2/3] added helper methods to check if auth enabled --- JitsiConference.js | 34 +++++++++++++++++++++++++++++++++- lib-jitsi-meet.js | 44 ++++++++++++++++++++++++++++++++++++++------ modules/xmpp/xmpp.js | 8 ++++---- 3 files changed, 75 insertions(+), 11 deletions(-) diff --git a/JitsiConference.js b/JitsiConference.js index c57d404ab..d4a82dea7 100644 --- a/JitsiConference.js +++ b/JitsiConference.js @@ -3,6 +3,7 @@ var logger = require("jitsi-meet-logger").getLogger(__filename); var RTC = require("./modules/RTC/RTC"); var XMPPEvents = require("./service/xmpp/XMPPEvents"); +var AuthenticationEvents = require("./service/authentication/AuthenticationEvents"); var RTCEvents = require("./service/RTC/RTCEvents"); var EventEmitter = require("events"); var JitsiConferenceEvents = require("./JitsiConferenceEvents"); @@ -31,7 +32,7 @@ function JitsiConference(options) { this.connection = this.options.connection; this.xmpp = this.connection.xmpp; this.eventEmitter = new EventEmitter(); - this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config); + this.room = this.xmpp.createRoom(this.options.name, this.options.config); this.room.updateDeviceAvailability(RTC.getDeviceAvailability()); this.rtc = new RTC(this.room, options); if(!RTC.options.disableAudioLevels) @@ -41,6 +42,8 @@ function JitsiConference(options) { this.lastActiveSpeaker = null; this.dtmfManager = null; this.somebodySupportsDTMF = false; + this.authEnabled = false; + this.authIdentity; } /** @@ -75,6 +78,27 @@ JitsiConference.prototype.getName = function () { return this.options.name; }; +/** + * Check if authentication is enabled for this conference. + */ +JitsiConference.prototype.isAuthEnabled = function () { + return this.authEnabled; +}; + +/** + * Check if user is logged in. + */ +JitsiConference.prototype.isLoggedIn = function () { + return !!this.authIdentity; +}; + +/** + * Get authorized login. + */ +JitsiConference.prototype.getAuthLogin = function () { + return this.authIdentity; +}; + /** * Check if external authentication is enabled for this conference. */ @@ -382,6 +406,9 @@ JitsiConference.prototype.onMemberJoined = function (jid, email, nick) { JitsiConference.prototype.onMemberLeft = function (jid) { var id = Strophe.getResourceFromJid(jid); + if (id === 'focus') { + return; + } var participant = this.participants[id]; delete this.participants[id]; this.eventEmitter.emit(JitsiConferenceEvents.USER_LEFT, id, participant); @@ -560,6 +587,11 @@ function setupListeners(conference) { conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.SETUP_FAILED); }); + conference.room.addListener(AuthenticationEvents.IDENTITY_UPDATED, function (authEnabled, authIdentity) { + conference.authEnabled = authEnabled; + conference.authIdentity = authIdentity; + }); + conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED, function (jid, displayName, txt, myJid, ts) { var id = Strophe.getResourceFromJid(jid); conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED, id, txt, ts); diff --git a/lib-jitsi-meet.js b/lib-jitsi-meet.js index 79038348f..363d05f47 100644 --- a/lib-jitsi-meet.js +++ b/lib-jitsi-meet.js @@ -5,6 +5,7 @@ var logger = require("jitsi-meet-logger").getLogger(__filename); var RTC = require("./modules/RTC/RTC"); var XMPPEvents = require("./service/xmpp/XMPPEvents"); +var AuthenticationEvents = require("./service/authentication/AuthenticationEvents"); var RTCEvents = require("./service/RTC/RTCEvents"); var EventEmitter = require("events"); var JitsiConferenceEvents = require("./JitsiConferenceEvents"); @@ -33,7 +34,7 @@ function JitsiConference(options) { this.connection = this.options.connection; this.xmpp = this.connection.xmpp; this.eventEmitter = new EventEmitter(); - this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config); + this.room = this.xmpp.createRoom(this.options.name, this.options.config); this.room.updateDeviceAvailability(RTC.getDeviceAvailability()); this.rtc = new RTC(this.room, options); if(!RTC.options.disableAudioLevels) @@ -43,6 +44,8 @@ function JitsiConference(options) { this.lastActiveSpeaker = null; this.dtmfManager = null; this.somebodySupportsDTMF = false; + this.authEnabled = false; + this.authIdentity; } /** @@ -77,6 +80,27 @@ JitsiConference.prototype.getName = function () { return this.options.name; }; +/** + * Check if authentication is enabled for this conference. + */ +JitsiConference.prototype.isAuthEnabled = function () { + return this.authEnabled; +}; + +/** + * Check if user is logged in. + */ +JitsiConference.prototype.isLoggedIn = function () { + return !!this.authIdentity; +}; + +/** + * Get authorized login. + */ +JitsiConference.prototype.getAuthLogin = function () { + return this.authIdentity; +}; + /** * Check if external authentication is enabled for this conference. */ @@ -384,6 +408,9 @@ JitsiConference.prototype.onMemberJoined = function (jid, email, nick) { JitsiConference.prototype.onMemberLeft = function (jid) { var id = Strophe.getResourceFromJid(jid); + if (id === 'focus') { + return; + } var participant = this.participants[id]; delete this.participants[id]; this.eventEmitter.emit(JitsiConferenceEvents.USER_LEFT, id, participant); @@ -562,6 +589,11 @@ function setupListeners(conference) { conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.SETUP_FAILED); }); + conference.room.addListener(AuthenticationEvents.IDENTITY_UPDATED, function (authEnabled, authIdentity) { + conference.authEnabled = authEnabled; + conference.authIdentity = authIdentity; + }); + conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED, function (jid, displayName, txt, myJid, ts) { var id = Strophe.getResourceFromJid(jid); conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED, id, txt, ts); @@ -612,7 +644,7 @@ function setupListeners(conference) { module.exports = JitsiConference; }).call(this,"/JitsiConference.js") -},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./JitsiTrackEvents":10,"./modules/DTMF/JitsiDTMFManager":11,"./modules/RTC/RTC":16,"./modules/statistics/statistics":24,"./service/RTC/RTCEvents":79,"./service/xmpp/XMPPEvents":85,"events":43,"jitsi-meet-logger":47}],2:[function(require,module,exports){ +},{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./JitsiTrackEvents":10,"./modules/DTMF/JitsiDTMFManager":11,"./modules/RTC/RTC":16,"./modules/statistics/statistics":24,"./service/RTC/RTCEvents":79,"./service/authentication/AuthenticationEvents":81,"./service/xmpp/XMPPEvents":85,"events":43,"jitsi-meet-logger":47}],2:[function(require,module,exports){ /** * Enumeration with the errors for the conference. * @type {{string: string}} @@ -11517,12 +11549,12 @@ XMPP.prototype.connect = function (jid, password) { return this._connect(jid, password); }; -XMPP.prototype.createRoom = function (roomName, options, useNicks, nick) { +XMPP.prototype.createRoom = function (roomName, options) { var roomjid = roomName + '@' + this.options.hosts.muc; - if (useNicks) { - if (nick) { - roomjid += '/' + nick; + if (options.useNicks) { + if (options.nick) { + roomjid += '/' + options.nick; } else { roomjid += '/' + Strophe.getNodeFromJid(this.connection.jid); } diff --git a/modules/xmpp/xmpp.js b/modules/xmpp/xmpp.js index 5fd5fbedf..ec1409c6b 100644 --- a/modules/xmpp/xmpp.js +++ b/modules/xmpp/xmpp.js @@ -180,12 +180,12 @@ XMPP.prototype.connect = function (jid, password) { return this._connect(jid, password); }; -XMPP.prototype.createRoom = function (roomName, options, useNicks, nick) { +XMPP.prototype.createRoom = function (roomName, options) { var roomjid = roomName + '@' + this.options.hosts.muc; - if (useNicks) { - if (nick) { - roomjid += '/' + nick; + if (options.useNicks) { + if (options.nick) { + roomjid += '/' + options.nick; } else { roomjid += '/' + Strophe.getNodeFromJid(this.connection.jid); } From 81eb706d2dfe212e57e27b160c1d47af8da7c4b2 Mon Sep 17 00:00:00 2001 From: isymchych Date: Mon, 21 Dec 2015 14:29:56 +0200 Subject: [PATCH 3/3] add "kick participant" support --- JitsiConference.js | 20 ++++++++++++-- JitsiConferenceEvents.js | 4 +++ JitsiParticipant.js | 31 +++++++++++++++------ doc/API.md | 4 +++ lib-jitsi-meet.js | 60 ++++++++++++++++++++++++++++++++-------- modules/xmpp/ChatRoom.js | 5 ++-- 6 files changed, 100 insertions(+), 24 deletions(-) diff --git a/JitsiConference.js b/JitsiConference.js index d4a82dea7..0dee6c1cd 100644 --- a/JitsiConference.js +++ b/JitsiConference.js @@ -387,12 +387,24 @@ JitsiConference.prototype.getParticipantById = function(id) { return this.participants[id]; }; +/** + * Kick participant from this conference. + * @param {string} id id of the participant to kick + */ +JitsiConference.prototype.kickParticipant = function (id) { + var participant = this.getParticipantById(id); + if (!participant) { + return; + } + this.room.kick(participant.getJid()); +}; + JitsiConference.prototype.onMemberJoined = function (jid, email, nick) { var id = Strophe.getResourceFromJid(jid); if (id === 'focus') { return; } - var participant = new JitsiParticipant(id, this, nick); + var participant = new JitsiParticipant(jid, this, nick); this.participants[id] = participant; this.eventEmitter.emit(JitsiConferenceEvents.USER_JOINED, id, participant); this.xmpp.connection.disco.info( @@ -406,7 +418,7 @@ JitsiConference.prototype.onMemberJoined = function (jid, email, nick) { JitsiConference.prototype.onMemberLeft = function (jid) { var id = Strophe.getResourceFromJid(jid); - if (id === 'focus') { + if (id === 'focus' || this.myUserId() === id) { return; } var participant = this.participants[id]; @@ -566,6 +578,10 @@ function setupListeners(conference) { // conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_LEFT); // }); + conference.room.addListener(XMPPEvents.KICKED, function () { + conference.eventEmitter.emit(JitsiConferenceEvents.KICKED); + }); + conference.room.addListener(XMPPEvents.MUC_MEMBER_JOINED, conference.onMemberJoined.bind(conference)); conference.room.addListener(XMPPEvents.MUC_MEMBER_LEFT, conference.onMemberLeft.bind(conference)); diff --git a/JitsiConferenceEvents.js b/JitsiConferenceEvents.js index 57aa87ace..166c14152 100644 --- a/JitsiConferenceEvents.js +++ b/JitsiConferenceEvents.js @@ -80,6 +80,10 @@ var JitsiConferenceEvents = { * Indicates that conference has been left. */ CONFERENCE_LEFT: "conference.left", + /** + * You are kicked from the conference. + */ + KICKED: "conferenece.kicked", /** * Indicates that DTMF support changed. */ diff --git a/JitsiParticipant.js b/JitsiParticipant.js index e7c2f34fd..7be1958d7 100644 --- a/JitsiParticipant.js +++ b/JitsiParticipant.js @@ -1,8 +1,11 @@ +/* global Strophe */ + /** * Represents a participant in (a member of) a conference. */ -function JitsiParticipant(id, conference, displayName){ - this._id = id; +function JitsiParticipant(jid, conference, displayName){ + this._jid = jid; + this._id = Strophe.getResourceFromJid(jid); this._conference = conference; this._displayName = displayName; this._supportsDTMF = false; @@ -25,12 +28,19 @@ JitsiParticipant.prototype.getTracks = function() { }; /** - * @returns {String} The ID (i.e. JID) of this participant. + * @returns {String} The ID of this participant. */ JitsiParticipant.prototype.getId = function() { return this._id; }; +/** + * @returns {String} The JID of this participant. + */ +JitsiParticipant.prototype.getJid = function() { + return this._jid; +}; + /** * @returns {String} The human-readable display name of this participant. */ @@ -70,7 +80,8 @@ JitsiParticipant.prototype.isVideoMuted = function() { }; /* - * @returns {???} The latest statistics reported by this participant (i.e. info used to populate the GSM bars) + * @returns {???} The latest statistics reported by this participant + * (i.e. info used to populate the GSM bars) * TODO: do we expose this or handle it internally? */ JitsiParticipant.prototype.getLatestStats = function() { @@ -85,14 +96,16 @@ JitsiParticipant.prototype.getRole = function() { }; /* - * @returns {Boolean} Whether this participant is the conference focus (i.e. jicofo). + * @returns {Boolean} Whether this participant is + * the conference focus (i.e. jicofo). */ JitsiParticipant.prototype.isFocus = function() { }; /* - * @returns {Boolean} Whether this participant is a conference recorder (i.e. jirecon). + * @returns {Boolean} Whether this participant is + * a conference recorder (i.e. jirecon). */ JitsiParticipant.prototype.isRecorder = function() { @@ -106,14 +119,16 @@ JitsiParticipant.prototype.isSipGateway = function() { }; /** - * @returns {Boolean} Whether this participant is currently sharing their screen. + * @returns {Boolean} Whether this participant + * is currently sharing their screen. */ JitsiParticipant.prototype.isScreenSharing = function() { }; /** - * @returns {String} The user agent of this participant (i.e. browser userAgent string). + * @returns {String} The user agent of this participant + * (i.e. browser userAgent string). */ JitsiParticipant.prototype.getUserAgent = function() { diff --git a/doc/API.md b/doc/API.md index 79f6ca0ea..45f4140a6 100644 --- a/doc/API.md +++ b/doc/API.md @@ -80,6 +80,7 @@ JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR); - DTMF_SUPPORT_CHANGED - notifies if at least one user supports DTMF. (parameters - supports(boolean)) - USER_ROLE_CHANGED - notifies that role of some user changed. (parameters - id(string), role(string)) - CONFERENCE_FAILED - notifies that user failed to join the conference. (parameters - errorCode(JitsiMeetJS.errors.conference)) + - KICKED - notifies that user has been kicked from the conference. 2. connection - CONNECTION_FAILED - indicates that the server connection failed. @@ -238,6 +239,9 @@ The object represents a conference. We have the following methods to control the Note: available only for moderator +24. kick(id) - Kick participant from the conference + - id - string participant id + JitsiTrack ====== The object represents single track - video or audio. They can be remote tracks ( from the other participants in the call) or local tracks (from the devices of the local participant). diff --git a/lib-jitsi-meet.js b/lib-jitsi-meet.js index 363d05f47..a0a1e0150 100644 --- a/lib-jitsi-meet.js +++ b/lib-jitsi-meet.js @@ -389,12 +389,24 @@ JitsiConference.prototype.getParticipantById = function(id) { return this.participants[id]; }; +/** + * Kick participant from this conference. + * @param {string} id id of the participant to kick + */ +JitsiConference.prototype.kickParticipant = function (id) { + var participant = this.getParticipantById(id); + if (!participant) { + return; + } + this.room.kick(participant.getJid()); +}; + JitsiConference.prototype.onMemberJoined = function (jid, email, nick) { var id = Strophe.getResourceFromJid(jid); if (id === 'focus') { return; } - var participant = new JitsiParticipant(id, this, nick); + var participant = new JitsiParticipant(jid, this, nick); this.participants[id] = participant; this.eventEmitter.emit(JitsiConferenceEvents.USER_JOINED, id, participant); this.xmpp.connection.disco.info( @@ -408,7 +420,7 @@ JitsiConference.prototype.onMemberJoined = function (jid, email, nick) { JitsiConference.prototype.onMemberLeft = function (jid) { var id = Strophe.getResourceFromJid(jid); - if (id === 'focus') { + if (id === 'focus' || this.myUserId() === id) { return; } var participant = this.participants[id]; @@ -568,6 +580,10 @@ function setupListeners(conference) { // conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_LEFT); // }); + conference.room.addListener(XMPPEvents.KICKED, function () { + conference.eventEmitter.emit(JitsiConferenceEvents.KICKED); + }); + conference.room.addListener(XMPPEvents.MUC_MEMBER_JOINED, conference.onMemberJoined.bind(conference)); conference.room.addListener(XMPPEvents.MUC_MEMBER_LEFT, conference.onMemberLeft.bind(conference)); @@ -765,6 +781,10 @@ var JitsiConferenceEvents = { * Indicates that conference has been left. */ CONFERENCE_LEFT: "conference.left", + /** + * You are kicked from the conference. + */ + KICKED: "conferenece.kicked", /** * Indicates that DTMF support changed. */ @@ -1021,11 +1041,14 @@ window.Promise = window.Promise || require("es6-promise").Promise; module.exports = LibJitsiMeet; },{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiConnection":4,"./JitsiConnectionErrors":5,"./JitsiConnectionEvents":6,"./JitsiTrackErrors":9,"./JitsiTrackEvents":10,"./modules/RTC/RTC":16,"./modules/statistics/statistics":24,"es6-promise":45,"jitsi-meet-logger":47}],8:[function(require,module,exports){ +/* global Strophe */ + /** * Represents a participant in (a member of) a conference. */ -function JitsiParticipant(id, conference, displayName){ - this._id = id; +function JitsiParticipant(jid, conference, displayName){ + this._jid = jid; + this._id = Strophe.getResourceFromJid(jid); this._conference = conference; this._displayName = displayName; this._supportsDTMF = false; @@ -1048,12 +1071,19 @@ JitsiParticipant.prototype.getTracks = function() { }; /** - * @returns {String} The ID (i.e. JID) of this participant. + * @returns {String} The ID of this participant. */ JitsiParticipant.prototype.getId = function() { return this._id; }; +/** + * @returns {String} The JID of this participant. + */ +JitsiParticipant.prototype.getJid = function() { + return this._jid; +}; + /** * @returns {String} The human-readable display name of this participant. */ @@ -1093,7 +1123,8 @@ JitsiParticipant.prototype.isVideoMuted = function() { }; /* - * @returns {???} The latest statistics reported by this participant (i.e. info used to populate the GSM bars) + * @returns {???} The latest statistics reported by this participant + * (i.e. info used to populate the GSM bars) * TODO: do we expose this or handle it internally? */ JitsiParticipant.prototype.getLatestStats = function() { @@ -1108,14 +1139,16 @@ JitsiParticipant.prototype.getRole = function() { }; /* - * @returns {Boolean} Whether this participant is the conference focus (i.e. jicofo). + * @returns {Boolean} Whether this participant is + * the conference focus (i.e. jicofo). */ JitsiParticipant.prototype.isFocus = function() { }; /* - * @returns {Boolean} Whether this participant is a conference recorder (i.e. jirecon). + * @returns {Boolean} Whether this participant is + * a conference recorder (i.e. jirecon). */ JitsiParticipant.prototype.isRecorder = function() { @@ -1129,14 +1162,16 @@ JitsiParticipant.prototype.isSipGateway = function() { }; /** - * @returns {Boolean} Whether this participant is currently sharing their screen. + * @returns {Boolean} Whether this participant + * is currently sharing their screen. */ JitsiParticipant.prototype.isScreenSharing = function() { }; /** - * @returns {String} The user agent of this participant (i.e. browser userAgent string). + * @returns {String} The user agent of this participant + * (i.e. browser userAgent string). */ JitsiParticipant.prototype.getUserAgent = function() { @@ -6240,7 +6275,8 @@ ChatRoom.prototype.onPresenceUnavailable = function (pres, from) { reason = reasonSelect.text(); } - this.xmpp.disposeConference(false); + this.xmpp.leaveRoom(this.roomjid); + this.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason); delete this.connection.emuc.rooms[Strophe.getBareJidFromJid(from)]; return true; @@ -6262,7 +6298,7 @@ ChatRoom.prototype.onPresenceUnavailable = function (pres, from) { } if ($(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="307"]').length) { if (this.myroomjid === from) { - this.xmpp.disposeConference(false); + this.xmpp.leaveRoom(this.roomjid); this.eventEmitter.emit(XMPPEvents.KICKED); } } diff --git a/modules/xmpp/ChatRoom.js b/modules/xmpp/ChatRoom.js index 5484e307d..a97fb2e6a 100644 --- a/modules/xmpp/ChatRoom.js +++ b/modules/xmpp/ChatRoom.js @@ -343,7 +343,8 @@ ChatRoom.prototype.onPresenceUnavailable = function (pres, from) { reason = reasonSelect.text(); } - this.xmpp.disposeConference(false); + this.xmpp.leaveRoom(this.roomjid); + this.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason); delete this.connection.emuc.rooms[Strophe.getBareJidFromJid(from)]; return true; @@ -365,7 +366,7 @@ ChatRoom.prototype.onPresenceUnavailable = function (pres, from) { } if ($(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="307"]').length) { if (this.myroomjid === from) { - this.xmpp.disposeConference(false); + this.xmpp.leaveRoom(this.roomjid); this.eventEmitter.emit(XMPPEvents.KICKED); } }