From d242efe7dc5e2c2096826edf17dda69dc2d5b17c Mon Sep 17 00:00:00 2001 From: Rob DiMarco Date: Sun, 7 Jul 2013 16:26:54 -0700 Subject: [PATCH] Allow unauthenticated users read-only access --- src/js/firechat-ui.js | 36 +++++++++++++++------ src/js/firechat.js | 73 +++++++++++++++++++++++++++++------------- templates/message.html | 2 +- 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/src/js/firechat-ui.js b/src/js/firechat-ui.js index e213993..03318cd 100644 --- a/src/js/firechat-ui.js +++ b/src/js/firechat-ui.js @@ -136,6 +136,7 @@ $('.message[data-user-id="' + userId + '"]').fadeOut(); } }, + _onEnterRoom: function(room) { this.attachTab(room.id, room.name); }, @@ -149,7 +150,7 @@ }, _onNewMessage: function(roomId, message) { var userId = message.userId; - if (!this._user.muted || !this._user.muted[userId]) { + if (!this._user || !this._user.muted || !this._user.muted[userId]) { this.showMessage(roomId, message); } }, @@ -220,11 +221,16 @@ } }; - FirechatUI.prototype.initWithUser = function(userId, userName) { + /** + * Initialize an authenticated session with a user id and name. + * This method assumes that the underlying Firebase reference has + * already been authenticated. + */ + FirechatUI.prototype.setUser = function(userId, userName) { var self = this; // Initialize data events - self._chat.initWithUser(userId, userName, function(user) { + self._chat.setUser(userId, userName, function(user) { self._user = user; if (self._chat.userIsModerator()) { @@ -235,6 +241,15 @@ }); }; + /** + * Exposes internal chat bindings via this external interface. + */ + FirechatUI.prototype.on = function(eventType, cb) { + var self = this; + + this._chat.on(eventType, cb); + }; + /** * Binds a custom context menu to messages for superusers to warn or ban * users for violating terms of service. @@ -412,9 +427,9 @@ self._chat.getUsersByRoom(roomId, function(users) { for (var username in users) { user = users[username]; - user.disableActions = (user.id === self._user.id); + user.disableActions = (!self._user || user.id === self._user.id); user.nameTrimmed = self.trimWithEllipsis(user.name, self.maxLengthUsernameDisplay); - user.isMuted = (self._user.muted && self._user.muted[user.id]); + user.isMuted = (self._user && self._user.muted && self._user.muted[user.id]); $target.append($(template(user))); } self.sortListLexicographically('#' + targetId); @@ -457,7 +472,7 @@ var user = users[username]; // Disable buttons for . - user.disableActions = (user.id === self._user.id); + user.disableActions = (!self._user || user.id === self._user.id); numResults += 1; @@ -944,12 +959,13 @@ // Setup defaults var message = { id : rawMessage.id, - localtime : this.formatTime(rawMessage.timestamp), + localtime : self.formatTime(rawMessage.timestamp), message : rawMessage.message || '', userId : rawMessage.userId, name : rawMessage.name, type : rawMessage.type || 'default', - isSelfMessage : (rawMessage.userId == this._user.id) + isSelfMessage : (self._user && rawMessage.userId == self._user.id), + disableActions : (!self._user || rawMessage.userId == self._user.id) }; // While other data is escaped in the Underscore.js templates, escape and @@ -963,12 +979,12 @@ return _.escape(token); } }).join(' '); - message.message = this.trimWithEllipsis(message.message, this.maxLengthMessage); + message.message = self.trimWithEllipsis(message.message, self.maxLengthMessage); // Populate and render the message template. var template = FirechatDefaultTemplates["templates/message.html"]; var $message = $(template(message)); - var $messages = this.$messages[roomId]; + var $messages = self.$messages[roomId]; if ($messages) { var scrollToBottom = false; diff --git a/src/js/firechat.js b/src/js/firechat.js index 085aaa0..ae39c87 100644 --- a/src/js/firechat.js +++ b/src/js/firechat.js @@ -179,12 +179,17 @@ delete this._presenceBits[path]; }, - // Event to monitor user current user state. + // Event to monitor current user state. _onUpdateUser: function(snapshot) { this._user = snapshot.val(); this._invokeEventCallbacks('user-update', this._user); }, + // Event to monitor current auth + user state. + _onAuthRequired: function() { + this._invokeEventCallbacks('auth-required'); + }, + // Events to monitor room entry / exit and messages additional / removal. _onEnterRoom: function(room) { this._invokeEventCallbacks('room-enter', room); @@ -242,7 +247,7 @@ // -------------- // Initialize the library and setup data listeners. - Firechat.prototype.initWithUser = function(userId, userName, callback) { + Firechat.prototype.setUser = function(userId, userName, callback) { var self = this; self._firebase.root().child('.info/authenticated').on('value', function(snapshot) { @@ -320,19 +325,21 @@ self._rooms[roomId] = true; - // Save entering this room to resume the session again later. - self._userRef.child('rooms').child(roomId).set({ - id: roomId, - name: roomName, - active: true - }); + if (self._user) { + // Save entering this room to resume the session again later. + self._userRef.child('rooms').child(roomId).set({ + id: roomId, + name: roomName, + active: true + }); - // Set presence bit for the room and queue it for removal on disconnect. - var presenceRef = self._firebase.child('room-users').child(roomId).child(self._userId).child(self._sessionId); - self._queuePresenceOperation(presenceRef, { - id: self._userId, - name: self._userName - }, null); + // Set presence bit for the room and queue it for removal on disconnect. + var presenceRef = self._firebase.child('room-users').child(roomId).child(self._userId).child(self._sessionId); + self._queuePresenceOperation(presenceRef, { + id: self._userId, + name: self._userName + }, null); + } // Invoke our callbacks before we start listening for new messages. self._onEnterRoom({ id: roomId, name: roomName }); @@ -362,11 +369,13 @@ // Remove listener for new messages to this room. self._messageRef.child(roomId).off(); - // Remove presence bit for the room and cancel on-disconnect removal. - self._removePresenceOperation(presenceRef.toString(), null); + if (self._user) { + // Remove presence bit for the room and cancel on-disconnect removal. + self._removePresenceOperation(presenceRef.toString(), null); - // Remove session bit for the room. - self._userRef.child('rooms').child(roomId).remove(); + // Remove session bit for the room. + self._userRef.child('rooms').child(roomId).remove(); + } delete self._rooms[roomId]; @@ -383,8 +392,17 @@ message: messageContent, type: messageType || 'default' }, - newMessageRef = self._messageRef.child(roomId).push(); + newMessageRef; + if (!self._user) { + self._onAuthRequired(); + if (cb) { + cb(new Error('Not authenticated or user not set!')); + } + return; + } + + newMessageRef = self._messageRef.child(roomId).push(); newMessageRef.setWithPriority(message, Firebase.ServerValue.TIMESTAMP, cb); }; @@ -400,6 +418,14 @@ Firechat.prototype.toggleUserMute = function(userId, cb) { var self = this; + if (!self._user) { + self._onAuthRequired(); + if (cb) { + cb(new Error('Not authenticated or user not set!')); + } + return; + } + self._userRef.child('muted').child(userId).transaction(function(isMuted) { return (isMuted) ? null : true; }, cb); @@ -458,6 +484,11 @@ inviteRef.on('value', self._onFirechatInviteResponse, function(){}, self); }; + if (!self._user) { + self._onAuthRequired(); + return; + } + self.getRoom(roomId, function(room) { if (room.type === 'private') { var authorizedUserRef = self._roomRef.child(roomId).child('authorizedUsers'); @@ -596,8 +627,4 @@ Firechat.prototype.userIsModerator = function() { return this._isModerator; }; - - Firechat.prototype.sessionIdGet = function() { - return this._sessionId; - }; })(Firebase); \ No newline at end of file diff --git a/templates/message.html b/templates/message.html index 89f1892..000c738 100644 --- a/templates/message.html +++ b/templates/message.html @@ -5,7 +5,7 @@ (<%- localtime %>): - <% if (!isSelfMessage) { %> + <% if (!disableActions) { %>